Skip to content

Commit da3f505

Browse files
committed
module: fix dynamic import from eval
This allows dynamic import to work from CLI `--eval` with or without `--input-type=module`. Fixes: nodejs#30591
1 parent 51ccf1b commit da3f505

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

lib/internal/modules/esm/loader.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ const defaultResolve = require('internal/modules/esm/default_resolve');
2525
const createDynamicModule = require(
2626
'internal/modules/esm/create_dynamic_module');
2727
const { translators } = require('internal/modules/esm/translators');
28-
const { ModuleWrap } = internalBinding('module_wrap');
2928
const { getOptionValue } = require('internal/options');
3029

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

lib/internal/process/execution.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,19 @@ function evalScript(name, body, breakFirstLine, print) {
6464
const module = new CJSModule(name);
6565
module.filename = path.join(cwd, name);
6666
module.paths = CJSModule._nodeModulePaths(cwd);
67+
68+
let fileURL;
69+
module.importModuleDynamically = async (specifier) => {
70+
if (!fileURL) {
71+
const { pathToFileURL } = require('url');
72+
fileURL = pathToFileURL(path.join(cwd, name)).href;
73+
}
74+
75+
const asyncESM = require('internal/process/esm_loader');
76+
const loader = await asyncESM.ESMLoader;
77+
return loader.import(specifier, fileURL);
78+
};
79+
6780
global.kVmBreakFirstLineSymbol = kVmBreakFirstLineSymbol;
6881
const script = `
6982
global.__filename = ${JSONStringify(name)};
@@ -73,11 +86,14 @@ function evalScript(name, body, breakFirstLine, print) {
7386
global.require = require;
7487
const { kVmBreakFirstLineSymbol } = global;
7588
delete global.kVmBreakFirstLineSymbol;
89+
const { importModuleDynamically } = module;
90+
delete module.importModuleDynamically;
7691
return require("vm").runInThisContext(
7792
${JSONStringify(body)}, {
7893
filename: ${JSONStringify(name)},
7994
displayErrors: true,
80-
[kVmBreakFirstLineSymbol]: ${!!breakFirstLine}
95+
[kVmBreakFirstLineSymbol]: ${!!breakFirstLine},
96+
importModuleDynamically
8197
});\n`;
8298
const result = module._compile(script, `${name}-wrapper`);
8399
if (print) {

test/parallel/test-cli-eval.js

Lines changed: 20 additions & 0 deletions
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} ` +
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)