CertainLach/jrsonnet

I want to implement async function as native function in jsonnet how can I ? Please could you help

redoC-A2k opened this issue · 5 comments

Here's where I am implementing trait - https://github.com/redoC-A2k/EdgeChains/blob/abb2398ec030ee43817324fbbfc2993e6620e08c/JS/jsonnet/src/lib.rs#L227

We are using wasm bindgen and executing native js function in jsonnet . Normal function works fine but async functions do not .

Jsonnet is synchronous
It is possible to implement async imports, but not async functions

It might be possible to extend jsonnet for polling (Pending error, which wouldn't be cached), but what's your use-case?

I have overriden call method of NativeCallbackHandler ,

#[wasm_bindgen]
pub fn get_func(name: &str) -> Option<js_sys::Function> {
    unsafe {
        let func = map_struct.as_mut().unwrap().func_map.get(name);
        match func {
            Some(f) => Some(f.clone()),
            None => None,
        }
    }
}

#[wasm_bindgen]
pub fn set_func(name: String, func: js_sys::Function) {
    unsafe {
        map_struct.as_mut().unwrap().func_map.insert(name, func);
    }
}

#[derive(jrsonnet_gcmodule::Trace)]
struct NativeJSCallback(String);

impl NativeCallbackHandler for NativeJSCallback {
    fn call(&self, args: &[Val]) -> jrsonnet_evaluator::Result<Val> {
        let this = JsValue::null();
        let func = get_func(&self.0).expect("Function not found");
        let result;
        if args.len() > 0 {
            result = func.call1(
                &this,
                &JsValue::from_str(
                    &serde_json::to_string(args).expect("Error converting args to JSON"),
                ),
            );
        } else {
            result = func.call0(&this);
        }
        println!("Result of calling JS function: {:?}", result);
        if let Ok(r) = result {
            Ok(Val::Str(r.as_string().unwrap().into()))
        } else {
            Err(ErrorKind::RuntimeError("Error calling JS function".into()).into())
        }
    }
}

But the issue is in case of normal js function it works fine but when some js function returns promise , I want to return resolved promise value from call method . Which I am not being able to do , I tried polling but it didn't worked when I compiled the rust to wasm using wasm-pack .

Jrsonnet is synchronous.
You can't call an async function from sync code unless you execute this function in another thread (or climb the stack up and poll jrsonnet code until it will be able to get already executed function output synchronously, I can write an example for that), and that is not possible with JS and WASM. (Ok, in fact there is some other solutions for waiting for promise synchronously, but they have large limitations, only try to use them if you understand the limitations:
https://github.com/jimmywarting/await-sync)

It might be possible in some cases to replace synchronous function call with asynchronous import (which jrsonnet supports), I.e it is not possible to implement myStd.fetch("http://...") in JS, but it is possible to do it using import "http://...", because imports might be async: https://github.com/CertainLach/jrsonnet/blob/master/crates/jrsonnet-evaluator/src/async_import.rs#L294

Thanks a lot for your help , for now we have used sync-rpc library to make asynchronous function synchronous in nodejs .