Skip to content

Commit e86a638

Browse files
authored
src: add initial shadow realm support
Add initial shadow realm support behind an off-by-default flag `--experimental-shadow-realm`. PR-URL: #42869 Refs: #42528 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Darshan Sen <raisinten@gmail.com>
1 parent 3bd87e1 commit e86a638

11 files changed

+85
-1
lines changed

.eslintrc.js

+1
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ module.exports = {
337337
TextEncoderStream: 'readable',
338338
TransformStream: 'readable',
339339
TransformStreamDefaultController: 'readable',
340+
ShadowRealm: 'readable',
340341
SubtleCrypto: 'readable',
341342
WritableStream: 'readable',
342343
WritableStreamDefaultWriter: 'readable',

doc/api/cli.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -346,10 +346,18 @@ Disable experimental support for the [Fetch API][].
346346

347347
<!-- YAML
348348
added: v16.6.0
349-
-->
349+
-->
350350

351351
Use this flag to disable top-level await in REPL.
352352

353+
### `--experimental-shadow-realm`
354+
355+
<!-- YAML
356+
added: REPLACEME
357+
-->
358+
359+
Use this flag to enable [ShadowRealm][] support.
360+
353361
### `--experimental-specifier-resolution=mode`
354362

355363
<!-- YAML
@@ -1622,6 +1630,7 @@ Node.js options that are allowed are:
16221630
* `--experimental-modules`
16231631
* `--experimental-network-imports`
16241632
* `--experimental-policy`
1633+
* `--experimental-shadow-realm`
16251634
* `--experimental-specifier-resolution`
16261635
* `--experimental-top-level-await`
16271636
* `--experimental-vm-modules`
@@ -2017,6 +2026,7 @@ $ node --max-old-space-size=1536 index.js
20172026
[OSSL_PROVIDER-legacy]: https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-legacy.html
20182027
[REPL]: repl.md
20192028
[ScriptCoverage]: https://chromedevtools.github.io/devtools-protocol/tot/Profiler#type-ScriptCoverage
2029+
[ShadowRealm]: https://github.com/tc39/proposal-shadowrealm
20202030
[Source Map]: https://sourcemaps.info/spec.html
20212031
[Subresource Integrity]: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
20222032
[V8 JavaScript code coverage]: https://v8project.blogspot.com/2017/12/javascript-code-coverage.html

doc/node.1

+3
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ Enable experimental support for loading modules using `import` over `https:`.
156156
.It Fl -experimental-policy
157157
Use the specified file as a security policy.
158158
.
159+
.It Fl -experimental-shadow-realm
160+
Use this flag to enable ShadowRealm support.
161+
.
159162
.It Fl -no-experimental-fetch
160163
Disable experimental support for the Fetch API.
161164
.

lib/.eslintrc.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ rules:
8787
message: Use `const { Request } = require('internal/deps/undici/undici');` instead of the global.
8888
- name: Response
8989
message: Use `const { Response } = require('internal/deps/undici/undici');` instead of the global.
90+
# ShadowRealm is not available in primordials because it can be
91+
# disabled with --no-harmony-shadow-realm CLI flag.
92+
- name: ShadowRealm
93+
message: Use `const { ShadowRealm } = globalThis;` instead of the global.
9094
# SharedArrayBuffer is not available in primordials because it can be
9195
# disabled with --no-harmony-sharedarraybuffer CLI flag.
9296
- name: SharedArrayBuffer

node.gyp

+2
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@
531531
'src/node_report_module.cc',
532532
'src/node_report_utils.cc',
533533
'src/node_serdes.cc',
534+
'src/node_shadow_realm.cc',
534535
'src/node_snapshotable.cc',
535536
'src/node_sockaddr.cc',
536537
'src/node_stat_watcher.cc',
@@ -637,6 +638,7 @@
637638
'src/node_report.h',
638639
'src/node_revert.h',
639640
'src/node_root_certs.h',
641+
'src/node_shadow_realm.h',
640642
'src/node_snapshotable.h',
641643
'src/node_snapshot_builder.h',
642644
'src/node_sockaddr.h',

src/api/environment.cc

+7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "node_native_module_env.h"
66
#include "node_options-inl.h"
77
#include "node_platform.h"
8+
#include "node_shadow_realm.h"
89
#include "node_v8_platform-inl.h"
910
#include "node_wasm_web_api.h"
1011
#include "uv.h"
@@ -261,6 +262,12 @@ void SetIsolateMiscHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
261262
isolate->SetWasmStreamingCallback(wasm_web_api::StartStreamingCompilation);
262263
}
263264

