[graalvm-users] Replacing ScriptEngine Invocable cast with Context API equivalent

Kulkova, Katarina katarina.kulkova18 at imperial.ac.uk
Mon Aug 3 02:36:20 PDT 2020


Hello!


I am working on porting a rather large code base from nashorn to graal.js. The original code was using javax.script.ScriptEngine. I would like to replace it by the polyglot Context API if possible

 private ScriptEngine engine =
    new ScriptEngineManager().getEngineByName("nashorn");


I have decided to replace the ScriptEngine with the polyglot Context API.

private Context cx = Context.newBuilder().allowAllAccess(true).allowHostAccess(HostAccess.ALL).build();


I replaced every call to engine.put() with a call to cx.getBindings("js").putMember() and similarly engine.get() with cx.getBindings("js").getMember() like this:

cx.getBindings("js").putMember("mote", mote);
cx.getBindings("js").putMember("id", id);
//engine.put("mote", mote);
//engine.put("id", id);


I also replaced the engine.eval() call with a cx.eval() call. However, there is one place in the code where I cannot get rid of the engine. The engine is cast as an Invocable and runs a Thread in a thread group:

scriptThread = new Thread(group, new Runnable() {
  public void run() {
    try {
      ((Invocable)engine).getInterface(Runnable.class).run();
    } catch (RuntimeException e) {
      Throwable throwable = e;
      while (throwable.getCause() != null) {
        throwable = throwable.getCause();
      }

      if (throwable.getMessage() != null &&
          throwable.getMessage().contains("test script killed") ) {
        logger.info("Test script finished");
      } else {
        if (!Cooja.isVisualized()) {
          logger.fatal("Test script error, terminating Cooja.");
          logger.fatal("Script error:", e);
          System.exit(1);
        }

        logger.fatal("Script error:", e);
        deactivateScript();
        simulation.stopSimulation();
        if (Cooja.isVisualized()) {
          Cooja.showErrorDialog(Cooja.getTopParentContainer(),
              "Script error", e, false);
        }
      }
    }
    /*logger.info("test script thread exits");*/
  }
});
scriptThread.start(); /* Starts by acquiring semaphore (blocks) */
while (!semaphoreScript.hasQueuedThreads()) {
  Thread.yield();
}


This is the part I would like to change:

 ((Invocable)engine).getInterface(Runnable.class).run();


Is there a Context equivalent for this? I could not find any documentation regarding Invocables in the Context API. I have, however, read somewhere that it I should use Context to execute JavaScript code when using GraalVM. So my question is, is there a way to change this piece of code, so that it keeps its functionality but I don't have to use the engine anymore and use the Context API instead? If not, what would be a good way to do it?


Thanks in advance.


Best regards,

   Katarina

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://oss.oracle.com/pipermail/graalvm-users/attachments/20200803/03560a90/attachment.html 


More information about the GraalVM-Users mailing list