Hubbry Logo
JS++JS++Main
Open search
JS++
Community hub
JS++
logo
8 pages, 0 posts
0 subscribers
Be the first to start a discussion here.
Be the first to start a discussion here.
JS++
JS++
from Wikipedia
JS++
ParadigmMulti-paradigm: Imperative, structured, object-oriented, functional, generic
FamilyECMAScript
Designed byRoger Poon, Anton Rapetov
DeveloperOnux
First appearedOctober 8, 2011; 14 years ago (2011-10-08)
Stable release
0.10.0 / December 10, 2021; 3 years ago (2021-12-10)
Typing disciplineGradual, static, dynamic
Scopelexical
LicenseBSD
Filename extensions.jspp, .js++, .jpp
Websitewww.onux.com/jspp
Influenced by
C, C++, C#, Java, JavaScript

JS++ is a programming language for web development that extends JavaScript with a sound type system. It includes imperative, object-oriented, functional, and generic programming features. It is free and open-source software released under a BSD license.

History

[edit]

JS++ first appeared on October 8, 2011.[1][2][3] The modern implementation was announced at DeveloperWeek 2016[4] and released on May 31, 2016.[5][6][7][8] The language is designed by Roger Poon and Anton Rapetov.

Features

[edit]

Sound gradual type system

[edit]

Since JS++ is a superset of JavaScript, declaring data types for variables is optional. However, when types are declared, the types are enforced at both compile time and runtime.

Type annotations in JS++ use the traditional C/C++ syntax:

int x = 1;
var y = 2;
bool z = true;

Notably, this differs from TypeScript and ActionScript, which use a more verbose style:

var x: number = 1;
var y: any = 2;
var z: boolean = true;

The type system in JS++ is sound for ECMAScript and DOM API corner cases, including host objects, dynamic key-value pairs, Comet, JScript conditional compilation, dynamic return types, ActiveX, ECMAScript for XML, web browser garbage collector and cyclic reference counting bugs, conditional logic, and other edge and corner cases.[9][10] This differs from other JavaScript supersets where types are optional and discarded at runtime via type erasure, such as in TypeScript.[11][12]

Importing JavaScript libraries

[edit]

JS++ can use JavaScript libraries using the one-line external statement as in the following example from the homepage of JS++:

import System;
// Import JavaScript libraries in one line of code
external jQuery, $;

class Example {
    public Example() {
        // Nearly NO learning curve
        // You can keep writing regular JavaScript
        var a = 0, random = Math.random();
        // Integer types and other primitives
        // ... enable fast (optimized) and clear code
        byte[] rgbColors = [ 0xFF, 0xFA, 0xFF ];
    }

    public void showMessage(int id, string text) {
        // 100% compatible with regular JavaScript
        jQuery("#msgbox").show();
        $("#msgbox").text(id.toString() + text);
    }
}

Object-oriented programming

[edit]

While classes in JavaScript (ECMAScript 6) are syntactic sugar for prototypes under the hood,[13] JS++ classes resemble the classes found in classical programming languages such as C++, Java, and C# in terms of memory layout, performance, and semantics. "Classes" are a static concept, and they cannot be altered at runtime (during program execution) as is the case for JavaScript, Smalltalk, Lisp, and TypeScript, which rely on prototypes.[14] For example, private methods are private at both compile time and runtime, and external JavaScript objects cannot access private JS++ fields or methods—even if a reference to a JS++ object is obtained from JavaScript.

Example: object-oriented sorting

[edit]

The following source code illustrates object-oriented sorting in JS++ using the IComparable<T> interface and Comparison enumeration for type-safe and readable comparisons.[15] The custom sorting logic is one line of code in the overridden compare method below:

import System;
 
class Employee : IComparable<Employee> {
    private string firstName;
    private string lastName;
 
    public Employee(string firstName, string lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
 
    public override Comparison compare(Employee that) {
        // Sort by employee surname
        return this.lastName.compare(that.lastName);
    }
 
    public override string toString() {
        return this.firstName + " " + this.lastName;
    }
}

Employee zig = new Employee("Zig", "Ziglar");
Employee john = new Employee("John", "Smith");
Employee abe = new Employee("Abe", "Lincoln");

Employee[] employees = [ zig, john, abe ];
employees.sort();
Console.log(employees.join(", "));

// Output:
// Abe Lincoln, John Smith, Zig Ziglar

Thus, in the code above, the custom sorting logic provided is:

return this.lastName.compare(that.lastName);

Likewise, to call the sort:

employees.sort();

For printing the sorted results:

Console.log(employees.join(", "));

Example: encapsulation by default

[edit]

JS++ provides encapsulation by default. In the following example, the fields x and y are private by default, even if no access modifier is specified. The methods getX() and getY() are public by default. This enables a more concise class definition syntax, as illustrated in the Point class below:[16]

class Point {
    int x, y;
 
    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
 
