Skip to content

Commit 32b2e94

Browse files
committed
add virtual module loader
1 parent efec345 commit 32b2e94

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

src/devtools/262_worker.mjs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ import {
88
Get,
99
CreateDataPropertyOrThrow,
1010
Value,
11+
Realm,
12+
Throw,
13+
Descriptor,
14+
CreateBuiltinFunction,
15+
JSStringValue,
16+
CreateNonEnumerableDataPropertyOrThrow,
17+
surroundingAgent,
1118
} from '../../lib/engine262.mjs';
1219
import { Inspector, createConsole } from '../../lib/inspector.mjs';
1320
import { Test262HarnessFiles } from '../shared/harness.mjs';
@@ -44,12 +51,41 @@ function recreateAgent(features, signal) {
4451
const agent = new Agent({ features });
4552
setSurroundingAgent(agent);
4653

54+
4755
inspector.attachAgent(agent, []);
4856
signal.addEventListener('abort', () => inspector.detachAgent(agent), { once: true });
4957

50-
const realm = new ManagedRealm({});
58+
const realm = new ManagedRealm({ name: 'playground repl' });
5159
createConsole(realm, {});
5260

61+
if (features.includes('virtual-module-loader')) {
62+
const virtualModuleCache = new Map();
63+
agent.hostDefinedOptions.loadImportedModule = (referrer, specifier, attributes, hostDefined, finish) => {
64+
const importerRealm = referrer instanceof Realm ? referrer : referrer.Realm;
65+
if (importerRealm instanceof ManagedRealm && virtualModuleCache.has(specifier)) {
66+
finish(importerRealm.compileModule(virtualModuleCache.get(specifier), { specifier }));
67+
return;
68+
}
69+
finish(Throw('SyntaxError', 'CouldNotResolveModule', specifier, 'repl'));
70+
}
71+
realm.scope(() => {
72+
const defineModule = CreateBuiltinFunction.from(function* defineModule(specifier, source) {
73+
if (!(specifier instanceof JSStringValue)) {
74+
return Throw('TypeError', 'NotAString', specifier);
75+
}
76+
if (!(source instanceof JSStringValue)) {
77+
return Throw('TypeError', 'NotAString', source);
78+
}
79+
if (surroundingAgent.debugger_cannotPreview) {
80+
return surroundingAgent.debugger_cannotPreview;
81+
}
82+
virtualModuleCache.set(specifier.stringValue(), source.stringValue());
83+
return Value.undefined;
84+
})
85+
CreateNonEnumerableDataPropertyOrThrow(realm.GlobalObject, Value('defineModule'), defineModule);
86+
});
87+
}
88+
5389
if (features.includes('test262-harness')) {
5490
createTest262Intrinsics(realm, false);
5591
evalQ((_Q, X) => {

src/devtools/index.mjs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const L = {
4444
title: ': A JavaScript engine written in JavaScript for development and exploration',
4545
featureSwitch: 'Enable {name}',
4646
includeTest262Env: 'Include test262 environment',
47+
includeVirtualModuleLoader: 'Include virtual module loader for the playground',
4748
evaluateAs: 'Evaluate as ',
4849
console: 'Console',
4950
script: 'Script',
@@ -300,6 +301,23 @@ function modifyUI(ConsolePanel) {
300301
),
301302
);
302303
}
304+
{
305+
const debugModuleLoader = Common.Settings.Settings.instance().createSetting(
306+
'engine262:virtual-module-loader',
307+
true,
308+
);
309+
if (state.features) {
310+
debugModuleLoader.set(state.features.includes('virtual-module-loader'));
311+
}
312+
debugModuleLoader.addChangeListener(updateFeature);
313+
featureSettings.push(debugModuleLoader);
314+
settingsPane.append(
315+
SettingsUI.createSettingCheckbox(
316+
S.engine262(L.engine262.includeVirtualModuleLoader),
317+
debugModuleLoader,
318+
),
319+
);
320+
}
303321
function updateFeature() {
304322
const features = [];
305323
for (const setting of featureSettings) {

0 commit comments

Comments
 (0)