summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/Tuple
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/non262/Tuple')
-rw-r--r--js/src/tests/non262/Tuple/4.1.2.11.js128
-rw-r--r--js/src/tests/non262/Tuple/4.1.2.6.js19
-rw-r--r--js/src/tests/non262/Tuple/9.1.1.1.js12
-rw-r--r--js/src/tests/non262/Tuple/browser.js0
-rw-r--r--js/src/tests/non262/Tuple/constructor.js18
-rw-r--r--js/src/tests/non262/Tuple/constructor/8.2.1.js55
-rw-r--r--js/src/tests/non262/Tuple/constructor/8.2.2.js11
-rw-r--r--js/src/tests/non262/Tuple/constructor/call-method.js17
-rw-r--r--js/src/tests/non262/Tuple/constructor/is-a-constructor.js4
-rw-r--r--js/src/tests/non262/Tuple/constructor/length.js13
-rw-r--r--js/src/tests/non262/Tuple/constructor/name.js20
-rw-r--r--js/src/tests/non262/Tuple/cross-realm.js22
-rw-r--r--js/src/tests/non262/Tuple/elements-literal.js22
-rw-r--r--js/src/tests/non262/Tuple/elements.js19
-rw-r--r--js/src/tests/non262/Tuple/enumeration.js48
-rw-r--r--js/src/tests/non262/Tuple/equality.js32
-rw-r--r--js/src/tests/non262/Tuple/from/arraylike-get-length-error.js17
-rw-r--r--js/src/tests/non262/Tuple/from/arraylike-to-length-error.js17
-rw-r--r--js/src/tests/non262/Tuple/from/calling-from-valid-1-noStrict.js43
-rw-r--r--js/src/tests/non262/Tuple/from/calling-from-valid-1-onlyStrict-strict.js44
-rw-r--r--js/src/tests/non262/Tuple/from/calling-from-valid-2.js44
-rw-r--r--js/src/tests/non262/Tuple/from/descriptor.js9
-rw-r--r--js/src/tests/non262/Tuple/from/elements-added-after.js29
-rw-r--r--js/src/tests/non262/Tuple/from/elements-deleted-after.js24
-rw-r--r--js/src/tests/non262/Tuple/from/from.js89
-rw-r--r--js/src/tests/non262/Tuple/from/get-iter-method-err.js12
-rw-r--r--js/src/tests/non262/Tuple/from/indexed-setters.js12
-rw-r--r--js/src/tests/non262/Tuple/from/items-is-arraybuffer.js8
-rw-r--r--js/src/tests/non262/Tuple/from/items-is-null-throws.js5
-rw-r--r--js/src/tests/non262/Tuple/from/iter-adv-err.js15
-rw-r--r--js/src/tests/non262/Tuple/from/iter-get-iter-err.js11
-rw-r--r--js/src/tests/non262/Tuple/from/iter-get-iter-val-err.js21
-rw-r--r--js/src/tests/non262/Tuple/from/iter-map-fn-args.js44
-rw-r--r--js/src/tests/non262/Tuple/from/iter-map-fn-err.js26
-rw-r--r--js/src/tests/non262/Tuple/from/iter-map-fn-return.js44
-rw-r--r--js/src/tests/non262/Tuple/from/iter-map-fn-this-arg.js38
-rw-r--r--js/src/tests/non262/Tuple/from/iter-map-fn-this-non-strict.js39
-rw-r--r--js/src/tests/non262/Tuple/from/iter-map-fn-this-strict-strict.js37
-rw-r--r--js/src/tests/non262/Tuple/from/iter-next-error.js18
-rw-r--r--js/src/tests/non262/Tuple/from/iter-next-value-error.js25
-rw-r--r--js/src/tests/non262/Tuple/from/iter-set-elem-prop.js37
-rw-r--r--js/src/tests/non262/Tuple/from/iter-set-length.js31
-rw-r--r--js/src/tests/non262/Tuple/from/length.js14
-rw-r--r--js/src/tests/non262/Tuple/from/mapfn-is-not-callable-typeerror.js15
-rw-r--r--js/src/tests/non262/Tuple/from/mapfn-throws-exception.js12
-rw-r--r--js/src/tests/non262/Tuple/from/name.js9
-rw-r--r--js/src/tests/non262/Tuple/from/not-a-constructor.js9
-rw-r--r--js/src/tests/non262/Tuple/from/prop-desc.js9
-rw-r--r--js/src/tests/non262/Tuple/from/source-array-boundary.js21
-rw-r--r--js/src/tests/non262/Tuple/from/source-object-iterator-1.js25
-rw-r--r--js/src/tests/non262/Tuple/from/source-object-length.js15
-rw-r--r--js/src/tests/non262/Tuple/from/source-object-without.js13
-rw-r--r--js/src/tests/non262/Tuple/from/this-null.js14
-rw-r--r--js/src/tests/non262/Tuple/gc.js14
-rw-r--r--js/src/tests/non262/Tuple/initializers/6.1.2.1.js129
-rw-r--r--js/src/tests/non262/Tuple/isTuple/8.2.2.1.js54
-rw-r--r--js/src/tests/non262/Tuple/isTuple/descriptor.js9
-rw-r--r--js/src/tests/non262/Tuple/isTuple/length.js9
-rw-r--r--js/src/tests/non262/Tuple/isTuple/name.js9
-rw-r--r--js/src/tests/non262/Tuple/isTuple/not-a-constructor.js15
-rw-r--r--js/src/tests/non262/Tuple/length-ownproperty.js21
-rw-r--r--js/src/tests/non262/Tuple/literal.js32
-rw-r--r--js/src/tests/non262/Tuple/methods.js554
-rw-r--r--js/src/tests/non262/Tuple/of/length.js20
-rw-r--r--js/src/tests/non262/Tuple/of/name.js9
-rw-r--r--js/src/tests/non262/Tuple/of/not-a-constructor.js9
-rw-r--r--js/src/tests/non262/Tuple/of/of.js29
-rw-r--r--js/src/tests/non262/Tuple/of/prop-desc.js9
-rw-r--r--js/src/tests/non262/Tuple/property-descriptors.js91
-rw-r--r--js/src/tests/non262/Tuple/proto-override.js13
-rw-r--r--js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/invoked-as-accessor.js22
-rw-r--r--js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/length.js11
-rw-r--r--js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/name.js7
-rw-r--r--js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/prop-desc.js31
-rw-r--r--js/src/tests/non262/Tuple/prototype/concat/concat-with-array.js7
-rw-r--r--js/src/tests/non262/Tuple/prototype/concat/concat.js104
-rw-r--r--js/src/tests/non262/Tuple/prototype/concat/indexed-setters.js17
-rw-r--r--js/src/tests/non262/Tuple/prototype/concat/length.js27
-rw-r--r--js/src/tests/non262/Tuple/prototype/filter/filter.js82
-rw-r--r--js/src/tests/non262/Tuple/prototype/filter/indexed-setters.js16
-rw-r--r--js/src/tests/non262/Tuple/prototype/filter/length.js27
-rw-r--r--js/src/tests/non262/Tuple/prototype/flat/empty-tuple-elements.js8
-rw-r--r--js/src/tests/non262/Tuple/prototype/flat/flat.js96
-rw-r--r--js/src/tests/non262/Tuple/prototype/flat/indexed-setters.js16
-rw-r--r--js/src/tests/non262/Tuple/prototype/flat/length.js27
-rw-r--r--js/src/tests/non262/Tuple/prototype/flat/undefined-elements.js10
-rw-r--r--js/src/tests/non262/Tuple/prototype/flatMap/depth-always-one.js16
-rw-r--r--js/src/tests/non262/Tuple/prototype/flatMap/flatMap.js114
-rw-r--r--js/src/tests/non262/Tuple/prototype/flatMap/length.js27
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/fromIndex-equal-or-greater-length-returns-false.js13
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/fromIndex-infinity.js23
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/fromIndex-minus-zero.js24
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/includes.js18
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/length-internal.js14
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/length-zero-returns-false.js23
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/length.js27
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/name.js17
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/no-arg.js12
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/not-a-constructor.js20
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/prop-desc.js14
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/return-abrupt-get-length.js27
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tointeger-fromindex-symbol.js15
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tointeger-fromindex.js21
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tonumber-length-symbol.js15
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/samevaluezero.js21
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/search-found-returns-true.js28
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/search-not-found-returns-false.js26
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/this-is-not-tuple.js17
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/tointeger-fromindex.js40
-rw-r--r--js/src/tests/non262/Tuple/prototype/includes/using-fromindex.js38
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/empty-tuple.js13
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-boolean.js14
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-float.js15
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-greater-than-length.js17
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-infinity-string.js13
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-inherited-valueOf.js36
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-missing.js17
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-nan.js15
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-neg-infinity.js13
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-neg-zero.js14
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-negative.js16
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-null.js15
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-number.js14
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-not-primitive.js33
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-valueOf-toString.js31
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-valueOf.js21
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object.js24
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-positive.js16
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-side-effects-3.js23
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-2.js14
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-exponent.js16
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-hex.js17
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-leading-zeros.js16
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-neg-infinity.js13
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-negative.js14
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string.js14
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-trunc-2.js17
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-trunc.js17
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-undefined.js14
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-with-index.js17
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-zero.js13
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/includes.js18
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/length-internal.js14
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/length.js27
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/undefined-throws-type-error.js18
-rw-r--r--js/src/tests/non262/Tuple/prototype/indexOf/uses-internal-length.js17
-rw-r--r--js/src/tests/non262/Tuple/prototype/isTuple/isTuple.js47
-rw-r--r--js/src/tests/non262/Tuple/prototype/isTuple/length.js22
-rw-r--r--js/src/tests/non262/Tuple/prototype/join/browser.js0
-rw-r--r--js/src/tests/non262/Tuple/prototype/join/dda-separator.js17
-rw-r--r--js/src/tests/non262/Tuple/prototype/join/shell.js0
-rw-r--r--js/src/tests/non262/Tuple/prototype/length/length-getter.js42
-rw-r--r--js/src/tests/non262/Tuple/prototype/map/callback-not-called-on-empty.js7
-rw-r--r--js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-with-thisarg45
-rw-r--r--js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-with-thisarg.js43
-rw-r--r--js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-without-thisarg.js45
-rw-r--r--js/src/tests/non262/Tuple/prototype/map/callbackfn-is-not-callable.js40
-rw-r--r--js/src/tests/non262/Tuple/prototype/map/callbackfn-returns-abrupt.js8
-rw-r--r--js/src/tests/non262/Tuple/prototype/map/indexed-setters.js12
-rw-r--r--js/src/tests/non262/Tuple/prototype/map/invoked-as-func.js6
-rw-r--r--js/src/tests/non262/Tuple/prototype/map/invoked-as-method.js10
-rw-r--r--js/src/tests/non262/Tuple/prototype/map/length-internal.js18
-rw-r--r--js/src/tests/non262/Tuple/prototype/map/length.js27
-rw-r--r--js/src/tests/non262/Tuple/prototype/map/map.js85
-rw-r--r--js/src/tests/non262/Tuple/prototype/map/this-is-not-tuple.js30
-rw-r--r--js/src/tests/non262/Tuple/prototype/slice/invoked-as-func.js7
-rw-r--r--js/src/tests/non262/Tuple/prototype/slice/invoked-as-method.js9
-rw-r--r--js/src/tests/non262/Tuple/prototype/slice/length.js26
-rw-r--r--js/src/tests/non262/Tuple/prototype/slice/name.js9
-rw-r--r--js/src/tests/non262/Tuple/prototype/slice/negative-zero.js10
-rw-r--r--js/src/tests/non262/Tuple/prototype/slice/not-a-constructor.js10
-rw-r--r--js/src/tests/non262/Tuple/prototype/slice/prop-desc.js9
-rw-r--r--js/src/tests/non262/Tuple/prototype/slice/return-abrupt-from-end.js13
-rw-r--r--js/src/tests/non262/Tuple/prototype/slice/return-abrupt-from-start.js13
-rw-r--r--js/src/tests/non262/Tuple/prototype/slice/slice.js176
-rw-r--r--js/src/tests/non262/Tuple/prototype/slice/tointeger-end.js35
-rw-r--r--js/src/tests/non262/Tuple/prototype/slice/tointeger-start.js35
-rw-r--r--js/src/tests/non262/Tuple/prototype/slice/tuple-length-internal.js23
-rw-r--r--js/src/tests/non262/Tuple/prototype/toReversed/indexed-setters.js16
-rw-r--r--js/src/tests/non262/Tuple/prototype/toReversed/invoked-as-func.js10
-rw-r--r--js/src/tests/non262/Tuple/prototype/toReversed/invoked-as-method.js10
-rw-r--r--js/src/tests/non262/Tuple/prototype/toReversed/length.js27
-rw-r--r--js/src/tests/non262/Tuple/prototype/toReversed/this-is-not-tuple.js21
-rw-r--r--js/src/tests/non262/Tuple/prototype/toReversed/toReversed.js29
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSorted/comparefn-call-throws.js16
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSorted/comparefn-calls.js25
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSorted/comparefn-nonfunction-call-throws.js25
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSorted/invoked-as-func.js10
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSorted/invoked-as-method.js10
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSorted/length.js27
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSorted/sorted-values.js29
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSorted/stability.js32
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSorted/this-is-not-tuple.js21
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSorted/toSorted.js36
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSorted/toSortedcompare-with-no-tostring.js14
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSorted/tuplelength-internal.js28
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSpliced/indexed-setters.js16
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSpliced/length.js27
-rw-r--r--js/src/tests/non262/Tuple/prototype/toSpliced/toSpliced.js254
-rw-r--r--js/src/tests/non262/Tuple/prototype/toString/length.js27
-rw-r--r--js/src/tests/non262/Tuple/prototype/toString/to-string.js21
-rw-r--r--js/src/tests/non262/Tuple/prototype/valueOf/length.js15
-rw-r--r--js/src/tests/non262/Tuple/prototype/valueOf/name.js9
-rw-r--r--js/src/tests/non262/Tuple/prototype/valueOf/valueOf.js23
-rw-r--r--js/src/tests/non262/Tuple/prototype/with/with.js68
-rw-r--r--js/src/tests/non262/Tuple/shell.js0
-rw-r--r--js/src/tests/non262/Tuple/syntax.js16
-rw-r--r--js/src/tests/non262/Tuple/type-errors.js31
-rw-r--r--js/src/tests/non262/Tuple/wrapper.js25
209 files changed, 5912 insertions, 0 deletions
diff --git a/js/src/tests/non262/Tuple/4.1.2.11.js b/js/src/tests/non262/Tuple/4.1.2.11.js
new file mode 100644
index 0000000000..9f8c018958
--- /dev/null
+++ b/js/src/tests/non262/Tuple/4.1.2.11.js
@@ -0,0 +1,128 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+/*
+2. If ! IsValidTupleIndex(numericIndex) is false, return empty.
+*/
+
+var t = #[1,2,3,4,5];
+assertEq(t[true], undefined);
+assertEq(t[false], undefined);
+assertEq(t[-2], undefined);
+/* TODO: This should be undefined as per section 4.1.2.10, step 1,
+ * but it's currently treated the same as t[0].
+ */
+// assertEq(t[-0], undefined);
+assertEq(t[10], undefined);
+assertEq(t[NaN], undefined);
+assertEq(t[Number.POSITIVE_INFINITY], undefined);
+assertEq(t[Number.NEGATIVE_INFINITY], undefined);
+assertEq(t["abc"], undefined);
+assertEq(t["3"], t[3]);
+assertEq(t[new String("3")], t[3]);
+assertEq(t["0"], t[0]);
+assertEq(t[new String("0")], t[0]);
+assertEq(t[new Number(0)], t[0]);
+assertEq(t[new Number(3)], t[3]);
+assertEq(t[1.1], undefined);
+assertEq(t[null], undefined);
+assertEq(t[undefined], undefined);
+
+var object = {
+ valueOf: function() {
+ return 1
+ }
+};
+assertEq(t[object], undefined);
+
+var object = {
+ valueOf: function() {
+ return 1
+ },
+ toString: function() {
+ return 0
+ }
+};
+assertEq(t[object], t[0]);
+
+var object = {
+ valueOf: function() {
+ return 1
+ },
+ toString: function() {
+ return {}
+ }
+};
+assertEq(t[object], t[1]);
+
+//CHECK#4
+try {
+ x = [];
+ var object = {
+ valueOf: function() {
+ throw "error"
+ },
+ toString: function() {
+ return 1
+ }
+ };
+ assertEq(tup[object], tup[1]);
+}
+catch (e) {
+ assertEq(e === "error", false);
+}
+
+//CHECK#5
+var object = {
+ toString: function() {
+ return 1
+ }
+};
+assertEq(t[object], t[1]);
+
+//CHECK#6
+x = [];
+var object = {
+ valueOf: function() {
+ return {}
+ },
+ toString: function() {
+ return 1
+ }
+}
+assertEq(t[object], t[1]);
+
+//CHECK#7
+try {
+ var object = {
+ valueOf: function() {
+ return 1
+ },
+ toString: function() {
+ throw "error"
+ }
+ };
+ t[object];
+ throw new SyntaxError();
+}
+catch (e) {
+ assertEq(e, "error", 'The value of e is expected to be "error"');
+}
+
+//CHECK#8
+try {
+ var object = {
+ valueOf: function() {
+ return {}
+ },
+ toString: function() {
+ return {}
+ }
+ };
+ t[object];
+ throw new SyntaxError();
+}
+catch (e) {
+ assertEq(e instanceof TypeError, true);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/4.1.2.6.js b/js/src/tests/non262/Tuple/4.1.2.6.js
new file mode 100644
index 0000000000..c1533bd7f6
--- /dev/null
+++ b/js/src/tests/non262/Tuple/4.1.2.6.js
@@ -0,0 +1,19 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+/*
+4.1.2.6 [[Set]] ( P, Receiver )
+The [[Set]] internal method of a Tuple exotic object takes arguments P and Receiver. It performs the following steps when called:
+
+1. Assert: IsPropertyKey(P) is true.
+2. Return false.
+*/
+
+// Setting properties should have no effect
+var t = #[1];
+t[4294967295] = "not a tuple element";
+assertEq(t[4294967295], undefined);
+assertEq(t.length, 1);
+t[1] = 5;
+assertEq(t.length, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/9.1.1.1.js b/js/src/tests/non262/Tuple/9.1.1.1.js
new file mode 100644
index 0000000000..0f1e8d8e0a
--- /dev/null
+++ b/js/src/tests/non262/Tuple/9.1.1.1.js
@@ -0,0 +1,12 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+assertEq(Object.prototype.toString.call(#[1,2,3]),
+ "[object Tuple]");
+assertEq(Object.prototype.toString.call(Object(#[1,2,3])),
+ "[object Tuple]");
+assertEq(Object.prototype.toString.call(#[]),
+ "[object Tuple]");
+assertEq(Object.prototype.toString.call(Object(#[])),
+ "[object Tuple]");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/browser.js b/js/src/tests/non262/Tuple/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Tuple/browser.js
diff --git a/js/src/tests/non262/Tuple/constructor.js b/js/src/tests/non262/Tuple/constructor.js
new file mode 100644
index 0000000000..067a5d5ea2
--- /dev/null
+++ b/js/src/tests/non262/Tuple/constructor.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+assertThrowsInstanceOf(
+ () => new Tuple(),
+ TypeError,
+ "Tuple is not a constructor"
+);
+
+assertEq(typeof Tuple(), "tuple");
+assertEq(typeof Object(Tuple()), "object");
+assertEq(Tuple() instanceof Tuple, false);
+assertEq(Object(Tuple()) instanceof Tuple, true);
+
+assertEq(Tuple().__proto__, Tuple.prototype);
+assertEq(Object(Tuple()).__proto__, Tuple.prototype);
+assertEq(Tuple.prototype.constructor, Tuple);
+
+if (typeof reportCompare === "function") reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/constructor/8.2.1.js b/js/src/tests/non262/Tuple/constructor/8.2.1.js
new file mode 100644
index 0000000000..0e43551f8f
--- /dev/null
+++ b/js/src/tests/non262/Tuple/constructor/8.2.1.js
@@ -0,0 +1,55 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.1 The Tuple Constructor
+The Tuple constructor:
+
+is the intrinsic object %Tuple%.
+*/
+
+assertEq(typeof Tuple, "function");
+assertEq(typeof Tuple.prototype, "object");
+
+/*
+is the initial value of the "Tuple" property of the global object.
+*/
+assertEq(this.Tuple, Tuple);
+
+/*
+creates and initializes a new Tuple object when called as a function.
+*/
+assertEq(Tuple(), #[]);
+assertEq(Tuple(1), #[1]);
+assertEq(Tuple("a", 1, true), #["a", 1, true]);
+/* 8.2.1.1
+3. For each element e of items,
+a. If Type(e) is Object, throw a TypeError exception.
+*/
+assertThrowsInstanceOf(() => Tuple("a", new Object()), TypeError,
+ "Object in Tuple");
+
+/*
+is not intended to be used with the new operator or to be subclassed.
+*/
+/* 8.2.1.1
+1. If NewTarget is not undefined, throw a TypeError exception.
+*/
+assertThrowsInstanceOf(() => new Tuple(1, 2, 3), TypeError, "Tuple is not intended to be used with the new operator");
+
+
+/* It may be used as the value of an extends clause of a class definition but a super call to the Tuple constructor will cause an exception.
+*/
+class C extends Tuple{}; // class declaration is allowed
+// super() is called implicitly
+assertThrowsInstanceOf (() => new C(), TypeError, "super call to Tuple constructor");
+class D extends Tuple {
+ constructor() {
+ super();
+ }
+};
+// Explicit call to super() will also throw
+assertThrowsInstanceOf(() => new D(), TypeError, "super call to Tuple constructor");
+
+reportCompare(0, 0);
+
+
+
diff --git a/js/src/tests/non262/Tuple/constructor/8.2.2.js b/js/src/tests/non262/Tuple/constructor/8.2.2.js
new file mode 100644
index 0000000000..938f7896d7
--- /dev/null
+++ b/js/src/tests/non262/Tuple/constructor/8.2.2.js
@@ -0,0 +1,11 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+/*
+8.2.2 Properties of the Tuple Constructor
+The Tuple constructor:
+
+has a [[Prototype]] internal slot whose value is %Function.prototype%.
+*/
+assertEq(Object.getPrototypeOf(Tuple), Function.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/constructor/call-method.js b/js/src/tests/non262/Tuple/constructor/call-method.js
new file mode 100644
index 0000000000..8675240029
--- /dev/null
+++ b/js/src/tests/non262/Tuple/constructor/call-method.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+10.2 ECMAScript Function Objects
+...
+All ECMAScript function objects have the [[Call]] internal method defined here. ECMAScript functions that are also constructors in addition have the [[Construct]] internal method.
+*/
+
+assertEq(Tuple.call(), #[]);
+assertEq(Tuple.call(undefined), #[]);
+assertEq(Tuple.call(undefined, 1), #[1]);
+assertEq(Tuple.call(2, 1), #[1]);
+assertEq(Tuple.call(#[], 1), #[1]);
+assertEq(Tuple.call(undefined, 1, 2, 3), #[1,2,3]);
+assertEq(Tuple.call(6, 1, 2, 3), #[1,2,3]);
+assertEq(Tuple.call(#[1], 1, 2, 3), #[1,2,3]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/constructor/is-a-constructor.js b/js/src/tests/non262/Tuple/constructor/is-a-constructor.js
new file mode 100644
index 0000000000..4ad4ee1560
--- /dev/null
+++ b/js/src/tests/non262/Tuple/constructor/is-a-constructor.js
@@ -0,0 +1,4 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+assertEq(isConstructor(Tuple), true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/constructor/length.js b/js/src/tests/non262/Tuple/constructor/length.js
new file mode 100644
index 0000000000..67169ef0d1
--- /dev/null
+++ b/js/src/tests/non262/Tuple/constructor/length.js
@@ -0,0 +1,13 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+18 ECMAScript Standard Built-in Objects
+...
+Every built-in function object, including constructors, has a "length" property whose value is a non-negative integral Number. Unless otherwise specified, this value is equal to the number of required parameters shown in the subclause heading for the function description. Optional parameters and rest parameters are not included in the parameter count.
+*/
+var desc = Object.getOwnPropertyDescriptor(Tuple, "length");
+assertEq(desc.value, 0);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/constructor/name.js b/js/src/tests/non262/Tuple/constructor/name.js
new file mode 100644
index 0000000000..6656c2ee54
--- /dev/null
+++ b/js/src/tests/non262/Tuple/constructor/name.js
@@ -0,0 +1,20 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+18 ECMAScript Standard Built-in Objects
+
+Every built-in function object, including constructors, has a "name" property whose value is a String. Unless otherwise specified, this value is the name that is given to the function in this specification. Functions that are identified as anonymous functions use the empty String as the value of the "name" property.
+...
+Unless otherwise specified, the "name" property of a built-in function object has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
+*/
+
+
+var desc = Object.getOwnPropertyDescriptor(Tuple, "name");
+assertEq(desc.value, "Tuple");
+
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
+
+
diff --git a/js/src/tests/non262/Tuple/cross-realm.js b/js/src/tests/non262/Tuple/cross-realm.js
new file mode 100644
index 0000000000..ca385c7ca4
--- /dev/null
+++ b/js/src/tests/non262/Tuple/cross-realm.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+const realm = newGlobal();
+
+const realm_TupleConstructor = realm.eval("Tuple");
+const realm_tuple = realm.eval(`
+ var tuple = Tuple(1, 2, 3);
+ tuple;
+`);
+
+assertEq(realm_tuple === #[1, 2, 3], true);
+assertEq(realm_tuple.constructor, Tuple);
+assertEq(realm.eval("tuple.constructor"), realm_TupleConstructor);
+
+realm_TupleConstructor.prototype.foo = 42;
+assertEq(realm.eval("tuple.foo"), 42);
+assertEq(realm_tuple.foo, undefined);
+
+assertEq("foo" in Object(realm_tuple), false);
+assertEq(realm.eval(`"foo" in Object(tuple)`), true);
+
+if (typeof reportCompare === "function") reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/elements-literal.js b/js/src/tests/non262/Tuple/elements-literal.js
new file mode 100644
index 0000000000..1cc5cabf6f
--- /dev/null
+++ b/js/src/tests/non262/Tuple/elements-literal.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var tup = #[1, 2, 10n ** 100n, Tuple(5, 6)];
+
+assertEq(tup[0], 1);
+assertEq(tup[1], 2);
+assertEq(tup[2], 10n ** 100n);
+assertEq(typeof tup[3], "tuple");
+assertEq(tup[3][0], 5);
+assertEq(tup[3][1], 6);
+
+var err;
+try {
+ tup = #[1, 2, 3,
+ 4, 5,
+ 7, {}, 8];
+} catch (e) { err = e }
+
+assertEq(err.lineNumber, 16);
+assertEq(err.columnNumber, 10);
+
+if (typeof reportCompare === "function") reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/elements.js b/js/src/tests/non262/Tuple/elements.js
new file mode 100644
index 0000000000..81ff41a0bf
--- /dev/null
+++ b/js/src/tests/non262/Tuple/elements.js
@@ -0,0 +1,19 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var tup = Tuple(1, 2, 10n ** 100n, Tuple(5, 6));
+
+assertEq(tup[0], 1);
+assertEq(tup[1], 2);
+assertEq(tup[2], 10n ** 100n);
+assertEq(typeof tup[3], "tuple");
+assertEq(tup[3][0], 5);
+assertEq(tup[3][1], 6);
+
+assertEq(Object(tup)[0], 1);
+
+assertEq(tup.length, 4);
+assertEq(Object(tup).length, 4);
+
+assertEq("0" in Object(tup), true);
+
+if (typeof reportCompare === "function") reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/enumeration.js b/js/src/tests/non262/Tuple/enumeration.js
new file mode 100644
index 0000000000..834c919e8e
--- /dev/null
+++ b/js/src/tests/non262/Tuple/enumeration.js
@@ -0,0 +1,48 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var tup = #[1, 2, 3];
+
+var keys = Object.keys(tup);
+assertEq(keys.length, 3);
+assertEq(keys[0], "0");
+assertEq(keys[1], "1");
+assertEq(keys[2], "2");
+
+var values = Object.values(tup);
+assertEq(values.length, 3);
+assertEq(values[0], 1);
+assertEq(values[1], 2);
+assertEq(values[2], 3);
+
+var entries = Object.entries(tup);
+assertEq(entries.length, 3);
+assertEq(entries[0][0], "0");
+assertEq(entries[0][1], 1);
+assertEq(entries[1][0], "1");
+assertEq(entries[1][1], 2);
+assertEq(entries[2][0], "2");
+assertEq(entries[2][1], 3);
+
+var ownKeys = Reflect.ownKeys(Object(tup));
+assertEq(ownKeys.length, 3);
+assertEq(ownKeys[0], "0");
+assertEq(ownKeys[1], "1");
+assertEq(ownKeys[2], "2");
+
+var spreadKeys = Object.keys({ ...tup });
+assertEq(spreadKeys.length, 3);
+assertEq(spreadKeys[0], "0");
+assertEq(spreadKeys[1], "1");
+assertEq(spreadKeys[2], "2");
+
+var i = 0;
+for (var key in tup) {
+ switch (i++) {
+ case 0: assertEq(key, "0"); break;
+ case 1: assertEq(key, "1"); break;
+ case 2: assertEq(key, "2"); break;
+ default: assertUnreachable();
+ }
+}
+
+if (typeof reportCompare === "function") reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/equality.js b/js/src/tests/non262/Tuple/equality.js
new file mode 100644
index 0000000000..4e85d9bb59
--- /dev/null
+++ b/js/src/tests/non262/Tuple/equality.js
@@ -0,0 +1,32 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+let simple1 = #[1, 2];
+let simple2 = #[1, 2];
+let simpleDiff = #[0, 2];
+let simpleDiff2 = #[1];
+
+assertEq(simple1 === simple2, true);
+assertEq(simple1 === simpleDiff, false);
+assertEq(simple1 === simpleDiff2, false);
+
+let withPositiveZero = #[1, 2, +0];
+let withPositiveZero2 = #[1, 2, +0];
+let withNegativeZero = #[1, 2, -0];
+
+assertEq(withPositiveZero === withPositiveZero2, true);
+assertEq(Object.is(withPositiveZero, withPositiveZero2), true);
+assertEq(#[withPositiveZero] === #[withPositiveZero2], true);
+assertEq(Object.is(#[withPositiveZero], #[withPositiveZero2]), true);
+
+assertEq(withPositiveZero === withNegativeZero, true);
+assertEq(Object.is(withPositiveZero, withNegativeZero), false);
+assertEq(#[withPositiveZero] === #[withNegativeZero], true);
+assertEq(Object.is(#[withPositiveZero], #[withNegativeZero]), false);
+
+let withNaN = #[1, NaN, 2];
+let withNaN2 = #[1, NaN, 2];
+
+assertEq(withNaN === withNaN2, true);
+assertEq(Object.is(withNaN, withNaN2), true);
+
+if (typeof reportCompare === "function") reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/arraylike-get-length-error.js b/js/src/tests/non262/Tuple/from/arraylike-get-length-error.js
new file mode 100644
index 0000000000..7c16e988ba
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/arraylike-get-length-error.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+/* 9. Let len be ? LengthOfArrayLike(arrayLike). */
+
+var arrayLike = {};
+
+Object.defineProperty(arrayLike, "length", {
+ get: function() {
+ throw new SyntaxError();
+ }
+});
+
+assertThrowsInstanceOf(function() {
+ Tuple.from(arrayLike);
+}, SyntaxError, "items.length throws");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/arraylike-to-length-error.js b/js/src/tests/non262/Tuple/from/arraylike-to-length-error.js
new file mode 100644
index 0000000000..fb1c20a5c8
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/arraylike-to-length-error.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+/* 9. Let len be ? LengthOfArrayLike(arrayLike). */
+
+var arrayLike = { length: {} };
+
+arrayLike.length = {
+ valueOf: function() {
+ throw new SyntaxError();
+ }
+};
+
+assertThrowsInstanceOf(() => Tuple.from(arrayLike),
+ SyntaxError, "items has invalid length");
+
+reportCompare(0, 0);
+
diff --git a/js/src/tests/non262/Tuple/from/calling-from-valid-1-noStrict.js b/js/src/tests/non262/Tuple/from/calling-from-valid-1-noStrict.js
new file mode 100644
index 0000000000..a90e10dbae
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/calling-from-valid-1-noStrict.js
@@ -0,0 +1,43 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var list = {
+ '0': 41,
+ '1': 42,
+ '2': 43,
+ length: 3
+};
+var calls = [];
+
+function mapFn(value) {
+ calls.push({
+ args: arguments,
+ thisArg: this
+ });
+ return value * 2;
+}
+
+var result = Tuple.from(list, mapFn);
+
+assertEq(result.length, 3);
+assertEq(result[0], 82);
+assertEq(result[1], 84);
+assertEq(result[2], 86);
+
+assertEq(calls.length, 3);
+
+assertEq(calls[0].args.length, 2);
+assertEq(calls[0].args[0], 41);
+assertEq(calls[0].args[1], 0);
+assertEq(calls[0].thisArg, this);
+
+assertEq(calls[1].args.length, 2);
+assertEq(calls[1].args[0], 42);
+assertEq(calls[1].args[1], 1);
+assertEq(calls[1].thisArg, this);
+
+assertEq(calls[2].args.length, 2);
+assertEq(calls[2].args[0], 43);
+assertEq(calls[2].args[1], 2);
+assertEq(calls[2].thisArg, this);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/calling-from-valid-1-onlyStrict-strict.js b/js/src/tests/non262/Tuple/from/calling-from-valid-1-onlyStrict-strict.js
new file mode 100644
index 0000000000..79914f4fd6
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/calling-from-valid-1-onlyStrict-strict.js
@@ -0,0 +1,44 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+'use strict';
+
+var list = {
+ '0': 41,
+ '1': 42,
+ '2': 43,
+ length: 3
+};
+var calls = [];
+
+function mapFn(value) {
+ calls.push({
+ args: arguments,
+ thisArg: this
+ });
+ return value * 2;
+}
+
+var result = Tuple.from(list, mapFn);
+
+assertEq(result.length, 3);
+assertEq(result[0], 82);
+assertEq(result[1], 84);
+assertEq(result[2], 86);
+
+assertEq(calls.length, 3);
+
+assertEq(calls[0].args.length, 2);
+assertEq(calls[0].args[0], 41);
+assertEq(calls[0].args[1], 0);
+assertEq(calls[0].thisArg, undefined);
+
+assertEq(calls[1].args.length, 2);
+assertEq(calls[1].args[0], 42);
+assertEq(calls[1].args[1], 1);
+assertEq(calls[1].thisArg, undefined);
+
+assertEq(calls[2].args.length, 2);
+assertEq(calls[2].args[0], 43);
+assertEq(calls[2].args[1], 2);
+assertEq(calls[2].thisArg, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/calling-from-valid-2.js b/js/src/tests/non262/Tuple/from/calling-from-valid-2.js
new file mode 100644
index 0000000000..23f78d829e
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/calling-from-valid-2.js
@@ -0,0 +1,44 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var list = {
+ '0': 41,
+ '1': 42,
+ '2': 43,
+ length: 3
+};
+var calls = [];
+var thisArg = {};
+
+function mapFn(value) {
+ calls.push({
+ args: arguments,
+ thisArg: this
+ });
+ return value * 2;
+}
+
+var result = Tuple.from(list, mapFn, thisArg);
+
+assertEq(result.length, 3);
+assertEq(result[0], 82);
+assertEq(result[1], 84);
+assertEq(result[2], 86);
+
+assertEq(calls.length, 3);
+
+assertEq(calls[0].args.length, 2);
+assertEq(calls[0].args[0], 41);
+assertEq(calls[0].args[1], 0);
+assertEq(calls[0].thisArg, thisArg);
+
+assertEq(calls[1].args.length, 2);
+assertEq(calls[1].args[0], 42);
+assertEq(calls[1].args[1], 1);
+assertEq(calls[1].thisArg, thisArg);
+
+assertEq(calls[2].args.length, 2);
+assertEq(calls[2].args[0], 43);
+assertEq(calls[2].args[1], 2);
+assertEq(calls[2].thisArg, thisArg);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/descriptor.js b/js/src/tests/non262/Tuple/from/descriptor.js
new file mode 100644
index 0000000000..60d5575187
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/descriptor.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var desc = Object.getOwnPropertyDescriptor(Tuple, "from");
+assertEq(desc.value, Tuple.from);
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/elements-added-after.js b/js/src/tests/non262/Tuple/from/elements-added-after.js
new file mode 100644
index 0000000000..d0c045ffb6
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/elements-added-after.js
@@ -0,0 +1,29 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var tupleIndex = -1;
+var originalLength = 7;
+var obj = {
+ length: originalLength,
+ 0: 2,
+ 1: 4,
+ 2: 8,
+ 3: 16,
+ 4: 32,
+ 5: 64,
+ 6: 128
+};
+var tuple = #[2, 4, 8, 16, 32, 64, 128];
+
+function mapFn(value, index) {
+ tupleIndex++;
+ assertEq(value, obj[tupleIndex]);
+ assertEq(index, tupleIndex);
+ obj[originalLength + tupleIndex] = 2 * tupleIndex + 1;
+
+ return obj[tupleIndex];
+}
+
+
+var t = Tuple.from(obj, mapFn);
+assertEq(t, tuple);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/elements-deleted-after.js b/js/src/tests/non262/Tuple/from/elements-deleted-after.js
new file mode 100644
index 0000000000..b4f6f24593
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/elements-deleted-after.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var originalTuple = #[0, 1, -2, 4, -8, 16];
+var array = [0,1,-2,4,-8,16];
+var t = #[];
+var arrayIndex = -1;
+
+function mapFn(value, index) {
+ this.arrayIndex++;
+ assertEq(value, array[this.arrayIndex]);
+ assertEq(index, this.arrayIndex);
+ array.splice(array.length - 1, 1);
+ return 127;
+}
+
+
+t = Tuple.from(array, mapFn, this);
+
+assertEq(t.length, originalTuple.length / 2);
+
+for (var j = 0; j < originalTuple.length / 2; j++) {
+ assertEq(t[j], 127);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/from.js b/js/src/tests/non262/Tuple/from/from.js
new file mode 100644
index 0000000000..ee79cdd33f
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/from.js
@@ -0,0 +1,89 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.2.2 Tuple.from ( items [ , mapFn [, thisArg ] ] )
+When the from method is called with argument items and optional arguments mapfn and thisArg, the following steps are taken:
+
+1. If mapfn is undefined, let mapping be false.
+2. Else,
+a. If IsCallable(mapfn) is false, throw a TypeError exception.
+b. Let mapping be true.
+3. Let list be a new empty List.
+4. Let k be 0.
+5. Let usingIterator be ? GetMethod(items, @@iterator).
+6. If usingIterator is not undefined, then
+a. Let adder be a new Abstract Closure with parameters (key, value) that captures (list, mapFn, thisArg, mapping, k) and performs the following steps when called:
+i. If mapping is true, then
+1. Let mappedValue be ? Call(mapfn, thisArg, « value, k »).
+ii. Else, let mappedValue be value.
+iii. If Type(mappedValue) is Object, throw a TypeError exception.
+iv. Append mappedValue to list.
+v. Set k to k + 1.
+b. Perform ! AddEntriesFromIterable(undefined, iterable, adder).
+c. Return a new Tuple value whose [[Sequence]] is list.
+7. NOTE: items is not an Iterable so assume it is an array-like object.
+8. Let arrayLike be ! ToObject(items).
+9. Let len be ? LengthOfArrayLike(arrayLike).
+10. Repeat, while k < len,
+a. Let Pk be ! ToString(k).
+b. Let kValue be ? Get(arrayLike, Pk).
+c. If mapping is true, then
+i. Let mappedValue be ? Call(mapfn, thisArg, « kValue, k »).
+d. Else, let mappedValue be kValue.
+e. If Type(mappedValue) is Object, throw a TypeError exception.
+f. Append mappedValue to list.
+g. Set k to k + 1.
+11. Return a new Tuple value whose [[Sequence]] is list.
+*/
+
+/* Step 1: mapfn explicitly undefined */
+assertEq(Tuple.from([1,2],undefined),#[1,2]);
+
+/* Step 2a: If IsCallable(mapfn) is false, throw a TypeError exception. */
+assertThrowsInstanceOf(() => Tuple.from([1,2,3],"monkeys"), TypeError, "mapfn not callable");
+
+/* Step 5 */
+assertThrowsInstanceOf(() => Tuple.from(undefined), TypeError,
+ "can't access property Symbol.iterator of undefined");
+assertThrowsInstanceOf(() => Tuple.from(null), TypeError,
+ "can't access property Symbol.iterator of null");
+assertEq(Tuple.from(1), #[]);
+var obj = {};
+obj[Symbol.iterator] = null;
+assertEq(Tuple.from(obj), #[]);
+obj[Symbol.iterator] = 5;
+assertThrowsInstanceOf(() => Tuple.from(obj), TypeError,
+ "number is not a function");
+
+
+/* Step 6a.i. mapping exists */
+assertEq(Tuple.from([1,2,3],x => x+1), #[2,3,4]);
+assertEq(Tuple.from(#[1,2,3],x => x+1), #[2,3,4]);
+assertEq(Tuple.from("xyz", c => String.fromCharCode(c.charCodeAt(0) + 1)), #['y', 'z', '{']);
+/* Step 6a.ii. mapping does not exist */
+assertEq(Tuple.from([1,2,3,4,5]), #[1,2,3,4,5]);
+assertEq(Tuple.from(#[1,2,3,4,5]), #[1,2,3,4,5]);
+assertEq(Tuple.from("xyz"), #['x', 'y', 'z']);
+
+/* Step 6a.iii. if mapfn returns Object, throw */
+assertThrowsInstanceOf(() => Tuple.from([1,2], x => [x]), TypeError, "Tuple cannot contain object");
+
+/* Step 7 -- array-like but not iterable */
+var obj = { length: 3, 0: "a", 1: "b", 2: "c" };
+assertEq(Tuple.from(obj), #["a","b","c"]);
+assertEq(Tuple.from(obj, s => s + s), #["aa","bb","cc"]);
+
+obj = { 0: "a", 1: "b", 2: "c" };
+assertEq(Tuple.from(obj), #[]);
+
+obj = { length: 3, 0: 1, 2: 3 };
+assertEq(Tuple.from(obj), #[1, undefined, 3]);
+
+obj = { length: 3, 0: 1, 1: [2], 2: 3 };
+assertThrowsInstanceOf(() => Tuple.from(obj), TypeError, "Tuple cannot contain object");
+
+/* Step 10e */
+assertThrowsInstanceOf(() => Tuple.from([1, 2, [3,4]]), TypeError,
+ "Tuple can't contain Object");
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/get-iter-method-err.js b/js/src/tests/non262/Tuple/from/get-iter-method-err.js
new file mode 100644
index 0000000000..847b3374ae
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/get-iter-method-err.js
@@ -0,0 +1,12 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var items = {};
+Object.defineProperty(items, Symbol.iterator, {
+ get: function() {
+ throw new RangeError();
+ }
+});
+
+assertThrowsInstanceOf(() => Tuple.from(items), RangeError,
+ 'Tuple.from(items) should throw');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/indexed-setters.js b/js/src/tests/non262/Tuple/from/indexed-setters.js
new file mode 100644
index 0000000000..90aa5be1cb
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/indexed-setters.js
@@ -0,0 +1,12 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+// If an indexed Array setter is overridden, TupleMap shouldn't use it
+// when constructing the intermediate array
+
+z = 5;
+Object.defineProperty(Array.prototype, '0', { set: function(y) { z = 42; }});
+newT = Tuple.from([1, 2, 3]);
+assertEq(z, 5);
+
+reportCompare(0, 0);
+
diff --git a/js/src/tests/non262/Tuple/from/items-is-arraybuffer.js b/js/src/tests/non262/Tuple/from/items-is-arraybuffer.js
new file mode 100644
index 0000000000..4e55c1b9fe
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/items-is-arraybuffer.js
@@ -0,0 +1,8 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var arrayBuffer = new ArrayBuffer(7);
+
+var result = Tuple.from(arrayBuffer);
+
+assertEq(result.length, 0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/items-is-null-throws.js b/js/src/tests/non262/Tuple/from/items-is-null-throws.js
new file mode 100644
index 0000000000..d6574bebd1
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/items-is-null-throws.js
@@ -0,0 +1,5 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+assertThrowsInstanceOf(() => Tuple.from(null), TypeError,
+ 'Tuple.from(null) should throw');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/iter-adv-err.js b/js/src/tests/non262/Tuple/from/iter-adv-err.js
new file mode 100644
index 0000000000..44b96dc5ff
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/iter-adv-err.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var items = {};
+items[Symbol.iterator] = function() {
+ return {
+ next: function() {
+ throw new RangeError();
+ }
+ };
+};
+
+assertThrowsInstanceOf(function() {
+ Tuple.from(items);
+}, RangeError, 'Tuple.from(items) should throw');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/iter-get-iter-err.js b/js/src/tests/non262/Tuple/from/iter-get-iter-err.js
new file mode 100644
index 0000000000..c868c549fd
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/iter-get-iter-err.js
@@ -0,0 +1,11 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var itemsPoisonedSymbolIterator = {};
+itemsPoisonedSymbolIterator[Symbol.iterator] = function() {
+ throw new RangeError();
+};
+
+assertThrowsInstanceOf(function() {
+ Tuple.from(itemsPoisonedSymbolIterator);
+}, RangeError, 'Tuple.from(itemsPoisonedSymbolIterator) throws');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/iter-get-iter-val-err.js b/js/src/tests/non262/Tuple/from/iter-get-iter-val-err.js
new file mode 100644
index 0000000000..d1590ecb01
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/iter-get-iter-val-err.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var itemsPoisonedIteratorValue = {};
+var poisonedValue = {};
+Object.defineProperty(poisonedValue, 'value', {
+ get: function() {
+ throw new RangeError();
+ }
+});
+itemsPoisonedIteratorValue[Symbol.iterator] = function() {
+ return {
+ next: function() {
+ return poisonedValue;
+ }
+ };
+};
+
+assertThrowsInstanceOf(function() {
+ Tuple.from(itemsPoisonedIteratorValue);
+}, RangeError, 'Tuple.from(itemsPoisonedIteratorValue) throws');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/iter-map-fn-args.js b/js/src/tests/non262/Tuple/from/iter-map-fn-args.js
new file mode 100644
index 0000000000..33c8234d47
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/iter-map-fn-args.js
@@ -0,0 +1,44 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var args = [];
+var firstResult = {
+ done: false,
+ value: {}
+};
+var secondResult = {
+ done: false,
+ value: {}
+};
+var mapFn = function(value, idx) {
+ args.push(arguments);
+};
+var items = {};
+var nextResult = firstResult;
+var nextNextResult = secondResult;
+
+items[Symbol.iterator] = function() {
+ return {
+ next: function() {
+ var result = nextResult;
+ nextResult = nextNextResult;
+ nextNextResult = {
+ done: true
+ };
+
+ return result;
+ }
+ };
+};
+
+Tuple.from(items, mapFn);
+
+assertEq(args.length, 2);
+
+assertEq(args[0].length, 2);
+assertEq(args[0][0], firstResult.value);
+assertEq(args[0][1], 0);
+
+assertEq(args[1].length, 2);
+assertEq(args[1][0], secondResult.value);
+assertEq(args[1][1], 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/iter-map-fn-err.js b/js/src/tests/non262/Tuple/from/iter-map-fn-err.js
new file mode 100644
index 0000000000..c48db001b0
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/iter-map-fn-err.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var closeCount = 0;
+var mapFn = function() {
+ throw new RangeError();
+};
+var items = {};
+items[Symbol.iterator] = function() {
+ return {
+ return: function() {
+ closeCount += 1;
+ },
+ next: function() {
+ return {
+ done: false
+ };
+ }
+ };
+};
+
+assertThrowsInstanceOf(function() {
+ Tuple.from(items, mapFn);
+}, RangeError, 'Tuple.from(items, mapFn) should throw');
+
+assertEq(closeCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/iter-map-fn-return.js b/js/src/tests/non262/Tuple/from/iter-map-fn-return.js
new file mode 100644
index 0000000000..418439b255
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/iter-map-fn-return.js
@@ -0,0 +1,44 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var thisVals = [];
+var nextResult = {
+ done: false,
+ value: {}
+};
+var nextNextResult = {
+ done: false,
+ value: {}
+};
+var firstReturnVal = 1;
+var secondReturnVal = 2;
+var mapFn = function(value, idx) {
+ var returnVal = nextReturnVal;
+ nextReturnVal = nextNextReturnVal;
+ nextNextReturnVal = null;
+ return returnVal;
+};
+var nextReturnVal = firstReturnVal;
+var nextNextReturnVal = secondReturnVal;
+var items = {};
+var result;
+
+items[Symbol.iterator] = function() {
+ return {
+ next: function() {
+ var result = nextResult;
+ nextResult = nextNextResult;
+ nextNextResult = {
+ done: true
+ };
+
+ return result;
+ }
+ };
+};
+
+result = Tuple.from(items, mapFn);
+
+assertEq(result.length, 2);
+assertEq(result[0], firstReturnVal);
+assertEq(result[1], secondReturnVal);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/iter-map-fn-this-arg.js b/js/src/tests/non262/Tuple/from/iter-map-fn-this-arg.js
new file mode 100644
index 0000000000..2fdd3ddfb4
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/iter-map-fn-this-arg.js
@@ -0,0 +1,38 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var thisVals = [];
+var nextResult = {
+ done: false,
+ value: {}
+};
+var nextNextResult = {
+ done: false,
+ value: {}
+};
+var mapFn = function() {
+ thisVals.push(this);
+};
+var items = {};
+var thisVal = {};
+
+items[Symbol.iterator] = function() {
+ return {
+ next: function() {
+ var result = nextResult;
+ nextResult = nextNextResult;
+ nextNextResult = {
+ done: true
+ };
+
+ return result;
+ }
+ };
+};
+
+Tuple.from(items, mapFn, thisVal);
+
+assertEq(thisVals.length, 2);
+assertEq(thisVals[0], thisVal);
+assertEq(thisVals[1], thisVal);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/iter-map-fn-this-non-strict.js b/js/src/tests/non262/Tuple/from/iter-map-fn-this-non-strict.js
new file mode 100644
index 0000000000..56225e0021
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/iter-map-fn-this-non-strict.js
@@ -0,0 +1,39 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var thisVals = [];
+var nextResult = {
+ done: false,
+ value: {}
+};
+var nextNextResult = {
+ done: false,
+ value: {}
+};
+var mapFn = function() {
+ thisVals.push(this);
+};
+var items = {};
+var global = function() {
+ return this;
+}();
+
+items[Symbol.iterator] = function() {
+ return {
+ next: function() {
+ var result = nextResult;
+ nextResult = nextNextResult;
+ nextNextResult = {
+ done: true
+ };
+
+ return result;
+ }
+ };
+};
+
+Tuple.from(items, mapFn);
+
+assertEq(thisVals.length, 2);
+assertEq(thisVals[0], global);
+assertEq(thisVals[1], global);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/iter-map-fn-this-strict-strict.js b/js/src/tests/non262/Tuple/from/iter-map-fn-this-strict-strict.js
new file mode 100644
index 0000000000..8dec1851d3
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/iter-map-fn-this-strict-strict.js
@@ -0,0 +1,37 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+'use strict';
+var thisVals = [];
+var nextResult = {
+ done: false,
+ value: {}
+};
+var nextNextResult = {
+ done: false,
+ value: {}
+};
+var mapFn = function() {
+ thisVals.push(this);
+};
+var items = {};
+
+items[Symbol.iterator] = function() {
+ return {
+ next: function() {
+ var result = nextResult;
+ nextResult = nextNextResult;
+ nextNextResult = {
+ done: true
+ };
+
+ return result;
+ }
+ };
+};
+
+Tuple.from(items, mapFn);
+
+assertEq(thisVals.length, 2);
+assertEq(thisVals[0], undefined);
+assertEq(thisVals[1], undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/iter-next-error.js b/js/src/tests/non262/Tuple/from/iter-next-error.js
new file mode 100644
index 0000000000..b29c83c2ec
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/iter-next-error.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/* Step 6b. */
+/* AddEntriesFromIterable should throw if next() throws */
+
+var iter = {};
+iter[Symbol.iterator] = function() {
+ return {
+ next: function() {
+ throw new SyntaxError();
+ }
+ };
+};
+
+assertThrowsInstanceOf(function() {
+ Tuple.from(iter);
+}, SyntaxError, "from() should throw if next() throws");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/iter-next-value-error.js b/js/src/tests/non262/Tuple/from/iter-next-value-error.js
new file mode 100644
index 0000000000..e3b78f0c60
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/iter-next-value-error.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/* Step 6b. */
+/* AddEntriesFromIterable should throw if next() throws */
+
+var iter = {};
+iter[Symbol.iterator] = function() {
+ return {
+ next: function() {
+ var result = {};
+ Object.defineProperty(result, 'value', {
+ get: function() {
+ throw new SyntaxError();
+ }
+ });
+
+ return result;
+ }
+ };
+};
+
+assertThrowsInstanceOf(function() {
+ Tuple.from(iter);
+}, SyntaxError, "from() should throw if next() returns value that throws");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/iter-set-elem-prop.js b/js/src/tests/non262/Tuple/from/iter-set-elem-prop.js
new file mode 100644
index 0000000000..0cf1452d0a
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/iter-set-elem-prop.js
@@ -0,0 +1,37 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var items = {};
+var firstIterResult = {
+ done: false,
+ value: 1
+};
+var secondIterResult = {
+ done: false,
+ value: 2
+};
+var thirdIterResult = {
+ done: true,
+ value: 3
+};
+var nextIterResult = firstIterResult;
+var nextNextIterResult = secondIterResult;
+var result;
+
+items[Symbol.iterator] = function() {
+ return {
+ next: function() {
+ var result = nextIterResult;
+
+ nextIterResult = nextNextIterResult;
+ nextNextIterResult = thirdIterResult;
+
+ return result;
+ }
+ };
+};
+
+result = Tuple.from(items);
+
+assertEq(result[0], firstIterResult.value);
+assertEq(result[1], secondIterResult.value);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/iter-set-length.js b/js/src/tests/non262/Tuple/from/iter-set-length.js
new file mode 100644
index 0000000000..8515ea2bd9
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/iter-set-length.js
@@ -0,0 +1,31 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var items = {};
+var result, nextIterResult, lastIterResult;
+items[Symbol.iterator] = function() {
+ return {
+ next: function() {
+ var result = nextIterResult;
+ nextIterResult = lastIterResult;
+ return result;
+ }
+ };
+};
+
+nextIterResult = lastIterResult = {
+ done: true
+};
+result = Tuple.from(items);
+
+assertEq(result.length, 0);
+
+nextIterResult = {
+ done: false
+};
+lastIterResult = {
+ done: true
+};
+result = Tuple.from(items);
+
+assertEq(result.length, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/length.js b/js/src/tests/non262/Tuple/from/length.js
new file mode 100644
index 0000000000..0c4c77af6f
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/length.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.from, "length");
+assertEq(desc.value, 1);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.from), false);
+
+assertThrowsInstanceOf(() => {
+ new Tuple.from([]);
+}, TypeError, '`new Tuple.from()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/mapfn-is-not-callable-typeerror.js b/js/src/tests/non262/Tuple/from/mapfn-is-not-callable-typeerror.js
new file mode 100644
index 0000000000..9643a8a916
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/mapfn-is-not-callable-typeerror.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+let vals = [[null, "null"],
+ [{}, "{}"],
+ ['string', "\'string\'"],
+ [true, "true"],
+ [42, "42"],
+ [Symbol('1'), "Symbol(\'1\')"]];
+
+for (p of vals) {
+ let mapfn = p[0];
+ assertThrowsInstanceOf(() => Tuple.from([], mapfn),
+ TypeError, 'Tuple.from([],' + p[1] + ' should throw');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/mapfn-throws-exception.js b/js/src/tests/non262/Tuple/from/mapfn-throws-exception.js
new file mode 100644
index 0000000000..fd3d78fb98
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/mapfn-throws-exception.js
@@ -0,0 +1,12 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var array = [2, 4, 8, 16, 32, 64, 128];
+
+function mapFnThrows(value, index, obj) {
+ throw new RangeError();
+}
+
+assertThrowsInstanceOf(function() {
+ Tuple.from(array, mapFnThrows);
+}, RangeError, 'Tuple.from(array, mapFnThrows) throws');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/name.js b/js/src/tests/non262/Tuple/from/name.js
new file mode 100644
index 0000000000..04e23d420d
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/name.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+desc = Object.getOwnPropertyDescriptor(Tuple.from, "name");
+assertEq(desc.value, "from");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/not-a-constructor.js b/js/src/tests/non262/Tuple/from/not-a-constructor.js
new file mode 100644
index 0000000000..9c1318c8b0
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/not-a-constructor.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+assertEq(isConstructor(Tuple.from), false);
+
+assertThrowsInstanceOf(() => {
+ new Tuple.from([]);
+}, TypeError, 'new Tuple.from([]) throws a TypeError exception');
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/prop-desc.js b/js/src/tests/non262/Tuple/from/prop-desc.js
new file mode 100644
index 0000000000..60d5575187
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/prop-desc.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var desc = Object.getOwnPropertyDescriptor(Tuple, "from");
+assertEq(desc.value, Tuple.from);
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/source-array-boundary.js b/js/src/tests/non262/Tuple/from/source-array-boundary.js
new file mode 100644
index 0000000000..283f47425b
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/source-array-boundary.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var array = [Number.MAX_VALUE, Number.MIN_VALUE, Number.NaN, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY];
+var arrayIndex = -1;
+
+function mapFn(value, index) {
+ this.arrayIndex++;
+ assertEq(value, array[this.arrayIndex]);
+ assertEq(index, this.arrayIndex);
+ return value;
+}
+
+var t = Tuple.from(array, mapFn, this);
+
+assertEq(t.length, array.length);
+assertEq(t[0], Number.MAX_VALUE);
+assertEq(t[1], Number.MIN_VALUE);
+assertEq(t[2], Number.NaN);
+assertEq(t[3], Number.NEGATIVE_INFINITY);
+assertEq(t[4], Number.POSITIVE_INFINITY);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/source-object-iterator-1.js b/js/src/tests/non262/Tuple/from/source-object-iterator-1.js
new file mode 100644
index 0000000000..65afd950f4
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/source-object-iterator-1.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var array = [2, 4, 8, 16, 32, 64, 128];
+var obj = {
+ [Symbol.iterator]() {
+ return {
+ index: 0,
+ next() {
+ throw new RangeError();
+ },
+ isDone: false,
+ get val() {
+ this.index++;
+ if (this.index > 7) {
+ this.isDone = true;
+ }
+ return 1 << this.index;
+ }
+ };
+ }
+};
+assertThrowsInstanceOf(function() {
+ Tuple.from(obj);
+}, RangeError, 'Tuple.from(obj) throws');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/source-object-length.js b/js/src/tests/non262/Tuple/from/source-object-length.js
new file mode 100644
index 0000000000..3d0c2a0aac
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/source-object-length.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var array = [2, 4, 0, 16];
+var expectedTuple = #[2, 4, undefined, 16];
+var obj = {
+ length: 4,
+ 0: 2,
+ 1: 4,
+ 2: 0,
+ 3: 16
+};
+delete obj[2];
+let t = Tuple.from(obj);
+assertEq(t, expectedTuple);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/source-object-without.js b/js/src/tests/non262/Tuple/from/source-object-without.js
new file mode 100644
index 0000000000..b2d625c5ae
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/source-object-without.js
@@ -0,0 +1,13 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var obj = {
+ 0: 2,
+ 1: 4,
+ 2: 8,
+ 3: 16
+}
+
+var t = Tuple.from(obj);
+assertEq(t.length, 0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/from/this-null.js b/js/src/tests/non262/Tuple/from/this-null.js
new file mode 100644
index 0000000000..16f2bfe021
--- /dev/null
+++ b/js/src/tests/non262/Tuple/from/this-null.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+// this = null or undefined should not throw
+var result = Tuple.from.call(null, #[]);
+
+assertEq(result, #[]);
+result = Tuple.from.call(undefined, #[]);
+assertEq(result, #[]);
+result = Tuple.from.call({}, #[]);
+assertEq(result, #[]);
+result = Tuple.from.call(5, #[]);
+assertEq(result, #[]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/gc.js b/js/src/tests/non262/Tuple/gc.js
new file mode 100644
index 0000000000..0cf37ad46c
--- /dev/null
+++ b/js/src/tests/non262/Tuple/gc.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+// Test that objects (in this case, closures) containing Tuples are traced properly
+function foo() {
+ var tup = #[1];
+ (() => assertEq(tup, #[1]))();
+}
+
+let n = 1000;
+for (i = 0; i < n; i++) {
+ foo();
+}
+
+if (typeof reportCompare === "function") reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/initializers/6.1.2.1.js b/js/src/tests/non262/Tuple/initializers/6.1.2.1.js
new file mode 100644
index 0000000000..dca7b0f2e3
--- /dev/null
+++ b/js/src/tests/non262/Tuple/initializers/6.1.2.1.js
@@ -0,0 +1,129 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+TupleElementList : AssignmentExpression
+1. Let initResult be the result of evaluating AssignmentExpression.
+2. Let initValue be ? GetValue(initResult).
+3. Return ? AddValueToTupleSequenceList(sequence, value).
+*/
+
+var a = 5;
+var b = 10;
+var arr = [1,2,3,4,5];
+var badArr = [1, new Object(), 3];
+var t = #[a < b ? "x" : "y"];
+assertEq(t, #["x"]);
+
+t = #[0 in arr, 42 in arr, 1 in arr, 100 in arr];
+assertEq(t, #[true, false, true, false]);
+
+t = #[a = 1, b = b * 3];
+assertEq(t, #[1, 30]);
+assertEq(a, 1);
+assertEq(b, 30);
+
+/* 6.1.2.1
+TupleElementList : AssignmentExpression
+ ...
+ 2. Let initValue be ? GetValue(initResult).
+ ...
+ 6.2.4.5 GetValue ( V )
+ The abstract operation GetValue takes argument V. It performs the following steps when called:
+
+ 1. ReturnIfAbrupt(V).
+*/
+let bBefore = b;
+let tBefore = t;
+function f() { throw new RangeError(); }
+assertThrowsInstanceOf(() => t = #[a = 2, f(), b = 3],
+ RangeError, "t = #[a = 2, f(), b = 3] throws");
+assertEq(a, 2);
+assertEq(b, bBefore);
+assertEq(t, tBefore);
+
+/*
+ GetValue
+ ...
+ 3. If IsUnresolvableReference(V) is true, throw a ReferenceError exception.
+*/
+assertThrowsInstanceOf(() => t = #[unbound],
+ ReferenceError, "t = #[unbound] throws");
+assertEq(t, tBefore);
+
+/* 6.1.2.1
+TupleElementList : AssignmentExpression
+ ...
+ 3. Return ? AddValueToTupleSequenceList(sequence, value).
+*/
+assertThrowsInstanceOf(() => t = #[new Object()],
+ TypeError, "Object in Tuple");
+assertEq(t, tBefore);
+assertThrowsInstanceOf(() => t = #[{}],
+ TypeError, "Object in Tuple")
+assertEq(t, tBefore);
+assertThrowsInstanceOf(() => t = #[new String("s")],
+ TypeError, "Object in Tuple")
+assertEq(t, tBefore);
+assertThrowsInstanceOf(() => t = #[[1,2,3]],
+ TypeError, "Object in Tuple")
+assertEq(t, tBefore);
+assertThrowsInstanceOf(() => t = #[function(x) { return x; }],
+ TypeError, "Object in Tuple")
+assertEq(t, tBefore);
+
+/* 6.1.2.1
+
+TupleElementList : SpreadElement
+1. Return the Result of performing TupleSequenceAccumulation for SpreadElement with argument sequence.
+*/
+assertEq(#[...arr], #[1,2,3,4,5]);
+assertThrowsInstanceOf(() => #[...badArr],
+ TypeError, "Object in Tuple");
+
+/*
+TupleElementList : TupleElementList , AssignmentExpression
+1. Perform TupleSequenceAccumulation for TupleElementList with argument sequence.
+2. Let initResult be the result of evaluating AssignmentExpression.
+3. Let initValue be ? GetValue(initResult).
+4. Return ? AddValueToTupleSequenceList(sequence, value).
+*/
+
+assertThrowsInstanceOf(() => t = #[1, a = 5, b = new Object(), 5],
+ TypeError, "Object in Tuple");
+assertEq(t, tBefore);
+
+/* TupleElementList : TupleElementList , SpreadElement
+1. Perform TupleSequenceAccumulation for TupleElementList with argument sequence.
+2. Return the Result of performing TupleSequenceAccumulation for SpreadElement with argument sequence.
+*/
+
+assertEq(#["a", "b", ...arr, "c"], #["a", "b", 1, 2, 3, 4, 5, "c"]);
+assertThrowsInstanceOf(() => t = #["a", "b", ...badArr, "c"],
+ TypeError, "Object in Tuple");
+
+/*
+SpreadElement : ... AssignmentExpression
+1. Let spreadRef be the result of evaluating AssignmentExpression.
+2. Let spreadObj be ? GetValue(spreadRef).
+3. Let iteratorRecord be ? GetIterator(spreadObj).
+4. Repeat,
+a. Let next be ? IteratorStep(iteratorRecord).
+b. If next is false, return sequence.
+c. Let nextValue be ? IteratorValue(next).
+d. Let completion be AddValueToTupleSequenceList(sequence, nextValue).
+e. If completion is an abrupt completion, then
+i. Return IteratorClose(iteratorRecord, completion).
+*/
+/* Step 2 */
+assertThrowsInstanceOf(() => t = #[...unbound],
+ ReferenceError, "t = #[...unbound throws]");
+assertEq(t, tBefore);
+/* Step 3 */
+var notIterable = Symbol('c');
+assertThrowsInstanceOf(() => t = #[...notIterable],
+ TypeError, "t = #[...notIterable] is type error");
+/* TODO -- test other iterator cases */
+
+
+reportCompare(0, 0);
+
+
diff --git a/js/src/tests/non262/Tuple/isTuple/8.2.2.1.js b/js/src/tests/non262/Tuple/isTuple/8.2.2.1.js
new file mode 100644
index 0000000000..9ac63ebc66
--- /dev/null
+++ b/js/src/tests/non262/Tuple/isTuple/8.2.2.1.js
@@ -0,0 +1,54 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.2
+The Tuple constructor:
+...
+has the following properties:
+...
+
+8.2.2.1 Tuple.isTuple ( arg )
+The isTuple function takes one argument arg, and performs the following steps:
+
+1. Return ! IsTuple(arg).
+*/
+
+var Tuple_isTuple = Tuple.isTuple;
+assertEq(typeof Tuple_isTuple, "function");
+
+assertEq(Tuple_isTuple(), false);
+assertEq(Tuple_isTuple(Tuple.prototype), false);
+assertEq(Tuple_isTuple([]), false);
+assertEq(Tuple_isTuple(42), false);
+assertEq(Tuple_isTuple(new Number(-50)), false);
+assertEq(Tuple_isTuple(undefined), false);
+assertEq(Tuple_isTuple(true), false);
+assertEq(Tuple_isTuple(new Boolean(false)), false);
+assertEq(Tuple_isTuple("hello"), false);
+assertEq(Tuple_isTuple(new String("bye")), false);
+assertEq(Tuple_isTuple({}), false);
+assertEq(Tuple_isTuple(null), false);
+assertEq(Tuple_isTuple(new RegExp()), false);
+assertEq(Tuple_isTuple(JSON), false);
+assertEq(Tuple_isTuple(Math), false);
+assertEq(Tuple_isTuple(new Date()), false);
+assertEq(Tuple_isTuple(new SyntaxError()), false);
+var arg;
+function fun() { arg = arguments; }(1, 2, 3);
+assertEq(Tuple_isTuple(arg), false);
+assertEq(Tuple_isTuple(this), false);
+assertEq(Tuple_isTuple(function() {}), false);
+var proto = Tuple.prototype;
+var Con = function() {};
+Con.prototype = proto;
+var child = new Con();
+assertEq(Tuple_isTuple(child), false);
+assertEq(Tuple_isTuple({0: 1, 1: 2, length: 2}), false);
+
+assertEq(Tuple_isTuple.call(1), false);
+assertEq(Tuple_isTuple.call(#[1]), false);
+assertEq(Tuple_isTuple.call(undefined, 1), false);
+assertEq(Tuple_isTuple.call(undefined, undefined), false);
+assertEq(Tuple_isTuple.call(undefined, #[1]), true);
+assertEq(Tuple_isTuple.call(undefined, Object(#[1])), true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/isTuple/descriptor.js b/js/src/tests/non262/Tuple/isTuple/descriptor.js
new file mode 100644
index 0000000000..c6e3965e09
--- /dev/null
+++ b/js/src/tests/non262/Tuple/isTuple/descriptor.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var desc = Object.getOwnPropertyDescriptor(Tuple, "isTuple");
+assertEq(desc.value, Tuple.isTuple);
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/isTuple/length.js b/js/src/tests/non262/Tuple/isTuple/length.js
new file mode 100644
index 0000000000..6bad2aa680
--- /dev/null
+++ b/js/src/tests/non262/Tuple/isTuple/length.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+desc = Object.getOwnPropertyDescriptor(Tuple.isTuple, "length");
+assertEq(desc.value, 1);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/isTuple/name.js b/js/src/tests/non262/Tuple/isTuple/name.js
new file mode 100644
index 0000000000..a0c0688543
--- /dev/null
+++ b/js/src/tests/non262/Tuple/isTuple/name.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+desc = Object.getOwnPropertyDescriptor(Tuple.isTuple, "name");
+assertEq(desc.value, "isTuple");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/isTuple/not-a-constructor.js b/js/src/tests/non262/Tuple/isTuple/not-a-constructor.js
new file mode 100644
index 0000000000..c7844a4c83
--- /dev/null
+++ b/js/src/tests/non262/Tuple/isTuple/not-a-constructor.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/* 18 ECMAScript Standard Built-in 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.
+*/
+
+assertEq(isConstructor(Tuple.isTuple), false);
+
+assertThrowsInstanceOf(() => new Tuple.isTuple(#[]), TypeError,
+ "new Tuple.isTuple(#[]) throws");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/length-ownproperty.js b/js/src/tests/non262/Tuple/length-ownproperty.js
new file mode 100644
index 0000000000..d79aea4136
--- /dev/null
+++ b/js/src/tests/non262/Tuple/length-ownproperty.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/* Tuples should have a length ownProperty that can't be overridden
+ * This test is expected to fail until the spec change in
+ * https://github.com/tc39/proposal-record-tuple/issues/282 is implemented.
+ */
+
+/*
+var desc = Object.getOwnPropertyDescriptor(#[1,2,3], "length");
+assertEq(desc.value, 3);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, false);
+Object.defineProperty(Tuple.prototype, "length", {value: 0});
+desc = Object.getOwnPropertyDescriptor(#[1,2,3], "length");
+assertEq(desc.value, 3);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, false);
+*/
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/literal.js b/js/src/tests/non262/Tuple/literal.js
new file mode 100644
index 0000000000..356b5255c3
--- /dev/null
+++ b/js/src/tests/non262/Tuple/literal.js
@@ -0,0 +1,32 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+let tup = #[1, 2, 3];
+
+assertEq(tup.length, 3);
+assertEq(tup[0], 1);
+assertEq(tup[1], 2);
+assertEq(tup[2], 3);
+
+let arr = [3, 4, 5];
+tup = #[1, 2, ...arr, 6, ...arr];
+
+assertEq(tup.length, 9);
+assertEq(tup[0], 1);
+assertEq(tup[1], 2);
+assertEq(tup[2], 3);
+assertEq(tup[3], 4);
+assertEq(tup[4], 5);
+assertEq(tup[5], 6);
+assertEq(tup[6], 3);
+assertEq(tup[7], 4);
+assertEq(tup[8], 5);
+
+tup = #[(() => 1)()];
+
+assertEq(tup.length, 1);
+assertEq(tup[0], 1);
+
+tup = #[];
+assertEq(tup.length, 0);
+
+if (typeof reportCompare === "function") reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/methods.js b/js/src/tests/non262/Tuple/methods.js
new file mode 100644
index 0000000000..df21b816f1
--- /dev/null
+++ b/js/src/tests/non262/Tuple/methods.js
@@ -0,0 +1,554 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+let tup = #[1,2,3];
+let tup2 = #[1,2,3];
+let empty = #[];
+
+var tReversed = tup.toReversed();
+assertEq(tReversed, #[3, 2, 1]);
+assertEq(tup, tup2);
+assertEq(#[].toReversed(), #[]);
+
+
+let tup5 = #[42, 1, 5, 0, 333, 10];
+let sorted_result = tup5.toSorted();
+let expected_result = #[0, 1, 10, 333, 42, 5];
+assertEq(sorted_result, expected_result);
+let sorted_result2 = tup5.toSorted((x, y) => y > x);
+let expected_result2 = #[333, 42, 10, 5, 1, 0];
+assertEq(sorted_result2, expected_result2);
+
+assertThrowsInstanceOf(() => tup5.toSorted("monkeys"),
+ TypeError,
+ "invalid Array.prototype.toSorted argument")
+
+/* toSpliced */
+/* examples from:
+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice */
+
+function unchanged(t) {
+ assertEq(t, #['angel', 'clown', 'mandarin', 'sturgeon']);
+}
+
+// Remove no elements before index 2, insert "drum"
+let myFish = #['angel', 'clown', 'mandarin', 'sturgeon']
+var myFishSpliced = myFish.toSpliced(2, 0, 'drum')
+unchanged(myFish);
+assertEq(myFishSpliced, #['angel', 'clown', 'drum', 'mandarin', 'sturgeon']);
+
+
+// Remove no elements before index 2, insert "drum" and "guitar"
+myFishSpliced = myFish.toSpliced(2, 0, 'drum', 'guitar');
+unchanged(myFish);
+assertEq(myFishSpliced, #['angel', 'clown', 'drum', 'guitar', 'mandarin', 'sturgeon'])
+
+// Remove 1 element at index 3
+let myFish1 = #['angel', 'clown', 'drum', 'mandarin', 'sturgeon'];
+myFishSpliced = myFish1.toSpliced(3, 1);
+assertEq(myFish1, #['angel', 'clown', 'drum', 'mandarin', 'sturgeon']);
+assertEq(myFishSpliced, #['angel', 'clown', 'drum', 'sturgeon']);
+
+// Remove 1 element at index 2, and insert 'trumpet'
+let myFish2 = #['angel', 'clown', 'drum', 'sturgeon']
+myFishSpliced = myFish2.toSpliced(2, 1, 'trumpet');
+assertEq(myFish2, #['angel', 'clown', 'drum', 'sturgeon']);
+assertEq(myFishSpliced, #['angel', 'clown', 'trumpet', 'sturgeon']);
+
+// Remove 2 elements at index 0, and insert 'parrot', 'anemone', and 'blue'
+let myFish3 = #['angel', 'clown', 'trumpet', 'sturgeon']
+myFishSpliced = myFish3.toSpliced(0, 2, 'parrot', 'anemone', 'blue');
+assertEq(myFish3, #['angel', 'clown', 'trumpet', 'sturgeon']);
+assertEq(myFishSpliced, #['parrot', 'anemone', 'blue', 'trumpet', 'sturgeon']);
+
+// Remove 2 elements, starting at index 2
+let myFish4 = #['parrot', 'anemone', 'blue', 'trumpet', 'sturgeon']
+myFishSpliced = myFish4.toSpliced(2, 2);
+assertEq(myFish4, #['parrot', 'anemone', 'blue', 'trumpet', 'sturgeon']);
+assertEq(myFishSpliced, #['parrot', 'anemone', 'sturgeon']);
+
+// Remove 1 element from index -2
+myFishSpliced = myFish.toSpliced(-2, 1);
+unchanged(myFish);
+assertEq(myFishSpliced, #['angel', 'clown', 'sturgeon']);
+
+// Remove all elements, starting from index 2
+myFishSpliced = myFish.toSpliced(2);
+unchanged(myFish);
+assertEq(myFishSpliced, #['angel', 'clown']);
+
+assertThrowsInstanceOf(() => myFish.toSpliced(1, 0, new Object(42)),
+ TypeError,
+ "Record and Tuple can only contain primitive values");
+
+//******************
+function concatTest(t, expected, ...args) {
+ let result = t.concat(...args);
+ assertEq(result, expected);
+}
+
+let tupConcat = tup.concat(#[4,5,6]);
+assertEq(tup, tup2);
+assertEq(tupConcat, #[1,2,3,4,5,6]);
+
+concatTest(tup, tup, #[]);
+concatTest(empty, tup, #[1,2,3]);
+concatTest(tup, #[1,2,3,1,2,3,4,5,6],1,2,3,4,5,6);
+concatTest(tup, #[1,2,3,1,2,3,4,5,6],1,#[2,3,4],5,6);
+concatTest(tup, #[1,2,3,1,2,3,4],[1,2,3,4]);
+concatTest(tup, #[1,2,3,1,2,3,4,5,6],1,[2,3,4],5,6);
+concatTest(tup, #[1,2,3,1,2,3,4,5,6],[1,2,3],[4,5,6]);
+concatTest(tup, #[1,2,3,1,2,3,4,5,6],#[1,2,3],#[4,5,6]);
+
+// .includes()
+
+assertEq(tup.includes(1), true);
+assertEq(tup.includes(2), true);
+assertEq(tup.includes(3), true);
+assertEq(empty.includes(1), false);
+assertEq(empty.includes(0), false);
+assertEq(empty.includes(0, 1), false);
+assertEq(tup.includes(2, 1), true);
+assertEq(tup.includes(2, 2), false);
+assertEq(tup.includes(2, -1), false);
+assertEq(tup.includes(2, -2), true);
+assertEq(tup.includes(0, Infinity), false);
+assertEq(tup.includes(2, -Infinity), true);
+assertEq(tup.includes(2, undefined), true);
+
+// .indexOf()
+assertEq(tup.indexOf(1), 0);
+assertEq(tup.indexOf(2), 1);
+assertEq(tup.indexOf(3), 2);
+assertEq(empty.indexOf(1), -1);
+assertEq(empty.indexOf(0), -1);
+assertEq(empty.indexOf(0, 1), -1);
+assertEq(tup.indexOf(2, 1), 1);
+assertEq(tup.indexOf(2, 2), -1);
+assertEq(tup.indexOf(2, -1), -1);
+assertEq(tup.indexOf(2, -2), 1);
+assertEq(tup.indexOf(0, Infinity), -1);
+assertEq(tup.indexOf(2, -Infinity), 1);
+assertEq(tup.indexOf(2, undefined), 1);
+
+// .join()
+assertEq(tup.join(), "1,2,3");
+assertEq(tup.join("~"),"1~2~3");
+assertEq(#[1].join(), "1");
+assertEq(empty.join(), "");
+assertEq(#[1,2,undefined,3].join(), "1,2,,3");
+assertEq(#[1,null,2,3].join(), "1,,2,3");
+
+// .lastIndexOf()
+assertEq(tup.lastIndexOf(1), 0);
+assertEq(tup.lastIndexOf(2), 1);
+assertEq(tup.lastIndexOf(3), 2);
+assertEq(empty.lastIndexOf(1), -1);
+assertEq(empty.lastIndexOf(0), -1);
+assertEq(empty.lastIndexOf(0, 1), -1);
+assertEq(tup.lastIndexOf(2, 1), 1);
+assertEq(tup.lastIndexOf(2, 0), -1);
+assertEq(tup.lastIndexOf(2, -3), -1);
+assertEq(tup.lastIndexOf(2, -2), 1);
+assertEq(tup.lastIndexOf(2, -Infinity), -1);
+var duplicates = #[1,2,3,1,3,1,5,6,1,2,10];
+assertEq(duplicates.lastIndexOf(2), 9);
+assertEq(duplicates.lastIndexOf(3, 2), 2);
+assertEq(duplicates.lastIndexOf(3, -7), 4);
+assertEq(duplicates.lastIndexOf(1), 8);
+assertEq(duplicates.lastIndexOf(1, 0), 0);
+assertEq(duplicates.lastIndexOf(1, -5), 5);
+
+// .slice()
+var sliced = empty.slice(2);
+assertEq(empty, #[]);
+assertEq(empty, sliced);
+sliced = empty.slice(2, 3);
+assertEq(empty, sliced);
+sliced = tup.slice(1);
+assertEq(tup, tup2);
+assertEq(sliced, #[2,3]);
+sliced = tup.slice(3);
+assertEq(sliced, #[]);
+sliced = tup.slice(0, 0);
+assertEq(sliced, #[]);
+sliced = tup.slice(0, 1);
+assertEq(sliced, #[1]);
+sliced = tup.slice(0, 3);
+assertEq(sliced, tup);
+
+// .toString()
+assertEq(tup.toString(), "1,2,3");
+assertEq(empty.toString(), "");
+assertEq(#[1].toString(), "1");
+assertEq(myFish.toString(), "angel,clown,mandarin,sturgeon");
+
+// .toLocaleString() -- TODO more tests
+assertEq(tup.toString(), tup.toLocaleString());
+assertEq(empty.toString(), empty.toLocaleString());
+assertEq(myFish.toString(), myFish.toLocaleString());
+
+// .entries()
+var iterator = tup.entries();
+var result;
+result = iterator.next();
+assertEq(result.done, false);
+assertEq(result.value[0], 0);
+assertEq(result.value[1], 1);
+assertEq(result.value.length, 2);
+
+result = iterator.next();
+assertEq(result.done, false);
+assertEq(result.value[0], 1);
+assertEq(result.value[1], 2);
+assertEq(result.value.length, 2);
+
+result = iterator.next();
+assertEq(result.done, false);
+assertEq(result.value[0], 2);
+assertEq(result.value[1], 3);
+assertEq(result.value.length, 2);
+
+result = iterator.next();
+assertEq(result.done, true);
+assertEq(result.value, undefined);
+
+iterator = empty.entries();
+var result1 = iterator.next();
+assertEq(result1.done, true);
+assertEq(result1.value, undefined);
+
+// .every()
+var everyResult = tup.every(x => x < 10);
+assertEq(tup, tup2);
+assertEq(everyResult, true);
+everyResult = tup.every(x => x < 2);
+assertEq(everyResult, false);
+assertEq(true, empty.every(x => a > 100));
+
+assertThrowsInstanceOf(() => tup.every(),
+ TypeError,
+ "missing argument 0 when calling function Tuple.prototype.every");
+
+assertThrowsInstanceOf(() => tup.every("monkeys"),
+ TypeError,
+ "\"monkeys\" is not a function");
+
+// .filter()
+var filtered = tup.filter(x => x % 2 == 1);
+assertEq(tup, tup2);
+assertEq(filtered, #[1,3]);
+assertEq(#[].filter(x => x), #[]);
+
+assertThrowsInstanceOf(() => tup.filter(),
+ TypeError,
+ "missing argument 0 when calling function Tuple.prototype.filter");
+
+assertThrowsInstanceOf(() => tup.filter("monkeys"),
+ TypeError,
+ "\"monkeys\" is not a function");
+
+// .find()
+var findResult = tup.find(x => x > 2);
+assertEq(tup, tup2);
+assertEq(findResult, 3);
+assertEq(#[].find(x => true), undefined);
+
+assertThrowsInstanceOf(() => tup.find(),
+ TypeError,
+ "missing argument 0 when calling function Tuple.prototype.find");
+
+assertThrowsInstanceOf(() => tup.find("monkeys"),
+ TypeError,
+ "\"monkeys\" is not a function");
+
+// .findIndex()
+var findIndexResult = tup.findIndex(x => x > 2);
+assertEq(tup, tup2);
+assertEq(findIndexResult, 2);
+assertEq(#[].findIndex(x => true), -1);
+
+assertThrowsInstanceOf(() => tup.findIndex(),
+ TypeError,
+ "missing argument 0 when calling function Tuple.prototype.find");
+
+assertThrowsInstanceOf(() => tup.findIndex("monkeys"),
+ TypeError,
+ "\"monkeys\" is not a function");
+
+
+// .forEach()
+var a = 0;
+var forEachResult = tup.forEach(x => a += x);
+assertEq(tup, tup2);
+assertEq(forEachResult, undefined);
+assertEq(a, 6);
+
+assertEq(undefined, empty.forEach(x => a += x));
+assertEq(a, 6);
+
+assertThrowsInstanceOf(() => tup.forEach(),
+ TypeError,
+ "missing argument 0 when calling function Tuple.prototype.forEach");
+
+assertThrowsInstanceOf(() => tup.forEach("monkeys"),
+ TypeError,
+ "\"monkeys\" is not a function");
+
+// .keys()
+var iterator = tup.keys();
+var result;
+result = iterator.next();
+assertEq(result.done, false);
+assertEq(result.value, 0);
+
+result = iterator.next();
+assertEq(result.done, false);
+assertEq(result.value, 1);
+
+result = iterator.next();
+assertEq(result.done, false);
+assertEq(result.value, 2);
+
+result = iterator.next();
+assertEq(result.done, true);
+assertEq(result.value, undefined);
+
+iterator = empty.keys();
+var result1 = iterator.next();
+assertEq(result1.done, true);
+assertEq(result1.value, undefined);
+
+// .map()
+var mapResult = tup.map(x => x*x);
+assertEq(tup, tup2);
+assertEq(mapResult, #[1, 4, 9]);
+assertEq(empty, empty.map(x => x*x));
+
+assertThrowsInstanceOf(() => tup.map(x => new Object(x)),
+ TypeError,
+ "Record and Tuple can only contain primitive values");
+
+assertThrowsInstanceOf(() => tup.map("monkeys"),
+ TypeError,
+ "\"monkeys\" is not a function");
+
+// .reduce()
+var add = (previousValue, currentValue, currentIndex, O) =>
+ previousValue + currentValue;
+var reduceResult = tup.reduce(add);
+assertEq(tup, tup2);
+assertEq(reduceResult, 6);
+assertEq(tup.reduce(add, 42), 48);
+assertEq(0, empty.reduce(add, 0));
+
+assertThrowsInstanceOf(() => tup.reduce(),
+ TypeError,
+ "Tuple.prototype.reduce");
+
+assertThrowsInstanceOf(() => tup.reduce("monkeys"),
+ TypeError,
+ "\"monkeys\" is not a function");
+
+assertThrowsInstanceOf(() => empty.reduce(add),
+ TypeError,
+ "reduce of empty tuple with no initial value");
+
+// .reduceRight()
+var sub = (previousValue, currentValue, currentIndex, O) =>
+ previousValue - currentValue;
+var reduceResult = tup.reduceRight(sub);
+assertEq(tup, tup2);
+assertEq(reduceResult, 0);
+assertEq(tup.reduceRight(sub, 42), 36);
+assertEq(0, empty.reduceRight(sub, 0));
+
+assertThrowsInstanceOf(() => tup.reduceRight(),
+ TypeError,
+ "Tuple.prototype.reduceRight");
+
+assertThrowsInstanceOf(() => tup.reduceRight("monkeys"),
+ TypeError,
+ "\"monkeys\" is not a function");
+
+assertThrowsInstanceOf(() => empty.reduceRight(sub),
+ TypeError,
+ "reduce of empty tuple with no initial value");
+
+// .some()
+var truePred = x => x % 2 == 0;
+var falsePred = x => x > 30;
+var trueResult = tup.some(truePred);
+assertEq(tup, tup2);
+assertEq(trueResult, true);
+var falseResult = tup.some(falsePred);
+assertEq(falseResult, false);
+assertEq(false, empty.some(truePred));
+
+assertThrowsInstanceOf(() => tup.some(),
+ TypeError,
+ "Tuple.prototype.some");
+
+assertThrowsInstanceOf(() => tup.some("monkeys"),
+ TypeError,
+ "\"monkeys\" is not a function");
+
+// .values()
+var iterator = tup.values();
+var result;
+result = iterator.next();
+assertEq(result.done, false);
+assertEq(result.value, 1);
+
+result = iterator.next();
+assertEq(result.done, false);
+assertEq(result.value, 2);
+
+result = iterator.next();
+assertEq(result.done, false);
+assertEq(result.value, 3);
+
+result = iterator.next();
+assertEq(result.done, true);
+assertEq(result.value, undefined);
+
+iterator = empty.values();
+var result1 = iterator.next();
+assertEq(result1.done, true);
+assertEq(result1.value, undefined);
+
+// @@iterator
+
+var iterator = tup[Symbol.iterator](tup);
+var result;
+result = iterator.next();
+assertEq(result.done, false);
+assertEq(result.value, 1);
+
+result = iterator.next();
+assertEq(result.done, false);
+assertEq(result.value, 2);
+
+result = iterator.next();
+assertEq(result.done, false);
+assertEq(result.value, 3);
+
+result = iterator.next();
+assertEq(result.done, true);
+assertEq(result.value, undefined);
+
+iterator = empty[Symbol.iterator](empty);
+var result1 = iterator.next();
+assertEq(result1.done, true);
+assertEq(result1.value, undefined);
+
+// @@toStringTag
+
+assertEq(tup[Symbol.toStringTag], "Tuple");
+assertEq(Object(#[1,2,3])[Symbol.toStringTag], "Tuple");
+
+// length
+assertEq(tup.length, 3);
+assertEq(Object(#[1,2,3]).length, 3);
+assertEq(empty.length, 0);
+assertEq(Object(#[]).length, 0);
+
+// .flat()
+var toFlatten = #[#[1,2],#[3,#[4,5]],#[6],#[7,8,#[9,#[10,#[11,12]]]]];
+var toFlatten2 = #[#[1,2],#[3,#[4,5]],#[6],#[7,8,#[9,#[10,#[11,12]]]]];
+assertEq(toFlatten.flat(10), #[1,2,3,4,5,6,7,8,9,10,11,12]);
+assertEq(toFlatten, toFlatten2);
+assertEq(tup.flat(), tup);
+assertEq(empty.flat(), empty);
+assertEq(toFlatten.flat(2), #[1,2,3,4,5,6,7,8,9,#[10,#[11,12]]]);
+assertEq(toFlatten.flat(), #[1,2,3,#[4,5],6,7,8,#[9,#[10,#[11,12]]]]);
+
+// .flatMap()
+var inc = (x, sourceIndex, source) => #[x, x+1];
+var toFlatten0 = #[1, 2, 3];
+assertEq(toFlatten0.flatMap(inc), #[1, 2, 2, 3, 3, 4]);
+assertEq(empty.flatMap(inc), empty);
+
+// miscellaneous
+
+let nullaryMethods = [[Tuple.prototype.toReversed, x => x === #[1,2,3]],
+ [Tuple.prototype.toSorted, x => x === #[1,2,3]],
+ [Tuple.prototype.toString, x => x === "3,2,1"],
+ [Tuple.prototype.toLocaleString, x => x === "3,2,1"],
+ [Tuple.prototype.join, x => x === "3,2,1"],
+ [Tuple.prototype.entries, x => typeof(x) === "object"],
+ [Tuple.prototype.keys, x => typeof(x) === "object"],
+ [Tuple.prototype.values, x => typeof(x) === "object"],
+ [Tuple.prototype.flat, x => x === #[3,2,1]]];
+
+for (p of nullaryMethods) {
+ let method = p[0];
+ let f = p[1];
+ assertEq(f(method.call(Object(#[3,2,1]))), true);
+}
+
+function assertTypeError(f) {
+ for (thisVal of ["monkeys", [3,2,1], null, undefined, 0]) {
+ assertThrowsInstanceOf(f(thisVal), TypeError, "value of TupleObject must be a Tuple");
+ }
+}
+
+assertTypeError(x => (() => Tuple.prototype.toSorted.call(x)));
+
+assertEq(Tuple.prototype.toSpliced.call(Object(myFish), 2, 0, 'drum'),
+ #['angel', 'clown', 'drum', 'mandarin', 'sturgeon']);
+assertTypeError(thisVal => (() => Tuple.prototype.toSpliced.call(thisVal, 2, 0, 'drum')));
+
+assertEq(Tuple.prototype.concat.call(Object(#[1,2,3]), 1,2,3,4,5,6), #[1,2,3,1,2,3,4,5,6]);
+assertEq(Tuple.prototype.concat.call(Object(#[1,2,3]), 1,2,Object(#[3,4]),5,6), #[1,2,3,1,2,3,4,5,6]);
+assertTypeError(thisVal => (() => Tuple.prototype.concat.call(thisVal, 1, 2, 3, 4)));
+
+assertEq(Tuple.prototype.includes.call(Object(#[1,2,3]), 1), true);
+assertTypeError(thisVal => (() => Tuple.prototype.concat.includes(thisVal, 1)));
+
+assertEq(Tuple.prototype.indexOf.call(Object(#[1,2,3]), 1), 0);
+assertTypeError(thisVal => (() => Tuple.prototype.indexOf.call(thisVal, 0)));
+
+assertEq(Tuple.prototype.lastIndexOf.call(Object(#[1,2,3]), 1), 0);
+assertTypeError(thisVal => (() => Tuple.prototype.lastIndexOf.call(thisVal, 0)));
+
+assertEq(Tuple.prototype.slice.call(Object(#[1,2,3]), 1), #[2,3]);
+assertTypeError(thisVal => (() => Tuple.prototype.slice.call(thisVal, 0)));
+
+var pred = x => x > 2;
+
+assertEq(Tuple.prototype.every.call(Object(#[1,2,3]), pred), false);
+assertTypeError(thisVal => (() => Tuple.prototype.every.call(thisVal, pred)));
+
+assertEq(Tuple.prototype.filter.call(Object(#[1,2,3]), pred), #[3]);
+assertTypeError(thisVal => (() => Tuple.prototype.filter.call(thisVal, pred)));
+
+assertEq(Tuple.prototype.find.call(Object(#[1,2,3]), pred), 3);
+assertTypeError(thisVal => (() => Tuple.prototype.find.call(thisVal, pred)));
+
+assertEq(Tuple.prototype.findIndex.call(Object(#[1,2,3]), pred), 2);
+assertTypeError(thisVal => (() => Tuple.prototype.findIndex.call(thisVal, pred)));
+
+assertEq(Tuple.prototype.some.call(Object(#[1,2,3]), pred), true);
+assertTypeError(thisVal => (() => Tuple.prototype.some.call(thisVal, pred)));
+
+var a = 0;
+var f = (x => a += x);
+assertEq(Tuple.prototype.forEach.call(Object(#[1,2,3]), f), undefined);
+assertEq(a, 6);
+assertTypeError(thisVal => (() => Tuple.prototype.forEach.call(thisVal, f)));
+
+f = (x => x+1);
+assertEq(Tuple.prototype.map.call(Object(#[1,2,3]), f), #[2,3,4]);
+assertTypeError(thisVal => (() => Tuple.prototype.map.call(thisVal, f)));
+
+f = (x => #[x,x+1]);
+assertEq(Tuple.prototype.flatMap.call(Object(#[1,2,3]), f), #[1,2,2,3,3,4]);
+assertTypeError(thisVal => (() => Tuple.prototype.flatMap.call(thisVal, f)));
+
+assertEq(Tuple.prototype.reduce.call(Object(#[1,2,3]), add), 6);
+assertTypeError(thisVal => (() => Tuple.prototype.reduce.call(thisVal, add)));
+
+assertEq(Tuple.prototype.reduceRight.call(Object(#[1,2,3]), sub), 0);
+assertTypeError(thisVal => (() => Tuple.prototype.reduce.call(thisVal, sub)));
+
+if (typeof reportCompare === "function") reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/of/length.js b/js/src/tests/non262/Tuple/of/length.js
new file mode 100644
index 0000000000..5038d3fc5e
--- /dev/null
+++ b/js/src/tests/non262/Tuple/of/length.js
@@ -0,0 +1,20 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.of, "length");
+assertEq(desc.value, 0);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+desc = Object.getOwnPropertyDescriptor(Tuple.of, "name");
+assertEq(desc.value, "of");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.of), false);
+
+assertThrowsInstanceOf(() => {
+ new Tuple.of(1, 2, 3);
+}, TypeError, '`new Tuple.of(1, 2, 3)` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/of/name.js b/js/src/tests/non262/Tuple/of/name.js
new file mode 100644
index 0000000000..f09e793010
--- /dev/null
+++ b/js/src/tests/non262/Tuple/of/name.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var desc = Object.getOwnPropertyDescriptor(Tuple.of, "name");
+assertEq(desc.value, "of");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/of/not-a-constructor.js b/js/src/tests/non262/Tuple/of/not-a-constructor.js
new file mode 100644
index 0000000000..b397a820cd
--- /dev/null
+++ b/js/src/tests/non262/Tuple/of/not-a-constructor.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+assertEq(isConstructor(Tuple.of), false);
+
+assertThrowsInstanceOf(() => {
+ new Tuple.of(1, 2, 3);
+}, TypeError, '`new Tuple.of(1, 2, 3)` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/of/of.js b/js/src/tests/non262/Tuple/of/of.js
new file mode 100644
index 0000000000..bbda64608d
--- /dev/null
+++ b/js/src/tests/non262/Tuple/of/of.js
@@ -0,0 +1,29 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.2.3 Tuple.of ( ...items )
+The of method takes any number of arguments, and performs the following steps:
+
+1. Let items be the List of arguments passed to this function.
+2. For each element e of items,
+a. If Type(e) is Object, throw a TypeError exception.
+3. Let tuple be a new Tuple value whose [[Sequence]] is items.
+4. Return tuple.
+*/
+
+assertEq(Tuple.of(), #[]);
+assertEq(Tuple.of(undefined), #[undefined]);
+assertEq(Tuple.of(null), #[null]);
+assertEq(Tuple.of(1), #[1]);
+assertEq(Tuple.of(1, 2), #[1,2]);
+assertEq(Tuple.of(true, 5, "monkeys", #[3, 4]), #[true, 5, "monkeys", #[3, 4]]);
+assertEq(Tuple.of(undefined, false, null, undefined), #[undefined, false, null, undefined]);
+
+/* Step 2a. */
+assertThrowsInstanceOf(() => Tuple.of([1, 2, 3]), TypeError,
+ "Tuple can't contain Object");
+assertThrowsInstanceOf(() => Tuple.of([]), TypeError,
+ "Tuple can't contain Object");
+assertThrowsInstanceOf(() => Tuple.of(new Object(), [1, 2, 3], new String("a")), TypeError,
+ "Tuple can't contain Object");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/of/prop-desc.js b/js/src/tests/non262/Tuple/of/prop-desc.js
new file mode 100644
index 0000000000..e797646531
--- /dev/null
+++ b/js/src/tests/non262/Tuple/of/prop-desc.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var desc = Object.getOwnPropertyDescriptor(Tuple, "of");
+assertEq(desc.value, Tuple.of);
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/property-descriptors.js b/js/src/tests/non262/Tuple/property-descriptors.js
new file mode 100644
index 0000000000..0e21ad8b97
--- /dev/null
+++ b/js/src/tests/non262/Tuple/property-descriptors.js
@@ -0,0 +1,91 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var tup = Tuple(1, 2, 3);
+var tupO = Object(tup);
+
+var desc = Object.getOwnPropertyDescriptor(tupO, "0");
+assertEq(desc.value, 1);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, true);
+assertEq(desc.configurable, false);
+
+assertEq(Object.getOwnPropertyDescriptor(tupO, "3"), undefined);
+assertEq(Object.getOwnPropertyDescriptor(tupO, "w"), undefined);
+assertEq(Object.getOwnPropertyDescriptor(tupO, "length"), undefined);
+
+assertThrowsInstanceOf(
+ () => Object.defineProperty(tup, "0", { value: 1 }),
+ TypeError,
+ "#[1, 2, 3] is not a non-null object"
+);
+
+assertThrowsInstanceOf(
+ () => Object.defineProperty(tupO, "b", {}),
+ TypeError,
+ 'can\'t define property "b": tuple is not extensible'
+);
+
+assertThrowsInstanceOf(
+ () => Object.defineProperty(tupO, "3", {}),
+ TypeError,
+ 'can\'t define property "3": tuple is not extensible'
+);
+
+assertThrowsInstanceOf(
+ () => Object.defineProperty(tupO, Symbol(), {}),
+ TypeError,
+ 'can\'t define property "Symbol()": tuple is not extensible'
+);
+
+assertThrowsInstanceOf(
+ () => Object.defineProperty(tupO, "0", { value: 2 }),
+ TypeError,
+ '"0" is read-only'
+);
+
+Object.defineProperty(tupO, "0", { value: 1 });
+
+assertThrowsInstanceOf(
+ () => Object.defineProperty(tupO, "0", { value: 1, writable: true }),
+ TypeError,
+ "Invalid tuple property descriptor"
+);
+
+assertThrowsInstanceOf(
+ () => Object.defineProperty(tupO, "0", { value: 1, enumerable: false }),
+ TypeError,
+ "Invalid tuple property descriptor"
+);
+
+assertThrowsInstanceOf(
+ () => Object.defineProperty(tupO, "0", { value: 1, configurable: true }),
+ TypeError,
+ "Invalid tuple property descriptor"
+);
+
+assertEq(Object.prototype.propertyIsEnumerable.call(tupO, "0"), true);
+assertEq(Object.prototype.propertyIsEnumerable.call(tupO, "0"), true);
+assertEq(Object.prototype.propertyIsEnumerable.call(tupO, "w"), false);
+assertEq(Object.prototype.propertyIsEnumerable.call(tupO, "w"), false);
+assertEq(Object.prototype.propertyIsEnumerable.call(tupO, "3"), false);
+assertEq(Object.prototype.propertyIsEnumerable.call(tupO, "3"), false);
+
+assertEq(Object.prototype.hasOwnProperty.call(tupO, "0"), true);
+assertEq(Object.prototype.hasOwnProperty.call(tupO, "0"), true);
+assertEq(Object.prototype.hasOwnProperty.call(tupO, "w"), false);
+assertEq(Object.prototype.hasOwnProperty.call(tupO, "w"), false);
+assertEq(Object.prototype.hasOwnProperty.call(tupO, "3"), false);
+assertEq(Object.prototype.hasOwnProperty.call(tupO, "3"), false);
+
+assertEq("0" in tupO, true);
+assertEq("w" in tupO, false);
+assertEq("3" in tupO, false);
+
+assertEq(delete tupO[0], false);
+assertEq(delete tupO[0], false);
+assertEq(delete tupO.w, true);
+assertEq(delete tupO.w, true);
+assertEq(delete tupO[3], true);
+assertEq(delete tupO[3], true);
+
+if (typeof reportCompare === "function") reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/proto-override.js b/js/src/tests/non262/Tuple/proto-override.js
new file mode 100644
index 0000000000..4e0ac54a93
--- /dev/null
+++ b/js/src/tests/non262/Tuple/proto-override.js
@@ -0,0 +1,13 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+//CHECK#1
+Tuple.prototype.toString = Object.prototype.toString;
+var x = Tuple();
+assertEq(x.toString(), "[object Tuple]");
+
+//CHECK#2
+Tuple.prototype.toString = Object.prototype.toString;
+var x = Tuple(0, 1, 2);
+assertEq(x.toString(), "[object Tuple]");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/invoked-as-accessor.js b/js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/invoked-as-accessor.js
new file mode 100644
index 0000000000..809a8a41bf
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/invoked-as-accessor.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+// 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-get-%Tuple%.prototype-@@tostringtag
+description: >
+info: |
+ 8.2.3.4 %Tuple%.prototype [ @@toStringTag ]
+
+The initial value of Tuple.prototype[@@toStringTag] is the String value "Tuple".
+
+This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
+
+features: [Symbol.toStringTag, Tuple]
+---*/
+
+var TuplePrototype = Tuple.prototype;
+
+assertEq(TuplePrototype[Symbol.toStringTag], "Tuple");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/length.js b/js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/length.js
new file mode 100644
index 0000000000..ad82466f1f
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/length.js
@@ -0,0 +1,11 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype, Symbol.toStringTag);
+
+assertEq(desc.length, undefined);
+
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/name.js b/js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/name.js
new file mode 100644
index 0000000000..cc7c101cd7
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/name.js
@@ -0,0 +1,7 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype, Symbol.toStringTag);
+
+assertEq(desc.name, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/prop-desc.js b/js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/prop-desc.js
new file mode 100644
index 0000000000..43e5c73d35
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/prop-desc.js
@@ -0,0 +1,31 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+// 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-get-%Tuple%.prototype-@@tostringtag
+description: >
+info: |
+ 8.2.3.4 %Tuple%.prototype [ @@toStringTag ]
+
+The initial value of Tuple.prototype[@@toStringTag] is the String value "Tuple".
+
+This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
+
+features: [Symbol.toStringTag, Tuple]
+---*/
+
+var TuplePrototype = Tuple.prototype;
+var desc = Object.getOwnPropertyDescriptor(
+ TuplePrototype, Symbol.toStringTag
+);
+
+assertEq(desc.value, "Tuple");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(desc.set, undefined);
+assertEq(desc.get, undefined);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/concat/concat-with-array.js b/js/src/tests/non262/Tuple/prototype/concat/concat-with-array.js
new file mode 100644
index 0000000000..938f4838cf
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/concat/concat-with-array.js
@@ -0,0 +1,7 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+assertDeepEq([1, 2].concat(#[3, 4]), [1, 2, 3, 4]);
+assertDeepEq([].concat(#[3, 4]), [3, 4]);
+assertDeepEq([].concat(#[]), []);
+assertDeepEq([1, 2, 3].concat(#[]), [1, 2, 3]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/concat/concat.js b/js/src/tests/non262/Tuple/prototype/concat/concat.js
new file mode 100644
index 0000000000..92270db7e9
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/concat/concat.js
@@ -0,0 +1,104 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.6 Tuple.prototype.concat ( ...args )
+
+When the concat method is called with zero or more arguments, it returns a Tuple containing the elements of the Tuple followed by the elements of each argument in order.
+
+The following steps are taken:
+
+1. Let T be ? thisTupleValue(this value).
+2. Let list be a new empty List.
+3. Let n be 0.
+4. Let items be a List whose first element is T and whose subsequent element are, in left to right order, the arguments that were passed to this function invocation.
+5. Repeat, while items is not empty,
+a. Remove the first element from items and let E be the value of the element.
+b. Let spreadable be ? IsConcatSpreadable(E).
+c. If spreadable is true, then
+i. Let k be 0.
+ii. Let len be ? LengthOfArrayLike(E).
+iii. If n + len > 253 - 1, throw a TypeError exception.
+iv. Repeat, while k < len,
+1. Let P be ! ToString(k).
+2. Let exists be ? HasProperty(E, P).
+3. If exists is true, then
+a. Let subElement be ? Get(E, P).
+b. If Type(subElement) is Object, throw a TypeError exception.
+c. Append subElement to the end of list list.
+4. Set n to n + 1.
+5. Set k to k + 1.
+d. Else,
+i. NOTE: E is added as a single item rather than spread.
+ii. If n ≥ 253 - 1, throw a TypeError exception.
+iii. If Type(E) is Object, throw a TypeError exception.
+iv. Append E to the end of list list.
+v. Set n to n + 1.
+6. Return a new Tuple value whose [[Sequence]] is list.
+*/
+
+/* Step 1 */
+/* concat() should throw on a non-Tuple */
+let method = Tuple.prototype.concat;
+assertEq(method.call(#[1,2,3,4,5,6], #[1],#[2,3]), #[1,2,3,4,5,6,1,2,3]);
+assertEq(method.call(Object(#[1,2,3,4,5,6]), #[1],#[2,3]), method.call(#[1,2,3,4,5,6],#[1],#[2,3]));
+assertThrowsInstanceOf(() => method.call("monkeys"), TypeError,
+ "value of TupleObject must be a Tuple");
+
+/* Step 5 */
+/* No arguments or empty arguments => returns this */
+let tup = #[1,2,3];
+assertEq(tup.concat(), tup);
+assertEq(tup.concat(#[]), tup);
+assertEq(tup.concat([]), tup);
+assertEq(tup.concat(#[],#[],#[]), tup);
+
+/* Step 5 */
+/* 1 spreadable argument */
+assertEq(tup.concat(tup), #[1,2,3,1,2,3]);
+assertEq(tup.concat([1,2,3]), #[1,2,3,1,2,3]);
+
+/* spreadable followed by non-spreadable */
+assertEq(tup.concat(tup, "monkeys"), #[1,2,3,1,2,3, "monkeys"]);
+assertEq(tup.concat([1,2,3], "monkeys"), #[1,2,3,1,2,3, "monkeys"]);
+
+/* non-spreadable followed by spreadable */
+assertEq(tup.concat("monkeys", tup), #[1,2,3, "monkeys", 1,2,3]);
+assertEq(tup.concat("monkeys", [1,2,3]), #[1,2,3, "monkeys", 1,2,3,]);
+
+/* Step 5.c.iii.
+ If n + len > 2^53 - 1, throw a TypeError */
+var spreadableLengthOutOfRange = {};
+spreadableLengthOutOfRange.length = Number.MAX_SAFE_INTEGER;
+spreadableLengthOutOfRange[Symbol.isConcatSpreadable] = true;
+/*
+TODO
+this.length = (2^53/2)
+this.concat(a) throws if a.length = 2^53/2 - 1
+*/
+
+
+assertThrowsInstanceOf(() => tup.concat(spreadableLengthOutOfRange),
+ TypeError,
+ 'Too long array');
+
+/* Step 5.c.iv.2. Let exists be ?HasProperty(E, P)
+ Step 5.c.iv.3 Append only if exists is true */
+assertEq(tup.concat([42,17,,5,,12]), #[1,2,3,42,17,5,12]);
+
+/* Step 5.c.iv.3.b. -- Object elements should throw */
+assertThrowsInstanceOf(() => tup.concat([1, new Object(), 2]),
+ TypeError,
+ '#[1,2,3].concat([1, new Object(), 2]) throws a TypeError exception');
+
+/* Step 5d -- add as a single item */
+assertEq(tup.concat("monkeys"), #[1,2,3, "monkeys"]);
+/*
+Step 5d.c.ii.
+- Throw if this has length 2^53
+TODO: not sure how to test this -- creating a tuple with length 2^53 takes too long
+*/
+
+/* Step 5d.iii -- Object should throw */
+assertThrowsInstanceOf(() => tup.concat(new Object()), TypeError,
+ '#[1,2,3].concat(new Object()) throws a TypeError exception');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/concat/indexed-setters.js b/js/src/tests/non262/Tuple/prototype/concat/indexed-setters.js
new file mode 100644
index 0000000000..da6840927c
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/concat/indexed-setters.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+// If an indexed Array setter is overridden, TupleConcat shouldn't use it
+// when constructing the intermediate array
+
+var z = 5;
+for (i = 0; i < 4; i++) {
+ Object.defineProperty(Array.prototype, i, { set: function(y) { z = 42; }});
+}
+var newT = #[1, 2].concat([3, 4]);
+assertEq(z, 5);
+
+newT = #[1, 2].concat("hello");
+assertEq(z, 5);
+
+reportCompare(0, 0);
+
diff --git a/js/src/tests/non262/Tuple/prototype/concat/length.js b/js/src/tests/non262/Tuple/prototype/concat/length.js
new file mode 100644
index 0000000000..6b801f8783
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/concat/length.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype.concat, "length");
+assertEq(desc.value, 0);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype.concat, "name");
+assertEq(desc.value, "concat");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype, "concat");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.prototype.concat), false);
+
+assertThrowsInstanceOf(() => {
+ let t = #[1];
+ new t.concat();
+}, TypeError, '`let t = #[1]; new t.concat()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/filter/filter.js b/js/src/tests/non262/Tuple/prototype/filter/filter.js
new file mode 100644
index 0000000000..d51c982868
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/filter/filter.js
@@ -0,0 +1,82 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.13 Tuple.prototype.filter ( callbackfn [ , thisArg ] )
+NOTE
+callbackfn should be a function that accepts three arguments and returns a value that is coercible to the Boolean value true or false. filter calls callbackfn once for each element in the tuple, in ascending order, and constructs a new tuple of all the values for which callbackfn returns true.
+
+If a thisArg parameter is provided, it will be used as the this value for each invocation of callbackfn. If it is not provided, undefined is used instead.
+
+callbackfn is called with three arguments: the value of the element, the index of the element, and the Tuple being traversed.
+
+When the filter method is called with one or two arguments, the following steps are taken:
+
+1. Let T be ? thisTupleValue(this value).
+2. Let list be T.[[Sequence]].
+3. Let len be the number of elements in list.
+4. If IsCallable(callbackfn) is false, throw a TypeError exception.
+5. Let newList be a new empty List.
+6. Let k be 0.
+7. Repeat, while k < len,
+a. Let kValue be list[k].
+b. Let selected be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, k, T »)).
+c. If selected is true, then
+i. Append kValue to the end of list newList.
+d. Set k to k + 1.
+8. Return a new Tuple value whose [[Sequence]] is newLis.t
+
+*/
+
+/* Step 1 */
+/* filter() should throw on a non-Tuple */
+let method = Tuple.prototype.filter;
+let pred = (x, i, tup) => x % 2 === 0;
+assertEq(method.call(#[1,2,3,4,5,6],pred), #[2,4,6]);
+assertEq(method.call(Object(#[1,2,3,4,5,6]), pred), #[2,4,6]);
+assertThrowsInstanceOf(() => method.call("monkeys", pred), TypeError,
+ "value of TupleObject must be a Tuple");
+
+let tup = #[1,2,3];
+
+/* Step 4 */
+/* callbackfn not callable -- should throw */
+assertThrowsInstanceOf(() => tup.filter(), TypeError,
+ "missing function argument to Tuple.prototype.filter");
+assertThrowsInstanceOf(() => tup.filter(undefined), TypeError,
+ "missing function argument to Tuple.prototype.filter");
+assertThrowsInstanceOf(() => tup.filter("monkeys"), TypeError,
+ "bad function argument to Tuple.prototype.filter");
+
+
+/* callbackfn with 1 argument -- should be allowed */
+var pred2 = x => x % 2 === 0;
+assertEq(tup.filter(pred2), #[2]);
+
+/* callbackfn with 2 arguments -- should be allowed */
+pred2 = (x, i) => x + i < 5;
+assertEq(tup.filter(pred2), #[1, 2]);
+
+/* callbackfn with > 3 arguments -- subsequent ones will be undefined */
+var pred3 = (a, b, c, d, e) => e === undefined;
+assertEq(tup.filter(pred3), tup);
+
+/* callbackfn should be able to use index and tuple */
+var pred1 = (x, i, tup) => (tup.indexOf(x + i) !== (-1));
+assertEq(#[1,2,3,4,5,6,7].filter(pred1), #[1,2,3,4]);
+
+/* explicit thisArg */
+pred1 = function (x, i, tup) { return(this.elements.indexOf(x) !== -1); };
+assertEq(#[1,2,3,4,5].filter(pred1, { elements: [2, 4] }), #[2,4]);
+
+/* Step 3 */
+/* Test that length is still handled correctly if it's overridden */
+Object.defineProperty(Tuple.prototype, "length", { get() { return 0 } })
+assertEq(tup.filter(pred), #[2]);
+
+/* Step 7 */
+assertEq(#[].filter(pred), #[]);
+assertEq(#[1].filter(pred), #[]);
+assertEq(#[2].filter(pred), #[2]);
+assertEq(tup.filter(pred), #[2]);
+assertEq(tup.filter(x => x > 1), #[2,3]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/filter/indexed-setters.js b/js/src/tests/non262/Tuple/prototype/filter/indexed-setters.js
new file mode 100644
index 0000000000..a110b460e1
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/filter/indexed-setters.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+// If an indexed Array setter is overridden, TupleSplice shouldn't use it
+// when constructing the intermediate array
+
+var z = 5;
+print("1111");
+Object.defineProperty(Array.prototype, '0', { set: function(y) { z = 42; }});
+print("2222");
+let newT = #[1,2,3].filter(x => true);
+print("3333");
+assertEq(z, 5);
+print("4444");
+
+reportCompare(0, 0);
+
diff --git a/js/src/tests/non262/Tuple/prototype/filter/length.js b/js/src/tests/non262/Tuple/prototype/filter/length.js
new file mode 100644
index 0000000000..a780c2b2b1
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/filter/length.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype.filter, "length");
+assertEq(desc.value, 1);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype.filter, "name");
+assertEq(desc.value, "filter");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype, "filter");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.prototype.filter), false);
+
+assertThrowsInstanceOf(() => {
+ let t = #[1];
+ new t.filter();
+}, TypeError, '`let t = #[1]; new t.filter()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/flat/empty-tuple-elements.js b/js/src/tests/non262/Tuple/prototype/flat/empty-tuple-elements.js
new file mode 100644
index 0000000000..e8acef7b43
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/flat/empty-tuple-elements.js
@@ -0,0 +1,8 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var t = #[];
+assertEq(#[].flat(), #[]);
+assertEq(#[#[],#[]].flat(), #[]);
+assertEq(#[#[], #[1]].flat(), #[1]);
+assertEq(#[#[], #[1, t]].flat(), #[1, t]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/flat/flat.js b/js/src/tests/non262/Tuple/prototype/flat/flat.js
new file mode 100644
index 0000000000..93748f9c36
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/flat/flat.js
@@ -0,0 +1,96 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.16 Tuple.prototype.flat ( [ depth ] )
+When the flat method is called with zero or one arguments, the following steps are taken:
+
+1. Let T be ? thisTupleValue(this value).
+2. Let list be T.[[Sequence]].
+3. Let depthNum be 1.
+4. If depth is not undefined, then
+a. Set depthNum to ? ToInteger(depth).
+5. Let flat be a new empty List.
+6. Perform ? FlattenIntoTuple(flat, list, depthNum).
+7. Return a new Tuple value whose [[Sequence]] is flat.
+
+8.2.3.16.1 FlattenIntoTuple ( target, source, depth [ , mapperFunction, thisArg ] )
+The abstract operation FlattenIntoTuple takes arguments target, source, and depth and optional arguments mapperFunction and thisArg. It performs the following steps when called:
+
+1. Assert: target is a List.
+2. Assert: source is a List.
+3. Assert: ! IsInteger(depth) is true, or depth is either +∞ or -∞.
+4. Assert: If mapperFunction is present, then ! IsCallable(mapperFunction) is true, thisArg is present, and depth is 1.
+5. Let sourceIndex be 0.
+6. For each element of source,
+a. If mapperFunction is present, then
+i. Set element to ? Call(mapperFunction, thisArg, « element, sourceIndex, source »).
+ii. If Type(element) is Object, throw a TypeError exception.
+b. If depth > 0 and Type(element) is Tuple, then
+i. Perform ? FlattenIntoTuple(target, element, depth - 1).
+c. Else,
+i. Let len be the length of target.
+ii. If len ≥ 253 - 1, throw a TypeError exception.
+iii. Append element to target.
+d. Set sourceIndex to sourceIndex + 1.
+
+*/
+/* Step 1 */
+/* flat() should throw on a non-Tuple */
+let method = Tuple.prototype.flat;
+assertEq(method.call(#[1,#[2],3]), #[1,2,3]);
+assertEq(method.call(Object(#[1,#[2],3])), #[1,2,3]);
+assertThrowsInstanceOf(() => method.call("monkeys"), TypeError,
+ "value of TupleObject must be a Tuple");
+assertThrowsInstanceOf(() => method.call(null), TypeError,
+ "value of TupleObject must be a Tuple");
+assertThrowsInstanceOf(() => method.call(), TypeError,
+ "value of TupleObject must be a Tuple");
+
+
+let tup = #[1,2,#[3,#[4,5],6],#[5,6],7];
+let tup2 = #[1,2,#[3,#[4,#["a", "b"], 5],6],#[5,#[6,#[7,8,#[9,10]]]],7];
+
+/* Step 3 -- depth is converted to Integer */
+assertEq(tup.flat("monkeys"), tup.flat(0));
+assertEq(tup.flat({}), tup.flat(0));
+assertEq(tup.flat(+0), tup.flat(0));
+assertEq(tup.flat(-0), tup.flat(0));
+assertEq(tup.flat('2'), tup.flat(2));
+assertEq(tup.flat(true), tup.flat(1));
+assertEq(tup.flat(false), tup.flat(0));
+assertEq(tup.flat(null), tup.flat(0));
+assertEq(tup.flat(NaN), tup.flat(0));
+assertEq(tup.flat([1,2,3]), tup.flat(0));
+assertThrowsInstanceOf(() => tup.flat(Symbol("x")), TypeError,
+ "can't convert symbol to number");
+assertThrowsInstanceOf(() => tup.flat(Object.create(null)), TypeError,
+ "can't convert Object to number");
+assertThrowsInstanceOf(() => tup.flat(#[1]), TypeError,
+ "can't convert Tuple to number");
+
+
+/* Step 3 -- if depth is undefined, depthNum is set to 1 */
+assertEq(tup.flat(undefined), tup.flat(1));
+assertEq(tup.flat(), tup.flat(1));
+
+/* Step 7 */
+assertEq(#[].flat(), #[]);
+assertEq(#[1].flat(), #[1]);
+assertEq(#[#[1,2],#[3,4]].flat(), #[1,2,3,4]);
+assertEq(tup.flat(0), tup);
+assertEq(tup.flat(1), #[1,2,3,#[4,5],6,5,6,7]);
+assertEq(tup.flat(2), #[1,2,3,4,5,6,5,6,7]);
+assertEq(tup.flat(3), tup.flat(2));
+assertEq(tup2.flat(0), tup2);
+assertEq(tup2.flat(1), #[1,2,3,#[4,#["a", "b"], 5],6,5,#[6,#[7,8,#[9,10]]],7]);
+assertEq(tup2.flat(2), #[1,2,3,4,#["a", "b"],5,6,5,6,#[7, 8, #[9, 10]],7]);
+assertEq(tup2.flat(3), #[1,2,3,4,"a","b",5,6,5,6, 7, 8, #[9, 10], 7]);
+assertEq(tup2.flat(4), #[1,2,3,4,"a","b",5,6,5,6, 7, 8, 9, 10, 7]);
+
+/* FlattenIntoTuple steps: */
+/* Step 3: depth can be Infinity or -Infinity */
+assertEq(tup2.flat(Infinity), tup2.flat(4));
+assertEq(tup2.flat(-Infinity), tup2.flat(0));
+
+/* Step 6.c.ii. -- throw if len would be > n^253 - 1 -- not sure how to test this */
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/flat/indexed-setters.js b/js/src/tests/non262/Tuple/prototype/flat/indexed-setters.js
new file mode 100644
index 0000000000..26b77e03fd
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/flat/indexed-setters.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+// If an indexed Array setter is overridden, TupleSplice shouldn't use it
+// when constructing the intermediate array
+
+var z = 5;
+print("1111");
+Object.defineProperty(Array.prototype, '0', { set: function(y) { z = 42; }});
+print("2222");
+let newT = #[#[1],#[2,3]].flat();
+print("3333");
+assertEq(z, 5);
+print("4444");
+
+reportCompare(0, 0);
+
diff --git a/js/src/tests/non262/Tuple/prototype/flat/length.js b/js/src/tests/non262/Tuple/prototype/flat/length.js
new file mode 100644
index 0000000000..8bbbea0ae9
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/flat/length.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype.flat, "length");
+assertEq(desc.value, 0);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype.flat, "name");
+assertEq(desc.value, "flat");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype, "flat");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.prototype.flat), false);
+
+assertThrowsInstanceOf(() => {
+ let t = #[1];
+ new t.flat();
+}, TypeError, '`let t = #[1]; new t.flat()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/flat/undefined-elements.js b/js/src/tests/non262/Tuple/prototype/flat/undefined-elements.js
new file mode 100644
index 0000000000..4a705167f5
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/flat/undefined-elements.js
@@ -0,0 +1,10 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var t = #[void 0];
+
+assertEq(#[1, null, void 0].flat(), #[1, null, undefined]);
+assertEq(#[1, #[null, void 0]].flat(), #[1, null, undefined]);
+assertEq(#[#[null, void 0], #[null, void 0]].flat(), #[null, undefined, null, undefined]);
+assertEq(#[1, #[null, t]].flat(1), #[1, null, t]);
+assertEq(#[1, #[null, t]].flat(2), #[1, null, undefined]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/flatMap/depth-always-one.js b/js/src/tests/non262/Tuple/prototype/flatMap/depth-always-one.js
new file mode 100644
index 0000000000..2f3aed6e32
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/flatMap/depth-always-one.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+assertEq(#[1, 2].flatMap(function(e) {
+ return #[e, e * 2];
+}), #[1, 2, 2, 4]);
+
+var result = #[1, 2, 3].flatMap(function(ele) {
+ return #[
+ #[ele * 2]
+ ];
+});
+assertEq(result.length, 3);
+assertEq(result[0], #[2]);
+assertEq(result[1] ,#[4]);
+assertEq(result[2], #[6]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/flatMap/flatMap.js b/js/src/tests/non262/Tuple/prototype/flatMap/flatMap.js
new file mode 100644
index 0000000000..0fde7014a8
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/flatMap/flatMap.js
@@ -0,0 +1,114 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.17 Tuple.prototype.flatMap ( mapperFunction [ , thisArg ] )
+When the flatMap method is called with one or two arguments, the following steps are taken:
+
+1. Let T be ? thisTupleValue(this value).
+2. Let list be T.[[Sequence]].
+3. If ! IsCallable(mapperFunction) is false, throw a TypeError exception.
+4. Let flat be a new empty List.
+5. Perform ? FlattenIntoTuple(flat, list, 1, mapperFunction, thisArg).
+6. Return a new Tuple value whose [[Sequence]] is flat.
+
+8.2.3.16.1 FlattenIntoTuple ( target, source, depth [ , mapperFunction, thisArg ] )
+The abstract operation FlattenIntoTuple takes arguments target, source, and depth and optional arguments mapperFunction and thisArg. It performs the following steps when called:
+
+1. Assert: target is a List.
+2. Assert: source is a List.
+3. Assert: ! IsInteger(depth) is true, or depth is either +∞ or -∞.
+4. Assert: If mapperFunction is present, then ! IsCallable(mapperFunction) is true, thisArg is present, and depth is 1.
+5. Let sourceIndex be 0.
+6. For each element of source,
+a. If mapperFunction is present, then
+i. Set element to ? Call(mapperFunction, thisArg, « element, sourceIndex, source »).
+ii. If Type(element) is Object, throw a TypeError exception.
+b. If depth > 0 and Type(element) is Tuple, then
+i. Perform ? FlattenIntoTuple(target, element, depth - 1).
+c. Else,
+i. Let len be the length of target.
+ii. If len ≥ 253 - 1, throw a TypeError exception.
+iii. Append element to target.
+d. Set sourceIndex to sourceIndex + 1.
+ */
+
+/* Step 1 */
+/* flatMap() should throw on a non-Tuple */
+let method = Tuple.prototype.flatMap;
+let id = x => x;
+assertEq(method.call(#[1,#[2],3], id), #[1,2,3]);
+assertEq(method.call(Object(#[1,#[2],3]), id), #[1,2,3]);
+assertThrowsInstanceOf(() => method.call("monkeys", id), TypeError,
+ "value of TupleObject must be a Tuple");
+assertThrowsInstanceOf(() => method.call(null, id), TypeError,
+ "value of TupleObject must be a Tuple");
+assertThrowsInstanceOf(() => method.call(id), TypeError,
+ "value of TupleObject must be a Tuple");
+
+
+let tup = #[1,2,#[3,#[4,5],6],#[5,6],7];
+let tup2 = #[1, #[2], 3];
+
+/* Step 4 */
+/* callbackfn not callable -- should throw */
+assertThrowsInstanceOf(() => tup.flatMap(), TypeError,
+ "missing function argument to Tuple.prototype.flatMap");
+assertThrowsInstanceOf(() => tup.flatMap(undefined), TypeError,
+ "missing function argument to Tuple.prototype.flatMap");
+assertThrowsInstanceOf(() => tup.flatMap("monkeys"), TypeError,
+ "bad function argument to Tuple.prototype.flatMap");
+
+
+/* callbackfn with 1 argument -- should be allowed */
+var f2 = function(x) {
+ if (typeof(x) === "number") {
+ return(x * x);
+ } else {
+ return 0;
+ }
+};
+assertEq(tup2.flatMap(f2), #[1, 0, 9]);
+
+/* callbackfn with 2 arguments -- should be allowed */
+f2 = function(x, i) {
+ if (typeof(x) === "number") {
+ return(x + i);
+ } else {
+ return(i);
+ }
+};
+assertEq(tup2.flatMap(f2), #[1, 1, 5]);
+
+/* callbackfn with > 3 arguments -- subsequent ones will be undefined */
+var f3 = (a, b, c, d, e) => e === undefined;
+assertEq(tup2.flatMap(f3), #[true, true, true]);
+
+/* callbackfn should be able to use index and tuple */
+var f4 = function (x, i, tup) {
+ if (typeof(x) === "number") {
+ return(tup.indexOf(x+1) * i * x);
+ } else {
+ return(tup.indexOf(x) * i);
+ }
+}
+assertEq(tup2.flatMap(f4), #[-0, 1, -6]);
+
+/* explicit thisArg */
+f1 = function (x, i, tup) {
+ if (typeof(x) == "number") {
+ return(this.elements.indexOf(x) * x);
+ } else {
+ return(this.elements.indexOf(x));
+ }
+}
+assertEq(#[1,2,#[3,4],#[5]].flatMap(f1, { elements: [2, 4] }), #[-1, 0, -1, -1]);
+
+/* FlattenIntoTuple steps */
+/* Step 6.a.ii. */
+var badF = x => new Object(x);
+assertThrowsInstanceOf(() => tup.flatMap(badF), TypeError,
+ "Tuple cannot contain Object");
+/* Step 6.b.i. */
+var f = x => #[x, x];
+assertEq(#[1,#[2,3],4].flatMap(f), #[1,1,#[2,3],#[2,3],4,4]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/flatMap/length.js b/js/src/tests/non262/Tuple/prototype/flatMap/length.js
new file mode 100644
index 0000000000..4e6f5eb0ab
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/flatMap/length.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype.flatMap, "length");
+assertEq(desc.value, 1);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype.flatMap, "name");
+assertEq(desc.value, "flatMap");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype, "flatMap");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.prototype.flatMap), false);
+
+assertThrowsInstanceOf(() => {
+ let t = #[1];
+ new t.flatMap();
+}, TypeError, '`let t = #[1]; new t.flatMap()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/fromIndex-equal-or-greater-length-returns-false.js b/js/src/tests/non262/Tuple/prototype/includes/fromIndex-equal-or-greater-length-returns-false.js
new file mode 100644
index 0000000000..6108e38cbc
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/fromIndex-equal-or-greater-length-returns-false.js
@@ -0,0 +1,13 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Return false if fromIndex >= TupleLength
+---*/
+
+var sample = #[7, 7, 7, 7];
+assertEq(sample.includes(7, 4), false, "length");
+assertEq(sample.includes(7, 5), false, "length + 1");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/fromIndex-infinity.js b/js/src/tests/non262/Tuple/prototype/includes/fromIndex-infinity.js
new file mode 100644
index 0000000000..3ed0c3b43c
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/fromIndex-infinity.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// 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-array.prototype.includes
+description: handle Infinity values for fromIndex
+---*/
+
+var sample = #[42, 43, 43, 41];
+
+assertEq(
+ sample.includes(43, Infinity),
+ false,
+ "includes(43, Infinity)"
+);
+assertEq(
+ sample.includes(43, -Infinity),
+ true,
+ "includes(43, -Infinity)"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/fromIndex-minus-zero.js b/js/src/tests/non262/Tuple/prototype/includes/fromIndex-minus-zero.js
new file mode 100644
index 0000000000..23ebaf8346
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/fromIndex-minus-zero.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// 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-array.prototype.includes
+description: -0 fromIndex becomes 0
+info: |
+ 22.1.3.11 Array.prototype.includes ( searchElement [ , fromIndex ] )
+
+ ...
+ 5. If n ≥ 0, then
+ a. Let k be n.
+ ...
+ 7. Repeat, while k < len
+ ...
+---*/
+
+var sample = [42, 43];
+assertEq(sample.includes(42, -0), true, "-0 [0]");
+assertEq(sample.includes(43, -0), true, "-0 [1]");
+assertEq(sample.includes(44, -0), false, "-0 [2]");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/includes.js b/js/src/tests/non262/Tuple/prototype/includes/includes.js
new file mode 100644
index 0000000000..26ef2bfb03
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/includes.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.7 Tuple.prototype.includes ( searchElement [ , fromIndex ] )
+Tuple.prototype.includes is a distinct function that implements the same algorithm as Array.prototype.includes as defined in 22.1.3.13 except that ? thisTupleValue(this value) is used instead of directly accessing the this value. The implementation of the algorithm may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse, do not change, and their access is not observable. However, such optimization must not introduce any observable changes in the specified behaviour of the algorithm.
+
+This function is not generic, since thisTupleValue(this value) can return an abrupt completion: in that case, that exception is thrown instead of evaluating the algorithm.
+*/
+
+/* Step 1 */
+/* includes() should throw on a non-Tuple */
+let method = Tuple.prototype.includes;
+assertEq(method.call(#[1,2,3,4,5,6], 2), true);
+assertEq(method.call(Object(#[1,2,3,4,5,6]), 2), true);
+assertThrowsInstanceOf(() => method.call("monkeys", 2), TypeError,
+ "value of TupleObject must be a Tuple");
+
+/* Not sure what else to test, since it just calls the array method */
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/length-internal.js b/js/src/tests/non262/Tuple/prototype/includes/length-internal.js
new file mode 100644
index 0000000000..a199884f00
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/length-internal.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/* Tuples should have a length ownProperty that can't be overridden, which will
+ * be read by any built-in methods called on Tuples.
+ * This test is expected to fail until the spec change in
+ * https://github.com/tc39/proposal-record-tuple/issues/282 is implemented.
+ */
+
+/*
+t = #[1,2,3];
+Object.defineProperty(Tuple.prototype, "length", {value: 0});
+assertEq(t.includes(2), true);
+*/
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/length-zero-returns-false.js b/js/src/tests/non262/Tuple/prototype/includes/length-zero-returns-false.js
new file mode 100644
index 0000000000..b72397d8f3
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/length-zero-returns-false.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Returns false if length is 0
+ ...
+---*/
+
+var calls = 0;
+var fromIndex = {
+ valueOf: function() {
+ calls++;
+ }
+};
+
+var sample = #[];
+assertEq(sample.includes(0), false, "returns false");
+assertEq(sample.includes(), false, "returns false - no arg");
+assertEq(sample.includes(0, fromIndex), false, "using fromIndex");
+assertEq(calls, 0, "length is checked before ToInteger(fromIndex)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/length.js b/js/src/tests/non262/Tuple/prototype/includes/length.js
new file mode 100644
index 0000000000..b8a60b837c
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/length.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype.includes, "length");
+assertEq(desc.value, 1);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype.includes, "name");
+assertEq(desc.value, "includes");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype, "includes");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.prototype.includes), false);
+
+assertThrowsInstanceOf(() => {
+ let t = #[1];
+ new t.includes();
+}, TypeError, '`let t = #[1]; new t.includes()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/name.js b/js/src/tests/non262/Tuple/prototype/includes/name.js
new file mode 100644
index 0000000000..df6537a3b4
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/name.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.includes.name is "includes".
+---*/
+
+assertEq(Tuple.prototype.includes.name, "includes");
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype.includes, "name");
+
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/no-arg.js b/js/src/tests/non262/Tuple/prototype/includes/no-arg.js
new file mode 100644
index 0000000000..83fee6722c
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/no-arg.js
@@ -0,0 +1,12 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: no argument searches for a undefined value
+---*/
+
+assertEq(#[0].includes(), false, "#[0].includes()");
+assertEq(#[undefined].includes(), true, "#[undefined].includes()");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/not-a-constructor.js b/js/src/tests/non262/Tuple/prototype/includes/not-a-constructor.js
new file mode 100644
index 0000000000..e60846e70a
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/not-a-constructor.js
@@ -0,0 +1,20 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.includes does not implement [[Construct]], is not new-able
+---*/
+
+assertEq(
+ isConstructor(Tuple.prototype.includes),
+ false,
+ 'isConstructor(Tuple.prototype.includes) must return false'
+);
+
+assertThrowsInstanceOf(() => new Tuple.prototype.includes(1),
+ TypeError, '`new Tuple.prototype.includes(1)` throws TypeError');
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/prop-desc.js b/js/src/tests/non262/Tuple/prototype/includes/prop-desc.js
new file mode 100644
index 0000000000..4dcd03d64c
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/prop-desc.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ "includes" property of Tuple.prototype
+---*/
+
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype, "includes");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/return-abrupt-get-length.js b/js/src/tests/non262/Tuple/prototype/includes/return-abrupt-get-length.js
new file mode 100644
index 0000000000..169a4318d8
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/return-abrupt-get-length.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// 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-array.prototype.includes
+description: Return abrupt from Get(O, "length")
+info: |
+ 22.1.3.11 Array.prototype.includes ( searchElement [ , fromIndex ] )
+
+ ...
+ 2. Let len be ? ToLength(? Get(O, "length")).
+ ...
+---*/
+
+var obj = {};
+
+Object.defineProperty(obj, "length", {
+ get: function() {
+ throw new Test262Error();
+ }
+});
+
+assertThrowsInstanceOf(() => #[].includes.call(obj, 7), TypeError,
+ "value of TupleObject must be a tuple");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tointeger-fromindex-symbol.js b/js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tointeger-fromindex-symbol.js
new file mode 100644
index 0000000000..9f6a0f5938
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tointeger-fromindex-symbol.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Return abrupt from ToInteger(fromIndex) - using symbol
+---*/
+
+var fromIndex = Symbol("1");
+
+var sample = #[7];
+
+assertThrowsInstanceOf(() => sample.includes(7, fromIndex), TypeError);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tointeger-fromindex.js b/js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tointeger-fromindex.js
new file mode 100644
index 0000000000..2d8ec0ee87
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tointeger-fromindex.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Return abrupt from ToInteger(fromIndex)
+---*/
+
+function TestError() {};
+
+var fromIndex = {
+ valueOf: function() {
+ throw new TestError();
+ }
+};
+
+var sample = #[7];
+
+assertThrowsInstanceOf(() => sample.includes(7, fromIndex), TestError);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tonumber-length-symbol.js b/js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tonumber-length-symbol.js
new file mode 100644
index 0000000000..f94fde9772
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tonumber-length-symbol.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Return abrupt from ToNumber(symbol "length")
+---*/
+
+var obj = {
+ length: Symbol("1")
+};
+
+assertThrowsInstanceOf(() => #[].includes.call(obj, 7), TypeError);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/samevaluezero.js b/js/src/tests/non262/Tuple/prototype/includes/samevaluezero.js
new file mode 100644
index 0000000000..c8dbe08c14
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/samevaluezero.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: search element is compared using SameValueZero
+---*/
+
+var sample = #[42, 0, 1, NaN];
+assertEq(sample.includes("42"), false);
+assertEq(sample.includes([42]), false);
+assertEq(sample.includes(#[42]), false);
+assertEq(sample.includes(42.0), true);
+assertEq(sample.includes(-0), true);
+assertEq(sample.includes(true), false);
+assertEq(sample.includes(false), false);
+assertEq(sample.includes(null), false);
+assertEq(sample.includes(""), false);
+assertEq(sample.includes(NaN), true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/search-found-returns-true.js b/js/src/tests/non262/Tuple/prototype/includes/search-found-returns-true.js
new file mode 100644
index 0000000000..0084583591
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/search-found-returns-true.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: returns true for found index
+---*/
+
+var symbol = Symbol("1");
+var tuple = #[];
+var record = #{};
+
+var sample = #[42, "test262", null, undefined, true, false, 0, -1, "", symbol, tuple, record];
+
+assertEq(sample.includes(42), true, "42");
+assertEq(sample.includes("test262"), true, "'test262'");
+assertEq(sample.includes(null), true, "null");
+assertEq(sample.includes(undefined), true, "undefined");
+assertEq(sample.includes(true), true, "true");
+assertEq(sample.includes(false), true, "false");
+assertEq(sample.includes(0), true, "0");
+assertEq(sample.includes(-1), true, "-1");
+assertEq(sample.includes(""), true, "the empty string");
+assertEq(sample.includes(symbol), true, "symbol");
+assertEq(sample.includes(tuple), true, "tuple");
+assertEq(sample.includes(record), true, "record");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/search-not-found-returns-false.js b/js/src/tests/non262/Tuple/prototype/includes/search-not-found-returns-false.js
new file mode 100644
index 0000000000..0e1889099f
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/search-not-found-returns-false.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: returns false if the element is not found
+---*/
+
+assertEq(#[42].includes(43), false, "43");
+
+assertEq(#["test262"].includes("test"), false, "string");
+
+assertEq(#[0, "test262", undefined].includes(""), false, "the empty string");
+
+assertEq(#["true", false].includes(true), false, "true");
+assertEq(#["", true].includes(false), false, "false");
+
+assertEq(#[undefined, false, 0, 1].includes(null), false, "null");
+assertEq(#[null].includes(undefined), false, "undefined");
+
+assertEq(#[Symbol("1")].includes(Symbol("1")), false, "symbol");
+
+var sample = #[42];
+assertEq(sample.includes(sample), false, "this");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/this-is-not-tuple.js b/js/src/tests/non262/Tuple/prototype/includes/this-is-not-tuple.js
new file mode 100644
index 0000000000..00679f2a73
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/this-is-not-tuple.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Throws a TypeError exception when `this` cannot be coerced to Tuple
+---*/
+
+var includes = Tuple.prototype.includes;
+
+assertThrowsInstanceOf(() => includes.call(undefined, 42), TypeError,
+ "this is undefined");
+
+assertThrowsInstanceOf(() => includes.call(null, 42), TypeError,
+ "this is null");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/tointeger-fromindex.js b/js/src/tests/non262/Tuple/prototype/includes/tointeger-fromindex.js
new file mode 100644
index 0000000000..608dbbf732
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/tointeger-fromindex.js
@@ -0,0 +1,40 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: get the integer value from fromIndex
+*/
+
+var obj = {
+ valueOf: function() {
+ return 1;
+ }
+};
+
+var sample = #[42, 43];
+assertEq(sample.includes(42, "1"), false, "string [0]");
+assertEq(sample.includes(43, "1"), true, "string [1]");
+
+assertEq(sample.includes(42, true), false, "true [0]");
+assertEq(sample.includes(43, true), true, "true [1]");
+
+assertEq(sample.includes(42, false), true, "false [0]");
+assertEq(sample.includes(43, false), true, "false [1]");
+
+assertEq(sample.includes(42, NaN), true, "NaN [0]");
+assertEq(sample.includes(43, NaN), true, "NaN [1]");
+
+assertEq(sample.includes(42, null), true, "null [0]");
+assertEq(sample.includes(43, null), true, "null [1]");
+
+assertEq(sample.includes(42, undefined), true, "undefined [0]");
+assertEq(sample.includes(43, undefined), true, "undefined [1]");
+
+assertEq(sample.includes(42, null), true, "null [0]");
+assertEq(sample.includes(43, null), true, "null [1]");
+
+assertEq(sample.includes(42, obj), false, "object [0]");
+assertEq(sample.includes(43, obj), true, "object [1]");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/includes/using-fromindex.js b/js/src/tests/non262/Tuple/prototype/includes/using-fromindex.js
new file mode 100644
index 0000000000..7dbcc00c20
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/includes/using-fromindex.js
@@ -0,0 +1,38 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+info: |
+ 22.1.3.11 Tuple.prototype.includes ( searchElement [ , fromIndex ] )
+---*/
+
+var sample = #["a", "b", "c"];
+assertEq(sample.includes("a", 0), true, "includes('a', 0)");
+assertEq(sample.includes("a", 1), false, "includes('a', 1)");
+assertEq(sample.includes("a", 2), false, "includes('a', 2)");
+
+assertEq(sample.includes("b", 0), true, "includes('b', 0)");
+assertEq(sample.includes("b", 1), true, "includes('b', 1)");
+assertEq(sample.includes("b", 2), false, "includes('b', 2)");
+
+assertEq(sample.includes("c", 0), true, "includes('c', 0)");
+assertEq(sample.includes("c", 1), true, "includes('c', 1)");
+assertEq(sample.includes("c", 2), true, "includes('c', 2)");
+
+assertEq(sample.includes("a", -1), false, "includes('a', -1)");
+assertEq(sample.includes("a", -2), false, "includes('a', -2)");
+assertEq(sample.includes("a", -3), true, "includes('a', -3)");
+assertEq(sample.includes("a", -4), true, "includes('a', -4)");
+
+assertEq(sample.includes("b", -1), false, "includes('b', -1)");
+assertEq(sample.includes("b", -2), true, "includes('b', -2)");
+assertEq(sample.includes("b", -3), true, "includes('b', -3)");
+assertEq(sample.includes("b", -4), true, "includes('b', -4)");
+
+assertEq(sample.includes("c", -1), true, "includes('c', -1)");
+assertEq(sample.includes("c", -2), true, "includes('c', -2)");
+assertEq(sample.includes("c", -3), true, "includes('c', -3)");
+assertEq(sample.includes("c", -4), true, "includes('c', -4)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/empty-tuple.js b/js/src/tests/non262/Tuple/prototype/indexOf/empty-tuple.js
new file mode 100644
index 0000000000..1334ba9271
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/empty-tuple.js
@@ -0,0 +1,13 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Tuple.prototype.indexOf returns -1 if 'length' is 0 (empty tuple)
+---*/
+
+var i = #[].indexOf(42);
+
+assertEq(i, -1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-boolean.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-boolean.js
new file mode 100644
index 0000000000..41c064370b
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-boolean.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Tuple.prototype.indexOf when fromIndex is boolean
+---*/
+
+let a = #[1, 2, 3];
+
+assertEq(a.indexOf(1, true), -1);
+assertEq(a.indexOf(1, false), 0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-float.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-float.js
new file mode 100644
index 0000000000..1c2995a0af
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-float.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Tuple.prototype.indexOf when fromIndex is floating point number
+---*/
+
+var a = #[1,2,3];
+
+assertEq(a.indexOf(3, 0.49), 2);
+assertEq(a.indexOf(1, 0.51), 0);
+assertEq(a.indexOf(1, 1.51), -1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-greater-than-length.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-greater-than-length.js
new file mode 100644
index 0000000000..3514d0a444
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-greater-than-length.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf returns -1 if fromIndex is greater than
+ Tuple length
+---*/
+
+let a = #[1, 2, 3];
+
+assertEq(a.indexOf(1, 5), -1);
+assertEq(a.indexOf(1, 3), -1);
+assertEq(#[].indexOf(1, 0), -1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-infinity-string.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-infinity-string.js
new file mode 100644
index 0000000000..de5895aca3
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-infinity-string.js
@@ -0,0 +1,13 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is a string
+ containing -Infinity
+---*/
+
+assertEq(#[true].indexOf(true, "-Infinity"), 0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-inherited-valueOf.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-inherited-valueOf.js
new file mode 100644
index 0000000000..a2ad8353bf
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-inherited-valueOf.js
@@ -0,0 +1,36 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-array.prototype.indexof
+description: >
+ Tuple.prototype.indexOf uses inherited valueOf method when value
+ of 'fromIndex' is an object with an own toString and inherited
+ valueOf methods
+---*/
+
+var toStringAccessed = false;
+var valueOfAccessed = false;
+
+var proto = {
+ valueOf: function() {
+ valueOfAccessed = true;
+ return 1;
+ }
+};
+
+var Con = function() {};
+Con.prototype = proto;
+
+var child = new Con();
+child.toString = function() {
+ toStringAccessed = true;
+ return 2;
+};
+
+assertEq(#[0, true].indexOf(true, child), 1, '[0, true].indexOf(true, child)');
+assertEq(valueOfAccessed, true);
+assertEq(toStringAccessed, false, 'toStringAccessed');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-missing.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-missing.js
new file mode 100644
index 0000000000..6a16da4847
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-missing.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-array.prototype.indexof
+description: Tuple.prototype.indexOf - 'fromIndex' isn't passed
+---*/
+
+var arr = #[0, 1, 2, 3, 4];
+//'fromIndex' will be set as 0 if not passed by default
+
+assertEq(arr.indexOf(0), arr.indexOf(0, 0), 'arr.indexOf(0)');
+assertEq(arr.indexOf(2), arr.indexOf(2, 0), 'arr.indexOf(2)');
+assertEq(arr.indexOf(4), arr.indexOf(4, 0), 'arr.indexOf(4)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-nan.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-nan.js
new file mode 100644
index 0000000000..40fdde8a34
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-nan.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-array.prototype.indexof
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is a number (value
+ is NaN)
+---*/
+
+assertEq(#[true].indexOf(true, NaN), 0, '[true].indexOf(true, NaN)');
+assertEq(#[true].indexOf(true, -NaN), 0, '[true].indexOf(true, -NaN)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-neg-infinity.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-neg-infinity.js
new file mode 100644
index 0000000000..4595230e83
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-neg-infinity.js
@@ -0,0 +1,13 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is a number (value
+ is -Infinity)
+---*/
+
+assertEq(#[true].indexOf(true, -Infinity), 0, '#[true].indexOf(true, -Infinity)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-neg-zero.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-neg-zero.js
new file mode 100644
index 0000000000..2d0d856f4f
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-neg-zero.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-array.prototype.indexof
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is a number (value
+ is -0)
+---*/
+
+assertEq(#[true].indexOf(true, -0), 0, '#[true].indexOf(true, -0)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-negative.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-negative.js
new file mode 100644
index 0000000000..db87f171d2
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-negative.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is a number (value
+ is negative number)
+---*/
+
+var target = #[];
+
+assertEq(#[0, target, 2].indexOf(target, -1), -1, '[0, target, 2].indexOf(target, -1)');
+assertEq(#[0, 1, target].indexOf(target, -1), 2, '[0, 1, target].indexOf(target, -1)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-null.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-null.js
new file mode 100644
index 0000000000..f046fe2398
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-null.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-array.prototype.indexof
+description: Tuple.prototype.indexOf returns 0 if fromIndex is null
+---*/
+
+var a = #[1, 2, 3];
+
+// null resolves to 0
+assertEq(a.indexOf(1, null), 0, 'a.indexOf(1,null)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-number.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-number.js
new file mode 100644
index 0000000000..8fc53c3a5a
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-number.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-array.prototype.indexof
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is a number (value
+ is 0)
+---*/
+
+assertEq(#[true].indexOf(true, 0), 0, '#[true].indexOf(true, 0)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-not-primitive.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-not-primitive.js
new file mode 100644
index 0000000000..946dc411fc
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-not-primitive.js
@@ -0,0 +1,33 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf throws TypeError exception when value of
+ 'fromIndex' is an object with toString and valueOf methods that
+ don�t return primitive values
+---*/
+
+var toStringAccessed = false;
+var valueOfAccessed = false;
+var fromIndex = {
+ toString: function() {
+ toStringAccessed = true;
+ return {};
+ },
+
+ valueOf: function() {
+ valueOfAccessed = true;
+ return {};
+ }
+};
+
+assertThrowsInstanceOf(function() {
+ #[0, true].indexOf(true, fromIndex);
+}, TypeError);
+
+assertEq(toStringAccessed, true);
+assertEq(valueOfAccessed, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-valueOf-toString.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-valueOf-toString.js
new file mode 100644
index 0000000000..5568a31bdf
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-valueOf-toString.js
@@ -0,0 +1,31 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is an object that
+ has an own valueOf method that returns an object and toString
+ method that returns a string
+---*/
+
+var toStringAccessed = false;
+var valueOfAccessed = false;
+
+var fromIndex = {
+ toString: function() {
+ toStringAccessed = true;
+ return '1';
+ },
+
+ valueOf: function() {
+ valueOfAccessed = true;
+ return {};
+ }
+};
+
+assertEq(#[0, true].indexOf(true, fromIndex), 1, '#[0, true].indexOf(true, fromIndex)');
+assertEq(toStringAccessed, true);
+assertEq(valueOfAccessed, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-valueOf.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-valueOf.js
new file mode 100644
index 0000000000..c69aadaefb
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-valueOf.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-array.prototype.indexof
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is an Object, which
+ has an own valueOf method
+---*/
+
+var fromIndex = {
+ valueOf: function() {
+ return 1;
+ }
+};
+
+
+assertEq(#[0, true].indexOf(true, fromIndex), 1, '#[0, true].indexOf(true, fromIndex)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object.js
new file mode 100644
index 0000000000..cb1d74ddf8
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is an Object, which
+ has an own toString method
+---*/
+
+// objects inherit the default valueOf() method from Object
+// that simply returns itself. Since the default valueOf() method
+// does not return a primitive value, ES next tries to convert the object
+// to a number by calling its toString() method and converting the
+// resulting string to a number.
+var fromIndex = {
+ toString: function() {
+ return '1';
+ }
+};
+
+assertEq(#[0, true].indexOf(true, fromIndex), 1, '#[0, true].indexOf(true, fromIndex)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-positive.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-positive.js
new file mode 100644
index 0000000000..c5b1948356
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-positive.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is a number (value
+ is positive number)
+---*/
+
+var target = #[];
+
+assertEq(#[0, target, 2].indexOf(target, 2), -1, '#[0, target, 2].indexOf(target, 2)');
+assertEq(#[0, 1, target].indexOf(target, 2), 2, '#[0, 1, target].indexOf(target, 2)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-side-effects-3.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-side-effects-3.js
new file mode 100644
index 0000000000..b2a98cc58a
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-side-effects-3.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf - side effects produced by step 1 are
+ visible when an exception occurs
+---*/
+
+var stepFiveOccurs = false;
+var fromIndex = {
+ valueOf: function() {
+ stepFiveOccurs = true;
+ return 0;
+ }
+};
+assertThrowsInstanceOf(function() {
+ Tuple.prototype.indexOf.call(undefined, undefined, fromIndex);
+}, TypeError);
+assertEq(stepFiveOccurs, false, 'stepFiveOccurs');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-2.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-2.js
new file mode 100644
index 0000000000..ca7591a49b
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-2.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Tuple.prototype.indexOf when fromIndex is string
+---*/
+
+var a = #[1, 2, 1, 2, 1, 2];
+
+assertEq(a.indexOf(2, "2"), 3, '"2" resolves to 2');
+assertEq(a.indexOf(2, "one"), 1, '"one" resolves to 0');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-exponent.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-exponent.js
new file mode 100644
index 0000000000..a544e56717
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-exponent.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is a string
+ containing an exponential number
+---*/
+
+var target = #[];
+
+assertEq(#[0, 1, target, 3, 4].indexOf(target, "3E0"), -1, '#[0, 1, target, 3, 4].indexOf(target, "3E0")');
+assertEq(#[0, 1, 2, target, 4].indexOf(target, "3E0"), 3, '#[0, 1, 2, target, 4].indexOf(target, "3E0")');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-hex.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-hex.js
new file mode 100644
index 0000000000..633a2688b3
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-hex.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-array.prototype.indexof
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is a string
+ containing a hex number
+---*/
+
+var target = #[];
+
+assertEq(#[0, 1, target, 3, 4].indexOf(target, "0x0003"), -1, '#[0, 1, target, 3, 4].indexOf(target, "0x0003")');
+assertEq(#[0, 1, 2, target, 4].indexOf(target, "0x0003"), 3, '#[0, 1, 2, target, 4].indexOf(target, "0x0003")');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-leading-zeros.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-leading-zeros.js
new file mode 100644
index 0000000000..805516e4fa
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-leading-zeros.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' which is a string
+ containing a number with leading zeros
+---*/
+
+var target = #[];
+
+assertEq(#[0, 1, target, 3, 4].indexOf(target, "0003.10"), -1, '#[0, 1, target, 3, 4].indexOf(target, "0003.10")');
+assertEq(#[0, 1, 2, target, 4].indexOf(target, "0003.10"), 3, '#[0, 1, 2, target, 4].indexOf(target, "0003.10")');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-neg-infinity.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-neg-infinity.js
new file mode 100644
index 0000000000..7595ab2bb5
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-neg-infinity.js
@@ -0,0 +1,13 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is a string
+ containing -Infinity
+---*/
+
+assertEq(#[true].indexOf(true, "-Infinity"), 0, '#[true].indexOf(true, "-Infinity")');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-negative.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-negative.js
new file mode 100644
index 0000000000..1b1c330725
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-negative.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is a string
+ containing a negative number
+---*/
+
+assertEq(#[0, true, 2].indexOf(true, "-1"), -1, '#[0, true, 2].indexOf(true, "-1")');
+assertEq(#[0, 1, true].indexOf(true, "-1"), 2, '#[0, 1, true].indexOf(true, "-1")');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string.js
new file mode 100644
index 0000000000..1b1c330725
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is a string
+ containing a negative number
+---*/
+
+assertEq(#[0, true, 2].indexOf(true, "-1"), -1, '#[0, true, 2].indexOf(true, "-1")');
+assertEq(#[0, 1, true].indexOf(true, "-1"), 2, '#[0, 1, true].indexOf(true, "-1")');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-trunc-2.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-trunc-2.js
new file mode 100644
index 0000000000..4d08a4700d
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-trunc-2.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-array.prototype.indexof
+description: >
+ Tuple.prototype.indexOf - 'fromIndex' is a negative non-integer,
+ verify truncation occurs in the proper direction
+---*/
+
+var target = #[];
+
+assertEq(#[0, target, 2].indexOf(target, -1.5), -1, '#[0, target, 2].indexOf(target, -1.5)');
+assertEq(#[0, 1, target].indexOf(target, -1.5), 2, '#[0, 1, target].indexOf(target, -1.5)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-trunc.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-trunc.js
new file mode 100644
index 0000000000..a9cbd3fa9c
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-trunc.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-array.prototype.indexof
+description: >
+ Tuple.prototype.indexOf - 'fromIndex' is a positive non-integer,
+ verify truncation occurs in the proper direction
+---*/
+
+var target = #[];
+
+assertEq(#[0, target, 2].indexOf(target, 2.5), -1, '#[0, target, 2].indexOf(target, 2.5)');
+assertEq(#[0, 1, target].indexOf(target, 2.5), 2, '#[0, 1, target].indexOf(target, 2.5)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-undefined.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-undefined.js
new file mode 100644
index 0000000000..054495a9d9
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-undefined.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Tuple.prototype.indexOf returns 0 if fromIndex is 'undefined'
+---*/
+
+var a = #[1, 2, 3];
+
+// undefined resolves to 0
+assertEq(a.indexOf(1, undefined), 0, 'a.indexOf(1,undefined)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-with-index.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-with-index.js
new file mode 100644
index 0000000000..75a5e5266f
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-with-index.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf match on the first element, a middle
+ element and the last element when 'fromIndex' is passed
+---*/
+
+assertEq(#[0, 1, 2, 3, 4].indexOf(0, 0), 0, '#[0, 1, 2, 3, 4].indexOf(0, 0)');
+assertEq(#[0, 1, 2, 3, 4].indexOf(2, 1), 2, '#[0, 1, 2, 3, 4].indexOf(2, 1)');
+assertEq(#[0, 1, 2, 3, 4].indexOf(2, 2), 2, '#[0, 1, 2, 3, 4].indexOf(2, 2)');
+assertEq(#[0, 1, 2, 3, 4].indexOf(4, 2), 4, '#[0, 1, 2, 3, 4].indexOf(4, 2)');
+assertEq(#[0, 1, 2, 3, 4].indexOf(4, 4), 4, '#[0, 1, 2, 3, 4].indexOf(4, 4)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-zero.js b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-zero.js
new file mode 100644
index 0000000000..0fa7d114e9
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-zero.js
@@ -0,0 +1,13 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf - value of 'fromIndex' is a number (value
+ is +0)
+---*/
+
+assertEq(#[true].indexOf(true, +0), 0, '#[true].indexOf(true, +0)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/includes.js b/js/src/tests/non262/Tuple/prototype/indexOf/includes.js
new file mode 100644
index 0000000000..26ef2bfb03
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/includes.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.7 Tuple.prototype.includes ( searchElement [ , fromIndex ] )
+Tuple.prototype.includes is a distinct function that implements the same algorithm as Array.prototype.includes as defined in 22.1.3.13 except that ? thisTupleValue(this value) is used instead of directly accessing the this value. The implementation of the algorithm may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse, do not change, and their access is not observable. However, such optimization must not introduce any observable changes in the specified behaviour of the algorithm.
+
+This function is not generic, since thisTupleValue(this value) can return an abrupt completion: in that case, that exception is thrown instead of evaluating the algorithm.
+*/
+
+/* Step 1 */
+/* includes() should throw on a non-Tuple */
+let method = Tuple.prototype.includes;
+assertEq(method.call(#[1,2,3,4,5,6], 2), true);
+assertEq(method.call(Object(#[1,2,3,4,5,6]), 2), true);
+assertThrowsInstanceOf(() => method.call("monkeys", 2), TypeError,
+ "value of TupleObject must be a Tuple");
+
+/* Not sure what else to test, since it just calls the array method */
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/length-internal.js b/js/src/tests/non262/Tuple/prototype/indexOf/length-internal.js
new file mode 100644
index 0000000000..a199884f00
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/length-internal.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/* Tuples should have a length ownProperty that can't be overridden, which will
+ * be read by any built-in methods called on Tuples.
+ * This test is expected to fail until the spec change in
+ * https://github.com/tc39/proposal-record-tuple/issues/282 is implemented.
+ */
+
+/*
+t = #[1,2,3];
+Object.defineProperty(Tuple.prototype, "length", {value: 0});
+assertEq(t.includes(2), true);
+*/
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/length.js b/js/src/tests/non262/Tuple/prototype/indexOf/length.js
new file mode 100644
index 0000000000..46cd2b914b
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/length.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype.indexOf, "length");
+assertEq(desc.value, 1);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype.indexOf, "name");
+assertEq(desc.value, "indexOf");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype, "indexOf");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.prototype.indexOf), false);
+
+assertThrowsInstanceOf(() => {
+ let t = #[1];
+ new t.indexOf();
+}, TypeError, '`let t = #[1]; new t.indexOf()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/undefined-throws-type-error.js b/js/src/tests/non262/Tuple/prototype/indexOf/undefined-throws-type-error.js
new file mode 100644
index 0000000000..da72398b79
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/undefined-throws-type-error.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Tuple.prototype.indexOf applied to undefined throws a TypeError
+---*/
+
+
+assertThrowsInstanceOf(function() {
+ Tuple.prototype.indexOf.call(undefined);
+}, TypeError);
+
+assertThrowsInstanceOf(function() {
+ Tuple.prototype.indexOf.call(null);
+}, TypeError);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/indexOf/uses-internal-length.js b/js/src/tests/non262/Tuple/prototype/indexOf/uses-internal-length.js
new file mode 100644
index 0000000000..8c8cc1beb4
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/indexOf/uses-internal-length.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Tuple.prototype.indexOf - 'length' is own data property that
+ overrides an inherited data property on an Tuple
+---*/
+
+var target = #[];
+
+Tuple.prototype.length = 0;
+
+assertEq(#[0, target].indexOf(target), 1, '#[0, target].indexOf(target)');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/isTuple/isTuple.js b/js/src/tests/non262/Tuple/prototype/isTuple/isTuple.js
new file mode 100644
index 0000000000..714c9cab42
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/isTuple/isTuple.js
@@ -0,0 +1,47 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var f = Tuple.isTuple;
+
+assertEq(typeof f, "function");
+assertEq(f.length, 1);
+assertEq(f(#[]), true);
+assertEq(f(#[1]), true);
+assertEq(f(#[1,2,3]), true);
+assertEq(f(Object(#[])), true);
+assertEq(f(Object(#[1])), true);
+assertEq(f(Object(#[1,2,3])), true);
+
+for (thing of [42, new Number(-42), undefined, true, false, "abc" , new String("a\nb\\!"), {}, [], [1,2,3], new Uint8Array(1,2,3), null, new RegExp(), JSON, new SyntaxError(), function() {}, Math, new Date()]) {
+ assertEq(f(thing), false);
+}
+assertEq(f(Tuple.prototype), false);
+var arg;
+(function fun() { arg = arguments; }(1,2,3));
+assertEq(f(arg), false);
+assertEq(f(this), false);
+
+var proto = [];
+var Con = function() {};
+Con.prototype = proto;
+
+var child = new Con();
+
+assertEq(f(child), false);
+
+var proto = Tuple.prototype;
+var Con = function() {};
+Con.prototype = proto;
+
+var child = new Con();
+
+assertEq(f(child), false);
+
+assertEq(f({
+ 0: 12,
+ 1: 9,
+ length: 2
+}), false);
+
+
+reportCompare(0, 0);
+
+
diff --git a/js/src/tests/non262/Tuple/prototype/isTuple/length.js b/js/src/tests/non262/Tuple/prototype/isTuple/length.js
new file mode 100644
index 0000000000..75acb7aedd
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/isTuple/length.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.isTuple, "length");
+assertEq(desc.value, 1);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+
+desc = Object.getOwnPropertyDescriptor(Tuple.isTuple, "name");
+assertEq(desc.value, "isTuple");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.isTuple), false);
+
+assertThrowsInstanceOf(() => {
+ let t = #[1];
+ new t.isTuple()();
+}, TypeError, '`let t = #[1]; new t.isTuple()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/join/browser.js b/js/src/tests/non262/Tuple/prototype/join/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/join/browser.js
diff --git a/js/src/tests/non262/Tuple/prototype/join/dda-separator.js b/js/src/tests/non262/Tuple/prototype/join/dda-separator.js
new file mode 100644
index 0000000000..cee96a708d
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/join/dda-separator.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+let dda = createIsHTMLDDA();
+
+assertEq(dda == null, true);
+assertEq(dda === null, false);
+
+assertEq(dda == undefined, true);
+assertEq(dda === undefined, false);
+
+let tup = Tuple("A", "B");
+assertEq(tup.join(null), "A,B");
+assertEq(tup.join(undefined), "A,B");
+assertEq(tup.join(dda), "A" + dda.toString() + "B");
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/join/shell.js b/js/src/tests/non262/Tuple/prototype/join/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/join/shell.js
diff --git a/js/src/tests/non262/Tuple/prototype/length/length-getter.js b/js/src/tests/non262/Tuple/prototype/length/length-getter.js
new file mode 100644
index 0000000000..7d07c152e3
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/length/length-getter.js
@@ -0,0 +1,42 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*---
+esid: sec-get-%tuple%.prototype.length
+description: >
+info: |
+ get %Tuple%.prototype.length
+
+Tuple.prototype.length is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:
+
+1. Let T be ? thisTupleValue(this value).
+2. Let size be the length of T.[[Sequence]].
+3. Return size.
+
+features: [Tuple]
+---*/
+
+/* Section 8.2.3.2 */
+
+let TuplePrototype = Tuple.prototype;
+let desc = Object.getOwnPropertyDescriptor(TuplePrototype, "length");
+
+assertEq(typeof desc.get, "function");
+
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(desc.set, undefined);
+
+let values = [[#[1,2,3], 3], [#[1], 1], [#[], 0]];
+
+for (pair of values) {
+ let tup = pair[0];
+ let len = pair[1];
+ assertEq(desc.get.call(tup), len);
+ assertEq(desc.get.call(Object(tup)), len);
+ assertEq(tup["length"], len);
+}
+
+assertThrowsInstanceOf(() => desc.get.call("monkeys"), TypeError, "get length method called on incompatible string");
+assertThrowsInstanceOf(() => desc.get.call(new Object()), TypeError, "get length method called on incompatible Object");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/map/callback-not-called-on-empty.js b/js/src/tests/non262/Tuple/prototype/map/callback-not-called-on-empty.js
new file mode 100644
index 0000000000..a28699c282
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/map/callback-not-called-on-empty.js
@@ -0,0 +1,7 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var called = 0;
+#[].map(() => called++);
+assertEq(called, 0);
+
+reportCompare(0, 0);
+
diff --git a/js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-with-thisarg b/js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-with-thisarg
new file mode 100644
index 0000000000..88a9454e87
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-with-thisarg
@@ -0,0 +1,45 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// 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-%Tuple%.prototype.map
+description: >
+ callbackfn arguments
+info: |
+ 8.2.3.20 %Tuple%.prototype.map ( callbackfn [ , thisArg ] )
+
+ ...
+7. Repeat, while k < len,
+a. Let kValue be list[k].
+b. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, k, T »).
+ ...
+features: [Tuple]
+---*/
+
+var sample = #[42,43,44];
+
+var results = [];
+
+sample.map(function() {
+ results.push(arguments);
+ return 0;
+});
+
+assertEq(results.length, 3);
+
+assertEq(results[0].length, 3);
+assertEq(results[0][0], 42);
+assertEq(results[0][1], 0);
+assertEq(results[0][2], sample);
+
+assertEq(results[1].length, 3);
+assertEq(results[1][0], 43);
+assertEq(results[1][1], 1);
+assertEq(results[1][2], sample);
+
+assertEq(results[2].length, 3);
+assertEq(results[2][0], 44);
+assertEq(results[2][1], 2);
+assertEq(results[2][2], sample);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-with-thisarg.js b/js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-with-thisarg.js
new file mode 100644
index 0000000000..380f493995
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-with-thisarg.js
@@ -0,0 +1,43 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// 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-%Tuple%.prototype.map
+description: >
+ callbackfn arguments
+info: |
+ 8.2.3.20 %Tuple%.prototype.map ( callbackfn [ , thisArg ] )
+
+ ...
+7. Repeat, while k < len,
+a. Let kValue be list[k].
+b. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, k, T »).
+ ...
+features: [Tuple]
+---*/
+
+var sample = #[42,43,44];
+var results = [];
+var thisArg = ["monkeys", 0, "bunnies", 0];
+
+sample.map(function() { results.push(arguments); return 0; }, thisArg);
+
+assertEq(results.length, 3);
+assertEq(thisArg.length, 4);
+
+assertEq(results[0].length, 3);
+assertEq(results[0][0], 42);
+assertEq(results[0][1], 0);
+assertEq(results[0][2], sample);
+
+assertEq(results[1].length, 3);
+assertEq(results[1][0], 43);
+assertEq(results[1][1], 1);
+assertEq(results[1][2], sample);
+
+assertEq(results[2].length, 3);
+assertEq(results[2][0], 44);
+assertEq(results[2][1], 2);
+assertEq(results[2][2], sample);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-without-thisarg.js b/js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-without-thisarg.js
new file mode 100644
index 0000000000..88a9454e87
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-without-thisarg.js
@@ -0,0 +1,45 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// 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-%Tuple%.prototype.map
+description: >
+ callbackfn arguments
+info: |
+ 8.2.3.20 %Tuple%.prototype.map ( callbackfn [ , thisArg ] )
+
+ ...
+7. Repeat, while k < len,
+a. Let kValue be list[k].
+b. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, k, T »).
+ ...
+features: [Tuple]
+---*/
+
+var sample = #[42,43,44];
+
+var results = [];
+
+sample.map(function() {
+ results.push(arguments);
+ return 0;
+});
+
+assertEq(results.length, 3);
+
+assertEq(results[0].length, 3);
+assertEq(results[0][0], 42);
+assertEq(results[0][1], 0);
+assertEq(results[0][2], sample);
+
+assertEq(results[1].length, 3);
+assertEq(results[1][0], 43);
+assertEq(results[1][1], 1);
+assertEq(results[1][2], sample);
+
+assertEq(results[2].length, 3);
+assertEq(results[2][0], 44);
+assertEq(results[2][1], 2);
+assertEq(results[2][2], sample);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/map/callbackfn-is-not-callable.js b/js/src/tests/non262/Tuple/prototype/map/callbackfn-is-not-callable.js
new file mode 100644
index 0000000000..e2a3c10bcb
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/map/callbackfn-is-not-callable.js
@@ -0,0 +1,40 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// 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-%Tuple%.prototype.map
+description: >
+ callbackfn arguments
+info: |
+ 8.2.3.20 %Tuple%.prototype.map ( callbackfn [ , thisArg ] )
+
+ ...
+ 4. If IsCallable(callbackfn) is false, throw a TypeError exception.
+ ...
+features: [Tuple]
+---*/
+
+var sample = #[1,2,3];
+
+assertThrowsInstanceOf(() => sample.map(), TypeError,
+ "map: callbackfn is not callable (no argument)");
+
+assertThrowsInstanceOf(() => sample.map(undefined), TypeError,
+ "map: callbackfn is not callable (undefined)");
+
+assertThrowsInstanceOf(() => sample.map(null), TypeError,
+ "map: callbackfn is not callable (null)");
+
+assertThrowsInstanceOf(() => sample.map({}), TypeError,
+ "map: callbackfn is not callable ({})");
+
+assertThrowsInstanceOf(() => sample.map(1), TypeError,
+ "map: callbackfn is not callable (1)");
+
+assertThrowsInstanceOf(() => sample.map(""), TypeError,
+ "map: callbackfn is not callable (\"\")");
+
+assertThrowsInstanceOf(() => sample.map(false), TypeError,
+ "map: callbackfn is not callable (false)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/map/callbackfn-returns-abrupt.js b/js/src/tests/non262/Tuple/prototype/map/callbackfn-returns-abrupt.js
new file mode 100644
index 0000000000..1819aac0c4
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/map/callbackfn-returns-abrupt.js
@@ -0,0 +1,8 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var sample = #[1,2,3];
+
+assertThrowsInstanceOf(() => sample.map(function () { throw new TypeError("monkeys"); }),
+ TypeError,
+ "should throw TypeError: monkeys");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/map/indexed-setters.js b/js/src/tests/non262/Tuple/prototype/map/indexed-setters.js
new file mode 100644
index 0000000000..774f1dc349
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/map/indexed-setters.js
@@ -0,0 +1,12 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+// If an indexed Array setter is overridden, TupleMap shouldn't use it
+// when constructing the intermediate array
+
+z = 5;
+Object.defineProperty(Array.prototype, '0', { set: function(y) { z = 42; }});
+newT = #[1,2,3].map(x => x*x);
+assertEq(z, 5);
+
+reportCompare(0, 0);
+
diff --git a/js/src/tests/non262/Tuple/prototype/map/invoked-as-func.js b/js/src/tests/non262/Tuple/prototype/map/invoked-as-func.js
new file mode 100644
index 0000000000..6a485157b2
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/map/invoked-as-func.js
@@ -0,0 +1,6 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var map = Tuple.prototype.map;
+
+assertEq(typeof map, 'function');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/map/invoked-as-method.js b/js/src/tests/non262/Tuple/prototype/map/invoked-as-method.js
new file mode 100644
index 0000000000..bf838117b8
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/map/invoked-as-method.js
@@ -0,0 +1,10 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var TuplePrototype = Tuple.prototype;
+
+assertEq(typeof TuplePrototype.map, 'function');
+
+assertThrowsInstanceOf(function() {
+ TuplePrototype.map();
+}, TypeError, "Tuple.prototype.map() with no argument");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/map/length-internal.js b/js/src/tests/non262/Tuple/prototype/map/length-internal.js
new file mode 100644
index 0000000000..9d4538288c
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/map/length-internal.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+Object.defineProperty(Tuple.prototype, "length", {value: 0});
+let t = #[1,2,3];
+var result = t.map(x => x + 1);
+// overriding length shouldn't have an effect
+assertEq(result, #[2,3,4]);
+
+
+Object.defineProperty(Tuple.prototype, "length", {
+ get() { return 0 }
+});
+let u = #[1,2,3];
+var result = u.map(x => x + 1);
+// overriding length shouldn't have an effect
+assertEq(result, #[2,3,4]);
+
+reportCompare(0, 0);
+
diff --git a/js/src/tests/non262/Tuple/prototype/map/length.js b/js/src/tests/non262/Tuple/prototype/map/length.js
new file mode 100644
index 0000000000..02d77af7ed
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/map/length.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype.map, "length");
+assertEq(desc.value, 1);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype.map, "name");
+assertEq(desc.value, "map");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype, "map");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.prototype.map), false);
+
+assertThrowsInstanceOf(() => {
+ let t = #[1];
+ new t.map();
+}, TypeError, '`let t = #[1]; new t.map()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/map/map.js b/js/src/tests/non262/Tuple/prototype/map/map.js
new file mode 100644
index 0000000000..40f871b1d2
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/map/map.js
@@ -0,0 +1,85 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.20 Tuple.prototype.map ( callbackfn [ , thisArg ] )
+NOTE
+callbackfn should be a function that accepts three arguments. map calls callbackfn once for each element in the Tuple, in ascending order, and constructs a new tuple from the results.
+
+If a thisArg parameter is provided, it will be used as the this value for each invocation of callbackfn. If it is not provided, undefined is used instead.
+
+callbackfn is called with three arguments: the value of the element, the index of the element, and the Tuple being traversed.
+
+When the map method is called with one or two arguments, the following steps are taken:
+
+1. Let T be ? thisTupleValue(this value).
+2. Let list be T.[[Sequence]].
+3. Let len be the number of elements in list.
+4. If IsCallable(callbackfn) is false, throw a TypeError exception.
+5. Let newList be a new empty List.
+6. Let k be 0.
+7. Repeat, while k < len,
+a. Let kValue be list[k].
+b. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, k, T »).
+c. If Type(mappedValue) is Object, throw a TypeError exception.
+d. Append mappedValue to the end of list newList.
+e. Set k to k + 1.
+8. Return a new Tuple value whose [[Sequence]] is newList.
+
+*/
+
+/* Step 1 */
+/* map() should throw on a non-Tuple */
+let method = Tuple.prototype.map;
+let f = (x, i, tup) => x + 1;
+assertEq(method.call(#[1,2,3,4,5,6],f), #[2,3,4,5,6,7]);
+assertEq(method.call(Object(#[1,2,3,4,5,6]), f), #[2,3,4,5,6,7]);
+assertThrowsInstanceOf(() => method.call("monkeys", f), TypeError,
+ "value of TupleObject must be a Tuple");
+
+let tup = #[1,2,3];
+
+/* Step 4 */
+/* callbackfn not callable -- should throw */
+assertThrowsInstanceOf(() => tup.map(), TypeError,
+ "missing function argument to Tuple.prototype.map");
+assertThrowsInstanceOf(() => tup.map(undefined), TypeError,
+ "missing function argument to Tuple.prototype.map");
+assertThrowsInstanceOf(() => tup.map("monkeys"), TypeError,
+ "bad function argument to Tuple.prototype.map");
+
+
+/* callbackfn with 1 argument -- should be allowed */
+var f2 = x => x * x;
+assertEq(tup.map(f2), #[1, 4, 9]);
+
+/* callbackfn with 2 arguments -- should be allowed */
+f2 = (x, i) => x + i;
+assertEq(tup.map(f2), #[1, 3, 5]);
+
+/* callbackfn with > 3 arguments -- subsequent ones will be undefined */
+var f3 = (a, b, c, d, e) => e === undefined;
+assertEq(tup.map(f3), #[true, true, true]);
+
+/* callbackfn should be able to use index and tuple */
+var f4 = (x, i, tup) => (tup.indexOf(x+1) * i * x);
+assertEq(tup.map(f4), #[0, 4, -6]);
+
+/* explicit thisArg */
+f1 = function (x, i, tup) { return(this.elements.indexOf(x) * x); };
+assertEq(#[1,2,3,4,5].map(f1, { elements: [2, 4] }), #[-1, 0, -3, 4, -5]);
+
+/* Step 3 */
+/* Test that length is still handled correctly if it's overridden */
+Object.defineProperty(Tuple.prototype, "length", { get() { return 0 } })
+assertEq(tup.map(f), #[2,3,4]);
+
+/* Step 7 */
+assertEq(#[].map(f), #[]);
+assertEq(#[1].map(f), #[2]);
+assertEq(#[1,2].map(f), #[2,3]);
+
+/* Step 7c. */
+var badFun = x => new Object(x);
+assertThrowsInstanceOf(() => tup.map(badFun),
+ TypeError, "Tuples cannot contain Objects");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/map/this-is-not-tuple.js b/js/src/tests/non262/Tuple/prototype/map/this-is-not-tuple.js
new file mode 100644
index 0000000000..5464da96f5
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/map/this-is-not-tuple.js
@@ -0,0 +1,30 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// 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-%typedarray%.prototype.map
+description: Throws a TypeError exception when `this` is not a Tuple
+info: |
+
+features: [Tuple]
+---*/
+
+var map = Tuple.prototype.map;
+var callbackfn = function() {};
+
+var thisVals = [[undefined, "undefined"],
+ [null, "null"],
+ [42, "42"],
+ ["1", "1"],
+ [true, "true"],
+ [false, "false"],
+ [Symbol("s"), "Symbol(\"s\")"]];
+
+for (pair of thisVals) {
+ thisVal = pair[0];
+ errorMsg = "this is: " + pair[1];
+ assertThrowsInstanceOf(() => map.call(thisVal, callbackfn),
+ TypeError, errorMsg);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/slice/invoked-as-func.js b/js/src/tests/non262/Tuple/prototype/slice/invoked-as-func.js
new file mode 100644
index 0000000000..961ed9aff5
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/slice/invoked-as-func.js
@@ -0,0 +1,7 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var slice = Tuple.prototype.slice;
+
+assertThrowsInstanceOf(function() { slice() }, TypeError,
+ "value of TupleObject must be a Tuple");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/slice/invoked-as-method.js b/js/src/tests/non262/Tuple/prototype/slice/invoked-as-method.js
new file mode 100644
index 0000000000..291bf433cd
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/slice/invoked-as-method.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var TuplePrototype = Tuple.prototype;
+
+assertEq(typeof TuplePrototype.slice, 'function');
+
+assertThrowsInstanceOf(function() { TuplePrototype.slice() }, TypeError,
+ "value of TupleObject must be a Tuple");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/slice/length.js b/js/src/tests/non262/Tuple/prototype/slice/length.js
new file mode 100644
index 0000000000..d0e9359934
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/slice/length.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype.slice, "length");
+assertEq(desc.value, 2);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype.slice, "name");
+assertEq(desc.value, "slice");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype, "slice");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.prototype.slice), false);
+
+assertThrowsInstanceOf(() => {
+ let t = #[1];
+ new t.slice();
+}, TypeError, '`let t = #[1]; new t.slice()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/slice/name.js b/js/src/tests/non262/Tuple/prototype/slice/name.js
new file mode 100644
index 0000000000..19b6957105
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/slice/name.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype.slice, "name");
+assertEq(desc.value, "slice");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/slice/negative-zero.js b/js/src/tests/non262/Tuple/prototype/slice/negative-zero.js
new file mode 100644
index 0000000000..029455c5d0
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/slice/negative-zero.js
@@ -0,0 +1,10 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var sample = #[40,41,42,43];
+
+assertEq(sample.slice(-0), sample);
+assertEq(sample.slice(-0, 4), sample);
+assertEq(sample.slice(0, -0), #[]);
+assertEq(sample.slice(-0, -0), #[]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/slice/not-a-constructor.js b/js/src/tests/non262/Tuple/prototype/slice/not-a-constructor.js
new file mode 100644
index 0000000000..ebd27dd17d
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/slice/not-a-constructor.js
@@ -0,0 +1,10 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+assertEq(isConstructor(Tuple.prototype.slice), false);
+
+assertThrowsInstanceOf(() => {
+ let t = #[1];
+ new t.slice();
+}, TypeError, '`let t = #[1]; new t.slice()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/slice/prop-desc.js b/js/src/tests/non262/Tuple/prototype/slice/prop-desc.js
new file mode 100644
index 0000000000..1eda464d2f
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/slice/prop-desc.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype, "slice");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+assertEq(typeof Tuple.prototype.slice, 'function');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/slice/return-abrupt-from-end.js b/js/src/tests/non262/Tuple/prototype/slice/return-abrupt-from-end.js
new file mode 100644
index 0000000000..9d9f8733a3
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/slice/return-abrupt-from-end.js
@@ -0,0 +1,13 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var o1 = { valueOf: function() { throw new SyntaxError(); } };
+var o2 = { toString: function() { throw new SyntaxError(); } };
+
+var sample = #[];
+
+assertThrowsInstanceOf(() => sample.slice(0, o1),
+ SyntaxError, "valueOf throws");
+assertThrowsInstanceOf(() => sample.slice(0, o2),
+ SyntaxError, "toString throws");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/slice/return-abrupt-from-start.js b/js/src/tests/non262/Tuple/prototype/slice/return-abrupt-from-start.js
new file mode 100644
index 0000000000..0c8b23acf7
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/slice/return-abrupt-from-start.js
@@ -0,0 +1,13 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var o1 = { valueOf: function() { throw new SyntaxError(); } };
+var o2 = { toString: function() { throw new SyntaxError(); } };
+
+var sample = #[];
+
+assertThrowsInstanceOf(() => sample.slice(o1),
+ SyntaxError, "valueOf throws");
+assertThrowsInstanceOf(() => sample.slice(o2),
+ SyntaxError, "toString throws");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/slice/slice.js b/js/src/tests/non262/Tuple/prototype/slice/slice.js
new file mode 100644
index 0000000000..c1d30dfefa
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/slice/slice.js
@@ -0,0 +1,176 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.5 Tuple.prototype.slice ( start, end )
+When the slice method is called with two arguments, start and end, and returns a Tuple containing the elements of the Tuple from element start up to, but not including, element end (or through the end of the tuple if end is undefined). If start is negative, it is treated as length + start where length is the length of the tuple. If end is negative, it is treated as length + end where length is the length of the tuple.
+
+The following steps are taken:
+
+1. Let T be ? thisTupleValue(this value).
+2. Let list be T.[[Sequence]].
+3. Let len be the number of elements in list.
+4. Let relativeStart be ? ToInteger(start).
+5. If relativeStart < 0, let k be max((len + relativeStart), 0); else let k be min(relativeStart, len).
+6. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToInteger(end).
+7. If relativeEnd < 0, let final be max((len + relativeEnd), 0); else let final be min(relativeEnd, len).
+8. Let newList be a new empty List.
+9. Repeat, while k < final,
+a. Let kValue be list[k].
+b. Assert: Type(kValue) is not Object.
+c. Append kValue to the end of newList.
+d. Set k to k + 1.
+10. Return a new Tuple value whose [[Sequence]] is newList.
+*/
+
+/* Step 1 */
+/* slice() should throw on a non-Tuple */
+let method = Tuple.prototype.slice;
+assertEq(method.call(#[1,2,3,4,5,6], 2, 4), #[3,4]);
+assertEq(method.call(Object(#[1,2,3,4,5,6]), 2, 4), #[3,4]);
+assertThrowsInstanceOf(() => method.call("monkeys"), TypeError,
+ "value of TupleObject must be a Tuple");
+assertThrowsInstanceOf(() => method.call(true), TypeError,
+ "value of TupleObject must be a Tuple");
+assertThrowsInstanceOf(() => method.call(false), TypeError,
+ "value of TupleObject must be a Tuple");
+
+
+let tup = #[1,2,3];
+let len = 3;
+/* Step 4 -- toInteger returns 0 for non-integers */
+assertEq(tup.slice("monkeys", 4), tup.slice(0, 4));
+assertThrowsInstanceOf(() => tup.slice(Symbol("1"), 4),
+ TypeError, "can't convert symbol to number");
+assertEq(tup.slice(undefined, 4), tup.slice(0, 4));
+assertEq(tup.slice(undefined), tup.slice(0));
+assertEq(tup.slice(NaN), tup.slice(0));
+assertEq(tup.slice(Number.POSITIVE_INFINITY), tup.slice(len));
+assertEq(tup.slice(Number.NEGATIVE_INFINITY), tup.slice(0));
+assertEq(tup.slice({valueOf: function() { return 0 },
+ toString: function() { return 3 }}),
+ tup.slice(0, 3));
+assertEq(tup.slice(), tup.slice(0));
+
+
+/* Step 5 -- if relativeStart < 0, k should be max((len + relativeStart), 0) */
+/* Case 1: len + relativeStart > 0 */
+var relativeStart = -2;
+assertEq(tup.slice(relativeStart, 4), tup.slice(len + relativeStart, 4));
+/* Case 2: len + relativeStart === 0 */
+relativeStart = (-1 * len);
+assertEq(tup.slice(relativeStart, 4), tup.slice(0, 4));
+/* Case 3: len + relativeStart < 0 */
+relativeStart = -256;
+assertEq(tup.slice(relativeStart, 4), tup.slice(0, 4));
+
+/* Step 5 -- start positive, end positive */
+var tup2 = #[1,2,3,4,5,6,7];
+relativeStart = 2;
+/* length > end > start */
+assertEq(tup2.slice(relativeStart, 4), #[3,4]);
+/* start == len */
+/* length == end == start */
+assertEq(tup2.slice(tup2.length, tup2.length), #[]);
+/* start > len */
+/* start > end == len */
+assertEq(tup2.slice(tup2.length + 5, tup2.length), tup2.slice(tup2.length, tup2.length));
+/* length > end > start = 0 */
+relativeStart = 0;
+assertEq(tup2.slice(relativeStart, 4), #[1,2,3,4]);
+/* length > end == start > 0 */
+relativeStart = 2;
+assertEq(tup2.slice(relativeStart, relativeStart), #[]);
+/* length > start > end > 0 */
+relativeStart = 4;
+relativeEnd = 2;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[]);
+/* length = end > start > 0 */
+relativeEnd = tup2.length;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[5,6,7]);
+/* end > length > start > 0 */
+relativeEnd = tup2.length + 3;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[5,6,7]);
+
+/* length > end == abs(start), start < 0 */
+relativeStart = -4;
+relativeEnd = 4;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[4]);
+/* length == end > abs(start), start < 0 */
+relativeEnd = tup2.length;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[4,5,6,7]);
+/* abs(start) = length > end > 0, start < 0 */
+relativeStart = -1*tup2.length;
+relativeEnd = 5;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[1,2,3,4,5]);
+/* abs(start) > length = end > 0 */
+relativeStart = (-1*tup2.length) - 4;
+relativeEnd = tup2.length;
+assertEq(tup2.slice(relativeStart, relativeEnd), tup2);
+
+/* Step 6 -- if end is undefined, let relativeEnd = len */
+assertEq(tup.slice(2, undefined), tup.slice(2, len));
+assertEq(tup.slice(2), tup.slice(2, len));
+/* relativeEnd converted with toInteger */
+assertEq(tup.slice(2, "monkeys"), tup.slice(2, 0));
+assertThrowsInstanceOf(() => tup.slice(2, Symbol("x")),
+ TypeError, "can't convert Symbol to Number");
+assertEq(tup.slice(2, 2.5), tup.slice(2, 0));
+assertEq(tup.slice(2, NaN), tup.slice(2, 0));
+assertEq(tup.slice(2, Number.POSITIVE_INFINITY), tup.slice(2, len));
+assertEq(tup.slice(2, Number.NEGATIVE_INFINITY), tup.slice(2, 0));
+assertEq(tup.slice(0, Number.POSITIVE_INFINITY), tup.slice(0, len));
+assertEq(tup.slice(0, Number.NEGATIVE_INFINITY), tup.slice(0, 0));
+assertEq(tup.slice({valueOf: function() { return 3 },
+ toString: function() { return 0 }}),
+ tup.slice(0, 0));
+
+/* Step 7 -- if relativeEnd < 0, final should be max((len + relativeEnd), 0) */
+/* Case 1: len + relativeEnd > 0 */
+var relativeEnd = -1;
+relativeStart = 2;
+assertEq(tup.slice(relativeStart, relativeEnd), tup.slice(relativeStart, len + relativeEnd));
+/* Case 2: len + relativeEnd === 0 */
+relativeEnd = (-1 * len);
+assertEq(tup.slice(relativeStart, relativeEnd), tup.slice(relativeStart, 0));
+/* Case 3: len + relativeEnd < 0 */
+relativeEnd = -256;
+assertEq(tup.slice(relativeStart, relativeEnd), tup.slice(relativeStart, 0));
+/* start and end both negative */
+relativeStart = -3;
+relativeEnd = -1;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[5, 6]);
+relativeEnd = (-1*len);
+assertEq(tup2.slice(relativeStart, relativeEnd), #[]);
+relativeEnd = -256;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[]);
+
+/* length > abs(end) > start === 0 */
+relativeStart = 0;
+relativeEnd = -3;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[1,2,3,4]);
+/* length > abs(end) > start > 0 */
+relativeStart = 2;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[3,4]);
+/* length == abs(end) > start == 0 */
+relativeEnd = -1*tup2.length;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[]);
+/* abs(end) > length > start > 0 */
+relativeEnd = (-1*tup2.length) - 5;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[]);
+/* -length == start < end < 0 */
+relativeStart = -1*tup2.length;
+relativeEnd = 5;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[1,2,3,4,5]);
+/* -length < start < end < 0 */
+relativeStart = -3;
+relativeEnd = -1;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[5,6]);
+/* start < -length < end < 0 */
+relativeStart = (-1*tup2.length) - 5;
+relativeEnd = -3;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[1,2,3,4]);
+/* start = end < -length */
+relativeEnd = relativeStart;
+assertEq(tup2.slice(relativeStart, relativeEnd), #[]);
+
+reportCompare(0, 0);
+
diff --git a/js/src/tests/non262/Tuple/prototype/slice/tointeger-end.js b/js/src/tests/non262/Tuple/prototype/slice/tointeger-end.js
new file mode 100644
index 0000000000..a379e5d7d3
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/slice/tointeger-end.js
@@ -0,0 +1,35 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.5
+...
+6. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToInteger(end).
+*/
+
+var obj = {
+ valueOf: function() {
+ return 2;
+ }
+};
+
+
+var sample = #[40, 41, 42, 43];
+
+assertEq(sample.slice(0, false), #[]);
+assertEq(sample.slice(0, true), #[40]);
+
+assertEq(sample.slice(0, NaN), #[]);
+assertEq(sample.slice(0, null), #[]);
+assertEq(sample.slice(0, undefined), #[40, 41, 42, 43]);
+
+assertEq(sample.slice(0, 0.6), #[]);
+assertEq(sample.slice(0, 1.1), #[40]);
+assertEq(sample.slice(0, 1.5), #[40]);
+assertEq(sample.slice(0, -0.6), #[]);
+assertEq(sample.slice(0, -1.1), #[40, 41, 42]);
+assertEq(sample.slice(0, -1.5), #[40, 41, 42]);
+
+assertEq(sample.slice(0, "3"), #[40, 41, 42]);
+
+assertEq(sample.slice(0, obj), #[40, 41]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/slice/tointeger-start.js b/js/src/tests/non262/Tuple/prototype/slice/tointeger-start.js
new file mode 100644
index 0000000000..55a59ad024
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/slice/tointeger-start.js
@@ -0,0 +1,35 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.5
+...
+4. Let relativeStart be ? ToInteger(start).
+*/
+
+var obj = {
+ valueOf: function() {
+ return 2;
+ }
+};
+
+
+var sample = #[40, 41, 42, 43];
+
+assertEq(sample.slice(false), sample);
+assertEq(sample.slice(true), #[41, 42, 43]);
+
+assertEq(sample.slice(NaN), sample);
+assertEq(sample.slice(null), sample);
+assertEq(sample.slice(undefined), sample);
+
+assertEq(sample.slice(0.6), sample);
+assertEq(sample.slice(1.1), #[41, 42, 43]);
+assertEq(sample.slice(1.5), #[41, 42, 43]);
+assertEq(sample.slice(-0.6), sample);
+assertEq(sample.slice(-1.1), #[43]);
+assertEq(sample.slice(-1.5), #[43]);
+
+assertEq(sample.slice("3"), #[43]);
+
+assertEq(sample.slice(obj), #[42, 43]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/slice/tuple-length-internal.js b/js/src/tests/non262/Tuple/prototype/slice/tuple-length-internal.js
new file mode 100644
index 0000000000..f0fff9693e
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/slice/tuple-length-internal.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+/* Ensure that slice uses internal length and not length property */
+
+
+var getCalls = 0;
+var desc = {
+ get: function getLen() {
+ getCalls++;
+ return 0;
+ }
+};
+
+Object.defineProperty(Tuple.prototype, "length", desc);
+
+var sample = Object(#[42, 43]);
+
+var result = sample.slice();
+
+assertEq(getCalls, 0, "ignores length properties");
+assertEq(result, #[42, 43]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toReversed/indexed-setters.js b/js/src/tests/non262/Tuple/prototype/toReversed/indexed-setters.js
new file mode 100644
index 0000000000..a2477d37e3
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toReversed/indexed-setters.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+// If an indexed Array setter is overridden, TupleSplice shouldn't use it
+// when constructing the intermediate array
+
+var z = 5;
+print("1111");
+Object.defineProperty(Array.prototype, '0', { set: function(y) { z = 42; }});
+print("2222");
+let newT = #[1,2,3].toReversed();
+print("3333");
+assertEq(z, 5);
+print("4444");
+
+reportCompare(0, 0);
+
diff --git a/js/src/tests/non262/Tuple/prototype/toReversed/invoked-as-func.js b/js/src/tests/non262/Tuple/prototype/toReversed/invoked-as-func.js
new file mode 100644
index 0000000000..2e2c6facce
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toReversed/invoked-as-func.js
@@ -0,0 +1,10 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var toReversed = Tuple.prototype.toReversed;
+
+assertEq(typeof toReversed, 'function');
+
+assertThrowsInstanceOf(function() {
+ toReversed();
+}, TypeError, "toReversed() invoked as function");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toReversed/invoked-as-method.js b/js/src/tests/non262/Tuple/prototype/toReversed/invoked-as-method.js
new file mode 100644
index 0000000000..4014c97e4f
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toReversed/invoked-as-method.js
@@ -0,0 +1,10 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var TuplePrototype = Tuple.prototype;
+
+assertEq(typeof TuplePrototype.toReversed, 'function');
+
+assertThrowsInstanceOf(function() {
+ TuplePrototype.toReversed();
+}, TypeError, "toReversed() invoked as method");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toReversed/length.js b/js/src/tests/non262/Tuple/prototype/toReversed/length.js
new file mode 100644
index 0000000000..ff4d7e6114
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toReversed/length.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype.toReversed, "length");
+assertEq(desc.value, 0);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype.toReversed, "name");
+assertEq(desc.value, "toReversed");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype, "toReversed");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.prototype.toReversed), false);
+
+assertThrowsInstanceOf(() => {
+ let t = #[1];
+ new t.toReversed();
+}, TypeError, '`let t = #[1]; new t.toReversed()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toReversed/this-is-not-tuple.js b/js/src/tests/non262/Tuple/prototype/toReversed/this-is-not-tuple.js
new file mode 100644
index 0000000000..7df6300533
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toReversed/this-is-not-tuple.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var withReversed = Tuple.prototype.withReversed;
+
+var thisVals = [[undefined, "undefined"],
+ [null, "null"],
+ [42, "42"],
+ ["1", "1"],
+ [true, "true"],
+ [false, "false"],
+ [Symbol("s"), "Symbol(\"s\")"],
+ [[], "[]"],
+ [{}, "{}"]];
+
+for (pair of thisVals) {
+ thisVal = pair[0];
+ errorMsg = "this is: " + pair[1];
+ assertThrowsInstanceOf(() => withReversed.call(thisVal),
+ TypeError, errorMsg);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toReversed/toReversed.js b/js/src/tests/non262/Tuple/prototype/toReversed/toReversed.js
new file mode 100644
index 0000000000..2c672ef1ce
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toReversed/toReversed.js
@@ -0,0 +1,29 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.28 Tuple.prototype.toReversed ( )
+When the toReversed method is called, the following steps are taken:
+
+1. Let T be ? thisTupleValue(this value).
+2. Let oldList be a new List containing the elements of T.[[Sequence]].
+3. Let newList be a new empty List.
+4. Repeat, while oldList is not empty,
+a. Remove the last element from oldList, and let E be the value of the element.
+b. Append E to the end of List newList.
+5. Return a new Tuple value whose [[Sequence]] is newList.
+*/
+/* Step 1 */
+/* toReversed() should throw on a non-Tuple */
+let method = Tuple.prototype.toReversed;
+assertEq(method.call(#[1,2,3,4,5,6]), #[6,5,4,3,2,1]);
+assertEq(method.call(Object(#[1,2,3,4,5,6])), #[6,5,4,3,2,1]);
+assertThrowsInstanceOf(() => method.call("monkeys"), TypeError,
+ "value of TupleObject must be a Tuple");
+
+assertEq(#[].toReversed(), #[]);
+assertEq(#[1].toReversed(), #[1]);
+
+/* Test that length is still handled correctly if it's overridden */
+Object.defineProperty(Tuple.prototype, "length", { get() { return 0 } })
+assertEq(#[1,2,3,4,5].toReversed(), #[5,4,3,2,1]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toSorted/comparefn-call-throws.js b/js/src/tests/non262/Tuple/prototype/toSorted/comparefn-call-throws.js
new file mode 100644
index 0000000000..4442b0d3d5
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSorted/comparefn-call-throws.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+let sample = #[42, 43, 44, 45, 46];
+var calls = 0;
+
+let comparefn = function() {
+ calls += 1;
+ throw new TypeError();
+};
+
+assertThrowsInstanceOf(function() {
+ sample.toSorted(comparefn);
+}, TypeError, "comparefn should throw");
+
+assertEq(calls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toSorted/comparefn-calls.js b/js/src/tests/non262/Tuple/prototype/toSorted/comparefn-calls.js
new file mode 100644
index 0000000000..e8d65b9445
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSorted/comparefn-calls.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var expectedThis = (function() {
+ return this;
+})();
+
+
+var sample = #[42, 42, 42, 42, 42];
+var calls = [];
+
+var comparefn = function() {
+ calls.push([this, arguments]);
+};
+
+let result = sample.toSorted(comparefn);
+
+assertEq(calls.length > 0, true);
+
+calls.forEach(function(args) {
+ assertEq(args[0], expectedThis);
+ assertEq(args[1].length, 2);
+ assertEq(args[1][0], 42);
+ assertEq(args[1][0], 42);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toSorted/comparefn-nonfunction-call-throws.js b/js/src/tests/non262/Tuple/prototype/toSorted/comparefn-nonfunction-call-throws.js
new file mode 100644
index 0000000000..5a68e1d343
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSorted/comparefn-nonfunction-call-throws.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+ 1. If _comparefn_ is not *undefined* and IsCallable(_comparefn_) is *false*, throw a *TypeError* exception.
+ ...
+*/
+
+let sample = #[42, 43, 44, 45, 46];
+
+let compareFnVals = [[null, "null"],
+ [true, "true"],
+ [false, "false"],
+ ['', "\'\'"],
+ [/a/g, "/a/g"],
+ [42, "42"],
+ [[], "[]"],
+ [{}, "{}"]];
+
+for (pair of compareFnVals) {
+ f = pair[0];
+ errorMsg = "comparefn is: " + pair[1];
+ assertThrowsInstanceOf(() => sample.withSorted(f),
+ TypeError, errorMsg);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toSorted/invoked-as-func.js b/js/src/tests/non262/Tuple/prototype/toSorted/invoked-as-func.js
new file mode 100644
index 0000000000..da68b8b8fc
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSorted/invoked-as-func.js
@@ -0,0 +1,10 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var toSorted = Tuple.prototype.toSorted;
+
+assertEq(typeof toSorted, 'function');
+
+assertThrowsInstanceOf(function() {
+ toSorted();
+}, TypeError, "toSorted invoked as function");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toSorted/invoked-as-method.js b/js/src/tests/non262/Tuple/prototype/toSorted/invoked-as-method.js
new file mode 100644
index 0000000000..86fc2e713b
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSorted/invoked-as-method.js
@@ -0,0 +1,10 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var TuplePrototype = Tuple.prototype;
+
+assertEq(typeof TuplePrototype.toSorted, 'function');
+
+assertThrowsInstanceOf(function() {
+ TuplePrototype.toSorted();
+}, TypeError, "toSorted() invoked as method");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toSorted/length.js b/js/src/tests/non262/Tuple/prototype/toSorted/length.js
new file mode 100644
index 0000000000..7a94575ce6
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSorted/length.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype.toSorted, "length");
+assertEq(desc.value, 1);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype.toSorted, "name");
+assertEq(desc.value, "toSorted");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype, "toSorted");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.prototype.toSorted), false);
+
+assertThrowsInstanceOf(() => {
+ let t = #[1];
+ new t.toSorted();
+}, TypeError, '`let t = #[1]; new t.toSorted()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toSorted/sorted-values.js b/js/src/tests/non262/Tuple/prototype/toSorted/sorted-values.js
new file mode 100644
index 0000000000..ecdd349145
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSorted/sorted-values.js
@@ -0,0 +1,29 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var sample;
+
+sample = #[4,3,2,1].toSorted();
+assertEq(sample, #[1,2,3,4]);
+
+sample = #[3, 4, 1, 2].toSorted();
+assertEq(sample, #[1, 2, 3, 4]);
+
+sample = #[3,4,3,1,0,1,2].toSorted();
+assertEq(sample, #[0,1,1,2,3,3,4]);
+
+sample = #[1,0,-0,2].toSorted();
+// This matches the behavior of Array.sort()
+assertEq(sample, #[0,-0,1,2]);
+
+sample = #[-4,3,4,-3,2,-1,1,0].toSorted();
+assertEq(sample, #[-1,-3,-4,0,1,2,3,4]);
+
+sample = #[0.5,0,1.5,1].toSorted();
+assertEq(sample, #[0,0.5,1,1.5]);
+
+sample = #[0.5,0,1.5,-0.5,-1,-1.5,1].toSorted();
+assertEq(sample, #[-0.5,-1,-1.5,0,0.5,1,1.5]);
+
+sample = #[3,4,Infinity,-Infinity,1,2].toSorted();
+assertEq(sample, #[-Infinity,1,2,3,4,Infinity]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toSorted/stability.js b/js/src/tests/non262/Tuple/prototype/toSorted/stability.js
new file mode 100644
index 0000000000..1b2d0eb193
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSorted/stability.js
@@ -0,0 +1,32 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+// Treat 0..3, 4..7, etc. as equal.
+const compare = (a, b) => (a / 4 | 0) - (b / 4 | 0);
+
+// Create a tuple of the form `[0, 1, …, 126, 127]`.
+var tup = Tuple.from({ length: 128 }, (_, i) => i);
+
+const tuple1 = tup;
+assertEq(tuple1.toSorted(compare), tup);
+
+
+// Reverse `tup` so it becomes `[127, 126, …, 1, 0]`.
+tup = tup.toReversed();
+
+const tuple2 = tup;
+assertEq(tuple2.toSorted(compare),
+ #[
+ 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8,
+ 15, 14, 13, 12, 19, 18, 17, 16, 23, 22, 21, 20,
+ 27, 26, 25, 24, 31, 30, 29, 28, 35, 34, 33, 32,
+ 39, 38, 37, 36, 43, 42, 41, 40, 47, 46, 45, 44,
+ 51, 50, 49, 48, 55, 54, 53, 52, 59, 58, 57, 56,
+ 63, 62, 61, 60, 67, 66, 65, 64, 71, 70, 69, 68,
+ 75, 74, 73, 72, 79, 78, 77, 76, 83, 82, 81, 80,
+ 87, 86, 85, 84, 91, 90, 89, 88, 95, 94, 93, 92,
+ 99, 98, 97, 96, 103, 102, 101, 100, 107, 106, 105, 104,
+ 111, 110, 109, 108, 115, 114, 113, 112, 119, 118, 117, 116,
+ 123, 122, 121, 120, 127, 126, 125, 124,
+ ]);
+
+reportCompare(0, 0);
+
diff --git a/js/src/tests/non262/Tuple/prototype/toSorted/this-is-not-tuple.js b/js/src/tests/non262/Tuple/prototype/toSorted/this-is-not-tuple.js
new file mode 100644
index 0000000000..3d1761f08f
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSorted/this-is-not-tuple.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var withSorted = Tuple.prototype.withSorted;
+
+var thisVals = [[undefined, "undefined"],
+ [null, "null"],
+ [42, "42"],
+ ["1", "1"],
+ [true, "true"],
+ [false, "false"],
+ [Symbol("s"), "Symbol(\"s\")"],
+ [[], "[]"],
+ [{}, "{}"]];
+
+for (pair of thisVals) {
+ thisVal = pair[0];
+ errorMsg = "this is: " + pair[1];
+ assertThrowsInstanceOf(() => withSorted.call(thisVal),
+ TypeError, errorMsg);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toSorted/toSorted.js b/js/src/tests/non262/Tuple/prototype/toSorted/toSorted.js
new file mode 100644
index 0000000000..c2d90f06f6
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSorted/toSorted.js
@@ -0,0 +1,36 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.29 Tuple.prototype.toSorted ( compareFn )
+Except as described below, implements the same requirements as those of Array.prototype.sort as defined in 22.1.3.27. The implementation may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.
+
+Upon entry, the following steps are performed to initialize evaluation of the sorted function. These steps are used instead of the entry steps in 22.1.3.27:
+
+1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception.
+2. Let T be ? thisTupleValue(this value).
+3. Let list be a new List containing the elements of T.[[Sequence]].
+4. Let len be the length of list.
+A new Tuple containing the elements from the original Tuple is returned, where the elements are sorted. The sort order is the ordering, after completion of this function, of the elements of list. The sort order of the result of sorted is the same order as if the elements of list were sorted in an Array via %Array.prototype.sort% with comparefn as the first argument.
+
+*/
+/* Step 2 */
+/* toSorted() should throw on a non-Tuple */
+let method = Tuple.prototype.toSorted;
+assertEq(method.call(#[6,5,4,3,2,1]), #[1,2,3,4,5,6]);
+assertEq(method.call(Object(#[6,5,4,3,2,1])), #[1,2,3,4,5,6]);
+assertThrowsInstanceOf(() => method.call("monkeys"), TypeError,
+ "value of TupleObject must be a Tuple");
+
+/* Test that length is still handled correctly if it's overridden */
+Object.defineProperty(Tuple.prototype, "length", { get() { return 0 } })
+assertEq(#[5,4,3,2,1].toSorted(), #[1,2,3,4,5]);
+
+/* Step 1. If comparefn is not undefined... */
+assertEq(#[5,4,3,2,1].toSorted(), #[1,2,3,4,5]);
+assertEq(#[5,4,3,2,1].toSorted(undefined), #[1,2,3,4,5]);
+assertThrowsInstanceOf(() => #[1].toSorted("monkeys"), TypeError,
+ "bad comparefn passed to toSorted");
+let comparefn = (x, y) => x < y;
+assertEq(#[1,2,3,4,5].toSorted(comparefn), #[5,4,3,2,1]);
+
+reportCompare(0, 0);
+
diff --git a/js/src/tests/non262/Tuple/prototype/toSorted/toSortedcompare-with-no-tostring.js b/js/src/tests/non262/Tuple/prototype/toSorted/toSortedcompare-with-no-tostring.js
new file mode 100644
index 0000000000..68b5774d61
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSorted/toSortedcompare-with-no-tostring.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/* description: Tuple toSorted does cast values to String */
+
+var toStringCalled = false;
+Number.prototype.toString = function() {
+ toStringCalled = true;
+}
+
+let sample = #[20, 100, 3];
+let result = sample.toSorted();
+assertEq(toStringCalled, false);
+assertEq(result, #[100, 20, 3]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toSorted/tuplelength-internal.js b/js/src/tests/non262/Tuple/prototype/toSorted/tuplelength-internal.js
new file mode 100644
index 0000000000..8353eaea11
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSorted/tuplelength-internal.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/* Use internal length rather than getting a length property */
+var getCalls = 0;
+var desc = {
+ get: function getLen() {
+ getCalls++;
+ return 0;
+ }
+};
+
+var internalLength = Object.getOwnPropertyDescriptor(Tuple.prototype, "length").get;
+Object.defineProperty(Tuple.prototype, "length", desc);
+
+let sample = #[42,42,42];
+
+getCalls = 0;
+
+var result = sample.toSorted();
+
+assertEq(getCalls, 0)
+assertEq(result, sample);
+assertEq(result[0], sample[0]);
+assertEq(result[1], sample[1]);
+assertEq(result[2], sample[2]);
+assertEq(result.length, 0);
+assertEq(internalLength.call(result), 3);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toSpliced/indexed-setters.js b/js/src/tests/non262/Tuple/prototype/toSpliced/indexed-setters.js
new file mode 100644
index 0000000000..ce2fc39954
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSpliced/indexed-setters.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+// If an indexed Array setter is overridden, TupleSplice shouldn't use it
+// when constructing the intermediate array
+
+var z = 5;
+print("1111");
+Object.defineProperty(Array.prototype, '0', { set: function(y) { z = 42; }});
+print("2222");
+let newT = #[1,2,3].toSpliced(0, 2);
+print("3333");
+assertEq(z, 5);
+print("4444");
+
+reportCompare(0, 0);
+
diff --git a/js/src/tests/non262/Tuple/prototype/toSpliced/length.js b/js/src/tests/non262/Tuple/prototype/toSpliced/length.js
new file mode 100644
index 0000000000..a95d957533
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSpliced/length.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype.toSpliced, "length");
+assertEq(desc.value, 2);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype.toSpliced, "name");
+assertEq(desc.value, "toSpliced");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype, "toSpliced");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.prototype.toSpliced), false);
+
+assertThrowsInstanceOf(() => {
+ let t = #[1];
+ new t.toSpliced();
+}, TypeError, '`let t = #[1]; new t.toSpliced()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toSpliced/toSpliced.js b/js/src/tests/non262/Tuple/prototype/toSpliced/toSpliced.js
new file mode 100644
index 0000000000..dd5ccdfcbf
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toSpliced/toSpliced.js
@@ -0,0 +1,254 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.30 Tuple.prototype.toSpliced ( start, deleteCount, ...items )
+When the toSpliced method is called with two or more arguments start, deleteCount and zero or more items, a new Tuple is returned where the deleteCount elements of the Tuple starting at integer index start are replaced by the arguments items.
+
+The following steps are taken:
+
+1. Let T be ? thisTupleValue(this value).
+2. Let list be T.[[Sequence]].
+3. Let len be the number of elements in list.
+4. Let relativeStart be ? ToInteger(start).
+5. If relativeStart < 0, let actualStart be max((len + relativeStart), 0); else let actualStart be min(relativeStart, len).
+6. If the number of actual arguments is 0, then
+a. Let insertCount be 0.
+b. Let actualDeleteCount be 0.
+7. Else if the number of actual arguments is 1, then
+a. Let insertCount be 0.
+b. Let actualDeleteCount be len - actualStart.
+8. Else,
+a. Let insertCount be the number of actual arguments minus 2.
+b. Let dc be ? ToInteger(deleteCount).
+c. Let actualDeleteCount be min(max(dc, 0), len - actualStart).
+9. If len + insertCount - actualDeleteCount > 253 - 1, throw a TypeError exception.
+10. Let k be 0.
+11. Let items be a List whose elements are, in left to right order, the portion of the actual argument list starting with the third argument. The list is empty if fewer than three arguments were passed.
+12. Let itemCount be the number of elements in items.
+13. Let newList be a new empty List.
+14. Repeat, while k < actualStart,
+a. Let E be list[k].
+b. Append E to the end of list newList.
+c. Set k to k + 1.
+15. Let itemK be 0.
+16. Repeat, while itemK < itemCount.
+a. Let E be items[itemK].
+b. If Type(E) is Object, throw a TypeError exception.
+c. Append E to the end of newList.
+d. Set itemK to itemK + 1.
+17. Set k to actualStart + actualDeleteCount.
+18. Repeat, while k < len,
+a. Let E be list[k].
+b. Append E to the end of newList.
+c. Set k to k + 1.
+19. Return a new Tuple value whose [[Sequence]] is newList.
+*/
+/* Step 1 */
+/* toSpliced() should throw on a non-Tuple */
+let method = Tuple.prototype.toSpliced;
+assertEq(method.call(#[1,2,3,4,5,6], 2, 3), #[1,2,6]);
+assertEq(method.call(Object(#[1,2,3,4,5,6]),2,3), #[1,2,6]);
+assertThrowsInstanceOf(() => method.call("monkeys"), TypeError,
+ "value of TupleObject must be a Tuple");
+assertThrowsInstanceOf(() => method.call(true), TypeError,
+ "value of TupleObject must be a Tuple");
+assertThrowsInstanceOf(() => method.call(false), TypeError,
+ "value of TupleObject must be a Tuple");
+
+/* method does not access constructor */
+var t = #[];
+t.constructor = null;
+var result = t.toSpliced(0, 0);
+assertEq(result, #[]);
+assertEq(Object.getPrototypeOf(result), Tuple.prototype);
+
+/* Step 3 */
+/* Test that length is still handled correctly if it's overridden */
+Object.defineProperty(Tuple.prototype, "length", { get() { return 0 } })
+assertEq(#[1,2,3,4,5].toSpliced(1, 2), #[1,4,5]);
+
+var tup = #[1,2,3];
+var len = 3;
+/* Step 4 -- toInteger returns 0 for non-integers */
+assertEq(tup.toSpliced("monkeys", 2), tup.toSpliced(0, 2));
+assertEq(tup.toSpliced(undefined, 2), tup.toSpliced(0, 2));
+assertEq(tup.toSpliced(undefined), tup.toSpliced(0, len));
+assertEq(tup.toSpliced(), tup.slice(0));
+
+/* Step 5 */
+/* relativeStart < 0, len + relativeStart > 0 */
+var relativeStart = -1;
+var result = tup.toSpliced(relativeStart, 1);
+assertEq(result, tup.toSpliced(len + relativeStart, 1));
+assertEq(result, #[1,2]);
+/* relativeStart < 0, len + relativeStart < 0 */
+relativeStart = -4;
+result = tup.toSpliced(relativeStart, 1);
+assertEq(result, tup.toSpliced(0, 1));
+assertEq(result, #[2,3]);
+/* relativeStart < 0, len + relativeStart === 0 */
+relativeStart = -3;
+result = tup.toSpliced(relativeStart, 1);
+assertEq(result, tup.toSpliced(0, 1));
+/* relativeStart === 0 */
+relativeStart = 0;
+result = tup.toSpliced(relativeStart, 2);
+assertEq(result, #[3]);
+/* relativeStart > 0, relativeStart < len */
+relativeStart = 2;
+result = tup.toSpliced(relativeStart, 1);
+assertEq(result, #[1,2]);
+/* relativeStart > 0, relativeStart > len */
+relativeStart = 5;
+result = tup.toSpliced(relativeStart, 1);
+assertEq(result, tup.toSpliced(len, 1));
+assertEq(result, tup);
+/* relativeStart > 0, relativeStart === len */
+relativeStart = len;
+result = tup.toSpliced(relativeStart, 1);
+assertEq(result, tup);
+
+/* Step 6 - no arguments */
+result = tup.toSpliced();
+assertEq(result, tup.toSpliced(0, 0));
+assertEq(result, tup);
+
+/* Step 7 -- 1 argument */
+result = tup.toSpliced(1);
+assertEq(result, tup.toSpliced(1, len - 1));
+assertEq(result, #[1]);
+
+/* Step 8 */
+/* 2 arguments */
+/* insertCount = 0 */
+/* (a) deleteCount = non-integer */
+assertEq(tup.toSpliced(1, "monkeys"), tup.toSpliced(1, 0));
+assertEq(tup.toSpliced(1, undefined), tup.toSpliced(1, 0));
+assertEq(tup.toSpliced(1, true), tup.toSpliced(1, 1));
+/* (b) deleteCount < 0, len - actualStart > 0 */
+result = tup.toSpliced(1, -1);
+assertEq(result, tup.toSpliced(1, 0));
+assertEq(result, tup);
+/* (c) deleteCount < 0, len - actualStart === 0 */
+result = tup.toSpliced(3, -1);
+assertEq(result, tup.toSpliced(3, 0));
+assertEq(result, tup);
+/* (d) deleteCount < 0, len - actualStart < 0 */
+/* Step 5 guarantees this case can't happen */
+/* (e) deleteCount === 0 */
+assertEq(tup.toSpliced(1, 0), tup);
+/* (f) deleteCount > 0, deleteCount < (len - actualStart) */
+var tup2 = #[1,2,3,4,5];
+var tup2_len = 5;
+result = tup2.toSpliced(1, 3);
+assertEq(result, #[1, 5]);
+/* (g) deleteCount > 0, deleteCount > (len - actualStart) */
+var actualStart = 3;
+result = tup2.toSpliced(actualStart, 4);
+assertEq(result, tup2.toSpliced(actualStart, tup2_len - actualStart));
+assertEq(result, #[1,2,3]);
+/* 3 arguments */
+assertEq(tup2.toSpliced(1, "bunnies", "monkeys"), tup2.toSpliced(1, 0, "monkeys")); // (a)
+assertEq(tup2.toSpliced(1, -1, "monkeys"), tup2.toSpliced(1, 0, "monkeys")); // (b)
+assertEq(tup2.toSpliced(tup2_len, -1, "monkeys"), tup2.toSpliced(tup2_len, 0, "monkeys")); // (c)
+assertEq(tup2.toSpliced(2, 0, "monkeys"), #[1, 2, "monkeys", 3, 4, 5]); // (e)
+assertEq(tup2.toSpliced(1, 3, "monkeys"), #[1, "monkeys", 5]); // (f)
+assertEq(tup2.toSpliced(3, 4, "monkeys"), #[1, 2, 3, "monkeys"]); // (g)
+/* 4 arguments */
+assertEq(tup2.toSpliced(1, "monkeys", 42, 17), tup2.toSpliced(1, 0, 42, 17)); // (a)
+assertEq(tup2.toSpliced(1, -1, 42, 17), tup2.toSpliced(1, 0, 42, 17)); // (b)
+assertEq(tup2.toSpliced(tup2_len, -1, 42, 17), tup2.toSpliced(tup2_len, 0, 42, 17)); // (c)
+assertEq(tup2.toSpliced(2, 0, 42, 17), #[1, 2, 42, 17, 3, 4, 5]); // (e)
+assertEq(tup2.toSpliced(1, 3, 42, 17), #[1, 42, 17, 5]); // (f)
+assertEq(tup2.toSpliced(3, 4, 42, 17), #[1, 2, 3, 42, 17]); // (g)
+
+/* Step 9 */
+/* If len + insertCount - actualDeleteCount > 2^53 - 1, throw a TypeError exception.
+ Not sure how to test the error case without constructing a tuple with length 2^53 */
+
+/* Steps 14-18 */
+/* each combination of:
+ actualStart = 0, actualStart = 1, actualStart = 4
+ itemCount = 0, itemCount = 1, itemCount = 4
+ actualStart + actualDeleteCount = len, actualStart + actualDeleteCount < len */
+
+/* actualStart = 0, itemCount = 0, actualDeleteCount = len */
+var tup = #[1,2,3,4,5,6];
+var len = 6;
+var actualStart;
+var actualDeleteCount;
+actualStart = 0;
+actualDeleteCount = len;
+assertEq(tup.toSpliced(actualStart, actualDeleteCount), #[]);
+
+/* actualStart = 0, itemCount = 1, actualDeleteCount = len */
+actualStart = 0;
+actualDeleteCount = len;
+assertEq(tup.toSpliced(actualStart, actualDeleteCount, "monkeys"), #["monkeys"]);
+
+/* actualStart = 0, itemCount = 4, actualDeleteCount = len */
+assertEq(tup.toSpliced(actualStart, actualDeleteCount, "a", "b", "c", "d"), #["a", "b", "c", "d"]);
+
+/* actualStart = 0, itemCount = 0, actualDeleteCount < len */
+actualDeleteCount = 3;
+assertEq(tup.toSpliced(actualStart, actualDeleteCount), #[4, 5, 6]);
+
+/* actualStart = 0, itemCount = 1, actualDeleteCount < len */
+assertEq(tup.toSpliced(actualStart, actualDeleteCount, "monkeys"), #["monkeys", 4, 5, 6]);
+
+/* actualStart = 0, itemCount = 4, actualDeleteCount < len */
+assertEq(tup.toSpliced(actualStart, actualDeleteCount, 42, 43, 44, 45), #[42, 43, 44, 45, 4, 5, 6]);
+
+/* actualStart = 1, itemCount = 0, actualDeleteCount = len - 1 */
+actualStart = 1;
+actualDeleteCount = len - 1;
+assertEq(tup.toSpliced(actualStart, actualDeleteCount), #[1]);
+
+/* actualStart = 1, itemCount = 1, actualDeleteCount = len - 1 */
+assertEq(tup.toSpliced(actualStart, actualDeleteCount, "monkeys"), #[1, "monkeys"]);
+
+/* actualStart = 1, itemCount = 4, actualDeleteCount = len - 1 */
+assertEq(tup.toSpliced(actualStart, actualDeleteCount, 0.0, 0.1, 0.2, 0.3), #[1, 0.0, 0.1, 0.2, 0.3]);
+
+/* actualStart = 1, itemCount = 0, actualDeleteCount < len - 1 */
+actualDeleteCount = 1;
+assertEq(tup.toSpliced(actualStart, actualDeleteCount), #[1, 3, 4, 5, 6]);
+
+/* actualStart = 1, itemCount = 1, actualDeleteCount < len - 1 */
+assertEq(tup.toSpliced(actualStart, actualDeleteCount, "monkeys"), #[1, "monkeys", 3, 4, 5, 6]);
+
+/* actualStart = 1, itemCount = 4, actualDeleteCount < len - 1 */
+assertEq(tup.toSpliced(actualStart, actualDeleteCount, 8, 9, 10, 11), #[1, 8, 9, 10, 11, 3, 4, 5, 6]);
+
+/* actualStart = 4, itemCount = 0, actualDeleteCount = len - 4 */
+actualStart = 4;
+actualDeleteCount = len - 4;
+assertEq(tup.toSpliced(actualStart, actualDeleteCount), #[1, 2, 3, 4]);
+
+/* actualStart = 4, itemCount = 1, actualDeleteCount = len - 4 */
+assertEq(tup.toSpliced(actualStart, actualDeleteCount, "monkeys"), #[1, 2, 3, 4, "monkeys"]);
+
+/* actualStart = 4, itemCount = 4, actualDeleteCount = len - 4 */
+assertEq(tup.toSpliced(actualStart, actualDeleteCount, 0, -1, -2, -3), #[1, 2, 3, 4, 0, -1, -2, -3]);
+
+/* actualStart = 4, itemCount = 0, actualDeleteCount < len - 4 */
+actualDeleteCount = 1;
+assertEq(tup.toSpliced(actualStart, actualDeleteCount), #[1, 2, 3, 4, 6]);
+
+/* actualStart = 4, itemCount = 1, actualDeleteCount < len - 4 */
+assertEq(tup.toSpliced(actualStart, actualDeleteCount, "monkeys"), #[1, 2, 3, 4, "monkeys", 6]);
+
+/* actualStart = 4, itemCount = 4, actualDeleteCount < len - 4 */
+assertEq(tup.toSpliced(actualStart, actualDeleteCount, "p", "q", "r", "s"), #[1, 2, 3, 4, "p", "q", "r", "s", 6]);
+
+/* Step 16.b -- item is Object */
+assertThrowsInstanceOf(() => tup.toSpliced(actualStart, actualDeleteCount, []),
+ TypeError, "Tuple can't contain Object");
+assertThrowsInstanceOf(() => tup.toSpliced(actualStart, actualDeleteCount, [], 2, 3),
+ TypeError, "Tuple can't contain Object");
+assertThrowsInstanceOf(() => tup.toSpliced(actualStart, actualDeleteCount, 2, new Object(), 3),
+ TypeError, "Tuple can't contain Object");
+assertThrowsInstanceOf(() => tup.toSpliced(actualStart, actualDeleteCount, 2, 3, {"a": "b"}),
+ TypeError, "Tuple can't contain Object");
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toString/length.js b/js/src/tests/non262/Tuple/prototype/toString/length.js
new file mode 100644
index 0000000000..1a12340df3
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toString/length.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+var desc = Object.getOwnPropertyDescriptor(Tuple.prototype.toString, "length");
+assertEq(desc.value, 0);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype.toString, "name");
+assertEq(desc.value, "toString");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+desc = Object.getOwnPropertyDescriptor(Tuple.prototype, "toString");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.prototype.toString), false);
+
+assertThrowsInstanceOf(() => {
+ let t = #[1];
+ new t.toString();
+}, TypeError, '`let t = #[1]; new t.toString()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/toString/to-string.js b/js/src/tests/non262/Tuple/prototype/toString/to-string.js
new file mode 100644
index 0000000000..e600ca78a2
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/toString/to-string.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/* Step 1 */
+/* toString() should throw on a non-Tuple */
+let method = Tuple.prototype.toString;
+assertEq(method.call(#[1,2,3,4,5,6]), "1,2,3,4,5,6");
+assertEq(method.call(Object(#[1,2,3,4,5,6])), "1,2,3,4,5,6");
+assertThrowsInstanceOf(() => method.call("monkeys"), TypeError,
+ "value of TupleObject must be a Tuple");
+
+// Normal case
+assertEq(#[].toString(), "");
+assertEq(#[1].toString(), "1");
+assertEq(#[1,2].toString(), "1,2");
+
+// if join method isn't callable, Object.toString should be called
+Tuple.prototype.join = 7;
+var t = #[1,2,3];
+assertEq(t.toString(), "[object Tuple]");
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/valueOf/length.js b/js/src/tests/non262/Tuple/prototype/valueOf/length.js
new file mode 100644
index 0000000000..1865563514
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/valueOf/length.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+var desc = Object.getOwnPropertyDescriptor(Tuple.valueOf, "length");
+assertEq(desc.value, 0);
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(isConstructor(Tuple.valueOf), false);
+
+assertThrowsInstanceOf(() => {
+ new Tuple.valueOf([]);
+}, TypeError, '`new Tuple.valueOf()` throws TypeError');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/valueOf/name.js b/js/src/tests/non262/Tuple/prototype/valueOf/name.js
new file mode 100644
index 0000000000..b20e121479
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/valueOf/name.js
@@ -0,0 +1,9 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+desc = Object.getOwnPropertyDescriptor(Tuple.valueOf, "name");
+assertEq(desc.value, "valueOf");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/valueOf/valueOf.js b/js/src/tests/non262/Tuple/prototype/valueOf/valueOf.js
new file mode 100644
index 0000000000..967f7fac3c
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/valueOf/valueOf.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.3 Tuple.prototype.valueOf ( )
+When the valueOf function is called, the following steps are taken:
+
+1. Return ? thisTupleValue(this value).
+*/
+
+var valueOf = Tuple.prototype.valueOf;
+assertEq(typeof valueOf, 'function');
+
+var tup = #[1,2,3];
+assertEq(valueOf.call(tup), tup);
+assertEq(valueOf.call(Object(tup)), tup);
+assertThrowsInstanceOf(() => valueOf.call("monkeys"), TypeError,
+ "this is not Tuple");
+assertThrowsInstanceOf(() => valueOf.call({}), TypeError,
+ "this is not Tuple");
+assertThrowsInstanceOf(() => valueOf.call(new Object(1)), TypeError,
+ "this is not Tuple");
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/prototype/with/with.js b/js/src/tests/non262/Tuple/prototype/with/with.js
new file mode 100644
index 0000000000..d4f8c4d62b
--- /dev/null
+++ b/js/src/tests/non262/Tuple/prototype/with/with.js
@@ -0,0 +1,68 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+8.2.3.31 Tuple.prototype.with ( index, value )
+When the with method is called with two arguments, it returns a new Tuple with the element at index index replaced with value value.
+
+1. Let T be ? thisTupleValue(this value).
+2. Let list be a new List containing the elements of T.[[Sequence]].
+3. Let length be the length of list list.
+4. Let I be ? ToIndex(index).
+5. If I ≥ length, throw a RangeError exception.
+6. If Type(value) is Object, throw a TypeError exception.
+7. Set list[I] to value.
+8. Return a new Tuple value whose [[Sequence]] is list.
+*/
+/* Step 1 */
+/* with() should throw on a non-Tuple */
+let method = Tuple.prototype.with;
+assertEq(method.call(#[1,2,3], 1, "monkeys"), #[1, "monkeys", 3]);
+assertEq(method.call(Object(#[1,2,3]), 1, "monkeys"), #[1, "monkeys", 3]);
+assertThrowsInstanceOf(() => method.call("monkeys"), TypeError,
+ "value of TupleObject must be a Tuple");
+assertThrowsInstanceOf(() => method.call(true), TypeError,
+ "value of TupleObject must be a Tuple");
+assertThrowsInstanceOf(() => method.call(false), TypeError,
+ "value of TupleObject must be a Tuple");
+
+/* method does not access constructor */
+var t = #[1];
+t.constructor = null;
+var result = t.with(0, 0);
+assertEq(result, #[0]);
+assertEq(Object.getPrototypeOf(result), Tuple.prototype);
+
+/* Step 3 */
+/* Test that length is still handled correctly if it's overridden */
+Object.defineProperty(Tuple.prototype, "length", { get() { return 0 } })
+assertEq(#[1,2,3,4,5].with(1, 5), #[1,5,3,4,5]);
+
+var tup = #[1,2,3];
+var len = 3;
+/* Step 4 -- toIndex returns 0 for non-integers */
+assertEq(tup.with("monkeys", 2), tup.with(0, 2));
+assertEq(tup.with(undefined, 2), tup.with(0, 2));
+assertEq(tup.with(undefined), tup.with(0, undefined));
+assertEq(tup.with(), tup.with(0, undefined));
+
+/* Step 5 */
+assertThrowsInstanceOf(() => tup.with(-5, "monkeys"),
+ RangeError, "index out of range");
+assertThrowsInstanceOf(() => tup.with(Number.MAX_SAFE_INTEGER, "monkeys"),
+ RangeError, "index out of range");
+assertThrowsInstanceOf(() => tup.with(len + 5, "monkeys"),
+ RangeError, "index out of range");
+
+/* Step 6 -- item is Object */
+assertThrowsInstanceOf(() => tup.with(1, []),
+ TypeError, "Tuple can't contain Object");
+assertThrowsInstanceOf(() => tup.with(0, new Object()),
+ TypeError, "Tuple can't contain Object");
+assertThrowsInstanceOf(() => tup.with(2, {'a': 'b'}),
+ TypeError, "Tuple can't contain Object");
+
+/* Step 8 */
+assertEq(tup.with(0, "monkeys"), #["monkeys", 2, 3]);
+assertEq(tup.with(1, #['a', 'b', 'c']), #[1, #['a', 'b', 'c'], 3]);
+assertEq(tup.with(2, 42), #[1, 2, 42]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/shell.js b/js/src/tests/non262/Tuple/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Tuple/shell.js
diff --git a/js/src/tests/non262/Tuple/syntax.js b/js/src/tests/non262/Tuple/syntax.js
new file mode 100644
index 0000000000..826e8adbdf
--- /dev/null
+++ b/js/src/tests/non262/Tuple/syntax.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+
+Reflect.parse("#[]");
+Reflect.parse("#[ foo ]");
+Reflect.parse("#[ foo, ]");
+Reflect.parse("#[ foo, bar ]");
+Reflect.parse("#[ foo, ...bar ]");
+Reflect.parse("#[ foo, ...bar, ]");
+Reflect.parse("#[ foo, ...bar, baz ]");
+Reflect.parse("#[ foo() ]");
+
+assertThrowsInstanceOf(() => Reflect.parse("#[,]"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("#[ foo, , bar ]"), SyntaxError);
+assertThrowsInstanceOf(() => Reflect.parse("#[ foo ] = bar"), SyntaxError);
+
+if (typeof reportCompare === "function") reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/type-errors.js b/js/src/tests/non262/Tuple/type-errors.js
new file mode 100644
index 0000000000..2b5373a3a6
--- /dev/null
+++ b/js/src/tests/non262/Tuple/type-errors.js
@@ -0,0 +1,31 @@
+// |reftest| skip-if(!this.hasOwnProperty("Tuple"))
+/*
+3.1.2 ToNumber ( argument )
+The abstract operation ToNumber takes argument argument. It converts argument to a value of type Number according to Table 2:
+
+...
+Tuple Throw a TypeError exception.
+...
+*/
+assertThrowsInstanceOf(() => #[1, 2] + 3, TypeError,
+ "cannot convert record or tuple to number");
+assertThrowsInstanceOf(() => 3 + #[1, 2], TypeError,
+ "cannot convert record or tuple to number");
+assertThrowsInstanceOf(() => 3 - #[1, 2], TypeError,
+ "cannot convert record or tuple to number");
+assertThrowsInstanceOf(() => 3 * #[1, 2], TypeError,
+ "cannot convert record or tuple to number");
+assertThrowsInstanceOf(() => 3 / #[1, 2], TypeError,
+ "cannot convert record or tuple to number");
+assertThrowsInstanceOf(() => #[1, 2] > #[1, 3], TypeError,
+ "cannot convert record or tuple to number");
+assertThrowsInstanceOf(() => #[1, 2] < #[1, 3], TypeError,
+ "cannot convert record or tuple to number");
+assertThrowsInstanceOf(() => #[1, 2] >= #[1, 3], TypeError,
+ "cannot convert record or tuple to number");
+assertThrowsInstanceOf(() => #[1, 2] <= #[1, 3], TypeError,
+ "cannot convert record or tuple to number");
+
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/non262/Tuple/wrapper.js b/js/src/tests/non262/Tuple/wrapper.js
new file mode 100644
index 0000000000..3cb0a42154
--- /dev/null
+++ b/js/src/tests/non262/Tuple/wrapper.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("Record"))
+
+var boxO = Object(#[1, 2, 3]);
+
+assertEq(Object.isExtensible(boxO), false);
+assertEq(Object.isSealed(boxO), true);
+assertEq(Object.isFrozen(boxO), true);
+
+boxO[0] = 3;
+assertEq(boxO[0], 1);
+assertThrowsInstanceOf(() => { "use strict"; boxO[0] = 3; }, TypeError);
+assertEq(boxO[0], 1);
+
+boxO[4] = 3;
+assertEq(boxO[4], undefined);
+assertThrowsInstanceOf(() => { "use strict"; boxO[4] = 3; }, TypeError);
+assertEq(boxO[4], undefined);
+
+assertThrowsInstanceOf(() => { Object.defineProperty(boxO, "0", { value: 3 }); }, TypeError);
+assertEq(boxO[0], 1);
+
+assertThrowsInstanceOf(() => { Object.defineProperty(boxO, "4", { value: 3 }); }, TypeError);
+assertEq(boxO[4], undefined);
+
+if (typeof reportCompare === "function") reportCompare(0, 0);