Closed rahul007-bit closed 3 months ago
Hi @rahul007-bit, even though a pattern like this doesn't exist today in Javy, in theory we could explose a class
macro (or similar) that allows you to achieve a similar behavior. Do you have a specific use-case in mind?
I am working on a project that utilizes Jsonnet, but unfortunately, it is not compatible with QuickJS. Therefore, I am attempting to integrate it as a built-in module within the runtime environment. At present, I am implementing this integration using the eval_module
and set_property
functions.
Here is the Rust code snippet I am currently employing:
static JSONNET: &str = include_str!("./index.js");
pub(super) struct Jsonnet;
impl JSApiSet for Jsonnet {
fn register(&self, runtime: &javy::Runtime, _config: &crate::APIConfig) -> anyhow::Result<()> {
let context = runtime.context();
let global = context.global_object()?;
global.set_property(
"__jsonnet_evaluate_snippet",
context.wrap_callback(jsonnet_evaluate_snippet_callback())?,
)?;
if let Err(err) = context.eval_module("jsonnet", JSONNET) {
eprintln!("Error loading the path shim: {:?}", err);
}
Ok(())
}
}
And here is the JavaScript class definition that corresponds to the Rust implementation:
const __jsonnet_evaluate_snippet = globalThis.__jsonnet_evaluate_snippet;
class Jsonnet {
evaluateSnippet(snippet) {
return __jsonnet_evaluate_snippet(snippet);
}
}
Reflect.deleteProperty(globalThis, "__jsonnet_evaluate_snippet");
export default Jsonnet;
However, when I attempt to import this module in JavaScript, the application encounters an error and crashes.
import Jsonnet from "jsonnet";
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
return new Response("Hello world", { status: 200 });
}
For further reference or testing, you may refer to this GitHub repository.
It would be very helpful if you could provide me with some guidance on how to resolve the import issue or suggest alternative approaches to integrating Jsonnet with QuickJS.
Getting imports to work in the way you've defined your program is a bit tricky, but given that you've evaluated the index.js
source as
if let Err(err) = context.eval_module("jsonnet", JSONNET) {
I suspect that if you're not seeing an error there, you should be able to use Jsonnet.evaluateSnippet
in your JS program, without having to import it. Have you tried removing the import and attaching your Jsonnet class to the global scope?
Thank you for your reply!
I tried using __jsonnet_evaluate_snippet
without importing it, which worked as expected in this case. However, when I attempt to evaluate it as a module and then import it, the program crashes at context.eval_binary
and this function is called here. Is there any way to achieve this behavior?
Can you provide a bit more details about how is it crashing? It's likely that Jsonnet, uses or imports features that are not currently supported by Javy, that would be my first guess, but it's difficult to say without more details.
Yes, the issue was related to the jsonnet package that I was using in the API, and when I moved it to cli folder it worked perfectly, there was some issue with memory out of bound which I use in the wasm coredump.
in theory we could expose a class macro (or similar)
can you share anything that can help me to do this?
A high-level view of how I envision this feature:
JSClass
trait to allow Rust-backed JS classes to QuickJS; the trait should expose at least the following methods: constructor
, prototype
, class_id
. JS_IsRegistered
and JSClassDef
apis from QuickJS. Note that the macro, is simply a suggestion to make the implementation of this trait easier on consumers, but not something to be considered critical for this to work IMO.
With https://github.com/bytecodealliance/javy/pull/618 merged, this is now possible. I'm going to ahead and close this issue, but feel free to follow up with questions and / or comments.
I found a line in AWS LLRT and was wondering if we can do the same in Javy too, create a struct that JS can access as a class.