Skip to content

Commit

Permalink
Redo as js function + fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
derekdreery committed Jan 10, 2019
1 parent 0144928 commit 7d5d443
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 48 deletions.
59 changes: 55 additions & 4 deletions crates/cli-support/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,16 +348,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_get_object();
me.expose_uint32_memory();
Ok(String::from(
"
function(i, len_ptr) {
let toString = getObject(i).toString();
if (typeof(toString) !== 'string') return 0;
const ptr = passStringToWasm(toString);
const debug_str = val => {
// primitive types
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;
return ptr;
}
Expand Down
66 changes: 23 additions & 43 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,13 @@ impl JsValue {
where
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
Expand Down Expand Up @@ -304,24 +310,14 @@ impl JsValue {
unsafe { __wbindgen_is_function(self.idx) == 1 }
}

/// Helper method to get the value as a json String (serialized in javascript)
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.
/// Get a string representation of the JavaScript object for debugging
#[cfg(feature = "std")]
fn js_to_string(&self) -> String {
fn as_debug_string(&self) -> String {
unsafe {
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() {
unreachable!("Object.toString must return a valid string")
unreachable!("`__wbindgen_debug_string` must return a valid string")
} else {
let data = Vec::from_raw_parts(ptr, len, len);
String::from_utf8_unchecked(data)
Expand Down Expand Up @@ -503,7 +499,7 @@ externs! {
fn __wbindgen_is_function(idx: u32) -> u32;
fn __wbindgen_is_string(idx: u32) -> u32;
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_rethrow(a: u32) -> !;

Expand All @@ -530,35 +526,19 @@ impl Clone for JsValue {
}
}

#[cfg(feature = "std")]
impl fmt::Debug for JsValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(n) = self.as_f64() {
return n.fmt(f);
}
#[cfg(feature = "std")]
{
if let Some(n) = self.as_string() {
return n.fmt(f);
}
}
if let Some(n) = self.as_bool() {
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)
}
f.write_str(&self.as_debug_string())
}
}

#[cfg(not(feature = "std"))]
impl fmt::Debug for JsValue {
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)?
f.write_str("[object]")
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/wasm/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub fn api_test_bool(a: &JsValue, b: &JsValue, c: &JsValue) {
pub fn api_mk_symbol() -> JsValue {
let a = JsValue::symbol(None);
assert!(a.is_symbol());
assert_eq!(format!("{:?}", a), "Symbol(..)");
assert_eq!(format!("{:?}", a), "Symbol()");
return a;
}

Expand Down

0 comments on commit 7d5d443

Please sign in to comment.