From 294c5e147b724e7e5eef757ab497a97a7b1ba49e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 20 Dec 2017 10:22:18 -0800 Subject: [PATCH] Support passing booleans back and forth --- crates/wasm-bindgen-cli-support/src/ts.rs | 48 ++++++++++++++++++++++- crates/wasm-bindgen-macro/src/ast.rs | 3 ++ crates/wasm-bindgen-macro/src/lib.rs | 19 +++++++++ crates/wasm-bindgen-shared/src/lib.rs | 1 + tests/imports.rs | 10 +++++ tests/simple.rs | 9 ++++- 6 files changed, 87 insertions(+), 3 deletions(-) diff --git a/crates/wasm-bindgen-cli-support/src/ts.rs b/crates/wasm-bindgen-cli-support/src/ts.rs index a55baef2..23a8abe4 100644 --- a/crates/wasm-bindgen-cli-support/src/ts.rs +++ b/crates/wasm-bindgen-cli-support/src/ts.rs @@ -128,6 +128,14 @@ impl Js { arg_conversions.push_str(&format!("_assertNum({});\n", name)); pass(&name) } + shared::Type::Boolean => { + dst.push_str("boolean"); + self.expose_assert_bool(); + arg_conversions.push_str(&format!("\ + const bool{i} = _assertBoolean({name}); + ", name = name, i = i)); + pass(&format!("bool{i}", i = i)) + } shared::Type::BorrowedStr | shared::Type::String => { dst.push_str("string"); @@ -191,6 +199,10 @@ impl Js { dst.push_str("number"); format!("return ret;") } + Some(&shared::Type::Boolean) => { + dst.push_str("boolean"); + format!("return ret != 0;") + } Some(&shared::Type::JsObject) => { dst.push_str("any"); self.expose_take_object(); @@ -270,6 +282,11 @@ impl Js { invocation.push_str(&format!("arg{}", i)); dst.push_str(&format!("arg{}: number", i)); } + shared::Type::Boolean => { + ts_dst.push_str("boolean"); + invocation.push_str(&format!("arg{} != 0", i)); + dst.push_str(&format!("arg{}: number", i)); + } shared::Type::BorrowedStr => { ts_dst.push_str("string"); self.expose_get_string_from_wasm(); @@ -298,11 +315,18 @@ impl Js { } ts_dst.push_str("): "); dst.push_str("): "); + let mut convert = None; match import.ret { Some(shared::Type::Number) => { ts_dst.push_str("number"); dst.push_str("number"); } + Some(shared::Type::Boolean) => { + ts_dst.push_str("boolean"); + dst.push_str("number"); + convert = Some("_assertBoolean"); + self.expose_assert_bool(); + } None => { ts_dst.push_str("void"); dst.push_str("void"); @@ -311,7 +335,12 @@ impl Js { } ts_dst.push_str("\n"); dst.push_str(" {\n"); - dst.push_str(&format!("return _imports.{}({});\n}}", import.name, invocation)); + let invoc = format!("_imports.{}({})", import.name, invocation); + let invoc = match convert { + Some(s) => format!("{}({})", s, invoc), + None => invoc, + }; + dst.push_str(&format!("return {};\n}}", invoc)); self.imports.push((import.name.clone(), dst, ts_dst)); } @@ -773,6 +802,23 @@ impl Js { "); } + fn expose_assert_bool(&mut self) { + if !self.exposed_globals.insert("assert_bool") { + return + } + self.globals.push_str("\ + function _assertBoolean(n: boolean): number { + if (typeof(n) !== 'boolean') + throw new Error('expected a boolean argument'); + if (n) { + return 1; + } else { + return 0; + } + } + "); + } + fn expose_pass_string_to_wasm(&mut self) { if !self.exposed_globals.insert("pass_string_to_wasm") { return diff --git a/crates/wasm-bindgen-macro/src/ast.rs b/crates/wasm-bindgen-macro/src/ast.rs index d8e3ba51..070ac0dc 100644 --- a/crates/wasm-bindgen-macro/src/ast.rs +++ b/crates/wasm-bindgen-macro/src/ast.rs @@ -33,6 +33,7 @@ pub enum Type { RawConstPtr(syn::Ident), JsObject, JsObjectRef, + Boolean, } pub struct Struct { @@ -271,6 +272,7 @@ impl Type { "f64" => { Type::Integer(ident) } + "bool" => Type::Boolean, "String" => Type::String, "JsObject" => Type::JsObject, _ => Type::ByValue(ident), @@ -292,6 +294,7 @@ impl Type { Type::ByMutRef(n) => shared::Type::ByMutRef(n.to_string()), Type::JsObject => shared::Type::JsObject, Type::JsObjectRef => shared::Type::JsObjectRef, + Type::Boolean => shared::Type::Boolean, } } } diff --git a/crates/wasm-bindgen-macro/src/lib.rs b/crates/wasm-bindgen-macro/src/lib.rs index fde2d882..0e524515 100644 --- a/crates/wasm-bindgen-macro/src/lib.rs +++ b/crates/wasm-bindgen-macro/src/lib.rs @@ -189,6 +189,12 @@ fn bindgen(export_name: &syn::Lit, ast::Type::Integer(i) => { args.push(my_quote! { #ident: #i }); } + ast::Type::Boolean => { + args.push(my_quote! { #ident: u32 }); + arg_conversions.push(my_quote! { + let #ident = #ident != 0; + }); + } ast::Type::RawMutPtr(i) => { args.push(my_quote! { #ident: *mut #i }); } @@ -272,6 +278,10 @@ fn bindgen(export_name: &syn::Lit, ret_ty = my_quote! { -> #i }; convert_ret = my_quote! { #ret }; } + Some(&ast::Type::Boolean) => { + ret_ty = my_quote! { -> u32 }; + convert_ret = my_quote! { #ret as u32 }; + } Some(&ast::Type::RawMutPtr(i)) => { ret_ty = my_quote! { -> *mut #i }; convert_ret = my_quote! { #ret }; @@ -444,6 +454,11 @@ fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) { abi_arguments.push(my_quote! { #name: #i }); arg_conversions.push(my_quote! {}); } + ast::Type::Boolean => { + abi_argument_names.push(name); + abi_arguments.push(my_quote! { #name: u32 }); + arg_conversions.push(my_quote! { let #name = #name as u32; }); + } ast::Type::RawMutPtr(i) => { abi_argument_names.push(name); abi_arguments.push(my_quote! { #name: *mut #i }); @@ -495,6 +510,10 @@ fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) { abi_ret = my_quote! { #i }; convert_ret = my_quote! { #ret_ident }; } + Some(ast::Type::Boolean) => { + abi_ret = my_quote! { u32 }; + convert_ret = my_quote! { #ret_ident != 0 }; + } Some(ast::Type::RawConstPtr(i)) => { abi_ret = my_quote! { *const #i }; convert_ret = my_quote! { #ret_ident }; diff --git a/crates/wasm-bindgen-shared/src/lib.rs b/crates/wasm-bindgen-shared/src/lib.rs index eb228de5..65c77f17 100644 --- a/crates/wasm-bindgen-shared/src/lib.rs +++ b/crates/wasm-bindgen-shared/src/lib.rs @@ -65,6 +65,7 @@ pub enum Type { ByMutRef(String), JsObject, JsObjectRef, + Boolean, } impl Type { diff --git a/tests/imports.rs b/tests/imports.rs index 4a54ce6b..4f77678e 100644 --- a/tests/imports.rs +++ b/tests/imports.rs @@ -14,6 +14,7 @@ fn simple() { extern "JS" { fn foo(s: &str); fn another(a: u32) -> i32; + fn take_and_return_bool(a: bool) -> bool; } pub fn bar(s: &str) { foo(s); @@ -21,6 +22,9 @@ fn simple() { pub fn another_thunk(a: u32) -> i32 { another(a) } + pub fn bool_thunk(a: bool) -> bool { + take_and_return_bool(a) + } } "#) .file("test.ts", r#" @@ -42,6 +46,9 @@ fn simple() { ANOTHER_ARG = s; return 35; }, + take_and_return_bool(s: boolean): boolean { + return s; + }, }; export function test(wasm: Exports) { @@ -52,6 +59,9 @@ fn simple() { assert.strictEqual(ANOTHER_ARG, null); assert.strictEqual(wasm.another_thunk(21), 35); assert.strictEqual(ANOTHER_ARG, 21); + + assert.strictEqual(wasm.bool_thunk(true), true); + assert.strictEqual(wasm.bool_thunk(false), false); } "#) .test(); diff --git a/tests/simple.rs b/tests/simple.rs index 9ca9adc4..41c1ca6f 100644 --- a/tests/simple.rs +++ b/tests/simple.rs @@ -19,10 +19,14 @@ fn add() { a + 3 } - pub fn get2() -> u32 { + pub fn get2(_b: bool) -> u32 { 2 } + pub fn return_and_take_bool(a: bool, b: bool) -> bool { + a && b + } + pub fn raw_pointers_work(a: *mut u32, b: *const u8) -> *const u32 { unsafe { (*a) = (*b) as u32; @@ -41,7 +45,8 @@ fn add() { assert.strictEqual(wasm.add(1, 2), 3); assert.strictEqual(wasm.add(2, 3), 5); assert.strictEqual(wasm.add3(2), 5); - assert.strictEqual(wasm.get2(), 2); + assert.strictEqual(wasm.get2(true), 2); + assert.strictEqual(wasm.return_and_take_bool(true, false), false); } "#) .test();