0

Suppose I have come text that defines a valid JavaScript function, like so:

function sum(x, y) {
    return x + y
}

I want to be able to write Java code which compiles that text into a callable entity such that:

  • My Java code can discover the compiled entity is a function and not an arbitrary script.
  • My Java code can discover how many parameters the function has.
  • I can invoke the function from Java by providing data bindings for all of the parameters.

I was expecting the javax.script package to provide code that would accomplish this, but I can't for the life of me see how. How would I write Java code to accomplish what I have described above.

0xbe5077ed
  • 4,217
  • 1
  • 28
  • 62

1 Answers1

2

To have Java call that JavaScript function, you first evaluate the script, then scan the variables in the global scope for functions.

You can call those functions, but you don't get the parameters. For that, you'd have to parse the function header yourself.

Java 8-14 uses the Nashorn engine. Here is example, with various ways to define a function, so you can see the difference in the function header.

import java.util.Map.Entry;
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import jdk.nashorn.api.scripting.JSObject;
String script = "function sum(x, y) {\n" +
                "    return x + y\n" +
                "}\n" +
                "function diff() {\n" +
                "    return arguments[0] - arguments[1]\n" +
                "}\n" +
                "mult = function(x, y) {\n" +
                "    return x * y\n" +
                "}\n";
ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
Bindings vars = engine.createBindings();
engine.eval(script, vars);
for (Entry<String, Object> var : vars.entrySet()) {
    String name = var.getKey();
    Object value = var.getValue();
    if (value instanceof JSObject) {
        JSObject jsObj = (JSObject) value;
        if (jsObj.isFunction()) {
            String funcHeader = jsObj.toString().replaceFirst("(?s)\\{.*", "");
            System.out.println("function '" + name + "' defined as: " + funcHeader);
            System.out.println(name + "(5,7) = " + jsObj.call(null, 5, 7));
        }
    }
}

Output

function 'sum' defined as: function sum(x, y) 
sum(5,7) = 12.0
function 'diff' defined as: function diff() 
diff(5,7) = -2.0
function 'mult' defined as: function(x, y) 
mult(5,7) = 35.0
Andreas
  • 138,167
  • 8
  • 112
  • 195