help icon indicating copy to clipboard operation
help copied to clipboard

Embedder API: Loading ES6 Modules

Open DavidPeicho opened this issue 3 years ago • 4 comments

Details

I am trying to use the NodeJS Embedder API in a C++ application. My goal would be to load JS modules that might contain import statement. What would be the best way to go about that?

So far, I have created a v8::Module and I can instantiate it and run it without trouble. However, I have issue importing modules especially default ones such as path. I am not sure what would be the best way to resolve module recursively taking into account the internal modules nodejs exposes (path, http, etc...)

What would be the best way to achieve something like that?

Node.js version

v18.10.0

Example code

Example with custom module execution:

v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate,
    "import Path from 'path';console.log(Path);"
).ToLocalChecked();

v8::ScriptOrigin origin(isolate, v8::String::NewFromUtf8(isolate, "main.mjs").ToLocalChecked(),
        0,
        0,
        false,
        0,
        v8::Local<v8::Value>(),
        false,
        false,
        true
);
v8::ScriptCompiler::Source source(source, origin);
v8::Local<v8::Module> module;
if (!v8::ScriptCompiler::CompileModule(isolate, &source).ToLocal(&module)) {
    return;
}

module->InstantiateModule(context, [](
    v8::Local<v8::Context> context, v8::Local<v8::String> specifier,
    v8::Local<v8::FixedArray> import_assertions, v8::Local<v8::Module> referrer) {
    // How should the module be resolved? Can we use the ModuleWrapper from NodeJS?
    return v8::Local<v8::Module>();
});

Operating system

MacOS Monterey 12.6, but not that relevant for this particular question

Scope

Embedder API

Module and version

Not applicable.

DavidPeicho avatar Oct 11 '22 17:10 DavidPeicho

I tried a lot of ways, none of them worked so far.

1. SourceTextModule

I tried to use vm.SourceTextModule, but it looks like I would need to link myself the modules dependencies...

2. vm.runInThisContext + dynamic import

Environment is loaded using a custom callback:

v8::MaybeLocal<v8::Value> loadRes = node::LoadEnvironment(env,
    [this](const node::StartExecutionCallbackInfo& info) {
        ...
    });

And then I use the vm.runInThisContext function obtained during the environment setup:

v8::Local<v8::Value> source = v8::String::NewFromUtf8Literal(isolate, "import('path').then(p => console.log(p))");
runInContextFunc->Get(isolate)->Call(context, v8::Null(solate), 1, &source).ToLocalChecked();

This doesn't work and keep throwing an error: ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING. Looking at the code, it makes sense why this error is thrown. However, I am not sure what I am supposed to do. Ideally, I would like to re-use the node resolution algorithm already there.

3. LoadEnvironment without any callback

I tried to set a startup script to process.argv[1], and then load the environment using:

node::LoadEnvironment(_setup->env(), node::StartExecutionCallback{});

The script is executed properly, but I still can't easily use import statements outside of that.

DavidPeicho avatar Oct 18 '22 16:10 DavidPeicho

I don't know if it's the best idea, but I solved that using evalModule from the internals.

DavidPeicho avatar Oct 24 '22 15:10 DavidPeicho

I tried to use vm.SourceTextModule, but it looks like I would need to link myself the modules dependencies...

Related to https://github.com/nodejs/node/issues/31234 to provide built-in implementations of module linker, initializeImportMeta, importModuleDynamically

MadLittleMods avatar Apr 22 '23 06:04 MadLittleMods

There has been no activity on this issue for 11 months. The help repository works best when sustained engagement moves conversation forward. The issue will be closed in 1 month. If you are still experiencing this issue on the latest supported versions of Node.js, please leave a comment.

github-actions[bot] avatar Mar 18 '24 01:03 github-actions[bot]

Closing after no activity on this issue for 12 months.

github-actions[bot] avatar Apr 17 '24 01:04 github-actions[bot]