summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/Tuple/from
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /js/src/tests/non262/Tuple/from
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-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
37 files changed, 895 insertions, 0 deletions
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);