mirror of
https://github.com/rustwasm/wasm-bindgen.git
synced 2024-12-14 20:11:37 +03:00
Redo as js function + fix tests
This commit is contained in:
parent
5b51d279b4
commit
126efd5a95
@ -350,16 +350,67 @@ impl<'a> Context<'a> {
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.bind("__wbindgen_to_string", &|me| {
|
self.bind("__wbindgen_debug_string", &|me| {
|
||||||
me.expose_pass_string_to_wasm()?;
|
me.expose_pass_string_to_wasm()?;
|
||||||
me.expose_get_object();
|
me.expose_get_object();
|
||||||
me.expose_uint32_memory();
|
me.expose_uint32_memory();
|
||||||
Ok(String::from(
|
Ok(String::from(
|
||||||
"
|
"
|
||||||
function(i, len_ptr) {
|
function(i, len_ptr) {
|
||||||
let toString = getObject(i).toString();
|
const debug_str = val => {
|
||||||
if (typeof(toString) !== 'string') return 0;
|
// primitive types
|
||||||
const ptr = passStringToWasm(toString);
|
const type = typeof val;
|
||||||
|
if (type == 'number' || type == 'boolean' || val == null) {
|
||||||
|
return val + '';
|
||||||
|
}
|
||||||
|
if (type == 'string') {
|
||||||
|
return '\"' + val + '\"';
|
||||||
|
}
|
||||||
|
if (type == 'symbol') {
|
||||||
|
const description = val.description;
|
||||||
|
if (description == null) {
|
||||||
|
return 'Symbol()';
|
||||||
|
} else {
|
||||||
|
return 'Symbol(' + description + ')';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type == 'function') {
|
||||||
|
return 'Function';
|
||||||
|
}
|
||||||
|
// objects
|
||||||
|
if (Array.isArray(val)) {
|
||||||
|
const length = val.length;
|
||||||
|
let debug = '[';
|
||||||
|
if (length > 0) {
|
||||||
|
debug += debug_str(val[0]);
|
||||||
|
}
|
||||||
|
for(let i = 1; i < length; i++) {
|
||||||
|
debug += debug_str(val[i]) + ', ';
|
||||||
|
}
|
||||||
|
debug += ']';
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
// Test for built-in
|
||||||
|
const builtInMatches = /\\[object ([^])+\\]/.exec(val.toString());
|
||||||
|
let className;
|
||||||
|
if (builtInMatches.len > 0) {
|
||||||
|
className = builtInMatches[0];
|
||||||
|
} else {
|
||||||
|
// Failed to match the standard '[object ClassName]'
|
||||||
|
return val.toString();
|
||||||
|
}
|
||||||
|
if (className == 'Object') {
|
||||||
|
// we're a user defined class or Object
|
||||||
|
// JSON.stringify avoids problems with cycles, and is generally much
|
||||||
|
// easier than looping through ownProperties of `val`.
|
||||||
|
return 'Object(' + JSON.stringify(val) + ')';
|
||||||
|
} else {
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const val = getObject(i);
|
||||||
|
const debug = debug_str(val);
|
||||||
|
const ptr = passStringToWasm(debug);
|
||||||
getUint32Memory()[len_ptr / 4] = WASM_VECTOR_LEN;
|
getUint32Memory()[len_ptr / 4] = WASM_VECTOR_LEN;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
66
src/lib.rs
66
src/lib.rs
@ -204,7 +204,13 @@ impl JsValue {
|
|||||||
where
|
where
|
||||||
T: for<'a> serde::de::Deserialize<'a>,
|
T: for<'a> serde::de::Deserialize<'a>,
|
||||||
{
|
{
|
||||||
serde_json::from_str(&self.as_json())
|
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
|
/// Returns the `f64` value of this JS value if it's an instance of a
|
||||||
@ -304,24 +310,14 @@ impl JsValue {
|
|||||||
unsafe { __wbindgen_is_function(self.idx) == 1 }
|
unsafe { __wbindgen_is_function(self.idx) == 1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper method to get the value as a json String (serialized in javascript)
|
/// Get a string representation of the JavaScript object for debugging
|
||||||
fn as_json(&self) -> String {
|
|
||||||
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);
|
|
||||||
String::from_utf8_unchecked(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the string value of self using the JS `toString` method.
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
fn js_to_string(&self) -> String {
|
fn as_debug_string(&self) -> String {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
let ptr = __wbindgen_to_string(self.idx, &mut len);
|
let ptr = __wbindgen_debug_string(self.idx, &mut len);
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
unreachable!("Object.toString must return a valid string")
|
unreachable!("`__wbindgen_debug_string` must return a valid string")
|
||||||
} else {
|
} else {
|
||||||
let data = Vec::from_raw_parts(ptr, len, len);
|
let data = Vec::from_raw_parts(ptr, len, len);
|
||||||
String::from_utf8_unchecked(data)
|
String::from_utf8_unchecked(data)
|
||||||
@ -503,7 +499,7 @@ externs! {
|
|||||||
fn __wbindgen_is_function(idx: u32) -> u32;
|
fn __wbindgen_is_function(idx: u32) -> u32;
|
||||||
fn __wbindgen_is_string(idx: u32) -> u32;
|
fn __wbindgen_is_string(idx: u32) -> u32;
|
||||||
fn __wbindgen_string_get(idx: u32, len: *mut usize) -> *mut u8;
|
fn __wbindgen_string_get(idx: u32, len: *mut usize) -> *mut u8;
|
||||||
fn __wbindgen_to_string(idx: u32, len: *mut usize) -> *mut u8;
|
fn __wbindgen_debug_string(idx: u32, len: *mut usize) -> *mut u8;
|
||||||
fn __wbindgen_throw(a: *const u8, b: usize) -> !;
|
fn __wbindgen_throw(a: *const u8, b: usize) -> !;
|
||||||
fn __wbindgen_rethrow(a: u32) -> !;
|
fn __wbindgen_rethrow(a: u32) -> !;
|
||||||
|
|
||||||
@ -530,35 +526,19 @@ impl Clone for JsValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl fmt::Debug for JsValue {
|
impl fmt::Debug for JsValue {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if let Some(n) = self.as_f64() {
|
f.write_str(&self.as_debug_string())
|
||||||
return n.fmt(f);
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "std")]
|
|
||||||
{
|
#[cfg(not(feature = "std"))]
|
||||||
if let Some(n) = self.as_string() {
|
impl fmt::Debug for JsValue {
|
||||||
return n.fmt(f);
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
}
|
// TODO before merge - this is less info than before - is this OK? Can we do the above
|
||||||
}
|
// without using allocation (no_std)?
|
||||||
if let Some(n) = self.as_bool() {
|
f.write_str("[object]")
|
||||||
return n.fmt(f);
|
|
||||||
}
|
|
||||||
if self.is_null() {
|
|
||||||
return fmt::Display::fmt("null", f);
|
|
||||||
}
|
|
||||||
if self.is_undefined() {
|
|
||||||
return fmt::Display::fmt("undefined", f);
|
|
||||||
}
|
|
||||||
if self.is_symbol() {
|
|
||||||
return fmt::Display::fmt("Symbol(..)", f);
|
|
||||||
}
|
|
||||||
let json = self.as_json();
|
|
||||||
if json == "{}" {
|
|
||||||
f.write_str(&self.js_to_string())
|
|
||||||
} else {
|
|
||||||
f.write_str(&json)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ pub fn api_test_bool(a: &JsValue, b: &JsValue, c: &JsValue) {
|
|||||||
pub fn api_mk_symbol() -> JsValue {
|
pub fn api_mk_symbol() -> JsValue {
|
||||||
let a = JsValue::symbol(None);
|
let a = JsValue::symbol(None);
|
||||||
assert!(a.is_symbol());
|
assert!(a.is_symbol());
|
||||||
assert_eq!(format!("{:?}", a), "Symbol(..)");
|
assert_eq!(format!("{:?}", a), "Symbol()");
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user