DelSkayn / rquickjs

High level bindings to the quickjs javascript engine
MIT License
504 stars 63 forks source link

How to return same js instance from a rust function? #172

Closed richarddd closed 1 year ago

richarddd commented 1 year ago

Example:

fn update<'js>(&self, ctx: Ctx<'js>, value: Value<'js>) -> Result<Value<'js>> {
        let bytes = get_bytes(ctx, value)?;
        self.context.update(&bytes);
        self.into_js(ctx)
    }

self.into_js(ctx) creates a new instance. How can i return the original one?

DelSkayn commented 1 year ago

Instead of taking the self instances as &self you can retrieve the this value as its javascript object by taking it as This<Class<'js,Self>>. You can return that object without any problems.

richarddd commented 1 year ago

Any idea how would this be done using the new proc macro? :) Or do i need to manually implement the JsClass trait?

Example:

#[rquickjs::class]
#[derive(rquickjs::class::Trace)]
struct TestClass {
    #[qjs(skip_trace)]
    value: String,
}

#[rquickjs::methods]
impl TestClass {
    #[qjs(constructor)]
    pub fn new(value: String) -> Self {
        Self { value }
    }

    pub fn append<'js>(this: This<Class<'js, Self>>, data: String) -> Class<'js, Self> {
        this.0
    }
}

the trait bound __impl_append: JsClass<'js> is not satisfied the following other types implement trait JsClass<'js>: RustFunction<'js> TestClass

Also tried with:

pub fn append<'js>(self, data: String) -> Self {
    self
}

Which results in:

the trait bound rquickjs::function::This<TestClass>: FromParam<'_> is not satisfied the trait FromParam<'js> is implemented for rquickjs::function::This<T>

DelSkayn commented 1 year ago

This seems to be a bug in the macro, It works if you use the resolved type instead of Self. So Class<'js, TestClass> in the case of this example.

The macro doesn't replace Self with the right type when implementing IntoJsFunc for the method.

DelSkayn commented 1 year ago

Should now be fixed in fd957b8.