I have a Map in Scala/Java I want to be visible in Javascript running on graal.js engine.
case class Thing() {
def foo() { println("FOO!") } // just to see if this is callable from js (it is)
val m = Map("foo" -> "bar", "one" -> 1)
val d1 = m
val d2 = m.asJava
val d3 = toGraalValue(m)
val d4 = MapProxyObject(m.map { case (k, v) => (k.toString, toGraalValue(v)) })
def toGraalValue(a: Any): Value =
a match {
case s: List[_] => Value.asValue(ListProxyArray(s.map(toGraalValue).toArray))
case m: Map[_, _] => Value.asValue(MapProxyObject(m.map { case (k, v) => (k.toString, toGraalValue(v)) }))
case _ => Value.asValue(a)
}
}
Later, a Javascript function in graal.js is called with:
inv.invokeFunction(bindFn, args: _*)
Where bindFn is a compiled function (below) and args is a 1-element list containing my Thing object.
Javascript:
function(thing) {
console.log(thing.d1);
console.log(thing.d2);
console.log(thing.d3);
console.log(thing.d4);
console.log(thing.foo());
}
The output from thing.foo() worked, but all the others resolved to 'foreign {}' in Javascript. None of them have any values in the Map.
How can I get Map data created on the JVM visible in graal.js Javascript code (preferably natively to Javascript)?
Ok, this actually seems to be a Scala vs Java thing. In Scala I can successfully pass a Map if its contents are converted to graal Value. No issues. I can successfully pass a Scala object (case or non-case) and call methods on that object, BUT... I cannot access data members of the object, even if they're all Value!
If I create a pure Java class I can access both the data members and methods of that class in graal.
Not sure why this is... a non-case Scala class should basically be the same as a Java class, but clearly there is some difference important to graal.
Fortunately I think I can live with the difference for now.