From 89b487d36e6df8964b21decf7897f580741f7a3d Mon Sep 17 00:00:00 2001 From: Nick Little Date: Mon, 18 May 2020 20:54:04 -0500 Subject: [PATCH] handle json stringification for arrays --- boa/src/builtins/json/tests.rs | 40 ++++++++++++++++++++++++++++++++++ boa/src/builtins/value/mod.rs | 38 +++++++++++++++++++++++--------- 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/boa/src/builtins/json/tests.rs b/boa/src/builtins/json/tests.rs index 14cb344e5ff..34c6b9266a9 100644 --- a/boa/src/builtins/json/tests.rs +++ b/boa/src/builtins/json/tests.rs @@ -102,3 +102,43 @@ fn json_stringify_replacer_function() { let expected = forward(&mut engine, r#"'{"bbb":2}'"#); assert_eq!(actual, expected); } + +#[test] +fn json_stringify_arrays() { + let realm = Realm::create(); + let mut engine = Executor::new(realm); + let actual = forward(&mut engine, r#"JSON.stringify(['a', 'b'])"#); + let expected = forward(&mut engine, r#"'["a","b"]'"#); + + assert_eq!(actual, expected); +} + +#[test] +fn json_stringify_object_array() { + let realm = Realm::create(); + let mut engine = Executor::new(realm); + let actual = forward(&mut engine, r#"JSON.stringify([{a: 'b'}, {b: 'c'}])"#); + let expected = forward(&mut engine, r#"'[{"a":"b"},{"b":"c"}]'"#); + + assert_eq!(actual, expected); +} + +#[test] +fn json_stringify_array_converts_undefined_to_null() { + let realm = Realm::create(); + let mut engine = Executor::new(realm); + let actual = forward(&mut engine, r#"JSON.stringify([undefined])"#); + let expected = forward(&mut engine, r#"'[null]'"#); + + assert_eq!(actual, expected); +} + +#[test] +fn json_stringify_array_converts_function_to_null() { + let realm = Realm::create(); + let mut engine = Executor::new(realm); + let actual = forward(&mut engine, r#"JSON.stringify([() => {}])"#); + let expected = forward(&mut engine, r#"'[null]'"#); + + assert_eq!(actual, expected); +} diff --git a/boa/src/builtins/value/mod.rs b/boa/src/builtins/value/mod.rs index f4c813f7143..b461a7f8aaf 100644 --- a/boa/src/builtins/value/mod.rs +++ b/boa/src/builtins/value/mod.rs @@ -682,24 +682,42 @@ impl ValueData { /// Conversts the `Value` to `JSON`. pub fn to_json(&self) -> JSONValue { match *self { - Self::Null | Self::Symbol(_) | Self::Undefined => JSONValue::Null, + Self::Null => JSONValue::Null, Self::Boolean(b) => JSONValue::Bool(b), Self::Object(ref obj) => { - let mut new_obj = Map::new(); - obj.borrow().properties.iter().for_each(|(k, _)| { - let key = k.clone(); - let value = self.get_field_slice(k); - if !value.is_undefined() && !value.is_function() { - new_obj.insert(key, value.to_json()); - } - }); - JSONValue::Object(new_obj) + if obj.borrow().kind == ObjectKind::Array { + let mut arr: Vec = Vec::new(); + obj.borrow().properties.iter().for_each(|(k, _)| { + if k != "length" { + let value = self.get_field_slice(k); + if value.is_undefined() || value.is_function() { + arr.push(JSONValue::Null); + } else { + arr.push(self.get_field_slice(k).to_json()); + } + } + }); + JSONValue::Array(arr) + } else { + let mut new_obj = Map::new(); + obj.borrow().properties.iter().for_each(|(k, _)| { + let key = k.clone(); + let value = self.get_field_slice(k); + if !value.is_undefined() && !value.is_function() { + new_obj.insert(key, value.to_json()); + } + }); + JSONValue::Object(new_obj) + } } Self::String(ref str) => JSONValue::String(str.clone()), Self::Rational(num) => JSONValue::Number( JSONNumber::from_f64(num).expect("Could not convert to JSONNumber"), ), Self::Integer(val) => JSONValue::Number(JSONNumber::from(val)), + Self::Symbol(_) | Self::Undefined => { + panic!("Symbols and Undefined depend on parent type"); + } } }