Skip to content

Commit 66a14d3

Browse files
devsnekdanielleadams
authored andcommitted
vm: add importModuleDynamically option to compileFunction
This reverts commit 2d5d773. See: #32985 See: #33364 See: #33166Fixes: #31860 PR-URL: #35431 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Ujjwal Sharma <ryzokuken@disroot.org>
1 parent 8a25405 commit 66a14d3

4 files changed

Lines changed: 60 additions & 29 deletions

File tree

‎doc/api/vm.md‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,9 @@ const vm = require('vm');
813813
<!--YAML
814814
added: v10.10.0
815815
changes:
816+
- version:REPLACEME
817+
pr-url: https://github.com/nodejs/node/pull/35431
818+
description: Added `importModuleDynamically` option again.
816819
- version: v14.3.0
817820
pr-url: https://github.com/nodejs/node/pull/33364
818821
description: Removal of`importModuleDynamically` due to compatibility
@@ -844,6 +847,16 @@ changes:
844847
* `contextExtensions` {Object[]} An array containing a collection of context
845848
extensions (objectswrappingthecurrentscope) to be applied while
846849
compiling. **Default:** `[]`.
850+
* `importModuleDynamically` {Function} Called during evaluation ofthismodule
851+
when `import()` is called. Ifthis option is not specified, calls to
852+
`import()` will reject with [`ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING`][].
853+
This option is part of the experimental modules API, and should not be
854+
considered stable.
855+
*`specifier` {string} specifier passed to `import()`
856+
*`function` {Function}
857+
* Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is
858+
recommended in order to take advantage of error tracking, and to avoid
859+
issues with namespaces that contain `then`function exports.
847860
* Returns: {Function}
848861

849862
Compiles the given code into the provided context (ifnocontextis

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

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
101101
constpolicy=getOptionValue('--experimental-policy') ?
102102
require('internal/process/policy') :
103103
null;
104-
const{ compileFunction }=internalBinding('contextify');
105104

106105
// Whether any user-provided CJS modules had been loaded (executed).
107106
// Used for internal assertions.
@@ -1019,40 +1018,25 @@ function wrapSafe(filename, content, cjsModuleInstance) {
10191018
},
10201019
});
10211020
}
1022-
letcompiled;
10231021
try{
1024-
compiled=compileFunction(
1025-
content,
1022+
returnvm.compileFunction(content,[
1023+
'exports',
1024+
'require',
1025+
'module',
1026+
'__filename',
1027+
'__dirname',
1028+
],{
10261029
filename,
1027-
0,
1028-
0,
1029-
undefined,
1030-
false,
1031-
undefined,
1032-
[],
1033-
[
1034-
'exports',
1035-
'require',
1036-
'module',
1037-
'__filename',
1038-
'__dirname',
1039-
]
1040-
);
1030+
importModuleDynamically(specifier){
1031+
constloader=asyncESM.ESMLoader;
1032+
returnloader.import(specifier,normalizeReferrerURL(filename));
1033+
},
1034+
});
10411035
}catch(err){
10421036
if(process.mainModule===cjsModuleInstance)
10431037
enrichCJSError(err);
10441038
throwerr;
10451039
}
1046-
1047-
const{ callbackMap }=internalBinding('module_wrap');
1048-
callbackMap.set(compiled.cacheKey,{
1049-
importModuleDynamically: async(specifier)=>{
1050-
constloader=asyncESM.ESMLoader;
1051-
returnloader.import(specifier,normalizeReferrerURL(filename));
1052-
}
1053-
});
1054-
1055-
returncompiled.function;
10561040
}
10571041

10581042
// Run the file contents in the correct scope or sandbox. Expose

‎lib/vm.js‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ function compileFunction(code, params, options = {}) {
324324
produceCachedData =false,
325325
parsingContext =undefined,
326326
contextExtensions =[],
327+
importModuleDynamically,
327328
}=options;
328329

329330
validateString(filename,'options.filename');
@@ -371,6 +372,22 @@ function compileFunction(code, params, options = {}) {
371372
result.function.cachedData=result.cachedData;
372373
}
373374

375+
if(importModuleDynamically!==undefined){
376+
if(typeofimportModuleDynamically!=='function'){
377+
thrownewERR_INVALID_ARG_TYPE('options.importModuleDynamically',
378+
'function',
379+
importModuleDynamically);
380+
}
381+
const{ importModuleDynamicallyWrap }=
382+
require('internal/vm/module');
383+
const{ callbackMap }=internalBinding('module_wrap');
384+
constwrapped=importModuleDynamicallyWrap(importModuleDynamically);
385+
constfunc=result.function;
386+
callbackMap.set(result.cacheKey,{
387+
importModuleDynamically: (s,_k)=>wrapped(s,func),
388+
});
389+
}
390+
374391
returnresult.function;
375392
}
376393

‎test/parallel/test-vm-module-basic.js‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ const {
88
Module,
99
SourceTextModule,
1010
SyntheticModule,
11-
createContext
11+
createContext,
12+
compileFunction,
1213
}=require('vm');
1314
constutil=require('util');
1415

@@ -160,3 +161,19 @@ const util = require('util');
160161
name: 'TypeError'
161162
});
162163
}
164+
165+
// Test compileFunction importModuleDynamically
166+
{
167+
constmodule=newSyntheticModule([],()=>{});
168+
module.link(()=>{});
169+
constf=compileFunction('return import("x")',[],{
170+
importModuleDynamically(specifier,referrer){
171+
assert.strictEqual(specifier,'x');
172+
assert.strictEqual(referrer,f);
173+
returnmodule;
174+
},
175+
});
176+
f().then((ns)=>{
177+
assert.strictEqual(ns,module.namespace);
178+
});
179+
}

0 commit comments

Comments
 (0)