pass object/class as parameter
How can you create a function like this in js?
function a(res) {
res.setA(42);
}
The only work around i foun was to create a type in rust like this:
#[napi] pub type Test = fn(res: &mut Response);
but has a problem #[napi] can only be applied to a function, struct, enum, const, mod or impl.
What should I do?
See https://github.com/napi-rs/napi-rs/blob/main/examples/napi/src/function.rs for example
See https://github.com/napi-rs/napi-rs/blob/main/examples/napi/src/function.rs for example
I tried something following the link provided:
#[derive(Debug, Clone, Copy)]
#[napi]
pub struct Res {
a: i32,
}
#[napi]
impl Res {
#[napi(constructor)]
pub fn new() -> Res {
Res { a: 0 }
}
#[napi]
pub fn set_a(&mut self, a: i32) {
self.a = a;
}
}
#[napi]
pub fn call(path: String, callback: Function<Rc<Res>, ()>) -> () {
let response: Res = Res::new();
let x = Rc::new(response);
let y = Rc::clone(&x);
println!("RUST#1 {:?}", response);
callback.call(x).unwrap();
println!("RUST#2 {:?}", y);
}
I need to pass the object as a parameter but then after all the function has done its things the parameter should be again return to rust code.
I also tried using Function<Rc<RefCell<Res>>, ()>) but the trait bound Rc<RefCell<Res>>: ToNapiValue is not satisfied
Another weird fact is the console.log visualization of the object.
JS code:
const { call } = require('./index')
call("/path", (res) => {
res.setA(66);
console.log('res1:', res);
res.a = 55;
console.log('res2:', res);
})
Here is all the logs:
RUST#1 Res { a: 0 }
res1: Res {}
res2: Res { a: 55 }
RUST#2 Res { a: 0 }
Why on the first console.log res1 the log does not include the a value after being set with the method setA? But on the second log explicitly setting with res.a = 55; it does appear in the log?
I also tried all methods in the linked file. Some of witch neither worked env.spawn_future_with_callback no method named spawn_future_with_callback found for struct Env and callback.build_threadsafe_function() no method named build_threadsafe_function found for struct napi::bindgen_prelude::Function
Passing Rc<T> from rust side to js side is actually passing a cloned value. So any mutation on one side will not affect the other.
A simple solution is to pass a napi object to js side and pass the mutated one back.
#[derive(Debug)]
#[napi(object)]
pub struct Res {
pub a: i32,
}
#[napi]
pub fn call(path: String, callback: Function<Res, Res>) -> () {
let response = Res { a: 0 };
println!("RUST#1 {:?}", response);
let response = callback.call(response).unwrap();
println!("RUST#2 {:?}", response);
}
const { call } = require("./index");
call("/path", (res) => {
console.log("res:", res);
res.a = 55;
console.log("res:", res);
return res;
});
results:
RUST#1 Res { a: 0 }
res: { a: 0 }
res: { a: 55 }
RUST#2 Res { a: 55 }