Is it possible to have Nashorn's load
method use the project's classpath when resolving URIs?
Here's what I'm attempting to do:
(defn create-engine
"Creates a new nashorn script engine and loads dependencies into its context."
[dependencies]
(let [nashorn (.getEngineByName (ScriptEngineManager.) "nashorn")
scripts (map #(str "load('" % "');") dependencies)]
(.eval nashorn "var global = this;")
(doseq [script scripts] (.eval nashorn script))
nashorn))
(def app "public/javascripts/app.js") ; in /resouces, on classpath
; resulting exception:
clojure.lang.Compiler$CompilerException:
javax.script.ScriptException: TypeError:
Cannot load script from public/javascripts/app.js in <eval> at line number 1
The Nashorn engine has been deprecated in JDK 11 as part of JEP 335 and and has been removed from JDK15 as part of JEP 372. GraalVM can step in as a replacement for JavaScript code previously executed on the Nashorn engine.
Technical Article. Until Java SE 7, JDKs shipped with a JavaScript scripting engine based on Mozilla Rhino. Java SE 8 will instead ship with a new engine called Oracle Nashorn, which is based on JSR 292 and invokedynamic .
Nashorn's load()
method actually supports taking a URL prefixed with classpath:
. It will load the file following that prefix from the classpath. Check out the source - http://cr.openjdk.java.net/~sundar/8025629/webrev.01/src/jdk/nashorn/internal/runtime/Context.java.html line 502.
Absolute path should always start with a slash, "/public/javascripts/app.js"
, but I'm not sure if load()
loads off the classpath, if it doesn't you may have to use eval(Reader)
method and construct the reader yourself
EDIT:
You need to use the opening slash for classpath resources if the path is absolute within the jar. No slash means relative to the particular class you're calling this from. You should get an InputStream
for the resource and eval a reader, in Java it would look like this:
nashorn.eval (new InputStreamReader (getClass().getResourceAsStream("/public/javascripts/app.js")));
I don't want to translate this to clojure since that's bound to end in failure.
EDIT2:
Well then here's an attempt then:
(defn create-engine
"Creates a new nashorn script engine and loads dependencies into its context."
[dependencies]
(let [nashorn (.getEngineByName (ScriptEngineManager.) "nashorn")]
(.eval nashorn "var global = this;")
(doseq [dependency dependencies] (.eval nashorn (new InputStreamReader (.getResourceAsStream String dependency))))
nashorn))
I shall not be held responsible if this starts the nuclear war or something
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With