diff --git a/crates/js-sys/src/lib.rs b/crates/js-sys/src/lib.rs index 39aaa452da2..cf70f3511df 100644 --- a/crates/js-sys/src/lib.rs +++ b/crates/js-sys/src/lib.rs @@ -3783,15 +3783,49 @@ extern "C" { #[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. + /// The `JSON.stringify()` method converts a JavaScript value to a JSON string. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) #[wasm_bindgen(catch, static_method_of = JSON)] pub fn stringify(obj: &JsValue) -> Result; + /// The `JSON.stringify()` method converts a JavaScript value to a JSON string. + /// + /// The `replacer` argument is a function that alters the behavior of the stringification + /// process, or an array of String and Number objects that serve as a whitelist + /// for selecting/filtering the properties of the value object to be included + /// in the JSON string. If this value is null or not provided, all properties + /// of the object are included in the resulting JSON string. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) + #[wasm_bindgen(catch, static_method_of = JSON, js_name = stringify)] + pub fn stringify_with_replacer(obj: &JsValue, replacer: &JsValue) -> Result; + + /// The `JSON.stringify()` method converts a JavaScript value to a JSON string. + /// + /// The `replacer` argument is a function that alters the behavior of the stringification + /// process, or an array of String and Number objects that serve as a whitelist + /// for selecting/filtering the properties of the value object to be included + /// in the JSON string. If this value is null or not provided, all properties + /// of the object are included in the resulting JSON string. + /// + /// The `space` argument is a String or Number object that's used to insert white space into + /// the output JSON string for readability purposes. If this is a Number, it + /// indicates the number of space characters to use as white space; this number + /// is capped at 10 (if it is greater, the value is just 10). Values less than + /// 1 indicate that no space should be used. If this is a String, the string + /// (or the first 10 characters of the string, if it's longer than that) is + /// used as white space. If this parameter is not provided (or is null), no + /// white space is used. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) + #[wasm_bindgen(catch, static_method_of = JSON, js_name = stringify)] + pub fn stringify_with_replacer_and_space( + obj: &JsValue, + replacer: &JsValue, + space: &JsValue, + ) -> Result; + } // JsString diff --git a/crates/js-sys/tests/wasm/JSON.rs b/crates/js-sys/tests/wasm/JSON.rs index bc7a1c287c7..c9a3257d010 100644 --- a/crates/js-sys/tests/wasm/JSON.rs +++ b/crates/js-sys/tests/wasm/JSON.rs @@ -59,9 +59,13 @@ fn stringify() { arr.push(&JsValue::from(true)); arr.push(&JsValue::from("hello")); - let str = JSON::stringify(&JsValue::from(arr)).unwrap(); - let rust_str: String = From::from(str); - assert_eq!(rust_str, "[1,true,\"hello\"]"); + let str1: String = JSON::stringify(&JsValue::from(arr)).unwrap().into(); + assert_eq!(str1, "[1,true,\"hello\"]"); + + let obj = Object::new(); + Reflect::set(obj.as_ref(), &JsValue::from("foo"), &JsValue::from("bar")).unwrap(); + let str2: String = JSON::stringify(&JsValue::from(obj)).unwrap().into(); + assert_eq!(str2, "{\"foo\":\"bar\"}"); } #[wasm_bindgen_test] @@ -79,6 +83,122 @@ fn stringify_error() { assert!(err_msg.contains("rust really rocks")); } +#[wasm_bindgen_test] +fn stringify_with_replacer() { + let obj = Object::new(); + Reflect::set(obj.as_ref(), &JsValue::from("foo"), &JsValue::from("bar")).unwrap(); + Reflect::set( + obj.as_ref(), + &JsValue::from("hello"), + &JsValue::from("world"), + ) + .unwrap(); + + let replacer_array = Array::new(); + replacer_array.push(&JsValue::from("hello")); + let output1: String = + JSON::stringify_with_replacer(&JsValue::from(obj.clone()), &JsValue::from(replacer_array)) + .unwrap() + .into(); + assert_eq!(output1, "{\"hello\":\"world\"}"); + + let replacer_func = + Function::new_no_args("return arguments[0] === 'hello' ? undefined : arguments[1]"); + let output2: String = + JSON::stringify_with_replacer(&JsValue::from(obj), &JsValue::from(replacer_func)) + .unwrap() + .into(); + assert_eq!(output2, "{\"foo\":\"bar\"}"); +} + +#[wasm_bindgen_test] +fn stringify_with_replacer_error() { + let arr = Array::new(); + arr.push(&JsValue::from(1)); + arr.push(&JsValue::from(true)); + arr.push(&JsValue::from("hello")); + + let replacer = Function::new_no_args("throw new Error(\"rust really rocks\")"); + + let result = JSON::stringify_with_replacer(&JsValue::from(arr), &JsValue::from(replacer)); + 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")); +} + +#[wasm_bindgen_test] +fn stringify_with_replacer_and_space() { + let arr = Array::new(); + arr.push(&JsValue::from(1)); + arr.push(&JsValue::from(true)); + arr.push(&JsValue::from("hello")); + + let output1: String = JSON::stringify_with_replacer_and_space( + &JsValue::from(arr), + &JsValue::NULL, + &JsValue::from(4), + ) + .unwrap() + .into(); + assert_eq!(output1, "[\n 1,\n true,\n \"hello\"\n]"); + + let obj = Object::new(); + Reflect::set(obj.as_ref(), &JsValue::from("foo"), &JsValue::from("bar")).unwrap(); + Reflect::set( + obj.as_ref(), + &JsValue::from("hello"), + &JsValue::from("world"), + ) + .unwrap(); + + let replacer_array = Array::new(); + replacer_array.push(&JsValue::from("hello")); + let output2: String = JSON::stringify_with_replacer_and_space( + &JsValue::from(obj.clone()), + &JsValue::from(replacer_array), + &JsValue::from(4), + ) + .unwrap() + .into(); + assert_eq!(output2, "{\n \"hello\": \"world\"\n}"); + + let replacer_func = + Function::new_no_args("return arguments[0] === 'hello' ? undefined : arguments[1]"); + let output3: String = JSON::stringify_with_replacer_and_space( + &JsValue::from(obj), + &JsValue::from(replacer_func), + &JsValue::from(4), + ) + .unwrap() + .into(); + assert_eq!(output3, "{\n \"foo\": \"bar\"\n}"); +} + +#[wasm_bindgen_test] +fn stringify_with_replacer_and_space_error() { + let arr = Array::new(); + arr.push(&JsValue::from(1)); + arr.push(&JsValue::from(true)); + arr.push(&JsValue::from("hello")); + + let replacer = Function::new_no_args("throw new Error(\"rust really rocks\")"); + + let result = JSON::stringify_with_replacer_and_space( + &JsValue::from(arr), + &JsValue::from(replacer), + &JsValue::from(4), + ); + 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")); +} + #[wasm_bindgen_test] fn json_extends() { #[wasm_bindgen]