From 23cb0ea656cd7447c80a3b31c17d629485a6a7d9 Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Thu, 9 Aug 2018 20:54:13 -0400 Subject: [PATCH 1/3] Add initial support and tests for JSON --- crates/js-sys/src/lib.rs | 25 ++++++++++++ crates/js-sys/tests/wasm/JSON.rs | 69 ++++++++++++++++++++++++++++++++ crates/js-sys/tests/wasm/main.rs | 1 + 3 files changed, 95 insertions(+) create mode 100644 crates/js-sys/tests/wasm/JSON.rs diff --git a/crates/js-sys/src/lib.rs b/crates/js-sys/src/lib.rs index e0f01f7bc..caaf9cdac 100644 --- a/crates/js-sys/src/lib.rs +++ b/crates/js-sys/src/lib.rs @@ -2663,6 +2663,31 @@ extern "C" { pub fn validate(bufferSource: &JsValue) -> Result; } +// JSON +#[wasm_bindgen] +extern "C" { + + #[derive(Clone, Debug)] + pub type JSON; + + /// The `JSON.parse()` method parses a JSON string, constructing the + /// JavaScript value or object described by the string. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse + #[wasm_bindgen(catch, static_method_of = JSON)] + pub fn parse(text: &str) -> Result; + + /// The JSON.stringify() method converts a JavaScript value to a JSON string, + /// optionally replacing values if a replacer function is specified or + /// optionally including only the specified properties if a replacer array is + /// specified. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify + #[wasm_bindgen(static_method_of = JSON)] + pub fn stringify(obj: &JsValue) -> JsString; + +} + // JsString #[wasm_bindgen] extern "C" { diff --git a/crates/js-sys/tests/wasm/JSON.rs b/crates/js-sys/tests/wasm/JSON.rs new file mode 100644 index 000000000..70ece6e8f --- /dev/null +++ b/crates/js-sys/tests/wasm/JSON.rs @@ -0,0 +1,69 @@ +use wasm_bindgen::JsValue; +use wasm_bindgen_test::*; +use wasm_bindgen::JsCast; +use js_sys::*; + +#[wasm_bindgen_test] +fn parse_array() { + + let js_array = JSON::parse("[1, 2, 3]").unwrap();; + assert!(Array::is_array(&js_array)); + + let array = Array::from(&js_array); + assert_eq!(array.length(), 3); + assert_eq!(array.pop(), 3); + assert_eq!(array.pop(), 2); + assert_eq!(array.pop(), 1); + +} + +#[wasm_bindgen_test] +fn parse_object() { + + let js_object = JSON::parse("{\"x\": 5, \"y\": true, \"z\": [\"foo\", \"bar\"]}").unwrap(); + assert!(js_object.is_object()); + + let obj = Object::from(js_object); + let keys = Object::keys(&obj); + assert_eq!(keys.length(), 3); + assert_eq!(keys.pop().as_string().unwrap(), "z"); + assert_eq!(keys.pop().as_string().unwrap(), "y"); + assert_eq!(keys.pop().as_string().unwrap(), "x"); + + let values = Object::values(&obj); + assert_eq!(values.length(), 3); + + let z = values.pop(); + assert!(Array::is_array(&z)); + let z_array = Array::from(&z); + assert_eq!(z_array.length(), 2); + + let y = values.pop(); + assert_eq!(y.as_bool(), Some(true)); + + let x = values.pop(); + assert!(Number::is_integer(&x)); + let x_num = Number::new(&x); + assert_eq!(x_num.value_of(), 5.0); + +} + +#[wasm_bindgen_test] +fn parse_error() { + let js_object = JSON::parse("invalid json"); + assert!(js_object.is_err()); + let err = js_object.unwrap_err(); + assert!(err.is_instance_of::()); +} + +#[wasm_bindgen_test] +fn stringify() { + let arr = Array::new(); + arr.push(&JsValue::from(1)); + arr.push(&JsValue::from(true)); + arr.push(&JsValue::from("hello")); + + let str = JSON::stringify(&JsValue::from(arr)); + let rust_str: String = From::from(str); + assert_eq!(rust_str, "[1,true,\"hello\"]"); +} \ No newline at end of file diff --git a/crates/js-sys/tests/wasm/main.rs b/crates/js-sys/tests/wasm/main.rs index 1c4414b07..fdc5bbef4 100755 --- a/crates/js-sys/tests/wasm/main.rs +++ b/crates/js-sys/tests/wasm/main.rs @@ -18,6 +18,7 @@ pub mod Function; pub mod Generator; pub mod Intl; pub mod JsString; +pub mod JSON; pub mod Map; pub mod MapIterator; pub mod Math; From f5203bba8a025342aa0a9d335e855989b40ffb38 Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Fri, 10 Aug 2018 14:10:51 -0400 Subject: [PATCH 2/3] Handle exceptions from JSON::stringify --- crates/js-sys/src/lib.rs | 4 ++-- crates/js-sys/tests/wasm/JSON.js | 4 ++++ crates/js-sys/tests/wasm/JSON.rs | 26 ++++++++++++++++++++++++-- 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 crates/js-sys/tests/wasm/JSON.js diff --git a/crates/js-sys/src/lib.rs b/crates/js-sys/src/lib.rs index caaf9cdac..282c77d6b 100644 --- a/crates/js-sys/src/lib.rs +++ b/crates/js-sys/src/lib.rs @@ -2683,8 +2683,8 @@ extern "C" { /// specified. /// /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify - #[wasm_bindgen(static_method_of = JSON)] - pub fn stringify(obj: &JsValue) -> JsString; + #[wasm_bindgen(catch, static_method_of = JSON)] + pub fn stringify(obj: &JsValue) -> Result; } diff --git a/crates/js-sys/tests/wasm/JSON.js b/crates/js-sys/tests/wasm/JSON.js new file mode 100644 index 000000000..796bd2007 --- /dev/null +++ b/crates/js-sys/tests/wasm/JSON.js @@ -0,0 +1,4 @@ +exports.set_in_object = function(obj, name, value) { + obj[name] = value; +}; + diff --git a/crates/js-sys/tests/wasm/JSON.rs b/crates/js-sys/tests/wasm/JSON.rs index 70ece6e8f..c7f0f4bb2 100644 --- a/crates/js-sys/tests/wasm/JSON.rs +++ b/crates/js-sys/tests/wasm/JSON.rs @@ -1,8 +1,15 @@ use wasm_bindgen::JsValue; use wasm_bindgen_test::*; +use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; use js_sys::*; + +#[wasm_bindgen(module = "tests/wasm/JSON.js")] +extern { + fn set_in_object(obj: &Object, name: &str, value: &JsValue); +} + #[wasm_bindgen_test] fn parse_array() { @@ -63,7 +70,22 @@ fn stringify() { arr.push(&JsValue::from(true)); arr.push(&JsValue::from("hello")); - let str = JSON::stringify(&JsValue::from(arr)); + let str = JSON::stringify(&JsValue::from(arr)).unwrap(); let rust_str: String = From::from(str); assert_eq!(rust_str, "[1,true,\"hello\"]"); -} \ No newline at end of file +} + +#[wasm_bindgen_test] +fn stringify_error() { + let func = Function::new_no_args("throw new Error(\"rust really rocks\")"); + let obj = Object::new(); + set_in_object(&obj, "toJSON", &JsValue::from(func)); + + let result = JSON::stringify(&JsValue::from(obj)); + assert!(result.is_err()); + let err_obj = result.unwrap_err(); + assert!(err_obj.is_instance_of::()); + let err: &Error = err_obj.dyn_ref().unwrap(); + let err_msg: String = From::from(err.message()); + assert!(err_msg.contains("rust really rocks")); +} From 1092816652d6da212825cc11cb9a339b9c84b97f Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Fri, 10 Aug 2018 14:33:21 -0400 Subject: [PATCH 3/3] Use Reflect::set instead of javascript helper --- crates/js-sys/tests/wasm/JSON.js | 4 ---- crates/js-sys/tests/wasm/JSON.rs | 9 +-------- 2 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 crates/js-sys/tests/wasm/JSON.js diff --git a/crates/js-sys/tests/wasm/JSON.js b/crates/js-sys/tests/wasm/JSON.js deleted file mode 100644 index 796bd2007..000000000 --- a/crates/js-sys/tests/wasm/JSON.js +++ /dev/null @@ -1,4 +0,0 @@ -exports.set_in_object = function(obj, name, value) { - obj[name] = value; -}; - diff --git a/crates/js-sys/tests/wasm/JSON.rs b/crates/js-sys/tests/wasm/JSON.rs index c7f0f4bb2..b1d9fd184 100644 --- a/crates/js-sys/tests/wasm/JSON.rs +++ b/crates/js-sys/tests/wasm/JSON.rs @@ -1,15 +1,8 @@ use wasm_bindgen::JsValue; use wasm_bindgen_test::*; -use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; use js_sys::*; - -#[wasm_bindgen(module = "tests/wasm/JSON.js")] -extern { - fn set_in_object(obj: &Object, name: &str, value: &JsValue); -} - #[wasm_bindgen_test] fn parse_array() { @@ -79,7 +72,7 @@ fn stringify() { fn stringify_error() { let func = Function::new_no_args("throw new Error(\"rust really rocks\")"); let obj = Object::new(); - set_in_object(&obj, "toJSON", &JsValue::from(func)); + Reflect::set(obj.as_ref(), &JsValue::from("toJSON"), func.as_ref()); let result = JSON::stringify(&JsValue::from(obj)); assert!(result.is_err());