Call linker when dynamically importing inside a vm.Module
Dynamically importing from a Module
Currently vm.Module
can construct and evaluate modules just fine, but there's no way for one of those modules to dynamically import another file e.g.:
const mod = new vm.Module(`
import("./otherModule.mjs");
`);
await mod.link((specifier, module) => {
console.log("Expected this be called on dynamic import!")
});
mod.instantiate();
const { result } = await mod.evaluate();
// Error: Cannot find module ./otherModule.mjs
await result;
Now for dynamic import reusing the linker function should be sufficient as the algorithm for resolving a dynamic module should be the same as for a static module.
Hence we can do import("some-specifier")
with this simple process:
- Repeat the linker algorithm starting by letting
importedModule
belinkerFunction("some-specifier", importingModule)
. - Perform
importedModule.instantiate()
. - Perform
importedModule.evaluate()
- Resolve the promise for
import("some-specifier")
withimportedModule.namespace
. - NOTE: If any of the above steps fail then reject the Promise for
import("some-specifier")
Dynamically importing from a Script
Because the script goal also supports dynamic import we need a way to be able to create a vm.Script
with a dynamic import hook, I'm not really sure where this should go, perhaps a linker
option to script.runInContext(...)
(and variants).
For this to be easily compatible with vm.Module
then vm.Script
should also support the url
option in lieu of filename
so that the linker can just inspect the .url
property to perform linking.
e.g.:
const script = new vm.Script(`
import("./someModule.mjs");
`, {
url: "file:///my-directory/my-cool-script.js",
});
script.runInContext(context, {
linker(specifier, scriptOrModule) {
const resolvedUrl = new URL(specifier, scriptOrModule.url);
// fetch and instantiate module
return importedModule;
},
});