diff --git a/crates/wasm-bindgen-cli-support/src/js.rs b/crates/wasm-bindgen-cli-support/src/js.rs index 65f12feb..a6db0f32 100644 --- a/crates/wasm-bindgen-cli-support/src/js.rs +++ b/crates/wasm-bindgen-cli-support/src/js.rs @@ -35,13 +35,11 @@ pub struct SubContext<'a, 'b: 'a> { impl<'a> Context<'a> { pub fn add_custom_type_names(&mut self, program: &shared::Program) { for custom in program.custom_type_names.iter() { - assert!(self.custom_type_names.insert(custom.descriptor, - custom.name.clone()).is_none()); - let val = custom.descriptor as u32; - assert!(val & 1 == 0); - let descriptor = char::from_u32(val | 1).unwrap(); - assert!(self.custom_type_names.insert(descriptor, - custom.name.clone()).is_none()); + let prev = self.custom_type_names.insert(custom.descriptor, + custom.name.clone()); + if let Some(prev) = prev { + assert_eq!(prev, custom.name); + } } } @@ -636,6 +634,12 @@ impl<'a> Context<'a> { i.module() == "env" && i.field() == name }) } + + fn custom_type_name(&self, c: char) -> &str { + let c = (c as u32) & !shared::TYPE_CUSTOM_REF_FLAG; + let c = char::from_u32(c).unwrap(); + &self.custom_type_names[&c] + } } impl<'a, 'b> SubContext<'a, 'b> { @@ -772,7 +776,7 @@ impl<'a, 'b> SubContext<'a, 'b> { pass(&format!("idx{}", i)); } custom if (custom as u32) & shared::TYPE_CUSTOM_REF_FLAG != 0 => { - let s = self.cx.custom_type_names[&custom].clone(); + let s = self.cx.custom_type_name(custom).to_string(); dst_ts.push_str(&format!(": {}", s)); if self.cx.config.debug { self.cx.expose_assert_class(); @@ -783,7 +787,7 @@ impl<'a, 'b> SubContext<'a, 'b> { pass(&format!("{}.ptr", name)); } custom => { - let s = self.cx.custom_type_names[&custom].clone(); + let s = self.cx.custom_type_name(custom).to_string(); dst_ts.push_str(&format!(": {}", s)); if self.cx.config.debug { self.cx.expose_assert_class(); @@ -836,8 +840,8 @@ impl<'a, 'b> SubContext<'a, 'b> { Some(shared::TYPE_JS_REF) | Some(shared::TYPE_BORROWED_STR) => panic!(), Some(t) if (t as u32) & shared::TYPE_CUSTOM_REF_FLAG != 0 => panic!(), - Some(ref custom) => { - let name = &self.cx.custom_type_names[custom]; + Some(custom) => { + let name = self.cx.custom_type_name(custom); dst_ts.push_str(": "); dst_ts.push_str(name); if self.cx.config.debug { diff --git a/crates/wasm-bindgen-macro/src/ast.rs b/crates/wasm-bindgen-macro/src/ast.rs index 552ab9e4..f3e74ef7 100644 --- a/crates/wasm-bindgen-macro/src/ast.rs +++ b/crates/wasm-bindgen-macro/src/ast.rs @@ -289,6 +289,7 @@ impl Program { ("custom_type_names", &|a| { let names = self.exports.iter() .filter_map(|e| e.class) + .chain(self.structs.iter().map(|s| s.name)) .collect::>(); a.list(&names, |s, a| { let val = shared::name_to_descriptor(s.as_ref()); diff --git a/tests/classes.rs b/tests/classes.rs index e4738491..2e520f88 100644 --- a/tests/classes.rs +++ b/tests/classes.rs @@ -224,3 +224,47 @@ fn pass_one_to_another() { "#) .test(); } + +#[test] +fn issue_27() { + test_support::project() + .file("src/lib.rs", r#" + #![feature(proc_macro)] + + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + + #[wasm_bindgen] + pub struct Context {} + + #[wasm_bindgen] + impl Context { + pub fn parse(&self, expr: &str) -> Expr { + panic!() + } + pub fn eval(&self, expr: &Expr) -> f64 { + panic!() + } + pub fn set(&mut self, var: &str, val: f64) { + panic!() + } + } + + #[wasm_bindgen] + pub struct Expr {} + + #[wasm_bindgen] + #[no_mangle] + pub extern fn context() -> Context { + Context {} + } + "#) + .file("test.ts", r#" + import { context } from "./out"; + + export function test() { + context(); + } + "#) + .test(); +}