Generate bindings for indexed struct properties

This allows to export fields of tuple-like structs as indexed JS properties.
This commit is contained in:
Ingvar Stepanyan 2019-04-16 20:31:25 +01:00
parent 10cbc789a8
commit 3a7d384dc8
5 changed files with 47 additions and 35 deletions

View File

@ -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,

View File

@ -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(),
}

View File

@ -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;
}
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,
});
attrs.check_used()?;
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 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()?;

View File

@ -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 = () => {

View File

@ -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();