Fix #[wasm_bindgen] on structs with no exports

It should still be usable in other types!

Closes #27
This commit is contained in:
Alex Crichton 2018-02-16 13:49:53 -08:00
parent c148a3b6dc
commit 7802535948
3 changed files with 60 additions and 11 deletions

View File

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

View File

@ -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::<BTreeSet<_>>();
a.list(&names, |s, a| {
let val = shared::name_to_descriptor(s.as_ref());

View File

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