Skip to content

Commit d4aa656

Browse files
coreyfarrelltargos
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 3557659 commit d4aa656

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
@@ -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

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

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

6465
const module = new CJSModule(name);
6566
module.filename = path.join(cwd, name);
6667
module.paths = CJSModule._nodeModulePaths(cwd);
68+
6769
global.kVmBreakFirstLineSymbol = kVmBreakFirstLineSymbol;
70+
global.asyncESM = require('internal/process/esm_loader');
71+
72+
const baseUrl = pathToFileURL(module.filename).href;
73+
6874
const script = `
6975
global.__filename = ${JSONStringify(name)};
7076
global.exports = exports;
7177
global.module = module;
7278
global.__dirname = __dirname;
7379
global.require = require;
74-
const { kVmBreakFirstLineSymbol } = global;
80+
const { kVmBreakFirstLineSymbol, asyncESM } = global;
7581
delete global.kVmBreakFirstLineSymbol;
82+
delete global.asyncESM;
7683
return require("vm").runInThisContext(
7784
${JSONStringify(body)}, {
7885
filename: ${JSONStringify(name)},
7986
displayErrors: true,
80-
[kVmBreakFirstLineSymbol]: ${!!breakFirstLine}
87+
[kVmBreakFirstLineSymbol]: ${!!breakFirstLine},
88+
async importModuleDynamically (specifier) {
89+
const loader = await asyncESM.ESMLoader;
90+
return loader.import(specifier, ${JSONStringify(baseUrl)});
91+
}
8192
});\n`;
8293
const result = module._compile(script, `${name}-wrapper`);
8394
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} ` +
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)