summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/built-ins/JSON
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/test262/built-ins/JSON')
-rw-r--r--js/src/tests/test262/built-ins/JSON/15.12-0-1.js17
-rw-r--r--js/src/tests/test262/built-ins/JSON/15.12-0-2.js18
-rw-r--r--js/src/tests/test262/built-ins/JSON/15.12-0-3.js18
-rw-r--r--js/src/tests/test262/built-ins/JSON/15.12-0-4.js24
-rw-r--r--js/src/tests/test262/built-ins/JSON/Symbol.toStringTag.js23
-rw-r--r--js/src/tests/test262/built-ins/JSON/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-1.js13
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-2.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-3.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-4.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-5.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-6.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-8.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-0-9.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-1.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-2.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-3.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g1-4.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-1.js11
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-2.js13
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-3.js13
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-4.js13
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g2-5.js13
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-1.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-2.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-3.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g4-4.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g5-1.js13
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g5-2.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g5-3.js15
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-1.js13
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-2.js13
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-3.js13
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-4.js13
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-5.js13
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-6.js13
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.1.1-g6-7.js13
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-1.js51
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-10.js51
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-2.js51
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-3.js51
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-4.js51
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-5.js51
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-6.js51
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-7.js51
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-8.js51
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/15.12.2-2-9.js51
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/S15.12.2_A1.js20
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/builtin.js30
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/duplicate-proto.js19
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/invalid-whitespace.js76
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/length.js27
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/name.js29
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/not-a-constructor.js31
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/prop-desc.js22
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/revived-proxy-revoked.js47
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/revived-proxy.js86
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-array-define-prop-err.js48
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-array-delete-err.js42
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-array-get-prop-from-prototype.js46
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-array-length-coerce-err.js45
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-array-length-get-err.js40
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-array-non-configurable-prop-create.js49
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-array-non-configurable-prop-delete.js49
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-call-err.js27
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-call-order.js22
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-get-name-err.js31
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-object-define-prop-err.js49
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-object-delete-err.js44
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-object-get-prop-from-prototype.js48
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-object-non-configurable-prop-create.js51
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-object-non-configurable-prop-delete.js51
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-object-own-keys-err.js38
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/reviver-wrapper.js41
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/text-negative-zero.js23
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/text-non-string-primitive.js36
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/text-object-abrupt.js30
-rw-r--r--js/src/tests/test262/built-ins/JSON/parse/text-object.js27
-rw-r--r--js/src/tests/test262/built-ins/JSON/prop-desc.js42
-rw-r--r--js/src/tests/test262/built-ins/JSON/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/builtin.js29
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/length.js27
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/name.js29
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/not-a-constructor.js31
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/prop-desc.js22
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/property-order.js41
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-array-abrupt.js61
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-array-duplicates.js31
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-array-empty.js42
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-array-number-object.js33
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-array-number.js42
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-array-order.js39
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-array-proxy-revoked-realm.js37
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-array-proxy-revoked.js34
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-array-proxy.js32
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-array-string-object.js33
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-array-undefined.js31
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-array-wrong-type.js39
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-function-abrupt.js30
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-function-arguments.js55
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-function-array-circular.js37
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-function-object-circular.js50
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-function-object-deleted-property.js50
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-function-result-undefined.js36
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-function-result.js56
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-function-tojson.js54
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-function-wrapper.js40
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/replacer-wrong-type.js34
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/space-number-float.js41
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/space-number-object.js49
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/space-number-range.js38
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/space-number.js39
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/space-string-object.js50
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/space-string-range.js32
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/space-string.js46
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/space-wrong-type.js33
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-array-abrupt.js68
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-array-circular.js39
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-array-proxy-revoked.js39
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-array-proxy.js51
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-bigint-cross-realm.js21
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-bigint-order.js44
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-bigint-replacer.js26
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-bigint-tojson-receiver.js27
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-bigint-tojson.js20
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-bigint.js14
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-boolean-object.js40
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-function.js25
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-number-negative-zero.js29
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-number-non-finite.js29
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-number-object.js54
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-object-abrupt.js26
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-object-circular.js46
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-object-proxy-revoked.js40
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-object-proxy.js59
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-primitive-top-level.js33
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-string-escape-ascii.js68
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-string-escape-unicode.js38
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-string-object.js57
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-symbol.js29
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-tojson-abrupt.js38
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-tojson-arguments.js47
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-tojson-array-circular.js41
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-tojson-not-function.js27
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-tojson-object-circular.js41
-rw-r--r--js/src/tests/test262/built-ins/JSON/stringify/value-tojson-result.js41
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);