Skip to content

Commit ffd22e8

Browse files
committed
module: use v8 synthetic modules
PR-URL: #29846 Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Minwoo Jung <[email protected]>
1 parent 0521a98 commit ffd22e8

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
@@ -74,9 +74,7 @@ const experimentalExports = getOptionValue('--experimental-exports');
7474

7575
module.exports = { wrapSafe, Module };
7676

77-
let asyncESM;
78-
let ModuleJob;
79-
let createDynamicModule;
77+
let asyncESM, ModuleJob, ModuleWrap, kInstantiated;
8078

8179
const {
8280
CHAR_FORWARD_SLASH,
@@ -819,21 +817,18 @@ Module.prototype.load = function(filename) {
819817
const module = ESMLoader.moduleMap.get(url);
820818
// Create module entry at load time to snapshot exports correctly
821819
const exports = this.exports;
822-
if (module !== undefined) { // Called from cjs translator
823-
if (module.reflect) {
824-
module.reflect.onReady((reflect) => {
825-
reflect.exports.default.set(exports);
826-
});
827-
}
820+
// Called from cjs translator
821+
if (module !== undefined && module.module !== undefined) {
822+
if (module.module.getStatus() >= kInstantiated)
823+
module.module.setExport('default', exports);
828824
} else { // preemptively cache
829825
ESMLoader.moduleMap.set(
830826
url,
831-
new ModuleJob(ESMLoader, url, async () => {
832-
return createDynamicModule(
833-
[], ['default'], url, (reflect) => {
834-
reflect.exports.default.set(exports);
835-
});
836-
})
827+
new ModuleJob(ESMLoader, url, () =>
828+
new ModuleWrap(function() {
829+
this.setExport('default', exports);
830+
}, ['default'], url)
831+
)
837832
);
838833
}
839834
}
@@ -1150,6 +1145,5 @@ Module.Module = Module;
11501145
if (experimentalModules) {
11511146
asyncESM = require('internal/process/esm_loader');
11521147
ModuleJob = require('internal/modules/esm/module_job');
1153-
createDynamicModule = require(
1154-
'internal/modules/esm/create_dynamic_module');
1148+
({ ModuleWrap, kInstantiated } = internalBinding('module_wrap'));
11551149
}

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
@@ -32,6 +32,8 @@ const {
3232
const readFileAsync = promisify(fs.readFile);
3333
const JsonParse = JSON.parse;
3434
const { maybeCacheSourceMap } = require('internal/source_map/source_map_cache');
35+
const moduleWrap = internalBinding('module_wrap');
36+
const { ModuleWrap } = moduleWrap;
3537

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

@@ -77,22 +79,18 @@ translators.set('module', async function moduleStrategy(url) {
7779
const source = `${await getSource(url)}`;
7880
maybeCacheSourceMap(url, source);
7981
debug(`Translating StandardModule ${url}`);
80-
const { ModuleWrap, callbackMap } = internalBinding('module_wrap');
8182
const module = new ModuleWrap(source, url);
82-
callbackMap.set(module, {
83+
moduleWrap.callbackMap.set(module, {
8384
initializeImportMeta,
8485
importModuleDynamically,
8586
});
86-
return {
87-
module,
88-
reflect: undefined,
89-
};
87+
return module;
9088
});
9189

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

121119
// Strategy for loading a node builtin CommonJS module that isn't
@@ -145,9 +143,9 @@ translators.set('json', async function jsonStrategy(url) {
145143
module = CJSModule._cache[modulePath];
146144
if (module && module.loaded) {
147145
const exports = module.exports;
148-
return createDynamicModule([], ['default'], url, (reflect) => {
149-
reflect.exports.default.set(exports);
150-
});
146+
return new ModuleWrap(function() {
147+
this.setExport('default', exports);
148+
}, ['default'], url);
151149
}
152150
}
153151
const content = `${await getSource(url)}`;
@@ -158,9 +156,9 @@ translators.set('json', async function jsonStrategy(url) {
158156
module = CJSModule._cache[modulePath];
159157
if (module && module.loaded) {
160158
const exports = module.exports;
161-
return createDynamicModule(['default'], url, (reflect) => {
162-
reflect.exports.default.set(exports);
163-
});
159+
return new ModuleWrap(function() {
160+
this.setExport('default', exports);
161+
}, ['default'], url);
164162
}
165163
}
166164
try {
@@ -180,10 +178,10 @@ translators.set('json', async function jsonStrategy(url) {
180178
if (pathname) {
181179
CJSModule._cache[modulePath] = module;
182180
}
183-
return createDynamicModule([], ['default'], url, (reflect) => {
181+
return new ModuleWrap(function() {
184182
debug(`Parsing JSONModule ${url}`);
185-
reflect.exports.default.set(module.exports);
186-
});
183+
this.setExport('default', module.exports);
184+
}, ['default'], url);
187185
});
188186

189187
// Strategy for loading a wasm module
@@ -206,5 +204,5 @@ translators.set('wasm', async function(url) {
206204
const { exports } = new WebAssembly.Instance(compiled, reflect.imports);
207205
for (const expt of Object.keys(exports))
208206
reflect.exports[expt].set(exports[expt]);
209-
});
207+
}).module;
210208
});

0 commit comments

Comments
 (0)