Skip to content

Commit f1f3986

Browse files
committedAug 17, 2023
module: bootstrap module loaders in shadow realm
1 parent 966e3d3 commit f1f3986

25 files changed

+487
-190
lines changed
 

‎lib/internal/bootstrap/realm.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050

5151
const {
5252
ArrayFrom,
53+
ArrayPrototypeFilter,
54+
ArrayPrototypeIncludes,
5355
ArrayPrototypeMap,
5456
ArrayPrototypePush,
5557
ArrayPrototypeSlice,
@@ -215,8 +217,8 @@ const internalBuiltinIds = builtinIds
215217
.filter((id) => StringPrototypeStartsWith(id, 'internal/') && id !== selfId);
216218

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

222224
/**
@@ -269,6 +271,13 @@ class BuiltinModule {
269271
}
270272
}
271273

274+
static setRealmAllowRequireByUsers(ids) {
275+
canBeRequiredByUsersList =
276+
new SafeSet(ArrayPrototypeFilter(ids, (id) => ArrayPrototypeIncludes(publicBuiltinIds, id)));
277+
canBeRequiredByUsersWithoutSchemeList =
278+
new SafeSet(ArrayPrototypeFilter(ids, (id) => !schemelessBlockList.has(id)));
279+
}
280+
272281
// To be called during pre-execution when --expose-internals is on.
273282
// Enables the user-land module loader to access internal modules.
274283
static exposeInternals() {
+47
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

+4-1
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

+9
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ function setCallbackForWrap(wrap, data) {
3131
callbackMap.set(wrap, data);
3232
}
3333

34+
let defaultImportModuleDynamically;
35+
function setDefaultImportModuleDynamically(importModuleDynamically) {
36+
defaultImportModuleDynamically = importModuleDynamically;
37+
}
38+
3439
let defaultConditions;
3540
function getDefaultConditions() {
3641
assert(defaultConditions !== undefined);
@@ -90,6 +95,9 @@ async function importModuleDynamicallyCallback(wrap, specifier, assertions) {
9095
specifier, getModuleFromWrap(wrap) || wrap, assertions);
9196
}
9297
}
98+
if (defaultImportModuleDynamically) {
99+
return defaultImportModuleDynamically(specifier, assertions);
100+
}
93101
throw new ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING();
94102
}
95103

@@ -152,6 +160,7 @@ async function initializeHooks() {
152160

153161
module.exports = {
154162
setCallbackForWrap,
163+
setDefaultImportModuleDynamically,
155164
initializeESM,
156165
initializeHooks,
157166
getDefaultConditions,

‎lib/internal/process/pre_execution.js

+18-4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const {
2626
exposeLazyInterfaces,
2727
defineReplaceableLazyAttribute,
2828
setupCoverageHooks,
29+
kEmptyObject,
2930
} = require('internal/util');
3031

3132
const {
@@ -59,6 +60,18 @@ function prepareWorkerThreadExecution() {
5960
});
6061
}
6162

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

@@ -150,16 +163,16 @@ function setupSymbolDisposePolyfill() {
150163
}
151164
}
152165

153-
function setupUserModules(isLoaderWorker = false) {
166+
function setupUserModules(options = kEmptyObject) {
167+
const { isLoaderWorker = false, noPreloadModules = false } = options;
154168
initializeCJSLoader();
155169
initializeESMLoader(isLoaderWorker);
156170
const CJSLoader = require('internal/modules/cjs/loader');
157171
assert(!CJSLoader.hasLoadedAnyUserCJSModule);
158172
// Loader workers are responsible for doing this themselves.
159-
if (isLoaderWorker) {
160-
return;
173+
if (!isLoaderWorker || noPreloadModules) {
174+
loadPreloadModules();
161175
}
162-
loadPreloadModules();
163176
// Need to be done after --require setup.
164177
initializeFrozenIntrinsics();
165178
}
@@ -687,6 +700,7 @@ module.exports = {
687700
setupUserModules,
688701
prepareMainThreadExecution,
689702
prepareWorkerThreadExecution,
703+
prepareShadowRealmExecution,
690704
markBootstrapComplete,
691705
loadPreloadModules,
692706
initializeFrozenIntrinsics,

‎lib/internal/vm/module.js

+1
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class Module {
126126
options.cachedData);
127127
const { setCallbackForWrap } = require('internal/modules/esm/utils');
128128
setCallbackForWrap(this[kWrap], {
129+
__proto__: null,
129130
initializeImportMeta: options.initializeImportMeta,
130131
importModuleDynamically: options.importModuleDynamically ?
131132
importModuleDynamicallyWrap(options.importModuleDynamically) :

‎src/async_wrap.cc

+10-9
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,9 @@ void AsyncWrap::CreatePerContextProperties(Local<Object> target,
372372
Local<Value> unused,
373373
Local<Context> context,
374374
void* priv) {
375-
Environment* env = Environment::GetCurrent(context);
376-
Isolate* isolate = env->isolate();
375+
Realm* realm = Realm::GetCurrent(context);
376+
Environment* env = realm->env();
377+
Isolate* isolate = realm->isolate();
377378
HandleScope scope(isolate);
378379

379380
PropertyAttribute ReadOnlyDontDelete =
@@ -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.cc

+8-4
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ void IsolateData::CreateProperties() {
500500
binding::CreateInternalBindingTemplates(this);
501501

502502
contextify::ContextifyContext::InitializeGlobalTemplates(this);
503+
CreateEnvProxyTemplate(this);
503504
}
504505

505506
constexpr uint16_t kDefaultCppGCEmebdderID = 0x90de;
@@ -1650,10 +1651,13 @@ void AsyncHooks::MemoryInfo(MemoryTracker* tracker) const {
16501651
void AsyncHooks::grow_async_ids_stack() {
16511652
async_ids_stack_.reserve(async_ids_stack_.Length() * 3);
16521653

1653-
env()->async_hooks_binding()->Set(
1654-
env()->context(),
1655-
env()->async_ids_stack_string(),
1656-
async_ids_stack_.GetJSArray()).Check();
1654+
env()
1655+
->principal_realm()
1656+
->async_hooks_binding()
1657+
->Set(env()->context(),
1658+
env()->async_ids_stack_string(),
1659+
async_ids_stack_.GetJSArray())
1660+
.Check();
16571661
}
16581662

16591663
void AsyncHooks::FailWithCorruptedAsyncStack(double expected_async_id) {

0 commit comments

Comments
 (0)
Please sign in to comment.