    int getX() {
        return this.x; 
    }

    int getY() { 
        return this.y; 
    }
}

Out-of-bounds analysis

[edit]

An out-of-bounds access usually occurs with arrays and other containers. For example, when we access the 100th element of a 3-element array, we have an out-of-bounds access:

int[] arr = [ 1, 2, 3 ];
Console.log(arr[100]); // out-of-bounds access, 'arr' does not have an element at index 100

In Java and C#, this can result in an exception and program termination. In C, this can result in buffer overflows or segmentation faults. C++ has varying semantics, such as default initialization, exceptions, segmentation faults, or buffer overflows.[17][18]

JS++ can efficiently analyze and prevent out-of-bounds errors at compile time.[19][20][21]

JavaScript has the notion of null and undefined values, where null means a value is present but it's an empty value, and undefined means there isn't a value there at all. JS++ extends this intuition further to differentiate between empty values and out-of-bounds accesses.[21]

Consider the following code, with a nullable int type represented with int?:

int[] a = [ 1, 2 ];
int? value1 = a[2];
if (value1 == null) {
    Console.log("Definitely out of bounds");
}
 
int?[] b = [ 1, null ];
int? value2 = b[2];
if (value2 == null) {
    Console.log("Might be out of bounds, might just be an access of a null element");
}

While nullable types can represent an out-of-bounds access, it falls apart when the array might contain nullable values as illustrated above. Instead, JS++ introduces an additional concept in addition to null values: undefined values. Recall that JS++ extends the JavaScript notion that null means a value is present but is an empty value, while an undefined value means a value does not exist at all. JS++ uses the concept of "a value does not exist at all" to mean an out-of-bounds access has occurred, and this concept is known in JS++ as "existent types."[21]

Therefore, the previous example can be amended. The existent type int+ means "int or out of bounds" and int?+ means "int, null, or out of bounds":

int[] a = [ 1, 2 ];
int? value1 = a[2];
if (value1 == undefined) {
    Console.log("Definitely out of bounds");
}

int?[] b = [ 1, null ];
int?+ value2 = b[2];
if (value2 == undefined) {
    Console.log("Definitely out of bounds");
}

Intuitively, this means existent types cannot be used as the underlying type for array elements. JS++ enforces this at compile time:

int+[] arr = []; // ERROR
[ ERROR ] JSPPE5204: Existent type `int+' cannot be used as the element type for arrays

Instead of following every conditional branch or virtual method call path, which would result in path explosion and exponential compile times, existent types have essentially the same compile-time analysis cost as int, bool, and other primitive types. Consequently, compile times have been shown to be unaffected (±1-2ms) by the introduction of existent types.[21] Since existent types are used for all array and container types in JS++ (such as hash maps, Stack<T>, and Queue<T>), JS++ containers are thus guaranteed to not have out-of-bounds errors.

In JS++, undefined is a value that cannot be changed. In JavaScript (ECMAScript 3), undefined is a mutable property of the global object, resulting in circumstances where "undefined" can be "defined."[22] Thus, existent types would not have been possible in pure JavaScript, as arrays can contain elements with the undefined value, undefined can be defined, or other edge and corner cases that are prevented in JS++.[21][23]

Also, in comparison to Java and early object-oriented languages such as Eiffel,[24][25] JS++ does not default initialize objects to null.[21] Instead, the compiler enforces initialization by the programmer:

class Car {}

Car car;
[  ERROR  ] JSPPE6000: Variable `car' is not initialized at line 3 char 4

Therefore, since existent types are deeply embedded into the language, JS++ can guarantee that out-of-bounds errors never occur.[26][10]

Databases

[edit]

The concept of existent types can be extended outside of containers. For example, in MySQL, columns can be nullable.[27][28] If the row does not exist for a specified condition (e.g. WHERE clause), the undefined value can be returned. However, if the row does exist but the value at the column is empty, a null value can be returned instead. This can simplify the code and interfaces to the data access layer.

Integer types

[edit]

JS++ provides 8-bit, 16-bit, 32-bit, and 64-bit integer types as well as floating point types:

byte b1 = 0xFF;        // unsigned 8-bit
signed byte b2 = -1;   // signed 8-bit
short s1 = 1;          // signed 16-bit
unsigned short s2 = 1; // unsigned 16-bit
int x1 = 0;            // signed 32-bit
unsigned int x2 = 0;   // unsigned 32-bit
long z1 = 1;           // signed 64-bit
unsigned long z2 = 1;  // unsigned 64-bit

float f = 0.5;         // single-precision floating point
double d = 0.5;        // double-precision floating point

From the project homepage:

// You're not required to declare the type for a variable and you can just
// keep writing regular JavaScript (again, NO learning curve):
var offset = 0;

// But, if you do, this next variable will always remain an 'unsigned int' - even at runtime.
// You'll never see NaN ("Not a Number") runtime errors again.
// This variable is 'unsigned' so it's also guaranteed to never be negative.
unsigned int pageHeight = $(document).height();

Block scoping

[edit]

All variables in JS++ are block-scoped, including the JavaScript var statement.[29][30][31] Thus, there is no need for two different variable declaration keywords with different scoping rules, such as var and let co-existing simultaneously in JavaScript (ECMAScript 6).

Development tools

[edit]

Compiler

[edit]

The JS++ compiler is available for Windows, macOS, and Linux. It is a source-to-source compiler which emits JavaScript source code as an intermediate representation.

The compiler is developed with C/C++, and the developers claim there are "fewer than 10 open bug reports in the core compiler" after 3.5 years of engineering and 400,000 lines of code.[31][32]

Editor integration

[edit]

JS++ integrates with various code editors including Visual Studio Code, Atom, and Sublime Text.[33][34][35]

Build tools

[edit]

JS++ can be integrated with third-party build tools like Webpack.[36]

Release history

[edit]
Version number Release date Changes
0.01 8 October 2011 (2011-10-08) Alpha version, initial release
0.011 10 October 2011 (2011-10-10) Alpha version
0.012 25 October 2011 (2011-10-25) Alpha version
0.013 29 January 2012 (2012-01-29) Alpha version
0.014.1 15 August 2012 (2012-08-15) Alpha version
0.4.1 31 May 2016 (2016-05-31) Beta version, array and callback types, character literals, integral suffixes, removed ECMAScript ASI
0.4.2 18 October 2016 (2016-10-18) Modules, function overloading, dead code elimination, editor integrations
0.4.2.1 24 October 2016 (2016-10-24) Bug fixes
0.4.2.2 17 November 2016 (2016-11-17) Source map debugging
0.4.2.4 25 December 2016 (2016-12-25) Support for Mac OS X, C-style casts, callback and array conversions
0.5.0 13 March 2017 (2017-03-13) Classes
0.5.1 26 March 2017 (2017-03-26) 'foreach' loops
0.5.2 27 July 2017 (2017-07-27) BSD License, Interfaces, Abstract Classes, Virtual Methods, Auto-boxing
0.7.0 27 October 2017 (2017-10-27) All ECMAScript 3 features via Array<T> and Standard Library
0.8.0 15 March 2018 (2018-03-15) Generic programming, Dictionary<T>, multi-line strings, .js++ file extension
0.8.1 27 March 2018 (2018-03-27) auto, catch-all clauses, standard library modules for handling time, bug fixes
0.8.4 23 May 2018 (2018-05-23) New string functions, advanced generics, bug fixes, standard library expansion
0.8.5 2 June 2018 (2018-06-02) Bug fixes
0.8.10 24 November 2018 (2018-11-24) Faster compile times, stacks, queues, Unicode, Base64, generic default constraint rules
0.9.0 11 January 2019 (2019-01-11) Efficient compile time out-of-bounds error analysis
0.9.1 1 July 2019 (2019-07-01) Bug fixes
0.9.2 18 October 2019 (2019-10-18) Final (immutable) variables and default to 64-bit for macOS Catalina

See also

[edit]

References

[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
JS++ is a programming language that serves as a typed superset of JavaScript, designed specifically for high-quality web and mobile development by incorporating an optional, sound type system to ensure type safety at both compile-time and runtime. Developed by Onux, a company founded in 2011 in London with operations in Silicon Valley, JS++ was first announced and released in open beta on June 7, 2016, as a reliable successor to JavaScript aimed at addressing its notorious type-related errors, such as NaN values or negative numbers in unsigned contexts. Unlike type-erased systems like TypeScript, JS++ employs a patented "unified external type" mechanism (U.S. Patent 10,296,313, issued 2019) to seamlessly integrate and convert untyped JavaScript code and libraries, providing automatic safeguards and lightweight type conversions without requiring a steep learning curve for JavaScript developers. Key features include optional type declarations (e.g., unsigned int), elimination of runtime type errors, full compatibility with existing JavaScript environments—including edge cases like ActiveX objects, cross-browser DOM inconsistencies, and iframes—and support for imperative, object-oriented, and functional programming paradigms. The language compiles to ECMAScript 3-compliant JavaScript, ensuring broad compatibility from legacy browsers like Internet Explorer 6 to modern ones, and includes a standard library with classes, data structures, algorithms, and utilities, alongside tools like a documentation generator that produces pages from source code comments. Backed by years of scientific research and developed by a team with experience dating to the early World Wide Web, JS++ emphasizes reliability in production environments, particularly when interfacing with third-party untyped code, and remains available for free download via its official compiler.

Overview

Description and Purpose

JS++ is a statically-typed, optional-type programming language designed as a superset of JavaScript that compiles to plain JavaScript, targeting ECMAScript 3 (ES3)-compatible output with a sound gradual typing system to provide compile-time and runtime type correctness. This approach ensures compatibility with existing JavaScript environments while introducing robust type guarantees that prevent subtle errors inherent in JavaScript's dynamic typing. The primary purposes of JS++ are to enhance JavaScript's reliability and developer productivity by incorporating type safety mechanisms that catch common issues, such as type mismatches and NaN propagation, at both compile time and runtime, all while retaining the language's dynamic scripting flexibility for rapid prototyping and iteration. By addressing these pain points, JS++ enables the creation of more maintainable and error-resistant codebases without requiring a complete rewrite of existing JavaScript applications. Unique to JS++, its design is grounded in years of scientific research tackling JavaScript's shortcomings in large-scale , including the brittleness of type systems in competing supersets like , and it prioritizes across client-side browsers and server-side environments through full compatibility. This foundation allows JS++ to handle obscure edge cases, such as cross-browser DOM inconsistencies, that often plague untyped in production. JS++ targets developers seeking enhanced typing similar to , with a for integrating untyped legacy code into typed systems for scalable web projects. Its gradual permits seamless mixing of typed and untyped code, ensuring without forcing full adoption upfront. Development of JS++ appears to have ceased around 2018, with no major updates since then (as of November 2025).

Compatibility and Compilation

JS++ source code is transpiled to standard , ensuring it can execute in any JavaScript runtime environment, such as web browsers or , without requiring additional runtime dependencies. The compilation process, performed via the js++ command-line tool, generates standalone .js files from .jspp sources, allowing seamless deployment in legacy environments like as well as modern ones. This approach prioritizes broad compatibility while leveraging the host environment's native execution capabilities. As a superset of , JS++ accepts all valid JavaScript code as syntactically correct, facilitating incremental adoption where developers can gradually introduce typed elements into existing untyped codebases without full rewrites. Automatic type inference assigns the unified external type to undeclared variables (using var), while coercion mechanisms handle conversions between typed JS++ code and untyped , such as appending "" for string promotion from external types. The generated output incorporates runtime type checks and lightweight conversions only in regions with declared types, optimizing performance by avoiding unnecessary overhead in untyped sections. Support for ES5 and ES6+ features is achieved through transpilation to ES3 when targeting older runtimes. A key compatibility feature is the unified external type, which encapsulates all untyped JavaScript values into a single category, isolating JS++'s sound internal type system from potential errors in external code, such as propagation of undefined or null values into typed contexts. This isolation enforces explicit conversions at boundaries, preventing runtime failures like type mismatches or unexpected mutations, while maintaining interoperability with JavaScript libraries declared via external statements. By design, this mechanism ensures type soundness without compromising the dynamic nature of integrated JavaScript portions.

History and Development

Origins and Design

JS++ was developed by Onux, a founded in , , with operations extending to , , and , beginning in 2011 as an exploration of advanced and mechanisms for . The project originated from the need to mitigate the pitfalls of JavaScript's dynamic typing, such as runtime errors that proliferate in large-scale codebases and enterprise applications, while overcoming limitations in existing supersets like , which do not provide full type soundness when interacting with untyped code. Onux, established by Roger Poon, drew on the team's extensive experience—spanning over two decades and dating back to the early days of the —to focus on enhancing reliability for in production environments. The core motivations behind JS++ centered on delivering a dependable superset of that enforces engineering rigor without sacrificing compatibility or ease of adoption. Unlike prior attempts at typed variants, which often resulted in brittle or incomplete error detection, JS++ aimed to eliminate common issues like out-of-bounds errors through innovative approaches, including the invention of "existent types" by co-lead Anton Rapetov. This effort was grounded in a scientific foundation, incorporating research-inspired type systems and techniques to ensure provable guarantees against type-related failures. Key design principles of JS++ emphasize soundness, defined as comprehensive verified at both compile-time and runtime, enabling where developers can incrementally add types to existing code without a steep learning curve. The language maintains full with legacy , including seamless integration of untyped libraries via a unified external type mechanism that isolates typed regions while enforcing correctness across boundaries. Over years of iteration, the initial evolved to simplify complex typing challenges, such as runtime enforcement and type preservation, resulting in a system that compiles to efficient, typed while preserving the original ecosystem's flexibility. This approach reflects the team's background in , algorithms, and , with contributions from patented innovations in type systems.

Release History

Development of JS++ began with alpha releases in 2011 and 2012, including version 0.013 on January 29, 2012, and 0.014.1 on August 15, 2012. JS++ entered open beta on June 7, 2016, introducing a typed superset of with initial support for basic type checking and incremental typing for existing codebases. At launch, the language targeted ES3 compatibility while emphasizing runtime through a patent-pending unified external . Later in 2016, version 0.4.2 was released on October 19, adding features such as classes and the "module" keyword for modular code organization, alongside to optimize compilation by excluding unused functions and overloads. This update also enhanced integration with editors like and improved Windows support. Version 0.4.2.2 followed on November 21, 2016, incorporating in-browser debugging capabilities via source maps for setting breakpoints and logging. Minor releases through 2017 and 2018 primarily addressed refinements, fixes, and compatibility improvements, with no major feature additions documented publicly. The project's repository reflects updates ceasing around 2018, though official releases continued thereafter. The most recent version, 0.10.0, was released on December 10, 2021, under the BSD License, with the compiler remaining available for download from the official Onux website. As of November 2025, JS++ operates in , with no new major versions or significant updates since version 0.10.0.

Language Features

Type System

JS++ employs a gradual type system that allows developers to optionally specify static types while maintaining compatibility with untyped JavaScript code. This approach enables a seamless transition from dynamic typing to full static typing, where variables can be declared with explicit types such as int x = 5; or left untyped using var for dynamic fallback. Unlike purely dynamic languages, JS++ provides compile-time guarantees that prevent type errors from propagating when mixing typed and untyped regions, ensuring runtime safety without requiring annotations for all code. The categorizes types into internal and external varieties to distinguish between JS++'s safe, statically checked constructs and JavaScript's dynamic behaviors. Internal types include like int, unsigned int, string, and bool, as well as object types derived from classes and collections such as arrays and dictionaries. External types, represented by a unified external type (via keywords like external or var), abstract all JavaScript values into a single compile-time category, allowing automatic inference from context in mixed scenarios. For instance, a function declared as external can accept any JavaScript input without immediate type checking, while internal types enforce strict validation. Soundness is achieved through a combination of compile-time checks and runtime guards that isolate typed JS++ code from untyped . At compile time, the system detects mismatches, such as assigning a to an int variable, halting compilation to prevent errors. Runtime guards employ the unified external type to handle untyped inputs safely; for example, invalid values are converted to safe defaults like 0 for numeric types, avoiding crashes or unexpected behaviors. This mechanism ensures no type errors escape into execution, providing stronger guarantees than unsound systems. Unique to JS++, the eliminates common pitfalls like and undefined propagation by enforcing automatic conversions to predictable values during type transitions. It also supports custom type conversions for user-defined types, allowing developers to define how internal objects interact with external data. In contrast to , which relies on an any type that can introduce false negatives, JS++ proves by isolating regions and avoiding unchecked unions, ensuring all type checks are verifiable without human-provided annotations.

Object-Oriented Programming

JS++ supports through a class-based system that emphasizes and compile-time checks, distinguishing it from JavaScript's prototypal . This system was introduced in post-beta releases around 2016, enabling developers to define structured, reusable code with single and runtime polymorphism. Classes in JS++ are declared using the class keyword, creating user-defined types with typed fields and methods. Fields are declared with their types, and constructors initialize instances. For example, a basic Point class can be defined as follows:

jspp

class Point { int x; int y; Point(int x, int y) { this.x = x; this.y = y; } }

class Point { int x; int y; Point(int x, int y) { this.x = x; this.y = y; } }

Instances are created with the new keyword, such as Point p = new Point(3, 4);. Inheritance is achieved via the extends keyword for single inheritance, allowing subclasses to inherit and override members while supporting polymorphism through virtual methods resolved at runtime. The super keyword accesses parent class members, and the final modifier prevents further subclassing or overriding to enforce design contracts. Encapsulation in JS++ defaults to private visibility for all members, reducing accidental exposure in large codebases and promoting data hiding. Explicit access modifiers like public, protected, and private provide fine-grained control. Getters and setters enable controlled access to private fields. Consider this BankAccount example demonstrating encapsulation:

jspp

class BankAccount { private int balance; BankAccount(int initialBalance) { this.balance = initialBalance; } public int getBalance() { return this.balance; } public void deposit(int amount) { if (amount > 0) { this.balance += amount; } } public void withdraw(int amount) { if (amount > 0 && amount <= this.balance) { this.balance -= amount; } } }

class BankAccount { private int balance; BankAccount(int initialBalance) { this.balance = initialBalance; } public int getBalance() { return this.balance; } public void deposit(int amount) { if (amount > 0) { this.balance += amount; } } public void withdraw(int amount) { if (amount > 0 && amount <= this.balance) { this.balance -= amount; } } }

Here, balance is private, accessible only through public methods that enforce business rules. To illustrate polymorphism in practice, JS++ allows defining comparable classes for sorting. A Sortable base class with a compare method can be extended, enabling type-safe sorting implementations. For instance:

jspp

class Sortable { public virtual int compare(Sortable other) { // Default comparison; subclasses override return 0; } } class Person extends Sortable { string name; int age; Person(string name, int age) { this.name = name; this.age = age; } public override int compare(Sortable other) { Person p = (Person) other; if (this.age < p.age) return -1; if (this.age > p.age) return 1; return 0; } } // Usage in a sorting function (assuming a typed [array](/page/Array)) Person[] people = new Person[2] { new Person("Alice", 30), new Person("Bob", 25) }; // Sort using compare method (implementation via [standard library](/page/Standard_library) or custom sorter)

class Sortable { public virtual int compare(Sortable other) { // Default comparison; subclasses override return 0; } } class Person extends Sortable { string name; int age; Person(string name, int age) { this.name = name; this.age = age; } public override int compare(Sortable other) { Person p = (Person) other; if (this.age < p.age) return -1; if (this.age > p.age) return 1; return 0; } } // Usage in a sorting function (assuming a typed [array](/page/Array)) Person[] people = new Person[2] { new Person("Alice", 30), new Person("Bob", 25) }; // Sort using compare method (implementation via [standard library](/page/Standard_library) or custom sorter)

This setup leverages subtype polymorphism for age-based sorting, with compile-time type checks ensuring safety. JS++ modules facilitate organizing OOP code into namespaces, using typed import and export statements akin to ES6 modules but with static type verification across boundaries. For example, a class can be exported from one module and imported into another, maintaining type integrity for large-scale applications.

Control Structures and Data Types

JS++ introduces enhancements to JavaScript's mechanisms and primitive data types, providing stricter scoping and precise numeric handling to mitigate common pitfalls in untyped JavaScript code. These features leverage the language's to enable compile-time verification, ensuring more reliable program behavior in web applications.

Data Types

JS++ supports a range of primitive data types, with a particular emphasis on integer types for accurate arithmetic operations. The int type is a 32-bit signed two's-complement integer, ranging from -2,147,483,648 to 2,147,483,647, while unsigned int is a 32-bit unsigned integer ranging from 0 to 4,294,967,295. Unlike JavaScript's Number type, which uses 64-bit IEEE 754 double-precision floating-point representation with only 53 bits of integer precision, JS++ integers provide exact representation for values within their range, avoiding precision loss in computations such as large integer additions or multiplications. For example:

jspp

int x = 2147483647; // Maximum int value unsigned int y = 4294967295; // Maximum unsigned int value int result = x + 1; // Wraps around to -2147483648 due to overflow

int x = 2147483647; // Maximum int value unsigned int y = 4294967295; // Maximum unsigned int value int result = x + 1; // Wraps around to -2147483648 due to overflow

Integer operations in JS++ wrap around on overflow at runtime, similar to C-style behavior, which contrasts with JavaScript's potential for unexpected floating-point approximations. Other primitives include bool for boolean values and string for text, all integrated with the for compile-time checks.

Control Structures

Control structures in JS++ build on JavaScript's syntax but incorporate block scoping and type awareness to prevent common errors like variable hoisting. All variables declared within blocks, such as int i = 0;, are strictly scoped to that block, akin to let and const in modern JavaScript, ensuring they cannot be accessed outside their defining scope and eliminating hoisting-related issues associated with var. For instance:

jspp

{ int i = 0; // Scoped only to this block // i is incremented here } // i is inaccessible outside, preventing unintended reuse

{ int i = 0; // Scoped only to this block // i is incremented here } // i is inaccessible outside, preventing unintended reuse

Conditional statements include if, else if, and else for branching based on boolean expressions, and switch for multi-way selection using strict equality matching (equivalent to ===). The switch statement requires explicit break statements to avoid fallthrough, with the compiler issuing warnings for missing breaks, and supports a default case for unmatched values. Loops such as for, while, do...while, for...in, and foreach allow iteration, with declarations inside loops benefiting from block scoping and type enforcement—for example, a for loop can declare a typed counter like for (int i = 0; i < 10; ++i). These structures integrate with JS++'s type system (detailed separately) to catch type mismatches at compile time, such as assigning a non-integer to a loop variable.

Safety Features

JS++ incorporates several built-in safety features that extend beyond its type system to prevent common runtime errors prevalent in plain JavaScript, such as out-of-bounds accesses and null/undefined mishandling, through compile-time static analysis and targeted runtime checks. These mechanisms aim to prove the absence of specific error classes at compile time, reducing reliance on dynamic error handling and enabling safer code generation that compiles to efficient ECMAScript 3 JavaScript. Unlike JavaScript's dynamic checks, which can lead to unpredictable runtime failures, JS++'s analyses ensure deterministic behavior while maintaining full compatibility with existing JavaScript environments. These features were introduced in JS++ 0.9.0 (2019); the latest version, 0.10.0, was released on December 10, 2021. A core safety feature is the out-of-bounds analysis introduced in JS++ 0.9.0, which performs efficient compile-time detection of invalid array, string, and object accesses to prevent buffer overflows or undefined value returns that could crash applications. This analysis leverages existent types (denoted as T+), which distinguish in-bounds values of type T from out-of-bounds accesses that would otherwise yield undefined in JavaScript. For instance, in the code int[] arr = [7, 8, 9]; int+ x = arr[0];, the compiler confirms x is an in-bounds int, while int+ y = arr[1000]; flags the out-of-bounds access at compile time, allowing safe fallback handling like int b = y ?? 1;. The compiler generates minimal runtime bounds checks only when necessary, adding negligible overhead (e.g., 1-2 ms on benchmarks for projects up to 6,000 lines), and extends to dictionary (object) key accesses and conditional branching logic. This static proof of bounds safety eliminates entire classes of errors without the performance cost of pervasive dynamic checks in other languages like Java or C#. Null and undefined safety is enhanced through nullable types (T?) and combined existent-nullable types (T?+), which explicitly model empty or non-existent values, preventing ambiguous runtime errors common in JavaScript. For example, int?+ d = 1; can hold an integer, null (an empty but existent value), or undefined (non-existent), allowing the compiler to track and enforce safe handling. JS++ supports optional chaining via the safe navigation operator (?.) and nullish coalescing (??), enabling expressions like Console.log(arr[1000]?.toString() ?? "out of bounds"); to avoid exceptions on invalid accesses. These features integrate with the type system to eliminate obscure JavaScript edge cases, such as unreliable instanceof checks across execution frames, by resolving type identities statically during compilation. For enforcing program invariants, JS++ provides runtime assertions through the System.Assert module in its standard library, which includes methods to verify conditions at execution time and throw an AssertError if violated. These assertions complement compile-time checks, allowing developers to validate assumptions like data integrity or external library behaviors, such as Assert.isTrue(condition, "Invariant failed");. In web database code, frameworks like leverage JS++'s type-safe data access layers for and similar databases, ensuring typed query results handle nulls and prevent pointer-like exceptions through compile-time validation of result types. This typed approach indirectly mitigates risks like by promoting parameterized queries via safe, typed interfaces, though primary prevention relies on database library implementations.

Interoperability

Importing JavaScript Libraries

JS++ facilitates the integration of existing untyped libraries by allowing developers to declare them as external symbols, enabling seamless interoperability while providing optional type safety. The primary mechanism is the external statement, which imports JavaScript identifiers into the JS++ scope without requiring type definition files or build tools. This declaration assumes the JavaScript library is loaded in the runtime environment, such as via a <script> tag in browsers or require in , making JS++ compatible with the vast JavaScript ecosystem. The syntax for the external statement is straightforward: external identifier; or external identifier = initializer;, where multiple identifiers can be comma-separated. For instance, to import the jQuery library, one declares external jQuery, $;, which brings the global $ and jQuery objects into scope. This allows direct usage in JS++ code, such as string src = $("#logo").attr("src");, where the selector returns a typed string at compile time. Without explicit typing, these symbols adopt the unified external type, a special type in JS++ that encompasses all possible JavaScript values, ensuring sound static analysis across varying JavaScript implementations. Handling untyped JavaScript code involves wrapping functions and objects with the unified external type, which provides a safe typed interface for calls while abstracting platform-specific behaviors. Automatic occurs during compilation to JavaScript, converting JS++ types (e.g., int or string) to compatible JavaScript equivalents, such as numbers or strings. If a returns an unexpected type, JS++ isolates errors at runtime without propagating to typed code, maintaining isolation through the external wrapper; for example, invoking an untyped method on invalid input triggers a standard JavaScript error, but typed parameters prevent compile-time issues. Developers can enhance safety by adding type annotations, such as using typed variables for parameters like byte for RGB values (0-255).

jspp

// Example: Typed jQuery usage external jQuery, $; // Typed selector and attribute access string url = $("#logo").attr("src"); // Compile-time type: string if (url == "/images/logo.png") { alert("Logo found"); }

// Example: Typed jQuery usage external jQuery, $; // Typed selector and attribute access string url = $("#logo").attr("src"); // Compile-time type: string if (url == "/images/logo.png") { alert("Logo found"); }

Best practices emphasize incremental typing of external wrappers to gradually enhance for dependencies. Start with basic external declarations for quick integration, then refine with specific types for critical APIs to catch errors early; for complex libraries, create JS++ wrapper modules that export typed interfaces, allowing progressive adoption without rewriting the entire codebase. This approach leverages JS++'s optional to bridge untyped while minimizing runtime surprises. As of 2025, JS++ development appears inactive since its last update in 2019.

External Interactions

JS++ provides typed interfaces for core browser objects such as document and window, enabling developers to interact with the Document Object Model (DOM) and other Web APIs while benefiting from compile-time type checking. These interfaces account for variations in browser implementations, including support for non-standard features like ActiveX objects in Internet Explorer, ensuring consistent behavior without requiring manual type guards. For instance, the type system safeguards against garbage collection bugs and unpredictable data formats in host objects, promoting portability across environments from legacy browsers like IE6 to modern ones. In cross-context scenarios, such as iframes, JS++ addresses challenges with operators like instanceof by enforcing safe type resolution across frames, which prevents runtime type errors and issues in modular web applications. Event handling in these contexts is similarly protected, allowing reliable propagation without explicit checks for frame boundaries. This built-in extends to edge cases in legacy browser quirks, such as inconsistent event bubbling or access, ensuring code runs portably without additional runtime guards. For server-side development, JS++ maintains compatibility with through its compilation to 3 JavaScript, supporting typed modules for operations like file I/O and HTTP requests. Developers can import modules using the external statement, such as external require; external fs = require("fs"); for safe file operations with error handling, or integrate HTTP clients via external libraries with type safeguards against common pitfalls like unhandled asynchronous errors. These features enable robust server-side code with compile-time verification of interactions with APIs.

Development Tools

Compiler

The JS++ compiler, distributed as the command-line executable js++, serves as the primary tool for transpiling JS++ source files into optimized, executable . It processes JS++ code by the syntax, enforcing optional static type checking, and generating standard that maintains compatibility with existing JavaScript environments and libraries. This compilation ensures type guarantees at both compile-time and runtime, enabling developers to integrate JS++ seamlessly with untyped JavaScript without runtime errors from type mismatches. Basic usage of the compiler involves invoking it from or command prompt with the source file as input. For example, js++ main.jspp compiles the file and outputs main.js by default, while specifying an output file uses the -o flag: js++ -o output.js input.jspp. Additional flags include --execute to compile and immediately run the resulting in a environment, and -O levels (e.g., -O2) to enable optimization passes for . Debug information can be retained via appropriate flags during development, though strict mode enforcement is handled implicitly through type annotations rather than a dedicated flag. The is freely downloadable from the official site at onux.com/jspp, with binaries provided for Windows (via setup.exe installer), macOS, and . Architecturally, the JS++ operates in multiple passes: an initial phase to build an from JS++ source, followed by a typing pass for static and checking, an analysis pass for optimizations and error detection, and a final code generation pass to produce output. is integrated into the analysis phase, automatically removing unused functions, variables, and overloads to reduce bundle sizes and improve runtime efficiency— a feature unique to JS++ and not applicable to plain . This modular design supports handling large codebases effectively, with incremental compilation capabilities introduced in the 2016 beta release to recompile only modified modules, minimizing build times for extensive projects. During the and passes, the performs analyses to detect potential runtime issues, such as out-of-bounds access, contributing to JS++'s sound (detailed further in the Safety Features section).

IDE and Editor Support

JS++ offers integrations with several popular code editors through plugins that primarily provide for enhanced editing workflows. These include , Vim, , , Notepad++, Atom, and Adobe Brackets, enabling developers to write and navigate JS++ code more effectively. In , the official JS++ extension supports and can be installed by downloading the plugin from the project's repository and placing it in the extensions folder. For Vim and , dedicated plugins deliver , with the Vim plugin bundled in JS++ releases starting from version 0.4.0; installation involves copying the plugin files to the respective editor's plugin directory. integration extends beyond highlighting to include , build system support for invoking the JS++ compiler, and error navigation via squiggles in the editor. Additional editors such as Notepad++, UltraEdit, gedit, Kate/KWrite, and also feature JS++ syntax highlighting through simple plugin installations from , often with extras like TODO comment highlighting or symbol navigation in select tools. Web-based editors like and support JS++ via syntax definition files for highlighting in environments such as online code playgrounds. These plugins connect to the JS++ for on-the-fly builds when configured in editors with build integration, such as . As of 2025, JS++ editor support remains limited to these community-driven plugins, with no dedicated language server for advanced features like real-time type checking, autocomplete, refactoring, or hover documentation. The project, last actively updated in , has seen low adoption, resulting in no official full IDE comparable to those for , though basic compatibility provides minimal support in tools like WebStorm.

Build and Integration Tools

JS++ compiles to standard , enabling its integration into established build ecosystems without requiring wholesale changes to existing workflows. Developers typically incorporate the JS++ compiler into task runners like Gulp or Grunt through custom tasks or plugins that invoke the compiler on source files, transforming JS++ modules into before further processing, such as minification or concatenation. Similarly, bundlers like can be configured with loaders or pre-compilation steps to handle JS++ files, ensuring they are resolved and bundled alongside plain for production deployment. In and () pipelines, JS++ supports automated compilation via command-line invocation of its within scripts for platforms such as Jenkins or Actions. These workflows often include type checking as a preliminary step in testing suites, allowing early detection of type errors before runtime, which enhances reliability in automated builds. For deployment, the generates minified outputs that are fully compatible with content delivery networks (CDNs) and web servers, facilitating efficient distribution of applications. JS++ tools accommodate mixed-language projects in monorepos, where JS++ files coexist with untyped , enabling phased adoption without disrupting ongoing development. JS++ uniquely facilitates gradual migration in legacy projects by providing mechanisms to incrementally apply to existing files, preserving compatibility with unmodified code while progressively enhancing across large codebases.

References

Add your contribution
Related Hubs
User Avatar
No comments yet.