diff --git a/js/src/jit-test/tests/basic/shifted-elements1.js b/js/src/jit-test/tests/basic/shifted-elements1.js new file mode 100644 index 000000000..ee001c5e3 --- /dev/null +++ b/js/src/jit-test/tests/basic/shifted-elements1.js @@ -0,0 +1,14 @@ +function f() { + var arr = []; + var iters = 1500; + for (var i = 0; i < iters; i++) { + arr.push(i); + if (i % 2 === 0) + assertEq(arr.shift(), i / 2); + } + assertEq(arr.length, iters / 2); + for (var i = iters / 2; i < iters; i++) + assertEq(arr.shift(), i); + assertEq(arr.length, 0); +} +f(); diff --git a/js/src/jit-test/tests/basic/shifted-elements2.js b/js/src/jit-test/tests/basic/shifted-elements2.js new file mode 100644 index 000000000..f989db154 --- /dev/null +++ b/js/src/jit-test/tests/basic/shifted-elements2.js @@ -0,0 +1,22 @@ +// Always use the per-element barrier. +gczeal(12); + +function f() { + var arr = []; + for (var i = 0; i < 1000; i++) + arr.push(i); + gc(); // Ensure arr is tenured. + + // Now store a nursery object somewhere in the array, shift elements, + // trigger a GC, and check the post barrier kept the object alive. + for (var i = 0; i < 20; i++) + arr.shift(); + for (var i = 0; i < 40; i++) + arr[900] = {x: i}; + for (var i = 0; i < 10; i++) + arr.shift(); + gc(); + + assertEq(arr[890].x, 39); +} +f(); diff --git a/js/src/jit-test/tests/basic/shifted-elements3.js b/js/src/jit-test/tests/basic/shifted-elements3.js new file mode 100644 index 000000000..6bbe296fa --- /dev/null +++ b/js/src/jit-test/tests/basic/shifted-elements3.js @@ -0,0 +1,23 @@ +// Always use the per-element barrier. +gczeal(12); + +function f() { + var arr = []; + for (var i = 0; i < 1000; i++) + arr.push(i); + gc(); // Ensure arr is tenured. + + for (var i = 0; i < 10; i++) + arr.shift(); + + // Add a nursery object, shift all elements, and trigger a GC to ensure + // the post barrier doesn't misbehave. + for (var j = 0; j < 40; j++) + arr[500] = {x: j}; + while (arr.length > 0) + arr.shift(); + + gc(); + return arr; +} +f(); diff --git a/js/src/jit-test/tests/basic/shifted-elements4.js b/js/src/jit-test/tests/basic/shifted-elements4.js new file mode 100644 index 000000000..59bd83608 --- /dev/null +++ b/js/src/jit-test/tests/basic/shifted-elements4.js @@ -0,0 +1,11 @@ +function f() { + var arr = []; + for (var i = 0; i < 2; i++) { + for (var j = 0; j < 90000; j++) + arr.push(j); + for (var j = 0; j < 90000; j++) + assertEq(arr.shift(), j); + assertEq(arr.length, 0); + } +} +f(); diff --git a/js/src/jit-test/tests/basic/shifted-elements5.js b/js/src/jit-test/tests/basic/shifted-elements5.js new file mode 100644 index 000000000..07e0bce5b --- /dev/null +++ b/js/src/jit-test/tests/basic/shifted-elements5.js @@ -0,0 +1,39 @@ +function testFreeze() { + var arr = []; + for (var i = 0; i < 20; i++) + arr.push(i); + for (var i = 0; i < 10; i++) + arr.shift(); + Object.freeze(arr); + assertEq(arr.length, 10); + arr[0] = -1; + assertEq(arr[0], 10); +} +testFreeze(); +testFreeze(); + +function testCopyOnWrite() { + var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + for (var i = 0; i < 5; i++) + assertEq(arr.shift(), i + 1); + assertEq(arr.toString(), "6,7,8,9"); +} +testCopyOnWrite(); +testCopyOnWrite(); + +function testNonWritableLength() { + var arr = []; + for (var i = 0; i < 20; i++) + arr.push(i); + Object.defineProperty(arr, "length", {writable: false, value: arr.length}); + var ex; + try { + arr.shift(); + } catch(e) { + ex = e; + } + assertEq(ex instanceof TypeError, true); + assertEq(arr.length, 20); +} +testNonWritableLength(); +testNonWritableLength(); diff --git a/js/src/jit-test/tests/basic/shifted-elements6.js b/js/src/jit-test/tests/basic/shifted-elements6.js new file mode 100644 index 000000000..671e49325 --- /dev/null +++ b/js/src/jit-test/tests/basic/shifted-elements6.js @@ -0,0 +1,17 @@ +// Test incremental GC slices and shifted elements. +function f() { + var arr = []; + for (var i = 0; i < 1000; i++) + arr.push({x: i}); + var arr2 = []; + for (var i = 0; i < 1000; i++) { + gcslice(900); + var o = arr.shift(); + assertEq(o.x, i); + arr2.push(o); + } + gc(); + for (var i = 0; i < 1000; i++) + assertEq(arr2[i].x, i); +} +f(); diff --git a/js/src/tests/ecma_7/String/shell.js b/js/src/tests/ecma_7/String/shell.js new file mode 100644 index 000000000..e69de29bb diff --git a/js/src/tests/ecma_7/String/string-pad-start-end.js b/js/src/tests/ecma_7/String/string-pad-start-end.js new file mode 100644 index 000000000..d784c83e0 --- /dev/null +++ b/js/src/tests/ecma_7/String/string-pad-start-end.js @@ -0,0 +1,99 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +// `this` must be object coercable. + +for (let badThis of [null, undefined]) { + assertThrowsInstanceOf(() => { + String.prototype.padStart.call(badThis, 42, "oups"); + }, TypeError); + + assertThrowsInstanceOf(() => { + String.prototype.padEnd.call(badThis, 42, "oups"); + }, TypeError); +} + +let proxy = new Proxy({}, { +get(t, name) { + if (name === Symbol.toPrimitive || name === "toString") return; + if (name === "valueOf") return () => 42; + throw "This should not be reachable"; +} +}); + +assertEq("42bloop", String.prototype.padEnd.call(proxy, 7, "bloopie")); + +// maxLength must convert to an integer + +assertEq("lame", "lame".padStart(0, "foo")); +assertEq("lame", "lame".padStart(0.1119, "foo")); +assertEq("lame", "lame".padStart(-0, "foo")); +assertEq("lame", "lame".padStart(NaN, "foo")); +assertEq("lame", "lame".padStart(-1, "foo")); +assertEq("lame", "lame".padStart({toString: () => 0}, "foo")); + +assertEq("lame", "lame".padEnd(0, "foo")); +assertEq("lame", "lame".padEnd(0.1119, "foo")); +assertEq("lame", "lame".padEnd(-0, "foo")); +assertEq("lame", "lame".padEnd(NaN, "foo")); +assertEq("lame", "lame".padEnd(-1, "foo")); +assertEq("lame", "lame".padEnd({toString: () => 0}, "foo")); + +assertThrowsInstanceOf(() => { + "lame".padStart(Symbol("9900"), 0); +}, TypeError); + +assertThrowsInstanceOf(() => { + "lame".padEnd(Symbol("9900"), 0); +}, TypeError); + +// The fill argument must be string coercable. + +assertEq("nulln.", ".".padStart(6, null)); +assertEq(".nulln", ".".padEnd(6, null)); + +assertEq("[obje.", ".".padStart(6, {})); +assertEq(".[obje", ".".padEnd(6, {})); + +assertEq("1,2,3.", ".".padStart(6, [1, 2, 3])); +assertEq(".1,2,3", ".".padEnd(6, [1, 2, 3])); + +assertEq("aaaaa.", ".".padStart(6, {toString: () => "a"})); +assertEq(".aaaaa", ".".padEnd(6, {toString: () => "a"})); + +// undefined is converted to " " + +assertEq(" .", ".".padStart(6, undefined)); +assertEq(". ", ".".padEnd(6, undefined)); + +assertEq(" .", ".".padStart(6)); +assertEq(". ", ".".padEnd(6)); + +// The empty string has no effect + +assertEq("Tilda", "Tilda".padStart(100000, "")); +assertEq("Tilda", "Tilda".padEnd(100000, "")); + +assertEq("Tilda", "Tilda".padStart(100000, {toString: () => ""})); +assertEq("Tilda", "Tilda".padEnd(100000, {toString: () => ""})); + +// Test repetition against a bruteforce implementation + +let filler = "space"; +let truncatedFiller = ""; +for (let i = 0; i < 2500; i++) { + truncatedFiller += filler[i % filler.length]; + assertEq(truncatedFiller + "goto", "goto".padStart(5 + i, filler)); + assertEq("goto" + truncatedFiller, "goto".padEnd(5 + i, filler)); +} + +// [Argument] Length + +assertEq(1, String.prototype.padStart.length) +assertEq(1, String.prototype.padEnd.length) + +if (typeof reportCompare === "function") + reportCompare(true, true); +