diff options
Diffstat (limited to 'js/src/tests/test262/built-ins/JSON')
150 files changed, 4919 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/JSON/15.12-0-1.js b/js/src/tests/test262/built-ins/JSON/15.12-0-1.js new file mode 100644 index 0000000000..6af7fc3113 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/15.12-0-1.js @@ -0,0 +1,17 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +info: | + This test should be run without any built-ins being added/augmented. + The name JSON must be bound to an object. + 4.2 calls out JSON as one of the built-in objects. +es5id: 15.12-0-1 +description: JSON must be a built-in object +---*/ + +var o = JSON; + +assert.sameValue(typeof(o), "object", 'typeof(o)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/15.12-0-2.js b/js/src/tests/test262/built-ins/JSON/15.12-0-2.js new file mode 100644 index 0000000000..f9c4ecf391 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/15.12-0-2.js @@ -0,0 +1,18 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +info: | + This test should be run without any built-ins being added/augmented. + The name JSON must be bound to an object, and must not support [[Construct]]. + step 4 in 11.2.2 should throw a TypeError exception. +es5id: 15.12-0-2 +description: JSON must not support the [[Construct]] method +---*/ + +var o = JSON; +assert.throws(TypeError, function() { + var j = new JSON(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/15.12-0-3.js b/js/src/tests/test262/built-ins/JSON/15.12-0-3.js new file mode 100644 index 0000000000..1467f19db2 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/15.12-0-3.js @@ -0,0 +1,18 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +info: | + This test should be run without any built-ins being added/augmented. + The name JSON must be bound to an object, and must not support [[Call]]. + step 5 in 11.2.3 should throw a TypeError exception. +es5id: 15.12-0-3 +description: JSON must not support the [[Call]] method +---*/ + +var o = JSON; +assert.throws(TypeError, function() { + var j = JSON(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/15.12-0-4.js b/js/src/tests/test262/built-ins/JSON/15.12-0-4.js new file mode 100644 index 0000000000..f07e43608e --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/15.12-0-4.js @@ -0,0 +1,24 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +info: | + This test should be run without any built-ins being added/augmented. + The last paragraph in section 15 says "every other property described + in this section has the attribute {... [[Enumerable]] : false ...} + unless otherwise specified. This default applies to the properties on + JSON, and we should not be able to enumerate them. +es5id: 15.12-0-4 +description: JSON object's properties must be non enumerable +---*/ + +var o = JSON; +var i = 0; +for (var p in o) { + i++; +} + + +assert.sameValue(i, 0, 'i'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/Symbol.toStringTag.js b/js/src/tests/test262/built-ins/JSON/Symbol.toStringTag.js new file mode 100644 index 0000000000..4edc1c932b --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/Symbol.toStringTag.js @@ -0,0 +1,23 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 24.3.3 +description: > + `Symbol.toStringTag` property descriptor +info: | + The initial value of the @@toStringTag property is the String value + "JSON". + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Symbol.toStringTag] +---*/ + +assert.sameValue(JSON[Symbol.toStringTag], 'JSON'); + +verifyNotEnumerable(JSON, Symbol.toStringTag); +verifyNotWritable(JSON, Symbol.toStringTag); +verifyConfigurable(JSON, Symbol.toStringTag); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/browser.js b/js/src/tests/test262/built-ins/JSON/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/browser.js diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-1.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-1.js new file mode 100644 index 0000000000..ae9059ed5b --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-1.js @@ -0,0 +1,13 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-0-1 +description: The JSON lexical grammar treats whitespace as a token seperator +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('12\t\r\n 34'); // should produce a syntax error as whitespace results in two tokens +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-2.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-2.js new file mode 100644 index 0000000000..7cb3e4fc2d --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-2.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-0-2 +description: > + <VT> is not valid JSON whitespace as specified by the production + JSONWhitespace. +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('\u000b1234'); // should produce a syntax error +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-3.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-3.js new file mode 100644 index 0000000000..b6436fa204 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-3.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-0-3 +description: > + <FF> is not valid JSON whitespace as specified by the production + JSONWhitespace. +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('\u000c1234'); // should produce a syntax error +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-4.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-4.js new file mode 100644 index 0000000000..448066da70 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-4.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-0-4 +description: > + <NBSP> is not valid JSON whitespace as specified by the production + JSONWhitespace. +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('\u00a01234'); // should produce a syntax error +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-5.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-5.js new file mode 100644 index 0000000000..0d0b9d0e1b --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-5.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-0-5 +description: > + <ZWSPP> is not valid JSON whitespace as specified by the + production JSONWhitespace. +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('\u200b1234'); // should produce a syntax error +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-6.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-6.js new file mode 100644 index 0000000000..07c7436077 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-6.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-0-6 +description: > + <BOM> is not valid JSON whitespace as specified by the production + JSONWhitespace. +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('\ufeff1234'); // should produce a syntax error a +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-8.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-8.js new file mode 100644 index 0000000000..c2a49dbb58 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-8.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-0-8 +description: > + U+2028 and U+2029 are not valid JSON whitespace as specified by + the production JSONWhitespace. +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('\u2028\u20291234'); // should produce a syntax error +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-9.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-9.js new file mode 100644 index 0000000000..04a9d306a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-9.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-0-9 +description: Whitespace characters can appear before/after any JSONtoken +---*/ + +JSON.parse('\t\r \n{\t\r \n' + + '"property"\t\r \n:\t\r \n{\t\r \n}\t\r \n,\t\r \n' + + '"prop2"\t\r \n:\t\r \n' + + '[\t\r \ntrue\t\r \n,\t\r \nnull\t\r \n,123.456\t\r \n]' + + '\t\r \n}\t\r \n'); // should JOSN parse without error + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-1.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-1.js new file mode 100644 index 0000000000..64bddfb579 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-1.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g1-1 +description: The JSON lexical grammar treats <TAB> as a whitespace character +---*/ + +assert.sameValue(JSON.parse('\t1234'), 1234, '<TAB> should be ignored'); + +assert.throws(SyntaxError, function() { + JSON.parse('12\t34'); +}, '<TAB> should produce a syntax error as whitespace results in two tokens'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-2.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-2.js new file mode 100644 index 0000000000..53a0261914 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-2.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g1-2 +description: The JSON lexical grammar treats <CR> as a whitespace character +---*/ + +assert.sameValue(JSON.parse('\r1234'), 1234, '<cr> should be ignored'); + +assert.throws(SyntaxError, function() { + JSON.parse('12\r34'); +}, '<CR> should produce a syntax error as whitespace results in two tokens'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-3.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-3.js new file mode 100644 index 0000000000..b846ff548c --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-3.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g1-3 +description: The JSON lexical grammar treats <LF> as a whitespace character +---*/ + +assert.sameValue(JSON.parse('\n1234'), 1234, '<LF> should be ignored'); + +assert.throws(SyntaxError, function() { + JSON.parse('12\n34'); +}, '<LF> should produce a syntax error as whitespace results in two tokens'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-4.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-4.js new file mode 100644 index 0000000000..ba29db50da --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-4.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g1-4 +description: The JSON lexical grammar treats <SP> as a whitespace character +---*/ + +assert.sameValue(JSON.parse(' 1234'), 1234, '<SP> should be ignored'); + +assert.throws(SyntaxError, function() { + JSON.parse('12 34'); +}, '<SP> should produce a syntax error as whitespace results in two tokens'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-1.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-1.js new file mode 100644 index 0000000000..f39bb364b6 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-1.js @@ -0,0 +1,11 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g2-1 +description: JSONStrings can be written using double quotes +---*/ + +assert.sameValue(JSON.parse('"abc"'), "abc", 'JSON.parse(\'"abc"\')'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-2.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-2.js new file mode 100644 index 0000000000..28379cace7 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-2.js @@ -0,0 +1,13 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g2-2 +description: A JSONString may not be delimited by single quotes +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse("'abc'"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-3.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-3.js new file mode 100644 index 0000000000..4a0e5ad382 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-3.js @@ -0,0 +1,13 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g2-3 +description: A JSONString may not be delimited by Uncode escaped quotes +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse("\\u0022abc\\u0022"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-4.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-4.js new file mode 100644 index 0000000000..0e366108bc --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-4.js @@ -0,0 +1,13 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g2-4 +description: A JSONString must both begin and end with double quotes +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('"ab'+"c'"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-5.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-5.js new file mode 100644 index 0000000000..51fd1c8e77 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-5.js @@ -0,0 +1,13 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g2-5 +description: > + A JSONStrings can contain no JSONStringCharacters (Empty + JSONStrings) +---*/ + +assert.sameValue(JSON.parse('""'), "", 'JSON.parse(\'""\')'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-1.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-1.js new file mode 100644 index 0000000000..fcbe29740a --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-1.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g4-1 +description: > + The JSON lexical grammar does not allow a JSONStringCharacter to + be any of the Unicode characters U+0000 thru U+0007 +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('"\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007"'); // invalid string characters should produce a syntax error +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-2.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-2.js new file mode 100644 index 0000000000..7d29a50833 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-2.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g4-2 +description: > + The JSON lexical grammar does not allow a JSONStringCharacter to + be any of the Unicode characters U+0008 thru U+000F +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('"\u0008\u0009\u000a\u000b\u000c\u000d\u000e\u000f"'); // invalid string characters should produce a syntax error +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-3.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-3.js new file mode 100644 index 0000000000..94b1a4f02f --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-3.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g4-3 +description: > + The JSON lexical grammar does not allow a JSONStringCharacter to + be any of the Unicode characters U+0010 thru U+0017 +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('"\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017"'); // invalid string characters should produce a syntax error +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-4.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-4.js new file mode 100644 index 0000000000..3df9c206f1 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-4.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g4-4 +description: > + The JSON lexical grammar does not allow a JSONStringCharacter to + be any of the Unicode characters U+0018 thru U+001F +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('"\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f"'); // invalid string characters should produce a syntax error +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g5-1.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g5-1.js new file mode 100644 index 0000000000..80f58f2b52 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g5-1.js @@ -0,0 +1,13 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g5-1 +description: > + The JSON lexical grammar allows Unicode escape sequences in a + JSONString +---*/ + +assert.sameValue(JSON.parse('"\\u0058"'), 'X', 'JSON.parse(\'"\\u0058"\')'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g5-2.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g5-2.js new file mode 100644 index 0000000000..8111eae39d --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g5-2.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g5-2 +description: > + A JSONStringCharacter UnicodeEscape may not have fewer than 4 hex + characters +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('"\\u005"') +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g5-3.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g5-3.js new file mode 100644 index 0000000000..c302bc31ef --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g5-3.js @@ -0,0 +1,15 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g5-3 +description: > + A JSONStringCharacter UnicodeEscape may not include any non=hex + characters +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('"\\u0X50"') +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-1.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-1.js new file mode 100644 index 0000000000..49ed1a4af1 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-1.js @@ -0,0 +1,13 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g6-1 +description: > + The JSON lexical grammer allows '/' as a JSONEscapeCharacter after + '' in a JSONString +---*/ + +assert.sameValue(JSON.parse('"\\/"'), '/', 'JSON.parse(\'"\\/"\')'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-2.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-2.js new file mode 100644 index 0000000000..a9951a0064 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-2.js @@ -0,0 +1,13 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g6-2 +description: > + The JSON lexical grammer allows '' as a JSONEscapeCharacter after + '' in a JSONString +---*/ + +assert.sameValue(JSON.parse('"\\\\"'), '\\', 'JSON.parse(\'"\\\\"\')'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-3.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-3.js new file mode 100644 index 0000000000..d6b3f59919 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-3.js @@ -0,0 +1,13 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g6-3 +description: > + The JSON lexical grammer allows 'b' as a JSONEscapeCharacter after + '' in a JSONString +---*/ + +assert.sameValue(JSON.parse('"\\b"'), '\b', 'JSON.parse(\'"\\b"\')'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-4.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-4.js new file mode 100644 index 0000000000..0788c5ce01 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-4.js @@ -0,0 +1,13 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g6-4 +description: > + The JSON lexical grammer allows 'f' as a JSONEscapeCharacter after + '' in a JSONString +---*/ + +assert.sameValue(JSON.parse('"\\f"'), '\f', 'JSON.parse(\'"\\f"\')'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-5.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-5.js new file mode 100644 index 0000000000..3c53499abd --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-5.js @@ -0,0 +1,13 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g6-5 +description: > + The JSON lexical grammer allows 'n' as a JSONEscapeCharacter after + '' in a JSONString +---*/ + +assert.sameValue(JSON.parse('"\\n"'), '\n', 'JSON.parse(\'"\\n"\')'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-6.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-6.js new file mode 100644 index 0000000000..871c6560e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-6.js @@ -0,0 +1,13 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g6-6 +description: > + The JSON lexical grammer allows 'r' as a JSONEscapeCharacter after + '' in a JSONString +---*/ + +assert.sameValue(JSON.parse('"\\r"'), '\r', 'JSON.parse(\'"\\r"\')'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-7.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-7.js new file mode 100644 index 0000000000..3a44f9fc08 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-7.js @@ -0,0 +1,13 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.1.1-g6-7 +description: > + The JSON lexical grammer allows 't' as a JSONEscapeCharacter after + '' in a JSONString +---*/ + +assert.sameValue(JSON.parse('"\\t"'), '\t', 'JSON.parse(\'"\\t"\')'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-1.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-1.js new file mode 100644 index 0000000000..abb366914a --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-1.js @@ -0,0 +1,51 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.2-2-1 +description: > + JSON.parse - parsing an object where property name is a null + character +---*/ + +var nullChars = new Array(); +nullChars[0] = '\"\u0000\"'; +nullChars[1] = '\"\u0001\"'; +nullChars[2] = '\"\u0002\"'; +nullChars[3] = '\"\u0003\"'; +nullChars[4] = '\"\u0004\"'; +nullChars[5] = '\"\u0005\"'; +nullChars[6] = '\"\u0006\"'; +nullChars[7] = '\"\u0007\"'; +nullChars[8] = '\"\u0008\"'; +nullChars[9] = '\"\u0009\"'; +nullChars[10] = '\"\u000A\"'; +nullChars[11] = '\"\u000B\"'; +nullChars[12] = '\"\u000C\"'; +nullChars[13] = '\"\u000D\"'; +nullChars[14] = '\"\u000E\"'; +nullChars[15] = '\"\u000F\"'; +nullChars[16] = '\"\u0010\"'; +nullChars[17] = '\"\u0011\"'; +nullChars[18] = '\"\u0012\"'; +nullChars[19] = '\"\u0013\"'; +nullChars[20] = '\"\u0014\"'; +nullChars[21] = '\"\u0015\"'; +nullChars[22] = '\"\u0016\"'; +nullChars[23] = '\"\u0017\"'; +nullChars[24] = '\"\u0018\"'; +nullChars[25] = '\"\u0019\"'; +nullChars[26] = '\"\u001A\"'; +nullChars[27] = '\"\u001B\"'; +nullChars[28] = '\"\u001C\"'; +nullChars[29] = '\"\u001D\"'; +nullChars[30] = '\"\u001E\"'; +nullChars[31] = '\"\u001F\"'; + +for (var index in nullChars) { + assert.throws(SyntaxError, function() { + var obj = JSON.parse('{ ' + nullChars[index] + ' : "John" } '); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-10.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-10.js new file mode 100644 index 0000000000..102c7bc53b --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-10.js @@ -0,0 +1,51 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.2-2-10 +description: > + JSON.parse - parsing an object where property value middles with a + null character +---*/ + +var nullChars = new Array(); +nullChars[0] = '\"\u0000\"'; +nullChars[1] = '\"\u0001\"'; +nullChars[2] = '\"\u0002\"'; +nullChars[3] = '\"\u0003\"'; +nullChars[4] = '\"\u0004\"'; +nullChars[5] = '\"\u0005\"'; +nullChars[6] = '\"\u0006\"'; +nullChars[7] = '\"\u0007\"'; +nullChars[8] = '\"\u0008\"'; +nullChars[9] = '\"\u0009\"'; +nullChars[10] = '\"\u000A\"'; +nullChars[11] = '\"\u000B\"'; +nullChars[12] = '\"\u000C\"'; +nullChars[13] = '\"\u000D\"'; +nullChars[14] = '\"\u000E\"'; +nullChars[15] = '\"\u000F\"'; +nullChars[16] = '\"\u0010\"'; +nullChars[17] = '\"\u0011\"'; +nullChars[18] = '\"\u0012\"'; +nullChars[19] = '\"\u0013\"'; +nullChars[20] = '\"\u0014\"'; +nullChars[21] = '\"\u0015\"'; +nullChars[22] = '\"\u0016\"'; +nullChars[23] = '\"\u0017\"'; +nullChars[24] = '\"\u0018\"'; +nullChars[25] = '\"\u0019\"'; +nullChars[26] = '\"\u001A\"'; +nullChars[27] = '\"\u001B\"'; +nullChars[28] = '\"\u001C\"'; +nullChars[29] = '\"\u001D\"'; +nullChars[30] = '\"\u001E\"'; +nullChars[31] = '\"\u001F\"'; + +for (var index in nullChars) { + assert.throws(SyntaxError, function() { + var obj = JSON.parse('{ "name" : ' + "Jo" + nullChars[index] + "hn" + ' } '); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-2.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-2.js new file mode 100644 index 0000000000..6735e36f0e --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-2.js @@ -0,0 +1,51 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.2-2-2 +description: > + JSON.parse - parsing an object where property name starts with a + null character +---*/ + +var nullChars = new Array(); +nullChars[0] = '\"\u0000\"'; +nullChars[1] = '\"\u0001\"'; +nullChars[2] = '\"\u0002\"'; +nullChars[3] = '\"\u0003\"'; +nullChars[4] = '\"\u0004\"'; +nullChars[5] = '\"\u0005\"'; +nullChars[6] = '\"\u0006\"'; +nullChars[7] = '\"\u0007\"'; +nullChars[8] = '\"\u0008\"'; +nullChars[9] = '\"\u0009\"'; +nullChars[10] = '\"\u000A\"'; +nullChars[11] = '\"\u000B\"'; +nullChars[12] = '\"\u000C\"'; +nullChars[13] = '\"\u000D\"'; +nullChars[14] = '\"\u000E\"'; +nullChars[15] = '\"\u000F\"'; +nullChars[16] = '\"\u0010\"'; +nullChars[17] = '\"\u0011\"'; +nullChars[18] = '\"\u0012\"'; +nullChars[19] = '\"\u0013\"'; +nullChars[20] = '\"\u0014\"'; +nullChars[21] = '\"\u0015\"'; +nullChars[22] = '\"\u0016\"'; +nullChars[23] = '\"\u0017\"'; +nullChars[24] = '\"\u0018\"'; +nullChars[25] = '\"\u0019\"'; +nullChars[26] = '\"\u001A\"'; +nullChars[27] = '\"\u001B\"'; +nullChars[28] = '\"\u001C\"'; +nullChars[29] = '\"\u001D\"'; +nullChars[30] = '\"\u001E\"'; +nullChars[31] = '\"\u001F\"'; + +for (var index in nullChars) { + assert.throws(SyntaxError, function() { + var obj = JSON.parse('{ ' + nullChars[index] + "name" + ' : "John" } '); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-3.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-3.js new file mode 100644 index 0000000000..4f1136bc48 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-3.js @@ -0,0 +1,51 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.2-2-3 +description: > + JSON.parse - parsing an object where property name ends with a + null character +---*/ + +var nullChars = new Array(); +nullChars[0] = '\"\u0000\"'; +nullChars[1] = '\"\u0001\"'; +nullChars[2] = '\"\u0002\"'; +nullChars[3] = '\"\u0003\"'; +nullChars[4] = '\"\u0004\"'; +nullChars[5] = '\"\u0005\"'; +nullChars[6] = '\"\u0006\"'; +nullChars[7] = '\"\u0007\"'; +nullChars[8] = '\"\u0008\"'; +nullChars[9] = '\"\u0009\"'; +nullChars[10] = '\"\u000A\"'; +nullChars[11] = '\"\u000B\"'; +nullChars[12] = '\"\u000C\"'; +nullChars[13] = '\"\u000D\"'; +nullChars[14] = '\"\u000E\"'; +nullChars[15] = '\"\u000F\"'; +nullChars[16] = '\"\u0010\"'; +nullChars[17] = '\"\u0011\"'; +nullChars[18] = '\"\u0012\"'; +nullChars[19] = '\"\u0013\"'; +nullChars[20] = '\"\u0014\"'; +nullChars[21] = '\"\u0015\"'; +nullChars[22] = '\"\u0016\"'; +nullChars[23] = '\"\u0017\"'; +nullChars[24] = '\"\u0018\"'; +nullChars[25] = '\"\u0019\"'; +nullChars[26] = '\"\u001A\"'; +nullChars[27] = '\"\u001B\"'; +nullChars[28] = '\"\u001C\"'; +nullChars[29] = '\"\u001D\"'; +nullChars[30] = '\"\u001E\"'; +nullChars[31] = '\"\u001F\"'; + +for (var index in nullChars) { + assert.throws(SyntaxError, function() { + var obj = JSON.parse('{' + "name" + nullChars[index] + ' : "John" } '); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-4.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-4.js new file mode 100644 index 0000000000..9a2c4f5d72 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-4.js @@ -0,0 +1,51 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.2-2-4 +description: > + JSON.parse - parsing an object where property name starts and ends + with a null character +---*/ + +var nullChars = new Array(); +nullChars[0] = '\"\u0000\"'; +nullChars[1] = '\"\u0001\"'; +nullChars[2] = '\"\u0002\"'; +nullChars[3] = '\"\u0003\"'; +nullChars[4] = '\"\u0004\"'; +nullChars[5] = '\"\u0005\"'; +nullChars[6] = '\"\u0006\"'; +nullChars[7] = '\"\u0007\"'; +nullChars[8] = '\"\u0008\"'; +nullChars[9] = '\"\u0009\"'; +nullChars[10] = '\"\u000A\"'; +nullChars[11] = '\"\u000B\"'; +nullChars[12] = '\"\u000C\"'; +nullChars[13] = '\"\u000D\"'; +nullChars[14] = '\"\u000E\"'; +nullChars[15] = '\"\u000F\"'; +nullChars[16] = '\"\u0010\"'; +nullChars[17] = '\"\u0011\"'; +nullChars[18] = '\"\u0012\"'; +nullChars[19] = '\"\u0013\"'; +nullChars[20] = '\"\u0014\"'; +nullChars[21] = '\"\u0015\"'; +nullChars[22] = '\"\u0016\"'; +nullChars[23] = '\"\u0017\"'; +nullChars[24] = '\"\u0018\"'; +nullChars[25] = '\"\u0019\"'; +nullChars[26] = '\"\u001A\"'; +nullChars[27] = '\"\u001B\"'; +nullChars[28] = '\"\u001C\"'; +nullChars[29] = '\"\u001D\"'; +nullChars[30] = '\"\u001E\"'; +nullChars[31] = '\"\u001F\"'; + +for (var index in nullChars) { + assert.throws(SyntaxError, function() { + var obj = JSON.parse('{' + nullChars[index] + "name" + nullChars[index] + ' : "John" } '); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-5.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-5.js new file mode 100644 index 0000000000..25a39033c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-5.js @@ -0,0 +1,51 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.2-2-5 +description: > + JSON.parse - parsing an object where property name middles with a + null character +---*/ + +var nullChars = new Array(); +nullChars[0] = '\"\u0000\"'; +nullChars[1] = '\"\u0001\"'; +nullChars[2] = '\"\u0002\"'; +nullChars[3] = '\"\u0003\"'; +nullChars[4] = '\"\u0004\"'; +nullChars[5] = '\"\u0005\"'; +nullChars[6] = '\"\u0006\"'; +nullChars[7] = '\"\u0007\"'; +nullChars[8] = '\"\u0008\"'; +nullChars[9] = '\"\u0009\"'; +nullChars[10] = '\"\u000A\"'; +nullChars[11] = '\"\u000B\"'; +nullChars[12] = '\"\u000C\"'; +nullChars[13] = '\"\u000D\"'; +nullChars[14] = '\"\u000E\"'; +nullChars[15] = '\"\u000F\"'; +nullChars[16] = '\"\u0010\"'; +nullChars[17] = '\"\u0011\"'; +nullChars[18] = '\"\u0012\"'; +nullChars[19] = '\"\u0013\"'; +nullChars[20] = '\"\u0014\"'; +nullChars[21] = '\"\u0015\"'; +nullChars[22] = '\"\u0016\"'; +nullChars[23] = '\"\u0017\"'; +nullChars[24] = '\"\u0018\"'; +nullChars[25] = '\"\u0019\"'; +nullChars[26] = '\"\u001A\"'; +nullChars[27] = '\"\u001B\"'; +nullChars[28] = '\"\u001C\"'; +nullChars[29] = '\"\u001D\"'; +nullChars[30] = '\"\u001E\"'; +nullChars[31] = '\"\u001F\"'; + +for (var index in nullChars) { + assert.throws(SyntaxError, function() { + var obj = JSON.parse('{ ' + "na" + nullChars[index] + "me" + ' : "John" } '); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-6.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-6.js new file mode 100644 index 0000000000..7d8d572f3d --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-6.js @@ -0,0 +1,51 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.2-2-6 +description: > + JSON.parse - parsing an object where property value is a null + character +---*/ + +var nullChars = new Array(); +nullChars[0] = '\"\u0000\"'; +nullChars[1] = '\"\u0001\"'; +nullChars[2] = '\"\u0002\"'; +nullChars[3] = '\"\u0003\"'; +nullChars[4] = '\"\u0004\"'; +nullChars[5] = '\"\u0005\"'; +nullChars[6] = '\"\u0006\"'; +nullChars[7] = '\"\u0007\"'; +nullChars[8] = '\"\u0008\"'; +nullChars[9] = '\"\u0009\"'; +nullChars[10] = '\"\u000A\"'; +nullChars[11] = '\"\u000B\"'; +nullChars[12] = '\"\u000C\"'; +nullChars[13] = '\"\u000D\"'; +nullChars[14] = '\"\u000E\"'; +nullChars[15] = '\"\u000F\"'; +nullChars[16] = '\"\u0010\"'; +nullChars[17] = '\"\u0011\"'; +nullChars[18] = '\"\u0012\"'; +nullChars[19] = '\"\u0013\"'; +nullChars[20] = '\"\u0014\"'; +nullChars[21] = '\"\u0015\"'; +nullChars[22] = '\"\u0016\"'; +nullChars[23] = '\"\u0017\"'; +nullChars[24] = '\"\u0018\"'; +nullChars[25] = '\"\u0019\"'; +nullChars[26] = '\"\u001A\"'; +nullChars[27] = '\"\u001B\"'; +nullChars[28] = '\"\u001C\"'; +nullChars[29] = '\"\u001D\"'; +nullChars[30] = '\"\u001E\"'; +nullChars[31] = '\"\u001F\"'; + +for (var index in nullChars) { + assert.throws(SyntaxError, function() { + var obj = JSON.parse('{ "name" : ' + nullChars[index] + ' } '); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-7.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-7.js new file mode 100644 index 0000000000..312ee20a88 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-7.js @@ -0,0 +1,51 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.2-2-7 +description: > + JSON.parse - parsing an object where property value starts with a + null character +---*/ + +var nullChars = new Array(); +nullChars[0] = '\"\u0000\"'; +nullChars[1] = '\"\u0001\"'; +nullChars[2] = '\"\u0002\"'; +nullChars[3] = '\"\u0003\"'; +nullChars[4] = '\"\u0004\"'; +nullChars[5] = '\"\u0005\"'; +nullChars[6] = '\"\u0006\"'; +nullChars[7] = '\"\u0007\"'; +nullChars[8] = '\"\u0008\"'; +nullChars[9] = '\"\u0009\"'; +nullChars[10] = '\"\u000A\"'; +nullChars[11] = '\"\u000B\"'; +nullChars[12] = '\"\u000C\"'; +nullChars[13] = '\"\u000D\"'; +nullChars[14] = '\"\u000E\"'; +nullChars[15] = '\"\u000F\"'; +nullChars[16] = '\"\u0010\"'; +nullChars[17] = '\"\u0011\"'; +nullChars[18] = '\"\u0012\"'; +nullChars[19] = '\"\u0013\"'; +nullChars[20] = '\"\u0014\"'; +nullChars[21] = '\"\u0015\"'; +nullChars[22] = '\"\u0016\"'; +nullChars[23] = '\"\u0017\"'; +nullChars[24] = '\"\u0018\"'; +nullChars[25] = '\"\u0019\"'; +nullChars[26] = '\"\u001A\"'; +nullChars[27] = '\"\u001B\"'; +nullChars[28] = '\"\u001C\"'; +nullChars[29] = '\"\u001D\"'; +nullChars[30] = '\"\u001E\"'; +nullChars[31] = '\"\u001F\"'; + +for (var index in nullChars) { + assert.throws(SyntaxError, function() { + var obj = JSON.parse('{ "name" : ' + nullChars[index] + "John" + ' } '); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-8.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-8.js new file mode 100644 index 0000000000..9f25002a2f --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-8.js @@ -0,0 +1,51 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.2-2-8 +description: > + JSON.parse - parsing an object where property value ends with a + null character +---*/ + +var nullChars = new Array(); +nullChars[0] = '\"\u0000\"'; +nullChars[1] = '\"\u0001\"'; +nullChars[2] = '\"\u0002\"'; +nullChars[3] = '\"\u0003\"'; +nullChars[4] = '\"\u0004\"'; +nullChars[5] = '\"\u0005\"'; +nullChars[6] = '\"\u0006\"'; +nullChars[7] = '\"\u0007\"'; +nullChars[8] = '\"\u0008\"'; +nullChars[9] = '\"\u0009\"'; +nullChars[10] = '\"\u000A\"'; +nullChars[11] = '\"\u000B\"'; +nullChars[12] = '\"\u000C\"'; +nullChars[13] = '\"\u000D\"'; +nullChars[14] = '\"\u000E\"'; +nullChars[15] = '\"\u000F\"'; +nullChars[16] = '\"\u0010\"'; +nullChars[17] = '\"\u0011\"'; +nullChars[18] = '\"\u0012\"'; +nullChars[19] = '\"\u0013\"'; +nullChars[20] = '\"\u0014\"'; +nullChars[21] = '\"\u0015\"'; +nullChars[22] = '\"\u0016\"'; +nullChars[23] = '\"\u0017\"'; +nullChars[24] = '\"\u0018\"'; +nullChars[25] = '\"\u0019\"'; +nullChars[26] = '\"\u001A\"'; +nullChars[27] = '\"\u001B\"'; +nullChars[28] = '\"\u001C\"'; +nullChars[29] = '\"\u001D\"'; +nullChars[30] = '\"\u001E\"'; +nullChars[31] = '\"\u001F\"'; + +for (var index in nullChars) { + assert.throws(SyntaxError, function() { + var obj = JSON.parse('{ "name" : ' + "John" + nullChars[index] + ' } '); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-9.js b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-9.js new file mode 100644 index 0000000000..df23a803dd --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-9.js @@ -0,0 +1,51 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 15.12.2-2-9 +description: > + JSON.parse - parsing an object where property value starts and + ends with a null character +---*/ + +var nullChars = new Array(); +nullChars[0] = '\"\u0000\"'; +nullChars[1] = '\"\u0001\"'; +nullChars[2] = '\"\u0002\"'; +nullChars[3] = '\"\u0003\"'; +nullChars[4] = '\"\u0004\"'; +nullChars[5] = '\"\u0005\"'; +nullChars[6] = '\"\u0006\"'; +nullChars[7] = '\"\u0007\"'; +nullChars[8] = '\"\u0008\"'; +nullChars[9] = '\"\u0009\"'; +nullChars[10] = '\"\u000A\"'; +nullChars[11] = '\"\u000B\"'; +nullChars[12] = '\"\u000C\"'; +nullChars[13] = '\"\u000D\"'; +nullChars[14] = '\"\u000E\"'; +nullChars[15] = '\"\u000F\"'; +nullChars[16] = '\"\u0010\"'; +nullChars[17] = '\"\u0011\"'; +nullChars[18] = '\"\u0012\"'; +nullChars[19] = '\"\u0013\"'; +nullChars[20] = '\"\u0014\"'; +nullChars[21] = '\"\u0015\"'; +nullChars[22] = '\"\u0016\"'; +nullChars[23] = '\"\u0017\"'; +nullChars[24] = '\"\u0018\"'; +nullChars[25] = '\"\u0019\"'; +nullChars[26] = '\"\u001A\"'; +nullChars[27] = '\"\u001B\"'; +nullChars[28] = '\"\u001C\"'; +nullChars[29] = '\"\u001D\"'; +nullChars[30] = '\"\u001E\"'; +nullChars[31] = '\"\u001F\"'; + +for (var index in nullChars) { + assert.throws(SyntaxError, function() { + var obj = JSON.parse('{ "name" : ' + nullChars[index] + "John" + nullChars[index] + ' } '); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/S15.12.2_A1.js b/js/src/tests/test262/built-ins/JSON/parse/S15.12.2_A1.js new file mode 100644 index 0000000000..2de3caa3c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/S15.12.2_A1.js @@ -0,0 +1,20 @@ +// Copyright 2011 the Sputnik authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +info: JSON.parse must create a property with the given property name +es5id: 15.12.2_A1 +description: Tests that JSON.parse treats "__proto__" as a regular property name +---*/ + +var x = JSON.parse('{"__proto__":[]}'); + +assert.sameValue( + Object.getPrototypeOf(x), + Object.prototype, + 'Object.getPrototypeOf("JSON.parse(\'{"__proto__":[]}\')") returns Object.prototype' +); + +assert(Array.isArray(x.__proto__), 'Array.isArray(x.__proto__) must return true'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/browser.js b/js/src/tests/test262/built-ins/JSON/parse/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/browser.js diff --git a/js/src/tests/test262/built-ins/JSON/parse/builtin.js b/js/src/tests/test262/built-ins/JSON/parse/builtin.js new file mode 100644 index 0000000000..c9737b46c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/builtin.js @@ -0,0 +1,30 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.parse +description: > + Requirements for built-in functions, defined in introduction of chapter 17, + are satisfied. +features: [Reflect.construct] +---*/ + +var parse = JSON.parse; +assert(Object.isExtensible(parse), 'Object.isExtensible(parse) must return true'); +assert.sameValue(typeof parse, 'function', 'The value of `typeof parse` is "function"'); +assert.sameValue( + Object.prototype.toString.call(parse), + '[object Function]', + 'Object.prototype.toString.call("JSON.parse") must return "[object Function]"' +); +assert.sameValue( + Object.getPrototypeOf(parse), + Function.prototype, + 'Object.getPrototypeOf("JSON.parse") must return the value of Function.prototype' +); +assert.sameValue( + parse.hasOwnProperty('prototype'), + false, + 'parse.hasOwnProperty("prototype") must return false' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/duplicate-proto.js b/js/src/tests/test262/built-ins/JSON/parse/duplicate-proto.js new file mode 100644 index 0000000000..93becbbc45 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/duplicate-proto.js @@ -0,0 +1,19 @@ +// Copyright (C) 2020 devsnek. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-object-initializer-static-semantics-early-errors +description: > + It is a Syntax Error if PropertyNameList of PropertyDefinitionList contains + any duplicate entries for "__proto__" and at least two of those entries were + obtained from productions of the form + PropertyDefinition : PropertyName `:` AssignmentExpression . + This rule is not applied if this PropertyDefinition is contained within a + Script which is being evaluated for JSON.parse (see step 4 of JSON.parse). +---*/ + +var result = JSON.parse('{ "__proto__": 1, "__proto__": 2 }'); + +assert.sameValue(result.__proto__, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/invalid-whitespace.js b/js/src/tests/test262/built-ins/JSON/parse/invalid-whitespace.js new file mode 100644 index 0000000000..96693fb97e --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/invalid-whitespace.js @@ -0,0 +1,76 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-json.parse +es5id: 15.12.1.1-0-7 +description: > + other category z spaces are not valid JSON whitespace as specified + by the production JSONWhitespace. +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse('\u16801'); +}, '\\u1680'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u180e1'); +}, '\\u180e'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u20001'); +}, '\\u2000'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u20011'); +}, '\\u2001'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u20021'); +}, '\\u2002'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u20031'); +}, '\\u2003'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u20041'); +}, '\\u2004'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u20051'); +}, '\\u2005'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u20061'); +}, '\\u2006'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u20071'); +}, '\\u2007'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u20081'); +}, '\\u2008'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u20091'); +}, '\\u2009'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u200a1'); +}, '\\u200a'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u202f1'); +}, '\\u202f'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u205f1'); +}, '\\u205f'); + +assert.throws(SyntaxError, function() { + JSON.parse('\u30001'); +}, '\\u3000'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/length.js b/js/src/tests/test262/built-ins/JSON/parse/length.js new file mode 100644 index 0000000000..85c0515de0 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/length.js @@ -0,0 +1,27 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.parse +description: > + JSON.parse.length is 2. +info: | + JSON.parse ( text [ , reviver ] ) + + The "length" property of the parse function is 2. + + ECMAScript Standard Built-in Objects + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +verifyProperty(JSON.parse, 'length', { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/name.js b/js/src/tests/test262/built-ins/JSON/parse/name.js new file mode 100644 index 0000000000..b029b4f744 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/name.js @@ -0,0 +1,29 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-json.parse +description: > + JSON.parse.name is "parse". +info: | + JSON.parse ( text [ , reviver ] ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value + is a String. + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +verifyProperty(JSON.parse, 'name', { + value: 'parse', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/not-a-constructor.js b/js/src/tests/test262/built-ins/JSON/parse/not-a-constructor.js new file mode 100644 index 0000000000..d46040d8a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/not-a-constructor.js @@ -0,0 +1,31 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + JSON.parse does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, arrow-function] +---*/ + +assert.sameValue(isConstructor(JSON.parse), false, 'isConstructor(JSON.parse) must return false'); + +assert.throws(TypeError, () => { + new JSON.parse('{}'); +}, '`new JSON.parse(\'{}\')` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/prop-desc.js b/js/src/tests/test262/built-ins/JSON/parse/prop-desc.js new file mode 100644 index 0000000000..f3f2fc6b18 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/prop-desc.js @@ -0,0 +1,22 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.parse +description: > + Property descriptor of JSON.parse. +info: | + ECMAScript Standard Built-in Objects + + Every other data property described in clauses 18 through 26 and in Annex B.2 + has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +---*/ + +verifyProperty(JSON, 'parse', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/revived-proxy-revoked.js b/js/src/tests/test262/built-ins/JSON/parse/revived-proxy-revoked.js new file mode 100644 index 0000000000..b0f82dcca5 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/revived-proxy-revoked.js @@ -0,0 +1,47 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.parse +description: Behavior when revived value is a revoked Proxy exotic object +info: | + [...] + 7. If IsCallable(reviver) is true, then + a. Let root be ObjectCreate(%ObjectPrototype%). + b. Let rootName be the empty String. + c. Let status be CreateDataProperty(root, rootName, unfiltered). + d. Assert: status is true. + e. Return ? InternalizeJSONProperty(root, rootName). + + 24.3.1.1 Runtime Semantics: InternalizeJSONProperty + + [...] + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + + 7.2.2 IsArray + + [...] + 3. If argument is a Proxy exotic object, then + a. If the value of the [[ProxyHandler]] internal slot of argument is null, + throw a TypeError exception. + b. Let target be the value of the [[ProxyTarget]] internal slot of + argument. + c. Return ? IsArray(target). +features: [Proxy] +---*/ + +var handle = Proxy.revocable([], {}); +var returnCount = 0; + +handle.revoke(); + +assert.throws(TypeError, function() { + JSON.parse('[null, null]', function() { + this[1] = handle.proxy; + returnCount += 1; + }); +}); + +assert.sameValue(returnCount, 1, 'invocation returns normally'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/revived-proxy.js b/js/src/tests/test262/built-ins/JSON/parse/revived-proxy.js new file mode 100644 index 0000000000..fd3c659907 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/revived-proxy.js @@ -0,0 +1,86 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.parse +description: Behavior when revived value is a Proxy exotic object +info: | + [...] + 7. If IsCallable(reviver) is true, then + a. Let root be ObjectCreate(%ObjectPrototype%). + b. Let rootName be the empty String. + c. Let status be CreateDataProperty(root, rootName, unfiltered). + d. Assert: status is true. + e. Return ? InternalizeJSONProperty(root, rootName). + + 24.3.1.1 Runtime Semantics: InternalizeJSONProperty + + [...] + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + b. If isArray is true, then + [...] + c. Else, + [...] + + 7.2.2 IsArray + + [...] + 3. If argument is a Proxy exotic object, then + a. If the value of the [[ProxyHandler]] internal slot of argument is null, + throw a TypeError exception. + b. Let target be the value of the [[ProxyTarget]] internal slot of + argument. + c. Return ? IsArray(target). +features: [Proxy] +---*/ + +var objectProxy = new Proxy({ + length: 0, + other: 0 +}, {}); +var arrayProxy = new Proxy([], {}); +var arrayProxyProxy = new Proxy(arrayProxy, {}); +var visitedOther, injectProxy; + +arrayProxy.other = 0; + +injectProxy = function(name, val) { + if (name === 'other') { + visitedOther = true; + } + this[1] = objectProxy; + return val; +}; +visitedOther = false; + +JSON.parse('[null, null]', injectProxy); + +assert.sameValue(visitedOther, true, 'proxy for ordinary object'); + +injectProxy = function(name, val) { + if (name === 'other') { + visitedOther = true; + } + this[1] = arrayProxy; + return val; +}; +visitedOther = false; + +JSON.parse('[null, null]', injectProxy); + +assert.sameValue(visitedOther, false, 'proxy for array'); + +injectProxy = function(name, val) { + if (name === 'other') { + visitedOther = true; + } + this[1] = arrayProxyProxy; + return val; +}; +visitedOther = false; + +JSON.parse('[null, null]', injectProxy); + +assert.sameValue(visitedOther, false, 'proxy for array proxy'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-array-define-prop-err.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-array-define-prop-err.js new file mode 100644 index 0000000000..1613fa6878 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-array-define-prop-err.js @@ -0,0 +1,48 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: Abrupt completion from defining array property while reviving +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + e. Return ? InternalizeJSONProperty(root, rootName). + + Runtime Semantics: InternalizeJSONProperty ( holder, name) + + 1. Let val be ? Get(holder, name). + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + b. If isArray is true, then + i. Set I to 0. + ii. Let len be ? ToLength(? Get(val, "length")). + iii. Repeat while I < len, + 1. Let newElement be ? InternalizeJSONProperty(val, ! + ToString(I)). + 2. If newElement is undefined, then + [...] + 3. Else, + a. Perform ? CreateDataProperty(val, ! ToString(I), + newElement). +features: [Proxy] +---*/ + +var badDefine = new Proxy([null], { + defineProperty: function(_, name) { + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, function() { + JSON.parse('["first", null]', function(_, value) { + if (value === 'first') { + this[1] = badDefine; + } + return value; + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-array-delete-err.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-array-delete-err.js new file mode 100644 index 0000000000..92d37426ef --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-array-delete-err.js @@ -0,0 +1,42 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: Abrupt completion from array property deletion while reviving +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + e. Return ? InternalizeJSONProperty(root, rootName). + + Runtime Semantics: InternalizeJSONProperty ( holder, name) + + 1. Let val be ? Get(holder, name). + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + b. If isArray is true, then + i. Set I to 0. + ii. Let len be ? ToLength(? Get(val, "length")). + iii. Repeat while I < len, + 1. Let newElement be ? InternalizeJSONProperty(val, ! + ToString(I)). + 2. If newElement is undefined, then + a. Perform ? val.[[Delete]](! ToString(I)). +features: [Proxy] +---*/ + +var badDelete = new Proxy([0], { + deleteProperty: function() { + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, function() { + JSON.parse('[0,0]', function() { + this[1] = badDelete; + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-array-get-prop-from-prototype.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-array-get-prop-from-prototype.js new file mode 100644 index 0000000000..a148a6e55d --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-array-get-prop-from-prototype.js @@ -0,0 +1,46 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: > + `name` property is obtained with [[Get]] from prototype chain. +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + d. Return ? InternalizeJSONProperty(root, rootName). + + InternalizeJSONProperty ( holder, name ) + + 1. Let val be ? Get(holder, name). + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + b. If isArray is true, then + [...] + iii. Repeat, while I < len, + 1. Let newElement be ? InternalizeJSONProperty(val, ! ToString(I)). + 2. If newElement is undefined, then + [...] + 3. Else, + a. Perform ? CreateDataProperty(val, ! ToString(I), newElement). +---*/ + +Array.prototype[1] = 3; + +var json = '[1, 2]'; +var arr = JSON.parse(json, function(key, value) { + if (key === '0') { + assert(delete this[1]); + } + + return value; +}); + +assert(delete Array.prototype[1]); +assert.sameValue(arr[0], 1); +assert(arr.hasOwnProperty('1')); +assert.sameValue(arr[1], 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-array-length-coerce-err.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-array-length-coerce-err.js new file mode 100644 index 0000000000..5a2f8be696 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-array-length-coerce-err.js @@ -0,0 +1,45 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: > + Abrupt completion from coercing array "length" property to a number value +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + e. Return ? InternalizeJSONProperty(root, rootName). + + Runtime Semantics: InternalizeJSONProperty ( holder, name) + + 1. Let val be ? Get(holder, name). + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + b. If isArray is true, then + i. Set I to 0. + ii. Let len be ? ToLength(? Get(val, "length")). +features: [Proxy] +---*/ + +var uncoercible = { + valueOf: function() { + throw new Test262Error(); + } +}; +var badLength = new Proxy([], { + get: function(_, name) { + if (name === 'length') { + return uncoercible; + } + } +}); + +assert.throws(Test262Error, function() { + JSON.parse('[0,0]', function() { + this[1] = badLength; + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-array-length-get-err.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-array-length-get-err.js new file mode 100644 index 0000000000..1004af33e0 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-array-length-get-err.js @@ -0,0 +1,40 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: > + Abrupt completion from array "length" property access while reviving +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + e. Return ? InternalizeJSONProperty(root, rootName). + + Runtime Semantics: InternalizeJSONProperty ( holder, name) + + 1. Let val be ? Get(holder, name). + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + b. If isArray is true, then + i. Set I to 0. + ii. Let len be ? ToLength(? Get(val, "length")). +features: [Proxy] +---*/ + +var badLength = new Proxy([], { + get: function(_, name) { + if (name === 'length') { + throw new Test262Error(); + } + } +}); + +assert.throws(Test262Error, function() { + JSON.parse('[0,0]', function() { + this[1] = badLength; + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-array-non-configurable-prop-create.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-array-non-configurable-prop-create.js new file mode 100644 index 0000000000..848cf62b6b --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-array-non-configurable-prop-create.js @@ -0,0 +1,49 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: > + [[DefineOwnProperty]] validates property descriptor before applying. + If [[DefineOwnProperty]] is unsuccessful, no exception is thrown. +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + d. Return ? InternalizeJSONProperty(root, rootName). + + InternalizeJSONProperty ( holder, name ) + + 1. Let val be ? Get(holder, name). + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + b. If isArray is true, then + [...] + iii. Repeat, while I < len, + 1. Let newElement be ? InternalizeJSONProperty(val, ! ToString(I)). + 2. If newElement is undefined, then + [...] + 3. Else, + a. Perform ? CreateDataProperty(val, ! ToString(I), newElement). + + CreateDataProperty ( O, P, V ) + + [...] + 4. Return ? O.[[DefineOwnProperty]](P, newDesc). +---*/ + +var json = '[1, 2]'; +var arr = JSON.parse(json, function(key, value) { + if (key === '0') { + Object.defineProperty(this, '1', {configurable: false}); + } + if (key === '1') return 22; + + return value; +}); + +assert.sameValue(arr[0], 1); +assert.sameValue(arr[1], 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-array-non-configurable-prop-delete.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-array-non-configurable-prop-delete.js new file mode 100644 index 0000000000..550c232652 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-array-non-configurable-prop-delete.js @@ -0,0 +1,49 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: > + [[Delete]] does not remove non-configurable properties. + If [[Delete]] is unsuccessful, no exception is thrown. +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + d. Return ? InternalizeJSONProperty(root, rootName). + + InternalizeJSONProperty ( holder, name ) + + 1. Let val be ? Get(holder, name). + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + b. If isArray is true, then + [...] + iii. Repeat, while I < len, + 1. Let newElement be ? InternalizeJSONProperty(val, ! ToString(I)). + 2. If newElement is undefined, then + a. Perform ? val.[[Delete]](! ToString(I)). + + OrdinaryDelete ( O, P ) + + [...] + 4. If desc.[[Configurable]] is true, then + a. Remove the own property with name P from O. +---*/ + +var json = '[1, 2]'; +var arr = JSON.parse(json, function(key, value) { + if (key === '0') { + Object.defineProperty(this, '1', {configurable: false}); + } + if (key === '1') return; + + return value; +}); + +assert.sameValue(arr[0], 1); +assert(arr.hasOwnProperty('1')); +assert.sameValue(arr[1], 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-call-err.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-call-err.js new file mode 100644 index 0000000000..20903a9473 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-call-err.js @@ -0,0 +1,27 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: > + Abrupt completion when reviver function returns an abrupt completion +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + e. Return ? InternalizeJSONProperty(root, rootName). + + Runtime Semantics: InternalizeJSONProperty ( holder, name) + + [...] + 3. Return ? Call(reviver, holder, « name, val »). +---*/ + +assert.throws(Test262Error, function() { + JSON.parse('0', function() { + throw new Test262Error(); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-call-order.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-call-order.js new file mode 100644 index 0000000000..bdab32af01 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-call-order.js @@ -0,0 +1,22 @@ +// Copyright 2019 Kevin Gibbons. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-internalizejsonproperty +description: JSON.parse reviver call order +features: [for-in-order] +includes: [compareArray.js] +---*/ + +var calls = []; +function reviver(name, val) { + calls.push(name); + return val; +} + +JSON.parse('{"p1":0,"p2":0,"p1":0,"2":0,"1":0}', reviver); + +// The empty string is the _rootName_ in JSON.parse +assert.compareArray(calls, ['1', '2', 'p1', 'p2', '']); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-get-name-err.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-get-name-err.js new file mode 100644 index 0000000000..7e2801ecac --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-get-name-err.js @@ -0,0 +1,31 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: Abrupt completion from "holder" property access while reviving +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + e. Return ? InternalizeJSONProperty(root, rootName). + + Runtime Semantics: InternalizeJSONProperty ( holder, name) + + 1. Let val be ? Get(holder, name). +---*/ + +var thrower = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + JSON.parse('[0,0]', function() { + Object.defineProperty(this, '1', { + get: thrower + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-object-define-prop-err.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-object-define-prop-err.js new file mode 100644 index 0000000000..e42d327760 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-object-define-prop-err.js @@ -0,0 +1,49 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: Abrupt completion from defining object property while reviving +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + e. Return ? InternalizeJSONProperty(root, rootName). + + Runtime Semantics: InternalizeJSONProperty ( holder, name) + + 1. Let val be ? Get(holder, name). + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + b. If isArray is true, then + [...] + c. Else, + i. Let keys be ? EnumerableOwnProperties(val, "key"). + ii. For each String P in keys do, + 1. Let newElement be ? InternalizeJSONProperty(val, P). + 2. If newElement is undefined, then + [...] + 3. Else, + a. Perform ? CreateDataProperty(val, P, newElement). +features: [Proxy] +---*/ + +var badDefine = new Proxy({ + 0: null +}, { + defineProperty: function() { + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, function() { + JSON.parse('["first", null]', function(_, value) { + if (value === 'first') { + this[1] = badDefine; + } + return value; + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-object-delete-err.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-object-delete-err.js new file mode 100644 index 0000000000..079b494217 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-object-delete-err.js @@ -0,0 +1,44 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: Abrupt completion from object property deletion while reviving +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + e. Return ? InternalizeJSONProperty(root, rootName). + + Runtime Semantics: InternalizeJSONProperty ( holder, name) + + 1. Let val be ? Get(holder, name). + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + b. If isArray is true, then + [...] + c. Else, + i. Let keys be ? EnumerableOwnProperties(val, "key"). + ii. For each String P in keys do, + 1. Let newElement be ? InternalizeJSONProperty(val, P). + 2. If newElement is undefined, then + a. Perform ? val.[[Delete]](P). +features: [Proxy] +---*/ + +var badDelete = new Proxy({ + a: 1 +}, { + deleteProperty: function() { + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, function() { + JSON.parse('[0,0]', function() { + this[1] = badDelete; + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-object-get-prop-from-prototype.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-object-get-prop-from-prototype.js new file mode 100644 index 0000000000..7a4589fe48 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-object-get-prop-from-prototype.js @@ -0,0 +1,48 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: > + `name` property is obtained with [[Get]] from prototype chain. +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + d. Return ? InternalizeJSONProperty(root, rootName). + + InternalizeJSONProperty ( holder, name ) + + 1. Let val be ? Get(holder, name). + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + b. If isArray is true, then + [...] + c. Else, + i. Let keys be ? EnumerableOwnPropertyNames(val, "key"). + ii. For each String P in keys, do + 1. Let newElement be ? InternalizeJSONProperty(val, P). + 2. If newElement is undefined, then + [...] + 3. Else, + a. Perform ? CreateDataProperty(val, P, newElement). +---*/ + +Object.prototype.b = 3; + +var json = '{"a": 1, "b": 2}'; +var obj = JSON.parse(json, function(key, value) { + if (key === 'a') { + assert(delete this.b); + } + + return value; +}); + +assert(delete Object.prototype.b); +assert.sameValue(obj.a, 1); +assert(obj.hasOwnProperty('b')); +assert.sameValue(obj.b, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-object-non-configurable-prop-create.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-object-non-configurable-prop-create.js new file mode 100644 index 0000000000..3a09a6806b --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-object-non-configurable-prop-create.js @@ -0,0 +1,51 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: > + [[DefineOwnProperty]] validates property descriptor before applying. + If [[DefineOwnProperty]] is unsuccessful, no exception is thrown. +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + d. Return ? InternalizeJSONProperty(root, rootName). + + InternalizeJSONProperty ( holder, name ) + + 1. Let val be ? Get(holder, name). + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + b. If isArray is true, then + [...] + c. Else, + i. Let keys be ? EnumerableOwnPropertyNames(val, "key"). + ii. For each String P in keys, do + 1. Let newElement be ? InternalizeJSONProperty(val, P). + 2. If newElement is undefined, then + [...] + 3. Else, + a. Perform ? CreateDataProperty(val, P, newElement). + + CreateDataProperty ( O, P, V ) + + [...] + 4. Return ? O.[[DefineOwnProperty]](P, newDesc). +---*/ + +var json = '{"a": 1, "b": 2}'; +var obj = JSON.parse(json, function(key, value) { + if (key === 'a') { + Object.defineProperty(this, 'b', {configurable: false}); + } + if (key === 'b') return 22; + + return value; +}); + +assert.sameValue(obj.a, 1); +assert.sameValue(obj.b, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-object-non-configurable-prop-delete.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-object-non-configurable-prop-delete.js new file mode 100644 index 0000000000..83f0a86fa0 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-object-non-configurable-prop-delete.js @@ -0,0 +1,51 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: > + [[Delete]] does not remove non-configurable properties. + If [[Delete]] is unsuccessful, no exception is thrown. +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + d. Return ? InternalizeJSONProperty(root, rootName). + + InternalizeJSONProperty ( holder, name ) + + 1. Let val be ? Get(holder, name). + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + b. If isArray is true, then + [...] + c. Else, + i. Let keys be ? EnumerableOwnPropertyNames(val, "key"). + ii. For each String P in keys, do + 1. Let newElement be ? InternalizeJSONProperty(val, P). + 2. If newElement is undefined, then + a. Perform ? val.[[Delete]](P). + + OrdinaryDelete ( O, P ) + + [...] + 4. If desc.[[Configurable]] is true, then + a. Remove the own property with name P from O. +---*/ + +var json = '{"a": 1, "b": 2}'; +var obj = JSON.parse(json, function(key, value) { + if (key === 'a') { + Object.defineProperty(this, 'b', {configurable: false}); + } + if (key === 'b') return; + + return value; +}); + +assert.sameValue(obj.a, 1); +assert(obj.hasOwnProperty('b')); +assert.sameValue(obj.b, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-object-own-keys-err.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-object-own-keys-err.js new file mode 100644 index 0000000000..d795500537 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-object-own-keys-err.js @@ -0,0 +1,38 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-internalizejsonproperty +description: Abrupt completion from object property enumeration while reviving +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + [...] + e. Return ? InternalizeJSONProperty(root, rootName). + + Runtime Semantics: InternalizeJSONProperty ( holder, name) + + 1. Let val be ? Get(holder, name). + 2. If Type(val) is Object, then + a. Let isArray be ? IsArray(val). + b. If isArray is true, then + [...] + c. Else, + i. Let keys be ? EnumerableOwnProperties(val, "key"). +features: [Proxy] +---*/ + +var badKeys = new Proxy({}, { + ownKeys: function() { + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, function() { + JSON.parse('[0,0]', function() { + this[1] = badKeys; + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/reviver-wrapper.js b/js/src/tests/test262/built-ins/JSON/parse/reviver-wrapper.js new file mode 100644 index 0000000000..7545656d8c --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/reviver-wrapper.js @@ -0,0 +1,41 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.parse +description: > + Wrapper is plain extensible object with single data property. +info: | + JSON.parse ( text [ , reviver ] ) + + [...] + 7. If IsCallable(reviver) is true, then + a. Let root be ObjectCreate(%Object.prototype%). + b. Let rootName be the empty String. + c. Perform ! CreateDataPropertyOrThrow(root, rootName, unfiltered). +includes: [propertyHelper.js] +---*/ + +Object.defineProperty(Object.prototype, '', { + set: function() { + throw new Test262Error('[[Set]] should not be called.'); + }, +}); + +var wrapper; +JSON.parse('2', function() { + wrapper = this; +}); + +assert.sameValue(typeof wrapper, 'object'); +assert.sameValue(Object.getPrototypeOf(wrapper), Object.prototype); +assert.sameValue(Object.getOwnPropertyNames(wrapper).length, 1); +assert(Object.isExtensible(wrapper)); + +verifyProperty(wrapper, '', { + value: 2, + writable: true, + enumerable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/shell.js b/js/src/tests/test262/built-ins/JSON/parse/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/JSON/parse/text-negative-zero.js b/js/src/tests/test262/built-ins/JSON/parse/text-negative-zero.js new file mode 100644 index 0000000000..198c6d70e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/text-negative-zero.js @@ -0,0 +1,23 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.parse +description: > + Top-level negative zero surrounded by whitespace is parsed correctly. +info: | + JSON.parse ( text [ , reviver ] ) + + 1. Let JText be ? ToString(text). + 2. Parse JText interpreted as UTF-16 encoded Unicode points (6.1.4) as a JSON + text as specified in ECMA-404. Throw a SyntaxError exception if JText is not + a valid JSON text as defined in that specification. +---*/ + +assert.sameValue(JSON.parse('-0'), -0); +assert.sameValue(JSON.parse(' \n-0'), -0); +assert.sameValue(JSON.parse('-0 \t'), -0); +assert.sameValue(JSON.parse('\n\t -0\n '), -0); + +assert.sameValue(JSON.parse(-0), 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/text-non-string-primitive.js b/js/src/tests/test262/built-ins/JSON/parse/text-non-string-primitive.js new file mode 100644 index 0000000000..9efe855a7b --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/text-non-string-primitive.js @@ -0,0 +1,36 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.parse +description: > + Primitive values are coerced to strings and parsed. +info: | + JSON.parse ( text [ , reviver ] ) + + 1. Let JText be ? ToString(text). + 2. Parse JText interpreted as UTF-16 encoded Unicode points (6.1.4) as a JSON + text as specified in ECMA-404. Throw a SyntaxError exception if JText is not + a valid JSON text as defined in that specification. +features: [Symbol] +---*/ + +assert.throws(SyntaxError, function() { + JSON.parse(); +}); + +assert.throws(SyntaxError, function() { + JSON.parse(undefined); +}); + +assert.sameValue(JSON.parse(null), null); +assert.sameValue(JSON.parse(false), false); +assert.sameValue(JSON.parse(true), true); +assert.sameValue(JSON.parse(0), 0); +assert.sameValue(JSON.parse(3.14), 3.14); + +var sym = Symbol('desc'); +assert.throws(TypeError, function() { + JSON.parse(sym); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/text-object-abrupt.js b/js/src/tests/test262/built-ins/JSON/parse/text-object-abrupt.js new file mode 100644 index 0000000000..aa0a7a70ef --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/text-object-abrupt.js @@ -0,0 +1,30 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.parse +description: > + Abrupt completion from Get and Call in ToPrimitive. +info: | + JSON.parse ( text [ , reviver ] ) + + 1. Let JText be ? ToString(text). +---*/ + +assert.throws(Test262Error, function() { + JSON.parse({ + toString: null, + get valueOf() { + throw new Test262Error(); + }, + }); +}); + +assert.throws(Test262Error, function() { + JSON.parse({ + toString: function() { + throw new Test262Error(); + }, + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/parse/text-object.js b/js/src/tests/test262/built-ins/JSON/parse/text-object.js new file mode 100644 index 0000000000..c3eb0e74fc --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/parse/text-object.js @@ -0,0 +1,27 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.parse +description: > + Objects are coerced to strings using ToString. +info: | + JSON.parse ( text [ , reviver ] ) + + 1. Let JText be ? ToString(text). + 2. Parse JText interpreted as UTF-16 encoded Unicode points (6.1.4) as a JSON + text as specified in ECMA-404. Throw a SyntaxError exception if JText is not + a valid JSON text as defined in that specification. +---*/ + +var hint = JSON.parse({ + toString: function() { + return '"string"'; + }, + valueOf: function() { + return '"default_or_number"'; + }, +}); + +assert.sameValue(hint, 'string'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/prop-desc.js b/js/src/tests/test262/built-ins/JSON/prop-desc.js new file mode 100644 index 0000000000..8d17ae366a --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/prop-desc.js @@ -0,0 +1,42 @@ +// Copyright (C) 2016 The V8 Project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-json-object +description: > + Property descriptor of JSON +info: | + The JSON Object + + ... + The JSON object does not have a [[Construct]] internal method; + it is not possible to use the JSON object as a constructor with the new operator. + + The JSON object does not have a [[Call]] internal method; + it is not possible to invoke the JSON object as a function. + + 17 ECMAScript Standard Built-in Objects: + + Every other data property described in clauses 18 through 26 and in Annex B.2 + has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(typeof JSON, "object"); + +assert.throws(TypeError, function() { + JSON(); +}, "no [[Call]]"); + +assert.throws(TypeError, function() { + new JSON(); +}, "no [[Construct]]"); + +verifyProperty(this, "JSON", { + enumerable: false, + writable: true, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/shell.js b/js/src/tests/test262/built-ins/JSON/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/shell.js diff --git a/js/src/tests/test262/built-ins/JSON/stringify/browser.js b/js/src/tests/test262/built-ins/JSON/stringify/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/browser.js diff --git a/js/src/tests/test262/built-ins/JSON/stringify/builtin.js b/js/src/tests/test262/built-ins/JSON/stringify/builtin.js new file mode 100644 index 0000000000..f125bcbeb5 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/builtin.js @@ -0,0 +1,29 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Tests that JSON.stringify meets the requirements + for built-in objects defined by the introduction of chapter 17 of + the ECMAScript Language Specification. +features: [Reflect.construct] +---*/ + +assert(Object.isExtensible(JSON.stringify), 'Object.isExtensible(JSON.stringify) must return true'); +assert.sameValue( + Object.prototype.toString.call(JSON.stringify), + '[object Function]', + 'Object.prototype.toString.call(JSON.stringify) must return "[object Function]"' +); +assert.sameValue( + Object.getPrototypeOf(JSON.stringify), + Function.prototype, + 'Object.getPrototypeOf(JSON.stringify) must return the value of Function.prototype' +); +assert.sameValue( + JSON.stringify.hasOwnProperty('prototype'), + false, + 'JSON.stringify.hasOwnProperty("prototype") must return false' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/length.js b/js/src/tests/test262/built-ins/JSON/stringify/length.js new file mode 100644 index 0000000000..ea819ab04d --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/length.js @@ -0,0 +1,27 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + JSON.stringify.length is 3. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + The "length" property of the stringify function is 3. + + ECMAScript Standard Built-in Objects + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +verifyProperty(JSON.stringify, 'length', { + value: 3, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/name.js b/js/src/tests/test262/built-ins/JSON/stringify/name.js new file mode 100644 index 0000000000..d08ad4bf9d --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/name.js @@ -0,0 +1,29 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-json.stringify +description: > + JSON.stringify.name is "stringify". +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value + is a String. + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +verifyProperty(JSON.stringify, 'name', { + value: 'stringify', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/not-a-constructor.js b/js/src/tests/test262/built-ins/JSON/stringify/not-a-constructor.js new file mode 100644 index 0000000000..2458cdaf4a --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/not-a-constructor.js @@ -0,0 +1,31 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + JSON.stringify does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, arrow-function] +---*/ + +assert.sameValue(isConstructor(JSON.stringify), false, 'isConstructor(JSON.stringify) must return false'); + +assert.throws(TypeError, () => { + new JSON.stringify({}); +}, '`new JSON.stringify({})` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/prop-desc.js b/js/src/tests/test262/built-ins/JSON/stringify/prop-desc.js new file mode 100644 index 0000000000..d61ee040a7 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/prop-desc.js @@ -0,0 +1,22 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Property descriptor of JSON.stringify. +info: | + ECMAScript Standard Built-in Objects + + Every other data property described in clauses 18 through 26 and in Annex B.2 + has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +---*/ + +verifyProperty(JSON, 'stringify', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/property-order.js b/js/src/tests/test262/built-ins/JSON/stringify/property-order.js new file mode 100644 index 0000000000..00bfa481ee --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/property-order.js @@ -0,0 +1,41 @@ +// Copyright 2019 Kevin Gibbons. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-serializejsonobject +description: JSON.stringify property enumeration order +features: [for-in-order] +---*/ + +var o = { + p1: 'p1', + p2: 'p2', + p3: 'p3', +}; + +// This getter will be triggered during enumeration, but the property it adds should not be enumerated. +Object.defineProperty(o, 'add', { + enumerable: true, + get: function () { + o.extra = 'extra'; + return 'add'; + } +}); + +o.p4 = 'p4'; + +o[2] = '2'; +o[0] = '0'; +o[1] = '1'; + +delete o.p1; +delete o.p3; +o.p1 = 'p1'; + +var actual = JSON.stringify(o); + +var expected = '{"0":"0","1":"1","2":"2","p2":"p2","add":"add","p4":"p4","p1":"p1"}'; + +assert.sameValue(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-abrupt.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-abrupt.js new file mode 100644 index 0000000000..56cac0ef49 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-abrupt.js @@ -0,0 +1,61 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Abrupt completion from Get. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 4. If Type(replacer) is Object, then + [...] + 2. Let len be ? LengthOfArrayLike(replacer). + 3. Let k be 0. + 4. Repeat, while k < len, + a. Let v be ? Get(replacer, ! ToString(k)). +features: [Proxy] +---*/ + +var abruptLength = new Proxy([], { + get: function(_target, key) { + if (key === 'length') { + throw new Test262Error(); + } + }, +}); + +assert.throws(Test262Error, function() { + JSON.stringify(null, abruptLength); +}); + +var abruptToPrimitive = { + valueOf: function() { + throw new Test262Error(); + }, +}; + +var abruptToLength = new Proxy([], { + get: function(_target, key) { + if (key === 'length') { + return abruptToPrimitive; + } + }, +}); + +assert.throws(Test262Error, function() { + JSON.stringify([], abruptToLength); +}); + +var abruptIndex = new Array(1); +Object.defineProperty(abruptIndex, '0', { + get: function() { + throw new Test262Error(); + }, +}); + +assert.throws(Test262Error, function() { + JSON.stringify({}, abruptIndex); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-duplicates.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-duplicates.js new file mode 100644 index 0000000000..5351d6fb56 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-duplicates.js @@ -0,0 +1,31 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Replacer array is deduped before Get. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 4. If Type(replacer) is Object, then + [...] + 4. Repeat, while k < len, + a. Let v be ? Get(replacer, ! ToString(k)). + [...] + f. If item is not undefined and item is not currently an element of PropertyList, then + i. Append item to the end of PropertyList. +---*/ + +var getCalls = 0; +var value = { + get key() { + getCalls += 1; + return true; + }, +}; + +assert.sameValue(JSON.stringify(value, ['key', 'key']), '{"key":true}'); +assert.sameValue(getCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-empty.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-empty.js new file mode 100644 index 0000000000..7992ce8a25 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-empty.js @@ -0,0 +1,42 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonobject +description: > + Objects are serialized to {} if replacer array is empty. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 10. If Type(value) is Object and IsCallable(value) is false, then + [...] + c. Return ? SerializeJSONObject(value). + + SerializeJSONObject ( value ) + + [...] + 5. If PropertyList is not undefined, then + a. Let K be PropertyList. +---*/ + +assert.sameValue( + JSON.stringify({a: 1, b: 2}, []), + '{}' +); + +assert.sameValue( + JSON.stringify({a: 1, b: {c: 2}}, []), + '{}' +); + +assert.sameValue( + JSON.stringify([1, {a: 2}], []), + '[1,{}]' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-number-object.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-number-object.js new file mode 100644 index 0000000000..51886a4bba --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-number-object.js @@ -0,0 +1,33 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Converts Number objects from replacer array to primitives using ToString. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 4. If Type(replacer) is Object, then + [...] + 4. Repeat, while k < len, + a. Let v be ? Get(replacer, ! ToString(k)). + [...] + e. Else if Type(v) is Object, then + i. If v has a [[StringData]] or [[NumberData]] internal slot, + set item to ? ToString(v). +---*/ + +var num = new Number(10); +num.toString = function() { return 'toString'; }; +num.valueOf = function() { throw new Test262Error('should not be called'); }; + +var value = { + 10: 1, + toString: 2, + valueOf: 3, +}; + +assert.sameValue(JSON.stringify(value, [num]), '{"toString":2}'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-number.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-number.js new file mode 100644 index 0000000000..3f4744e85a --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-number.js @@ -0,0 +1,42 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Converts number primitives from replacer array to strings. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 4. If Type(replacer) is Object, then + [...] + 4. Repeat, while k < len, + a. Let v be ? Get(replacer, ! ToString(k)). + [...] + d. Else if Type(v) is Number, set item to ! ToString(v). +---*/ + +var obj = { + '0': 0, + '1': 1, + '-4': 2, + '0.3': 3, + '-Infinity': 4, + 'NaN': 5, +}; + +var replacer = [ + -0, + 1, + -4, + 0.3, + -Infinity, + NaN, +]; + +assert.sameValue( + JSON.stringify(obj, replacer), + JSON.stringify(obj) +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-order.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-order.js new file mode 100644 index 0000000000..7b424a1eda --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-order.js @@ -0,0 +1,39 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonobject +description: > + Keys order of serialized objects is determined by replacer array. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 10. If Type(value) is Object and IsCallable(value) is false, then + [...] + c. Return ? SerializeJSONObject(value). + + SerializeJSONObject ( value ) + + [...] + 5. If PropertyList is not undefined, then + a. Let K be PropertyList. +---*/ + +var replacer = ['c', 'b', 'a']; + +assert.sameValue( + JSON.stringify({b: 1, a: 2, c: 3}, replacer), + '{"c":3,"b":1,"a":2}' +); + +assert.sameValue( + JSON.stringify({a: {b: 2, c: 3}}, replacer), + '{"a":{"c":3,"b":2}}' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-proxy-revoked-realm.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-proxy-revoked-realm.js new file mode 100644 index 0000000000..82a53a0a11 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-proxy-revoked-realm.js @@ -0,0 +1,37 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Revoked proxy of array as replacer produces a TypeError + (honoring the realm of the current execution context). +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 4. If Type(replacer) is Object, then + a. If IsCallable(replacer) is true, then + i. Let ReplacerFunction be replacer. + b. Else, + i. Let isArray be ? IsArray(replacer). + + IsArray ( argument ) + + [...] + 3. If argument is a Proxy exotic object, then + a. If argument.[[ProxyHandler]] is null, throw a TypeError exception. + b. Let target be argument.[[ProxyTarget]]. + c. Return ? IsArray(target). +features: [cross-realm, Proxy] +---*/ + +var OProxy = $262.createRealm().global.Proxy; +var handle = OProxy.revocable([], {}); + +handle.revoke(); + +assert.throws(TypeError, function() { + JSON.stringify({}, handle.proxy); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-proxy-revoked.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-proxy-revoked.js new file mode 100644 index 0000000000..77cf5ef5bf --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-proxy-revoked.js @@ -0,0 +1,34 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: Revoked proxy value produces a TypeError. +info: | + [...] + 4. If Type(replacer) is Object, then + a. If IsCallable(replacer) is true, then + i. Let ReplacerFunction be replacer. + b. Else, + i. Let isArray be ? IsArray(replacer). + + 7.2.2 IsArray + + [...] + 3. If argument is a Proxy exotic object, then + a. If the value of the [[ProxyHandler]] internal slot of argument is null, + throw a TypeError exception. + b. Let target be the value of the [[ProxyTarget]] internal slot of + argument. + c. Return ? IsArray(target). +features: [Proxy] +---*/ + +var handle = Proxy.revocable([], {}); + +handle.revoke(); + +assert.throws(TypeError, function() { + JSON.stringify({}, handle.proxy); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-proxy.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-proxy.js new file mode 100644 index 0000000000..02fe6deb93 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-proxy.js @@ -0,0 +1,32 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Array proxy replacer serves as a filter of object keys. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 4. If Type(replacer) is Object, then + a. If IsCallable(replacer) is true, then + i. Let ReplacerFunction be replacer. + b. Else, + i. Let isArray be ? IsArray(replacer). + + IsArray ( argument ) + + [...] + 3. If argument is a Proxy exotic object, then + a. If argument.[[ProxyHandler]] is null, throw a TypeError exception. + b. Let target be argument.[[ProxyTarget]]. + c. Return ? IsArray(target). +features: [Proxy] +---*/ + +var replacer = new Proxy(['b'], {}); + +assert.sameValue(JSON.stringify({a: 1, b: 2}, replacer), '{"b":2}'); +assert.sameValue(JSON.stringify({b: {a: 3, b: 4}}, replacer), '{"b":{"b":4}}'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-string-object.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-string-object.js new file mode 100644 index 0000000000..c1380049e2 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-string-object.js @@ -0,0 +1,33 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Converts String objects from replacer array to primitives using ToString. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 4. If Type(replacer) is Object, then + [...] + 4. Repeat, while k < len, + a. Let v be ? Get(replacer, ! ToString(k)). + [...] + e. Else if Type(v) is Object, then + i. If v has a [[StringData]] or [[NumberData]] internal slot, + set item to ? ToString(v). +---*/ + +var str = new String('str'); +str.toString = function() { return 'toString'; }; +str.valueOf = function() { throw new Test262Error('should not be called'); }; + +var value = { + str: 1, + toString: 2, + valueOf: 3, +}; + +assert.sameValue(JSON.stringify(value, [str]), '{"toString":2}'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-undefined.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-undefined.js new file mode 100644 index 0000000000..1f2a176f34 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-undefined.js @@ -0,0 +1,31 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Undefined values in replacer array are ignored. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 4. If Type(replacer) is Object, then + [...] + 4. Repeat, while k < len, + a. Let v be ? Get(replacer, ! ToString(k)). + [...] + f. If item is not undefined and item is not currently an element of PropertyList, then + i. Append item to the end of PropertyList. +---*/ + +assert.sameValue(JSON.stringify({undefined: 1}, [undefined]), '{}'); +assert.sameValue(JSON.stringify({key: 1, undefined: 2}, [,,,]), '{}'); + +var sparse = new Array(3); +sparse[1] = 'key'; + +assert.sameValue( + JSON.stringify({undefined: 1, key: 2}, sparse), + '{"key":2}' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-wrong-type.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-wrong-type.js new file mode 100644 index 0000000000..2e69bf94a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-array-wrong-type.js @@ -0,0 +1,39 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Values that are neither strings nor numbers are ignored. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 4. If Type(replacer) is Object, then + [...] + 4. Repeat, while k < len, + a. Let v be ? Get(replacer, ! ToString(k)). + [...] + f. If item is not undefined and item is not currently an element of PropertyList, then + i. Append item to the end of PropertyList. +features: [Proxy, Symbol] +---*/ + +var obj = new Proxy({}, { + get: function(_target, key) { + if (key !== 'toJSON') { + throw new Test262Error(); + } + }, +}); + +var replacer = [ + true, + false, + null, + {toString: function() { return 'toString'; }}, + Symbol(), +]; + +assert.sameValue(JSON.stringify(obj, replacer), '{}'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-abrupt.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-abrupt.js new file mode 100644 index 0000000000..434622fd70 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-abrupt.js @@ -0,0 +1,30 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Abrupt completion from Call. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 4. If Type(replacer) is Object, then + a. If IsCallable(replacer) is true, then + i. Let ReplacerFunction be replacer. + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 3. If ReplacerFunction is not undefined, then + a. Set value to ? Call(ReplacerFunction, holder, « key, value »). +---*/ + +assert.throws(Test262Error, function() { + JSON.stringify({}, function() { + throw new Test262Error(); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-arguments.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-arguments.js new file mode 100644 index 0000000000..b072532e9f --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-arguments.js @@ -0,0 +1,55 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Replacer function is called with correct context and arguments. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + 1. Let value be ? Get(holder, key). + [...] + 3. If ReplacerFunction is not undefined, then + a. Set value to ? Call(ReplacerFunction, holder, « key, value »). +includes: [compareArray.js] +---*/ + +var calls = []; +var replacer = function(key, value) { + if (key !== '') { + calls.push([this, key, value]); + } + + return value; +}; + +var b1 = [1, 2]; +var b2 = {c1: true, c2: false}; +var a1 = { + b1: b1, + b2: { + toJSON: function() { return b2; }, + }, +}; +var obj = {a1: a1, a2: 'a2'}; + +assert.sameValue( + JSON.stringify(obj, replacer), + JSON.stringify(obj) +); + +assert.compareArray(calls[0], [obj, 'a1', a1]); +assert.compareArray(calls[1], [a1, 'b1', b1]); +assert.compareArray(calls[2], [b1, '0', 1]); +assert.compareArray(calls[3], [b1, '1', 2]); +assert.compareArray(calls[4], [a1, 'b2', b2]); +assert.compareArray(calls[5], [b2, 'c1', true]); +assert.compareArray(calls[6], [b2, 'c2', false]); +assert.compareArray(calls[7], [obj, 'a2', 'a2']); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-array-circular.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-array-circular.js new file mode 100644 index 0000000000..3e08de5694 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-array-circular.js @@ -0,0 +1,37 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonarray +description: > + Circular array value (returned from replacer function) throws a TypeError. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 3. If ReplacerFunction is not undefined, then + a. Set value to ? Call(ReplacerFunction, holder, « key, value »). + [...] + 10. If Type(value) is Object and IsCallable(value) is false, then + a. Let isArray be ? IsArray(value). + b. If isArray is true, return ? SerializeJSONArray(value). + + SerializeJSONArray ( value ) + + 1. If stack contains value, throw a TypeError exception because the structure is cyclical. +---*/ + +var circular = [{}]; +var circularReplacer = function(k, v) { + return circular; +}; + +assert.throws(TypeError, function() { + JSON.stringify(circular, circularReplacer); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-object-circular.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-object-circular.js new file mode 100644 index 0000000000..15ab0fbb00 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-object-circular.js @@ -0,0 +1,50 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonobject +description: > + Circular object value (returned from replacer function) throws a TypeError. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 3. If ReplacerFunction is not undefined, then + a. Set value to ? Call(ReplacerFunction, holder, « key, value »). + [...] + 10. If Type(value) is Object and IsCallable(value) is false, then + [...] + c. Return ? SerializeJSONObject(value). + + SerializeJSONObject ( value ) + + 1. If stack contains value, throw a TypeError exception because the structure is cyclical. +---*/ + +var direct = {prop: {}}; +var directReplacer = function(k, v) { + return direct; +}; + +assert.throws(TypeError, function() { + JSON.stringify(direct, directReplacer); +}); + +var indirect = {p1: {p2: {}}}; +var indirectReplacer = function(key, value) { + if (key === 'p2') { + return indirect; + } + + return value; +}; + +assert.throws(TypeError, function() { + JSON.stringify(indirect, indirectReplacer); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-object-deleted-property.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-object-deleted-property.js new file mode 100644 index 0000000000..7b9cea5d09 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-object-deleted-property.js @@ -0,0 +1,50 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Replacer function is called on properties, deleted during stringification. +info: | + SerializeJSONObject ( value ) + + [...] + 5. If PropertyList is not undefined, then + [...] + 6. Else, + a. Let K be ? EnumerableOwnPropertyNames(value, key). + [...] + 8. For each element P of K, do + a. Let strP be ? SerializeJSONProperty(P, value). + [...] + + SerializeJSONProperty ( key, holder ) + + 1. Let value be ? Get(holder, key). + [...] + 3. If ReplacerFunction is not undefined, then + a. Set value to ? Call(ReplacerFunction, holder, « key, value »). +---*/ + +var obj = { + get a() { + delete this.b; + return 1; + }, + b: 2, +}; + +var replacer = function(key, value) { + if (key === 'b') { + assert.sameValue(value, undefined); + return '<replaced>'; + } + + return value; +}; + +assert.sameValue( + JSON.stringify(obj, replacer), + '{"a":1,"b":"<replaced>"}' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-result-undefined.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-result-undefined.js new file mode 100644 index 0000000000..cb121cf55b --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-result-undefined.js @@ -0,0 +1,36 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Result of replacer function is stringified. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 3. If ReplacerFunction is not undefined, then + a. Set value to ? Call(ReplacerFunction, holder, « key, value »). +---*/ + +assert.sameValue(JSON.stringify(1, function() {}), undefined); +assert.sameValue(JSON.stringify([1], function() {}), undefined); +assert.sameValue(JSON.stringify({prop: 1}, function() {}), undefined); + +var replacer = function(_key, value) { + return value === 1 ? undefined : value; +}; + +assert.sameValue(JSON.stringify([1], replacer), '[null]'); +assert.sameValue(JSON.stringify({prop: 1}, replacer), '{}'); +assert.sameValue(JSON.stringify({ + a: { + b: [1], + }, +}, replacer), '{"a":{"b":[null]}}'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-result.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-result.js new file mode 100644 index 0000000000..be705fdcd1 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-result.js @@ -0,0 +1,56 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Result of replacer function is stringified. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 3. If ReplacerFunction is not undefined, then + a. Set value to ? Call(ReplacerFunction, holder, « key, value »). +---*/ + +var obj = { + a1: { + b1: [1, 2], + b2: { + c1: true, + c2: false, + }, + }, + a2: 'a2', +}; + +var replacer = function(key, value) { + assert.sameValue(value, null); + + switch (key) { + case '': return {a1: null, a2: null}; + case 'a1': return {b1: null, b2: null}; + case 'a2': return 'a2'; + + case 'b1': return [null, null]; + case 'b2': return {c1: null, c2: null}; + + case '0': return 1; + case '1': return 2; + case 'c1': return true; + case 'c2': return false; + } + + throw new Test262Error('unreachable'); +}; + +assert.sameValue( + JSON.stringify(null, replacer), + JSON.stringify(obj) +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-tojson.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-tojson.js new file mode 100644 index 0000000000..a6f034a924 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-tojson.js @@ -0,0 +1,54 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Replacer function is called on result of toJSON method. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 4. If Type(replacer) is Object, then + a. If IsCallable(replacer) is true, then + i. Let ReplacerFunction be replacer. + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 2. If Type(value) is Object, then + a. Let toJSON be ? Get(value, "toJSON"). + b. If IsCallable(toJSON) is true, then + i. Set value to ? Call(toJSON, value, « key »). + 3. If ReplacerFunction is not undefined, then + a. Set value to ? Call(ReplacerFunction, holder, « key, value »). +---*/ + +assert.sameValue( + JSON.stringify({ + toJSON: function() { + return 'toJSON'; + }, + }, function(_key, value) { + return value + '|replacer'; + }), + '"toJSON|replacer"' +); + +assert.sameValue( + JSON.stringify({ + toJSON: function() { + return {calls: 'toJSON'}; + }, + }, function(_key, value) { + if (value && value.calls) { + value.calls += '|replacer'; + } + + return value; + }), + '{"calls":"toJSON|replacer"}' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-wrapper.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-wrapper.js new file mode 100644 index 0000000000..7b21295ae8 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-function-wrapper.js @@ -0,0 +1,40 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Wrapper is plain extensible object with single data property. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 9. Let wrapper be ObjectCreate(%ObjectPrototype%). + 10. Let status be CreateDataProperty(wrapper, the empty String, value). +includes: [propertyHelper.js] +---*/ + +Object.defineProperty(Object.prototype, '', { + set: function() { + throw new Test262Error('[[Set]] should not be called.'); + }, +}); + +var value = {}; +var wrapper; +JSON.stringify(value, function() { + wrapper = this; +}); + +assert.sameValue(typeof wrapper, 'object'); +assert.sameValue(Object.getPrototypeOf(wrapper), Object.prototype); +assert.sameValue(Object.getOwnPropertyNames(wrapper).length, 1); +assert(Object.isExtensible(wrapper)); + +verifyProperty(wrapper, '', { + value: value, + writable: true, + enumerable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/replacer-wrong-type.js b/js/src/tests/test262/built-ins/JSON/stringify/replacer-wrong-type.js new file mode 100644 index 0000000000..1e12a38fd7 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/replacer-wrong-type.js @@ -0,0 +1,34 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Replacer paramter of wrong type is silently ignored. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 4. If Type(replacer) is Object, then + a. If IsCallable(replacer) is true, then + i. Set ReplacerFunction to replacer. + b. Else, + i. Let isArray be ? IsArray(replacer). + ii. If isArray is true, then + 1. Set PropertyList to a new empty List. +features: [Symbol] +---*/ + +var obj = {key: [1]}; +var json = '{"key":[1]}'; + +assert.sameValue(JSON.stringify(obj, {}), json); +assert.sameValue(JSON.stringify(obj, new String('str')), json); +assert.sameValue(JSON.stringify(obj, new Number(6.1)), json); + +assert.sameValue(JSON.stringify(obj, null), json); +assert.sameValue(JSON.stringify(obj, ''), json); +assert.sameValue(JSON.stringify(obj, 0), json); +assert.sameValue(JSON.stringify(obj, Symbol()), json); +assert.sameValue(JSON.stringify(obj, true), json); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/shell.js b/js/src/tests/test262/built-ins/JSON/stringify/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/JSON/stringify/space-number-float.js b/js/src/tests/test262/built-ins/JSON/stringify/space-number-float.js new file mode 100644 index 0000000000..ea2da90d0a --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/space-number-float.js @@ -0,0 +1,41 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Numeric space parameter is truncated to integer part. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 6. If Type(space) is Number, then + a. Set space to min(10, ! ToInteger(space)). +---*/ + +var obj = { + a1: { + b1: [1, 2, 3, 4], + b2: { + c1: 1, + c2: 2, + }, + }, + a2: 'a2', +}; + +assert.sameValue( + JSON.stringify(obj, null, -1.99999), + JSON.stringify(obj, null, -1) +); + +assert.sameValue( + JSON.stringify(obj, null, new Number(5.11111)), + JSON.stringify(obj, null, 5) +); + +assert.sameValue( + JSON.stringify(obj, null, 6.99999), + JSON.stringify(obj, null, 6) +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/space-number-object.js b/js/src/tests/test262/built-ins/JSON/stringify/space-number-object.js new file mode 100644 index 0000000000..8bce0f4b86 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/space-number-object.js @@ -0,0 +1,49 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Number objects are converted to primitives using ToNumber. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 5. If Type(space) is Object, then + a. If space has a [[NumberData]] internal slot, then + i. Set space to ? ToNumber(space). +---*/ + +var obj = { + a1: { + b1: [1, 2, 3, 4], + b2: { + c1: 1, + c2: 2, + }, + }, + a2: 'a2', +}; + +assert.sameValue( + JSON.stringify(obj, null, new Number(1)), + JSON.stringify(obj, null, 1) +); + +var num = new Number(1); +num.toString = function() { throw new Test262Error('should not be called'); }; +num.valueOf = function() { return 3; }; + +assert.sameValue( + JSON.stringify(obj, null, num), + JSON.stringify(obj, null, 3) +); + +var abrupt = new Number(4); +abrupt.toString = function() { throw new Test262Error(); }; +abrupt.valueOf = function() { throw new Test262Error(); }; + +assert.throws(Test262Error, function() { + JSON.stringify(obj, null, abrupt); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/space-number-range.js b/js/src/tests/test262/built-ins/JSON/stringify/space-number-range.js new file mode 100644 index 0000000000..24e7fae499 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/space-number-range.js @@ -0,0 +1,38 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Numeric space parameter is clamped to 0..10 range. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 6. If Type(space) is Number, then + a. Set space to min(10, ! ToInteger(space)). + b. If space < 1, let gap be the empty String; otherwise let gap be the + String value containing space occurrences of the code unit 0x0020 (SPACE). +---*/ + +var obj = { + a1: { + b1: [1, 2, 3, 4], + b2: { + c1: 1, + c2: 2, + }, + }, + a2: 'a2', +}; + +assert.sameValue( + JSON.stringify(obj, null, new Number(-5)), + JSON.stringify(obj, null, 0) +); + +assert.sameValue( + JSON.stringify(obj, null, 10), + JSON.stringify(obj, null, 100) +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/space-number.js b/js/src/tests/test262/built-ins/JSON/stringify/space-number.js new file mode 100644 index 0000000000..ff632d4a5e --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/space-number.js @@ -0,0 +1,39 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Numeric space parameter (integer in range 0..10) is equivalent + to string of spaces of that length. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 6. If Type(space) is Number, then + [...] + b. If space < 1, let gap be the empty String; otherwise let gap be the + String value containing space occurrences of the code unit 0x0020 (SPACE). +---*/ + +var obj = { + a1: { + b1: [1, 2, 3, 4], + b2: { + c1: 1, + c2: 2, + }, + }, + a2: 'a2', +}; + +assert.sameValue( + JSON.stringify(obj, null, 0), + JSON.stringify(obj, null, '') +); + +assert.sameValue( + JSON.stringify(obj, null, 4), + JSON.stringify(obj, null, ' ') // 4 spaces +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/space-string-object.js b/js/src/tests/test262/built-ins/JSON/stringify/space-string-object.js new file mode 100644 index 0000000000..ba0d5ac31a --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/space-string-object.js @@ -0,0 +1,50 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + String exotic objects are converted to primitives using ToString. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 5. If Type(space) is Object, then + [...] + b. Else if space has a [[StringData]] internal slot, then + i. Set space to ? ToString(space). +---*/ + +var obj = { + a1: { + b1: [1, 2, 3, 4], + b2: { + c1: 1, + c2: 2, + }, + }, + a2: 'a2', +}; + +assert.sameValue( + JSON.stringify(obj, null, new String('xxx')), + JSON.stringify(obj, null, 'xxx') +); + +var str = new String('xxx'); +str.toString = function() { return '---'; }; +str.valueOf = function() { throw new Test262Error('should not be called'); }; + +assert.sameValue( + JSON.stringify(obj, null, str), + JSON.stringify(obj, null, '---') +); + +var abrupt = new String('xxx'); +abrupt.toString = function() { throw new Test262Error(); }; +abrupt.valueOf = function() { throw new Test262Error(); }; + +assert.throws(Test262Error, function() { + JSON.stringify(obj, null, abrupt); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/space-string-range.js b/js/src/tests/test262/built-ins/JSON/stringify/space-string-range.js new file mode 100644 index 0000000000..e5157ac243 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/space-string-range.js @@ -0,0 +1,32 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Only first 10 code units of string space parameter are used. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 7. Else if Type(space) is String, then + a. If the length of space is 10 or less, let gap be space; otherwise + let gap be the String value consisting of the first 10 code units of space. +---*/ + +var obj = { + a1: { + b1: [1, 2, 3, 4], + b2: { + c1: 1, + c2: 2, + }, + }, + a2: 'a2', +}; + +assert.sameValue( + JSON.stringify(obj, null, '0123456789xxxxxxxxx'), + JSON.stringify(obj, null, '0123456789') +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/space-string.js b/js/src/tests/test262/built-ins/JSON/stringify/space-string.js new file mode 100644 index 0000000000..05551ce368 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/space-string.js @@ -0,0 +1,46 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + String space is used as gap. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 7. Else if Type(space) is String, then + a. If the length of space is 10 or less, let gap be space; otherwise + let gap be the String value consisting of the first 10 code units of space. +---*/ + +var obj = { + a1: { + b1: [1, 2, 3, 4], + b2: { + c1: 1, + c2: 2, + }, + }, + a2: 'a2', +}; + +assert.sameValue(JSON.stringify(obj, null, ''), JSON.stringify(obj)); +assert.sameValue(JSON.stringify(obj, null, ' '), [ + '{' +, ' "a1": {' +, ' "b1": [' +, ' 1,' +, ' 2,' +, ' 3,' +, ' 4' +, ' ],' +, ' "b2": {' +, ' "c1": 1,' +, ' "c2": 2' +, ' }' +, ' },' +, ' "a2": "a2"' +, '}' +].join('\n')); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/space-wrong-type.js b/js/src/tests/test262/built-ins/JSON/stringify/space-wrong-type.js new file mode 100644 index 0000000000..fe4c1ff827 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/space-wrong-type.js @@ -0,0 +1,33 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Space parameter of wrong type is silently ignored. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 8. Else, + a. Let gap be the empty String. +features: [Symbol] +---*/ + +var obj = { + a1: { + b1: [1, 2, 3, 4], + b2: { + c1: 1, + c2: 2, + }, + }, + a2: 'a2', +}; + +assert.sameValue(JSON.stringify(obj), JSON.stringify(obj, null, null)); +assert.sameValue(JSON.stringify(obj), JSON.stringify(obj, null, true)); +assert.sameValue(JSON.stringify(obj), JSON.stringify(obj, null, new Boolean(false))); +assert.sameValue(JSON.stringify(obj), JSON.stringify(obj, null, Symbol())); +assert.sameValue(JSON.stringify(obj), JSON.stringify(obj, null, {})); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-array-abrupt.js b/js/src/tests/test262/built-ins/JSON/stringify/value-array-abrupt.js new file mode 100644 index 0000000000..b60fa5c8d9 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-array-abrupt.js @@ -0,0 +1,68 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonarray +description: > + Abrupt completion from Get. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 10. If Type(value) is Object and IsCallable(value) is false, then + a. Let isArray be ? IsArray(value). + b. If isArray is true, return ? SerializeJSONArray(value). + + SerializeJSONArray ( value ) + + [...] + 6. Let len be ? LengthOfArrayLike(value). +features: [Proxy] +---*/ + +var abruptLength = new Proxy([], { + get: function(_target, key) { + if (key === 'length') { + throw new Test262Error(); + } + }, +}); + +assert.throws(Test262Error, function() { + JSON.stringify(abruptLength); +}); + +var abruptToPrimitive = { + valueOf: function() { + throw new Test262Error(); + }, +}; + +var abruptToLength = new Proxy([], { + get: function(_target, key) { + if (key === 'length') { + return abruptToPrimitive; + } + }, +}); + +assert.throws(Test262Error, function() { + JSON.stringify([abruptToLength]); +}); + +var abruptIndex = new Array(1); +Object.defineProperty(abruptIndex, '0', { + get: function() { + throw new Test262Error(); + }, +}); + +assert.throws(Test262Error, function() { + JSON.stringify({key: abruptIndex}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-array-circular.js b/js/src/tests/test262/built-ins/JSON/stringify/value-array-circular.js new file mode 100644 index 0000000000..d98050541d --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-array-circular.js @@ -0,0 +1,39 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonarray +description: > + Circular array value throws a TypeError. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 10. If Type(value) is Object and IsCallable(value) is false, then + a. Let isArray be ? IsArray(value). + b. If isArray is true, return ? SerializeJSONArray(value). + + SerializeJSONArray ( value ) + + 1. If stack contains value, throw a TypeError exception because the structure is cyclical. +---*/ + +var direct = []; +direct.push(direct); + +assert.throws(TypeError, function() { + JSON.stringify(direct); +}); + +var indirect = []; +indirect.push([[indirect]]); + +assert.throws(TypeError, function() { + JSON.stringify(indirect); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-array-proxy-revoked.js b/js/src/tests/test262/built-ins/JSON/stringify/value-array-proxy-revoked.js new file mode 100644 index 0000000000..ad91e3512d --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-array-proxy-revoked.js @@ -0,0 +1,39 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-json.stringify +description: > + Revoked array proxy value produces a TypeError. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 10. If Type(value) is Object and IsCallable(value) is false, then + a. Let isArray be ? IsArray(value). + + IsArray ( argument ) + + [...] + 3. If argument is a Proxy exotic object, then + a. If argument.[[ProxyHandler]] is null, throw a TypeError exception. +features: [Proxy] +---*/ + +var handle = Proxy.revocable([], {}); + +handle.revoke(); + +assert.throws(TypeError, function() { + JSON.stringify(handle.proxy); +}, 'top-level value'); + +assert.throws(TypeError, function() { + JSON.stringify([[[handle.proxy]]]); +}, 'nested value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-array-proxy.js b/js/src/tests/test262/built-ins/JSON/stringify/value-array-proxy.js new file mode 100644 index 0000000000..2cea3b4ebb --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-array-proxy.js @@ -0,0 +1,51 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonarray +description: > + Proxy of an array is treated as an array. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 10. If Type(value) is Object and IsCallable(value) is false, then + a. Let isArray be ? IsArray(value). + b. If isArray is true, return ? SerializeJSONArray(value). + + SerializeJSONArray ( value ) + + [...] + 6. Let len be ? LengthOfArrayLike(value). + 7. Let index be 0. + 8. Repeat, while index < len + a. Let strP be ? SerializeJSONProperty(! ToString(index), value). +features: [Proxy] +---*/ + +var arrayProxy = new Proxy([], { + get: function(_target, key) { + if (key === 'length') return 2; + return Number(key); + }, +}); + +assert.sameValue( + JSON.stringify(arrayProxy), '[0,1]', 'proxy for an array' +); +assert.sameValue( + JSON.stringify([[arrayProxy]]), '[[[0,1]]]', 'proxy for an array (nested)' +); + +var arrayProxyProxy = new Proxy(arrayProxy, {}); +assert.sameValue( + JSON.stringify([[arrayProxyProxy]]), + '[[[0,1]]]', + 'proxy for a proxy for an array (nested)' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-cross-realm.js b/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-cross-realm.js new file mode 100644 index 0000000000..a9d54c9e9c --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-cross-realm.js @@ -0,0 +1,21 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-serializejsonproperty +description: JSON.stringify called with a BigInt object from another realm +features: [BigInt, cross-realm] +---*/ + +var other = $262.createRealm().global; +var wrapped = other.Object(other.BigInt(100)); + +assert.throws(TypeError, () => JSON.stringify(wrapped), + "cross-realm BigInt object without toJSON method"); + +other.BigInt.prototype.toJSON = function () { return this.toString(); }; + +assert.sameValue(JSON.stringify(wrapped), "\"100\"", + "cross-realm BigInt object with toJSON method"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-order.js b/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-order.js new file mode 100644 index 0000000000..d4d902dc04 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-order.js @@ -0,0 +1,44 @@ +// Copyright (C) 2017 Robin Templeton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: BigInt stringify order of steps +esid: sec-serializejsonproperty +info: | + Runtime Semantics: SerializeJSONProperty ( key, holder ) + + 2. If Type(value) is Object or BigInt, then + a. Let toJSON be ? GetGetV(value, "toJSON"). + b. If IsCallable(toJSON) is true, then + i. Set value to ? Call(toJSON, value, « key »). + 3. If ReplacerFunction is not undefined, then + a. Set value to ? Call(ReplacerFunction, holder, « key, value »). + 4. If Type(value) is Object, then + [...] + d. Else if value has a [[BigIntData]] internal slot, then + i. Set value to value.[[BigIntData]]. + [...] + 10. If Type(value) is BigInt, throw a TypeError exception +features: [BigInt, arrow-function] +---*/ + +let step; + +function replacer(x, k, v) +{ + assert.sameValue(step++, 1); + assert.sameValue(v, 1n); + return x; +} + +BigInt.prototype.toJSON = function () { assert.sameValue(step++, 0); return 1n; }; + +step = 0; +assert.throws(TypeError, () => JSON.stringify(0n, (k, v) => replacer(2n, k, v))); +assert.sameValue(step, 2); + +step = 0; +assert.throws(TypeError, () => JSON.stringify(0n, (k, v) => replacer(Object(2n), k, v))); +assert.sameValue(step, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-replacer.js b/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-replacer.js new file mode 100644 index 0000000000..e7048872e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-replacer.js @@ -0,0 +1,26 @@ +// Copyright (C) 2017 Robin Templeton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: JSON serialization of BigInt values with replacer +esid: sec-serializejsonproperty +info: | + Runtime Semantics: SerializeJSONProperty ( key, holder ) + + 3. If ReplacerFunction is not undefined, then + a. Set value to ? Call(ReplacerFunction, holder, « key, value »). +features: [BigInt] +---*/ + +function replacer(k, v) +{ + if (typeof v === "bigint") + return "bigint"; + else + return v; +} + +assert.sameValue(JSON.stringify(0n, replacer), '"bigint"'); +assert.sameValue(JSON.stringify({x: 0n}, replacer), '{"x":"bigint"}'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-tojson-receiver.js b/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-tojson-receiver.js new file mode 100644 index 0000000000..3b5eb58411 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-tojson-receiver.js @@ -0,0 +1,27 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +// Test case written by André Bargull. + +/*--- +esid: sec-serializejsonproperty +description: toJSON method called with BigInt as receiver +features: [BigInt] +---*/ + +assert.throws(TypeError, () => JSON.stringify(1n), + "toString throws for BigInt object"); + +// The BigInt proposal changes the SerializeJSONProperty algorithm to +// specifically allow passing BigInt objects as receivers for the toJSON +// method. +Object.defineProperty(BigInt.prototype, "toJSON", { + get() { + "use strict"; + return () => typeof this; + } +}); + +assert.sameValue(JSON.stringify(1n), "\"bigint\"", + "BigInt toJSON method called with value as receiver"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-tojson.js b/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-tojson.js new file mode 100644 index 0000000000..6f2966fded --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-bigint-tojson.js @@ -0,0 +1,20 @@ +// Copyright (C) 2017 Robin Templeton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: BigInt toJSON method +esid: sec-serializejsonproperty +info: | + Runtime Semantics: SerializeJSONProperty ( key, holder ) + + 2. If Type(value) is Object or BigInt, then + a. Let toJSON be ? GetGetV(value, "toJSON"). + b. If IsCallable(toJSON) is true, then + i. Set value to ? Call(toJSON, value, « key »). +features: [BigInt] +---*/ + +BigInt.prototype.toJSON = function () { return this.toString(); }; +assert.sameValue(JSON.stringify(0n), '"0"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-bigint.js b/js/src/tests/test262/built-ins/JSON/stringify/value-bigint.js new file mode 100644 index 0000000000..f924aec4a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-bigint.js @@ -0,0 +1,14 @@ +// Copyright (C) 2017 Robin Templeton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: JSON serialization of BigInt values +esid: pending +features: [BigInt] +---*/ + +assert.throws(TypeError, () => JSON.stringify(0n)); +assert.throws(TypeError, () => JSON.stringify(Object(0n))); +assert.throws(TypeError, () => JSON.stringify({x: 0n})); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-boolean-object.js b/js/src/tests/test262/built-ins/JSON/stringify/value-boolean-object.js new file mode 100644 index 0000000000..21fddf5eec --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-boolean-object.js @@ -0,0 +1,40 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Boolean objects are converted to primitives using [[BooleanData]]. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 4. If Type(value) is Object, then + [...] + c. Else if value has a [[BooleanData]] internal slot, then + i. Set value to value.[[BooleanData]]. + [...] + 6. If value is true, return "true". + 7. If value is false, return "false". +---*/ + +assert.sameValue(JSON.stringify(new Boolean(true)), 'true'); + +assert.sameValue( + JSON.stringify({ + toJSON: function() { + return {key: new Boolean(false)}; + }, + }), + '{"key":false}' +); + +assert.sameValue(JSON.stringify([1], function(_k, v) { + return v === 1 ? new Boolean(true) : v; +}), '[true]'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-function.js b/js/src/tests/test262/built-ins/JSON/stringify/value-function.js new file mode 100644 index 0000000000..e4b18d857f --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-function.js @@ -0,0 +1,25 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Function values are ignored. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 10. If Type(value) is Object and IsCallable(value) is false, then + [...] + 11. Return undefined. +---*/ + +assert.sameValue(JSON.stringify(function() {}), undefined); +assert.sameValue(JSON.stringify([function() {}]), '[null]'); +assert.sameValue(JSON.stringify({key: function() {}}), '{}'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-number-negative-zero.js b/js/src/tests/test262/built-ins/JSON/stringify/value-number-negative-zero.js new file mode 100644 index 0000000000..665340762e --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-number-negative-zero.js @@ -0,0 +1,29 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Negative zero numbers are stringified to "0". +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 9. If Type(value) is Number, then + a. If value is finite, return ! ToString(value). + + NumberToString ( m ) + + [...] + 2. If m is +0 or -0, return the String "0". +---*/ + +assert.sameValue(JSON.stringify(-0), '0'); +assert.sameValue(JSON.stringify(['-0', 0, -0]), '["-0",0,0]'); +assert.sameValue(JSON.stringify({key: -0}), '{"key":0}'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-number-non-finite.js b/js/src/tests/test262/built-ins/JSON/stringify/value-number-non-finite.js new file mode 100644 index 0000000000..1109b956ea --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-number-non-finite.js @@ -0,0 +1,29 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Non-finite numbers as serialized as null. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 4. If Type(value) is Object, then + a. If value has a [[NumberData]] internal slot, then + i. Set value to ? ToNumber(value). + [...] + 9. If Type(value) is Number, then + a. If value is finite, return ! ToString(value). + b. Return "null". +---*/ + +assert.sameValue(JSON.stringify(Infinity), 'null'); +assert.sameValue(JSON.stringify({key: -Infinity}), '{"key":null}'); +assert.sameValue(JSON.stringify([NaN]), '[null]'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-number-object.js b/js/src/tests/test262/built-ins/JSON/stringify/value-number-object.js new file mode 100644 index 0000000000..d153c63c57 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-number-object.js @@ -0,0 +1,54 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Number objects are converted to primitives using ToNumber. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 4. If Type(value) is Object, then + a. If value has a [[NumberData]] internal slot, then + i. Set value to ? ToNumber(value). + [...] + 9. If Type(value) is Number, then + a. If value is finite, return ! ToString(value). +---*/ + +assert.sameValue(JSON.stringify(new Number(8.5)), '8.5'); + +var toPrimitiveReplacer = function(_key, value) { + if (value === 'str') { + var num = new Number(42); + num.toString = function() { throw new Test262Error('should not be called'); }; + num.valueOf = function() { return 2; }; + return num; + } + + return value; +}; + +assert.sameValue(JSON.stringify(['str'], toPrimitiveReplacer), '[2]'); + +var abruptToJSON = function() { + var num = new Number(3.14); + num.toString = function() { throw new Test262Error(); }; + num.valueOf = function() { throw new Test262Error(); }; + return num; +}; + +assert.throws(Test262Error, function() { + JSON.stringify({ + key: { + toJSON: abruptToJSON, + }, + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-object-abrupt.js b/js/src/tests/test262/built-ins/JSON/stringify/value-object-abrupt.js new file mode 100644 index 0000000000..131d1041d0 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-object-abrupt.js @@ -0,0 +1,26 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Abrupt completion from Get. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + 1. Let value be ? Get(holder, key). +---*/ + +assert.throws(Test262Error, function() { + JSON.stringify({ + get key() { + throw new Test262Error(); + }, + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-object-circular.js b/js/src/tests/test262/built-ins/JSON/stringify/value-object-circular.js new file mode 100644 index 0000000000..067261957d --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-object-circular.js @@ -0,0 +1,46 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonobject +description: > + Circular object value throws a TypeError. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 10. If Type(value) is Object and IsCallable(value) is false, then + [...] + c. Return ? SerializeJSONObject(value). + + SerializeJSONObject ( value ) + + 1. If stack contains value, throw a TypeError exception because the structure is cyclical. +---*/ + +var direct = {}; +direct.prop = direct; + +assert.throws(TypeError, function() { + JSON.stringify(direct); +}); + +var indirect = { + p1: { + p2: { + get p3() { + return indirect; + }, + }, + }, +}; + +assert.throws(TypeError, function() { + JSON.stringify(indirect); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-object-proxy-revoked.js b/js/src/tests/test262/built-ins/JSON/stringify/value-object-proxy-revoked.js new file mode 100644 index 0000000000..fef4cefdeb --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-object-proxy-revoked.js @@ -0,0 +1,40 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonobject +description: > + Revoked object proxy value produces a TypeError. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 10. If Type(value) is Object and IsCallable(value) is false, then + [...] + c. Return ? SerializeJSONObject(value). + + SerializeJSONObject ( value ) + + [...] + 6. Else, + a. Let K be ? EnumerableOwnPropertyNames(value, "key"). +features: [Proxy] +---*/ + +var handle = Proxy.revocable({}, {}); + +handle.revoke(); + +assert.throws(TypeError, function() { + JSON.stringify(handle.proxy); +}, 'top-level value'); + +assert.throws(TypeError, function() { + JSON.stringify({a: {b: handle.proxy}}); +}, 'nested value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-object-proxy.js b/js/src/tests/test262/built-ins/JSON/stringify/value-object-proxy.js new file mode 100644 index 0000000000..6a64a3cfee --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-object-proxy.js @@ -0,0 +1,59 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonobject +description: > + Proxy of an object is treated as regular object. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 10. If Type(value) is Object and IsCallable(value) is false, then + [...] + c. Return ? SerializeJSONObject(value). + + SerializeJSONObject ( value ) + + [...] + 6. Else, + a. Let K be ? EnumerableOwnPropertyNames(value, "key"). + 7. Let partial be a new empty List. + 8. For each element P of K, do + a. Let strP be ? SerializeJSONProperty(P, value). +features: [Proxy] +---*/ + +var objectProxy = new Proxy({}, { + getOwnPropertyDescriptor: function() { + return {value: 1, writable: true, enumerable: true, configurable: true}; + }, + get: function() { + return 1; + }, + ownKeys: function() { + return ['a', 'b']; + }, +}); + +assert.sameValue( + JSON.stringify(objectProxy), '{"a":1,"b":1}', 'proxy for an object' +); +assert.sameValue( + JSON.stringify({l1: {l2: objectProxy}}), + '{"l1":{"l2":{"a":1,"b":1}}}', + 'proxy for an object (nested)' +); + +var objectProxyProxy = new Proxy(objectProxy, {}); +assert.sameValue( + JSON.stringify({l1: {l2: objectProxyProxy}}), + '{"l1":{"l2":{"a":1,"b":1}}}', + 'proxy for a proxy for an object (nested)' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-primitive-top-level.js b/js/src/tests/test262/built-ins/JSON/stringify/value-primitive-top-level.js new file mode 100644 index 0000000000..f0b9ca86ac --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-primitive-top-level.js @@ -0,0 +1,33 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Top-level primitive values are stringified correctly. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 5. If value is null, return "null". + 6. If value is true, return "true". + 7. If value is false, return "false". + 8. If Type(value) is String, return QuoteJSONString(value). + 9. If Type(value) is Number, then + a. If value is finite, return ! ToString(value). + [...] + 11. Return undefined. +---*/ + +assert.sameValue(JSON.stringify(null), 'null'); +assert.sameValue(JSON.stringify(true), 'true'); +assert.sameValue(JSON.stringify(false), 'false'); +assert.sameValue(JSON.stringify('str'), '"str"'); +assert.sameValue(JSON.stringify(123), '123'); +assert.sameValue(JSON.stringify(undefined), undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-string-escape-ascii.js b/js/src/tests/test262/built-ins/JSON/stringify/value-string-escape-ascii.js new file mode 100644 index 0000000000..3ec26e928d --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-string-escape-ascii.js @@ -0,0 +1,68 @@ +// Copyright (c) 2018 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-quotejsonstring +description: > + JSON.stringify property names and values containing ASCII + characters that require escaping +---*/ + +var char_to_json = { + '"': '\\"', + "\\": "\\\\", + "\x00": "\\u0000", + "\x01": "\\u0001", + "\x02": "\\u0002", + "\x03": "\\u0003", + "\x04": "\\u0004", + "\x05": "\\u0005", + "\x06": "\\u0006", + "\x07": "\\u0007", + "\x08": "\\b", + "\x09": "\\t", + "\x0A": "\\n", + "\x0B": "\\u000b", + "\x0C": "\\f", + "\x0D": "\\r", + "\x0E": "\\u000e", + "\x0F": "\\u000f", + "\x10": "\\u0010", + "\x11": "\\u0011", + "\x12": "\\u0012", + "\x13": "\\u0013", + "\x14": "\\u0014", + "\x15": "\\u0015", + "\x16": "\\u0016", + "\x17": "\\u0017", + "\x18": "\\u0018", + "\x19": "\\u0019", + "\x1A": "\\u001a", + "\x1B": "\\u001b", + "\x1C": "\\u001c", + "\x1D": "\\u001d", + "\x1E": "\\u001e", + "\x1F": "\\u001f" +} + +var chars = Object.keys(char_to_json).join(""); +var chars_reversed = Object.keys(char_to_json).reverse().join(""); +var jsonChars = Object.values(char_to_json).join(""); +var jsonChars_reversed = Object.values(char_to_json).reverse().join(""); +var json = JSON.stringify({ + ["name" + chars + chars_reversed]: chars_reversed + chars + "value" +}); + +for (var char in char_to_json) { + var count = json.split(char_to_json[char]).length - 1; + assert.sameValue(count, 4, + "Every ASCII 0x" + char.charCodeAt(0).toString(16) + " serializes to " + char_to_json[char]); +} + +assert.sameValue( + json, + `{"${"name" + jsonChars + jsonChars_reversed}":"${jsonChars_reversed + jsonChars + "value"}"}`, + "JSON.stringify(objectUsingControlCharacters)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-string-escape-unicode.js b/js/src/tests/test262/built-ins/JSON/stringify/value-string-escape-unicode.js new file mode 100644 index 0000000000..a333bcc996 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-string-escape-unicode.js @@ -0,0 +1,38 @@ +// Copyright (c) 2018 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-quotejsonstring +description: > + JSON.stringify strings containing surrogate code units +features: [well-formed-json-stringify] +---*/ + +assert.sameValue(JSON.stringify("\uD834"), '"\\ud834"', + 'JSON.stringify("\\uD834")'); +assert.sameValue(JSON.stringify("\uDF06"), '"\\udf06"', + 'JSON.stringify("\\uDF06")'); + +assert.sameValue(JSON.stringify("\uD834\uDF06"), '"𝌆"', + 'JSON.stringify("\\uD834\\uDF06")'); +assert.sameValue(JSON.stringify("\uD834\uD834\uDF06\uD834"), '"\\ud834𝌆\\ud834"', + 'JSON.stringify("\\uD834\\uD834\\uDF06\\uD834")'); +assert.sameValue(JSON.stringify("\uD834\uD834\uDF06\uDF06"), '"\\ud834𝌆\\udf06"', + 'JSON.stringify("\\uD834\\uD834\\uDF06\\uDF06")'); +assert.sameValue(JSON.stringify("\uDF06\uD834\uDF06\uD834"), '"\\udf06𝌆\\ud834"', + 'JSON.stringify("\\uDF06\\uD834\\uDF06\\uD834")'); +assert.sameValue(JSON.stringify("\uDF06\uD834\uDF06\uDF06"), '"\\udf06𝌆\\udf06"', + 'JSON.stringify("\\uDF06\\uD834\\uDF06\\uDF06")'); + +assert.sameValue(JSON.stringify("\uDF06\uD834"), '"\\udf06\\ud834"', + 'JSON.stringify("\\uDF06\\uD834")'); +assert.sameValue(JSON.stringify("\uD834\uDF06\uD834\uD834"), '"𝌆\\ud834\\ud834"', + 'JSON.stringify("\\uD834\\uDF06\\uD834\\uD834")'); +assert.sameValue(JSON.stringify("\uD834\uDF06\uD834\uDF06"), '"𝌆𝌆"', + 'JSON.stringify("\\uD834\\uDF06\\uD834\\uDF06")'); +assert.sameValue(JSON.stringify("\uDF06\uDF06\uD834\uD834"), '"\\udf06\\udf06\\ud834\\ud834"', + 'JSON.stringify("\\uDF06\\uDF06\\uD834\\uD834")'); +assert.sameValue(JSON.stringify("\uDF06\uDF06\uD834\uDF06"), '"\\udf06\\udf06𝌆"', + 'JSON.stringify("\\uDF06\\uDF06\\uD834\\uDF06")'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-string-object.js b/js/src/tests/test262/built-ins/JSON/stringify/value-string-object.js new file mode 100644 index 0000000000..b7f5cd32cc --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-string-object.js @@ -0,0 +1,57 @@ +// Copyright (C) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + String exotic objects are converted to primitives using ToString. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 4. If Type(value) is Object, then + [...] + b. Else if value has a [[StringData]] internal slot, then + i. Set value to ? ToString(value). + [...] + 8. If Type(value) is String, return QuoteJSONString(value). +---*/ + +assert.sameValue(JSON.stringify(new String('str')), '"str"'); + +var toJSON = function() { + var str = new String('str'); + str.toString = function() { return 'toString'; }; + str.valueOf = function() { throw new Test262Error('should not be called'); }; + return str; +}; + +assert.sameValue( + JSON.stringify({ + key: { + toJSON: toJSON, + }, + }), + '{"key":"toString"}' +); + +var abruptReplacer = function(_key, value) { + if (value === true) { + var str = new String('str'); + str.toString = function() { throw new Test262Error(); }; + str.valueOf = function() { throw new Test262Error(); }; + return str; + } + + return value; +}; + +assert.throws(Test262Error, function() { + JSON.stringify([true], abruptReplacer); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-symbol.js b/js/src/tests/test262/built-ins/JSON/stringify/value-symbol.js new file mode 100644 index 0000000000..16dffec422 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-symbol.js @@ -0,0 +1,29 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Symbol primitives are ignored, both as keys and as values. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 11. Return undefined. +features: [Symbol] +---*/ + +var sym = Symbol('desc'); +assert.sameValue(JSON.stringify(sym), undefined); +assert.sameValue(JSON.stringify([sym]), '[null]'); +assert.sameValue(JSON.stringify({key: sym}), '{}'); + +var obj = {}; +obj[sym] = 1; +assert.sameValue(JSON.stringify(obj), '{}'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-abrupt.js b/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-abrupt.js new file mode 100644 index 0000000000..fb97cd9c4c --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-abrupt.js @@ -0,0 +1,38 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Abrupt completions from Get and Call. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 2. If Type(value) is Object, then + a. Let toJSON be ? Get(value, "toJSON"). + b. If IsCallable(toJSON) is true, then + i. Set value to ? Call(toJSON, value, « key »). +---*/ + +assert.throws(Test262Error, function() { + JSON.stringify({ + get toJSON() { + throw new Test262Error(); + }, + }); +}); + +assert.throws(Test262Error, function() { + JSON.stringify({ + toJSON() { + throw new Test262Error(); + }, + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-arguments.js b/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-arguments.js new file mode 100644 index 0000000000..27f001ef9a --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-arguments.js @@ -0,0 +1,47 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + toJSON is called with correct context and arguments. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 2. If Type(value) is Object, then + a. Let toJSON be ? Get(value, "toJSON"). + b. If IsCallable(toJSON) is true, then + i. Set value to ? Call(toJSON, value, « key »). +---*/ + +var callCount = 0; +var _this, _key; +var obj = { + toJSON: function(key) { + callCount += 1; + _this = this; + _key = key; + }, +}; + +assert.sameValue(JSON.stringify(obj), undefined); +assert.sameValue(callCount, 1); +assert.sameValue(_this, obj); +assert.sameValue(_key, ''); + +assert.sameValue(JSON.stringify([1, obj, 3]), '[1,null,3]'); +assert.sameValue(callCount, 2); +assert.sameValue(_this, obj); +assert.sameValue(_key, '1'); + +assert.sameValue(JSON.stringify({key: obj}), '{}'); +assert.sameValue(callCount, 3); +assert.sameValue(_this, obj); +assert.sameValue(_key, 'key'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-array-circular.js b/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-array-circular.js new file mode 100644 index 0000000000..4de99e7e17 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-array-circular.js @@ -0,0 +1,41 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonarray +description: > + Circular array value (returned from toJSON method) throws a TypeError. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 2. If Type(value) is Object, then + a. Let toJSON be ? Get(value, "toJSON"). + b. If IsCallable(toJSON) is true, then + i. Set value to ? Call(toJSON, value, « key »). + [...] + 10. If Type(value) is Object and IsCallable(value) is false, then + a. Let isArray be ? IsArray(value). + b. If isArray is true, return ? SerializeJSONArray(value). + + SerializeJSONArray ( value ) + + 1. If stack contains value, throw a TypeError exception because the structure is cyclical. +---*/ + +var arr = []; +var circular = [arr]; + +arr.toJSON = function() { + return circular; +}; + +assert.throws(TypeError, function() { + JSON.stringify(circular); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-not-function.js b/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-not-function.js new file mode 100644 index 0000000000..beb13ad9bb --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-not-function.js @@ -0,0 +1,27 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + toJSON value is not callable. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 2. If Type(value) is Object, then + a. Let toJSON be ? Get(value, "toJSON"). + b. If IsCallable(toJSON) is true, then + i. Set value to ? Call(toJSON, value, « key »). +---*/ + +assert.sameValue(JSON.stringify({toJSON: null}), '{"toJSON":null}'); +assert.sameValue(JSON.stringify({toJSON: false}), '{"toJSON":false}'); +assert.sameValue(JSON.stringify({toJSON: []}), '{"toJSON":[]}'); +assert.sameValue(JSON.stringify({toJSON: /re/}), '{"toJSON":{}}'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-object-circular.js b/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-object-circular.js new file mode 100644 index 0000000000..d6487dedb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-object-circular.js @@ -0,0 +1,41 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonobject +description: > + Circular object value (returned from toJSON method) throws a TypeError. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 2. If Type(value) is Object, then + a. Let toJSON be ? Get(value, "toJSON"). + b. If IsCallable(toJSON) is true, then + i. Set value to ? Call(toJSON, value, « key »). + [...] + 10. If Type(value) is Object and IsCallable(value) is false, then + [...] + c. Return ? SerializeJSONObject(value). + + SerializeJSONObject ( value ) + + 1. If stack contains value, throw a TypeError exception because the structure is cyclical. +---*/ + +var obj = {}; +var circular = { prop: obj }; + +obj.toJSON = function() { + return circular; +}; + +assert.throws(TypeError, function() { + JSON.stringify(circular); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-result.js b/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-result.js new file mode 100644 index 0000000000..f095e25566 --- /dev/null +++ b/js/src/tests/test262/built-ins/JSON/stringify/value-tojson-result.js @@ -0,0 +1,41 @@ +// Copyright (C) 2019 Aleksey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-serializejsonproperty +description: > + Result of toJSON method is stringified. +info: | + JSON.stringify ( value [ , replacer [ , space ] ] ) + + [...] + 12. Return ? SerializeJSONProperty(the empty String, wrapper). + + SerializeJSONProperty ( key, holder ) + + [...] + 2. If Type(value) is Object, then + a. Let toJSON be ? Get(value, "toJSON"). + b. If IsCallable(toJSON) is true, then + i. Set value to ? Call(toJSON, value, « key »). +---*/ + +assert.sameValue( + JSON.stringify({ + toJSON: function() { return [false]; }, + }), + '[false]' +); + +var arr = [true]; +arr.toJSON = function() {}; +assert.sameValue(JSON.stringify(arr), undefined); + +var str = new String('str'); +str.toJSON = function() { return null; }; +assert.sameValue(JSON.stringify({key: str}), '{"key":null}'); + +var num = new Number(14); +num.toJSON = function() { return {key: 7}; }; +assert.sameValue(JSON.stringify([num]), '[{"key":7}]'); + +reportCompare(0, 0); |