Skip to content

Nested Class changes ignored because generated getter clones #532

@io12

Description

@io12

The assert in the following code fails because the auto-generated getter from rquickjs::class clones the field, which makes changes to nested attributes get ignored.

quote! {
#crate_name::object::Accessor::new_get(
|this: #crate_name::function::This<#crate_name::class::OwnedBorrow<'js, Self>>|{
this.0.#field.clone()
},
)
}

[package]
name = "rquickjs-bug"
version = "0.1.0"
edition = "2024"

[dependencies]
rquickjs = { version = "0.9.0", features = ["macro"] }
use rquickjs::{class::Trace, Class, JsLifetime, Object};

#[derive(Trace, JsLifetime, Default, Clone)]
#[rquickjs::class]
struct A {
    #[qjs(get)]
    b: B,
}

#[derive(Trace, JsLifetime, Default, Clone)]
#[rquickjs::class]
struct B {
    #[qjs(get, set)]
    c: String,
}

fn main() {
    let rt = rquickjs::Runtime::new().unwrap();
    let ctx = rquickjs::Context::full(&rt).unwrap();

    ctx.with(|ctx| {
        let a = A {
            b: B {
                c: "my string".into(),
            },
        };
        let cls = Class::instance(ctx.clone(), a).unwrap();
        let val = cls.into_value();
        let obj = val.as_object().unwrap();

        // Set obj.b.c = "other string"
        obj.get::<_, Object>("b")
            .unwrap()
            .set("c", "other string")
            .unwrap();

        // Get obj.b.c
        let c = obj
            .get::<_, Object>("b")
            .unwrap()
            .get::<_, String>("c")
            .unwrap();

        // Bug: obj.b.c still has "my string"
        assert_eq!(c.as_str(), "other string");
    });
}

Metadata

Metadata

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions