JavaScript Compatibility

GraalVM provides an ECMAScript-compliant JavaScript language runtime. This document explains the public API it presents for user applications written in JavaScript.

ECMAScript Language Compliance #

GraalVM JavaScript implements JavaScript as prescribed in the ECMAScript (ECMA-262) specification. It is fully compatible with the ECMAScript 2023 specification (sometimes referred to as the 14th edition). New features are frequently added to GraalVM when they are confirmed to be part of ECMAScript 2024, see the CHANGELOG.md for details. Older versions starting from ECMAScript 5 can be enabled with a config flag (by number: --js.ecmascript-version=5 or by year: --js.ecmascript-version=2019). In a production setup you might consider specifying a fixed ECMAScript version to be used, as future versions of GraalVM JavaScript will use newer versions of the specification once available.

GraalVM JavaScript provides the following function objects in the global scope as specified by ECMAScript, representing the JavaScript core library: Array, ArrayBuffer, Boolean, DataView, Date, Error, Function, JSON, Map, Math, Number, Object, Promise, Proxy, Reflect, RegExp, Set, SharedArrayBuffer, String, Symbol, TypedArray, WeakMap, and WeakSet.

Additional objects are available under flags, for instance Temporal (flag: --js.temporal). Run js --help or js --help:languages for the list of available flags.

Several of these function objects and some of their members are only available when a certain version of the specification is selected for execution. For a list of methods provided, inspect the ECMAScript specification. Extensions to the specification are specified below.

Internationalization API (ECMA-402) #

GraalVM JavaScript comes with an implementation of the ECMA-402 Internationalization API, enabled by default (can be disabled using the following flag: --js.intl-402=false). This includes the following extensions:

  • Intl.Collator
  • Intl.DateTimeFormat
  • Intl.DisplayNames
  • Intl.ListFormat
  • Intl.Locale
  • Intl.NumberFormat
  • Intl.PluralRules
  • Intl.RelativeTimeFormat
  • Intl.Segmenter

The functionality of a few other built-ins, like toLocaleString, is also updated according to the ECMA-402 specification.

JavaScript Modules #

GraalVM JavaScript supports modules as defined by ECMAScript 6 and later. Be aware that the support for this feature grew and still grows over time. Be sure to use the latest ECMAScript version for the all the latest features.

When loading modules via a polyglot Source, you can use the inofficial application/javascript+module mime type to specify you are loading a module. When loading with JavaScript code from a file, make sure the module is loaded from a file with the .mjs extension. Loading with the import keyword is not limited by that, and can import from a file of any extension.

Compatibility Extensions #

The following objects and methods are available in GraalVM JavaScript for compatibility with other JavaScript engines. Note that the behavior of such methods might not strictly match the semantics of those methods in all existing engines.

Language Features #

Conditional Catch Clauses

GraalVM JavaScript supports conditional catch clauses if the js.syntax-extensions option is enabled:

try {
    myMethod(); // can throw
} catch (e if e instanceof TypeError) {
    print("TypeError caught");
} catch (e) {
    print("another Error caught");
}

Global Properties #

load(source)

  • loads (parses and executes) the specified JavaScript source code

Source can be of type:

  • a String: the path of the source file or a URL to execute.
  • java.lang.URL: the URL is queried for the source code to execute if the js.load-from-url option is set to true.
  • java.io.File: the file is read for the source code to execute.
  • a JavaScript object: the object is queried for a name and a script property, which represent the source name and code, respectively.
  • all other types: the source is converted to a String.

load is available by default and can be deactivated by setting the js.load option to false.

print(...arg) and printErr(...arg)

  • prints the arguments on the console (stdout and stderr, respectively)
  • provides a best-effort human readable output

print and printErr are available by default and can be deactivated by setting the js.print option to false.

Methods of the console Global Object

A global console object is provided that offers several methods for debugging purposes. These methods strive to provide similar functionality as provided in other engines, but do not guarantee identical results.

Note that those methods behave differently when GraalVM JavaScript is executed in Node.js mode (i.e., the node executable is started instead of js). Node.js provides its own implementation that is used instead.

  • console.log, console.info, and console.debug: an alias for print(...arg)
  • console.error, and console.warn: similar to print, but using the error IO stream
  • console.assert(check, message): prints message when check is falsy
  • console.clear: clears the console window if possible
  • console.count(), and console.countReset(): counts and print how many times it has been called, or resets this counter
  • console.group, and console.groupEnd: increases or decreases the indentation for succeeding outputs to the console
  • console.time(), console.timeLog(), and console.timeEnd(): starts a timer, prints the duration the timer has been active, or prints the duration and stops the timer, respectively

The console object is available by default and can be deactivated by setting the option js.console to false.

