ECMAScript 2019 comes to XS

The latest push of the XS JavaScript engine implements support for the forthcoming ECMAScript 2019 standard.

The ECMAScript 2019 standard includes several new capabilities and refinements but no major new features. A complete summary of the changes with links to details is available on the "2ality – JavaScript and more" blog by Axel Rauschmayer.

For XS, the most important change is a seemingly minor change to Function.prototype.toString. More on that below.

Conformance

XS passes 99.8% of the test262 language conformance tests and 99.8% of the built-ins conformance tests as well. As usual, the details are available together with instructions for running XS against test262.

Function.prototype.toString

The ability to access the source code of a JavaScript function is an essential feature of JavaScript on the web. It is used for a surprisingly wide variety of purposes, and some popular frameworks depend on this capability. The XS JavaScript engine is optimized for microcontrollers, not the web, and consequently has a different set of priorities from JavaScript engines focused on the browser.

The way JavaScript code accesses the source code of a function is elegant - it simply calls the toString function on the function object itself.

let x = add(1, 2);
let addSourceCode = add.toString();

The JavaScript language has long acknowledged that it is impossible to provide the JavaScript source code for every function. The built-in functions (e.g. Math.sqrt and Array.prototype.sort) are often implemented in C, so no JavaScript source code is available. Other situations, such as functions created with Function.prototype.bind cannot be represented with only JavaScript source code. For this reason, Function.prototype.toString has been allowed to return a special result in these situations, a string of invalid JavaScript "source code" that cannot be compiled.

One way that the XS JavaScript engine differs from engines focused on the web is that XS usually compiles JavaScript source code on a computer and then deploys it to the device where it executes. The device where the code executes often does not even have a JavaScript compiler.

Note: Having the eval function always throw an exception when invoked is allowed by the JavaScript standard. XS does support eval though many deployments omit it. For details see Compiling JavaScript on Embedded Devices.

Because these devices have limited storage space and because it is not possible to compile JavaScript source code to executable form, it makes little sense to include the source code to JavaScript in the flash storage of these devices. Consequently, XS does not make the source code to scripts available via Function.prototype.toString, and instead follows the model of native functions by returning a string that cannot be compiled.

In ECMAScript 2019, the host is now allowed to decide whether or not to provide scripts with the source code to JavaScript functions. This change allows the existing behavior of XS to be conformant with the standard. Additionally, this change may have security benefits for the web platform in the future, as it allows web browsers to deny a script access to a function's JavaScript source code under certain conditions.

The ECMAScript 2019 standard also fully defines the string returned when source code is unavailable. This eliminates potential future issues. The string returned is this:

function (){[native code]}

This string is imperfect. The content of the string suggests the reason the JavaScript source code is unavailable is because the function is implemented in native code. The reality is that the source code may be unavailable for many reasons. Those reasons include the following:

  • The engine does not have the source code available
  • A security policy prevents access to the script
  • The function was created by function.prototype.bind
  • It is implemented in native code

The above string should simply be understood to mean "the source code isn't available to you." The reason it is unavailable is not given. A more general purpose string is desirable, but for backwards compatibility the committee chose to remain with the "native code" string.

And BigInt

Earlier this year XS shipped an implementation of BigInt, JavaScript's support for arbitrary precision integers. BigInt is not yet part of the official JavaScript standard, though it is at Stage 3 in the proposal process with full implementations in V8 and XS. Therefore, it seems likely to be part of the standard in the near future. The BigInt implementation in XS has been improved in this update to conform with additions to the test262 suite since the initial deployment of BigInt in XS.