如何使用 GraalVM 从 Java 访问 JS 导出的模块对象?

How can I access a JS-exported module object from Java using GraalVM?

我有一些 JS 代码,大致如下所示:

let ssr = async (arg) => arg || "hello js";
export {ssr as default};

我想从 Java 访问并调用 ssr

我该怎么做?

我一直在尝试这样的事情:

var ctx = Context.newBuilder("js")
                .allowIO(true)
                .allowHostAccess(HostAccess.ALL)
                .build();

        var ssrResource = new String(Server.class.getResourceAsStream("/ssr.mjs").readAllBytes());

        ctx.eval(Source
                .newBuilder("js", ssrResource, "ssr.mjs")
                .build());
        var ssr = ctx.getBindings("js").getMember("ssr");

但这总是returns null。

以下java代码

import org.graalvm.polyglot.*;

class Main {
    public static void main(String[] args) {
        var ctx = Context.newBuilder("js").allowAllAccess(true).build();
        ctx.eval("js", "let ssr = async (arg) => arg || \"hello js\"");
        var v = ctx.getBindings("js").getMember("ssr");
        System.out.println(v.execute());
    }
}

产出

Promise{[[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello js"}

在 GraalVM CE 20.0.0 上,所以我假设您构建 Source 对象的方式有问题。

从一个模块导出的值可以由另一个模块使用 import 语法导入。例如,您可以让另一个文件加载您的模块,例如:

// -- some-module-file.mjs
import ssr from 'ssr.mjs'
ssr;

然后通过以下方式执行文件:

File file = loadSomehow("some-module-file.mjs");
Source mainSource = Source.newBuilder("js", file).mimeType("application/javascript+module").build();
Value ssr = context.eval(mainSource);

这里,Value ssr是你的模块用export {ssr as default};

导出的值