javascriptjava-11graaljs

Graaljs script engine evaluate on java script string condition


I am using jdk11, graal.js script engine .

We get two json string messages, one has rules/condition(jsRules) and the other one has message. If the value in message satisfies the condition in jsRules it should evaluate to 1 else 0 .

So for example in the below code as String "message" has code: CU_USER hence the jsRules condition

header.code == 'CU_USER'

should have been satisfied and hence the eval below should have printed 1 , but instead it gives 0. Kindly explain what is causing this behavior and how can I get the desired behavior ? .

public static void process()
{
    int eval =-2 ;
    String jsRules = "{(header.code == 'CU_USER' || header.subcode == 'SD_CODE')?1:0}";
    String message = "{code:'CU_USER'}";
    
    ScriptEngine graalEngine = new ScriptEngineManager().getEngineByName("Graal.js");
    //graalEngine.put("header",message);
    try {
        graalEngine.eval("var header = unescape(" + message + ")");
        eval = (int)graalEngine.eval(jsRules);
        System.out.println("Eval value::  "+eval);
    } catch (ScriptException e) {
        e.printStackTrace();
    }
}

Solution

  • You call unescape({code:'CU_USER'}) while unescape expects a String. Thus, the object you provide as argument is converted to a String (to [object Object] actually) and thus the header variable on the JavaScript side holds a String, not an Object as you expect.

    The solution would be to simply remove the unescape, i.e. use graalEngine.eval("var header = " + message); instead.


    An alternative solution would be to pass in a Java object. You seem to have tried that with the commented out graalEngine.put("header",message); line. Note that I suppose don't want to pass in a Java string; what you typically want to pass in was a Java object that has a code field. Note that for this to work you need to enable the hostAccess permission to the engine (for more details, check https://github.com/graalvm/graaljs/blob/master/docs/user/ScriptEngine.md).

    solution draft:

    public static class MyMessageObj {
      public String code = "CU_USER";
    }
    
    ScriptEngine graalEngine = new ScriptEngineManager().getEngineByName("graal.js");
    Bindings bindings = graalEngine.getBindings(ScriptContext.ENGINE_SCOPE);
    bindings.put("polyglot.js.allowHostAccess", true);
    graalEngine.put("header", new MyMessageObj());
    eval = (int) graalEngine.eval(jsRules);