Skip to content

Commit

Permalink
Merge JS&Node.js reference documentation from graalvm.org with User d…
Browse files Browse the repository at this point in the history
…ocs on GitHub
  • Loading branch information
olyagpl committed Jul 30, 2020
1 parent 6bb9171 commit e15acc9
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 95 deletions.
67 changes: 58 additions & 9 deletions docs/user/FAQ.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,37 @@
# Frequently Asked Questions

This file lists frequently asked questions and answers around GraalVM JavaScript.
Find the most frequently asked questions and answers around GraalVM JavaScript.

## Compatibility

### My application used to run on Nashorn, it does not work on GraalVM JavaScript
### Is GraalVM compatible with the JavaScript language?
GraalVM is compatible to the ECMAScript 2020 specification. The compatibility of GraalVM JavaScript is verified by external sources, like the [Kangax ECMAScript compatibility table](https://kangax.github.io/compat-table/es6/).

GraalVM JavaScript is tested against a set of test engines, like the official test suite of ECMAScript, [test262](https://github.com/tc39/test262), as well as tests published by V8 and Nashorn, Node.js unit tests and GraalVM's own unit tests.

For a reference of the JavaScript APIs that GraalVM supports, see [GRAAL.JS-API](https://github.com/graalvm/graaljs/blob/master/docs/user/JavaScriptCompatibility.md).

### Is GraalVM compatible with the original node implementation?
Node.js based on GraalVM is largely compatible with the original Node.js (based on the V8 engine).
This leads to a high number of npm-based modules being compatible with GraalVM (out of the 95k modules we test, more than 90% of them pass all tests).
Several sources of differences have to be considered.

- **Setup:**
GraalVM mostly mimicks the original setup of Node, including the `node` executable, `npm` and similar. However, not all command-line options are supported (or behave exactly identically), you need to (re-)compile native modules against the v8.h file, etc..

- **Internals:**
GraalVM is implemented on top of a JVM, and thus has a different internal architecture. This implies that some internal mechanisms behave differently and cannot exactly replicate V8 behaviour. This will hardly ever affect user code, but might affect modules implemented natively, depending on V8 internals.

- **Performance:**
Due to GraalVM being implemented on top of a JVM, performance characteristics vary from the original native implementation. While GraalVM's peak performance can match V8 on many benchmarks, it will typically take longer to reach the peak (known as _warmup_). Be sure to give the GraalVM compiler some extra time when measuring (peak) performance.

In addition, GraalVM uses the following approaches to check and retain compatibility to Node.js code:

* node-compat-table: GraalVM is compared against other engines using the _node-compat-table_ module, highlighting incompatibilities that might break Node.js code.
* automated mass-testing of modules using _mocha_: in order to test a large set of modules, GraalVM is tested against 95k modules that use the mocha test framework. Using mocha allows automating the process of executing the test and comprehending the test result.
* manual testing of popular modules: a select list of npm modules is tested in a manual test setup. These highly-relevant modules are tested in a more sophisticated manner.

### My application used to run on Nashorn, it does not work on GraalVM JavaScript
Reason:
* GraalVM JavaScript tries to be compatible to the ECMAScript specification, as well as competing engines (including Nashorn). In some cases, this is a contradicting requirement; then, ECMAScript is given precedence. Also, there are cases where GraalVM Javascript is not exactly replicating Nashorn features intentionally, e.g. for security reasons.

Expand All @@ -25,16 +51,24 @@ Solution:
* While the objects don't have the methods of the prototype assigned, you can explicitly call them, e.g. `Array.prototype.call.sort(myArray)`.
* We offer the experimental option `js.experimental-foreign-object-prototype`. When enabled, objects on the JavaScript side get the most prototype (e.g. `Array.prototype`, `Function.prototype`, `Object.prototype`) set and can thus behave more similarly to native JavaScript objects of the respective type. Normal JavaScript precedence rules apply here, e.g. own properties (of the Java object in that case) take precedence over and hide properties from the prototype.

Note that while the JavaScript builtin functions e.g. from `Array.prototype` can be called on the respective Java types, those functions expect JavaScript semantics.
Note that the JavaScript builtin functions e.g., from `Array.prototype` can be called on the respective Java types, those functions expect JavaScript semantics.
This for instance means that operations might fail (typically with a `TypeError`: `Message not supported`) when an operation is not supported in Java.
Consider `Array.prototype.push` as an example: while arrays can grow in size in JavaScript, they are fixed-size in Java, thus pushing a value is semantically not possible and will fail.
In such cases, you can wrap the Java object and handle that case explicitly.
Use the interfaces `ProxyObject` and `ProxyArray` for that purpose.

## Performance
### How can one verify GraalVM works on their application?
If your module ships with tests, execute them with GraalVM. Of course, this will
only test your application, but not its dependencies. You can use the
[Compatibility](https://www.graalvm.org/docs/reference-manual/compatibility/)
tool to find whether the module you are interested in is tested on GraalVM,
whether the tests pass successfully. Additionally, you can upload your
`package-lock.json` or `package.json` file into that tool and it will analyze
all your dependencies at once.

### My application is slower on GraalVM JavaScript than on [another engine]
## Performance

### My application is slower on GraalVM JavaScript than on another engine
Reason:
* Ensure your benchmark considers warmup. During the first few iterations, GraalVM JavaScript will be slower than natively implemented engines, while on peak performance, this difference should level out.
* GraalVM JavaScript is shipped in two different modes: `native` (default) and `JVM`. While the default of `native` offers fast startup, it might show slower peak performance once the application is warmed up. In the `JVM` mode, the application might need a few hundred milliseconds more to start, but typically shows better peak performance.
Expand All @@ -43,12 +77,29 @@ Solution:
* Use proper warmup in your benchmark, and disregard the first few iterations where the application still warms up.
* Use the `--jvm` option for slower startup, but higher peak performance.
* Double-check you have no flags set that might lower your performance, e.g. `-ea`/`-esa`.
* Try to minify the problem to the root cause, and [file an issue](https://github.com/graalvm/graaljs/issues) so the GraalVM team can have a look.
* Try to minify the problem to the root cause and [file an issue](https://github.com/graalvm/graaljs/issues) so the GraalVM team can have a look.

### How to achieve the best peak performance?
Here are a few tips you can follow to analyse and improve peak performance:

* When measuring, ensure you have given the GraalVM compiler enough time to compile all hot methods before starting to measure peak performance. A useful command line option for that is `--vm.Dgraal.TraceTruffleCompilation=true` -- this outputs a message whenever a (JavaScript) method is compiled. As long as this still prints frequently, measurement should not yet start.
* Compare the performance between the Native Image and the JVM mode if possible. Depending on the characteristics of your application, one or the other might show better peak performance.
* The Polyglot API comes with several tools and options to inspect the performance of your application:
* `--cpusampler` and `--cputracer` will print a list of the hottest methods when the application is terminated. Use that list to figure out where most time is spent in your application.
* `--experimental-options --memtracer` can help you understand the memory allocations of your application. Refer to the [Profiling Command Line Tool](https://www.graalvm.org/docs/tools/profiler) reference for more detail.

### What is the difference between running GraalVM's JavaScript in a Native Image compared to the JVM?_
In essence, the JavaScript engine of GraalVM is a plain Java application.
Running it on any JVM (JDK 8 or higher) is possible, but, for a better result, it should be GraalVM or a compatible JVMCI-enabled JDK using the GraalVM compiler.
This mode gives the JavaScript engine full access to Java at runtime, but also requires the JVM to first (just-in-time) compile the JavaScript engine when executed, just like any other Java application.

Running in a Native Image means that the JavaScript engine, including all its dependencies from, e.g., the JDK, is pre-compiled into a native binary. This will tremendously speed up the startup of any JavaScript application, as GraalVM can immediately start to compile JavaScript code, without itself requiring to be compiled first.
This mode, however, will only give GraalVM access to Java classes known at the time of image creation.
Most significantly, this means that the JavaScript-to-Java interoperability features are not available in this mode, as they would require dynamic class loading and execution of arbitrary Java code at runtime.

## Errors

### TypeError: Access to host class com.myexample.MyClass is not allowed or does not exist

Reason:
* You are trying to access a Java class that is not known to the `js` or `node` process, or is not among the allowed classes your code can access.

Expand All @@ -58,7 +109,6 @@ Solution:
* Ensure access to the class is permitted, by having `@HostAccess.Export` on your class and/or the `Context.Builder.allowHostAccess()` set to a permissive setting. See [JavaDoc of org.graalvm.polyglot.Context](https://graalvm.org/truffle/javadoc/org/graalvm/polyglot/Context.html).

### TypeError: UnsupportedTypeException

```
TypeError: execute on JavaObject[Main$$Lambda$63/1898325501@1be2019a (Main$$Lambda$63/1898325501)] failed due to: UnsupportedTypeException
```
Expand Down Expand Up @@ -95,7 +145,6 @@ public class Minified {
```

### TypeError: Message not supported

```
TypeError: execute on JavaObject[Main$$Lambda$62/953082513@4c60d6e9 (Main$$Lambda$62/953082513)] failed due to: Message not supported.
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ This way, GraalVM JavaScript is executed on a traditional JVM and allows full Ja
#### Classpath
To load Java classes you need to have them on the Java classpath.
You can specify the classpath with the `--vm.classpath=<classpath>` option (or short: `--vm.cp=<classpath>`).

```
node --jvm --vm.cp=/my/class/path
js --jvm --vm.cp=/my/class/path

```
The method `Java.addToClasspath()` can be used to programmatically add to the classpath at runtime.

### Polyglot Context
Expand All @@ -40,12 +40,12 @@ Context context = Context.newBuilder("js").
context.eval("js", jsSourceCode);
```

See [graalvm.org](http://www.graalvm.org/docs/reference-manual/polyglot/) for more details.
See the [Polyglot Programming](https://www.graalvm.org/docs/reference-manual/polyglot-programming/) reference for more details.

### ScriptEngine (JSR 223)
The `org.graalvm.polyglot.Context` is the preferred execution method for interoperability with languages and tool of the GraalVM.
In addition, GraalVM JavaScript is fully compatible with JSR 223 and supports the `ScriptEngine API`.
Internally, the GraalVM JavaScript ScriptEngine wraps a [polyglot context instance](http://www.graalvm.org/docs/reference-manual/polyglot/).
Internally, the GraalVM JavaScript ScriptEngine wraps a polyglot context instance.

```java
ScriptEngine eng = new ScriptEngineManager().getEngineByName("graal.js");
Expand Down
4 changes: 3 additions & 1 deletion docs/user/JavaScriptCompatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ GraalVM JavaScript provides the following function objects in the global scope a
Array, ArrayBuffer, Boolean, DataView, Date, Error, Function, JSON, Map, Math, Number, Object, Promise, Proxy, Reflect, RegExp, Set, SharedArrayBuffer, String, Symbol, TypedArray, WeakMap, WeakSet

Additional objects are available under flags, for instance `Intl` (flag: `--js.intl-402`).
Run `js --help` or `js --help:languages` for the list of available flags.
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 spec is selected for execution.
For a list of methods provided, inspect the ECMAScript specification.
Expand Down Expand Up @@ -174,6 +174,8 @@ $ js --experimental-options --js.scripting=true

In scripting mode, several properties and functions are added to the global object, including [readFully](#readfile), [readLine](#readline), `$ARG`, `$ENV`, and `$EXEC`.

We provide migration guides for code previously targeted to the [Nashorn](https://github.com/graalvm/graaljs/blob/master/docs/user/NashornMigrationGuide.md) or [Rhino](https://github.com/graalvm/graaljs/blob/master/docs/user/RhinoMigrationGuide.md) engines.

## GraalVM JavaScript Extensions

### Graal
Expand Down
17 changes: 10 additions & 7 deletions docs/user/NashornMigrationGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
The the Nashorn engine has been deprecated in JDK 11 as part of [JEP 335](https://openjdk.java.net/jeps/335) and is scheduled to be removed from future JDK releases as part of [JEP 372](https://openjdk.java.net/jeps/372).
GraalVM JavaScript can step in as a replacement for code previously executed on the Nashorn engine.
It provides all the features previously provided by Nashorn, with many being available by default, some behind flags, some requiring minor modifications to your source code.
This document serves as migration guide for code previously targeted to the Nashorn engine.
See the [JavaInterop.md](JavaInterop.md) for an overview of supported Java interoperability features.

This guide serves as migration guide for code previously targeted to the Nashorn engine.
See the [Java Interoperability](JavaInteroperability.md) guide for an overview of supported Java interoperability features.

Both Nashorn and GraalVM JavaScript support a similar set of syntax and semantics for Java interoperability.
One notable difference is that GraalVM JavaScript takes a _secure by default_ approach, meaning some features need to be explicitly enabled that were available by default on Nashorn.
Expand All @@ -17,18 +18,20 @@ Nashorn features available by default (dependent on [security settings](#Secure-
* Java package globals: `Packages`, `java`, `javafx`, `javax`, `com`, `org`, `edu`

## Nashorn Compatibility Mode

GraalVM JavaScript provides a Nashorn compatibility mode.
Some of the functionality necessary for Nashorn compatibility is only available when the `js.nashorn-compat` option is enabled.
This is the case for Nashorn-specific extensions that GraalVM JavaScript does not want to expose by default.
Note that you have to enable [experimental options](Options.md#stable-and-experimental-options) to use this flag.
Further note that setting this flag defeats the [secure by default](#Secure-by-default) approach of GraalVM JavaScript in some cases, e.g. when operating on a legacy `ScriptEngine`.
Further note that setting this flag defeats the [secure by default](#Secure-by-default) approach of GraalVM JavaScript in some cases, e.g., when operating on a legacy `ScriptEngine`.

The `js.nashorn-compat` option can be set using a command line option:
The `js.nashorn-compat` option can be set:
1. by using a command line option:
```
$ js --experimental-options --js.nashorn-compat=true
```

Or using the polyglot API:
2. by using the polyglot API:
```java
import org.graalvm.polyglot.Context;

Expand All @@ -37,7 +40,7 @@ try (Context context = Context.newBuilder().allowExperimentalOptions(true).optio
}
```

Or using a system property when starting a Java application (remember to enable `allowExperimentalOptions` on the `Context.Builder` in your application as well):
3. by using a system property when starting a Java application (remember to enable `allowExperimentalOptions` on the `Context.Builder` in your application as well):
```
$ java -Dpolyglot.js.nashorn-compat=true MyApplication
```
Expand Down Expand Up @@ -221,4 +224,4 @@ GraalVM JavaScript provides a `print` builtin function compatible with Nashorn.

Note that GraalVM JavaScript also provides a `console.log` function.
This is an alias for `print` in pure JavaScript mode, but uses an implementation provided by Node.js when running in Node mode.
Behavior around Java objects differs for `console.log` in Node mode as Node.js does not implement special treatment for such objects.
The behaviour around Java objects differs for `console.log` in Node mode as Node.js does not implement special treatment for such objects.
11 changes: 5 additions & 6 deletions docs/user/NodeJSVSJavaScriptContext.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Differences Between Node.js and Java Embeddings

GraalVM's JavaScript engine is a fully-compliant ECMA2020 language runtime.
As such, it can run JavaScript code in a variety of embedding scenarios, including the Oracle [RDBMS](https://www.graalvm.org/docs/examples/mle-oracle/), any Java-based application, and Node.js.
As such, it can run JavaScript code in a variety of embedding scenarios, including the Oracle [RDBMS](https://www.graalvm.org/docs/examples/mle-oracle/), any Java-based application and Node.js.

Depending on the GraalVM's JavaScript embedding scenario, applications have access to different built-in capabilities.
For example, Node.js applications running on GraalVM's JavaScript engine have access to all of Node.js' APIs, including built-in Node.js' modules such as `'fs'`, `'http'`, etc.
Conversely, JavaScript code embedded in a Java application has access to limited capabilities, as specified through the [Context API](https://www.graalvm.org/docs/reference-manual/embed/), and do _not_ have access to Node.js' built-in modules.
Conversely, JavaScript code embedded in a Java application has access to limited capabilities, as specified through the [Context API](https://www.graalvm.org/docs/reference-manual/embed/), and do _not_ have access to Node.js built-in modules.

In this document we focus on the main differences between a Node.js application and a GraalVM JavaScript application embedded in Java.
This guide describes the main differences between a Node.js application and a GraalVM JavaScript application embedded in Java.

## Context Creation

Expand All @@ -32,7 +32,7 @@ The object is not available by default, and can be enabled in the following way:
```
Context.create("js").withHostInterop()
```
More details on the Java interoperability capabilities of GraalVM JavaScript are available in [docs/user/JavaInterop.md](https://github.com/graalvm/graaljs/blob/master/docs/user/JavaInterop.md).
More details on the Java interoperability capabilities of GraalVM JavaScript are available in the [Java Interoperability](https://github.com/graalvm/graaljs/blob/master/docs/user/JavaInteroperability.md) guide.

## Multithreading

Expand All @@ -56,8 +56,7 @@ This can be done in the following way:
1. In Node.js, the classpath can be modified using the `--jvm.cp` option.
2. In Java, the default Java's `-cp` option can be used.

More details on GraalVM command line options are available in [docs/user/Options.md](https://github.com/graalvm/graaljs/blob/master/docs/user/Options.md).

More details on GraalVM command line options are available in the [Options](https://github.com/graalvm/graaljs/blob/master/docs/user/Options.md) guide.

## JavaScript Modules

Expand Down
Empty file added docs/user/Operations.md
Empty file.
Loading

0 comments on commit e15acc9

Please sign in to comment.