QuickJS is a small and embeddable JavaScript engine which supports the ES2023 specification.
I want to use it in Scala, for example, to create an interpreter and to execute some JavaScript code with it. I’m curious if anyone has tried this before? If not, how can I create bindings and make it into a Scala package?
Question number one: from where? I suspect (not knowing QuickJS aside from a quick look at the repo) that embedding it in ScalaJVM is a somewhat different project from doing so in ScalaNative, and that sort of depends on what you want to do with it.
Right, but the question remains, what kind of Scala you want to call it?
JVM Scala? If so, you need to look into JVM interop with native packages, something like JNI.
Or are you thinking in making your own native wrapper on top of it using ScalaNative? If so, I guess it should not differ from calling any other native library there.
Just to clarify this further, since it sometimes isn’t obvious to folks coming from other languages:
Scala is, intentionally, Just A Language. It specifically isn’t a full platform the way that something like JavaScript or Python (basically) are.
That’s why the question is ambiguous: Scala runs in a bunch of different places (in the JVM, natively on machines, or in the browser), and the answer is different depending on how you want to run it.
A quick check - you want to embed a JavaScript engine in a Scala application; so you want to run bits of JavaScript in it. Are you sure you want to run the application on the JVM?
I ask because if this is a new application with no constraints on it, perhaps you could use the JavaScript target toolchain for Scala and then call your bits of JavaScript directly.
If you really want to (or have to ) run your application on the JVM, then yes, JNI is for you….
…. however might want to try using SWIG (https://www.swig.org) to generate a Java API (it uses JNI under the hood). I’ve done this before to access C++ from Python. If it’s just a couple of C functions taking char * and int, then straight JNI is probably good enough, though.
Oh, I forgot - what about using Nashorn as an embedded JavaScript engine directly called from Scala? I’ll leave it to the JavaScript folks to opine on its suitability (my JavaScript experience is rudimentary).
It’s probable that someone already created a java wrapper around QuickJS with JNI. If that works you could just use that from scala instead of creating your own.
Yes. I want to do that. We’re developing a compiler which transpiles our language to JavaScript. We need to ensure that the generated code is syntactically correct and can run to achieve the expected results.
Our current approach is to spawn a Node.js process with REPL and send JavaScript code to its stdin and read results from its stdout. This solution can work properly at the moment, but our code interacting with the REPL is a bit dirty. The reason why we need REPL is that our generated code is executed block by block, so there’s no way to generate a complete JS file at once and then execute it with Node.js. Calling the JavaScript runtime directly from API is easier.
What’s more, Node.js is relatively cumbersome (it has too many built-in modules and the test requires specific versions). So I’m exploring using a relatively smaller JavaScript interpreter (and runtime) like QuickJS into our tests.
Thank you for your suggestion. I’m looking into SWIG and Nashorn.
Uhm I have zero experience with this, so this my be dumb, a bad idea, or plain wrong.
But can’t you generate a native executable on Graal that contains Graal itself.
Making your app self contained and not needing your users to install even Java.
I also have recently been looking to do the same thing as the original poster, and after much exploration have settled on the GraalVM approach. I am in early days here though, but the support seems substantive.
If your target is tooling then Graal Native Image is a good approach and is the path I am taking with a similar need.
We also have use case that requires embedding in JVM services and I’ve asked on the Graal slack channel and seen in their docs that they Graal polyglot support is a normal JVM library. In order to get the most out of this workload you want to have the Graal compiler performing JIT, but if you don’t, it should still work but be less performant. Run GraalVM JavaScript on a Stock JDK
You can see a thread where I ask about this here: Slack