-
-
Notifications
You must be signed in to change notification settings - Fork 33.5k
Description
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
importedModulebelinkerFunction("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;
},
});