1// Copyright JS Foundation and other contributors, http://js.foundation 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// This test will not pass on FLOAT32 due to precision issues 16 17// Checking primitve types 18var str; 19var result; 20var log; 21 22function check_parse_error (str) 23{ 24 try { 25 JSON.parse (str); 26 // Should throw a parse error. 27 assert (false); 28 } catch (e) { 29 } 30} 31 32str = ' null '; 33assert (JSON.parse (str) === null); 34str = 'true'; 35assert (JSON.parse (str) === true); 36str = 'false'; 37assert (JSON.parse (str) === false); 38str = '-32.5e002'; 39assert (JSON.parse (str) == -3250); 40str = '"str"'; 41assert (JSON.parse (str) == "str"); 42str = '"\\b\\f\\n\\t\\r"' 43assert (JSON.parse (str) === "\b\f\n\t\r"); 44/* Note: \u is parsed by the lexer, \\u is by the JSON parser. */ 45str = '"\\u0000\\u001f"'; 46assert (JSON.parse (str) === "\x00\x1f"); 47str = '"\\ud801\\udc00\\ud801\udc00\ud801\\udc00\ud801\udc00"'; 48assert (JSON.parse (str) === "\ud801\udc00\ud801\udc00\ud801\udc00\ud801\udc00"); 49/* These surrogates do not form a valid surrogate pairs. */ 50str = '"\\ud801,\\udc00,\\ud801,\udc00,\ud801,\\udc00,\ud801,\udc00"'; 51assert (JSON.parse (str) === "\ud801,\udc00,\ud801,\udc00,\ud801,\udc00,\ud801,\udc00"); 52 53check_parse_error ('undefined'); 54check_parse_error ('falses'); 55check_parse_error ('+5'); 56check_parse_error ('5.'); 57check_parse_error ('01'); 58check_parse_error ('0x1'); 59check_parse_error ('0e-'); 60check_parse_error ('3e+a'); 61check_parse_error ('55e4,'); 62check_parse_error ('5 true'); 63check_parse_error ("'str'"); 64check_parse_error ('\x00'); 65check_parse_error ('"\x00"'); 66check_parse_error ('"\x1f"'); 67 68// Checking objects 69str = ' { "x": 0, "yy": null, "zzz": { "A": 4.0, "BB": { "1": 63e-1 }, "CCC" : false } } '; 70result = JSON.parse (str); 71assert (typeof result == "object"); 72assert (result.x === 0); 73assert (result.yy === null); 74assert (typeof result.zzz == "object"); 75assert (result.zzz.A === 4); 76assert (typeof result.zzz.BB == "object"); 77assert (result.zzz.BB["1"] === 6.3); 78assert (result.zzz.CCC === false); 79 80check_parse_error ('{'); 81check_parse_error ('{{{}'); 82check_parse_error ('{x:5}'); 83check_parse_error ('{true:4}'); 84check_parse_error ('{"x":5 "y":6}'); 85check_parse_error ('{"x":5,"y":6,}'); 86check_parse_error ('{"x":5,,"y":6}'); 87 88// Checking arrays 89str = '[{"x":[]},[[]],{}, [ null ] ]'; 90result = JSON.parse (str); 91assert (result.length === 4); 92assert (typeof result === "object"); 93assert (typeof result[0] === "object"); 94assert (typeof result[0].x === "object"); 95assert (result[0].x.length === 0); 96assert (result[1].length === 1); 97assert (result[1][0].length === 0); 98assert (typeof result[2] === "object"); 99assert (result[3].length === 1); 100assert (result[3][0] === null); 101 102check_parse_error ('['); 103check_parse_error ('[[[]'); 104check_parse_error ('[ true null ]'); 105check_parse_error ('[1,,2]'); 106check_parse_error ('[1,2,]'); 107check_parse_error ('[1] [2]'); 108 109// Checking parse with different primitive types 110 111assert (JSON.parse (null) == null); 112assert (JSON.parse (true) == true); 113assert (JSON.parse (3) == 3); 114 115try { 116 JSON.parse (undefined); 117 // Should not be reached. 118 assert (false); 119} catch (e) { 120 assert (e instanceof SyntaxError); 121} 122 123// Checking parse with different object types 124 125object = { toString: function() { return false; } }; 126assert (JSON.parse (object) == false); 127 128object = {"a": 3, "b": "foo"}; 129try { 130 JSON.parse (object); 131 // Should not be reached. 132 assert (false); 133} catch (e) { 134 assert (e instanceof SyntaxError); 135} 136 137array = [3, "foo"]; 138try { 139 JSON.parse (array); 140 // Should not be reached. 141 assert (false); 142} catch (e) { 143 assert (e instanceof SyntaxError); 144} 145 146assert (JSON.parse (new Number (3)) == 3); 147assert (JSON.parse (new Boolean (true)) == true); 148 149object = new String ('{"a": 3, "b": "foo"}'); 150result = JSON.parse (object); 151 152assert (result.a == 3); 153assert (result.b == "foo"); 154 155// Checking reviver 156 157function toStringReviver(k, v) 158{ 159 log += "<" + k + ">:" + (typeof v == "number" ? v : "(obj)") + ", "; 160 return v; 161} 162 163str = '{ "a":1, "b":2, "c": { "d":4, "e": { "f":6 } } }'; 164log = ""; 165JSON.parse (str, toStringReviver); 166assert (log === "<a>:1, <b>:2, <d>:4, <f>:6, <e>:(obj), <c>:(obj), <>:(obj), "); 167 168str = '[ 32, 47, 33 ]'; 169log = ""; 170JSON.parse (str, toStringReviver); 171assert (log === "<0>:32, <1>:47, <2>:33, <>:(obj), "); 172 173// Defining properties multiple times 174 175str = ' { "a":1, "b":2, "a":3 } '; 176log = ""; 177JSON.parse (str, toStringReviver); 178assert (log === "<a>:3, <b>:2, <>:(obj), "); 179 180str = ' { "a":1, "b":2, "b":3 } '; 181log = ""; 182JSON.parse (str, toStringReviver); 183assert (log === "<a>:1, <b>:3, <>:(obj), "); 184 185str = ' { "a":1, "b":{}, "b":[], "a":2, "b":3, "c":4 } '; 186log = ""; 187JSON.parse (str, toStringReviver); 188assert (log === "<a>:2, <b>:3, <c>:4, <>:(obj), "); 189 190// Changing property value 191 192str = ' { "a":1, "b":2, "c":3 } '; 193result = JSON.parse (str, function (k, v) { 194 if (k == "a") 195 { 196 return 8; 197 } 198 if (k == "b") 199 { 200 return 9; 201 } 202 if (k == "c") 203 { 204 return void 0; 205 } 206 return v; 207}); 208 209assert (result.a === 8); 210assert (result.b === 9); 211assert (result.c === void 0); 212 213// Adding / deleting properties 214 215str = ' { "a":1, "b":2 } '; 216log = ""; 217result = JSON.parse (str, function (k, v) { 218 if (k == "a") 219 { 220 // Deleted properties must still be enumerated. 221 delete this["b"]; 222 // New properties must not be enumerated. 223 this.c = 4; 224 } 225 if (k != "") 226 { 227 log += "<" + k + ">:" + v + " "; 228 } 229 return v; 230}); 231 232assert (log === "<a>:1 <b>:undefined "); 233assert (result.a === 1); 234assert (result.b === void 0); 235assert (result.c === 4); 236 237// Changing properties to accessors 238 239str = ' { "a":1, "b":2, "c":3 } '; 240log = ""; 241JSON.parse (str, function (k, v) { 242 if (k == "a") 243 { 244 Object.defineProperty(this, "b", { 245 enumerable: true, 246 configurable: true, 247 get: function() { return 12; } 248 }); 249 Object.defineProperty(this, "c", { 250 enumerable: true, 251 configurable: true, 252 set: function(val) { } 253 }); 254 } 255 if (k != "") 256 { 257 log += "<" + k + ">:" + v + " "; 258 } 259 return v; 260}); 261assert (log === "<a>:1 <b>:12 <c>:undefined "); 262 263// Forcing extra walk steps 264 265str = ' { "a":1, "b":2 } '; 266log = ""; 267JSON.parse (str, function (k, v) { 268 if (k == "a") 269 { 270 this.b = { x:3, y:4 }; 271 } 272 if (k != "") 273 { 274 log += "<" + k + ">:" + v + " "; 275 } 276 return v; 277}); 278assert (log === "<a>:1 <x>:3 <y>:4 <b>:[object Object] "); 279 280// Setting a property to read-only, and change its value. 281 282str = ' { "a":1, "b":2 } '; 283result = JSON.parse (str, function (k, v) { 284 if (k == "a") 285 { 286 Object.defineProperty(this, "b", { 287 enumerable: true, 288 // FIXME: Should work with configurable: true. 289 configurable: false, 290 writable: false, 291 value: 2 292 }); 293 return 8; 294 } 295 if (k == "b") 296 { 297 return 9; 298 } 299 return v; 300}); 301 302assert (result.a === 8); 303assert (result.b === 2); 304 305// Throw error in the reviver 306 307try { 308 str = ' { "a":1, "b":2 } '; 309 result = JSON.parse (str, function (k, v) { throw new ReferenceError("error"); } ); 310 assert(false); 311} catch (e) { 312 assert (e.message === "error"); 313 assert (e instanceof ReferenceError); 314} 315 316// Throw error in a getter 317 318try { 319 str = ' { "a":1, "b":2 } '; 320 JSON.parse (str, function (k, v) { 321 if (k == "a") 322 { 323 Object.defineProperty(this, "b", { 324 enumerable: true, 325 configurable: true, 326 get: function() { throw new ReferenceError("error"); } 327 }); 328 } 329 return v; 330 }); 331 assert(false); 332} catch (e) { 333 assert (e.message === "error"); 334 assert (e instanceof ReferenceError); 335} 336 337// Checking reviver with different primitive types 338 339str = ' { "a":1 } '; 340 341result = JSON.parse (str, 4); 342assert (result.a == 1); 343 344result = JSON.parse (str, null); 345assert (result.a == 1); 346 347result = JSON.parse (str, undefined); 348assert (result.a == 1); 349 350result = JSON.parse (str, true); 351assert (result.a == 1); 352 353result = JSON.parse (str, "foo"); 354assert (result.a == 1); 355 356// Checking reviver with different object types 357 358str = ' { "a":1 } '; 359 360result = JSON.parse(str, new Boolean (true)); 361assert (result.a == 1); 362 363result = JSON.parse(str, new String ("foo")); 364assert (result.a == 1); 365 366result = JSON.parse(str, new Number (3)); 367assert (result.a == 1); 368 369result = JSON.parse(str, {"a": 2}); 370assert (result.a == 1); 371 372result = JSON.parse(str, [1, 2, 3]); 373assert (result.a == 1); 374