Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: test/mjsunit/json.js

Issue 5676005: Fix regression in JSON serialization of RegExps. (Closed)
Patch Set: Added test. Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/v8natives.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 function GenericToJSONChecks(Constructor, value, alternative) {
29 var n1 = new Constructor(value);
30 n1.valueOf = function () { return alternative; };
31 assertEquals(alternative, n1.toJSON());
32 var n2 = new Constructor(value);
33 n2.valueOf = null;
34 assertThrows(function () { n2.toJSON(); }, TypeError);
35 var n3 = new Constructor(value);
36 n3.valueOf = function () { return {}; };
37 assertThrows(function () { n3.toJSON(); }, TypeError, 'result_not_primitive');
38 var n4 = new Constructor(value);
39 n4.valueOf = function () {
40 assertEquals(0, arguments.length);
41 assertEquals(this, n4);
42 return null;
43 };
44 assertEquals(null, n4.toJSON());
45 }
46
47 // Number toJSON
48 assertEquals(3, (3).toJSON());
49 assertEquals(3, (3).toJSON(true));
50 assertEquals(4, (new Number(4)).toJSON());
51 GenericToJSONChecks(Number, 5, 6);
52
53 // Boolean toJSON
54 assertEquals(true, (true).toJSON());
55 assertEquals(true, (true).toJSON(false));
56 assertEquals(false, (false).toJSON());
57 assertEquals(true, (new Boolean(true)).toJSON());
58 GenericToJSONChecks(Boolean, true, false);
59 GenericToJSONChecks(Boolean, false, true);
60
61 // String toJSON
62 assertEquals("flot", "flot".toJSON());
63 assertEquals("flot", "flot".toJSON(3));
64 assertEquals("tolf", (new String("tolf")).toJSON());
65 GenericToJSONChecks(String, "x", "y");
66
67 // Date toJSON 28 // Date toJSON
68 assertEquals("1970-01-01T00:00:00.000Z", new Date(0).toJSON()); 29 assertEquals("1970-01-01T00:00:00.000Z", new Date(0).toJSON());
69 assertEquals("1979-01-11T08:00:00.000Z", new Date("1979-01-11 08:00 GMT").toJSON ()); 30 assertEquals("1979-01-11T08:00:00.000Z", new Date("1979-01-11 08:00 GMT").toJSON ());
70 assertEquals("2005-05-05T05:05:05.000Z", new Date("2005-05-05 05:05:05 GMT").toJ SON()); 31 assertEquals("2005-05-05T05:05:05.000Z", new Date("2005-05-05 05:05:05 GMT").toJ SON());
71 var n1 = new Date(10000); 32 var n1 = new Date(10000);
72 n1.toISOString = function () { return "foo"; }; 33 n1.toISOString = function () { return "foo"; };
73 assertEquals("foo", n1.toJSON()); 34 assertEquals("foo", n1.toJSON());
74 var n2 = new Date(10001); 35 var n2 = new Date(10001);
75 n2.toISOString = null; 36 n2.toISOString = null;
76 assertThrows(function () { n2.toJSON(); }, TypeError); 37 assertThrows(function () { n2.toJSON(); }, TypeError);
77 var n3 = new Date(10002);
78 n3.toISOString = function () { return {}; };
79 assertThrows(function () { n3.toJSON(); }, TypeError, "result_not_primitive");
80 var n4 = new Date(10003); 38 var n4 = new Date(10003);
81 n4.toISOString = function () { 39 n4.toISOString = function () {
82 assertEquals(0, arguments.length); 40 assertEquals(0, arguments.length);
83 assertEquals(this, n4); 41 assertEquals(this, n4);
84 return null; 42 return null;
85 }; 43 };
86 assertEquals(null, n4.toJSON()); 44 assertEquals(null, n4.toJSON());
87 45
88 assertTrue(Object.prototype === JSON.__proto__); 46 assertTrue(Object.prototype === JSON.__proto__);
89 assertEquals("[object JSON]", Object.prototype.toString.call(JSON)); 47 assertEquals("[object JSON]", Object.prototype.toString.call(JSON));
90 48
49 //Test Date.prototype.toJSON as generic function.
50 var d1 = {toJSON: Date.prototype.toJSON,
51 toISOString: function() { return 42; }};
52 assertEquals(42, d1.toJSON());
53
54 var d2 = {toJSON: Date.prototype.toJSON,
55 valueOf: function() { return Infinity; },
56 toISOString: function() { return 42; }};
57 assertEquals(null, d2.toJSON());
58
59 var d3 = {toJSON: Date.prototype.toJSON,
60 valueOf: "not callable",
61 toString: function() { return Infinity; },
62 toISOString: function() { return 42; }};
63
64 assertEquals(null, d3.toJSON());
65
66 var d4 = {toJSON: Date.prototype.toJSON,
67 valueOf: "not callable",
68 toString: "not callable either",
69 toISOString: function() { return 42; }};
70 assertThrows("d4.toJSON()", TypeError); // ToPrimitive throws.
71
72 var d5 = {toJSON: Date.prototype.toJSON,
73 valueOf: "not callable",
74 toString: function() { return "Infinity"; },
75 toISOString: function() { return 42; }};
76 assertEquals(42, d5.toJSON());
77
78 var d6 = {toJSON: Date.prototype.toJSON,
79 toISOString: function() { return ["not primitive"]; }};
80 assertEquals(["not primitive"], d6.toJSON());
81
82 var d7 = {toJSON: Date.prototype.toJSON,
83 ISOString: "not callable"};
84 assertThrows("d7.toJSON()", TypeError);
85
91 // DontEnum 86 // DontEnum
92 for (var p in this) 87 for (var p in this) {
93 assertFalse(p == "JSON"); 88 assertFalse(p == "JSON");
89 }
94 90
95 // Parse 91 // Parse
96 assertEquals({}, JSON.parse("{}")); 92 assertEquals({}, JSON.parse("{}"));
97 assertEquals({42:37}, JSON.parse('{"42":37}')); 93 assertEquals({42:37}, JSON.parse('{"42":37}'));
98 assertEquals(null, JSON.parse("null")); 94 assertEquals(null, JSON.parse("null"));
99 assertEquals(true, JSON.parse("true")); 95 assertEquals(true, JSON.parse("true"));
100 assertEquals(false, JSON.parse("false")); 96 assertEquals(false, JSON.parse("false"));
101 assertEquals("foo", JSON.parse('"foo"')); 97 assertEquals("foo", JSON.parse('"foo"'));
102 assertEquals("f\no", JSON.parse('"f\\no"')); 98 assertEquals("f\no", JSON.parse('"f\\no"'));
103 assertEquals("\b\f\n\r\t\"\u2028\/\\", 99 assertEquals("\b\f\n\r\t\"\u2028\/\\",
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 assertEquals('{"y":6,"x":5}', JSON.stringify({x:5,y:6}, ['y', 'x'])); 275 assertEquals('{"y":6,"x":5}', JSON.stringify({x:5,y:6}, ['y', 'x']));
280 276
281 // toJSON get string keys. 277 // toJSON get string keys.
282 var checker = {}; 278 var checker = {};
283 var array = [checker]; 279 var array = [checker];
284 checker.toJSON = function(key) { return 1 + key; }; 280 checker.toJSON = function(key) { return 1 + key; };
285 assertEquals('["10"]', JSON.stringify(array)); 281 assertEquals('["10"]', JSON.stringify(array));
286 282
287 // The gap is capped at ten characters if specified as string. 283 // The gap is capped at ten characters if specified as string.
288 assertEquals('{\n "a": "b",\n "c": "d"\n}', 284 assertEquals('{\n "a": "b",\n "c": "d"\n}',
289 JSON.stringify({a:"b",c:"d"}, null, 285 JSON.stringify({a:"b",c:"d"}, null,
290 " /*characters after 10th*/")); 286 " /*characters after 10th*/"));
291 287
292 //The gap is capped at ten characters if specified as number. 288 //The gap is capped at ten characters if specified as number.
293 assertEquals('{\n "a": "b",\n "c": "d"\n}', 289 assertEquals('{\n "a": "b",\n "c": "d"\n}',
294 JSON.stringify({a:"b",c:"d"}, null, 15)); 290 JSON.stringify({a:"b",c:"d"}, null, 15));
295 291
296 // Replaced wrapped primitives are unwrapped. 292 // Replaced wrapped primitives are unwrapped.
297 function newx(k, v) { return (k == "x") ? new v(42) : v; } 293 function newx(k, v) { return (k == "x") ? new v(42) : v; }
298 assertEquals('{"x":"42"}', JSON.stringify({x: String}, newx)); 294 assertEquals('{"x":"42"}', JSON.stringify({x: String}, newx));
299 assertEquals('{"x":42}', JSON.stringify({x: Number}, newx)); 295 assertEquals('{"x":42}', JSON.stringify({x: Number}, newx));
300 assertEquals('{"x":true}', JSON.stringify({x: Boolean}, newx)); 296 assertEquals('{"x":true}', JSON.stringify({x: Boolean}, newx));
301 297
302 assertEquals(undefined, JSON.stringify(undefined)); 298 assertEquals(undefined, JSON.stringify(undefined));
303 assertEquals(undefined, JSON.stringify(function () { })); 299 assertEquals(undefined, JSON.stringify(function () { }));
304 // Arrays with missing, undefined or function elements have those elements 300 // Arrays with missing, undefined or function elements have those elements
305 // replaced by null. 301 // replaced by null.
306 assertEquals("[null,null,null]", 302 assertEquals("[null,null,null]",
307 JSON.stringify([undefined,,function(){}])); 303 JSON.stringify([undefined,,function(){}]));
308 304
309 // Objects with undefined or function properties (including replaced properties) 305 // Objects with undefined or function properties (including replaced properties)
310 // have those properties ignored. 306 // have those properties ignored.
311 assertEquals('{}', 307 assertEquals('{}',
312 JSON.stringify({a: undefined, b: function(){}, c: 42, d: 42}, 308 JSON.stringify({a: undefined, b: function(){}, c: 42, d: 42},
313 function(k, v) { if (k == "c") return undefined; 309 function(k, v) { if (k == "c") return undefined;
314 if (k == "d") return function(){}; 310 if (k == "d") return function(){};
315 return v; })); 311 return v; }));
316 312
317 TestInvalid('1); throw "foo"; (1'); 313 TestInvalid('1); throw "foo"; (1');
318 314
319 var x = 0; 315 var x = 0;
320 eval("(1); x++; (1)"); 316 eval("(1); x++; (1)");
321 TestInvalid('1); x++; (1'); 317 TestInvalid('1); x++; (1');
322 318
323 // Test string conversion of argument. 319 // Test string conversion of argument.
324 var o = { toString: function() { return "42"; } }; 320 var o = { toString: function() { return "42"; } };
325 assertEquals(42, JSON.parse(o)); 321 assertEquals(42, JSON.parse(o));
326 322
327 323
328 for (var i = 0; i < 65536; i++) { 324 for (var i = 0; i < 65536; i++) {
329 var string = String.fromCharCode(i); 325 var string = String.fromCharCode(i);
330 var encoded = JSON.stringify(string); 326 var encoded = JSON.stringify(string);
331 var expected = "uninitialized"; 327 var expected = "uninitialized";
332 // Following the ES5 specification of the abstraction function Quote. 328 // Following the ES5 specification of the abstraction function Quote.
333 if (string == '"' || string == '\\') { 329 if (string == '"' || string == '\\') {
334 // Step 2.a 330 // Step 2.a
335 expected = '\\' + string; 331 expected = '\\' + string;
336 } else if ("\b\t\n\r\f".indexOf(string) >= 0) { 332 } else if ("\b\t\n\r\f".indexOf(string) >= 0) {
337 // Step 2.b 333 // Step 2.b
338 if (string == '\b') expected = '\\b'; 334 if (string == '\b') expected = '\\b';
339 else if (string == '\t') expected = '\\t'; 335 else if (string == '\t') expected = '\\t';
340 else if (string == '\n') expected = '\\n'; 336 else if (string == '\n') expected = '\\n';
341 else if (string == '\f') expected = '\\f'; 337 else if (string == '\f') expected = '\\f';
342 else if (string == '\r') expected = '\\r'; 338 else if (string == '\r') expected = '\\r';
343 } else if (i < 32) { 339 } else if (i < 32) {
344 // Step 2.c 340 // Step 2.c
345 if (i < 16) { 341 if (i < 16) {
346 expected = "\\u000" + i.toString(16); 342 expected = "\\u000" + i.toString(16);
347 } else { 343 } else {
348 expected = "\\u00" + i.toString(16); 344 expected = "\\u00" + i.toString(16);
349 } 345 }
350 } else { 346 } else {
351 expected = string; 347 expected = string;
352 } 348 }
353 assertEquals('"' + expected + '"', encoded, "Codepoint " + i); 349 assertEquals('"' + expected + '"', encoded, "Codepoint " + i);
354 } 350 }
351
352
353 // Ensure that wrappers and callables are handled correctly.
354 var num37 = new Number(42);
355 num37.valueOf = function() { return 37; };
356
357 var numFoo = new Number(42);
358 numFoo.valueOf = "not callable";
359 numFoo.toString = function() { return "foo"; };
360
361 var numTrue = new Number(42);
362 numTrue.valueOf = function() { return true; }
363
364 var strFoo = new String("bar");
365 strFoo.toString = function() { return "foo"; };
366
367 var str37 = new String("bar");
368 str37.toString = "not callable";
369 str37.valueOf = function() { return 37; };
370
371 var strTrue = new String("bar");
372 strTrue.toString = function() { return true; }
373
374 var func = function() { /* Is callable */ };
375
376 var funcJSON = function() { /* Is callable */ };
377 funcJSON.toJSON = function() { return "has toJSON"; };
378
379 var re = /Is callable/;
380
381 var reJSON = /Is callable/;
382 reJSON.toJSON = function() { return "has toJSON"; };
383
384 assertEquals(
385 '[37,null,1,"foo","37","true",null,"has toJSON",null,"has toJSON"]',
386 JSON.stringify([num37, numFoo, numTrue,
387 strFoo, str37, strTrue,
388 func, funcJSON, re, reJSON]));
389
390
391 var oddball = Object(42);
392 oddball.__proto__ = { __proto__: null, toString: function() { return true; } };
393 assertEquals('1', JSON.stringify(oddball));
394
395 var getCount = 0;
396 var callCount = 0;
397 var counter = { get toJSON() { getCount++;
398 return function() { callCount++;
399 return 42; }; } };
400 assertEquals('42', JSON.stringify(counter));
401 assertEquals(1, getCount);
402 assertEquals(1, callCount);
403
404 var oddball2 = Object(42);
405 var oddball3 = Object("foo");
406 oddball3.__proto__ = { __proto__: null,
407 toString: "not callable",
408 valueOf: function() { return true; } };
409 oddball2.__proto__ = { __proto__: null,
410 toJSON: function () { return oddball3; } }
411 assertEquals('"true"', JSON.stringify(oddball2));
412
413
414 var falseNum = Object("37");
415 falseNum.__proto__ = Number.prototype;
416 falseNum.toString = function() { return 42; };
417 assertEquals('"42"', JSON.stringify(falseNum));
OLDNEW
« no previous file with comments | « src/v8natives.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698