Skip to content

Commit 90562ae

Browse files
guybedfordBridgeAR
authored andcommitted
module: use v8 synthetic modules
PR-URL: #29846 Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Minwoo Jung <[email protected]>
1 parent ba4946a commit 90562ae

File tree

7 files changed

+173
-96
lines changed

7 files changed

+173
-96
lines changed

lib/internal/bootstrap/loaders.js

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,7 @@ function NativeModule(id) {
150150
this.filename = `${id}.js`;
151151
this.id = id;
152152
this.exports = {};
153-
this.reflect = undefined;
154-
this.esmFacade = undefined;
153+
this.module = undefined;
155154
this.exportKeys = undefined;
156155
this.loaded = false;
157156
this.loading = false;
@@ -240,16 +239,18 @@ NativeModule.prototype.getURL = function() {
240239
};
241240

242241
NativeModule.prototype.getESMFacade = function() {
243-
if (this.esmFacade) return this.esmFacade;
244-
const createDynamicModule = nativeModuleRequire(
245-
'internal/modules/esm/create_dynamic_module');
242+
if (this.module) return this.module;
243+
const { ModuleWrap } = internalBinding('module_wrap');
246244
const url = this.getURL();
247-
return this.esmFacade = createDynamicModule(
248-
[], [...this.exportKeys, 'default'], url, (reflect) => {
249-
this.reflect = reflect;
250-
this.syncExports();
251-
reflect.exports.default.set(this.exports);
252-
});
245+
const nativeModule = this;
246+
this.module = new ModuleWrap(function() {
247+
nativeModule.syncExports();
248+
this.setExport('default', nativeModule.exports);
249+
}, [...this.exportKeys, 'default'], url);
250+
// Ensure immediate sync execution to capture exports now
251+
this.module.instantiate();
252+
this.module.evaluate(-1, false);
253+
return this.module;
253254
};
254255

255256
// Provide named exports for all builtin libraries so that the libraries
@@ -258,13 +259,12 @@ NativeModule.prototype.getESMFacade = function() {
258259
// called so that APMs and other behavior are supported.
259260
NativeModule.prototype.syncExports = function() {
260261
const names = this.exportKeys;
261-
if (this.reflect) {
262+
if (this.module) {
262263
for (let i = 0; i < names.length; i++) {
263264
const exportName = names[i];
264265
if (exportName === 'default') continue;
265-
this.reflect.exports[exportName].set(
266-
getOwn(this.exports, exportName, this.exports)
267-
);
266+
this.module.setExport(exportName,
267+
getOwn(this.exports, exportName, this.exports));
268268
}
269269
}
270270
};

lib/internal/modules/cjs/loader.js

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,7 @@ const experimentalExports = getOptionValue('--experimental-exports');
7575

7676
module.exports = Module;
7777

78-
let asyncESM;
79-
let ModuleJob;
80-
let createDynamicModule;
78+
let asyncESM, ModuleJob, ModuleWrap, kInstantiated;
8179

8280
const {
8381
CHAR_FORWARD_SLASH,
@@ -820,21 +818,18 @@ Module.prototype.load = function(filename) {
820818
const module = ESMLoader.moduleMap.get(url);
821819
// Create module entry at load time to snapshot exports correctly
822820
const exports = this.exports;
823-
if (module !== undefined) { // Called from cjs translator
824-
if (module.reflect) {
825-
module.reflect.onReady((reflect) => {
826-
reflect.exports.default.set(exports);
827-
});
828-
}
821+
// Called from cjs translator
822+
if (module !== undefined && module.module !== undefined) {
823+
if (module.module.getStatus() >= kInstantiated)
824+
module.module.setExport('default', exports);
829825
} else { // preemptively cache
830826
ESMLoader.moduleMap.set(
831827
url,
832-
new ModuleJob(ESMLoader, url, async () => {
833-
return createDynamicModule(
834-
[], ['default'], url, (reflect) => {
835-
reflect.exports.default.set(exports);
836-
});
837-
})
828+
new ModuleJob(ESMLoader, url, () =>
829+
new ModuleWrap(function() {
830+
this.setExport('default', exports);
831+
}, ['default'], url)
832+
)
838833
);
839834
}
840835
}
@@ -1145,6 +1140,5 @@ Module.Module = Module;
11451140
if (experimentalModules) {
11461141
asyncESM = require('internal/process/esm_loader');
11471142
ModuleJob = require('internal/modules/esm/module_job');
1148-
createDynamicModule = require(
1149-
'internal/modules/esm/create_dynamic_module');
1143+
({ ModuleWrap, kInstantiated } = internalBinding('module_wrap'));
11501144
}

lib/internal/modules/esm/loader.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,7 @@ class Loader {
117117
source,
118118
url = pathToFileURL(`${process.cwd()}/[eval${++this.evalIndex}]`).href
119119
) {
120-
const evalInstance = async (url) => {
121-
return {
122-
module: new ModuleWrap(source, url),
123-
reflect: undefined
124-
};
125-
};
120+
const evalInstance = (url) => new ModuleWrap(source, url);
126121
const job = new ModuleJob(this, url, evalInstance, false);
127122
this.moduleMap.set(url, job);
128123
const { module, result } = await job.run();
@@ -165,7 +160,7 @@ class Loader {
165160
return createDynamicModule([], exports, url, (reflect) => {
166161
debug(`Loading dynamic ${url}`);
167162
execute(reflect.exports);
168-
});
163+
}).module;
169164
};
170165
} else {
171166
if (!translators.has(format))

lib/internal/modules/esm/module_job.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,17 @@ class ModuleJob {
3030
// onto `this` by `link()` below once it has been resolved.
3131
this.modulePromise = moduleProvider.call(loader, url, isMain);
3232
this.module = undefined;
33-
this.reflect = undefined;
3433

3534
// Wait for the ModuleWrap instance being linked with all dependencies.
3635
const link = async () => {
37-
({ module: this.module,
38-
reflect: this.reflect } = await this.modulePromise);
36+
this.module = await this.modulePromise;
3937
assert(this.module instanceof ModuleWrap);
4038

4139
const dependencyJobs = [];
4240
const promises = this.module.link(async (specifier) => {
4341
const jobPromise = this.loader.getModuleJob(specifier, url);
4442
dependencyJobs.push(jobPromise);
45-
return (await (await jobPromise).modulePromise).module;
43+
return (await jobPromise).modulePromise;
4644
});
4745

4846
if (promises !== undefined)

lib/internal/modules/esm/translators.js

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ const {
3333
const readFileAsync = promisify(fs.readFile);
3434
const JsonParse = JSON.parse;
3535
const { maybeCacheSourceMap } = require('internal/source_map/source_map_cache');
36+
const moduleWrap = internalBinding('module_wrap');
37+
const { ModuleWrap } = moduleWrap;
3638

3739
const debug = debuglog('esm');
3840

@@ -78,22 +80,18 @@ translators.set('module', async function moduleStrategy(url) {
7880
const source = `${await getSource(url)}`;
7981
maybeCacheSourceMap(url, source);
8082
debug(`Translating StandardModule ${url}`);
81-
const { ModuleWrap, callbackMap } = internalBinding('module_wrap');
8283
const module = new ModuleWrap(stripShebang(source), url);
83-
callbackMap.set(module, {
84+
moduleWrap.callbackMap.set(module, {
8485
initializeImportMeta,
8586
importModuleDynamically,
8687
});
87-
return {
88-
module,
89-
reflect: undefined,
90-
};
88+
return module;
9189
});
9290

9391
// Strategy for loading a node-style CommonJS module
9492
const isWindows = process.platform === 'win32';
9593
const winSepRegEx = /\//g;
96-
translators.set('commonjs', async function commonjsStrategy(url, isMain) {
94+
translators.set('commonjs', function commonjsStrategy(url, isMain) {
9795
debug(`Translating CJSModule ${url}`);
9896
const pathname = internalURLModule.fileURLToPath(new URL(url));
9997
const cached = this.cjsCache.get(url);
@@ -106,17 +104,17 @@ translators.set('commonjs', async function commonjsStrategy(url, isMain) {
106104
];
107105
if (module && module.loaded) {
108106
const exports = module.exports;
109-
return createDynamicModule([], ['default'], url, (reflect) => {
110-
reflect.exports.default.set(exports);
111-
});
107+
return new ModuleWrap(function() {
108+
this.setExport('default', exports);
109+
}, ['default'], url);
112110
}
113-
return createDynamicModule([], ['default'], url, () => {
111+
return new ModuleWrap(function() {
114112
debug(`Loading CJSModule ${url}`);
115113
// We don't care about the return val of _load here because Module#load
116114
// will handle it for us by checking the loader registry and filling the
117115
// exports like above
118116
CJSModule._load(pathname, undefined, isMain);
119-
});
117+
}, ['default'], url);
120118
});
121119

122120
// Strategy for loading a node builtin CommonJS module that isn't
@@ -146,9 +144,9 @@ translators.set('json', async function jsonStrategy(url) {
146144
module = CJSModule._cache[modulePath];
147145
if (module && module.loaded) {
148146
const exports = module.exports;
149-
return createDynamicModule([], ['default'], url, (reflect) => {
150-
reflect.exports.default.set(exports);
151-
});
147+
return new ModuleWrap(function() {
148+
this.setExport('default', exports);
149+
}, ['default'], url);
152150
}
153151
}
154152
const content = `${await getSource(url)}`;
@@ -159,9 +157,9 @@ translators.set('json', async function jsonStrategy(url) {
159157
module = CJSModule._cache[modulePath];
160158
if (module && module.loaded) {
161159
const exports = module.exports;
162-
return createDynamicModule(['default'], url, (reflect) => {
163-
reflect.exports.default.set(exports);
164-
});
160+
return new ModuleWrap(function() {
161+
this.setExport('default', exports);
162+
}, ['default'], url);
165163
}
166164
}
167165
try {
@@ -181,10 +179,10 @@ translators.set('json', async function jsonStrategy(url) {
181179
if (pathname) {
182180
CJSModule._cache[modulePath] = module;
183181
}
184-
return createDynamicModule([], ['default'], url, (reflect) => {
182+
return new ModuleWrap(function() {
185183
debug(`Parsing JSONModule ${url}`);
186-
reflect.exports.default.set(module.exports);
187-
});
184+
this.setExport('default', module.exports);
185+
}, ['default'], url);
188186
});
189187

190188
// Strategy for loading a wasm module
@@ -207,5 +205,5 @@ translators.set('wasm', async function(url) {
207205
const { exports } = new WebAssembly.Instance(compiled, reflect.imports);
208206
for (const expt of Object.keys(exports))
209207
reflect.exports[expt].set(exports[expt]);
210-
});
208+
}).module;
211209
});

0 commit comments

Comments
 (0)