Renato
Renato

Reputation: 13700

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

I have some JS code that looks roughly like this:

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

I want to access and call ssr from Java.

How can I do that?

I've been trying something like this:

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");

But this always returns null.

Upvotes: 1

Views: 1053

Answers (3)

user1336088
user1336088

Reputation: 21

Please look into testExportNamespace function at https://github.com/oracle/graaljs/blob/master/graal-js/src/com.oracle.truffle.js.test/src/com/oracle/truffle/js/test/interop/ESModuleTest.java

Hint is to use

  1. allowExperimentalOptions(true) in Context builder
  2. option(JSContextOptions.ESM_EVAL_RETURNS_EXPORTS_NAME, "true"); in Context builder
  3. Set .mimeType(JavaScriptLanguage.MODULE_MIME_TYPE) in Source builder

Regards Saurabh

Upvotes: 1

Daniele Bonetta
Daniele Bonetta

Reputation: 66

Values exported from a module can be imported by another module using the import syntax. For example, you could have another file loading your module, like:

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

and then execute the file via:

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

Here, Value ssr is the value exported by your module with export {ssr as default};

Upvotes: 3

BoriS
BoriS

Reputation: 982

The following java code

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());
    }
}

outputs

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

On GraalVM CE 20.0.0 so I assume there is something wrong with the way you build your Source object.

Upvotes: 1

Related Questions