diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index 9f762cef..34756279 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -56,13 +56,6 @@ pub struct ExportedClass { typescript: String, has_constructor: bool, wrap_needed: bool, - fields: Vec, -} - -struct ClassField { - comments: Vec, - name: String, - readonly: bool, } pub struct SubContext<'a, 'b: 'a> { @@ -590,46 +583,6 @@ impl<'a> Context<'a> { )); } - for field in class.fields.iter() { - let wasm_getter = shared::struct_field_get(name, &field.name); - let wasm_setter = shared::struct_field_set(name, &field.name); - let descriptor = match self.describe(&wasm_getter) { - None => continue, - Some(d) => d, - }; - - let set = { - let mut cx = Js2Rust::new(&field.name, self); - cx.method(true, false) - .argument(&descriptor)? - .ret(&Descriptor::Unit)?; - ts_dst.push_str(&format!( - "{}{}: {}\n", - if field.readonly { "readonly " } else { "" }, - field.name, - &cx.js_arguments[0].1 - )); - cx.finish("", &format!("wasm.{}", wasm_setter)).0 - }; - let (get, _ts, js_doc) = Js2Rust::new(&field.name, self) - .method(true, false) - .ret(&descriptor)? - .finish("", &format!("wasm.{}", wasm_getter)); - if !dst.ends_with("\n") { - dst.push_str("\n"); - } - dst.push_str(&format_doc_comments(&field.comments, Some(js_doc))); - dst.push_str("get "); - dst.push_str(&field.name); - dst.push_str(&get); - dst.push_str("\n"); - if !field.readonly { - dst.push_str("set "); - dst.push_str(&field.name); - dst.push_str(&set); - } - } - self.global(&format!( " function free{}(ptr) {{ @@ -1748,17 +1701,7 @@ impl<'a, 'b> SubContext<'a, 'b> { self.generate_enum(e); } for s in self.program.structs.iter() { - let mut class = self - .cx - .exported_classes - .entry(s.name.clone()) - .or_insert_with(Default::default); - class.comments = format_doc_comments(&s.comments, None); - class.fields.extend(s.fields.iter().map(|f| ClassField { - name: f.name.clone(), - readonly: f.readonly, - comments: f.comments.clone(), - })); + self.generate_struct(s); } Ok(()) @@ -2116,6 +2059,62 @@ impl<'a, 'b> SubContext<'a, 'b> { self.cx.typescript.push_str("}\n"); } + fn generate_struct(&mut self, struct_: &shared::Struct) -> Result<(), Error> { + let mut dst = String::new(); + let mut ts_dst = String::new(); + for field in struct_.fields.iter() { + let wasm_getter = shared::struct_field_get(&struct_.name, &field.name); + let wasm_setter = shared::struct_field_set(&struct_.name, &field.name); + let descriptor = match self.cx.describe(&wasm_getter) { + None => continue, + Some(d) => d, + }; + + let set = { + let mut cx = Js2Rust::new(&field.name, self.cx); + cx.method(true, false) + .argument(&descriptor)? + .ret(&Descriptor::Unit)?; + ts_dst.push_str(&format!( + "{}{}: {}\n", + if field.readonly { "readonly " } else { "" }, + field.name, + &cx.js_arguments[0].1 + )); + cx.finish("", &format!("wasm.{}", wasm_setter)).0 + }; + let (get, _ts, js_doc) = Js2Rust::new(&field.name, self.cx) + .method(true, false) + .ret(&descriptor)? + .finish("", &format!("wasm.{}", wasm_getter)); + if !dst.ends_with("\n") { + dst.push_str("\n"); + } + dst.push_str(&format_doc_comments(&field.comments, Some(js_doc))); + dst.push_str("get "); + dst.push_str(&field.name); + dst.push_str(&get); + dst.push_str("\n"); + if !field.readonly { + dst.push_str("set "); + dst.push_str(&field.name); + dst.push_str(&set); + } + } + + let class = self + .cx + .exported_classes + .entry(struct_.name.clone()) + .or_insert_with(Default::default); + class.comments = format_doc_comments(&struct_.comments, None); + class.contents.push_str(&dst); + class.contents.push_str("\n"); + class.typescript.push_str(&ts_dst); + class.typescript.push_str("\n"); + Ok(()) + } + fn register_vendor_prefix( &mut self, info: &shared::ImportType, diff --git a/tests/wasm/classes.js b/tests/wasm/classes.js index ad09011d..4e0408bf 100644 --- a/tests/wasm/classes.js +++ b/tests/wasm/classes.js @@ -132,3 +132,7 @@ exports.js_js_rename = () => { (new wasm.JsRename()).bar(); wasm.classes_foo(); }; + +exports.js_access_fields = () => { + assert.ok((new wasm.AccessFieldFoo()).bar instanceof wasm.AccessFieldBar); +}; diff --git a/tests/wasm/classes.rs b/tests/wasm/classes.rs index c0b562f7..4ef3e18a 100644 --- a/tests/wasm/classes.rs +++ b/tests/wasm/classes.rs @@ -20,6 +20,7 @@ extern "C" { fn js_readonly_fields(); fn js_double_consume(); fn js_js_rename(); + fn js_access_fields(); } #[wasm_bindgen_test] @@ -351,3 +352,30 @@ impl JsRename { #[wasm_bindgen(js_name = classes_foo)] pub fn foo() {} + + +#[wasm_bindgen] +pub struct AccessFieldFoo { + pub bar: AccessFieldBar, +} + +#[wasm_bindgen] +#[derive(Copy, Clone)] +pub struct AccessFieldBar { + value: u32, +} + +#[wasm_bindgen] +impl AccessFieldFoo { + #[wasm_bindgen(constructor)] + pub fn new() -> AccessFieldFoo { + AccessFieldFoo { + bar: AccessFieldBar { value: 2 }, + } + } +} + +#[wasm_bindgen_test] +fn access_fields() { + js_access_fields(); +}