long
long

Reputation: 414

Nashorn call method of java object (passed through bindings) via function reference in JS

I'd like to put native Java objects into the ScriptEngine bindings for easier access.

scriptEngine.put("myApi", myApiInstance);

Here "myApiInstance" has one non-static method "foo()".

Now in JS I have a function:

someJsFunction(func) { func.call(...) }

But the call

someJsFunction(myApiInstance.foo)

results to a "TypeError: func.call is not a function".

At the other hand, "myApiInstance.foo()" works as expected. This look like a ScripEngine specifics, as "call()" method should be available in any function. And yes, "typeof myApiInstance.foo" returns "function"

Upvotes: 3

Views: 1756

Answers (1)

A. Sundararajan
A. Sundararajan

Reputation: 4405

Java methods and function interface objects (lambda objects) are treated as script functions and hence callable from JavaScript as usual. As you mentioned "typeof" on such objects returns true. You can directly call these from script. But these are not real JS function objects in the sense that these don't have their proto to be Function.prototype. That said, if you want to invoke these using Function.prototype.call or .apply, [say you're dispatching to any callable passed), you can do the following:

import javax.script.*;

public class Main {
  public static void main(String[] args) throws Exception {
    ScriptEngineManager m = new ScriptEngineManager();
    ScriptEngine e = m.getEngineByName("nashorn");

    // get the java static method to call
    e.eval("var getProp = java.lang.System.getProperty");
    // direct call
    e.eval("print(getProp('java.home'))");

    // call using Function.prototype.call
    e.eval("print(Function.prototype.call.call(getProp, null, 'java.home'))");

    // a java object
    e.eval("var out = java.lang.System.out");
    // get an instance method
    e.eval("var p = out.println");
    // call java instance method using Function.prototype.call
    e.eval("Function.prototype.call.call(p, out, 'hello world')");
  }
}

Upvotes: 4

Related Questions