265+
if (per_process::cli_options->get_per_isolate_options()
266+
->experimental_shadow_realm) {
267+
isolate->SetHostCreateShadowRealmContextCallback(
268+
shadow_realm::HostCreateShadowRealmContextCallback);
269+
}
270+
264271
if ((s.flags & SHOULD_NOT_SET_PROMISE_REJECTION_CALLBACK) == 0) {
265272
auto* promise_reject_cb = s.promise_reject_callback ?
266273
s.promise_reject_callback : PromiseRejectCallback;

src/node_options.cc

+9
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,15 @@ PerIsolateOptionsParser::PerIsolateOptionsParser(
703703
AddOption(
704704
"--experimental-top-level-await", "", NoOp{}, kAllowedInEnvironment);
705705

706+
AddOption("--experimental-shadow-realm",
707+
"",
708+
&PerIsolateOptions::experimental_shadow_realm,
709+
kAllowedInEnvironment);
710+
AddOption("--harmony-shadow-realm", "", V8Option{});
711+
Implies("--experimental-shadow-realm", "--harmony-shadow-realm");
712+
Implies("--harmony-shadow-realm", "--experimental-shadow-realm");
713+
ImpliesNot("--no-harmony-shadow-realm", "--experimental-shadow-realm");
714+
706715
Insert(eop, &PerIsolateOptions::get_per_env_options);
707716
}
708717

src/node_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ class PerIsolateOptions : public Options {
205205
bool track_heap_objects = false;
206206
bool report_uncaught_exception = false;
207207
bool report_on_signal = false;
208+
bool experimental_shadow_realm = false;
208209
std::string report_signal = "SIGUSR2";
209210
inline EnvironmentOptions* get_per_env_options();
210211
void CheckOptions(std::vector<std::string>* errors) override;

src/node_shadow_realm.cc

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include "node_shadow_realm.h"
2+
3+
namespace node {
4+
namespace shadow_realm {
5+
using v8::Context;
6+
using v8::Local;
7+
using v8::MaybeLocal;
8+
9+
// static
10+
MaybeLocal<Context> HostCreateShadowRealmContextCallback(
11+
Local<Context> initiator_context) {
12+
return Context::New(initiator_context->GetIsolate());
13+
}
14+
15+
} // namespace shadow_realm
16+
} // namespace node

src/node_shadow_realm.h

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef SRC_NODE_SHADOW_REALM_H_
2+
#define SRC_NODE_SHADOW_REALM_H_
3+
4+
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5+
6+
#include "v8.h"
7+
8+
namespace node {
9+
namespace shadow_realm {
10+
11+
v8::MaybeLocal<v8::Context> HostCreateShadowRealmContextCallback(
12+
v8::Local<v8::Context> initiator_context);
13+
14+
} // namespace shadow_realm
15+
} // namespace node
16+
17+
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
18+
19+
#endif // SRC_NODE_SHADOW_REALM_H_

test/parallel/test-shadow-realm.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Flags: --experimental-shadow-realm
2+
'use strict';
3+
4+
require('../common');
5+
const assert = require('assert');
6+
7+
// Validates we can construct ShadowRealm successfully.
8+
const shadowRealm = new ShadowRealm();
9+
10+
const getter = shadowRealm.evaluate('globalThis.realmValue = "inner"; () => globalThis.realmValue;');
11+
assert.strictEqual(getter(), 'inner');
12+
assert.strictEqual('realmValue' in globalThis, false);

0 commit comments

Comments
 (0)