Search code examples
javascriptjavagraalvm

Migrating Nashorn to GraalVM to cache and execute scripts


So I have a java application that uses NashornScriptEngine to create a CompiledScript, where I can then create an Invocable. The compiled script was compiled from a File input which was the js I am trying to run. I then cached this Invocable in a map to later execute. Using it was as simple as

import javax.script.Invocable;

public void handleEvent(Event event, Processor processor){
    try {
        Invocable script = cache.get(event);
        if(script != null) {
            script.invokeFunction("run", data);
        } else {
            throw new UnsupportedOperationException(event.name());
        }
    } catch (Exception exception) ...
}

However, since Nashorn is deprecated, I am trying to switch to GraalVM while achieving the same thing. I saw some GitHub pages that talked about this but it honestly didn't help me. Here are some of the ones I am looking at.

https://github.com/graalvm/graaljs/blob/master/docs/user/ScriptEngine.md https://github.com/graalvm/graaljs/issues/78

And this is what I found to be the most useful, however it doesn't allow me to invoke at an entry point like my code above could nor could I create an invocable to cache and be called later on.

    public void compile(File file){
        try {
            Source source = Source.newBuilder("js", file).build();
            Engine engine = Engine.create();

            Context context = Context.newBuilder("js").engine(engine).option("js.nashorn-compat", "true").build();
            context.eval(source);
            context.close();
        } catch (Exception exception){
            exceptionCaught(exception);
        }
    }

Any tips on how I can compile a file (js) to an invocable using GraalVM? Thank you!


Solution

  • context.eval() will return a value of type org.graalvm.polyglot.Value. When source returns a function, then this value will answer canExecute() with true and you can value.execute(args...) it repeatedly. See the API of Value: https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/Value.html

    I see you are setting the nashorn-compat option. Please understand this is a backwards-compatibility option that you should best not use. In many scenarios, your code will run perfectly without that option. Please check the Migration guide for the cases where something is really not supported by GraalVM JavaScript that is available in Nashorn mode.