Additional Global Functions in the js Shell #

quit(status)

  • exits the engine and returns the specified status code

read(file)

  • reads the content of file

The result is returned as a String.

The argument file can be of type:

  • java.io.File: the file is used directly.
  • all other types: file is converted to a String and interpreted as a file name.

readbuffer(file)

  • reads the content of file similar to the read function

The result is returned as a JavaScript ArrayBuffer object.

readline()

  • reads one line of input from the input stream

The result is returned as a String.

Object #

Object.prototype.__defineGetter__(prop, func)

  • defines the prop property of this to be the getter function func

This functionality is deprecated in most JavaScript engines. In recent ECMAScript versions, getters and setters are natively supported by the language.

Object.prototype.__defineSetter__(prop, func)

  • defines the prop property of this to be the setter function func

This functionality is deprecated in most JavaScript engines. In recent ECMAScript versions, getters and setters are natively supported by the language.

Object.prototype.__lookupGetter__(prop)

  • returns the getter function for property prop of the object as set by __defineGetter__

This functionality is deprecated in most JavaScript engines. In recent ECMAScript versions, getters and setters are natively supported by the language.

Object.prototype.__lookupSetter__(prop)

  • returns the setter function for property prop of the object as set by __defineSetter__

This functionality is deprecated in most JavaScript engines. In recent ECMAScript versions, getters and setters are natively supported by the language.

Nashorn Scripting Mode #

GraalVM JavaScript provides a scripting mode compatible with the one provided by the Nashorn engine. It is enabled with the js.scripting option. Make sure to have --experimental-options set:

js --experimental-options --js.scripting=true

In scripting mode, several properties and functions are added to the global object, including readFully, readLine, $ARG, $ENV, and $EXEC.

There are migration guides available for code previously targeted to the Nashorn or Rhino engines.

GraalVM JavaScript Extensions #

Graal Object #

The Graal object is provided as a property of the global object. It provides Graal-specific information. The existence of the property can be used to identify whether the GraalVM JavaScript engine is the current language engine:

if (typeof Graal != 'undefined') {
    print(Graal.versionECMAScript);
    print(Graal.versionGraalVM);
    print(Graal.isGraalRuntime());
}

The Graal object is available in GraalVM JavaScript by default, unless deactivated by an option (js.graal-builtin=false).

Graal.versionECMAScript

  • provides the version number (year value) of GraalVM JavaScript’s ECMAScript compatibility mode.

Graal.versionGraalVM

  • provides the version of GraalVM, if the current engine is executed on GraalVM

Graal.isGraalRuntime()

  • provides whether GraalVM JavaScript is executed on a GraalVM-enabled runtime
  • If true, hot code is compiled by the GraalVM compiler, resulting in high peak performance.
  • If false, GraalVM JavaScript will not be optimized by the GraalVM Compiler, typically resulting in lower performance.

Graal.setUnhandledPromiseRejectionHandler(handler) #

  • provides the unhandled promise rejection handler when using option (js.unhandled-rejections=handler).
  • the handler is called with two arguments: (rejectionReason, unhandledPromise).
  • Graal.setUnhandledPromiseRejectionHandler can be called with null, undefined, or empty arguments to clear the handler.

Java #

The Java object is only available when host class lookup is allowed. In order to access Java host classes and its members, they first need to be allowed by the host access policy, and when running from a Native Image, be registered for run time reflection.

Note that some functions require the Nashorn compatibility mode flag to be set. When running from the JVM standalone distribution, this flag can be set with:

js --experimental-options --js.nashorn-compat=true

Java.type(className)

Java.type loads the specified Java class and returns a constructible object that has the static members (i.e. methods and fields) of the class and can be used with the new keyword to construct new instances:

var BigDecimal = Java.type('java.math.BigDecimal');
var point1 = new BigDecimal("0.1");
var two = BigDecimal.TWO;
console.log(point1.multiply(two).toString());

Note that when used directly with the new operator, Java.type(...) needs to be enclosed in parentheses:

console.log(new (Java.type('java.math.BigDecimal'))("1.1").pow(15));

Java.from(javaData)

Java.from creates a shallow copy of the Java data structure (Array, List) as a JavaScript array.

In many cases, this is not necessary; you can typically use the Java data structure directly from JavaScript.

Java.to(jsData, javaType)

Java.to converts the argument to the Java type.

The source object jsData is expected to be a JavaScript array, or an array-like object with a length property. The target javaType can either be a String (e.g. "int[]") or a type object (e.g., Java.type("int[]")). Valid target types are Java arrays. When the target type is omitted, it defaults to Object[].

