Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: add initial shadow realm support #42869

Merged
merged 1 commit into from May 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Expand Up @@ -337,6 +337,7 @@ module.exports = {
TextEncoderStream: 'readable',
TransformStream: 'readable',
TransformStreamDefaultController: 'readable',
ShadowRealm: 'readable',
SubtleCrypto: 'readable',
WritableStream: 'readable',
WritableStreamDefaultWriter: 'readable',
Expand Down
12 changes: 11 additions & 1 deletion doc/api/cli.md
Expand Up @@ -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`
RaisinTen marked this conversation as resolved.
Show resolved Hide resolved

<!-- YAML
added: REPLACEME
-->

Use this flag to enable [ShadowRealm][] support.

### `--experimental-specifier-resolution=mode`

<!-- YAML
Expand Down Expand Up @@ -1622,6 +1630,7 @@ Node.js options that are allowed are:
* `--experimental-modules`
* `--experimental-network-imports`
* `--experimental-policy`
* `--experimental-shadow-realm`
legendecas marked this conversation as resolved.
Show resolved Hide resolved
* `--experimental-specifier-resolution`
* `--experimental-top-level-await`
* `--experimental-vm-modules`
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions doc/node.1
Expand Up @@ -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.
.
Expand Down
4 changes: 4 additions & 0 deletions lib/.eslintrc.yaml
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions node.gyp
Expand Up @@ -531,6 +531,7 @@
'src/node_report_module.cc',
'src/node_report_utils.cc',
'src/node_serdes.cc',
'src/node_shadow_realm.cc',
legendecas marked this conversation as resolved.
Show resolved Hide resolved
'src/node_snapshotable.cc',
'src/node_sockaddr.cc',
'src/node_stat_watcher.cc',
Expand Down Expand Up @@ -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',
Expand Down
7 changes: 7 additions & 0 deletions src/api/environment.cc
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions src/node_options.cc
Expand Up @@ -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);
}

Expand Down
1 change: 1 addition & 0 deletions src/node_options.h
Expand Up @@ -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;
Expand Down
16 changes: 16 additions & 0 deletions 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
19 changes: 19 additions & 0 deletions 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_
12 changes: 12 additions & 0 deletions 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);