Skip to content

Call linker when dynamically importing inside a vm.Module #19363

@Jamesernator

Description

@Jamesernator

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:

  1. Repeat the linker algorithm starting by letting importedModule be linkerFunction("some-specifier", importingModule).
  2. Perform importedModule.instantiate().
  3. Perform importedModule.evaluate()
  4. Resolve the promise for import("some-specifier") with importedModule.namespace.
  5. 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;
    },
});

Metadata

Metadata

Assignees

Labels

esmIssues and PRs related to the ECMAScript Modules implementation.feature requestIssues that request new features to be added to Node.js.vmIssues and PRs related to the vm subsystem.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions