Add binding to static class Math in graal context

605 Views Asked by At

I use e.g.

context.getBindings("js").putMember("thing", new Thing(this));

to define a variable for my javascript.

How can I expose Java's Math """"object""""?

I can't do

context.getBindings("js").putMember("math", Math);

nor

context.getBindings("js").putMember("math", new Math());

(bc the constructor is private)

2

There are 2 best solutions below

0
On BEST ANSWER

Even using reflection like this to pass it

Constructor[] cs = Math.class.getDeclaredConstructors();
cs[0].setAccessible(true);
Math m = (Math) cs[0].newInstance();
context.getBindings("js").putMember("math", m);

Doesn't work in the end, because graaljs doesn't make static properties of Java host objects visible to the JavaScript.

So the solution is to use the .static property of Math.class

context.getBindings("js").putMember("math", Math.class);
System.out.println(context.eval("js", "math.static.toRadians(180)")); // prints 3.141592653589793

As I learnt here

0
On

As discussed in https://github.com/oracle/graaljs/issues/414, you need to:

  • expose Math.class and then access math.static.toRadians()
  • enable HostAccess on the Context you are using

The working example thus is:

try (Context ctx = Context.newBuilder("js").allowHostAccess(HostAccess.ALL).build()) {
        ctx.getBindings("js").putMember("math", Math.class);
        ctx.eval("js", "print(math.static.toRadians(180));");
        ctx.close();
}