Reputation: 167
The GraalJS documentation for host access states that its enough to add the annotation @HostAccess.Export
My code looks like this:
(ns graaljs.core
(:gen-class)
(:import (org.graalvm.polyglot Context)))
(definterface SampleAdapter (getData []))
(deftype AdapterInstance [documents]
SampleAdapter
(^{HostAccess.Export true}
getData
[this]
documents))
(let [js-code (format "(%s)" (slurp "./js/js-java-object-parser.js"))
adapter (AdapterInstance. "wo")
context (Context/create (into-array ["js"]))
_ (-> context
(.getBindings "js")
(.putMember "adapter" adapter))
js-evaluated-code (.eval context "js" js-code)]
(.execute js-evaluated-code (into-array [])))
and the JS I am executing is this one:
function parserFunction() {
console.log('foo')
console.log(adapter.getData())
console.log("this works")
}
When evaluating the code I get no issues but when I run the JS code I get the following error in the REPL
foo
;
; Syntax error (PolyglotException) compiling at (C:\ZigiOps\graaljs\src\graaljs\core.clj:14:1).
; TypeError: invokeMember (getData) on graaljs.core.AdapterInstance failed due to: Unknown identifier: getData
; Evaluation of file core.clj failed: class clojure.lang.Compiler$CompilerException
and for some reason I cant access my object methods inside the JS context
Upvotes: 1
Views: 55
Reputation: 167
So I found a way to do it!
One way to do this is quite crude, has side effects since it gives all kinds of unneeded access to your environment from the executed JS code is to call the (.allowAllAccess true)
method of the context you are creating
(-> context
(.getBindings "js")
(.putMember "adapter" adapter))
but as mentioned this has side effects check here
The more elegant way to solve it is to fix the annotations. It took quite a while to find it, for some unknown reason there are very little discussions for how to properly annotations in clojure. Here is the working code:
(ns graaljs.core
(:gen-class)
(:import (org.graalvm.polyglot Context HostAccess$Export)))
(definterface SampleAdapter (getData []))
(deftype AdapterInstance [documents]
SampleAdapter
(^{HostAccess$Export true}
getData
[this]
documents))
(let [js-code (format "(%s)" (slurp "./js/js-java-object-parser.js"))
adapter (AdapterInstance. "wo")
context (Context/create (into-array ["js"]))
_ (-> context
(.getBindings "js")
(.putMember "adapter" adapter))
js-evaluated-code (.eval context "js" js-code)]
(.execute js-evaluated-code (into-array [])))
The difference is that I imported the annotation and replaced the . (dot) with a $ (dollar sign) and it worked
Upvotes: 1