mirror of
https://github.com/rustwasm/wasm-bindgen.git
synced 2024-12-25 11:02:11 +03:00
Add JsValue::{from_serde, into_serde}
These functions are activated with the `serde-serialization` feature of the `wasm-bindgen` crate. When activated they will allow passing any arbitrary value into JS that implements the `Serialize` trait and receiving any value from JS using the `Deserialize` trait. The interchange between JS and Rust is JSON. Closes #96
This commit is contained in:
parent
acb5eac96a
commit
b8895b3a95
@ -20,9 +20,12 @@ doctest = false
|
||||
default = ["spans", "std"]
|
||||
spans = ["wasm-bindgen-macro/spans"]
|
||||
std = []
|
||||
serde-serialize = ["serde", "serde_json", "std"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen-macro = { path = "crates/macro", version = "=0.2.6" }
|
||||
serde = { version = "1.0", optional = true }
|
||||
serde_json = { version = "1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-cli-support = { path = "crates/cli-support", version = '=0.2.6' }
|
||||
|
@ -83,213 +83,230 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
bail!("\n\nthe exported function `{}` is required to generate bindings \
|
||||
bail!("the exported function `{}` is required to generate bindings \
|
||||
but it was not found in the wasm file, perhaps the `std` feature \
|
||||
of the `wasm-bindgen` crate needs to be enabled?\n\n",
|
||||
of the `wasm-bindgen` crate needs to be enabled?",
|
||||
name);
|
||||
}
|
||||
|
||||
pub fn finalize(&mut self, module_name: &str) -> Result<(String, String), Error> {
|
||||
self.write_classes()?;
|
||||
|
||||
self.bind("__wbindgen_object_clone_ref", &|me| {
|
||||
me.expose_add_heap_object();
|
||||
me.expose_get_object();
|
||||
let bump_cnt = if me.config.debug {
|
||||
String::from("
|
||||
if (typeof(val) === 'number')
|
||||
throw new Error('corrupt slab');
|
||||
val.cnt += 1;
|
||||
")
|
||||
} else {
|
||||
String::from("val.cnt += 1;")
|
||||
};
|
||||
Ok(format!("
|
||||
function(idx) {{
|
||||
// If this object is on the stack promote it to the heap.
|
||||
if ((idx & 1) === 1)
|
||||
return addHeapObject(getObject(idx));
|
||||
|
||||
// Otherwise if the object is on the heap just bump the
|
||||
// refcount and move on
|
||||
const val = slab[idx >> 1];
|
||||
{}
|
||||
return idx;
|
||||
}}
|
||||
", bump_cnt))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_object_drop_ref", &|me| {
|
||||
me.expose_drop_ref();
|
||||
Ok("function(i) { dropRef(i); }".to_string())
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_string_new", &|me| {
|
||||
me.expose_add_heap_object();
|
||||
me.expose_get_string_from_wasm();
|
||||
Ok(String::from("
|
||||
function(p, l) {
|
||||
return addHeapObject(getStringFromWasm(p, l));
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_number_new", &|me| {
|
||||
me.expose_add_heap_object();
|
||||
Ok(String::from("function(i) { return addHeapObject(i); }"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_number_get", &|me| {
|
||||
me.expose_get_object();
|
||||
me.expose_uint8_memory();
|
||||
Ok(format!("
|
||||
function(n, invalid) {{
|
||||
let obj = getObject(n);
|
||||
if (typeof(obj) === 'number')
|
||||
return obj;
|
||||
getUint8Memory()[invalid] = 1;
|
||||
return 0;
|
||||
}}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_undefined_new", &|me| {
|
||||
me.expose_add_heap_object();
|
||||
Ok(String::from("function() { return addHeapObject(undefined); }"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_null_new", &|me| {
|
||||
me.expose_add_heap_object();
|
||||
Ok(String::from("
|
||||
function() {
|
||||
return addHeapObject(null);
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_is_null", &|me| {
|
||||
me.expose_get_object();
|
||||
Ok(String::from("
|
||||
function(idx) {
|
||||
return getObject(idx) === null ? 1 : 0;
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_is_undefined", &|me| {
|
||||
me.expose_get_object();
|
||||
Ok(String::from("
|
||||
function(idx) {
|
||||
return getObject(idx) === undefined ? 1 : 0;
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_boolean_new", &|me| {
|
||||
me.expose_add_heap_object();
|
||||
Ok(String::from("
|
||||
function(v) {
|
||||
return addHeapObject(v === 1);
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_boolean_get", &|me| {
|
||||
me.expose_get_object();
|
||||
Ok(String::from("
|
||||
function(i) {
|
||||
let v = getObject(i);
|
||||
if (typeof(v) === 'boolean') {
|
||||
return v ? 1 : 0;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_symbol_new", &|me| {
|
||||
me.expose_get_string_from_wasm();
|
||||
me.expose_add_heap_object();
|
||||
Ok(format!("
|
||||
function(ptr, len) {{
|
||||
let a;
|
||||
if (ptr === 0) {{
|
||||
a = Symbol();
|
||||
}} else {{
|
||||
a = Symbol(getStringFromWasm(ptr, len));
|
||||
}}
|
||||
return addHeapObject(a);
|
||||
}}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_is_symbol", &|me| {
|
||||
me.expose_get_object();
|
||||
Ok(String::from("
|
||||
function(i) {
|
||||
return typeof(getObject(i)) === 'symbol' ? 1 : 0;
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_string_get", &|me| {
|
||||
me.expose_pass_string_to_wasm()?;
|
||||
me.expose_get_object();
|
||||
me.expose_uint32_memory();
|
||||
Ok(String::from("
|
||||
function(i, len_ptr) {
|
||||
let obj = getObject(i);
|
||||
if (typeof(obj) !== 'string')
|
||||
return 0;
|
||||
const [ptr, len] = passStringToWasm(obj);
|
||||
getUint32Memory()[len_ptr / 4] = len;
|
||||
return ptr;
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_cb_drop", &|me| {
|
||||
me.expose_drop_ref();
|
||||
Ok(String::from("
|
||||
function(i) {
|
||||
let obj = getObject(i).original;
|
||||
obj.a = obj.b = 0;
|
||||
dropRef(i);
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_cb_forget", &|me| {
|
||||
me.expose_drop_ref();
|
||||
Ok(String::from("
|
||||
function(i) {
|
||||
dropRef(i);
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_json_parse", &|me| {
|
||||
me.expose_add_heap_object();
|
||||
me.expose_get_string_from_wasm();
|
||||
Ok(String::from("
|
||||
function(ptr, len) {
|
||||
return addHeapObject(JSON.parse(getStringFromWasm(ptr, len)));
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_json_serialize", &|me| {
|
||||
me.expose_get_object();
|
||||
me.expose_pass_string_to_wasm()?;
|
||||
me.expose_uint32_memory();
|
||||
Ok(String::from("
|
||||
function(idx, ptrptr) {
|
||||
const [ptr, len] = passStringToWasm(JSON.stringify(getObject(idx)));
|
||||
getUint32Memory()[ptrptr / 4] = ptr;
|
||||
return len;
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.unexport_unused_internal_exports();
|
||||
self.gc()?;
|
||||
self.write_classes()?;
|
||||
{
|
||||
let mut bind = |name: &str, f: &Fn(&mut Self) -> Result<String, Error>|
|
||||
-> Result<(), Error>
|
||||
{
|
||||
if !self.wasm_import_needed(name) {
|
||||
return Ok(());
|
||||
}
|
||||
let contents = f(self)?;
|
||||
self.export(name, &contents);
|
||||
Ok(())
|
||||
};
|
||||
|
||||
bind("__wbindgen_object_clone_ref", &|me| {
|
||||
me.expose_add_heap_object();
|
||||
me.expose_get_object();
|
||||
let bump_cnt = if me.config.debug {
|
||||
String::from("
|
||||
if (typeof(val) === 'number')
|
||||
throw new Error('corrupt slab');
|
||||
val.cnt += 1;
|
||||
")
|
||||
} else {
|
||||
String::from("val.cnt += 1;")
|
||||
};
|
||||
Ok(format!("
|
||||
function(idx) {{
|
||||
// If this object is on the stack promote it to the heap.
|
||||
if ((idx & 1) === 1)
|
||||
return addHeapObject(getObject(idx));
|
||||
|
||||
// Otherwise if the object is on the heap just bump the
|
||||
// refcount and move on
|
||||
const val = slab[idx >> 1];
|
||||
{}
|
||||
return idx;
|
||||
}}
|
||||
", bump_cnt))
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_object_drop_ref", &|me| {
|
||||
me.expose_drop_ref();
|
||||
Ok("function(i) { dropRef(i); }".to_string())
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_string_new", &|me| {
|
||||
me.expose_add_heap_object();
|
||||
me.expose_get_string_from_wasm();
|
||||
Ok(String::from("
|
||||
function(p, l) {
|
||||
return addHeapObject(getStringFromWasm(p, l));
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_number_new", &|me| {
|
||||
me.expose_add_heap_object();
|
||||
Ok(String::from("function(i) { return addHeapObject(i); }"))
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_number_get", &|me| {
|
||||
me.expose_get_object();
|
||||
me.expose_uint8_memory();
|
||||
Ok(format!("
|
||||
function(n, invalid) {{
|
||||
let obj = getObject(n);
|
||||
if (typeof(obj) === 'number')
|
||||
return obj;
|
||||
getUint8Memory()[invalid] = 1;
|
||||
return 0;
|
||||
}}
|
||||
"))
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_undefined_new", &|me| {
|
||||
me.expose_add_heap_object();
|
||||
Ok(String::from("function() { return addHeapObject(undefined); }"))
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_null_new", &|me| {
|
||||
me.expose_add_heap_object();
|
||||
Ok(String::from("
|
||||
function() {
|
||||
return addHeapObject(null);
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_is_null", &|me| {
|
||||
me.expose_get_object();
|
||||
Ok(String::from("
|
||||
function(idx) {
|
||||
return getObject(idx) === null ? 1 : 0;
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_is_undefined", &|me| {
|
||||
me.expose_get_object();
|
||||
Ok(String::from("
|
||||
function(idx) {
|
||||
return getObject(idx) === undefined ? 1 : 0;
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_boolean_new", &|me| {
|
||||
me.expose_add_heap_object();
|
||||
Ok(String::from("
|
||||
function(v) {
|
||||
return addHeapObject(v === 1);
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_boolean_get", &|me| {
|
||||
me.expose_get_object();
|
||||
Ok(String::from("
|
||||
function(i) {
|
||||
let v = getObject(i);
|
||||
if (typeof(v) === 'boolean') {
|
||||
return v ? 1 : 0;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_symbol_new", &|me| {
|
||||
me.expose_get_string_from_wasm();
|
||||
me.expose_add_heap_object();
|
||||
Ok(format!("
|
||||
function(ptr, len) {{
|
||||
let a;
|
||||
if (ptr === 0) {{
|
||||
a = Symbol();
|
||||
}} else {{
|
||||
a = Symbol(getStringFromWasm(ptr, len));
|
||||
}}
|
||||
return addHeapObject(a);
|
||||
}}
|
||||
"))
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_is_symbol", &|me| {
|
||||
me.expose_get_object();
|
||||
Ok(String::from("
|
||||
function(i) {
|
||||
return typeof(getObject(i)) === 'symbol' ? 1 : 0;
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_throw", &|me| {
|
||||
me.expose_get_string_from_wasm();
|
||||
Ok(format!("
|
||||
function(ptr, len) {{
|
||||
throw new Error(getStringFromWasm(ptr, len));
|
||||
}}
|
||||
"))
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_string_get", &|me| {
|
||||
me.expose_pass_string_to_wasm()?;
|
||||
me.expose_get_object();
|
||||
me.expose_uint32_memory();
|
||||
Ok(String::from("
|
||||
function(i, len_ptr) {
|
||||
let obj = getObject(i);
|
||||
if (typeof(obj) !== 'string')
|
||||
return 0;
|
||||
const [ptr, len] = passStringToWasm(obj);
|
||||
getUint32Memory()[len_ptr / 4] = len;
|
||||
return ptr;
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
|
||||
bind("__wbindgen_cb_drop", &|me| {
|
||||
me.expose_drop_ref();
|
||||
Ok(String::from("
|
||||
function(i) {
|
||||
let obj = getObject(i).original;
|
||||
obj.a = obj.b = 0;
|
||||
dropRef(i);
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
bind("__wbindgen_cb_forget", &|me| {
|
||||
me.expose_drop_ref();
|
||||
Ok(String::from("
|
||||
function(i) {
|
||||
dropRef(i);
|
||||
}
|
||||
"))
|
||||
})?;
|
||||
}
|
||||
// Note that it's important `throw` comes last *after* we gc. The
|
||||
// `__wbindgen_malloc` function may call this but we only want to
|
||||
// generate code for this if it's actually live (and __wbindgen_malloc
|
||||
// isn't gc'd).
|
||||
self.bind("__wbindgen_throw", &|me| {
|
||||
me.expose_get_string_from_wasm();
|
||||
Ok(format!("
|
||||
function(ptr, len) {{
|
||||
throw new Error(getStringFromWasm(ptr, len));
|
||||
}}
|
||||
"))
|
||||
})?;
|
||||
|
||||
self.rewrite_imports(module_name);
|
||||
|
||||
@ -352,6 +369,20 @@ impl<'a> Context<'a> {
|
||||
Ok((js, self.typescript.clone()))
|
||||
}
|
||||
|
||||
fn bind(&mut self, name: &str, f: &Fn(&mut Self) -> Result<String, Error>)
|
||||
-> Result<(), Error>
|
||||
{
|
||||
if !self.wasm_import_needed(name) {
|
||||
return Ok(());
|
||||
}
|
||||
let contents = f(self)
|
||||
.with_context(|_| {
|
||||
format!("failed to generate internal JS function `{}`", name)
|
||||
})?;
|
||||
self.export(name, &contents);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_classes(&mut self) -> Result<(), Error> {
|
||||
let classes = mem::replace(&mut self.exported_classes, Default::default());
|
||||
for (class, exports) in classes {
|
||||
|
84
src/lib.rs
84
src/lib.rs
@ -8,6 +8,11 @@
|
||||
#![feature(use_extern_macros, wasm_import_module, try_reserve, unsize)]
|
||||
#![no_std]
|
||||
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
extern crate serde;
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
extern crate serde_json;
|
||||
|
||||
extern crate wasm_bindgen_macro;
|
||||
|
||||
use core::cell::UnsafeCell;
|
||||
@ -112,22 +117,58 @@ impl JsValue {
|
||||
}
|
||||
}
|
||||
|
||||
// #[doc(hidden)]
|
||||
// pub unsafe fn __from_idx(idx: u32) -> JsValue {
|
||||
// JsValue { idx }
|
||||
// }
|
||||
//
|
||||
// #[doc(hidden)]
|
||||
// pub fn __get_idx(&self) -> u32 {
|
||||
// self.idx
|
||||
// }
|
||||
//
|
||||
// #[doc(hidden)]
|
||||
// pub fn __into_idx(self) -> u32 {
|
||||
// let ret = self.idx;
|
||||
// mem::forget(self);
|
||||
// return ret
|
||||
// }
|
||||
/// Creates a new `JsValue` from the JSON serialization of the object `t`
|
||||
/// provided.
|
||||
///
|
||||
/// This function will serialize the provided value `t` to a JSON string,
|
||||
/// send the JSON string to JS, parse it into a JS object, and then return
|
||||
/// a handle to the JS object. This is unlikely to be super speedy so it's
|
||||
/// not recommended for large payloads, but it's a nice to have in some
|
||||
/// situations!
|
||||
///
|
||||
/// Usage of this API requires activating the `serde-serialize` feature of
|
||||
/// the `wasm-bindgen` crate.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns any error encountered when serializing `T` into JSON.
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
pub fn from_serde<T>(t: &T) -> serde_json::Result<JsValue>
|
||||
where T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
let s = serde_json::to_string(t)?;
|
||||
unsafe {
|
||||
Ok(JsValue {
|
||||
idx: __wbindgen_json_parse(s.as_ptr(), s.len()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Invokes `JSON.stringify` on this value and then parses the resulting
|
||||
/// JSON into an arbitrary Rust value.
|
||||
///
|
||||
/// This function will first call `JSON.stringify` on the `JsValue` itself.
|
||||
/// The resulting string is then passed into Rust which then parses it as
|
||||
/// JSON into the resulting value.
|
||||
///
|
||||
/// Usage of this API requires activating the `serde-serialize` feature of
|
||||
/// the `wasm-bindgen` crate.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns any error encountered when parsing the JSON into a `T`.
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
pub fn into_serde<T>(&self) -> serde_json::Result<T>
|
||||
where T: for<'a> serde::de::Deserialize<'a>,
|
||||
{
|
||||
unsafe {
|
||||
let mut ptr = ptr::null_mut();
|
||||
let len = __wbindgen_json_serialize(self.idx, &mut ptr);
|
||||
let s = Vec::from_raw_parts(ptr, len, len);
|
||||
let s = String::from_utf8_unchecked(s);
|
||||
serde_json::from_str(&s)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `f64` value of this JS value if it's an instance of a
|
||||
/// number.
|
||||
@ -252,18 +293,13 @@ extern {
|
||||
fn __wbindgen_string_get(idx: u32, len: *mut usize) -> *mut u8;
|
||||
fn __wbindgen_throw(a: *const u8, b: usize) -> !;
|
||||
|
||||
fn __wbindgen_cb_arity0(a: u32, b: u32, c: u32) -> u32;
|
||||
fn __wbindgen_cb_arity1(a: u32, b: u32, c: u32) -> u32;
|
||||
fn __wbindgen_cb_arity2(a: u32, b: u32, c: u32) -> u32;
|
||||
fn __wbindgen_cb_arity3(a: u32, b: u32, c: u32) -> u32;
|
||||
fn __wbindgen_cb_arity4(a: u32, b: u32, c: u32) -> u32;
|
||||
fn __wbindgen_cb_arity5(a: u32, b: u32, c: u32) -> u32;
|
||||
fn __wbindgen_cb_arity6(a: u32, b: u32, c: u32) -> u32;
|
||||
fn __wbindgen_cb_arity7(a: u32, b: u32, c: u32) -> u32;
|
||||
fn __wbindgen_cb_drop(idx: u32);
|
||||
fn __wbindgen_cb_forget(idx: u32);
|
||||
|
||||
fn __wbindgen_describe(v: u32);
|
||||
|
||||
fn __wbindgen_json_parse(ptr: *const u8, len: usize) -> u32;
|
||||
fn __wbindgen_json_serialize(idx: u32, ptr: *mut *mut u8) -> usize;
|
||||
}
|
||||
|
||||
impl Clone for JsValue {
|
||||
|
@ -244,3 +244,90 @@ fn another_vector_return() {
|
||||
"#)
|
||||
.test();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde() {
|
||||
project()
|
||||
.serde(true)
|
||||
.depend("serde = '1.0'")
|
||||
.depend("serde_derive = '1.0'")
|
||||
.file("src/lib.rs", r#"
|
||||
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
|
||||
|
||||
extern crate wasm_bindgen;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Foo {
|
||||
a: u32,
|
||||
b: String,
|
||||
c: Option<Bar>,
|
||||
d: Bar,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Bar {
|
||||
a: u32,
|
||||
}
|
||||
|
||||
#[wasm_bindgen(module = "./test")]
|
||||
extern {
|
||||
fn verify(a: JsValue) -> JsValue;
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn run() {
|
||||
let js = JsValue::from_serde("foo").unwrap();
|
||||
assert_eq!(js.as_string(), Some("foo".to_string()));
|
||||
|
||||
let ret = verify(JsValue::from_serde(&Foo {
|
||||
a: 0,
|
||||
b: "foo".to_string(),
|
||||
c: None,
|
||||
d: Bar { a: 1 },
|
||||
}).unwrap());
|
||||
|
||||
let foo = ret.into_serde::<Foo>().unwrap();
|
||||
assert_eq!(foo.a, 2);
|
||||
assert_eq!(foo.b, "bar");
|
||||
assert!(foo.c.is_some());
|
||||
assert_eq!(foo.c.as_ref().unwrap().a, 3);
|
||||
assert_eq!(foo.d.a, 4);
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn parse(j: &JsValue) {
|
||||
let s = j.into_serde::<String>().unwrap();
|
||||
assert_eq!(s, "bar");
|
||||
}
|
||||
"#)
|
||||
.file("test.ts", r#"
|
||||
import { run, parse } from "./out";
|
||||
import * as assert from "assert";
|
||||
|
||||
export function verify(a: any) {
|
||||
assert.deepStrictEqual(a, {
|
||||
a: 0,
|
||||
b: 'foo',
|
||||
c: null,
|
||||
d: { a: 1 }
|
||||
});
|
||||
|
||||
return {
|
||||
a: 2,
|
||||
b: 'bar',
|
||||
c: { a: 3 },
|
||||
d: { a: 4 },
|
||||
}
|
||||
}
|
||||
|
||||
export function test() {
|
||||
run();
|
||||
parse('bar');
|
||||
}
|
||||
"#)
|
||||
.test();
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ struct Project {
|
||||
debug: bool,
|
||||
node: bool,
|
||||
no_std: bool,
|
||||
serde: bool,
|
||||
}
|
||||
|
||||
fn project() -> Project {
|
||||
@ -27,6 +28,7 @@ fn project() -> Project {
|
||||
debug: true,
|
||||
node: false,
|
||||
no_std: false,
|
||||
serde: false,
|
||||
files: vec![
|
||||
("Cargo.toml".to_string(), format!(r#"
|
||||
[package]
|
||||
@ -151,6 +153,23 @@ impl Project {
|
||||
self
|
||||
}
|
||||
|
||||
fn serde(&mut self, serde: bool) -> &mut Project {
|
||||
self.serde = serde;
|
||||
self
|
||||
}
|
||||
|
||||
fn depend(&mut self, dep: &str) -> &mut Project {
|
||||
{
|
||||
let cargo_toml = self.files
|
||||
.iter_mut()
|
||||
.find(|f| f.0 == "Cargo.toml")
|
||||
.expect("should have Cargo.toml file!");
|
||||
cargo_toml.1.push_str(dep);
|
||||
cargo_toml.1.push_str("\n");
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn add_local_dependency(&mut self, name: &str, path: &str) -> &mut Project {
|
||||
{
|
||||
let cargo_toml = self.files
|
||||
@ -173,10 +192,12 @@ impl Project {
|
||||
.expect("should have Cargo.toml file!");
|
||||
cargo_toml.1.push_str("wasm-bindgen = { path = '");
|
||||
cargo_toml.1.push_str(env!("CARGO_MANIFEST_DIR"));
|
||||
cargo_toml.1.push_str("'");
|
||||
if self.no_std {
|
||||
cargo_toml.1.push_str("', default-features = false");
|
||||
} else {
|
||||
cargo_toml.1.push_str("'");
|
||||
cargo_toml.1.push_str(", default-features = false");
|
||||
}
|
||||
if self.serde {
|
||||
cargo_toml.1.push_str(", features = ['serde-serialize']");
|
||||
}
|
||||
cargo_toml.1.push_str(" }\n");
|
||||
}
|
||||
@ -207,13 +228,18 @@ impl Project {
|
||||
let as_a_module = root.join("out.wasm");
|
||||
fs::copy(&out, &as_a_module).unwrap();
|
||||
|
||||
cli::Bindgen::new()
|
||||
let res = cli::Bindgen::new()
|
||||
.input_path(&as_a_module)
|
||||
.typescript(true)
|
||||
.nodejs(self.node)
|
||||
.debug(self.debug)
|
||||
.generate(&root)
|
||||
.expect("failed to run bindgen");
|
||||
.generate(&root);
|
||||
if let Err(e) = res {
|
||||
for e in e.causes() {
|
||||
println!("- {}", e);
|
||||
}
|
||||
panic!("failed");
|
||||
}
|
||||
|
||||
let mut wasm = Vec::new();
|
||||
File::open(root.join("out_bg.wasm")).unwrap()
|
||||
|
Loading…
Reference in New Issue
Block a user