diff options
author | legendecas <legendecas@gmail.com> | 2022-05-02 19:46:31 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-02 19:46:31 +0300 |
commit | e86a6383054623e5168384a83d8cd6ebfe1fb584 (patch) | |
tree | 1953d373d3f24e9b5c6f2e84217328ff213289b6 | |
parent | 3bd87e1782b45fec6df7809823fdf16ec07bc4a7 (diff) |
src: add initial shadow realm support
Add initial shadow realm support behind an off-by-default flag
`--experimental-shadow-realm`.
PR-URL: https://github.com/nodejs/node/pull/42869
Refs: https://github.com/nodejs/node/issues/42528
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
-rw-r--r-- | .eslintrc.js | 1 | ||||
-rw-r--r-- | doc/api/cli.md | 12 | ||||
-rw-r--r-- | doc/node.1 | 3 | ||||
-rw-r--r-- | lib/.eslintrc.yaml | 4 | ||||
-rw-r--r-- | node.gyp | 2 | ||||
-rw-r--r-- | src/api/environment.cc | 7 | ||||
-rw-r--r-- | src/node_options.cc | 9 | ||||
-rw-r--r-- | src/node_options.h | 1 | ||||
-rw-r--r-- | src/node_shadow_realm.cc | 16 | ||||
-rw-r--r-- | src/node_shadow_realm.h | 19 | ||||
-rw-r--r-- | test/parallel/test-shadow-realm.js | 12 |
11 files changed, 85 insertions, 1 deletions
diff --git a/.eslintrc.js b/.eslintrc.js index ea69a2893ff..167107a0018 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -337,6 +337,7 @@ module.exports = { TextEncoderStream: 'readable', TransformStream: 'readable', TransformStreamDefaultController: 'readable', + ShadowRealm: 'readable', SubtleCrypto: 'readable', WritableStream: 'readable', WritableStreamDefaultWriter: 'readable', diff --git a/doc/api/cli.md b/doc/api/cli.md index 44ba09624b0..5bb0c3cf33d 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -346,10 +346,18 @@ Disable experimental support for the [Fetch API][]. <!-- YAML added: v16.6.0 - --> +--> Use this flag to disable top-level await in REPL. +### `--experimental-shadow-realm` + +<!-- YAML +added: REPLACEME +--> + +Use this flag to enable [ShadowRealm][] support. + ### `--experimental-specifier-resolution=mode` <!-- YAML @@ -1622,6 +1630,7 @@ Node.js options that are allowed are: * `--experimental-modules` * `--experimental-network-imports` * `--experimental-policy` +* `--experimental-shadow-realm` * `--experimental-specifier-resolution` * `--experimental-top-level-await` * `--experimental-vm-modules` @@ -2017,6 +2026,7 @@ $ node --max-old-space-size=1536 index.js [OSSL_PROVIDER-legacy]: https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-legacy.html [REPL]: repl.md [ScriptCoverage]: https://chromedevtools.github.io/devtools-protocol/tot/Profiler#type-ScriptCoverage +[ShadowRealm]: https://github.com/tc39/proposal-shadowrealm [Source Map]: https://sourcemaps.info/spec.html [Subresource Integrity]: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity [V8 JavaScript code coverage]: https://v8project.blogspot.com/2017/12/javascript-code-coverage.html diff --git a/doc/node.1 b/doc/node.1 index 2003bc8ca79..6ac0d675834 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -156,6 +156,9 @@ Enable experimental support for loading modules using `import` over `https:`. .It Fl -experimental-policy Use the specified file as a security policy. . +.It Fl -experimental-shadow-realm +Use this flag to enable ShadowRealm support. +. .It Fl -no-experimental-fetch Disable experimental support for the Fetch API. . diff --git a/lib/.eslintrc.yaml b/lib/.eslintrc.yaml index c1635e4cf08..6bfc102b817 100644 --- a/lib/.eslintrc.yaml +++ b/lib/.eslintrc.yaml @@ -87,6 +87,10 @@ rules: message: Use `const { Request } = require('internal/deps/undici/undici');` instead of the global. - name: Response message: Use `const { Response } = require('internal/deps/undici/undici');` instead of the global. + # ShadowRealm is not available in primordials because it can be + # disabled with --no-harmony-shadow-realm CLI flag. + - name: ShadowRealm + message: Use `const { ShadowRealm } = globalThis;` instead of the global. # SharedArrayBuffer is not available in primordials because it can be # disabled with --no-harmony-sharedarraybuffer CLI flag. - name: SharedArrayBuffer @@ -531,6 +531,7 @@ 'src/node_report_module.cc', 'src/node_report_utils.cc', 'src/node_serdes.cc', + 'src/node_shadow_realm.cc', 'src/node_snapshotable.cc', 'src/node_sockaddr.cc', 'src/node_stat_watcher.cc', @@ -637,6 +638,7 @@ 'src/node_report.h', 'src/node_revert.h', 'src/node_root_certs.h', + 'src/node_shadow_realm.h', 'src/node_snapshotable.h', 'src/node_snapshot_builder.h', 'src/node_sockaddr.h', diff --git a/src/api/environment.cc b/src/api/environment.cc index f3a8f49812d..ccdcdefb20f 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -5,6 +5,7 @@ #include "node_native_module_env.h" #include "node_options-inl.h" #include "node_platform.h" +#include "node_shadow_realm.h" #include "node_v8_platform-inl.h" #include "node_wasm_web_api.h" #include "uv.h" @@ -261,6 +262,12 @@ void SetIsolateMiscHandlers(v8::Isolate* isolate, const IsolateSettings& s) { isolate->SetWasmStreamingCallback(wasm_web_api::StartStreamingCompilation); } + if (per_process::cli_options->get_per_isolate_options() + ->experimental_shadow_realm) { + isolate->SetHostCreateShadowRealmContextCallback( + shadow_realm::HostCreateShadowRealmContextCallback); + } + if ((s.flags & SHOULD_NOT_SET_PROMISE_REJECTION_CALLBACK) == 0) { auto* promise_reject_cb = s.promise_reject_callback ? s.promise_reject_callback : PromiseRejectCallback; diff --git a/src/node_options.cc b/src/node_options.cc index 8341724089a..f7551248f7d 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -703,6 +703,15 @@ PerIsolateOptionsParser::PerIsolateOptionsParser( AddOption( "--experimental-top-level-await", "", NoOp{}, kAllowedInEnvironment); + AddOption("--experimental-shadow-realm", + "", + &PerIsolateOptions::experimental_shadow_realm, + kAllowedInEnvironment); + AddOption("--harmony-shadow-realm", "", V8Option{}); + Implies("--experimental-shadow-realm", "--harmony-shadow-realm"); + Implies("--harmony-shadow-realm", "--experimental-shadow-realm"); + ImpliesNot("--no-harmony-shadow-realm", "--experimental-shadow-realm"); + Insert(eop, &PerIsolateOptions::get_per_env_options); } diff --git a/src/node_options.h b/src/node_options.h index a3937900b41..a5af1684d38 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -205,6 +205,7 @@ class PerIsolateOptions : public Options { bool track_heap_objects = false; bool report_uncaught_exception = false; bool report_on_signal = false; + bool experimental_shadow_realm = false; std::string report_signal = "SIGUSR2"; inline EnvironmentOptions* get_per_env_options(); void CheckOptions(std::vector<std::string>* errors) override; diff --git a/src/node_shadow_realm.cc b/src/node_shadow_realm.cc new file mode 100644 index 00000000000..2ccd62edc31 --- /dev/null +++ b/src/node_shadow_realm.cc @@ -0,0 +1,16 @@ +#include "node_shadow_realm.h" + +namespace node { +namespace shadow_realm { +using v8::Context; +using v8::Local; +using v8::MaybeLocal; + +// static +MaybeLocal<Context> HostCreateShadowRealmContextCallback( + Local<Context> initiator_context) { + return Context::New(initiator_context->GetIsolate()); +} + +} // namespace shadow_realm +} // namespace node diff --git a/src/node_shadow_realm.h b/src/node_shadow_realm.h new file mode 100644 index 00000000000..a10fc425661 --- /dev/null +++ b/src/node_shadow_realm.h @@ -0,0 +1,19 @@ +#ifndef SRC_NODE_SHADOW_REALM_H_ +#define SRC_NODE_SHADOW_REALM_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "v8.h" + +namespace node { +namespace shadow_realm { + +v8::MaybeLocal<v8::Context> HostCreateShadowRealmContextCallback( + v8::Local<v8::Context> initiator_context); + +} // namespace shadow_realm +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_NODE_SHADOW_REALM_H_ diff --git a/test/parallel/test-shadow-realm.js b/test/parallel/test-shadow-realm.js new file mode 100644 index 00000000000..0b20265537f --- /dev/null +++ b/test/parallel/test-shadow-realm.js @@ -0,0 +1,12 @@ +// Flags: --experimental-shadow-realm +'use strict'; + +require('../common'); +const assert = require('assert'); + +// Validates we can construct ShadowRealm successfully. +const shadowRealm = new ShadowRealm(); + +const getter = shadowRealm.evaluate('globalThis.realmValue = "inner"; () => globalThis.realmValue;'); +assert.strictEqual(getter(), 'inner'); +assert.strictEqual('realmValue' in globalThis, false); |