summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/arrays
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/arrays')
-rw-r--r--js/src/jit-test/tests/arrays/apply-optimization.js58
-rw-r--r--js/src/jit-test/tests/arrays/ion-pop-denseinitializedlength-less-than-length.js49
-rw-r--r--js/src/jit-test/tests/arrays/ion-pop-nonwritable-length.js48
-rw-r--r--js/src/jit-test/tests/arrays/ion-push-nonwritable-length.js61
-rw-r--r--js/src/jit-test/tests/arrays/ion-shift-nonwritable-length.js59
-rw-r--r--js/src/jit-test/tests/arrays/length-set-after-define-nonconfigurable.js7
-rw-r--r--js/src/jit-test/tests/arrays/length-set-after-has-sparse.js9
-rw-r--r--js/src/jit-test/tests/arrays/new-array-int-undefined-args.js2
-rw-r--r--js/src/jit-test/tests/arrays/new-array-undefined-undefined-more-args-1.js6
-rw-r--r--js/src/jit-test/tests/arrays/new-array-undefined-undefined-more-args-2.js6
-rw-r--r--js/src/jit-test/tests/arrays/nonwritable-length-grow-capacity.js2
-rw-r--r--js/src/jit-test/tests/arrays/pop-nonarray-nonwritable-length.js13
-rw-r--r--js/src/jit-test/tests/arrays/pop-nonwritable-length-denseinitializedlength-below-length.js49
-rw-r--r--js/src/jit-test/tests/arrays/push-densely-loopy-nonwritable-length.js56
-rw-r--r--js/src/jit-test/tests/arrays/push-densely-nonwritable-length.js31
-rw-r--r--js/src/jit-test/tests/arrays/push-slowly-loopy-nonwritable-length.js51
-rw-r--r--js/src/jit-test/tests/arrays/push-slowly-nonwritable-length.js24
-rw-r--r--js/src/jit-test/tests/arrays/reverse-frozen.js6
-rw-r--r--js/src/jit-test/tests/arrays/reverse-nonarray-nonwritable-element.js13
-rw-r--r--js/src/jit-test/tests/arrays/setelem-one-past-nonwritable-length.js20
-rw-r--r--js/src/jit-test/tests/arrays/slice-sparse-getter.js12
-rw-r--r--js/src/jit-test/tests/arrays/slice.js37
-rw-r--r--js/src/jit-test/tests/arrays/sort-getter-only.js29
-rw-r--r--js/src/jit-test/tests/arrays/splice-nonwritable-length.js53
-rw-r--r--js/src/jit-test/tests/arrays/std_Array-prototype.js6
-rw-r--r--js/src/jit-test/tests/arrays/too-long-array-splice.js6
-rw-r--r--js/src/jit-test/tests/arrays/unshift-nonwritable-length.js61
27 files changed, 774 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/arrays/apply-optimization.js b/js/src/jit-test/tests/arrays/apply-optimization.js
new file mode 100644
index 000000000..fc62da910
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/apply-optimization.js
@@ -0,0 +1,58 @@
+function make(k) {
+ var a = new Array(k);
+ for ( let i=0 ; i < k ; i++ )
+ a[i] = {}
+ return a;
+}
+
+function g() {
+ return arguments.length;
+}
+
+function f(a) {
+ var sum = 0;
+ for ( let i=0 ; i < 1000 ; i++ )
+ sum += g.apply(null, a);
+ return sum;
+}
+
+function F2() {
+ var sum = 0;
+ for ( let i=0 ; i < 1000 ; i++ )
+ sum += g.apply(null, arguments);
+ return sum;
+}
+
+function F(a) {
+ return F2.apply(null, a);
+}
+
+function time(k, t) {
+ var then = Date.now();
+ assertEq(t(), 1000*k);
+ var now = Date.now();
+ return now - then;
+}
+
+function p(v) {
+ // Uncomment to see timings
+ // print(v);
+}
+
+f(make(200));
+
+// There is currently a cutoff after 375 where we bailout in order to avoid
+// handling very large stack frames. This slows the operation down by a factor
+// of 100 or so.
+
+p(time(374, () => f(make(374))));
+p(time(375, () => f(make(375))));
+p(time(376, () => f(make(376))));
+p(time(377, () => f(make(377))));
+
+F(make(200));
+
+p(time(374, () => F(make(374))));
+p(time(375, () => F(make(375))));
+p(time(376, () => F(make(376))));
+p(time(377, () => F(make(377))));
diff --git a/js/src/jit-test/tests/arrays/ion-pop-denseinitializedlength-less-than-length.js b/js/src/jit-test/tests/arrays/ion-pop-denseinitializedlength-less-than-length.js
new file mode 100644
index 000000000..9f4bda023
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/ion-pop-denseinitializedlength-less-than-length.js
@@ -0,0 +1,49 @@
+load(libdir + "asserts.js");
+
+function f(arr)
+{
+ arr.pop();
+}
+
+var N = 100;
+
+function test()
+{
+ // Create an array of arrays, to be iterated over for [].pop-calling. We
+ // can't just loop on pop on a single array with non-writable length because
+ // pop throws when called on an array with non-writable length.
+ var arrs = [];
+ for (var i = 0; i < N; i++)
+ arrs.push([0, 1, 2, 3]);
+
+ // Test Ion-pop where dense initialized length < length.
+ var a = [0, 1, 2];
+ a.length = 4;
+
+ arrs.push(a);
+
+ for (var i = 0, sz = arrs.length; i < sz; i++)
+ f(arrs[i]);
+
+ return arrs;
+}
+
+var arrs = test();
+assertEq(arrs.length, N + 1);
+for (var i = 0; i < N; i++)
+{
+ assertEq(arrs[i].length, 3, "unexpected length for arrs[" + i + "]");
+ assertEq(arrs[i][0], 0, "bad element for arrs[" + i + "][0]");
+ assertEq(arrs[i][1], 1, "bad element for arrs[" + i + "][1]");
+ assertEq(arrs[i][2], 2, "bad element for arrs[" + i + "][2]");
+ assertEq(3 in arrs[i], false, "shouldn't be a third element");
+ assertEq(arrs[i][3], undefined);
+}
+
+var a = arrs[N];
+assertEq(a.length, 3, "unexpected length for arrs[" + i + "]");
+assertEq(a[0], 0, "bad element for arrs[" + i + "][0]");
+assertEq(a[1], 1, "bad element for arrs[" + i + "][1]");
+assertEq(a[2], 2, "bad element for arrs[" + i + "][2]");
+assertEq(3 in a, false, "shouldn't be a third element");
+assertEq(a[3], undefined);
diff --git a/js/src/jit-test/tests/arrays/ion-pop-nonwritable-length.js b/js/src/jit-test/tests/arrays/ion-pop-nonwritable-length.js
new file mode 100644
index 000000000..acecd0a2c
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/ion-pop-nonwritable-length.js
@@ -0,0 +1,48 @@
+load(libdir + "asserts.js");
+
+function f(arr)
+{
+ arr.pop();
+}
+
+var N = 100;
+
+function test(out)
+{
+ // Create an array of arrays, to be iterated over for [].pop-calling. We
+ // can't just loop on pop on a single array with non-writable length because
+ // pop throws when called on an array with non-writable length.
+ var arrs = out.arrs = [];
+ for (var i = 0; i < N; i++)
+ arrs.push([0, 1, 2, 3]);
+
+ // Use a much-greater capacity than the eventual non-writable length.
+ var a = [0, 1, 2, 3, 4, 5, 6, 7];
+ Object.defineProperty(a, "length", { writable: false, value: 4 });
+
+ arrs.push(a);
+
+ for (var i = 0, sz = arrs.length; i < sz; i++)
+ f(arrs[i]);
+}
+
+var obj = {};
+
+assertThrowsInstanceOf(function() { test(obj); }, TypeError);
+
+var arrs = obj.arrs;
+assertEq(arrs.length, N + 1);
+for (var i = 0; i < N; i++)
+{
+ assertEq(arrs[i].length, 3, "unexpected length for arrs[" + i + "]");
+ assertEq(arrs[i][0], 0, "bad element for arrs[" + i + "][0]");
+ assertEq(arrs[i][1], 1, "bad element for arrs[" + i + "][1]");
+ assertEq(arrs[i][2], 2, "bad element for arrs[" + i + "][2]");
+ assertEq(3 in arrs[i], false, "shouldn't be a third element");
+ assertEq(arrs[i][3], undefined);
+}
+
+var a = arrs[N];
+assertEq(a.hasOwnProperty(3), false, "should have been deleted before throw");
+assertEq(a[3], undefined);
+assertEq(a.length, 4, "length shouldn't have been changed");
diff --git a/js/src/jit-test/tests/arrays/ion-push-nonwritable-length.js b/js/src/jit-test/tests/arrays/ion-push-nonwritable-length.js
new file mode 100644
index 000000000..514910316
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/ion-push-nonwritable-length.js
@@ -0,0 +1,61 @@
+function f(arr)
+{
+ assertEq(arr.push(4), 5); // if it doesn't throw :-)
+}
+
+function test(out)
+{
+ // Create an array of arrays, to be iterated over for [].push-calling. We
+ // can't just loop on push on a single array with non-writable length because
+ // push throws when called on an array with non-writable length.
+ var arrs = out.arrs = [];
+ for (var i = 0; i < 100; i++)
+ arrs.push([0, 1, 2, 3]);
+
+ // Use a much-greater capacity than the eventual non-writable length, so that
+ // the inline-push will work.
+ var a = [0, 1, 2, 3, 4, 5, 6, 7];
+ Object.defineProperty(a, "length", { writable: false, value: 4 });
+
+ arrs.push(a);
+
+ for (var i = 0, sz = arrs.length; i < sz; i++)
+ {
+ var arr = arrs[i];
+ f(arr);
+ }
+}
+
+var obj = {};
+var a, arrs;
+
+try
+{
+ test(obj);
+ throw new Error("didn't throw!");
+}
+catch (e)
+{
+ assertEq(e instanceof TypeError, true, "expected TypeError, got " + e);
+
+ arrs = obj.arrs;
+ assertEq(arrs.length, 101);
+ for (var i = 0; i < 100; i++)
+ {
+ assertEq(arrs[i].length, 5, "unexpected length for arrs[" + i + "]");
+ assertEq(arrs[i][0], 0, "bad element for arrs[" + i + "][0]");
+ assertEq(arrs[i][1], 1, "bad element for arrs[" + i + "][1]");
+ assertEq(arrs[i][2], 2, "bad element for arrs[" + i + "][2]");
+ assertEq(arrs[i][3], 3, "bad element for arrs[" + i + "][3]");
+ assertEq(arrs[i][4], 4, "bad element for arrs[" + i + "][4]");
+ }
+
+ a = arrs[100];
+ assertEq(a[0], 0, "bad element for a[" + i + "]");
+ assertEq(a[1], 1, "bad element for a[" + i + "]");
+ assertEq(a[2], 2, "bad element for a[" + i + "]");
+ assertEq(a[3], 3, "bad element for a[" + i + "]");
+ assertEq(a.hasOwnProperty(4), false, "element addition should have thrown");
+ assertEq(a[4], undefined);
+ assertEq(a.length, 4, "length shouldn't have been changed");
+}
diff --git a/js/src/jit-test/tests/arrays/ion-shift-nonwritable-length.js b/js/src/jit-test/tests/arrays/ion-shift-nonwritable-length.js
new file mode 100644
index 000000000..119271f20
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/ion-shift-nonwritable-length.js
@@ -0,0 +1,59 @@
+function f(arr)
+{
+ assertEq(arr.shift(), 0);
+}
+
+function test(out)
+{
+ // Create an array of arrays, to be iterated over for [].shift-calling. We
+ // can't just loop on shift on a single array with non-writable length because
+ // shift throws when called on an array with non-writable length.
+ var arrs = out.arrs = [];
+ for (var i = 0; i < 100; i++)
+ arrs.push([0, 1, 2, 3]);
+
+ // Use a much-greater capacity than the eventual non-writable length.
+ var a = [0, 1, 2, 3, 4, 5, 6, 7];
+ Object.defineProperty(a, "length", { writable: false, value: 4 });
+
+ arrs.push(a);
+
+ for (var i = 0, sz = arrs.length; i < sz; i++)
+ {
+ var arr = arrs[i];
+ f(arr);
+ }
+}
+
+var obj = {};
+var a, arrs;
+
+try
+{
+ test(obj);
+ throw new Error("didn't throw!");
+}
+catch (e)
+{
+ assertEq(e instanceof TypeError, true, "expected TypeError, got " + e);
+
+ arrs = obj.arrs;
+ assertEq(arrs.length, 101);
+ for (var i = 0; i < 100; i++)
+ {
+ assertEq(arrs[i].length, 3, "unexpected length for arrs[" + i + "]");
+ assertEq(arrs[i][0], 1, "bad element for arrs[" + i + "][0]");
+ assertEq(arrs[i][1], 2, "bad element for arrs[" + i + "][1]");
+ assertEq(arrs[i][2], 3, "bad element for arrs[" + i + "][2]");
+ assertEq(3 in arrs[i], false, "shouldn't be a third element");
+ assertEq(arrs[i][3], undefined);
+ }
+
+ a = arrs[100];
+ assertEq(a[0], 1, "bad element for a[" + i + "]");
+ assertEq(a[1], 2, "bad element for a[" + i + "]");
+ assertEq(a[2], 3, "bad element for a[" + i + "]");
+ assertEq(a.hasOwnProperty(3), false, "should have been deleted before throw");
+ assertEq(a[3], undefined);
+ assertEq(a.length, 4, "length shouldn't have been changed");
+}
diff --git a/js/src/jit-test/tests/arrays/length-set-after-define-nonconfigurable.js b/js/src/jit-test/tests/arrays/length-set-after-define-nonconfigurable.js
new file mode 100644
index 000000000..384154056
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/length-set-after-define-nonconfigurable.js
@@ -0,0 +1,7 @@
+var arr = [1];
+Object.defineProperty(arr, 1, { value: undefined, configurable: false });
+
+// no particular reason for 9 -- just enough to trigger property-cache code,
+// maybe start JITting a little
+for (var y = 0; y < 9; y++)
+ arr.length = 1;
diff --git a/js/src/jit-test/tests/arrays/length-set-after-has-sparse.js b/js/src/jit-test/tests/arrays/length-set-after-has-sparse.js
new file mode 100644
index 000000000..44e662661
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/length-set-after-has-sparse.js
@@ -0,0 +1,9 @@
+var arr = [];
+Object.defineProperty(arr, 4, {
+ configurable: true,
+ enumerable: false,
+ writable: false,
+ value: undefined
+});
+for (var y = 0; y < 2; y++)
+ arr.length = 0;
diff --git a/js/src/jit-test/tests/arrays/new-array-int-undefined-args.js b/js/src/jit-test/tests/arrays/new-array-int-undefined-args.js
new file mode 100644
index 000000000..56ac8e64d
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/new-array-int-undefined-args.js
@@ -0,0 +1,2 @@
+for (var i = 0; i < 1e4; i++)
+ assertEq(new Array(0, undefined).length, 2, "bad, i: " + i);
diff --git a/js/src/jit-test/tests/arrays/new-array-undefined-undefined-more-args-1.js b/js/src/jit-test/tests/arrays/new-array-undefined-undefined-more-args-1.js
new file mode 100644
index 000000000..e4a9e1a88
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/new-array-undefined-undefined-more-args-1.js
@@ -0,0 +1,6 @@
+for (var i = 0; i < 1e4; i++)
+{
+ assertEq(typeof new Array(undefined, undefined, 1, 2, 3, 4).sort()[0],
+ "number",
+ "bad, i: " + i);
+}
diff --git a/js/src/jit-test/tests/arrays/new-array-undefined-undefined-more-args-2.js b/js/src/jit-test/tests/arrays/new-array-undefined-undefined-more-args-2.js
new file mode 100644
index 000000000..cf8150493
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/new-array-undefined-undefined-more-args-2.js
@@ -0,0 +1,6 @@
+for (var i = 0; i < 1e4; i++)
+{
+ assertEq(new Array(undefined, undefined, 1, 2, 3, 4).length,
+ 6,
+ "bad, i: " + i);
+}
diff --git a/js/src/jit-test/tests/arrays/nonwritable-length-grow-capacity.js b/js/src/jit-test/tests/arrays/nonwritable-length-grow-capacity.js
new file mode 100644
index 000000000..160689bea
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/nonwritable-length-grow-capacity.js
@@ -0,0 +1,2 @@
+var arr = Object.defineProperty([], "length", { writable: false, value: 12 });
+arr[11] = true;
diff --git a/js/src/jit-test/tests/arrays/pop-nonarray-nonwritable-length.js b/js/src/jit-test/tests/arrays/pop-nonarray-nonwritable-length.js
new file mode 100644
index 000000000..22a5b706b
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/pop-nonarray-nonwritable-length.js
@@ -0,0 +1,13 @@
+// Array.prototype.pop does a strict assignment to this.length even if the
+// caller is nonstrict. Bug 886087.
+
+load(libdir + "asserts.js");
+
+// obj.length is read-only
+var obj = {pop: [].pop, 0: "zero"};
+Object.defineProperty(obj, "length", {configurable: true, value: 1, writable: false});
+assertThrowsInstanceOf(() => obj.pop(), TypeError);
+
+// obj.length has only a getter
+obj = {pop: [].pop, 0: "zero", get length() { return 1; }};
+assertThrowsInstanceOf(() => obj.pop(), TypeError);
diff --git a/js/src/jit-test/tests/arrays/pop-nonwritable-length-denseinitializedlength-below-length.js b/js/src/jit-test/tests/arrays/pop-nonwritable-length-denseinitializedlength-below-length.js
new file mode 100644
index 000000000..9330f775b
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/pop-nonwritable-length-denseinitializedlength-below-length.js
@@ -0,0 +1,49 @@
+load(libdir + "asserts.js");
+
+function f(arr)
+{
+ assertEq(arr.pop(), undefined); // if it doesn't throw
+}
+
+var N = 100;
+
+function basic(out)
+{
+ // Create an array of arrays, to be iterated over for [].pop-calling. We
+ // can't just loop on pop on a single array with non-writable length because
+ // pop throws when called on an array with non-writable length.
+ var arrs = out.arrs = [];
+ for (var i = 0; i < N; i++)
+ {
+ var arr = [0, 1, 2, 3, 4];
+ arr.length = 6;
+ arrs.push(arr);
+ }
+
+ var a = [0, 1, 2, 3, 4];
+ Object.defineProperty(a, "length", { writable: false, value: 6 });
+
+ arrs.push(a);
+
+ for (var i = 0, sz = arrs.length; i < sz; i++)
+ f(arrs[i]);
+}
+
+var obj = {};
+var arrs, a;
+
+assertThrowsInstanceOf(function() { basic(obj); }, TypeError);
+
+var arrs = obj.arrs;
+assertEq(arrs.length, N + 1);
+for (var i = 0; i < N; i++)
+{
+ assertEq(arrs[i].length, 5, "unexpected length for arrs[" + i + "]");
+ assertEq(arrs[i].hasOwnProperty(5), false,
+ "element not deleted for arrs[" + i + "]");
+}
+
+var a = arrs[N];
+assertEq(a.hasOwnProperty(5), false);
+assertEq(a[5], undefined);
+assertEq(a.length, 6);
diff --git a/js/src/jit-test/tests/arrays/push-densely-loopy-nonwritable-length.js b/js/src/jit-test/tests/arrays/push-densely-loopy-nonwritable-length.js
new file mode 100644
index 000000000..e09ed0964
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/push-densely-loopy-nonwritable-length.js
@@ -0,0 +1,56 @@
+// Force recognition of a known-constant.
+var push = Array.prototype.push;
+
+function f(arr)
+{
+ // Push an actual constant to trigger JIT-inlining of the effect of the push.
+ push.call(arr, 99);
+}
+
+function basic(out)
+{
+ // Create an array of arrays, to be iterated over for [].push-calling. We
+ // can't just loop on push on a single array with non-writable length because
+ // push throws when called on an array with non-writable length.
+ var arrs = out.arrs = [];
+ for (var i = 0; i < 100; i++)
+ arrs.push([]);
+
+ // Use a much-greater capacity than the eventual non-writable length.
+ var a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
+ Object.defineProperty(a, "length", { writable: false, value: 6 });
+
+ arrs.push(a);
+
+ for (var i = 0, sz = arrs.length; i < sz; i++)
+ {
+ var arr = arrs[i];
+ f(arr);
+ }
+}
+
+var obj = {};
+var arrs, a;
+
+try
+{
+ basic(obj);
+ throw new Error("didn't throw!");
+}
+catch (e)
+{
+ assertEq(e instanceof TypeError, true, "expected TypeError, got " + e);
+
+ arrs = obj.arrs;
+ assertEq(arrs.length, 101);
+ for (var i = 0; i < 100; i++)
+ {
+ assertEq(arrs[i].length, 1, "unexpected length for arrs[" + i + "]");
+ assertEq(arrs[i][0], 99, "bad element for arrs[" + i + "]");
+ }
+
+ a = arrs[100];
+ assertEq(a.hasOwnProperty(6), false);
+ assertEq(a[6], undefined);
+ assertEq(a.length, 6);
+}
diff --git a/js/src/jit-test/tests/arrays/push-densely-nonwritable-length.js b/js/src/jit-test/tests/arrays/push-densely-nonwritable-length.js
new file mode 100644
index 000000000..9c26661cb
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/push-densely-nonwritable-length.js
@@ -0,0 +1,31 @@
+function f(arr, v)
+{
+ arr.push(v);
+}
+
+function basic(out)
+{
+ // Use a much-greater capacity than the eventual non-writable length.
+ var a = out.a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
+ Object.defineProperty(a, "length", { writable: false, value: 6 });
+
+ f(a, 99);
+}
+
+var obj = {};
+var a;
+
+try
+{
+ basic(obj);
+ throw new Error("didn't throw!");
+}
+catch (e)
+{
+ assertEq(e instanceof TypeError, true, "expected TypeError, got " + e);
+
+ a = obj.a;
+ assertEq(a.hasOwnProperty(6), false);
+ assertEq(a[6], undefined);
+ assertEq(a.length, 6);
+}
diff --git a/js/src/jit-test/tests/arrays/push-slowly-loopy-nonwritable-length.js b/js/src/jit-test/tests/arrays/push-slowly-loopy-nonwritable-length.js
new file mode 100644
index 000000000..79d858715
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/push-slowly-loopy-nonwritable-length.js
@@ -0,0 +1,51 @@
+load(libdir + "asserts.js");
+
+function f(arr, v1, v2)
+{
+ // Ensure array_push_slowly is called by passing more than one argument.
+ arr.push(v1, v2);
+}
+
+var N = 100;
+
+function test(out)
+{
+ // Create an array of arrays, to be iterated over for [].push-calling. We
+ // can't just loop on push on a single array with non-writable length because
+ // push throws when called on an array with non-writable length.
+ var arrs = out.arrs = [];
+ for (var i = 0; i < N; i++)
+ arrs.push([]);
+
+ // Use a much-greater capacity than the eventual non-writable length.
+ var a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
+ Object.defineProperty(a, "length", { writable: false, value: 6 });
+
+ arrs.push(a);
+
+ for (var i = 0, sz = arrs.length; i < sz; i++)
+ {
+ var arr = arrs[i];
+ f(arr, 8675309, 3141592);
+ }
+}
+
+var obj = {};
+
+assertThrowsInstanceOf(function() { test(obj); }, TypeError);
+
+var arrs = obj.arrs;
+assertEq(arrs.length, N + 1);
+for (var i = 0; i < N; i++)
+{
+ assertEq(arrs[i].length, 2, "unexpected length for arrs[" + i + "]");
+ assertEq(arrs[i][0], 8675309, "bad element for arrs[" + i + "][0]");
+ assertEq(arrs[i][1], 3141592, "bad element for arrs[" + i + "][1]");
+}
+
+var a = arrs[N];
+assertEq(a.hasOwnProperty(6), false);
+assertEq(a[6], undefined);
+assertEq(a.hasOwnProperty(7), false);
+assertEq(a[7], undefined);
+assertEq(a.length, 6);
diff --git a/js/src/jit-test/tests/arrays/push-slowly-nonwritable-length.js b/js/src/jit-test/tests/arrays/push-slowly-nonwritable-length.js
new file mode 100644
index 000000000..9cfc45584
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/push-slowly-nonwritable-length.js
@@ -0,0 +1,24 @@
+load(libdir + "asserts.js");
+
+function f(arr, v1, v2)
+{
+ // Ensure array_push_slowly is called by passing more than one argument.
+ arr.push(v1, v2);
+}
+
+function basic()
+{
+ // Use a much-greater capacity than the eventual non-writable length.
+ var a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
+ Object.defineProperty(a, "length", { writable: false, value: 6 });
+
+ assertThrowsInstanceOf(() => f(a, 8675309, 3141592), TypeError);
+
+ assertEq(a.hasOwnProperty(6), false);
+ assertEq(a[6], undefined);
+ assertEq(a.hasOwnProperty(7), false);
+ assertEq(a[7], undefined);
+ assertEq(a.length, 6);
+}
+
+basic();
diff --git a/js/src/jit-test/tests/arrays/reverse-frozen.js b/js/src/jit-test/tests/arrays/reverse-frozen.js
new file mode 100644
index 000000000..d2f32b78d
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/reverse-frozen.js
@@ -0,0 +1,6 @@
+// |jit-test| error: TypeError
+
+x = [0];
+x.length = 9;
+Object.freeze(x);
+x.reverse();
diff --git a/js/src/jit-test/tests/arrays/reverse-nonarray-nonwritable-element.js b/js/src/jit-test/tests/arrays/reverse-nonarray-nonwritable-element.js
new file mode 100644
index 000000000..bca75a96b
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/reverse-nonarray-nonwritable-element.js
@@ -0,0 +1,13 @@
+// Array.prototype.reverse does a strict assignment to this.length even if the
+// caller is nonstrict. Bug 886087.
+
+load(libdir + "asserts.js");
+
+// obj[1] is read-only
+var obj = {0: "zero", length: 2, reverse: [].reverse};
+Object.defineProperty(obj, "1", {configurable: true, value: "one", writable: false});
+assertThrowsInstanceOf(() => obj.reverse(), TypeError);
+
+// obj[1] has only a getter
+Object.defineProperty(obj, "1", {configurable: true, get: () => "one"});
+assertThrowsInstanceOf(() => obj.reverse(), TypeError);
diff --git a/js/src/jit-test/tests/arrays/setelem-one-past-nonwritable-length.js b/js/src/jit-test/tests/arrays/setelem-one-past-nonwritable-length.js
new file mode 100644
index 000000000..7ea5971c0
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/setelem-one-past-nonwritable-length.js
@@ -0,0 +1,20 @@
+function f(arr, i, v)
+{
+ arr[i] = v;
+}
+
+function test()
+{
+ // Use a much-greater capacity than the eventual non-writable length.
+ var a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
+ Object.defineProperty(a, "length", { writable: false, value: 6 });
+
+ for (var i = 0; i < 100; i++)
+ f(a, a.length, i);
+
+ assertEq(a.hasOwnProperty(6), false);
+ assertEq(a[6], undefined);
+ assertEq(a.length, 6);
+}
+
+test();
diff --git a/js/src/jit-test/tests/arrays/slice-sparse-getter.js b/js/src/jit-test/tests/arrays/slice-sparse-getter.js
new file mode 100644
index 000000000..9416349ce
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/slice-sparse-getter.js
@@ -0,0 +1,12 @@
+// Indexed getters can add new properties that slice should not ignore.
+var arr = [];
+Object.defineProperty(arr, 10000, {get: function() {
+ arr[10001] = 4;
+ return 3;
+}});
+arr[10010] = 6;
+
+var res = arr.slice(8000);
+assertEq(res[2000], 3);
+assertEq(res[2001], 4);
+assertEq(res[2010], 6);
diff --git a/js/src/jit-test/tests/arrays/slice.js b/js/src/jit-test/tests/arrays/slice.js
new file mode 100644
index 000000000..ad4f66f63
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/slice.js
@@ -0,0 +1,37 @@
+let invoked = false;
+Object.defineProperty(Array.prototype, '0', {set: function () {
+ invoked = true;
+}});
+
+let result = [1, 2, 3].slice(1);
+assertEq(invoked, false);
+
+let proxy = new Proxy({}, {
+ get: function (target, name, proxy) {
+ switch (name) {
+ case "length":
+ return 2;
+ case "0":
+ return 15;
+ case "1":
+ // Should not invoke [[Get]] for this hole.
+ default:
+ assertEq(false, true);
+ }
+ },
+ has: function (target, name) {
+ switch (name) {
+ case "0":
+ return true;
+ case "1":
+ return false;
+ default:
+ assertEq(false, true);
+ }
+ }
+})
+result = Array.prototype.slice.call(proxy, 0);
+assertEq(result.length, 2);
+assertEq(0 in result, true);
+assertEq(1 in result, false);
+assertEq(result[0], 15);
diff --git a/js/src/jit-test/tests/arrays/sort-getter-only.js b/js/src/jit-test/tests/arrays/sort-getter-only.js
new file mode 100644
index 000000000..d17e8556d
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/sort-getter-only.js
@@ -0,0 +1,29 @@
+// The property assignments in Array.prototype.sort are strict assignments.
+
+load(libdir + "asserts.js");
+
+var a = ["A", , "B", "C", "D"];
+var normalArrayElementDesc = Object.getOwnPropertyDescriptor(a, 0);
+var getterDesc = {
+ get: function () { return "F"; },
+ set: undefined,
+ enumerable: true,
+ configurable: false
+};
+Object.defineProperty(a, 1, getterDesc);
+
+// a.sort is permitted to try to delete a[1] or to try to assign a[1], but it
+// must try one or the other. Either one will fail, throwing a TypeError.
+assertThrowsInstanceOf(() => a.sort(), TypeError);
+
+// a.sort() is not permitted to delete the nonconfigurable property.
+assertDeepEq(Object.getOwnPropertyDescriptor(a, 1), getterDesc);
+
+// The values left in the other elements of a are unspecified; some or all may
+// have been deleted.
+for (var i = 0; i < a.length; i++) {
+ if (i !== 1 && a.hasOwnProperty(i)) {
+ normalArrayElementDesc.value = a[i];
+ assertDeepEq(Object.getOwnPropertyDescriptor(a, i), normalArrayElementDesc);
+ }
+}
diff --git a/js/src/jit-test/tests/arrays/splice-nonwritable-length.js b/js/src/jit-test/tests/arrays/splice-nonwritable-length.js
new file mode 100644
index 000000000..233eb027b
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/splice-nonwritable-length.js
@@ -0,0 +1,53 @@
+load(libdir + "asserts.js");
+
+function f(arr)
+{
+ assertEq(arr.splice(1, 2, 9, 8, 7, 6).length, 2); // if it doesn't throw :-)
+}
+
+var N = 100;
+
+function test(out)
+{
+ // Create an array of arrays, to be iterated over for [].splice-calling.
+ var arrs = out.arrs = [];
+ for (var i = 0; i < N; i++)
+ arrs.push([0, 1, 2, 3]);
+
+ // Use a much-greater capacity than the eventual non-writable length, just for
+ // variability.
+ var a = [0, 1, 2, 3, 4, 5, 6, 7];
+ Object.defineProperty(a, "length", { writable: false, value: 4 });
+
+ arrs.push(a);
+
+ for (var i = 0, sz = arrs.length; i < sz; i++)
+ f(arrs[i]);
+}
+
+var obj = {};
+assertThrowsInstanceOf(function() { test(obj); }, TypeError);
+
+var arrs = obj.arrs;
+assertEq(arrs.length, N + 1);
+for (var i = 0; i < N; i++)
+{
+ assertEq(arrs[i].length, 6, "unexpected length for arrs[" + i + "]");
+ assertEq(arrs[i][0], 0, "bad element for arrs[" + i + "][0]");
+ assertEq(arrs[i][1], 9, "bad element for arrs[" + i + "][1]");
+ assertEq(arrs[i][2], 8, "bad element for arrs[" + i + "][2]");
+ assertEq(arrs[i][3], 7, "bad element for arrs[" + i + "][3]");
+ assertEq(arrs[i][4], 6, "bad element for arrs[" + i + "][4]");
+ assertEq(arrs[i][5], 3, "bad element for arrs[" + i + "][5]");
+}
+
+var a = arrs[N];
+assertEq(a[0], 0, "bad element for a[0]");
+assertEq(a[1], 1, "bad element for a[1]");
+assertEq(a[2], 2, "bad element for a[2]");
+assertEq(a[3], 3, "bad element for a[3]");
+assertEq(a.hasOwnProperty(4), false, "shouldn't have added any elements");
+assertEq(a[4], undefined);
+assertEq(a.hasOwnProperty(5), false, "shouldn't have added any elements");
+assertEq(a[5], undefined);
+assertEq(a.length, 4, "length shouldn't have been changed");
diff --git a/js/src/jit-test/tests/arrays/std_Array-prototype.js b/js/src/jit-test/tests/arrays/std_Array-prototype.js
new file mode 100644
index 000000000..89ebde5d0
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/std_Array-prototype.js
@@ -0,0 +1,6 @@
+Object.prototype.prototype = {};
+assertEq(Object.getPrototypeOf([].concat()), Array.prototype);
+assertEq(Object.getPrototypeOf([].map(x => x)), Array.prototype);
+assertEq(Object.getPrototypeOf([].filter(x => x)), Array.prototype);
+assertEq(Object.getPrototypeOf([].slice()), Array.prototype);
+assertEq(Object.getPrototypeOf([].splice()), Array.prototype);
diff --git a/js/src/jit-test/tests/arrays/too-long-array-splice.js b/js/src/jit-test/tests/arrays/too-long-array-splice.js
new file mode 100644
index 000000000..7e3f9386c
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/too-long-array-splice.js
@@ -0,0 +1,6 @@
+// |jit-test| allow-oom
+// array.splice should throw if array.length is too large.
+
+var length = 4294967295;
+var array = new Array(length);
+array.splice(100);
diff --git a/js/src/jit-test/tests/arrays/unshift-nonwritable-length.js b/js/src/jit-test/tests/arrays/unshift-nonwritable-length.js
new file mode 100644
index 000000000..db95c5f2e
--- /dev/null
+++ b/js/src/jit-test/tests/arrays/unshift-nonwritable-length.js
@@ -0,0 +1,61 @@
+load(libdir + "asserts.js");
+
+function f(arr)
+{
+ assertEq(arr.unshift(3, 5, 7, 9), 8); // if it doesn't throw :-)
+}
+
+var N = 100;
+
+function test(out)
+{
+ // Create an array of arrays, to be iterated over for [].unshift-calling. We
+ // can't just loop on unshift on a single array with non-writable length
+ // because unshift throws when called on an array with non-writable length.
+ var arrs = out.arrs = [];
+ for (var i = 0; i < N; i++)
+ arrs.push([0, 1, 2, 3]);
+
+ // Use a much-greater capacity than the eventual non-writable length, just for
+ // variability.
+ var a = [0, 1, 2, 3, 4, 5, 6, 7];
+ Object.defineProperty(a, "length", { writable: false, value: 4 });
+
+ arrs.push(a);
+
+ for (var i = 0, sz = arrs.length; i < sz; i++)
+ f(arrs[i]);
+}
+
+var obj = {};
+assertThrowsInstanceOf(function() { test(obj); }, TypeError);
+
+var arrs = obj.arrs;
+assertEq(arrs.length, N + 1);
+for (var i = 0; i < N; i++)
+{
+ assertEq(arrs[i].length, 8, "unexpected length for arrs[" + i + "]");
+ assertEq(arrs[i][0], 3, "bad element for arrs[" + i + "][0]");
+ assertEq(arrs[i][1], 5, "bad element for arrs[" + i + "][1]");
+ assertEq(arrs[i][2], 7, "bad element for arrs[" + i + "][2]");
+ assertEq(arrs[i][3], 9, "bad element for arrs[" + i + "][3]");
+ assertEq(arrs[i][4], 0, "bad element for arrs[" + i + "][4]");
+ assertEq(arrs[i][5], 1, "bad element for arrs[" + i + "][5]");
+ assertEq(arrs[i][6], 2, "bad element for arrs[" + i + "][6]");
+ assertEq(arrs[i][7], 3, "bad element for arrs[" + i + "][7]");
+}
+
+var a = arrs[N];
+assertEq(a[0], 0, "bad element for a[0]");
+assertEq(a[1], 1, "bad element for a[1]");
+assertEq(a[2], 2, "bad element for a[2]");
+assertEq(a[3], 3, "bad element for a[3]");
+assertEq(a.hasOwnProperty(4), false, "shouldn't have added any elements");
+assertEq(a[4], undefined);
+assertEq(a.hasOwnProperty(5), false, "shouldn't have added any elements");
+assertEq(a[5], undefined);
+assertEq(a.hasOwnProperty(6), false, "shouldn't have added any elements");
+assertEq(a[6], undefined);
+assertEq(a.hasOwnProperty(7), false, "shouldn't have added any elements");
+assertEq(a[7], undefined);
+assertEq(a.length, 4, "length shouldn't have been changed");