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 <me@gus.host> Reviewed-By: Yorkie Liu <yorkiefixer@gmail.com> Reviewed-By: Ben Coe <bencoe@gmail.com>
1 parent 2a2ae8e commit a91b735

3 files changed

Lines changed: 44 additions & 4 deletions

File tree

‎lib/internal/modules/esm/loader.js‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ const defaultResolve = require('internal/modules/esm/default_resolve');
2121
constcreateDynamicModule=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
constdebug=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-
constevalInstance=(url)=>newModuleWrap(url,undefined,source,0,0);
120+
constevalInstance=(url)=>{
121+
const{ ModuleWrap, callbackMap }=internalBinding('module_wrap');
122+
constmodule=newModuleWrap(url,undefined,source,0,0);
123+
callbackMap.set(module,{
124+
importModuleDynamically: (specifier,{ url })=>{
125+
returnthis.import(specifier,url);
126+
}
127+
});
128+
129+
returnmodule;
130+
};
122131
constjob=newModuleJob(this,url,evalInstance,false,false);
123132
this.moduleMap.set(url,job);
124133
const{ module, result }=awaitjob.run();

‎lib/internal/process/execution.js‎

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

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

6263
constmodule=newCJSModule(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+
constbaseUrl=pathToFileURL(module.filename).href;
71+
6672
constscript=`
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
constresult=module._compile(script,`${name}-wrapper`);
8192
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}${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)