1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction GenericToJSONChecks(Constructor, value, alternative) { 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var n1 = new Constructor(value); 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block n1.valueOf = function () { return alternative; }; 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assertEquals(alternative, n1.toJSON()); 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var n2 = new Constructor(value); 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block n2.valueOf = null; 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assertThrows(function () { n2.toJSON(); }, TypeError); 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var n3 = new Constructor(value); 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block n3.valueOf = function () { return {}; }; 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assertThrows(function () { n3.toJSON(); }, TypeError, 'result_not_primitive'); 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var n4 = new Constructor(value); 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block n4.valueOf = function () { 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assertEquals(0, arguments.length); 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assertEquals(this, n4); 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return null; 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assertEquals(null, n4.toJSON()); 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Number toJSON 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(3, (3).toJSON()); 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(3, (3).toJSON(true)); 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(4, (new Number(4)).toJSON()); 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockGenericToJSONChecks(Number, 5, 6); 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Boolean toJSON 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(true, (true).toJSON()); 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(true, (true).toJSON(false)); 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(false, (false).toJSON()); 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(true, (new Boolean(true)).toJSON()); 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockGenericToJSONChecks(Boolean, true, false); 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockGenericToJSONChecks(Boolean, false, true); 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// String toJSON 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("flot", "flot".toJSON()); 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("flot", "flot".toJSON(3)); 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("tolf", (new String("tolf")).toJSON()); 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockGenericToJSONChecks(String, "x", "y"); 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Date toJSON 68e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeassertEquals("1970-01-01T00:00:00.000Z", new Date(0).toJSON()); 69e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeassertEquals("1979-01-11T08:00:00.000Z", new Date("1979-01-11 08:00 GMT").toJSON()); 70e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeassertEquals("2005-05-05T05:05:05.000Z", new Date("2005-05-05 05:05:05 GMT").toJSON()); 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvar n1 = new Date(10000); 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockn1.toISOString = function () { return "foo"; }; 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("foo", n1.toJSON()); 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvar n2 = new Date(10001); 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockn2.toISOString = null; 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertThrows(function () { n2.toJSON(); }, TypeError); 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvar n3 = new Date(10002); 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockn3.toISOString = function () { return {}; }; 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertThrows(function () { n3.toJSON(); }, TypeError, "result_not_primitive"); 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvar n4 = new Date(10003); 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockn4.toISOString = function () { 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assertEquals(0, arguments.length); 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assertEquals(this, n4); 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return null; 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(null, n4.toJSON()); 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(Object.prototype, JSON.__proto__); 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("[object JSON]", Object.prototype.toString.call(JSON)); 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DontEnum 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfor (var p in this) 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assertFalse(p == "JSON"); 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Parse 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals({}, JSON.parse("{}")); 974515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals({42:37}, JSON.parse('{"42":37}')); 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(null, JSON.parse("null")); 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(true, JSON.parse("true")); 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(false, JSON.parse("false")); 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("foo", JSON.parse('"foo"')); 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("f\no", JSON.parse('"f\\no"')); 1034515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals("\b\f\n\r\t\"\u2028\/\\", 1044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke JSON.parse('"\\b\\f\\n\\r\\t\\"\\u2028\\/\\\\"')); 1054515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals([1.1], JSON.parse("[1.1]")); 1064515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals([1], JSON.parse("[1.0]")); 1074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1084515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(0, JSON.parse("0")); 1094515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(1, JSON.parse("1")); 1104515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(0.1, JSON.parse("0.1")); 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(1.1, JSON.parse("1.1")); 1124515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(1.1, JSON.parse("1.100000")); 1134515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(1.111111, JSON.parse("1.111111")); 1144515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(-0, JSON.parse("-0")); 1154515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(-1, JSON.parse("-1")); 1164515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(-0.1, JSON.parse("-0.1")); 1174515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(-1.1, JSON.parse("-1.1")); 1184515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(-1.1, JSON.parse("-1.100000")); 1194515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(-1.111111, JSON.parse("-1.111111")); 1204515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(11, JSON.parse("1.1e1")); 1214515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(11, JSON.parse("1.1e+1")); 1224515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(0.11, JSON.parse("1.1e-1")); 1234515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(11, JSON.parse("1.1E1")); 1244515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(11, JSON.parse("1.1E+1")); 1254515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(0.11, JSON.parse("1.1E-1")); 1264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals([], JSON.parse("[]")); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals([1], JSON.parse("[1]")); 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals([1, "2", true, null], JSON.parse('[1, "2", true, null]')); 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1314515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals("", JSON.parse('""')); 1324515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals(["", "", -0, ""], JSON.parse('[ "" , "" , -0, ""]')); 1334515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeassertEquals("", JSON.parse('""')); 1344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction GetFilter(name) { 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block function Filter(key, value) { 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (key == name) ? undefined : value; 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Filter; 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvar pointJson = '{"x": 1, "y": 2}'; 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals({'x': 1, 'y': 2}, JSON.parse(pointJson)); 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals({'x': 1}, JSON.parse(pointJson, GetFilter('y'))); 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals({'y': 2}, JSON.parse(pointJson, GetFilter('x'))); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals([1, 2, 3], JSON.parse("[1, 2, 3]")); 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals([1, undefined, 3], JSON.parse("[1, 2, 3]", GetFilter(1))); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals([1, 2, undefined], JSON.parse("[1, 2, 3]", GetFilter(2))); 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction DoubleNumbers(key, value) { 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (typeof value == 'number') ? 2 * value : value; 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvar deepObject = '{"a": {"b": 1, "c": 2}, "d": {"e": {"f": 3}}}'; 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals({"a": {"b": 1, "c": 2}, "d": {"e": {"f": 3}}}, 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSON.parse(deepObject)); 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals({"a": {"b": 2, "c": 4}, "d": {"e": {"f": 6}}}, 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSON.parse(deepObject, DoubleNumbers)); 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction TestInvalid(str) { 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assertThrows(function () { JSON.parse(str); }, SyntaxError); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTestInvalid('abcdef'); 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTestInvalid('isNaN()'); 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTestInvalid('{"x": [1, 2, deepObject]}'); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTestInvalid('[1, [2, [deepObject], 3], 4]'); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTestInvalid('function () { return 0; }'); 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTestInvalid("[1, 2"); 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTestInvalid('{"x": 3'); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke// JavaScript number literals not valid in JSON. 1754515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('[01]'); 1764515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('[.1]'); 1774515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('[1.]'); 1784515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('[1.e1]'); 1794515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('[-.1]'); 1804515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('[-1.]'); 1814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke// Plain invalid number literals. 1834515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('-'); 1844515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('--1'); 1854515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('-1e'); 1864515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('1e--1]'); 1874515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('1e+-1'); 1884515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('1e-+1'); 1894515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('1e++1'); 1904515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke// JavaScript string literals not valid in JSON. 1924515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid("'single quote'"); // Valid JavaScript 1934515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('"\\a invalid escape"'); 1944515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('"\\v invalid escape"'); // Valid JavaScript 1954515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('"\\\' invalid escape"'); // Valid JavaScript 1964515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('"\\x42 invalid escape"'); // Valid JavaScript 1974515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('"\\u202 invalid escape"'); 1984515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('"\\012 invalid escape"'); 1994515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('"Unterminated string'); 2004515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('"Unterminated string\\"'); 2014515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('"Unterminated string\\\\\\"'); 2024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// JavaScript RegExp literals not valid in JSON. 2043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuTestInvalid('/true/'); 2054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Test bad JSON that would be good JavaScript (ES5). 2074515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid("{true:42}"); 2084515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid("{false:42}"); 2094515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid("{null:42}"); 2104515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid("{'foo':42}"); 2114515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid("{42:42}"); 2124515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid("{0:42}"); 2134515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid("{-1:42}"); 2144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke// Test for trailing garbage detection. 2164515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('42 px'); 2174515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('42 .2'); 2184515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('42 2'); 2194515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('42 e1'); 2204515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('"42" ""'); 2214515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('"42" ""'); 2224515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('"" ""'); 2234515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('true ""'); 2244515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('false ""'); 2254515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('null ""'); 2264515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('null ""'); 2274515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('[] ""'); 2284515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('[true] ""'); 2294515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('{} ""'); 2304515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('{"x":true} ""'); 2314515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('"Garbage""After string"'); 2324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Stringify 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("true", JSON.stringify(true)); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("false", JSON.stringify(false)); 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("null", JSON.stringify(null)); 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("false", JSON.stringify({toJSON: function () { return false; }})); 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("4", JSON.stringify(4)); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals('"foo"', JSON.stringify("foo")); 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("null", JSON.stringify(Infinity)); 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("null", JSON.stringify(-Infinity)); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("null", JSON.stringify(NaN)); 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("4", JSON.stringify(new Number(4))); 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals('"bar"', JSON.stringify(new String("bar"))); 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals('"foo\\u0000bar"', JSON.stringify("foo\0bar")); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals('"f\\"o\'o\\\\b\\ba\\fr\\nb\\ra\\tz"', 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSON.stringify("f\"o\'o\\b\ba\fr\nb\ra\tz")); 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("[1,2,3]", JSON.stringify([1, 2, 3])); 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("[\n 1,\n 2,\n 3\n]", JSON.stringify([1, 2, 3], null, 1)); 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("[\n 1,\n 2,\n 3\n]", JSON.stringify([1, 2, 3], null, 2)); 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("[\n 1,\n 2,\n 3\n]", 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSON.stringify([1, 2, 3], null, new Number(2))); 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("[\n^1,\n^2,\n^3\n]", JSON.stringify([1, 2, 3], null, "^")); 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("[\n^1,\n^2,\n^3\n]", 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSON.stringify([1, 2, 3], null, new String("^"))); 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("[\n 1,\n 2,\n [\n 3,\n [\n 4\n ],\n 5\n ],\n 6,\n 7\n]", 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSON.stringify([1, 2, [3, [4], 5], 6, 7], null, 1)); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("[]", JSON.stringify([], null, 1)); 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("[1,2,[3,[4],5],6,7]", 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSON.stringify([1, 2, [3, [4], 5], 6, 7], null)); 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("[2,4,[6,[8],10],12,14]", 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSON.stringify([1, 2, [3, [4], 5], 6, 7], DoubleNumbers)); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvar circular = [1, 2, 3]; 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockcircular[2] = circular; 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertThrows(function () { JSON.stringify(circular); }, TypeError); 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvar singleton = []; 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvar multiOccurrence = [singleton, singleton, singleton]; 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals("[[],[],[]]", JSON.stringify(multiOccurrence)); 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals('{"x":5,"y":6}', JSON.stringify({x:5,y:6})); 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals('{"x":5}', JSON.stringify({x:5,y:6}, ['x'])); 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals('{\n "a": "b",\n "c": "d"\n}', 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSON.stringify({a:"b",c:"d"}, null, 1)); 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals('{"y":6,"x":5}', JSON.stringify({x:5,y:6}, ['y', 'x'])); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// The gap is capped at ten characters if specified as string. 2823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuassertEquals('{\n "a": "b",\n "c": "d"\n}', 2833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu JSON.stringify({a:"b",c:"d"}, null, 2843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu " /*characters after 10th*/")); 2853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//The gap is capped at ten characters if specified as number. 2873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuassertEquals('{\n "a": "b",\n "c": "d"\n}', 2883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu JSON.stringify({a:"b",c:"d"}, null, 15)); 2893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Replaced wrapped primitives are unwrapped. 2913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescufunction newx(k, v) { return (k == "x") ? new v(42) : v; } 2923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuassertEquals('{"x":"42"}', JSON.stringify({x: String}, newx)); 2933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuassertEquals('{"x":42}', JSON.stringify({x: Number}, newx)); 2943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuassertEquals('{"x":true}', JSON.stringify({x: Boolean}, newx)); 2953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(undefined, JSON.stringify(undefined)); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockassertEquals(undefined, JSON.stringify(function () { })); 2983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Arrays with missing, undefined or function elements have those elements 2993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// replaced by null. 3003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuassertEquals("[null,null,null]", 3013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu JSON.stringify([undefined,,function(){}])); 3023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Objects with undefined or function properties (including replaced properties) 3043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// have those properties ignored. 3053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuassertEquals('{}', 3063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu JSON.stringify({a: undefined, b: function(){}, c: 42, d: 42}, 3073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu function(k, v) { if (k == "c") return undefined; 3083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (k == "d") return function(){}; 3093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return v; })); 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3114515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('1); throw "foo"; (1'); 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvar x = 0; 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockeval("(1); x++; (1)"); 3154515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTestInvalid('1); x++; (1'); 316