Skip to content

Commit a91b735

Browse files
coreyfarrellMylesBorins
authored andcommitted
module: fix dynamic import from eval
This allows dynamic import to work from CLI `--eval` with or without `--input-type=module`. Fixes: #30591 PR-URL: #30624 Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Yorkie Liu <[email protected]> Reviewed-By: Ben Coe <[email protected]>
1 parent 2a2ae8e commit a91b735

File tree

3 files changed

+44
-4
lines changed

3 files changed

+44
-4
lines changed

lib/internal/modules/esm/loader.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ const defaultResolve = require('internal/modules/esm/default_resolve');
2121
const createDynamicModule = require(
2222
'internal/modules/esm/create_dynamic_module');
2323
const { translators } = require('internal/modules/esm/translators');
24-
const { ModuleWrap } = internalBinding('module_wrap');
2524
const { getOptionValue } = require('internal/options');
2625

2726
const debug = require('internal/util/debuglog').debuglog('esm');
@@ -118,7 +117,17 @@ class Loader {
118117
source,
119118
url = pathToFileURL(`${process.cwd()}/[eval${++this.evalIndex}]`).href
120119
) {
121-
const evalInstance = (url) => new ModuleWrap(url, undefined, source, 0, 0);
120+
const evalInstance = (url) => {
121+
const { ModuleWrap, callbackMap } = internalBinding('module_wrap');
122+
const module = new ModuleWrap(url, undefined, source, 0, 0);
123+
callbackMap.set(module, {
124+
importModuleDynamically: (specifier, { url }) => {
125+
return this.import(specifier, url);
126+
}
127+
});
128+
129+
return module;
130+
};
122131
const job = new ModuleJob(this, url, evalInstance, false, false);
123132
this.moduleMap.set(url, job);
124133
const { module, result } = await job.run();

lib/internal/process/execution.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -55,27 +55,38 @@ function evalModule(source, print) {
5555
function evalScript(name, body, breakFirstLine, print) {
5656
const CJSModule = require('internal/modules/cjs/loader').Module;
5757
const { kVmBreakFirstLineSymbol } = require('internal/util');
58+
const { pathToFileURL } = require('url');
5859

5960
const cwd = tryGetCwd();
6061
const origModule = global.module; // Set e.g. when called from the REPL.
6162

6263
const module = new CJSModule(name);
6364
module.filename = path.join(cwd, name);
6465
module.paths = CJSModule._nodeModulePaths(cwd);
66+
6567
global.kVmBreakFirstLineSymbol = kVmBreakFirstLineSymbol;
68+
global.asyncESM = require('internal/process/esm_loader');
69+
70+
const baseUrl = pathToFileURL(module.filename).href;
71+
6672
const script = `
6773
global.__filename = ${JSON.stringify(name)};
6874
global.exports = exports;
6975
global.module = module;
7076
global.__dirname = __dirname;
7177
global.require = require;
72-
const { kVmBreakFirstLineSymbol } = global;
78+
const { kVmBreakFirstLineSymbol, asyncESM } = global;
7379
delete global.kVmBreakFirstLineSymbol;
80+
delete global.asyncESM;
7481
return require("vm").runInThisContext(
7582
${JSON.stringify(body)}, {
7683
filename: ${JSON.stringify(name)},
7784
displayErrors: true,
78-
[kVmBreakFirstLineSymbol]: ${!!breakFirstLine}
85+
[kVmBreakFirstLineSymbol]: ${!!breakFirstLine},
86+
async importModuleDynamically (specifier) {
87+
const loader = await asyncESM.ESMLoader;
88+
return loader.import(specifier, ${JSON.stringify(baseUrl)});
89+
}
7990
});\n`;
8091
const result = module._compile(script, `${name}-wrapper`);
8192
if (print) {

test/parallel/test-cli-eval.js

+20
Original file line numberDiff line numberDiff line change
@@ -283,3 +283,23 @@ child.exec(
283283
assert.ifError(err);
284284
assert.strictEqual(stdout, '.mjs file\n');
285285
}));
286+
287+
288+
// Assert that packages can be dynamic imported initial cwd-relative with --eval
289+
child.exec(
290+
`${nodejs} ${execOptions} ` +
291+
'--eval "process.chdir(\'..\');' +
292+
'import(\'./test/fixtures/es-modules/mjs-file.mjs\')"',
293+
common.mustCall((err, stdout) => {
294+
assert.ifError(err);
295+
assert.strictEqual(stdout, '.mjs file\n');
296+
}));
297+
298+
child.exec(
299+
`${nodejs} ${execOptions} ` +
300+
'--eval "process.chdir(\'..\');' +
301+
'import(\'./test/fixtures/es-modules/mjs-file.mjs\')"',
302+
common.mustCall((err, stdout) => {
303+
assert.ifError(err);
304+
assert.strictEqual(stdout, '.mjs file\n');
305+
}));

0 commit comments

Comments
 (0)