Skip to content

Commit

Permalink
Merge pull request #952 from alexcrichton/field-export
Browse files Browse the repository at this point in the history
Fix bindings for classes only referenced through struct fields
  • Loading branch information
alexcrichton authored Oct 10, 2018
2 parents fe35750 + f6cb734 commit 70e1370
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 58 deletions.
115 changes: 57 additions & 58 deletions crates/cli-support/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,6 @@ pub struct ExportedClass {
typescript: String,
has_constructor: bool,
wrap_needed: bool,
fields: Vec<ClassField>,
}

struct ClassField {
comments: Vec<String>,
name: String,
readonly: bool,
}

pub struct SubContext<'a, 'b: 'a> {
Expand Down Expand Up @@ -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) {{
Expand Down Expand Up @@ -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(())
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions tests/wasm/classes.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
28 changes: 28 additions & 0 deletions tests/wasm/classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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();
}

0 comments on commit 70e1370

Please sign in to comment.