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

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

Issue 5676005: Fix regression in JSON serialization of RegExps. (Closed)
Patch Set: Address review comments. 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 d = {toJSON: Date.prototype.toJSON,
51 toISOString: function() { return 42; }};
52 assertEquals(42, d.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()"); // 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
Rico 2010/12/15 09:17:04 Add a test that we throw an exception if we have a
Lasse Reichstein 2010/12/15 09:29:41 Added test: var d7 = {toJSON: Date.prototype.toJS
91 // DontEnum 82 // DontEnum
92 for (var p in this) 83 for (var p in this)
93 assertFalse(p == "JSON"); 84 assertFalse(p == "JSON");
94 85
95 // Parse 86 // Parse
96 assertEquals({}, JSON.parse("{}")); 87 assertEquals({}, JSON.parse("{}"));
97 assertEquals({42:37}, JSON.parse('{"42":37}')); 88 assertEquals({42:37}, JSON.parse('{"42":37}'));
98 assertEquals(null, JSON.parse("null")); 89 assertEquals(null, JSON.parse("null"));
99 assertEquals(true, JSON.parse("true")); 90 assertEquals(true, JSON.parse("true"));
100 assertEquals(false, JSON.parse("false")); 91 assertEquals(false, JSON.parse("false"));
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 assertEquals('{"y":6,"x":5}', JSON.stringify({x:5,y:6}, ['y', 'x'])); 270 assertEquals('{"y":6,"x":5}', JSON.stringify({x:5,y:6}, ['y', 'x']));
280 271
281 // toJSON get string keys. 272 // toJSON get string keys.
282 var checker = {}; 273 var checker = {};
283 var array = [checker]; 274 var array = [checker];
284 checker.toJSON = function(key) { return 1 + key; }; 275 checker.toJSON = function(key) { return 1 + key; };
285 assertEquals('["10"]', JSON.stringify(array)); 276 assertEquals('["10"]', JSON.stringify(array));
286 277
287 // The gap is capped at ten characters if specified as string. 278 // The gap is capped at ten characters if specified as string.
288 assertEquals('{\n "a": "b",\n "c": "d"\n}', 279 assertEquals('{\n "a": "b",\n "c": "d"\n}',
289 JSON.stringify({a:"b",c:"d"}, null, 280 JSON.stringify({a:"b",c:"d"}, null,
290 " /*characters after 10th*/")); 281 " /*characters after 10th*/"));
291 282
292 //The gap is capped at ten characters if specified as number. 283 //The gap is capped at ten characters if specified as number.
293 assertEquals('{\n "a": "b",\n "c": "d"\n}', 284 assertEquals('{\n "a": "b",\n "c": "d"\n}',
294 JSON.stringify({a:"b",c:"d"}, null, 15)); 285 JSON.stringify({a:"b",c:"d"}, null, 15));
295 286
296 // Replaced wrapped primitives are unwrapped. 287 // Replaced wrapped primitives are unwrapped.
297 function newx(k, v) { return (k == "x") ? new v(42) : v; } 288 function newx(k, v) { return (k == "x") ? new v(42) : v; }
298 assertEquals('{"x":"42"}', JSON.stringify({x: String}, newx)); 289 assertEquals('{"x":"42"}', JSON.stringify({x: String}, newx));
299 assertEquals('{"x":42}', JSON.stringify({x: Number}, newx)); 290 assertEquals('{"x":42}', JSON.stringify({x: Number}, newx));
300 assertEquals('{"x":true}', JSON.stringify({x: Boolean}, newx)); 291 assertEquals('{"x":true}', JSON.stringify({x: Boolean}, newx));
301 292
302 assertEquals(undefined, JSON.stringify(undefined)); 293 assertEquals(undefined, JSON.stringify(undefined));
303 assertEquals(undefined, JSON.stringify(function () { })); 294 assertEquals(undefined, JSON.stringify(function () { }));
304 // Arrays with missing, undefined or function elements have those elements 295 // Arrays with missing, undefined or function elements have those elements
305 // replaced by null. 296 // replaced by null.
306 assertEquals("[null,null,null]", 297 assertEquals("[null,null,null]",
307 JSON.stringify([undefined,,function(){}])); 298 JSON.stringify([undefined,,function(){}]));
308 299
309 // Objects with undefined or function properties (including replaced properties) 300 // Objects with undefined or function properties (including replaced properties)
310 // have those properties ignored. 301 // have those properties ignored.
311 assertEquals('{}', 302 assertEquals('{}',
312 JSON.stringify({a: undefined, b: function(){}, c: 42, d: 42}, 303 JSON.stringify({a: undefined, b: function(){}, c: 42, d: 42},
313 function(k, v) { if (k == "c") return undefined; 304 function(k, v) { if (k == "c") return undefined;
314 if (k == "d") return function(){}; 305 if (k == "d") return function(){};
315 return v; })); 306 return v; }));
316 307
317 TestInvalid('1); throw "foo"; (1'); 308 TestInvalid('1); throw "foo"; (1');
318 309
319 var x = 0; 310 var x = 0;
320 eval("(1); x++; (1)"); 311 eval("(1); x++; (1)");
321 TestInvalid('1); x++; (1'); 312 TestInvalid('1); x++; (1');
322 313
323 // Test string conversion of argument. 314 // Test string conversion of argument.
324 var o = { toString: function() { return "42"; } }; 315 var o = { toString: function() { return "42"; } };
325 assertEquals(42, JSON.parse(o)); 316 assertEquals(42, JSON.parse(o));
326 317
327 318
328 for (var i = 0; i < 65536; i++) { 319 for (var i = 0; i < 65536; i++) {
329 var string = String.fromCharCode(i); 320 var string = String.fromCharCode(i);
330 var encoded = JSON.stringify(string); 321 var encoded = JSON.stringify(string);
331 var expected = "uninitialized"; 322 var expected = "uninitialized";
332 // Following the ES5 specification of the abstraction function Quote. 323 // Following the ES5 specification of the abstraction function Quote.
333 if (string == '"' || string == '\\') { 324 if (string == '"' || string == '\\') {
334 // Step 2.a 325 // Step 2.a
335 expected = '\\' + string; 326 expected = '\\' + string;
336 } else if ("\b\t\n\r\f".indexOf(string) >= 0) { 327 } else if ("\b\t\n\r\f".indexOf(string) >= 0) {
337 // Step 2.b 328 // Step 2.b
338 if (string == '\b') expected = '\\b'; 329 if (string == '\b') expected = '\\b';
339 else if (string == '\t') expected = '\\t'; 330 else if (string == '\t') expected = '\\t';
340 else if (string == '\n') expected = '\\n'; 331 else if (string == '\n') expected = '\\n';
341 else if (string == '\f') expected = '\\f'; 332 else if (string == '\f') expected = '\\f';
342 else if (string == '\r') expected = '\\r'; 333 else if (string == '\r') expected = '\\r';
343 } else if (i < 32) { 334 } else if (i < 32) {
344 // Step 2.c 335 // Step 2.c
345 if (i < 16) { 336 if (i < 16) {
346 expected = "\\u000" + i.toString(16); 337 expected = "\\u000" + i.toString(16);
347 } else { 338 } else {
348 expected = "\\u00" + i.toString(16); 339 expected = "\\u00" + i.toString(16);
349 } 340 }
350 } else { 341 } else {
351 expected = string; 342 expected = string;
352 } 343 }
353 assertEquals('"' + expected + '"', encoded, "Codepoint " + i); 344 assertEquals('"' + expected + '"', encoded, "Codepoint " + i);
354 } 345 }
346
347
348 // Ensure that wrappers and callables are handled correctly.
349 var num37 = new Number(42);
350 num37.valueOf = function() { return 37; };
351
352 var numFoo = new Number(42);
353 numFoo.valueOf = "not callable";
354 numFoo.toString = function() { return "foo"; };
355
356 var numTrue = new Number(42);
357 numTrue.valueOf = function() { return true; }
358
359 var strFoo = new String("bar");
360 strFoo.toString = function() { return "foo"; };
361
362 var str37 = new String("bar");
363 str37.toString = "not callable";
364 str37.valueOf = function() { return 37; };
365
366 var strTrue = new String("bar");
367 strTrue.toString = function() { return true; }
368
369 var func = function() { /* Is callable */ };
370
371 var funcJSON = function() { /* Is callable */ };
372 funcJSON.toJSON = function() { return "has toJSON"; };
373
374 var re = /Is callable/;
375
376 var reJSON = /Is callable/;
377 reJSON.toJSON = function() { return "has toJSON"; };
378
379 assertEquals(
380 '[37,null,1,"foo","37","true",null,"has toJSON",null,"has toJSON"]',
381 JSON.stringify([num37, numFoo, numTrue,
382 strFoo, str37, strTrue,
383 func, funcJSON, re, reJSON]));
384
385
386 var oddball = Object(42);
387 oddball.__proto__ = { __proto__: null, toString: function() { return true; } };
388 assertEquals('1', JSON.stringify(oddball));
389
390 var getCount = 0;
391 var callCount = 0;
392 var counter = { get toJSON() { getCount++;
393 return function() { callCount++;
394 return 42; }; } };
395 assertEquals('42', JSON.stringify(counter));
396 assertEquals(1, getCount);
397 assertEquals(1, callCount);
398
399 var oddball2 = Object(42);
400 var oddball3 = Object("foo");
401 oddball3.__proto__ = { __proto__: null,
402 toString: "not callable",
403 valueOf: function() { return true; } };
404 oddball2.__proto__ = { __proto__: null,
405 toJSON: function () { return oddball3; } }
406 assertEquals('"true"', JSON.stringify(oddball2));
407
408
409 var falseNum = Object("37");
410 falseNum.__proto__ = Number.prototype;
411 falseNum.toString = function() { return 42; };
412 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