Skip to content

Generate bindings for indexed struct properties #1467

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/backend/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 4 additions & 1 deletion crates/backend/src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
}
Expand Down
59 changes: 28 additions & 31 deletions crates/macro-support/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,40 +309,37 @@ impl<'a> ConvertToAst<BindgenAttrs> 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<String> = extract_doc_comments(&self.attrs);
attrs.check_used()?;
Expand Down
28 changes: 18 additions & 10 deletions examples/guide-supported-types-examples/exported_types.js
Original file line number Diff line number Diff line change
@@ -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
22 changes: 15 additions & 7 deletions examples/guide-supported-types-examples/src/exported_types.rs
Original file line number Diff line number Diff line change
@@ -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)
}
1 change: 1 addition & 0 deletions tests/wasm/classes.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = () => {
Expand Down
11 changes: 11 additions & 0 deletions tests/wasm/classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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();
Expand Down