From 4151461ab9ec29e84ddaac3e7c8664f9b2dfd9b7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 31 Dec 2017 14:44:44 -0800 Subject: [PATCH] Expose construction of a `JsObject` as a string Start fleshing out the `JsObject` API! --- crates/wasm-bindgen-cli-support/src/ts.rs | 10 ++++++ src/lib.rs | 39 +++++++++++++++++++++++ tests/api.rs | 36 +++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 tests/api.rs diff --git a/crates/wasm-bindgen-cli-support/src/ts.rs b/crates/wasm-bindgen-cli-support/src/ts.rs index b22b634c..52d11b4e 100644 --- a/crates/wasm-bindgen-cli-support/src/ts.rs +++ b/crates/wasm-bindgen-cli-support/src/ts.rs @@ -558,6 +558,16 @@ impl Js { imports_object.push_str(&format!("{}: dropRef,\n", name)); } + if self.wasm_import_needed("__wbindgen_string_new", m) { + self.expose_add_heap_object(); + self.expose_get_string_from_wasm(); + imports_object.push_str(&format!(" + {}: function(ptr: number, len: number): number {{ + return addHeapObject(getStringFromWasm(ptr, len)); + }}, + ", m.import_name("__wbindgen_string_new"))); + } + if self.wasm_import_needed("__wbindgen_throw", m) { self.expose_get_string_from_wasm(); imports_object.push_str(&format!("\ diff --git a/src/lib.rs b/src/lib.rs index 481bcd4f..847f3ed4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,19 +1,46 @@ +//! Runtime support for the `wasm-bindgen` tool +//! +//! This crate contains the runtime support necessary for `wasm-bindgen` the +//! macro and tool. Crates pull in the `wasm_bindgen!` macro through this crate +//! and this crate also provides JS bindings through the `JsObject` interface. + #![feature(use_extern_macros)] extern crate wasm_bindgen_macro; use std::mem; +/// A module which is typically glob imported from: +/// +/// ``` +/// use wasm_bindgen::prelude::*; +/// ``` pub mod prelude { pub use wasm_bindgen_macro::wasm_bindgen; pub use JsObject; } +/// Representation of an object owned by JS. +/// +/// A `JsObject` doesn't actually live in Rust right now but actually in a table +/// owned by the `wasm-bindgen` generated JS glue code. Eventually the ownership +/// will transfer into wasm directly and this will likely become more efficient, +/// but for now it may be slightly slow. pub struct JsObject { idx: u32, } impl JsObject { + /// Creates a new JS object which is a string. + /// + /// The utf-8 string provided is copied to the JS heap and the string will + /// be owned by the JS garbage collector. + pub fn from_str(s: &str) -> JsObject { + unsafe { + JsObject::__from_idx(__wbindgen_string_new(s.as_ptr(), s.len())) + } + } + #[doc(hidden)] pub fn __from_idx(idx: u32) -> JsObject { JsObject { idx } @@ -32,9 +59,16 @@ impl JsObject { } } +impl<'a> From<&'a str> for JsObject { + fn from(s: &'a str) -> JsObject { + JsObject::from_str(s) + } +} + extern { fn __wbindgen_object_clone_ref(idx: u32) -> u32; fn __wbindgen_object_drop_ref(idx: u32); + fn __wbindgen_string_new(ptr: *const u8, len: usize) -> u32; } impl Clone for JsObject { @@ -54,6 +88,11 @@ impl Drop for JsObject { } } +/// Throws a JS exception. +/// +/// This function will throw a JS exception with the message provided. The +/// function will not return as the wasm stack will be popped when the exception +/// is thrown. #[cold] #[inline(never)] pub fn throw(s: &str) -> ! { diff --git a/tests/api.rs b/tests/api.rs new file mode 100644 index 00000000..f1073215 --- /dev/null +++ b/tests/api.rs @@ -0,0 +1,36 @@ +extern crate test_support; + +#[test] +fn works() { + test_support::project() + .file("src/lib.rs", r#" + #![feature(proc_macro)] + + extern crate wasm_bindgen; + + use wasm_bindgen::prelude::*; + + wasm_bindgen! { + pub fn foo() -> JsObject { + JsObject::from("foo") + } + + pub fn bar(s: &str) -> JsObject { + JsObject::from(s) + } + } + "#) + .file("test.ts", r#" + import * as assert from "assert"; + import { Exports, Imports } from "./out"; + + export const imports: Imports = {}; + + export function test(wasm: Exports) { + assert.strictEqual(wasm.foo(), 'foo'); + assert.strictEqual(wasm.bar('a'), 'a'); + } + "#) + .test(); +} +