var jsArray = ["a", "b", "c"];
var stringArrayType = Java.type("java.lang.String[]");
var javaArray = Java.to(jsArray, stringArrayType);
assertEquals('class java.lang.String[]', String(javaArray.getClass()));
var javaArray = Java.to(jsArray);
assertEquals('class java.lang.Object[]', String(javaArray.getClass()));

The conversion methods as defined by ECMAScript (e.g., ToString and ToDouble) are executed when a JavaScript value has to be converted to a Java type. Lossy conversion is disallowed and results in a TypeError.

Java.isJavaObject(obj)

  • returns true if obj is a Java host object
  • returns false for native JavaScript objects, as well as for objects of other polyglot languages

Java.isType(obj)

  • returns true if obj is an object representing the constructor and static members of a Java class, as obtained by Java.type() or package objects.
  • returns false for all other arguments

Java.typeName(obj)

  • returns the Java Class name of obj when obj represents a Java type (isType(obj) === true) or Java Class instance
  • returns undefined otherwise

Java.isJavaFunction(fn)

  • returns whether fn is an object of the Java language that represents a Java function
  • returns false for all other types, including native JavaScript function, and functions of other polyglot languages

This function is only available in Nashorn compatibility mode (--js.nashorn-compat=true).

Java.isScriptObject(obj)

  • returns whether obj is an object of the JavaScript language
  • returns false for all other types, including objects of Java and other polyglot languages

This function is only available in Nashorn compatibility mode (--js.nashorn-compat=true).

Java.isScriptFunction(fn)

  • returns whether fn is a JavaScript function
  • returns false for all other types, including Java function, and functions of other polyglot languages

This function is only available in Nashorn compatibility mode (--js.nashorn-compat=true).

Java.addToClasspath(location)

  • adds the specified location (a .jar file or directory path string) to Java’s classpath

Polyglot #

The functions of the Polyglot object allow to interact with values from other polyglot languages.

The Polyglot object is available by default, unless deactivated by setting the js.polyglot-builtin option to false.

Polyglot.export(key, value)

  • exports the JavaScript value under the name key (a string) to the polyglot bindings:
    function helloWorld() { print("Hello, JavaScript world"); }
    Polyglot.export("helloJSWorld", helloWorld);
    

If the polyglot bindings already had a value identified by key, it is overwritten with the new value. The value may be any valid Polyglot value.

  • throws a TypeError if key is not a String or is missing

Polyglot.import(key)

  • imports the value identified by key (a string) from the polyglot bindings and returns it:
    var rubyHelloWorld = Polyglot.import("helloRubyWorld");
    rubyHelloWorld();
    

If no language has exported a value identified by key, undefined is returned.

  • throws a TypeError if key is not a string or missing

Polyglot.eval(languageId, sourceCode)

  • parses and evaluates the sourceCode with the interpreter identified by languageId

The value of sourceCode is expected to be a String (or convertable to one).

  • returns the evaluation result, depending on the sourceCode and/or the semantics of the language evaluated:
    var rArray = Polyglot.eval('R', 'runif(1000)');
    

Exceptions can occur when an invalid languageId is passed, when the sourceCode cannot be evaluated by the language, or when the executed program throws one.

Polyglot.evalFile(languageId, sourceFileName)

  • parses the file sourceFileName with the interpreter identified by languageId

The value of sourceFileName is expected to be a String (or convertable to one), representing a file reachable by the current path.

  • returns an executable object, typically a function:
    var rFunc = Polyglot.evalFile('R', 'myExample.r');
    var result = rFunc();
    

Exceptions can occur when an invalid languageId is passed, when the file identified by sourceFileName cannot be found, or when the language throws an exception during parsing (parse time errors, e.g. syntax errors). Exceptions thrown by the evaluated program are only thrown once the resulting function is evaluated.

The Polyglot.evalFile function is available by default when the Polyglot builtin is available, unless deactivated by setting the js.polyglot-evalfile option to false. It is also available when js.debug-builtin is activated.

Debug #

  • requires starting the engine with the js.debug-builtin flag

Debug is a GraalVM JavaScript specific function object that provides functionality for debugging JavaScript code and the GraalVM JavaScript compiler. This API might change without notice. Do not use for production purposes.

Global Functions #

printErr(...arg)

  • behaves identical to print

The only difference is that the error stream is used to print to, instead of the default output stream.

loadWithNewGlobal(source, arguments)

  • behaves similarly to load function

The relevant difference is that the code is evaluated in a new global scope (Realm, as defined by ECMAScript).

Source can be of type:

  • java.lang.URL: the URL is queried for the source code to execute.
  • a JavaScript object: the object is queried for a name and a script property.
  • all other types: the source is converted to a String.

The value of arguments is provided to the loaded code upon execution.

Connect with us