diff --git a/crates/backend/src/ast.rs b/crates/backend/src/ast.rs index aeb56ccba71..c54a27be021 100644 --- a/crates/backend/src/ast.rs +++ b/crates/backend/src/ast.rs @@ -227,7 +227,7 @@ pub struct Struct { #[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))] #[derive(Clone)] pub struct StructField { - pub name: Ident, + pub name: syn::Member, pub struct_name: Ident, pub readonly: bool, pub ty: syn::Type, diff --git a/crates/backend/src/encode.rs b/crates/backend/src/encode.rs index b0cc9cb6a31..ae8d4cd396c 100644 --- a/crates/backend/src/encode.rs +++ b/crates/backend/src/encode.rs @@ -332,7 +332,10 @@ fn shared_struct<'a>(s: &'a ast::Struct, intern: &'a Interner) -> Struct<'a> { fn shared_struct_field<'a>(s: &'a ast::StructField, intern: &'a Interner) -> StructField<'a> { StructField { - name: intern.intern(&s.name), + name: match &s.name { + syn::Member::Named(ident) => intern.intern(ident), + syn::Member::Unnamed(index) => intern.intern_str(&index.index.to_string()), + }, readonly: s.readonly, comments: s.comments.iter().map(|s| &**s).collect(), } diff --git a/crates/macro-support/src/parser.rs b/crates/macro-support/src/parser.rs index 998b6a8f817..165e76f4703 100644 --- a/crates/macro-support/src/parser.rs +++ b/crates/macro-support/src/parser.rs @@ -309,40 +309,37 @@ impl<'a> ConvertToAst for &'a mut syn::ItemStruct { .js_name() .map(|s| s.0.to_string()) .unwrap_or(self.ident.to_string()); - if let syn::Fields::Named(names) = &mut self.fields { - for field in names.named.iter_mut() { - match field.vis { - syn::Visibility::Public(..) => {} - _ => continue, - } - let name = match &field.ident { - Some(n) => n, - None => continue, - }; - - let attrs = BindgenAttrs::find(&mut field.attrs)?; - assert_not_variadic(&attrs)?; - if attrs.skip().is_some() { - attrs.check_used()?; - continue; - } + for (i, field) in self.fields.iter_mut().enumerate() { + match field.vis { + syn::Visibility::Public(..) => {} + _ => continue, + } + let (name_str, member) = match &field.ident { + Some(ident) => (ident.to_string(), syn::Member::Named(ident.clone())), + None => (i.to_string(), syn::Member::Unnamed(i.into())), + }; - let comments = extract_doc_comments(&field.attrs); - let name_str = name.to_string(); - let getter = shared::struct_field_get(&js_name, &name_str); - let setter = shared::struct_field_set(&js_name, &name_str); - - fields.push(ast::StructField { - name: name.clone(), - struct_name: self.ident.clone(), - readonly: attrs.readonly().is_some(), - ty: field.ty.clone(), - getter: Ident::new(&getter, Span::call_site()), - setter: Ident::new(&setter, Span::call_site()), - comments, - }); + let attrs = BindgenAttrs::find(&mut field.attrs)?; + assert_not_variadic(&attrs)?; + if attrs.skip().is_some() { attrs.check_used()?; + continue; } + + let comments = extract_doc_comments(&field.attrs); + let getter = shared::struct_field_get(&js_name, &name_str); + let setter = shared::struct_field_set(&js_name, &name_str); + + fields.push(ast::StructField { + name: member, + struct_name: self.ident.clone(), + readonly: attrs.readonly().is_some(), + ty: field.ty.clone(), + getter: Ident::new(&getter, Span::call_site()), + setter: Ident::new(&setter, Span::call_site()), + comments, + }); + attrs.check_used()?; } let comments: Vec = extract_doc_comments(&self.attrs); attrs.check_used()?; diff --git a/examples/guide-supported-types-examples/exported_types.js b/examples/guide-supported-types-examples/exported_types.js index 7c60aea8e3d..8119fecee14 100644 --- a/examples/guide-supported-types-examples/exported_types.js +++ b/examples/guide-supported-types-examples/exported_types.js @@ -1,14 +1,22 @@ import { - ExportedRustType, - exported_type_by_value, - exported_type_by_shared_ref, - exported_type_by_exclusive_ref, - return_exported_type, + ExportedNamedStruct, + named_struct_by_value, + named_struct_by_shared_ref, + named_struct_by_exclusive_ref, + return_named_struct, + + ExportedTupleStruct, + return_tuple_struct } from './guide_supported_types_examples'; -let rustThing = return_exported_type(); -console.log(rustThing instanceof ExportedRustType); // true +let namedStruct = return_named_struct(42); +console.log(namedStruct instanceof ExportedNamedStruct); // true +console.log(namedStruct.inner); // 42 + +named_struct_by_value(namedStruct); +named_struct_by_shared_ref(namedStruct); +named_struct_by_exclusive_ref(namedStruct); -exported_type_by_value(rustThing); -exported_type_by_shared_ref(rustThing); -exported_type_by_exclusive_ref(rustThing); +let tupleStruct = return_tuple_struct(10, 20); +console.log(tupleStruct instanceof ExportedTupleStruct); // true +console.log(tupleStruct[0], tupleStruct[1]); // 10, 20 diff --git a/examples/guide-supported-types-examples/src/exported_types.rs b/examples/guide-supported-types-examples/src/exported_types.rs index 963cb520d9c..fb1ef1fcba2 100644 --- a/examples/guide-supported-types-examples/src/exported_types.rs +++ b/examples/guide-supported-types-examples/src/exported_types.rs @@ -1,20 +1,28 @@ use wasm_bindgen::prelude::*; #[wasm_bindgen] -pub struct ExportedRustType { - inner: u32, +pub struct ExportedNamedStruct { + pub inner: u32, } #[wasm_bindgen] -pub fn exported_type_by_value(x: ExportedRustType) {} +pub fn named_struct_by_value(x: ExportedNamedStruct) {} #[wasm_bindgen] -pub fn exported_type_by_shared_ref(x: &ExportedRustType) {} +pub fn named_struct_by_shared_ref(x: &ExportedNamedStruct) {} #[wasm_bindgen] -pub fn exported_type_by_exclusive_ref(x: &mut ExportedRustType) {} +pub fn named_struct_by_exclusive_ref(x: &mut ExportedNamedStruct) {} #[wasm_bindgen] -pub fn return_exported_type() -> ExportedRustType { - unimplemented!() +pub fn return_named_struct(inner: u32) -> ExportedNamedStruct { + ExportedNamedStruct { inner } +} + +#[wasm_bindgen] +pub struct ExportedTupleStruct(pub u32, pub u32); + +#[wasm_bindgen] +pub fn return_tuple_struct(x: u32, y: u32) -> ExportedTupleStruct { + ExportedTupleStruct(x, y) } diff --git a/tests/wasm/classes.js b/tests/wasm/classes.js index 995e87dde93..86de4727457 100644 --- a/tests/wasm/classes.js +++ b/tests/wasm/classes.js @@ -137,6 +137,7 @@ exports.js_js_rename = () => { exports.js_access_fields = () => { assert.ok((new wasm.AccessFieldFoo()).bar instanceof wasm.AccessFieldBar); + assert.ok((new wasm.AccessField0())[0] instanceof wasm.AccessFieldBar); }; exports.js_renamed_export = () => { diff --git a/tests/wasm/classes.rs b/tests/wasm/classes.rs index be167058c62..ee904c0514a 100644 --- a/tests/wasm/classes.rs +++ b/tests/wasm/classes.rs @@ -369,6 +369,9 @@ pub struct AccessFieldFoo { pub bar: AccessFieldBar, } +#[wasm_bindgen] +pub struct AccessField0(pub AccessFieldBar); + #[wasm_bindgen] #[derive(Copy, Clone)] pub struct AccessFieldBar { @@ -385,6 +388,14 @@ impl AccessFieldFoo { } } +#[wasm_bindgen] +impl AccessField0 { + #[wasm_bindgen(constructor)] + pub fn new() -> AccessField0 { + AccessField0(AccessFieldBar { _value: 2 }) + } +} + #[wasm_bindgen_test] fn access_fields() { js_access_fields();