Merge pull request #77 from dflemstr/wasm-construct-js-class

Add support for constructing JsValue instances generically
This commit is contained in:
Alex Crichton 2018-04-03 16:08:30 +02:00 committed by GitHub
commit bb2e0c205f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 106 additions and 9 deletions

View File

@ -88,6 +88,7 @@ impl ToTokens for ast::Program {
impl ToTokens for ast::Struct {
fn to_tokens(&self, tokens: &mut Tokens) {
let name = &self.name;
let new_fn = syn::Ident::from(shared::new_function(self.name.as_ref()));
let free_fn = syn::Ident::from(shared::free_function(self.name.as_ref()));
let c = shared::name_to_descriptor(name.as_ref());
let descriptor = Literal::byte_string(format!("{:4}", c).as_bytes());
@ -153,6 +154,28 @@ impl ToTokens for ast::Struct {
}
}
impl ::std::convert::From<#name> for ::wasm_bindgen::JsValue {
fn from(value: #name) -> Self {
let ptr = ::wasm_bindgen::convert::WasmBoundary::into_abi(
value,
unsafe { &mut ::wasm_bindgen::convert::GlobalStack::new() },
);
#[wasm_import_module = "__wbindgen_placeholder__"]
extern {
fn #new_fn(ptr: u32) -> u32;
}
unsafe {
<::wasm_bindgen::JsValue as ::wasm_bindgen::convert::WasmBoundary>
::from_abi(
#new_fn(ptr),
unsafe { &mut ::wasm_bindgen::convert::GlobalStack::new() },
)
}
}
}
#[no_mangle]
pub unsafe extern fn #free_fn(ptr: u32) {
<#name as ::wasm_bindgen::convert::WasmBoundary>::from_abi(

View File

@ -266,6 +266,15 @@ impl<'a> Context<'a> {
}}
"));
ts_dst.push_str("constructor(ptr: number, sym: Symbol);\n");
let new_name = shared::new_function(&class);
if self.wasm_import_needed(&new_name) {
self.globals.push_str(&format!("
export function {new_name}(ptr) {{
return addHeapObject(new {class}(ptr, token));
}}
", new_name = new_name, class = class));
}
} else {
dst.push_str(&format!("
constructor(ptr) {{
@ -273,6 +282,15 @@ impl<'a> Context<'a> {
}}
"));
ts_dst.push_str("constructor(ptr: number);\n");
let new_name = shared::new_function(&class);
if self.wasm_import_needed(&new_name) {
self.globals.push_str(&format!("
export function {new_name}(ptr) {{
return addHeapObject(new {class}(ptr));
}}
", new_name = new_name, class = class));
}
}
dst.push_str(&format!("

View File

@ -88,6 +88,15 @@ pub struct CustomTypeName {
pub name: String,
}
pub fn new_function(struct_name: &str) -> String {
let mut name = format!("__wbg_");
name.extend(struct_name
.chars()
.flat_map(|s| s.to_lowercase()));
name.push_str("_new");
return name
}
pub fn free_function(struct_name: &str) -> String {
let mut name = format!("__wbg_");
name.extend(struct_name

View File

@ -95,7 +95,7 @@ impl JsValue {
}
// #[doc(hidden)]
// pub fn __from_idx(idx: u32) -> JsValue {
// pub unsafe fn __from_idx(idx: u32) -> JsValue {
// JsValue { idx }
// }
//

View File

@ -4,7 +4,7 @@ extern crate test_support;
fn simple() {
test_support::project()
.file("src/lib.rs", r#"
#![feature(proc_macro, wasm_custom_section)]
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
extern crate wasm_bindgen;
@ -56,7 +56,7 @@ fn simple() {
fn strings() {
test_support::project()
.file("src/lib.rs", r#"
#![feature(proc_macro, wasm_custom_section)]
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
extern crate wasm_bindgen;
@ -114,7 +114,7 @@ fn strings() {
fn exceptions() {
test_support::project()
.file("src/lib.rs", r#"
#![feature(proc_macro, wasm_custom_section)]
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
extern crate wasm_bindgen;
@ -179,7 +179,7 @@ fn exceptions() {
fn pass_one_to_another() {
test_support::project()
.file("src/lib.rs", r#"
#![feature(proc_macro, wasm_custom_section)]
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
extern crate wasm_bindgen;
@ -276,7 +276,7 @@ fn pass_into_js() {
fn issue_27() {
test_support::project()
.file("src/lib.rs", r#"
#![feature(proc_macro, wasm_custom_section)]
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
@ -314,3 +314,50 @@ fn issue_27() {
"#)
.test();
}
#[test]
fn pass_into_js_as_js_class() {
test_support::project()
.file("src/lib.rs", r#"
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Foo(i32);
#[wasm_bindgen]
impl Foo {
pub fn inner(&self) -> i32 {
self.0
}
}
#[wasm_bindgen(module = "./test")]
extern {
fn take_foo(foo: JsValue);
}
#[wasm_bindgen]
pub fn run() {
take_foo(Foo(13).into());
}
"#)
.file("test.ts", r#"
import { run, Foo } from "./out";
import * as assert from "assert";
export function take_foo(foo: any) {
assert(foo instanceof Foo);
assert.strictEqual(foo.inner(), 13);
foo.free();
}
export function test() {
run();
}
"#)
.test();
}

View File

@ -6,7 +6,7 @@ fn dependencies_work() {
.file(
"src/lib.rs",
r#"
#![feature(proc_macro, wasm_custom_section)]
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
extern crate wasm_bindgen;
extern crate dependency;
use wasm_bindgen::prelude::*;
@ -51,7 +51,7 @@ fn dependencies_work() {
.file(
"vendor/dependency/src/lib.rs",
r#"
#![feature(proc_macro, wasm_custom_section)]
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;

View File

@ -5,7 +5,7 @@ fn works() {
test_support::project()
.debug(false)
.file("src/lib.rs", r#"
#![feature(proc_macro, wasm_custom_section)]
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
extern crate wasm_bindgen;