Support returning custom types in imports (#350)

Closes #320
This commit is contained in:
Alex Crichton 2018-06-28 20:08:02 -05:00 committed by GitHub
parent 4138583dff
commit 9a3ff77ea9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 85 additions and 4 deletions

View File

@ -298,6 +298,26 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
);
return Ok(());
}
if let Some(class) = ty.rust_struct() {
if ty.is_by_ref() {
bail!("cannot invoke JS functions returning custom ref types yet")
}
// Insert an assertion to the type of the returned value as
// otherwise this will cause memory unsafety on the Rust side of
// things.
self.ret_expr = format!("\
const val = JS;
if (!(val instanceof {0})) {{
throw new Error('expected value of type {0}');
}}
const ret = val.ptr;
val.ptr = 0;
return ret;\
", class);
return Ok(())
}
self.ret_expr = match *ty {
Descriptor::Boolean => "return JS ? 1 : 0;".to_string(),
Descriptor::Char => "return JS.codePointAt(0);".to_string(),
@ -337,9 +357,9 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
invoc = format!(
"\
try {{\n\
{}
{}
}} catch (e) {{\n\
{}
{}
}}\
",
&invoc, catch
@ -350,9 +370,9 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
invoc = format!(
"\
try {{\n\
{}
{}
}} finally {{\n\
{}
{}
}}\
",
&invoc, &self.finally

View File

@ -607,3 +607,64 @@ fn rust_keyword2() {
)
.test();
}
#[test]
fn custom_type() {
project()
.debug(false)
.file("src/lib.rs", r#"
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "./test")]
extern {
fn foo(f: Foo) -> Foo;
fn bad2() -> Foo;
}
#[wasm_bindgen]
pub struct Foo(());
#[wasm_bindgen]
impl Foo {
pub fn touch(&self) {
panic!()
}
}
#[wasm_bindgen]
pub fn run() {
foo(Foo(()));
}
#[wasm_bindgen]
pub fn bad() {
bad2();
}
"#)
.file("test.ts", r#"
import * as assert from "assert";
import { run, Foo, bad } from "./out";
let VAL: any = null;
export function foo(f: Foo): Foo {
VAL = f;
return f;
}
export function bad2(): number {
return 2;
}
export function test() {
run();
assert.throws(() => VAL.touch(), /Attempt to use a moved value/);
assert.throws(bad, /expected value of type Foo/);
}
"#)
.test();
}