“JS++ is seamlessly compatible with all JavaScript libraries, frameworks, and APIs”
JAXenter: What is JS++ and why should developers use it? What are the immediate benefits?
Roger Poon: JS++ is a superset of JavaScript (ECMAScript 3 specification) featuring a sound gradual type system. While alternatives to JS++ have existed from large companies (including Microsoft TypeScript and “Safe TypeScript” from Microsoft Research; Google AtScript and SoundScript; and Facebook Flow), these alternatives have never been able to achieve “soundness” in their type system. Here’s another explanation of soundness, specifically he describes (please note this is not the actual case in Java, just an illustrative example):
“… Java’s type system is unsound if, say, without casting or other ‘unsafe’ operations, we could have a compile-time Integer that is actually a runtime String.”
When you declare a data type in JS++, it is guaranteed to be correct. Furthermore, it is guaranteed to be correct during compile time analysis and runtime execution after the application has been released.
In contrast, the popular alternative for adding types to JavaScript, Microsoft TypeScript, has over 72,000 results on Stack Overflow relating to TypeErrors alone that occur at runtime… after successful compiles. The reason is because TypeScript’s type system is unsound, and you should not expect the same runtime behaviors you’d expect from other programming languages where declaring types can guarantee correct program behavior as it relates to types – such as in Java. In TypeScript, this is known as “type erasure” (in contrast to JS++’s “type guarantees”), and TypeScript describes soundness as not a goal. Thus, in Microsoft TypeScript, it’s possible to declare your types and then have the application crash with a type error on the declared types.
Type errors are a major class of errors in JavaScript. Here’s a screenshot where GoDaddy lost sales revenue due to a runtime ‘TypeError’ (highlighted) that prevented the PayPal checkout from proceeding. Here’s a screenshot of Google Image Search being broken with lots of runtime TypeErrors; it’s not evident from the screenshot, but the Google error occurred on Easter Sunday 2018, when their team was on holiday.
JAXenter: How does JS++ work?
Roger Poon: JS++ extends the JavaScript language with new features, specifically JavaScript as standardized in the ECMAScript 3 specification. (JS++ was first released in October 2011 so it pre-dates ECMAScript 6 by four years, TypeScript by one year, etc. At the time, Internet Explorer 6 was still important for backwards compatibility, so ECMAScript 3 was chosen over ECMAScript 5 for maximum compatibility. This also allows us to address legacy enterprise web applications even today.)
JS++ works by compiling to ECMAScript 3 JavaScript. As a result, JS++ will work anywhere that JavaScript will work. This ranges from Internet Explorer 6 to the latest Chrome and iOS/Android browsers, but it also includes Node.js server applications, Windows Script Host (WSH) macros, Arduino, system utilities, game scripting, and more.
We spent the most time on the type system design, which dates back to work beginning in October 2011, exactly one year before Microsoft TypeScript was announced. We have an advanced type system that enables sound gradual typing at scale and efficient out-of-bounds error analysis. Unlike other JavaScript supersets, we have a focus on correctness. One of our cornerstone features (“type guarantees”) enables developers to correctly and gradually migrate dynamically-typed code to static typing (which is a much harder problem to solve than the reverse: enabling dynamic typing on mostly statically-typed code which, in most cases, are already well-typed).
JS++ works by compiling to ECMAScript 3 JavaScript. As a result, JS++ will work anywhere that JavaScript will work.
JAXenter: What are “type guarantees” in JS++? How does it differ from Microsoft TypeScript (the popular alternative for adding types to JavaScript)?
Roger Poon: Although we compile to JavaScript, the cornerstone of the JS++ language is “type guarantees.” In other words, when you declare your data types, they are guaranteed to be correct during compile time checking and runtime code execution. “Type guarantees” mean that JS++ is more akin to C, C++, Java, and C# than JavaScript/TypeScript because declaring the data types will change the semantics of your program.
Consider a Java program where a variable is declared as ‘int’ versus ‘String’. The operations allowed on the variable will change. The compiler will reject your programs and give you an error if you try a subtraction with a variable declared as ‘String’ but not for ‘int’.
Here is a correct Java program: https://ideone.com/
Here’s an incorrect Java program: https://ideone.com/
The incorrect program is not even allowed to compile. Thus, since no program was compiled or built, there is no program to run. In contrast, JavaScript and Microsoft TypeScript can allow incorrect programs to compile, run, and even be distributed. Here are four lines of TypeScript that will fail at runtime (when the application is running) with a type error but will pass the compiler’s checking:
var func:any = function() {}; var str1:string = func; var str2:string = str1.toLowerCase(); // TypeError: undefined is not a function console.log(str2); // Never runs. Program already crashed from TypeError.
Here are 2-3 lines of JavaScript that will fail at runtime:
// Simple variable declaration. Innocuous, right? var a = typo; // ReferenceError: typo is not defined console.log("Script started"); // Never runs. Script already crashed with ReferenceError.
Microsoft considers “a sound and ‘provably correct’ type system” (exact quote) to be a non-goal: https://github.com/
There are pros and cons to both approaches. With TypeScript, you get better IntelliSense if your codebase is mostly JavaScript rather than a JavaScript superset. With JS++, you get accurate analysis for type errors and predictable application runtime behavior that conforms with the types you declared. While we haven’t delivered it yet, JS++ is capable of IntelliSense but only for the “JS++ code” (e.g. declared with “unsigned int”, “class”, “interface”, etc.) rather than the “JavaScript code” (e.g. declared with “var” and “function”).
JAXenter: What are some of the corner cases in JavaScript that TypeScript has trouble handling?
Roger Poon: I started JS++ in 2011 with a deep understanding of corner cases that I don’t believe the TypeScript team can rival. This is why I believe JS++ is the better option whether you need to write a simple library or if you need backwards compatibility with a large, complex, legacy enterprise codebase.
For example, consider the following code (which is tested in IE6 for Windows XP):
var x = new ActiveXObject("WScript.shell"); alert(typeof x); // "object" alert(typeof x.run); // "unknown" x.run("explorer.exe"); // Opens Windows Explorer
Notice how ‘typeof’ returns “unknown”. MSDN does not document an “uknown” type for ActiveXObject. Clearly, the code is not incorrect; if executed, it will open Windows Explorer. This code is indeed correct and conforms with the ECMAScript 3 specification. ECMAScript 3 Section 11.4.3 “The typeof Operator” allows an “implementation-dependent” result for host objects, which includes ActiveXObjects, DOM objects, etc.
In another case, TypeScript uses structural typing. JS++ uses nominal typing. Structural typing doesn’t consider the case where an ‘Array’ (case-sensitive) in a parent page is not the same ‘Array’ (case-sensitive) in an iframe of the parent page. If the ‘Array’ inside the iframe is extended or changed, the ‘Array’ of the parent page may not necessarily change; thus, the structure of ‘Array’ in the iframe should not match the ‘Array’ of the parent page during static code analysis. Yet, this is very difficult to detect during static analysis, and TypeScript can mistakenly pass a type check here. In contrast, JS++ ‘external’ will remain correct.
JS++ can be used wherever JavaScript can be used, but we caution that JS++ has not reached 1.0 yet.
In yet another case, TypeScript’s lib.d.ts incorrectly returned ‘NodeList’ for the DOM API’s ‘getElementsByTagName’ (proof). This makes IntelliSense inaccurate, this makes the compiler’s analysis inaccurate, and this risks user’s code crashing at runtime as a consequence. At the time Microsoft made this error, Firefox did not implement ‘getElementsByTagName’ as returning ‘NodeList’ but other browsers did. Mozilla insisted that this function should return an “HTMLCollection” because this is correct according to the DOM API specification despite the fact that all other web browsers implemented it differently. This bug was filed in 1999 and was marked as “WONTFIX” by Mozilla. They could have fixed this for 20 years and chose not to.
These are fundamental design errors TypeScript made from failing to understand JavaScript and ECMAScript corner cases. An investment into TypeScript means accepting all the problems – now and in the future – that could have been avoided by choosing JS++. This results in technical debt that could have been avoided altogether. JS++ will work for Windows Script Host, buggy implementations of the DOM API, buggy garbage collector implementations where the data (and thus the types) change because an object was incorrectly collected early, nuances of the ECMAScript language specification, and so on.
JAXenter: When should JS++ be used?
Roger Poon: JS++ can be used wherever JavaScript can be used, but we caution that JS++ has not reached 1.0 yet. We’re close, but there are still edges to iron out.
JS++ is seamlessly compatible with all JavaScript libraries, frameworks, and APIs (such as the Document Object Model API for scripting the web browser).
Use cases:
- Node.js (server applications)
- Frontend web development
- Windows Script Host (WSH) macros
- Migrating complex, legacy enterprise JavaScript applications (such as corporate intranet applications)
SEE ALSO: State of JavaScript 2018: Angular’s downfall and new up-and-comers
JAXenter: What’s next for JS++?
Roger Poon: Version 1.0 and IntelliSense. These are the two biggest things on the horizon for JS++, and they are the most requested by our users.
JAXenter: What is an out-of-bounds error?
Roger Poon: An out-of-bounds error occurs when you try to access a container element that does not exist in the container.
JAXenter: How does JS++ prevent out-of-bounds errors?
When used correctly, existent types will prevent the application from terminating prematurely via abort(), segfaults, uncaught exceptions, runtime errors, etc.
JAXenter: Does TypeScript prevent out-of-bounds errors?
Roger Poon: No, a lot of languages can’t. However, in our latest benchmarks, we showed that you can compile 6,000 lines of JS++ code across 70 files – with sound type checking and full analysis of out-of-bounds errors – four times over in the time it takes TypeScript to compile 3 lines of code and get the types wrong. Here’s the TypeScript code and proof:
$ ./node_modules/typescript/bin/tsc --version Version 3.2.2 $ cat test.ts const xs: number[] = [1,2,3]; let x:number = xs[1000]; // number... even with --strictNullChecks console.log(x); $ time ./node_modules/typescript/bin/tsc --strictNullChecks test.ts real 0m1.084s user 0m1.692s sys 0m0.016s $ node test.js undefined
However, it should be said that out-of-bounds errors have existed since the first high-level programming language, Fortran, and continues to be a problem today.
JAXenter: JS++ is described as having “nearly no learning curve.” Can you elaborate on this?
Roger Poon: Once you learn “internal types” (JS++ types), “external types” (JavaScript types, although technically it describes more), and the conversions between them, the rest of JS++ should be intuitive for programmers with backgrounds in C, C++, Java, and C#.
For example, function overloading in JS++ is what you would expect: multiple function declarations with the same name. In TypeScript, users run into surprises where one function body handles all constructor overloads. Furthermore, JS++ has 8-, 16-, 32-, and 64-bit signed and unsigned integer types, so there aren’t any ‘NaN’ surprises that arise when all your numbers are IEEE-754 doubles as in JavaScript/TypeScript.
SEE ALSO: Pluralsight 2018 wrap-up: JavaScript reigns supreme, Dart gains momentum
JAXenter: Can you describe the migration path from JavaScript to JS++?
Roger Poon: Due to its advanced type system, JS++ can be one cog in a larger system. There is no vendor lock-in. For example, your JS++ commitment can be one file, one class, one module, one project, or even one line of code. JS++ is backwards- and forwards-compatible with JavaScript. It is designed to be seamlessly compatible with the rest of your system whether it’s JavaScript, TypeScript, etc – without vendor lock-in.
In contrast, TypeScript requires steep commitment due to its unsound type system. Before you can reap the full benefits of TypeScript, you have to add “typings” to almost all your code before it’s able to perform meaningful analyses. One company described their migration of 30,000 lines of JavaScript to TypeScript, and their independent conclusions were:
- You can’t always trust the compiler
- Type inference doesn’t go very far
- TypeScript requires many type annotations
- Types are still your assumptions
- Typing can’t always be incremental
- Circular dependencies
All of the problems listed above (except circular dependencies) are side effects of an unsound type system – everything from being unable to trust the compiler to requiring lots of type annotations before the tool becomes useful. It needs to be re-emphasized that JS++ can start becoming useful with one type annotation. We do not require you to rewrite your entire code base. They specifically highlighted that TypeScript failed incrementally (so you’re not going to just use it on 1% of a 1 million line code base), required many type annotations before it became useful (again, you’re not going to use it on 1% of your code successfully – even though technically you can, and Microsoft will tout this as a win without discussing the theoretical concerns), the risk of human error (e.g. I can declare a string but accidentally tell TypeScript it is a number), and so on.
An investment into TypeScript means accepting all the problems – now and in the future – that could have been avoided by choosing JS++
The problems they faced with the TypeScript compiler and type system don’t just grow linearly. Logically, they would exponentiate at scale if you think A is a number (but it’s actually a string at runtime) and the variables B, C, D, E depend on A and have further dependencies themselves.
It’s also interesting to note how they were bitten by a TypeScript breaking change:
“TypeScript doesn’t allow circular dependencies. Sort of. TypeScript was happily compiling our code, circular dependencies and all, for months until one day it broke.”
Despite having reached version 1.0 nearly 5 years ago, Microsoft TypeScript still routinely makes breaking changes on each new release. Meanwhile, JS++ automatically handles circular dependencies, automatically resolves complex cross-file import and inheritance hierarchies, and almost never makes breaking changes. I provide an explanation of the engineering behind how we efficiently handle circular dependencies – even in the presence of ambiguities – here.
In JS++, you don’t need to figure out all the types in your existing code. You only need to add types going forward in your new code or incrementally add types one-by-one to your existing code. Our Getting Started guide teaches both these techniques. You can also write a library in JS++ that can be consumed in JavaScript, and the types that you declared by writing the library in JS++ will be “preserved” even though you’re using the library from JavaScript via the toExternal/fromExternal design pattern. Finally, you can import an entire JavaScript library to JS++ using the external statement.
As a consequence, JS++ can be used in one file, one library, one class, one module or scale to your entire project. Thus, since JS++ works so well from the smallest commitment to the largest commitment, there is almost no vendor lock-in and no future risk of vendor lock-in.
Thank you!
The post “JS++ should be intuitive for programmers with backgrounds in C, C++, Java, and C#” appeared first on JAXenter.
Source : JAXenter