Skip to content

Commit e69e1fa

Browse files
committed
[GR-51016] Enable WebAssembly by default in Node.js.
PullRequest: js/3013
2 parents f3e8888 + 9d0b063 commit e69e1fa

File tree

4 files changed

+55
-23
lines changed

4 files changed

+55
-23
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ See [release calendar](https://www.graalvm.org/release-calendar/) for release da
1212
* Implemented the [Well-Formed Unicode Strings](https://github.com/tc39/proposal-is-usv-string) proposal. It is available in ECMAScript staging mode (`--js.ecmascript-version=staging`).
1313
* Implemented the [JSON.parse source text access](https://github.com/tc39/proposal-json-parse-with-source) proposal. It is available in ECMAScript staging mode (`--js.ecmascript-version=staging`).
1414
* Updated Node.js to version 18.18.2.
15+
* WebAssembly support in Node.js has been enabled by default. It can be disabled using the experimental option `--js.webassembly=false`.
1516
* `--js.import-assertions` option has been replaced by `--js.import-attributes` option because [the corresponding proposal](https://github.com/tc39/proposal-import-attributes) has migrated from the usage of assertions to the usage of attributes.
1617

1718
## Version 23.1.0

graal-nodejs/mx.graal-nodejs/com.oracle.truffle.trufflenode/src/com/oracle/truffle/trufflenode/Options.java

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,11 @@
4040
*/
4141
package com.oracle.truffle.trufflenode;
4242

43+
import java.io.OutputStream;
4344
import java.net.URL;
4445
import java.net.URLClassLoader;
4546
import java.nio.file.Path;
4647
import java.util.ArrayList;
47-
import java.util.Arrays;
48-
import java.util.HashSet;
4948
import java.util.List;
5049
import java.util.Map;
5150
import java.util.Optional;
@@ -119,20 +118,22 @@ public static class OptionsParser extends AbstractLanguageLauncher implements Fu
119118
private static final String INSPECT = "inspect";
120119
private static final String INSPECT_SUSPEND = "inspect.Suspend";
121120
private static final String INSPECT_WAIT_ATTACHED = "inspect.WaitAttached";
121+
private static final String WASM_LANGUAGE_ID = "wasm";
122122

123123
private Context.Builder contextBuilder;
124124
private boolean exposeGC;
125125
private boolean polyglot;
126126
private boolean unsafeWasmMemory;
127127
private boolean auxEngineCacheMode;
128+
private boolean wasmEnabled;
128129

129-
private static final Set<String> AUX_CACHE_OPTIONS = new HashSet<>(Arrays.asList("engine.Cache",
130+
private static final Set<String> AUX_CACHE_OPTIONS = Set.of("engine.Cache",
130131
"engine.CacheLoad",
131-
"engine.CacheStore"));
132+
"engine.CacheStore");
132133

133134
// Options that should not be passed to polyglot engine (they are processed
134135
// elsewhere or can be ignored without almost any harm).
135-
private static final Set<String> IGNORED_OPTIONS = new HashSet<>(Arrays.asList(new String[]{
136+
private static final Set<String> IGNORED_OPTIONS = Set.of(new String[]{
136137
"debug-code",
137138
"es-staging",
138139
"experimental-modules",
@@ -158,7 +159,7 @@ public static class OptionsParser extends AbstractLanguageLauncher implements Fu
158159
"nouse-idle-notification",
159160
"stack-size",
160161
"use-idle-notification"
161-
}));
162+
});
162163

163164
@Override
164165
public Object[] apply(String[] args) {
@@ -189,7 +190,7 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
189190
polyglotOptions.put("js.string-length-limit", Integer.toString((1 << 29) - 24)); // v8::String::kMaxLength
190191

191192
List<String> unprocessedArguments = new ArrayList<>();
192-
boolean optWebAssembly = false;
193+
Boolean optWebAssembly = null;
193194
Boolean optUnsafeWasmMemory = null;
194195
for (String arg : arguments) {
195196
String key = "";
@@ -298,10 +299,18 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
298299
}
299300
unprocessedArguments.add(arg);
300301
}
301-
if (optWebAssembly) {
302-
if (optUnsafeWasmMemory == null && polyglot && isLanguageAvailable("wasm")) {
303-
optUnsafeWasmMemory = Boolean.TRUE;
304-
polyglotOptions.put("wasm.UseUnsafeMemory", "true");
302+
if (optWebAssembly != Boolean.FALSE) {
303+
// WebAssembly is enabled by default, if available.
304+
if (isWasmAvailable()) {
305+
wasmEnabled = true;
306+
if (optWebAssembly == null) {
307+
optWebAssembly = Boolean.TRUE;
308+
polyglotOptions.put("js.webassembly", "true");
309+
}
310+
if (optWebAssembly && optUnsafeWasmMemory == null) {
311+
optUnsafeWasmMemory = Boolean.TRUE;
312+
polyglotOptions.put("wasm.UseUnsafeMemory", "true");
313+
}
305314
}
306315
if (optUnsafeWasmMemory == Boolean.TRUE) {
307316
unsafeWasmMemory = true;
@@ -339,14 +348,15 @@ protected void printHelp(OptionCategory maxCategory) {
339348
System.out.println();
340349
System.out.println("Usage: node [options] [ -e script | script.js ] [arguments]\n");
341350
System.out.println("Basic Options:");
342-
printOption("-v, --version", "print version");
343-
printOption("-e, --eval script", "evaluate script");
344-
printOption("-p, --print", "evaluate script and print result");
351+
printOption("-v, --version", "print Node.js version");
352+
printOption("-e, --eval=...", "evaluate script");
353+
printOption("-p, --print [...]", "evaluate script and print result");
345354
printOption("-c, --check", "syntax check script without executing");
346355
printOption("-i, --interactive", "always enter the REPL even if stdin does not appear to be a terminal");
347-
printOption("-r, --require", "module to preload (option can be repeated)");
356+
printOption("-r, --require=...", "CommonJS module to preload (option can be repeated)");
348357
printOption("--inspect[=port]", "activate inspector on port (overrides options of Chrome Inspector)");
349358
printOption("--inspect-brk[=port]", "activate inspector on port and break at start of user script (overrides options of Chrome Inspector)");
359+
// @formatter:on
350360
}
351361

352362
private static void printOption(String option, String description) {
@@ -362,11 +372,26 @@ private static void printOption(String option, String description) {
362372

363373
@Override
364374
protected String[] getDefaultLanguages() {
365-
return polyglot ? new String[0] : super.getDefaultLanguages();
375+
if (polyglot) {
376+
return new String[0];
377+
} else if (wasmEnabled) {
378+
assert isWasmAvailable() : "wasm not available";
379+
return new String[]{getLanguageId(), WASM_LANGUAGE_ID};
380+
} else {
381+
return super.getDefaultLanguages();
382+
}
383+
}
384+
385+
private static boolean isWasmAvailable() {
386+
return isLanguageAvailable(WASM_LANGUAGE_ID);
366387
}
367388

368-
static boolean isLanguageAvailable(String languageId) {
369-
try (Engine tempEngine = Engine.newBuilder().useSystemProperties(false).build()) {
389+
private static boolean isLanguageAvailable(String languageId) {
390+
try (Engine tempEngine = Engine.newBuilder().useSystemProperties(false).//
391+
out(OutputStream.nullOutputStream()).//
392+
err(OutputStream.nullOutputStream()).//
393+
option("engine.WarnInterpreterOnly", "false").//
394+
build()) {
370395
return tempEngine.getLanguages().containsKey(languageId);
371396
}
372397
}

graal-nodejs/mx.graal-nodejs/mx_graal_nodejs.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,6 @@ def _graal_nodejs_post_gate_runner(args, tasks):
7171
npm(['--scripts-prepend-node-path=auto', 'test'] + commonArgs + testArgs, cwd=unitTestDir)
7272
if mx.suite('wasm', fatalIfMissing=False):
7373
npm(['--scripts-prepend-node-path=auto', 'run', 'testwasm'] + commonArgs + testArgs, cwd=unitTestDir)
74-
# test that WebAssembly can be enabled using env. variables
75-
_setEnvVar('NODE_OPTIONS', '--polyglot')
76-
_setEnvVar('NODE_POLYGLOT_OPTIONS', '--js.webassembly --experimental-options')
7774
node(commonArgs + ['-e', 'console.log(WebAssembly)'])
7875
# check that fetch API is available when WebAssembly is available
7976
node(commonArgs + ['-e', 'FormData'])
@@ -88,8 +85,17 @@ def _graal_nodejs_post_gate_runner(args, tasks):
8885
]
8986
for test in wasm_tests:
9087
node(commonArgs + [join(_suite.dir, 'test', 'parallel', test)])
91-
_setEnvVar('NODE_OPTIONS', '')
88+
89+
# test that WebAssembly can be disabled using env. variables
90+
_setEnvVar('NODE_POLYGLOT_OPTIONS', '--js.webassembly=false --experimental-options')
91+
out = mx.OutputCapture()
92+
node(commonArgs + ['-p', 'try { WebAssembly; } catch (e) { e.toString(); }'], out=out)
93+
assert out.data.strip() == "ReferenceError: WebAssembly is not defined", out.data
9294
_setEnvVar('NODE_POLYGLOT_OPTIONS', '')
95+
else:
96+
out = mx.OutputCapture()
97+
node(commonArgs + ['-p', 'try { WebAssembly; } catch (e) { e.toString(); }'], out=out)
98+
assert out.data.strip() == "ReferenceError: WebAssembly is not defined", out.data
9399

94100
mx_gate.make_test_report(jsonResultsFile, task=t.title)
95101
finally:

graal-nodejs/test/graal/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
"scripts": {
1111
"install": "node-gyp rebuild",
1212
"test": "node --expose-gc index.js",
13-
"testwasm": "node --experimental-options --polyglot --js.webassembly=true --expose-gc index.js"
13+
"testwasm": "node --experimental-options --js.webassembly=true --expose-gc index.js"
1414
}
1515
}

0 commit comments

Comments
 (0)