Skip to content

Commit e1e63e3

Browse files
committed
module: bootstrap module loaders in shadow realm
1 parent 59a6ca5 commit e1e63e3

26 files changed

+476
-168
lines changed

lib/internal/bootstrap/realm.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,8 @@ const internalBuiltinIds = builtinIds
215215
.filter((id) => StringPrototypeStartsWith(id, 'internal/') && id !== selfId);
216216

217217
// When --expose-internals is on we'll add the internal builtin ids to these.
218-
const canBeRequiredByUsersList = new SafeSet(publicBuiltinIds);
219-
const canBeRequiredByUsersWithoutSchemeList =
218+
let canBeRequiredByUsersList = new SafeSet(publicBuiltinIds);
219+
let canBeRequiredByUsersWithoutSchemeList =
220220
new SafeSet(publicBuiltinIds.filter((id) => !schemelessBlockList.has(id)));
221221

222222
/**
@@ -269,6 +269,12 @@ class BuiltinModule {
269269
}
270270
}
271271

272+
static setRealmAllowRequireByUsers(ids) {
273+
canBeRequiredByUsersList = new SafeSet(ids.filter((id) => publicBuiltinIds.includes(id)));
274+
canBeRequiredByUsersWithoutSchemeList =
275+
new SafeSet(ids.filter((id) => !schemelessBlockList.has(id)));
276+
}
277+
272278
// To be called during pre-execution when --expose-internals is on.
273279
// Enables the user-land module loader to access internal modules.
274280
static exposeInternals() {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
'use strict';
2+
3+
// In ShadowRealm.
4+
5+
const {
6+
prepareShadowRealmExecution,
7+
} = require('internal/process/pre_execution');
8+
const {
9+
BuiltinModule,
10+
} = require('internal/bootstrap/realm');
11+
const { setDefaultImportModuleDynamically } = require('internal/modules/esm/utils');
12+
13+
BuiltinModule.setRealmAllowRequireByUsers([
14+
'assert',
15+
'assert/strict',
16+
'buffer',
17+
'console',
18+
'constants',
19+
'cypto',
20+
'diagnostics_channel',
21+
'events',
22+
'module',
23+
'path',
24+
'path/posix',
25+
'path/win32',
26+
'readline',
27+
'readline/promises',
28+
'repl',
29+
'stream',
30+
'stream/consumers',
31+
'stream/promises',
32+
'stream/web',
33+
'string_decoder',
34+
'url',
35+
'util',
36+
'util/types',
37+
'zlib',
38+
]);
39+
40+
prepareShadowRealmExecution();
41+
42+
// The handler for `ShadowRealm.prototype.importValue`.
43+
setDefaultImportModuleDynamically((specifier, assertions) => {
44+
const { esmLoader } = require('internal/process/esm_loader');
45+
// `parentUrl` is not set in the case of a ShadowRealm top-level import.
46+
return esmLoader.import(specifier, undefined, assertions);
47+
});

lib/internal/main/worker_thread.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,10 @@ port.on('message', (message) => {
136136
const isLoaderWorker =
137137
doEval === 'internal' &&
138138
filename === require('internal/modules/esm/utils').loaderWorkerId;
139-
setupUserModules(isLoaderWorker);
139+
setupUserModules({
140+
__proto__: null,
141+
isLoaderWorker,
142+
});
140143

141144
if (!hasStdin)
142145
process.stdin.push(null);

lib/internal/modules/esm/utils.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ const {
2626
} = internalBinding('module_wrap');
2727
const assert = require('internal/assert');
2828

29+
let defaultImportModuleDynamically;
30+
function setDefaultImportModuleDynamically(importModuleDynamically) {
31+
defaultImportModuleDynamically = importModuleDynamically;
32+
}
33+
2934
let defaultConditions;
3035
function getDefaultConditions() {
3136
assert(defaultConditions !== undefined);
@@ -139,6 +144,9 @@ async function importModuleDynamicallyCallback(symbol, specifier, assertions) {
139144
return importModuleDynamically(specifier, callbackReferrer, assertions);
140145
}
141146
}
147+
if (defaultImportModuleDynamically) {
148+
return defaultImportModuleDynamically(specifier, assertions);
149+
}
142150
throw new ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING();
143151
}
144152

@@ -220,6 +228,7 @@ async function initializeHooks() {
220228

221229
module.exports = {
222230
registerModule,
231+
setDefaultImportModuleDynamically,
223232
initializeESM,
224233
initializeHooks,
225234
getDefaultConditions,

lib/internal/process/pre_execution.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const {
2525
exposeLazyInterfaces,
2626
defineReplaceableLazyAttribute,
2727
setupCoverageHooks,
28+
kEmptyObject,
2829
} = require('internal/util');
2930

3031
const {
@@ -57,6 +58,18 @@ function prepareWorkerThreadExecution() {
5758
});
5859
}
5960

61+
function prepareShadowRealmExecution() {
62+
// Patch the process object with legacy properties and normalizations
63+
// Do not expand argv1 as it is not available in ShadowRealm
64+
patchProcessObject(false);
65+
setupDebugEnv();
66+
67+
setupUserModules({
68+
__proto__: null,
69+
noPreloadModules: true,
70+
});
71+
}
72+
6073
function prepareExecution(options) {
6174
const { expandArgv1, initializeModules, isMainThread } = options;
6275

@@ -132,12 +145,15 @@ function setupSymbolDisposePolyfill() {
132145
Symbol.asyncDispose ??= SymbolAsyncDispose;
133146
}
134147

135-
function setupUserModules(isLoaderWorker = false) {
148+
function setupUserModules(options = kEmptyObject) {
149+
const { isLoaderWorker = false, noPreloadModules = false } = options;
136150
initializeCJSLoader();
137151
initializeESMLoader(isLoaderWorker);
138152
const CJSLoader = require('internal/modules/cjs/loader');
139153
assert(!CJSLoader.hasLoadedAnyUserCJSModule);
140-
loadPreloadModules();
154+
if (!noPreloadModules) {
155+
loadPreloadModules();
156+
}
141157
// Need to be done after --require setup.
142158
initializeFrozenIntrinsics();
143159
}
@@ -666,5 +682,6 @@ module.exports = {
666682
setupUserModules,
667683
prepareMainThreadExecution,
668684
prepareWorkerThreadExecution,
685+
prepareShadowRealmExecution,
669686
markBootstrapComplete,
670687
};

src/async_wrap.cc

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ void AsyncWrap::CreatePerContextProperties(Local<Object> target,
373373
Local<Context> context,
374374
void* priv) {
375375
Environment* env = Environment::GetCurrent(context);
376+
Realm* realm = Realm::GetCurrent(context);
376377
Isolate* isolate = env->isolate();
377378
HandleScope scope(isolate);
378379

@@ -446,13 +447,13 @@ void AsyncWrap::CreatePerContextProperties(Local<Object> target,
446447

447448
#undef FORCE_SET_TARGET_FIELD
448449

449-
env->set_async_hooks_init_function(Local<Function>());
450-
env->set_async_hooks_before_function(Local<Function>());
451-
env->set_async_hooks_after_function(Local<Function>());
452-
env->set_async_hooks_destroy_function(Local<Function>());
453-
env->set_async_hooks_promise_resolve_function(Local<Function>());
454-
env->set_async_hooks_callback_trampoline(Local<Function>());
455-
env->set_async_hooks_binding(target);
450+
realm->set_async_hooks_init_function(Local<Function>());
451+
realm->set_async_hooks_before_function(Local<Function>());
452+
realm->set_async_hooks_after_function(Local<Function>());
453+
realm->set_async_hooks_destroy_function(Local<Function>());
454+
realm->set_async_hooks_promise_resolve_function(Local<Function>());
455+
realm->set_async_hooks_callback_trampoline(Local<Function>());
456+
realm->set_async_hooks_binding(target);
456457
}
457458

458459
void AsyncWrap::RegisterExternalReferences(

src/env-inl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ inline AliasedFloat64Array& AsyncHooks::async_ids_stack() {
9999
}
100100

101101
v8::Local<v8::Array> AsyncHooks::js_execution_async_resources() {
102+
DCHECK_EQ(env()->isolate()->GetCurrentContext(),
103+
env()->principal_realm()->context());
102104
if (UNLIKELY(js_execution_async_resources_.IsEmpty())) {
103105
js_execution_async_resources_.Reset(
104106
env()->isolate(), v8::Array::New(env()->isolate()));

src/env.cc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,7 @@ void IsolateData::CreateProperties() {
497497
binding::CreateInternalBindingTemplates(this);
498498

499499
contextify::ContextifyContext::InitializeGlobalTemplates(this);
500+
CreateEnvProxyTemplate(this);
500501
}
501502

502503
IsolateData::IsolateData(Isolate* isolate,
@@ -1587,10 +1588,13 @@ void AsyncHooks::MemoryInfo(MemoryTracker* tracker) const {
15871588
void AsyncHooks::grow_async_ids_stack() {
15881589
async_ids_stack_.reserve(async_ids_stack_.Length() * 3);
15891590

1590-
env()->async_hooks_binding()->Set(
1591-
env()->context(),
1592-
env()->async_ids_stack_string(),
1593-
async_ids_stack_.GetJSArray()).Check();
1591+
env()
1592+
->principal_realm()
1593+
->async_hooks_binding()
1594+
->Set(env()->context(),
1595+
env()->async_ids_stack_string(),
1596+
async_ids_stack_.GetJSArray())
1597+
.Check();
15941598
}
15951599

15961600
void AsyncHooks::FailWithCorruptedAsyncStack(double expected_async_id) {

0 commit comments

Comments
 (0)