1

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.

1
  • Very good question. I am also searching for an answer. Commented Apr 20, 2021 at 7:42

3 Answers 3

3

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

Sign up to request clarification or add additional context in comments.

1 Comment

That seems helpful. I will try it and accept the answer if it works for me. Thanks.
1

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.

4 Comments

It doesn't work if you use the script as I posted, with an exports clause.
notice that this is a JS module I am trying to use (hence the file extension, mjs) I can't change the JS code.
maybe you could import the module and assign ssr from it to something global to pass it to the bindings?
@Renato Ah, quite! Missed that, sorry.
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.