diff options
Diffstat (limited to 'js/src/jit-test/tests/basic')
1442 files changed, 32752 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/basic/FPQuadCmp.js b/js/src/jit-test/tests/basic/FPQuadCmp.js new file mode 100644 index 0000000000..010228d1ff --- /dev/null +++ b/js/src/jit-test/tests/basic/FPQuadCmp.js @@ -0,0 +1,6 @@ +function FPQuadCmp() +{ + for (let j = 0; j < 3; ++j) { true == 0; } + return "ok"; +} +assertEq(FPQuadCmp(), "ok"); diff --git a/js/src/jit-test/tests/basic/__proto__-not-prototype-mutation-ion.js b/js/src/jit-test/tests/basic/__proto__-not-prototype-mutation-ion.js new file mode 100644 index 0000000000..4a7b0bd37b --- /dev/null +++ b/js/src/jit-test/tests/basic/__proto__-not-prototype-mutation-ion.js @@ -0,0 +1,12 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function f() +{ + return { *__proto__() {}, __proto__: null }; +} + +for (var i = 0; i < 2e3; i++) + f(); diff --git a/js/src/jit-test/tests/basic/__proto__-not-prototype-mutation.js b/js/src/jit-test/tests/basic/__proto__-not-prototype-mutation.js new file mode 100644 index 0000000000..b940a229b2 --- /dev/null +++ b/js/src/jit-test/tests/basic/__proto__-not-prototype-mutation.js @@ -0,0 +1,29 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var __proto__ = "string value"; + +var propdefs = + [{ c: "['__proto__']: null", t: "object" }, + { c: "__proto__() {}", t: "function" }, + { c: "['__proto__']() {}", t: "function" }, + { c: "*__proto__() {}", t: "function" }, + { c: "*['__proto__']() {}", t: "function" }, + { c: "__proto__", t: "string" }, + { c: "get __proto__() { return 42; }", t: "number" }, + { c: "get ['__proto__']() { return undefined; }", t: "undefined" }, + { c: "set __proto__(v) { }", t: "undefined" }, + { c: "set ['__proto__'](v) { }", t: "undefined" }]; + +for (var propdef of propdefs) +{ + var f = new Function("return { " + propdef.c + " };"); + for (var i = 0; i < 100; i++) + { + var inst = f(); + assertEq(typeof inst.__proto__, propdef.t); + assertEq(Object.getPrototypeOf(inst), Object.prototype); + } +} diff --git a/js/src/jit-test/tests/basic/adjacent-trycatch-second-nested.js b/js/src/jit-test/tests/basic/adjacent-trycatch-second-nested.js new file mode 100644 index 0000000000..35767eb402 --- /dev/null +++ b/js/src/jit-test/tests/basic/adjacent-trycatch-second-nested.js @@ -0,0 +1,9 @@ +try { } +catch (e) { } + +try { throw 2; } +catch (e) +{ + try { throw 3; } + catch (e2) { } +} diff --git a/js/src/jit-test/tests/basic/allow-relazify.js b/js/src/jit-test/tests/basic/allow-relazify.js new file mode 100644 index 0000000000..26e20aa289 --- /dev/null +++ b/js/src/jit-test/tests/basic/allow-relazify.js @@ -0,0 +1,9 @@ +// |jit-test| skip-if: isLcovEnabled() +function f() { + return 1; +} +assertEq(isLazyFunction(f), true); +assertEq(isRelazifiableFunction(f), false); +f(); +assertEq(isLazyFunction(f), false); +assertEq(isRelazifiableFunction(f), true); diff --git a/js/src/jit-test/tests/basic/argumentsPassedToBuiltin.js b/js/src/jit-test/tests/basic/argumentsPassedToBuiltin.js new file mode 100644 index 0000000000..d8edfffffa --- /dev/null +++ b/js/src/jit-test/tests/basic/argumentsPassedToBuiltin.js @@ -0,0 +1,14 @@ +// bug 504797 + +function f() { + g(arguments, 1); +} + +function g(a, b) { + var s = Array.prototype.slice.call(a, b); + assertEq(s[0] == undefined, false); +} + +for (var i = 0; i < 10; ++i) { + f(1, 2, 3, 4); +} diff --git a/js/src/jit-test/tests/basic/arityMismatchExtraArg.js b/js/src/jit-test/tests/basic/arityMismatchExtraArg.js new file mode 100644 index 0000000000..6803368acd --- /dev/null +++ b/js/src/jit-test/tests/basic/arityMismatchExtraArg.js @@ -0,0 +1,13 @@ +function arityMismatchMissingArg(arg) +{ + for (var a = 0, i = 1; i < 10000; i *= 2) { + a += i; + } + return a; +} + +function arityMismatchExtraArg() +{ + return arityMismatchMissingArg(1, 2); +} +assertEq(arityMismatchExtraArg(), 16383); diff --git a/js/src/jit-test/tests/basic/arityMismatchMissingArg.js b/js/src/jit-test/tests/basic/arityMismatchMissingArg.js new file mode 100644 index 0000000000..79284e9487 --- /dev/null +++ b/js/src/jit-test/tests/basic/arityMismatchMissingArg.js @@ -0,0 +1,8 @@ +function arityMismatchMissingArg(arg) +{ + for (var a = 0, i = 1; i < 10000; i *= 2) { + a += i; + } + return a; +} +assertEq(arityMismatchMissingArg(), 16383); diff --git a/js/src/jit-test/tests/basic/array-concat-spreadable.js b/js/src/jit-test/tests/basic/array-concat-spreadable.js new file mode 100644 index 0000000000..5a8bd496d5 --- /dev/null +++ b/js/src/jit-test/tests/basic/array-concat-spreadable.js @@ -0,0 +1,33 @@ +function testConcat(o1, o2, len, json) { + let res = Array.prototype.concat.call(o1, o2); + assertEq(res.length, len); + assertEq(JSON.stringify(res), json); +} + +const o1 = {[Symbol.isConcatSpreadable]: true, length: 2, 0: 4, 1: 5, 2: 6}; +const o2 = {[Symbol.isConcatSpreadable]: true, length: 2, 0: 4, 2: 6}; + +testConcat([1, 2, 3], o1, 5, "[1,2,3,4,5]"); +testConcat([1, 2, 3], o2, 5, "[1,2,3,4,null]"); + +testConcat(o1, [1, 2, 3], 5, "[4,5,1,2,3]"); +testConcat(o2, [1, 2, 3], 5, "[4,null,1,2,3]"); + +testConcat(o1, o1, 4, "[4,5,4,5]"); +testConcat(o2, o2, 4, "[4,null,4,null]"); + +testConcat(o1, o2, 4, "[4,5,4,null]"); +testConcat(o2, o1, 4, "[4,null,4,5]"); + +o1[Symbol.isConcatSpreadable] = false; + +testConcat(o1, o2, 3, '[{"0":4,"1":5,"2":6,"length":2},4,null]'); +testConcat(o2, o1, 3, '[4,null,{"0":4,"1":5,"2":6,"length":2}]'); + +const ta = new Int32Array([4, 5, 6]); +testConcat([1, 2, 3], ta, 4, '[1,2,3,{"0":4,"1":5,"2":6}]'); +testConcat(ta, ta, 2, '[{"0":4,"1":5,"2":6},{"0":4,"1":5,"2":6}]'); + +ta[Symbol.isConcatSpreadable] = true; +testConcat([1, 2, 3], ta, 6, "[1,2,3,4,5,6]"); +testConcat(ta, ta, 6, "[4,5,6,4,5,6]"); diff --git a/js/src/jit-test/tests/basic/array-copyWithin.js b/js/src/jit-test/tests/basic/array-copyWithin.js new file mode 100644 index 0000000000..113613b38b --- /dev/null +++ b/js/src/jit-test/tests/basic/array-copyWithin.js @@ -0,0 +1,187 @@ +// Tests for Array#copyWithin + +load(libdir + "asserts.js"); + +assertEq(Array.prototype.copyWithin.length, 2); + +// works with two arguments +assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3), [4, 5, 3, 4, 5]); +assertDeepEq([1, 2, 3, 4, 5].copyWithin(1, 3), [1, 4, 5, 4, 5]); +assertDeepEq([1, 2, 3, 4, 5].copyWithin(1, 2), [1, 3, 4, 5, 5]); +assertDeepEq([1, 2, 3, 4, 5].copyWithin(2, 2), [1, 2, 3, 4, 5]); + +// works with three arguments +assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3, 4), [4, 2, 3, 4, 5]); +assertDeepEq([1, 2, 3, 4, 5].copyWithin(1, 3, 4), [1, 4, 3, 4, 5]); +assertDeepEq([1, 2, 3, 4, 5].copyWithin(1, 2, 4), [1, 3, 4, 4, 5]); + +// works with negative arguments +assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, -2), [4, 5, 3, 4, 5]); +assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, -2, -1), [4, 2, 3, 4, 5]); +assertDeepEq([1, 2, 3, 4, 5].copyWithin(-4, -3, -2), [1, 3, 3, 4, 5]); +assertDeepEq([1, 2, 3, 4, 5].copyWithin(-4, -3, -1), [1, 3, 4, 4, 5]); +assertDeepEq([1, 2, 3, 4, 5].copyWithin(-4, -3), [1, 3, 4, 5, 5]); + +// works with array-like objects +var args = (function () { return Array.prototype.slice.call(arguments); }(1, 2, 3)); +var argsClass = Object.prototype.toString.call(args); +assertDeepEq(args, [1, 2, 3]); +Array.prototype.copyWithin.call(args, -2, 0); +assertDeepEq(args, [1, 1, 2]); +assertDeepEq(Object.prototype.toString.call(args), argsClass); + +// throws on null/undefined values +assertThrowsInstanceOf(function() { + Array.prototype.copyWithin.call(null, 0, 3); +}, TypeError, "Assert that copyWithin fails if this value is null"); + +assertThrowsInstanceOf(function() { + Array.prototype.copyWithin.call(undefined, 0, 3); +}, TypeError, "Assert that copyWithin fails if this value is undefined"); + +// test with this value as string +assertThrowsInstanceOf(function() { + Array.prototype.copyWithin.call("hello world", 0, 3); +}, TypeError, "Assert that copyWithin fails if this value is string"); + +// test with this value as number +assertDeepEq(Array.prototype.copyWithin.call(34, 0, 3), new Number(34)); + +// test with this value as TypedArray +var buffer = new ArrayBuffer(16); +var int32View = new Int32Array(buffer); +for (var i=0; i<int32View.length; i++) { + int32View[i] = i*2; +} +assertDeepEq(Array.prototype.copyWithin.call(int32View, 0, 1), new Int32Array([2, 4, 6, 6])); + +// if arguments object is sloppy, copyWithin must move the arguments around +function f(a, b, c, d, e) { + [].copyWithin.call(arguments, 1, 3); + return [a, b, c, d, e]; +} +assertDeepEq(f(1, 2, 3, 4, 5), [1, 4, 5, 4, 5]); + +// test with target > start on 2 arguments +assertDeepEq([1, 2, 3, 4, 5].copyWithin(3, 0), [1, 2, 3, 1, 2]); + +// test with target > start on 3 arguments +assertDeepEq([1, 2, 3, 4, 5].copyWithin(3, 0, 4), [1, 2, 3, 1, 2]); + +// test on array with holes +var arr = new Array(6); +for (var i = 0; i < arr.length; i += 2) { + arr[i] = i; +} +assertDeepEq(arr.copyWithin(0, 3), [, 4, , , 4, , ]); + +// test on fractional arguments +assertDeepEq([1, 2, 3, 4, 5].copyWithin(0.2, 3.9), [4, 5, 3, 4, 5]); + +// test with -0 +assertDeepEq([1, 2, 3, 4, 5].copyWithin(-0, 3), [4, 5, 3, 4, 5]); + +// test with arguments more than this.length +assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 7), [1, 2, 3, 4, 5]); + +// test with arguments less than -this.length +assertDeepEq([1, 2, 3, 4, 5].copyWithin(-7, 0), [1, 2, 3, 4, 5]); + +// test with arguments equal to -this.length +assertDeepEq([1, 2, 3, 4, 5].copyWithin(-5, 0), [1, 2, 3, 4, 5]); + +// test on empty array +assertDeepEq([].copyWithin(0, 3), []); + +// test with target range being shorter than end - start +assertDeepEq([1, 2, 3, 4, 5].copyWithin(2, 1, 4), [1, 2, 2, 3, 4]); + +// test overlapping ranges +arr = [1, 2, 3, 4, 5]; +arr.copyWithin(2, 1, 4); +assertDeepEq(arr.copyWithin(2, 1, 4), [1, 2, 2, 2, 3]); + +// check that delete is strict +arr = [1, , 3, , 4, 5]; +Object.freeze(arr); +assertThrowsInstanceOf(function() { + arr.copyWithin(2, 1, 4); +}, TypeError, "Assert that delete is strict in copyWithin"); + +// test with a proxy object +var proxyObj = { + get: function(recipient, name) { + return recipient[name] + 2; + } +}; + +var p = new Proxy([1, 2, 3, 4, 5], proxyObj); +Array.prototype.copyWithin.call(p, 0, 3); +for (name of Object.getOwnPropertyNames(p)) { + print(name + ": " + JSON.stringify(Object.getOwnPropertyDescriptor(p, name))); +} + +assertDeepEq(p, [6, 7, , , 5]); + +// test if we throw in between +arr = [1, 2, 3, 4, 5]; +Object.defineProperty(arr, 1, { + set: function () { + throw new Error("Boom!"); + } +}); + +assertThrowsInstanceOf(function() { + arr.copyWithin(1, 3); +}, Error, "Throwing in between."); +assertEq(arr[0], 1); +assertEq(arr[1], undefined); +assertEq(arr[2], 3); +assertEq(arr[3], 4); +assertEq(arr[4], 5); + +// undefined as third argument +assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3, undefined), [4, 5, 3, 4, 5]); + +// test that this.length is called only once +arr = {0: 1, 1: 2, 2: 3, 3: 4, 4: 5}; +var count = 0; +Object.defineProperty(arr, "length", { + get: function () { + count++; + } +}); +Array.prototype.copyWithin.call(arr, 1, 3); +assertEq(count, 1); + +count = 0; +Array.prototype.copyWithin.call(arr, 1, 3, 4); +assertEq(count, 1); + +var large = 10000; + +// test on a large array +arr = new Array(large); +assertDeepEq(arr.copyWithin(45, 900), arr); + +// test on floating point numbers +for (var i = 0; i < large; i++) { + arr[i] = Math.random(); +} +arr.copyWithin(45, 900); + +// test on array of objects +for (var i = 0; i < large; i++) { + arr[i] = { num: Math.random() }; +} +arr.copyWithin(45, 900); + +// test array length remains same +assertEq(arr.length, large); + +// test null on third argument is handled correctly +assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3, null), [1, 2, 3, 4, 5]); + +// tamper the global Object prototype and test this works +Object.prototype[2] = 1; +assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3), [4, 5, 3, 4, 5]); diff --git a/js/src/jit-test/tests/basic/array-length-double.js b/js/src/jit-test/tests/basic/array-length-double.js new file mode 100644 index 0000000000..f4e0fd210d --- /dev/null +++ b/js/src/jit-test/tests/basic/array-length-double.js @@ -0,0 +1,13 @@ +function getLength(arr) { + return arr.length; +} +function f() { + var arr1 = new Array(10); + var arr2 = new Array(4294967295); + + for (var i=0; i<10; i++) { + assertEq(getLength(arr1), 10); + assertEq(getLength(arr2), 4294967295); + } +} +f(); diff --git a/js/src/jit-test/tests/basic/array-proto-outofrange.js b/js/src/jit-test/tests/basic/array-proto-outofrange.js new file mode 100644 index 0000000000..795f41f72d --- /dev/null +++ b/js/src/jit-test/tests/basic/array-proto-outofrange.js @@ -0,0 +1,18 @@ +function f(obj) { + return typeof obj[15]; +} + +function test() { + var a = [1, 2]; + a.__proto__ = {15: 1337}; + var b = [1, 2, 3, 4]; + + for (var i = 0; i < 1000; i++) { + var r = f(i % 2 ? a : b); + assertEq(r, i % 2 ? "number" : "undefined"); + } +} + +test(); +test(); +test(); diff --git a/js/src/jit-test/tests/basic/array-slice.js b/js/src/jit-test/tests/basic/array-slice.js new file mode 100644 index 0000000000..5aa87f391b --- /dev/null +++ b/js/src/jit-test/tests/basic/array-slice.js @@ -0,0 +1,32 @@ +function check_specified_range_zero_base_slice() { + var arr = new Array(32) + arr[0]=0, arr[1]=1, arr[7]=7; + var res = arr.slice(0,10); + assertEq(arr[0],res[0]); + assertEq(arr[1],res[1]); + assertEq(arr[7],res[7]); + assertEq(res.length,10); +} + +function check_specified_range_slice() { + var arr = new Array(32) + arr[0]=0, arr[6]=1, arr[8]=3; + var res = arr.slice(5,9); + assertEq(arr[6],res[1]); + assertEq(arr[8],res[3]); + assertEq(res.length,4); +} + +function check_all_range_slice() { + var arr = new Array(32) + arr[0]=0, arr[6]=1, arr[8]=3; + var res = arr.slice(); + assertEq(arr[0],res[0]); + assertEq(arr[6],res[6]); + assertEq(arr[8],res[8]); + assertEq(res.length,32); +} + +check_all_range_slice(); +check_specified_range_slice(); +check_specified_range_zero_base_slice();
\ No newline at end of file diff --git a/js/src/jit-test/tests/basic/array-tosource.js b/js/src/jit-test/tests/basic/array-tosource.js new file mode 100644 index 0000000000..b1f51f26d3 --- /dev/null +++ b/js/src/jit-test/tests/basic/array-tosource.js @@ -0,0 +1,10 @@ +// |jit-test| skip-if: !Array.prototype.toSource + +load(libdir + 'asserts.js'); + +assertEq(Array.prototype.toSource.call([1, 'hi']), '[1, "hi"]'); +assertEq(Array.prototype.toSource.call({1: 10, 0: 42, length: 2}), "[42, 10]"); +assertEq(Array.prototype.toSource.call({1: 10, 0: 42, length: 1}), "[42]"); +assertThrowsInstanceOf(() => Array.prototype.toSource.call("someString"), TypeError); +assertThrowsInstanceOf(() => Array.prototype.toSource.call(42), TypeError); +assertThrowsInstanceOf(() => Array.prototype.toSource.call(undefined), TypeError); diff --git a/js/src/jit-test/tests/basic/arrayConcat.js b/js/src/jit-test/tests/basic/arrayConcat.js new file mode 100644 index 0000000000..17ad877113 --- /dev/null +++ b/js/src/jit-test/tests/basic/arrayConcat.js @@ -0,0 +1,18 @@ + +/* Test concat compiler paths. */ + +for (var i = 9; i < 10; i++) + assertEq([2].concat([3])[0], 2); + +function f(a, b) { + return a.concat(b)[0]; +} +function g() { + var x = []; + var y = [1]; + for (var i = 0; i < 50; i++) + assertEq(f(x, y), 1); + eval('y[0] = "three"'); + assertEq(f(x, y), "three"); +} +g(); diff --git a/js/src/jit-test/tests/basic/arrayPopShift.js b/js/src/jit-test/tests/basic/arrayPopShift.js new file mode 100644 index 0000000000..9213f3c9ac --- /dev/null +++ b/js/src/jit-test/tests/basic/arrayPopShift.js @@ -0,0 +1,30 @@ + +/* Test pop/shift compiler paths. */ + +function a() { + var x = []; + for (var i = 0; i < 50; i++) + x.push(i); + for (var j = 0; j < 100; j++) { + var z = x.shift(); + if (j < 50) + assertEq(z, j); + else + assertEq(z, undefined); + } +} +a(); + +function b() { + var x = []; + for (var i = 0; i < 50; i++) + x.push(i); + for (var j = 0; j < 100; j++) { + var z = x.pop(); + if (j < 50) + assertEq(z, 49 - j); + else + assertEq(z, undefined); + } +} +b(); diff --git a/js/src/jit-test/tests/basic/arrayProto.js b/js/src/jit-test/tests/basic/arrayProto.js new file mode 100644 index 0000000000..0186d161e6 --- /dev/null +++ b/js/src/jit-test/tests/basic/arrayProto.js @@ -0,0 +1,12 @@ + +for (var i = 0; i < 15; i++) { + var x = Object.create([]); + assertEq(x.length, 0); +} + +for (var i = 0; i < 15; i++) { + function foo() {} + foo.prototype = []; + var x = new foo(); + assertEq(x.length, 0); +} diff --git a/js/src/jit-test/tests/basic/assign-primitive-error.js b/js/src/jit-test/tests/basic/assign-primitive-error.js new file mode 100644 index 0000000000..5dcf8b4d16 --- /dev/null +++ b/js/src/jit-test/tests/basic/assign-primitive-error.js @@ -0,0 +1,18 @@ +'use strict'; + +load(libdir + 'asserts.js'); + +assertTypeErrorMessage(() => { var x = 1; x.a = 'a'; }, + `can't assign to property "a" on 1: not an object`); +assertTypeErrorMessage(() => { var x = "hello"; x.b = 'a'; }, + `can't assign to property "b" on "hello": not an object`); +assertTypeErrorMessage(() => { var x = false; x.c = 'a'; }, + `can't assign to property "c" on false: not an object`); +assertTypeErrorMessage(() => { var x = Symbol(); x.d = 'a'; }, + `can't assign to property "d" on Symbol(): not an object`); +assertTypeErrorMessage(() => { var x = Symbol("abc"); x.d = 'a'; }, + `can't assign to property "d" on Symbol("abc"): not an object`); +assertTypeErrorMessage(() => { var x = 1; x[15] = 'a'; }, + `can't assign to property 15 on 1: not an object`); +assertTypeErrorMessage(() => { var x = 1; x[Symbol("abc")] = 'a'; }, + `can't assign to property Symbol("abc") on 1: not an object`); diff --git a/js/src/jit-test/tests/basic/assign-primitive-proxy-class-error.js b/js/src/jit-test/tests/basic/assign-primitive-proxy-class-error.js new file mode 100644 index 0000000000..a861c00c36 --- /dev/null +++ b/js/src/jit-test/tests/basic/assign-primitive-proxy-class-error.js @@ -0,0 +1,14 @@ +'use strict'; + +load(libdir + 'asserts.js'); + +let hook = {} +let Base = function() {} +Base.prototype = new Proxy(Base.prototype, hook); +class Derived extends Base { + testPrimitiveReceiver() { + super.foo = "Derived"; + } +} +assertTypeErrorMessage(() => Derived.prototype.testPrimitiveReceiver.call(null), + `can't assign to property "foo" on ({}): not an object`) diff --git a/js/src/jit-test/tests/basic/assign-reuse-propmap.js b/js/src/jit-test/tests/basic/assign-reuse-propmap.js new file mode 100644 index 0000000000..e78bddd20e --- /dev/null +++ b/js/src/jit-test/tests/basic/assign-reuse-propmap.js @@ -0,0 +1,41 @@ +function testBasic() { + var o1 = {x: 1}; + var o2 = {a: 1, b: 2, c: 3, x: 4, y: 5, z: 6}; + for (var i = 0; i < 4; i++) { + var to1 = Object.assign({}, o1); + assertEq(JSON.stringify(to1), '{"x":1}'); + var to2 = Object.assign({}, o2); + assertEq(JSON.stringify(to2), '{"a":1,"b":2,"c":3,"x":4,"y":5,"z":6}'); + } +} +testBasic(); + +// Target object's proto must not be changed by assign. +function testProto() { + var from = {}; + from.a = 1; + from.b = 2; + from.c = 3; + for (var i = 0; i < 5; i++) { + var to = Object.assign(Object.create(null), from); + assertEq(JSON.stringify(to), '{"a":1,"b":2,"c":3}'); + assertEq(Object.getPrototypeOf(to), null); + } +} +testProto(); + +// Target object's realm must not be changed by assign. +function testRealm() { + var global = newGlobal({sameCompartmentAs: this}); + var from = global.evaluate("({})"); + from.a = 1; + from.b = 2; + from.c = 3; + for (var i = 0; i < 5; i++) { + var to = Object.assign({}, from); + assertEq(JSON.stringify(to), '{"a":1,"b":2,"c":3}'); + assertEq(objectGlobal(to), this); + assertEq(Object.getPrototypeOf(to), Object.prototype); + } +} +testRealm(); diff --git a/js/src/jit-test/tests/basic/basic-fuses.js b/js/src/jit-test/tests/basic/basic-fuses.js new file mode 100644 index 0000000000..220c22ba8a --- /dev/null +++ b/js/src/jit-test/tests/basic/basic-fuses.js @@ -0,0 +1,57 @@ +// |jit-test| skip-if: !(getBuildConfiguration('debug')||getBuildConfiguration('fuzzing-defined')) + +function intact(name) { + let state = getFuseState(); + if (!(name in state)) { + throw "No such fuse " + name; + } + return state[name].intact +} + +function testRealmChange() { + let g = newGlobal(); + g.evaluate(intact.toString()) + + // Get a mutating function which will affect the symbol.iterator fuse. + let rdel = g.evaluate("function del(o) { delete o.prototype[Symbol.iterator] };del") + // Fuse is still intact. + g.evaluate(`assertEq(intact("ArrayPrototypeIteratorFuse"), true)`); + + // setup a new global, + let g2 = newGlobal(); + g2.evaluate(intact.toString()) + + // register the popping function. + g2.rdel = rdel; + + // Pop the array fuse in the new global. + g2.evaluate(`rdel(Array)`); + + // The realm of the original array should have a fuse still intact + g.evaluate(`assertEq(intact("ArrayPrototypeIteratorFuse"), true)`); + + // The realm of the array proto should no longer be intact. Oh dear. This is + // interesting. We currently ask the cx for the array iterator proto, + g2.evaluate(`assertEq(intact("ArrayPrototypeIteratorFuse"), false)`); +} + +testRealmChange(); + +function testInNewGlobal(pre, post) { + g = newGlobal(); + g.evaluate(intact.toString()); + g.evaluate(pre) + g.evaluate("assertRealmFuseInvariants()"); + g.evaluate(post); +} + +testInNewGlobal("delete Array.prototype[Symbol.iterator]", `assertEq(intact("ArrayPrototypeIteratorFuse"), false)`) +testInNewGlobal("([])[Symbol.iterator]().__proto__['return'] = () => 10;", `assertEq(intact("ArrayIteratorPrototypeHasNoReturnProperty"), false)`) +testInNewGlobal("([])[Symbol.iterator]().__proto__.__proto__['return'] = () => 10;", `assertEq(intact("IteratorPrototypeHasNoReturnProperty"), false)`) +testInNewGlobal("Object.prototype['return'] = () => 10;", `assertEq(intact("ObjectPrototypeHasNoReturnProperty"), false)`) +testInNewGlobal(`assertEq(intact("ArrayIteratorPrototypeHasIteratorProto"), true); Object.setPrototypeOf(( ([])[Symbol.iterator]().__proto__ ), {a:10})`, `assertEq(intact("ArrayIteratorPrototypeHasIteratorProto"), false);`); +testInNewGlobal(`assertEq(intact("IteratorPrototypeHasObjectProto"), true); Object.setPrototypeOf( ( ([])[Symbol.iterator]().__proto__.__proto__ ), {a:10})`, `assertEq(intact("IteratorPrototypeHasObjectProto"), false);`); + +testInNewGlobal(`assertEq(intact("hasSeenObjectEmulateUndefinedFuse"), true); createIsHTMLDDA()`, `assertEq(intact("hasSeenObjectEmulateUndefinedFuse"), false);`); +// Runtime wide fuse. +assertEq(intact("hasSeenObjectEmulateUndefinedFuse"), false); diff --git a/js/src/jit-test/tests/basic/bigLoadStoreDisp.js b/js/src/jit-test/tests/basic/bigLoadStoreDisp.js new file mode 100644 index 0000000000..4f0df81550 --- /dev/null +++ b/js/src/jit-test/tests/basic/bigLoadStoreDisp.js @@ -0,0 +1,25 @@ +// In Nanojit, loads and stores have a maximum displacement of 16-bits. Any +// displacements larger than that should be split off into a separate +// instruction that adds the displacement to the base pointer. This +// program tests if this is done correctly. +// +// x.y ends up having a dslot offset of 79988, because of the 20000 array +// elements before it. If Nanojit incorrectly stores this offset into a +// 16-bit value it will truncate to 14452 (because 79988 - 65536 == 14452). +// This means that the increments in the second loop will be done to one of +// the array elements instead of x.y. And so x.y's final value will be +// (99 + 8) instead of 1099. +// +// Note that setting x.y to 99 and checking its value at the end will +// access the correct location because those lines are interpreted. Phew. + +var x = {} +for (var i = 0; i < 20000; i++) + x[i] = 0; +x.y = 99; // not traced, correctly accessed + +for (var i = 0; i < 1000; ++i) { + x.y++; // traced, will access an array elem if disp was truncated +} +assertEq(x.y, 1099); // not traced, correctly accessed + diff --git a/js/src/jit-test/tests/basic/bindname-in-strict-eval.js b/js/src/jit-test/tests/basic/bindname-in-strict-eval.js new file mode 100644 index 0000000000..e052a65dd5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bindname-in-strict-eval.js @@ -0,0 +1,3 @@ +'use strict'; +eval("var i = 0; var end = 9; for(var j = 0; j < end; i++, j++) { i = 0; }"); +print("done"); diff --git a/js/src/jit-test/tests/basic/bitwiseAnd.js b/js/src/jit-test/tests/basic/bitwiseAnd.js new file mode 100644 index 0000000000..dc9fafa4ff --- /dev/null +++ b/js/src/jit-test/tests/basic/bitwiseAnd.js @@ -0,0 +1,10 @@ +function bitwiseAnd_inner(bitwiseAndValue) { + for (var i = 0; i < 60000; i++) + bitwiseAndValue = bitwiseAndValue & i; + return bitwiseAndValue; +} +function bitwiseAnd() +{ + return bitwiseAnd_inner(12341234); +} +assertEq(bitwiseAnd(), 0); diff --git a/js/src/jit-test/tests/basic/bitwiseGlobal.js b/js/src/jit-test/tests/basic/bitwiseGlobal.js new file mode 100644 index 0000000000..e8967c12b8 --- /dev/null +++ b/js/src/jit-test/tests/basic/bitwiseGlobal.js @@ -0,0 +1,8 @@ +bitwiseAndValue = Math.pow(2,32); +for (var i = 0; i < 60000; i++) + bitwiseAndValue = bitwiseAndValue & i; + +assertEq(bitwiseAndValue, 0); + + + diff --git a/js/src/jit-test/tests/basic/blinterp-jitoption.js b/js/src/jit-test/tests/basic/blinterp-jitoption.js new file mode 100644 index 0000000000..68c042b288 --- /dev/null +++ b/js/src/jit-test/tests/basic/blinterp-jitoption.js @@ -0,0 +1,3 @@ +// |jit-test| error:Enabling or disabling the Baseline Interpreter +let blInterpEnabled = getJitCompilerOptions()['blinterp.enable'] === 1; +setJitCompilerOption("blinterp.enable", blInterpEnabled ? 0 : 1); diff --git a/js/src/jit-test/tests/basic/bound-function-proto.js b/js/src/jit-test/tests/basic/bound-function-proto.js new file mode 100644 index 0000000000..a692381717 --- /dev/null +++ b/js/src/jit-test/tests/basic/bound-function-proto.js @@ -0,0 +1,18 @@ +// When allocating a bound function in JIT code, ensure it ends up with the +// correct proto. +function f() { + var arr = [function(){}, function(){}]; + + arr[0].bind = Function.prototype.bind; + arr[1].bind = Function.prototype.bind; + + var proto = {}; + Object.setPrototypeOf(arr[1], proto); + + for (var i = 0; i < 2000; i++) { + var fun = arr[Number(i > 1000)]; + var bound = fun.bind(null); + assertEq(Object.getPrototypeOf(bound), i > 1000 ? proto : Function.prototype); + } +} +f(); diff --git a/js/src/jit-test/tests/basic/bug-1133377.js b/js/src/jit-test/tests/basic/bug-1133377.js new file mode 100644 index 0000000000..3883eb7435 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug-1133377.js @@ -0,0 +1,11 @@ +var buffer = new ArrayBuffer(100); + +view = new DataView(buffer, undefined, undefined); +assertEq(view.buffer, buffer); +assertEq(view.byteOffset, 0); +assertEq(view.byteLength, 100); + +view = new DataView(buffer, 20, undefined); +assertEq(view.buffer, buffer); +assertEq(view.byteOffset, 20); +assertEq(view.byteLength, 80); diff --git a/js/src/jit-test/tests/basic/bug-1198090.js b/js/src/jit-test/tests/basic/bug-1198090.js new file mode 100644 index 0000000000..2ee6b5a2ed --- /dev/null +++ b/js/src/jit-test/tests/basic/bug-1198090.js @@ -0,0 +1,9 @@ +// |jit-test| allow-oom; skip-if: !('oomAtAllocation' in this) + +for (let a of [ + null, function() {}, function() {}, null, function() {}, function() {}, + function() {}, null, null, null, null, null, null, null, null, + function() {}, null, null, null, function() {} + ]) { + oomAtAllocation(5); +} diff --git a/js/src/jit-test/tests/basic/bug-1240532.js b/js/src/jit-test/tests/basic/bug-1240532.js new file mode 100644 index 0000000000..6fd1ccd46f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug-1240532.js @@ -0,0 +1,3 @@ +if (helperThreadCount() > 0) { + evalInWorker("try { newGlobal({principal : 5}); } catch (e) {}"); +} diff --git a/js/src/jit-test/tests/basic/bug-1271507.js b/js/src/jit-test/tests/basic/bug-1271507.js new file mode 100644 index 0000000000..88097aca8d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug-1271507.js @@ -0,0 +1,11 @@ +// |jit-test| allow-oom; skip-if: typeof oomAfterAllocations !== 'function' +lfcode = new Array(); +oomAfterAllocations(100); +loadFile(file); +lfGlobal = newGlobal() +for (lfLocal in this) + if (!(lfLocal in lfGlobal)) + lfGlobal[lfLocal] = this[lfLocal] +offThreadCompileToStencil(lfVarx); +var stencil = lfGlobal.finishOffThreadStencil(); +lfGlobal.evalStencil(stencil); diff --git a/js/src/jit-test/tests/basic/bug-1649234-1.js b/js/src/jit-test/tests/basic/bug-1649234-1.js new file mode 100644 index 0000000000..ab8368893b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug-1649234-1.js @@ -0,0 +1,8 @@ +// |jit-test| exitstatus: 6; skip-if: getBuildConfiguration("wasi") + +timeout(0.1, function() { return false; }); +Atomics.add(new Int32Array(1), 0, { + valueOf() { + while (1); + } +}); diff --git a/js/src/jit-test/tests/basic/bug-1649234-2.js b/js/src/jit-test/tests/basic/bug-1649234-2.js new file mode 100644 index 0000000000..c5cbfc5e46 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug-1649234-2.js @@ -0,0 +1,9 @@ +// |jit-test| exitstatus: 6; + +setInterruptCallback(() => false); +0n == { + valueOf() { + interruptIf(true); + for (;;) {} // block until interrupt callback, which terminates the script + } +}; diff --git a/js/src/jit-test/tests/basic/bug-1649234-3.js b/js/src/jit-test/tests/basic/bug-1649234-3.js new file mode 100644 index 0000000000..80df8b3ecf --- /dev/null +++ b/js/src/jit-test/tests/basic/bug-1649234-3.js @@ -0,0 +1,14 @@ +// |jit-test| exitstatus: 3; skip-if: getBuildConfiguration('pbl') + +let debuggerRealm = newGlobal({newCompartment: true}); +debuggerRealm.debuggee = this; +debuggerRealm.eval(` + let dbg = new Debugger(debuggee); + dbg.onDebuggerStatement = (frame) => null; // terminate the debuggee +`); + +Atomics.add(new Int32Array(1), 0, { + valueOf() { + debugger; + } +}); diff --git a/js/src/jit-test/tests/basic/bug-1663741.js b/js/src/jit-test/tests/basic/bug-1663741.js new file mode 100644 index 0000000000..866bd083a3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug-1663741.js @@ -0,0 +1,29 @@ +const thisGlobal = this; +const otherGlobalSameCompartment = newGlobal({sameCompartmentAs: thisGlobal}); +const otherGlobalNewCompartment = newGlobal({newCompartment: true}); + +const globals = [thisGlobal, otherGlobalSameCompartment, otherGlobalNewCompartment]; + +function testProperties(global, count) { + let {object: source, transplant} = transplantableObject(); + + // Create a bunch properties on |source|, which force allocation of dynamic + // slots. + for (let i = 0; i < count; i++) { + source["foo" + i] = i; + } + + // Calling |transplant| transplants the object and then returns undefined. + transplant(global); + + // Check the properties were copied over to the swapped object. + for (let i = 0; i < count; i++) { + assertEq(source["foo" + i], i); + } +} + +for (let global of globals) { + for (let count of [0, 10, 30]) { + testProperties(global, count); + } +} diff --git a/js/src/jit-test/tests/basic/bug-1665583.js b/js/src/jit-test/tests/basic/bug-1665583.js new file mode 100644 index 0000000000..012dc1d043 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug-1665583.js @@ -0,0 +1,41 @@ +// |jit-test| skip-if: !('oomTest' in this) + +function parseModule(source) { + offThreadCompileModuleToStencil(source); + var stencil = finishOffThreadStencil(); + return instantiateModuleStencil(stencil); +} +function loadFile(lfVarx) { + oomTest(function() { + parseModule(lfVarx); + }); +} +loadFile(` +const numberingSystems = { + "adlm": {}, + "ahom": {}, + "arab": {}, + "arabext": {}, + "armn": {}, + "armnlow": {}, + "bali": {}, + "beng": {}, + "bhks": {}, + "brah": {}, + "cakm": {}, + "cham": {}, + "cyrl": {}, + "hmnp": {}, + "java": {}, + "jpan": {}, + "jpanfin": {}, + "jpanyear": {}, + "knda": {}, + "lana": {}, + "latn": {}, + "lepc": {}, + "limb": {}, + "wcho": {}, + "extra1": {} +}; +`); diff --git a/js/src/jit-test/tests/basic/bug-1707422.js b/js/src/jit-test/tests/basic/bug-1707422.js new file mode 100644 index 0000000000..fa46c69735 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug-1707422.js @@ -0,0 +1,14 @@ +x = "a"; +x += +"a"; +x += +"a"; +x += x; +x += x; +var s = x; +x += 0; +y = x += 0; +y += x += "a"; +for (let i = 0; i < 12; ++i) { + try { + this(); + } catch {} +} diff --git a/js/src/jit-test/tests/basic/bug-508061.js b/js/src/jit-test/tests/basic/bug-508061.js new file mode 100644 index 0000000000..8ee45e8610 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug-508061.js @@ -0,0 +1,11 @@ +function loop() { + var x; + for (var i = 0; i < 9; i++) + x = {1.5: 1}; + return x; +} + +loop(); // record +Object.prototype.__defineSetter__('1.5', function () { return 'BAD'; }); +var x = loop(); // playback +assertEq(x["1.5"], 1);
\ No newline at end of file diff --git a/js/src/jit-test/tests/basic/bug-826124.js b/js/src/jit-test/tests/basic/bug-826124.js new file mode 100644 index 0000000000..6efda93aaf --- /dev/null +++ b/js/src/jit-test/tests/basic/bug-826124.js @@ -0,0 +1,14 @@ +var x = {}; +function f() { y.prop; } +x.toStr = function () { f(); }; +try { + f(); +} catch (e) { } +try { + x.toStr(); +} catch (e) { } +try { + function f() { which = 2; } + x.toStr(); +} catch (e) { which = 1; } +assertEq(which, 2); diff --git a/js/src/jit-test/tests/basic/bug1001090-1.js b/js/src/jit-test/tests/basic/bug1001090-1.js new file mode 100644 index 0000000000..86970ffc46 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1001090-1.js @@ -0,0 +1,2 @@ +(function() { let arguments })(); +(() => { let arguments; })() diff --git a/js/src/jit-test/tests/basic/bug1001090-2.js b/js/src/jit-test/tests/basic/bug1001090-2.js new file mode 100644 index 0000000000..2a3be27221 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1001090-2.js @@ -0,0 +1,5 @@ +// |jit-test| error: ReferenceError +(function() { + with(x); + let x +})() diff --git a/js/src/jit-test/tests/basic/bug1001090-3.js b/js/src/jit-test/tests/basic/bug1001090-3.js new file mode 100644 index 0000000000..3739c06b6f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1001090-3.js @@ -0,0 +1,27 @@ +var output = []; +function g(s) { + L = s.length; + for (var i = 0; i < L; i++) { + a = s.charAt() + } +} +function h(f, inputs) { + results = []; + for (var j = 0; j < 99; ++j) { + for (var k = 0; k < 99; ++k) { + try { + results.push(f()) + } catch (e) {} + } + } + output.push(g(JSON.stringify(results))) +} +m = (function(x, y) {}); +h(m, []) +try { + output.push(x); + let x = s() +} catch (e) {} + +assertEq(output.length, 1); +assertEq(output[0], undefined); diff --git a/js/src/jit-test/tests/basic/bug1001090-4.js b/js/src/jit-test/tests/basic/bug1001090-4.js new file mode 100644 index 0000000000..a94048af46 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1001090-4.js @@ -0,0 +1,30 @@ +var output = []; +function g(s) { + for (var i = 0; i < s.length; i++) { + s.charAt() + } +} +function h(f, inputs) { + results = [] + for (var j = 0; j < 99; ++j) { + for (var k = 0; k < 99; ++k) { + try { + results.push(f()) + } catch (e) {} + } + } + g(JSON.stringify(results)) +} +try { + x() +} catch (e) {} +m = function(y) { + return y; +}; +h(m, []); +try { + output.push(b); + let b = ""; +} catch (e) {} + +assertEq(output.length, 0); diff --git a/js/src/jit-test/tests/basic/bug1001090-5.js b/js/src/jit-test/tests/basic/bug1001090-5.js new file mode 100644 index 0000000000..4636ca053f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1001090-5.js @@ -0,0 +1,6 @@ +// |jit-test| error: ReferenceError +evalcx("\ + for(x = 0; x < 9; x++) {\ + let y = y.s()\ + }\ +", newGlobal()) diff --git a/js/src/jit-test/tests/basic/bug1001090-6.js b/js/src/jit-test/tests/basic/bug1001090-6.js new file mode 100644 index 0000000000..14d60e8043 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1001090-6.js @@ -0,0 +1,7 @@ +// |jit-test| error: ReferenceError +(function() { + ((function() { + p(y) + })()); + let y +})() diff --git a/js/src/jit-test/tests/basic/bug1003161.js b/js/src/jit-test/tests/basic/bug1003161.js new file mode 100644 index 0000000000..c2c602acb5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1003161.js @@ -0,0 +1,8 @@ + +function foo(a, b) { + function bar() { + return b; + } + return arguments[0] + arguments[1] + bar(); +} +foo(1, 2); diff --git a/js/src/jit-test/tests/basic/bug1008339.js b/js/src/jit-test/tests/basic/bug1008339.js new file mode 100644 index 0000000000..f253d6024c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1008339.js @@ -0,0 +1,64 @@ + +var count = 0; + +function Parent() { + // Scanning "this" properties here with Object.keys() solved the bug in my case + //Object.keys(this); + + this.log('Parent ctor'); + this.meth1(); + this.log('data3 before : ' + this.data3); + this.meth2(); + // Added properties lost in ChildA + this.log('data3 after : ' + this.data3); + this.log(''); + + if (count++) + assertEq(this.data3, 'z'); +} +Parent.prototype.meth1 = function () { + this.log('Parent.meth1()'); +}; +Parent.prototype.meth2 = function () { + this.log('Parent.meth2()'); + // Requirement for the bug : Parent.meth2() needs to add data + this.data4 = 'x'; +}; +Parent.prototype.log = function (data) { + print(data); +} + +// Intermediate constructor to instantiate children prototype without executing Parent constructor code +function ParentEmptyCtor() { } +ParentEmptyCtor.prototype = Parent.prototype; + +function ChildA() { + this.log('ChildA ctor'); + Parent.call(this); +} +ChildA.prototype = new ParentEmptyCtor(); +// Using Object.create() instead solves the bug +//ChildA.prototype = Object.create(ParentEmptyCtor.prototype); +ChildA.prototype.constructor = ChildA; +ChildA.prototype.meth1 = function () { + this.log('ChildA.meth1()'); + this.data3 = 'z'; +}; +ChildA.prototype.meth2 = function () { + this.log('ChildA.meth2()'); +}; + +function ChildB() { + this.log('ChildB ctor'); + Parent.call(this); +} +ChildB.prototype = new ParentEmptyCtor(); +//ChildB.prototype = Object.create(ParentEmptyCtor.prototype); +ChildB.prototype.constructor = ChildB; + +function demo() { + // Requirement for the bug : ChildB needs to be instantiated before ChildA + new ChildB(); + new ChildA(); +} +demo(); diff --git a/js/src/jit-test/tests/basic/bug1013922.js b/js/src/jit-test/tests/basic/bug1013922.js new file mode 100644 index 0000000000..febe32ea5f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1013922.js @@ -0,0 +1,67 @@ +String.prototype.repeat = function(num) { + return new Array(num + 1).join(this); +} + +function set_to_length(length, frag_size) +{ + var fragment = "'" + "x".repeat(frag_size) + "' + "; + var frags = Math.floor((length - 1)/frag_size); + var code = "var x = " + fragment.repeat(frags) + "'" + + "x".repeat(length - frags * frag_size) + "';"; + + try { + eval(code); + } + catch(err) { + if (err.message && err.message == "Out of memory") + return -1; + if (err == "out of memory") + return -1; + throw(err); /* Oops, broke something. */ + } + + return code.length; +} + +var first_fail; +var first_pass; +var frag_size; +var pass_code_length; + +function search_up() +{ + if (set_to_length(first_fail, frag_size) < 0) { + setTimeout(binary_search, 0); + return; + } + + first_fail *= 2; +} + +function binary_search() +{ + if (first_fail - first_pass > 1) { + var length = (first_pass + first_fail) / 2; + var code_len = set_to_length(length, frag_size); + if (code_len > 0) { + first_pass = length; + pass_code_length = code_len; + } else + first_fail = length; + setTimeout(binary_search, 0); + return; + } +} + +function run_find_limit() +{ + frag_size = 64; + first_fail = 65536; /* A guess */ + first_pass = 0; + pass_code_length = 0; + + for (var i=0; i<5; i++) + search_up(0); +} + +run_find_limit(); diff --git a/js/src/jit-test/tests/basic/bug1015339.js b/js/src/jit-test/tests/basic/bug1015339.js new file mode 100644 index 0000000000..2441811d49 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1015339.js @@ -0,0 +1,8 @@ +function f(x, y) { + for (var i=0; i<40; i++) { + var stack = getBacktrace({args: true, locals: true, thisprops: true}); + assertEq(stack.includes("f(x = "), true); + backtrace(); + } +} +f(1, 2); diff --git a/js/src/jit-test/tests/basic/bug1015766.js b/js/src/jit-test/tests/basic/bug1015766.js new file mode 100644 index 0000000000..e76aff7c7a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1015766.js @@ -0,0 +1,10 @@ +gczeal(8, 2) +try { + [new String, y] +} catch (e) {} +r = /()/ +try { + "".replace(r, () => { + []() + }); +} catch(e) {} diff --git a/js/src/jit-test/tests/basic/bug1018620.js b/js/src/jit-test/tests/basic/bug1018620.js new file mode 100644 index 0000000000..64463d23c4 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1018620.js @@ -0,0 +1,5 @@ + +String.prototype.search = evalcx('').String.prototype.search; +''.search(/()/); +gcPreserveCode(); +gc(this); diff --git a/js/src/jit-test/tests/basic/bug1024786.js b/js/src/jit-test/tests/basic/bug1024786.js new file mode 100644 index 0000000000..6811513cbe --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1024786.js @@ -0,0 +1,65 @@ +//|jit-test| error: SyntaxError + +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +(function(){}); +evaluate("function f(){\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",({ + fileName: null, + lineNumber: 42, + isRunOnce: 9, +})) diff --git a/js/src/jit-test/tests/basic/bug1033946.js b/js/src/jit-test/tests/basic/bug1033946.js new file mode 100644 index 0000000000..e2f07a8532 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1033946.js @@ -0,0 +1,2 @@ +assertEq((/(?!(?!(?!6)[\Wc]))/i).test(), false); +assertEq("foobar\xff5baz\u1200".search(/bar\u0178\d/i), 3); diff --git a/js/src/jit-test/tests/basic/bug1035287-track-allocation-sites-recursion.js b/js/src/jit-test/tests/basic/bug1035287-track-allocation-sites-recursion.js new file mode 100644 index 0000000000..79394c31c7 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1035287-track-allocation-sites-recursion.js @@ -0,0 +1,7 @@ +// |jit-test| exitstatus: 3 + +enableTrackAllocations(); +function f() { + eval('f();'); +} +f(); diff --git a/js/src/jit-test/tests/basic/bug1035325.js b/js/src/jit-test/tests/basic/bug1035325.js new file mode 100644 index 0000000000..48e6ff33a1 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1035325.js @@ -0,0 +1 @@ +print("\uDBFF\uDFFF"); // don't crash/assert diff --git a/js/src/jit-test/tests/basic/bug1054243.js b/js/src/jit-test/tests/basic/bug1054243.js new file mode 100644 index 0000000000..66d167ad70 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1054243.js @@ -0,0 +1,3 @@ +// |jit-test| error: uncaught exception +var prox = new Proxy({}, {getOwnPropertyDescriptor: function() { throw prox; }}); +Object.prototype.__lookupGetter__.call(prox, 'q'); diff --git a/js/src/jit-test/tests/basic/bug1057571.js b/js/src/jit-test/tests/basic/bug1057571.js new file mode 100644 index 0000000000..740febd3e6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1057571.js @@ -0,0 +1,15 @@ + +test = (function () { + function f() { + [1,2,3,4,5]; + }; + return "var obj = { x : 2 };" + f.toString() + "; f()"; +})(); +evalWithCache(test, {}); +function evalWithCache(code, ctx) { + code = cacheEntry(code); + ctx.global = newGlobal(); + ctx.isRunOnce = true; + var res1 = evaluate(code, Object.create(ctx, {saveIncrementalBytecode: { value: true } })); + var res2 = evaluate(code, Object.create(ctx, {loadBytecode: { value: true }, saveIncrementalBytecode: { value: true } })); +} diff --git a/js/src/jit-test/tests/basic/bug1059459.js b/js/src/jit-test/tests/basic/bug1059459.js new file mode 100644 index 0000000000..47f0246c71 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1059459.js @@ -0,0 +1 @@ +evalcx(" s = 3; s; for(let x = 0; x < 1; ++x) { null }", newGlobal()) diff --git a/js/src/jit-test/tests/basic/bug1061534.js b/js/src/jit-test/tests/basic/bug1061534.js new file mode 100644 index 0000000000..3fce6a7580 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1061534.js @@ -0,0 +1,15 @@ + +test = (function () { + function f() {}; + return "var obj = { x : 2 };" + f.toString() + (4); +})(); +evalWithCache(test, {}); +function evalWithCache(code, ctx) { + code = cacheEntry(code); + ctx.global = newGlobal({ cloneSingletons: true }); + var res1 = evaluate(code, Object.create(ctx, {saveIncrementalBytecode: { value: true } })); +} +if (typeof assertThrowsInstanceOf === 'undefined') { + var assertThrowsInstanceOf = function assertThrowsInstanceOf(f, ctor, msg) {}; +} +evaluate('evaluate(\'assertThrowsInstanceOf(function () {}, ["jak", "ms"]);\', { noScriptRval : true, isRunOnce: true })'); diff --git a/js/src/jit-test/tests/basic/bug1066414.js b/js/src/jit-test/tests/basic/bug1066414.js new file mode 100644 index 0000000000..be7ab33466 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1066414.js @@ -0,0 +1 @@ +for (var [...y] in Object) {} // dont assert diff --git a/js/src/jit-test/tests/basic/bug1078871.js b/js/src/jit-test/tests/basic/bug1078871.js new file mode 100644 index 0000000000..13ed812801 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1078871.js @@ -0,0 +1,44 @@ + +// Robert Jenkins' 32 bit integer hash function +var seed = 100; +Math.random = function() { + seed = (seed + 0x7ed55d16) + (seed<<12); + seed = (seed ^ 0xc761c23c) ^ (seed>>19); + seed = (seed + 0x165667b1) + (seed<<5); + seed = (seed + 0xd3a2646c) ^ (seed<<9); + seed = (seed + 0xfd7046c5) + (seed<<3); + seed = (seed ^ 0xb55a4f09) ^ (seed>>16); + seed = Math.abs(seed | 0); + return seed / 0xffffffff * 2; +} + +function tangle(n, m) { + function rand(n) { + return Math.floor(Math.random() * n); + } + + var arr = []; + for (var i = 0; i < n; i++) + arr[i] = String.fromCharCode(65 + rand(26)); + for (var i = 0; i < m; i++) { + var j = rand(n); + switch (rand(2)) { + case 0: { + var s = arr[rand(n)]; + var b = rand(s.length); + var e = b + rand(s.length - b); + if (e - b > 1) + arr[j] = s.substring(b, e); + } + break; + case 1: { + arr[j] = arr[rand(n)] + arr[rand(n)]; + } + } + JSON.stringify(arr[j]); + } + + return arr; +} + +tangle(10, 500); diff --git a/js/src/jit-test/tests/basic/bug1081175.js b/js/src/jit-test/tests/basic/bug1081175.js new file mode 100644 index 0000000000..32766d7680 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1081175.js @@ -0,0 +1,20 @@ +var input = "webkit-search-cancel-button-aaaaaaa-bbbbb-ccccccc-dddddddd," +var bad_regex = '([a-u-]|\\u0080|\\u0100)*[d]'; + +function forceUnicode(s) { + return ('\uffff' + s).replace(/^\uffff/, ''); +} +function testRegex(input) { + for (var i = 0; i < input.length; i++) { + var sub = input.substring(0, i + 1); + var res = sub.match(bad_regex); + if (i >= 50) { + assertEq(res.length, 2); + assertEq(res[1], sub.substr(-2, 1)); + } else { + assertEq(res, null); + } + } +} +testRegex(input); +testRegex(forceUnicode(input)); diff --git a/js/src/jit-test/tests/basic/bug1085464.js b/js/src/jit-test/tests/basic/bug1085464.js new file mode 100644 index 0000000000..1c09eb8afc --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1085464.js @@ -0,0 +1,20 @@ +function *f() { + var o = new Proxy({}, { + get: function() { assertEq(0, 1); }, + has: function() { assertEq(0, 2); } + }); + + with (o) { + yield 1; + with ({}) { + yield 2; + } + } + with ({".generator": 100}) { + yield eval("3"); + } +} +var s = ""; +for (var i of f()) + s += i; +assertEq(s, "123"); diff --git a/js/src/jit-test/tests/basic/bug1091757.js b/js/src/jit-test/tests/basic/bug1091757.js new file mode 100644 index 0000000000..e3c437b6a2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1091757.js @@ -0,0 +1,11 @@ +try { + (function() { + let a = 3; + let XY = XY; + return function() { return a; }; + })(); + assertEq(0, 1); +} catch(e) { + assertEq(e instanceof ReferenceError, true); + assertEq(e.message.includes("XY"), true); +} diff --git a/js/src/jit-test/tests/basic/bug1100623.js b/js/src/jit-test/tests/basic/bug1100623.js new file mode 100644 index 0000000000..dbd75ed4dd --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1100623.js @@ -0,0 +1,16 @@ +// |jit-test| error: baz is null; skip-if: getBuildConfiguration('pbl') +// +// (skip if PBL enabled: it doesn't support the decompiler so doesn't give the +// specific error message) + +var document = {getElementById: () => null}; + +(function() { + const one = 1; + + function foo() { return one; } + function bar() { return foo(); } + + var baz = document.getElementById("baz"); + baz.value; +})(); diff --git a/js/src/jit-test/tests/basic/bug1106982-2.js b/js/src/jit-test/tests/basic/bug1106982-2.js new file mode 100644 index 0000000000..1983c4b04f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1106982-2.js @@ -0,0 +1,15 @@ +var x = "wrong"; +var t = {x: "x"}; +var hits = 0; +var p = new Proxy(t, { + has(t, id) { + var found = id in t; + if (++hits == 2) + delete t[id]; + return found; + }, + get(t, id) { return t[id]; } +}); +evaluate(`x += " x";`, {envChainObject: p}); +assertEq(hits, 2); +assertEq(t.x, "undefined x"); diff --git a/js/src/jit-test/tests/basic/bug1106982.js b/js/src/jit-test/tests/basic/bug1106982.js new file mode 100644 index 0000000000..ededf3b936 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1106982.js @@ -0,0 +1,19 @@ +var x = "wrong"; +var t = {x: "x"}; +var hits = 0; +var p = new Proxy(t, { + has(t, id) { + var found = id in t; + if (++hits == 2) + delete t[id]; + return found; + }, + get(t, id) { return t[id]; } +}); +with (p) + x += " x"; +// If you change this testcase (e.g. because we fix the number of +// has() calls we end up making to match spec better), don't forget to +// update bug1106982-2.js too. See also bug 1145641. +assertEq(hits, 2); +assertEq(t.x, "undefined x"); diff --git a/js/src/jit-test/tests/basic/bug1113980.js b/js/src/jit-test/tests/basic/bug1113980.js new file mode 100644 index 0000000000..d975c5d8d1 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1113980.js @@ -0,0 +1,10 @@ +var p = new Proxy({}, { + getOwnPropertyDescriptor: function() { + return {value: 1, configurable: true, writable: true}; + }, + defineProperty: function() { + } +}, null); + +var o = Object.create(p); +o.a = 1; diff --git a/js/src/jit-test/tests/basic/bug1118996.js b/js/src/jit-test/tests/basic/bug1118996.js new file mode 100644 index 0000000000..44b345711d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1118996.js @@ -0,0 +1,13 @@ +// |jit-test| allow-oom; --fuzzing-safe; --no-threads; --no-ion; allow-unhandlable-oom +g = newGlobal(); +gcparam('maxBytes', gcparam('gcBytes')); +try { + evaluate("return 0", ({ + global: g, + newContext: true + })); +} catch (error) { + // We expect evaluate() above to fail with OOM, but due to GC zeal settings + // it may execute correctly and throw "SyntaxError: return not in function". + // This catch block is to ignore that error. +} diff --git a/js/src/jit-test/tests/basic/bug1122534.js b/js/src/jit-test/tests/basic/bug1122534.js new file mode 100644 index 0000000000..bdf1a0b57a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1122534.js @@ -0,0 +1,16 @@ +// |jit-test| error: TypeError + +function newFunc(x) { new Function(x)(); }; +newFunc("\ +function GetUnicodeValues(c) {\ + u = new Array();\ + if ((c >= 0x0100 && c < 0x0138) || (c > 0x1Bedb && c < 0x0178))\ + return;\ + return u;\ +}\ +function Unicode(c) {\ + u = GetUnicodeValues(c);\ + this.upper = u[0];\ +}\ +for (var i = 0; i <= 0x017f; i++) { var U = new Unicode(i); }\ +"); diff --git a/js/src/jit-test/tests/basic/bug1122581.js b/js/src/jit-test/tests/basic/bug1122581.js new file mode 100644 index 0000000000..7c99924270 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1122581.js @@ -0,0 +1,10 @@ +function f(x, y) { + for (var i=0; i<50; i++) { + if (i % 10 === 0) { + var stack = getBacktrace({args: true, locals: true, thisprops: true}); + assertEq(stack.includes("f(x = "), true); + foo = arguments; + } + } +} +f(1, 2); diff --git a/js/src/jit-test/tests/basic/bug1127303.js b/js/src/jit-test/tests/basic/bug1127303.js new file mode 100644 index 0000000000..078b4477c2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1127303.js @@ -0,0 +1,9 @@ + +function test1() {} +function test() { test1.call(this); } +var length = 30 * 1024 - 1; +var obj = new test(); +for(var i = 0 ; i < length ; i++) { + obj.next = new (function ( ) { } ) (); + obj = obj.next; +} diff --git a/js/src/jit-test/tests/basic/bug1131035.js b/js/src/jit-test/tests/basic/bug1131035.js new file mode 100644 index 0000000000..6ff80f3743 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1131035.js @@ -0,0 +1,9 @@ + +function TestCase() { + this.passed = 'x'; +} +result = "pass"; +for (var i = 0; i < 100; i++) + new TestCase(result); +function Gen2(value) {} +Gen2.prototype = new TestCase(); diff --git a/js/src/jit-test/tests/basic/bug1134146.js b/js/src/jit-test/tests/basic/bug1134146.js new file mode 100644 index 0000000000..5d2a478957 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1134146.js @@ -0,0 +1,10 @@ + +function Foo(a, b) { + b = {}; + this.b = b; +}; +var a = []; +for (var i = 0; i < 50; i++) + a.push(new Foo(i, i + 1)); +i = 0; +a[i].c = i; diff --git a/js/src/jit-test/tests/basic/bug1135718.js b/js/src/jit-test/tests/basic/bug1135718.js new file mode 100644 index 0000000000..515457cdfb --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1135718.js @@ -0,0 +1,14 @@ + +setJitCompilerOption("ion.warmup.trigger", 30); +function ArrayCallback(state) { + return this.state = state; +} +ArrayCallback.prototype.isUpperCase = function(v, index, array) { + return this.state ? true : (v == v.toUpperCase()); +}; +strings = ['hello', 'Array', 'WORLD']; +obj = new ArrayCallback(false); +strings.filter(obj.isUpperCase, obj) +obj = new ArrayCallback(true); +strings.filter(obj.isUpperCase, obj) +obj.__proto__ = {}; diff --git a/js/src/jit-test/tests/basic/bug1137616.js b/js/src/jit-test/tests/basic/bug1137616.js new file mode 100644 index 0000000000..ca093c1baf --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1137616.js @@ -0,0 +1,9 @@ +// Accessing a name that isn't a global property is a ReferenceError, +// even if a proxy is on the global's prototype chain. +load(libdir + "asserts.js"); +load(libdir + "immutable-prototype.js"); + +var g = newGlobal(); +if (globalPrototypeChainIsMutable()) + g.__proto__ = {}; +assertThrowsInstanceOf(() => g.eval("s += ''"), g.ReferenceError); diff --git a/js/src/jit-test/tests/basic/bug1141154.js b/js/src/jit-test/tests/basic/bug1141154.js new file mode 100644 index 0000000000..a56e6dc132 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1141154.js @@ -0,0 +1,19 @@ +function foo() { + (function() { + Object.preventExtensions(this); + setJitCompilerOption("ion.warmup.trigger", 4); + var g = newGlobal({newCompartment: true}); + g.debuggeeGlobal = this; + g.eval("(" + function () { + dbg = new Debugger(debuggeeGlobal); + dbg.onExceptionUnwind = function (frame, exc) { + var s = '!'; + for (var f = frame; f; f = f.older) + debuggeeGlobal.log += s; + }; + } + ")();"); + try { + j('Number.prototype.toString.call([])'); + } catch (exc) {} + })(); +} foo(); diff --git a/js/src/jit-test/tests/basic/bug1141329.js b/js/src/jit-test/tests/basic/bug1141329.js new file mode 100644 index 0000000000..ee41a61bbb --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1141329.js @@ -0,0 +1,15 @@ +x = [] +Object.defineProperty(x, 7, {}) +function f() { + "use strict" + x.length = { + valueOf: function() { + return 7 + } + } +} +for (var m = 0; m < 9; m++) { + try { + f() + } catch (e) {} +} diff --git a/js/src/jit-test/tests/basic/bug1143106.js b/js/src/jit-test/tests/basic/bug1143106.js new file mode 100644 index 0000000000..6bf81bb654 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1143106.js @@ -0,0 +1,8 @@ +({x:3}), ({x:3}), ({x:3}), ({x:3}), ({x:3}), ({x:3}), +({x:3}), ({x:3}), ({x:3}), ({x:3}), ({x:3}), ({x:3}), +({x:3}), ({x:3}), ({x:3}), ({x:3}), ({x:3}), ({x:3}), +({x:3}), ({x:3}), ({x:3}) + +[{x:3},{x:3},{x:3},{x:3},{x:3},{x:3},{x:3}, + {x:3},{x:3},{x:3},{x:3},{x:3},{x:3},{x:3}, + {x:3},{x:3},{x:3},{x:3},{x:3},{x:3},{x:3}] diff --git a/js/src/jit-test/tests/basic/bug1146836.js b/js/src/jit-test/tests/basic/bug1146836.js new file mode 100644 index 0000000000..2b4f4acec8 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1146836.js @@ -0,0 +1,11 @@ +function f() { + var s = "switch (x) {"; + for (var i=8000; i<16400; i++) { + s += "case " + i + ": return " + i + "; break;"; + } + s += "case 8005: return -1; break;"; + s += "}"; + var g = Function("x", s); + assertEq(g(8005), 8005); +} +f(); diff --git a/js/src/jit-test/tests/basic/bug1147216.js b/js/src/jit-test/tests/basic/bug1147216.js new file mode 100644 index 0000000000..d683d713f6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1147216.js @@ -0,0 +1,25 @@ +// Ensure JSOP_LINENO (emitted after JSOP_EVAL) handles big line +// numbers correctly. +function getsource() { + var s = ""; + for (var i=0; i<66002; i++) { + s += "\n"; + if (i === 66000) + s += "eval('stack = Error().stack');"; + } + return s; +} +function test() { + var stack; + eval(getsource()); + assertEq(stack.indexOf("line 66002") > 0, true); +} +test(); + +function testStrict() { + "use strict"; + var stack; + eval(getsource()); + assertEq(stack.indexOf("line 66002") > 0, true); +} +testStrict(); diff --git a/js/src/jit-test/tests/basic/bug1153057.js b/js/src/jit-test/tests/basic/bug1153057.js new file mode 100644 index 0000000000..7f4ab1b110 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1153057.js @@ -0,0 +1 @@ +({ "0"() { eval(); } }); diff --git a/js/src/jit-test/tests/basic/bug1161762.js b/js/src/jit-test/tests/basic/bug1161762.js new file mode 100644 index 0000000000..ba072c507f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1161762.js @@ -0,0 +1,24 @@ + +for (var actual = .5; actual < 100; actual++) { + var test2 = { + test4: actual + 6, + test2: actual + 9, + printStatus: actual + 10, + isPrototypeOf: actual + 12, + expect: actual + 14, + printErr: actual + 17, + ret2: actual + 19, + printBugNumber: actual + 32, + test3: actual + 33, + String: actual + 34, + summary: actual + 40, + test1: actual + 42, + Array: actual + 43, + BUGNUMBER: actual + 44, + assertEq: actual + 45, + __call__: actual + 47, + x: actual + 48, + test0: actual + 49, + res: actual + 50 + }; +} diff --git a/js/src/jit-test/tests/basic/bug1170355.js b/js/src/jit-test/tests/basic/bug1170355.js new file mode 100644 index 0000000000..cddb3c547d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1170355.js @@ -0,0 +1,3 @@ +x = Array(4294967295); +x[1] = 0; +Array.prototype.shift.call(x); diff --git a/js/src/jit-test/tests/basic/bug1172503-2.js b/js/src/jit-test/tests/basic/bug1172503-2.js new file mode 100644 index 0000000000..2c65b71617 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1172503-2.js @@ -0,0 +1,14 @@ +load(libdir + "immutable-prototype.js"); + +var n = 0; +if (globalPrototypeChainIsMutable()) { + this.__proto__ = new Proxy({}, { + has: function () { + if (++n === 2) + return false; + a = 0; + } + }); + } +a = 0; +assertEq(a, 0); diff --git a/js/src/jit-test/tests/basic/bug1177907.js b/js/src/jit-test/tests/basic/bug1177907.js new file mode 100644 index 0000000000..11bf47fe5c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1177907.js @@ -0,0 +1,4 @@ +// |jit-test| error: TypeError + +var Date_toString = newGlobal().Date.prototype.toString; +(function f(){ f(Date_toString.call({})); })(); diff --git a/js/src/jit-test/tests/basic/bug1180054.js b/js/src/jit-test/tests/basic/bug1180054.js new file mode 100644 index 0000000000..ae23ad3d60 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1180054.js @@ -0,0 +1,6 @@ +function entryFrame_1(d) { + assertJitStackInvariants(); +} +for (i = 0Xa; i < 40; i++) { + new entryFrame_1(); +} diff --git a/js/src/jit-test/tests/basic/bug1182865.js b/js/src/jit-test/tests/basic/bug1182865.js new file mode 100644 index 0000000000..f221b4328c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1182865.js @@ -0,0 +1,8 @@ + +for (var j = 0; j < 99; j++) { + Array[{ + f() { + eval() + } + }]; +} diff --git a/js/src/jit-test/tests/basic/bug1185653.js b/js/src/jit-test/tests/basic/bug1185653.js new file mode 100644 index 0000000000..b29fd6e0cd --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1185653.js @@ -0,0 +1,28 @@ +function f() { + var arr = []; + for (var i=0; i<80; i++) { + var o3 = {foo: i}; + var o2 = {owner: o3}; + arr.push(o2); + } + for (var i=0; i<80; i++) { + var o2 = arr[i]; + var o3 = o2.owner; + Object.defineProperty(o3, "bar", {value: arr, enumerable: false}); + } + assertEq(JSON.stringify(arr).length, 1671); +} +f(); + +function g() { + var arr = []; + for (var i=0; i<100; i++) { + arr.push([1, i]); + } + for (var i=0; i<100; i++) { + for (var p in arr[i]) { + assertEq(p === "0" || p === "1", true); + } + } +} +g(); diff --git a/js/src/jit-test/tests/basic/bug1189744.js b/js/src/jit-test/tests/basic/bug1189744.js new file mode 100644 index 0000000000..6d202e702c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1189744.js @@ -0,0 +1,11 @@ +var obj; +for (var i = 0; i < 100; i++) + obj = {a: 7, b: 13, c: 42, d: 0}; + +Object.defineProperty(obj, "x", { + get: function () { return 3; } +}); +obj.__ob__ = 17; + +Object.defineProperty(obj, "c", {value: 8, writable: true}); +assertEq(obj.__ob__, 17); diff --git a/js/src/jit-test/tests/basic/bug1190733.js b/js/src/jit-test/tests/basic/bug1190733.js new file mode 100644 index 0000000000..2b3f4a419d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1190733.js @@ -0,0 +1,7 @@ + +x = []; +Array.prototype.push.call(x, Uint8ClampedArray); +(function() { + x.length = 9; +})(); +Array.prototype.reverse.call(x); diff --git a/js/src/jit-test/tests/basic/bug1195452.js b/js/src/jit-test/tests/basic/bug1195452.js new file mode 100644 index 0000000000..92d8568574 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1195452.js @@ -0,0 +1,42 @@ +// |jit-test| allow-oom; allow-unhandlable-oom + +var lfcode = new Array(); +lfcode.push(` +function TestCase(e) { + this.expect = e; +} +function writeHeaderToLog() {} +var SECTION = "15.5.4.7-1"; +var TITLE = "String.protoype.lastIndexOf"; +writeHeaderToLog(); +var j = 0; +for (k = 0, i = 0x0021; i < 0x007e; i++, j++, k++) + new TestCase("x" - 1); +LastIndexOf(); +function LastIndexOf() { + if (isNaN(n)) {} +} +`); +lfcode.push(` +oomAfterAllocations(50); +writeHeaderToLog(SECTION + " " + TITLE); +var expect = "Passed"; +try { + eval("this = true"); +} catch (e) { + result = expect; + exception = e.toString(0, 0); +} +new TestCase(); +`); +while (lfcode.length > 0) { + var file = lfcode.shift(); + loadFile(file) +} +function loadFile(lfVarx) { + try { + if (lfVarx.substr(-3) != ".js" && lfVarx.length != 1) { + evaluate(lfVarx); + } + } catch (lfVare) {} +} diff --git a/js/src/jit-test/tests/basic/bug1196579.js b/js/src/jit-test/tests/basic/bug1196579.js new file mode 100644 index 0000000000..1f8f3760e3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1196579.js @@ -0,0 +1,14 @@ + +setJitCompilerOption("ion.warmup.trigger", 30); +var spaces = [ +"\u0009", "\u000b", "\u000c", "\u0020", "\u00a0", "\u1680", +"\u180e", "\u2000", "\u2001", "\u2002", "\u2003", "\u2004", +"\u2005", "\u2006", "\u2007", "\u2008", "\u2009", "\u200a", +]; +var line_terminators = [ "\u2028", "\u2029", "\u000a", "\u000d" ]; +var space_chars = [].concat(spaces, line_terminators); +var non_space_chars = [ "\u200b", "\u200c", "\u200d" ]; +var chars = [].concat(space_chars, non_space_chars); +var is_space = [].concat(space_chars.map(function(ch) { return true; }), +non_space_chars.map(function() { return false; })); +chars.map(function(ch) {}).join(','); diff --git a/js/src/jit-test/tests/basic/bug1203790.js b/js/src/jit-test/tests/basic/bug1203790.js new file mode 100644 index 0000000000..9fee5117f4 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1203790.js @@ -0,0 +1,10 @@ +gczeal(14); +verifyprebarriers(); +x = []; +Array.prototype.push.call(x, new Uint8Array()); +Array.prototype.some.call(x, function() { + try { + y.toString(); + } catch (e) {} +}); +Array.prototype.shift.call(x); diff --git a/js/src/jit-test/tests/basic/bug1204722.js b/js/src/jit-test/tests/basic/bug1204722.js new file mode 100644 index 0000000000..5102b57c9c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1204722.js @@ -0,0 +1,7 @@ + +x = [1e81]; +x.map(function() {}); +x.pop(); +x.push([]); +[].map(function() {}); +eval("[1/0]"); diff --git a/js/src/jit-test/tests/basic/bug1205870.js b/js/src/jit-test/tests/basic/bug1205870.js new file mode 100644 index 0000000000..8340a797c6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1205870.js @@ -0,0 +1,16 @@ + +// Make sure that unboxed arrays can be created with all possible inline +// capacities for the different sizes. +var bools = []; +var ints = []; +var doubles = []; +for (var i = 0; i < 150; i++) { + bools.push(false); + ints.push(0); + doubles.push(0.5); +} +for (var i = 0; i < 150; i++) { + bools = bools.slice(1); + ints = ints.slice(1); + doubles = doubles.slice(1); +} diff --git a/js/src/jit-test/tests/basic/bug1206265.js b/js/src/jit-test/tests/basic/bug1206265.js new file mode 100644 index 0000000000..7787389861 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1206265.js @@ -0,0 +1,8 @@ +x = [ + createIsHTMLDDA(), + function() {} +]; +x.forEach(function() {}); +this.x.sort(function() {}); +assertEq(x[0] instanceof Function, false); +assertEq(x[1] instanceof Function, true); diff --git a/js/src/jit-test/tests/basic/bug1207863.js b/js/src/jit-test/tests/basic/bug1207863.js new file mode 100644 index 0000000000..ef079a3c29 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1207863.js @@ -0,0 +1,21 @@ +// |jit-test| allow-oom; allow-unhandlable-oom; skip-if: !("oomAtAllocation" in this && "resetOOMFailure" in this) + +function oomTest(f) { + var i = 1; + do { + try { + oomAtAllocation(i); + f(); + } catch (e) { + more = resetOOMFailure(); + } + i++; + } while(more); +} +oomTest( + () => 3 + | (function () { + "use strict"; + return eval("f();"); + })() +); diff --git a/js/src/jit-test/tests/basic/bug1208403.js b/js/src/jit-test/tests/basic/bug1208403.js new file mode 100644 index 0000000000..5077fcef04 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1208403.js @@ -0,0 +1,2 @@ +// |jit-test| error: scripted function +byteSizeOfScript(Array); diff --git a/js/src/jit-test/tests/basic/bug1210596.js b/js/src/jit-test/tests/basic/bug1210596.js new file mode 100644 index 0000000000..5efea9fccf --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1210596.js @@ -0,0 +1,4 @@ +var count = 0; +var a = Array.prototype.concat.call([], [, []], []); +a.forEach(function() { count++; }); +assertEq(count, 1); diff --git a/js/src/jit-test/tests/basic/bug1219128-1.js b/js/src/jit-test/tests/basic/bug1219128-1.js new file mode 100644 index 0000000000..7a81d73f0a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1219128-1.js @@ -0,0 +1,8 @@ +// |jit-test| skip-if: !('oomTest' in this) + +evaluate(` + x = evalcx("lazy"); + oomTest(function () { + x.start("1"); + }); +`); diff --git a/js/src/jit-test/tests/basic/bug1219128-2.js b/js/src/jit-test/tests/basic/bug1219128-2.js new file mode 100644 index 0000000000..7208fc3260 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1219128-2.js @@ -0,0 +1,4 @@ +// |jit-test| skip-if: !('oomTest' in this) + +a = evalcx("lazy") +oomTest(() => a.toString) diff --git a/js/src/jit-test/tests/basic/bug1219128-3.js b/js/src/jit-test/tests/basic/bug1219128-3.js new file mode 100644 index 0000000000..feca3eb55c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1219128-3.js @@ -0,0 +1,6 @@ +// |jit-test| skip-if: !('oomTest' in this) + +x = evalcx('lazy'); +oomTest(function() { + x.eval +}); diff --git a/js/src/jit-test/tests/basic/bug1219128-4.js b/js/src/jit-test/tests/basic/bug1219128-4.js new file mode 100644 index 0000000000..41f8b9757a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1219128-4.js @@ -0,0 +1,6 @@ +// |jit-test| skip-if: !('oomTest' in this) + +x = evalcx("lazy"); +oomTest((function() { + evalcx("({", x); +})) diff --git a/js/src/jit-test/tests/basic/bug1219128-5.js b/js/src/jit-test/tests/basic/bug1219128-5.js new file mode 100644 index 0000000000..30dc56e5ce --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1219128-5.js @@ -0,0 +1,6 @@ +// |jit-test| skip-if: !('oomTest' in this) + +x = evalcx("lazy"); +oomTest(function() { + x.of(new(delete y)); +}); diff --git a/js/src/jit-test/tests/basic/bug1219128-6.js b/js/src/jit-test/tests/basic/bug1219128-6.js new file mode 100644 index 0000000000..cb9f4c7170 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1219128-6.js @@ -0,0 +1,6 @@ +// |jit-test| skip-if: !('oomTest' in this) + +a = evalcx("lazy") +oomTest(function() { + a.b +}) diff --git a/js/src/jit-test/tests/basic/bug1219128-7.js b/js/src/jit-test/tests/basic/bug1219128-7.js new file mode 100644 index 0000000000..87ec092f87 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1219128-7.js @@ -0,0 +1,34 @@ +// |jit-test| slow; skip-if: !('oomTest' in this) + +function main() { + const v1 = this.newGlobal(); + function v2(v3,v4) { + oomTest(() => { + const v13 = this.parseModule("apply"); + const v14 = {}; + const v15 = v14.size; + const v17 = Uint16Array !== v15; + const v18 = v17 && Uint16Array; + const v20 = this.objectGlobal(v18); + const v21 = v20.newGlobal(); + const v24 = this.resumeProfilers(); + const v25 = v24 && v21; + const v26 = v25.evalInWorker("9007199254740991"); + function v27(v28,v29) { + } + const v31 = new Promise(v27); + const v33 = this.getModuleEnvironmentNames(v13); + }); + } + const v36 = new Promise(v2); + const v37 = v1.Debugger; + const v38 = v37(); + const v39 = v38.findAllGlobals(); + const v40 = v39.pop(); + const v41 = v40.getOwnPropertyDescriptor(v37); + gc(); +} +try { + main(); +} catch(exn) { +} diff --git a/js/src/jit-test/tests/basic/bug1219128-8.js b/js/src/jit-test/tests/basic/bug1219128-8.js new file mode 100644 index 0000000000..a957b879dc --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1219128-8.js @@ -0,0 +1,4 @@ +// |jit-test| skip-if: !('oomTest' in this) + +a = evalcx('lazy') +oomTest(() => a < 0) diff --git a/js/src/jit-test/tests/basic/bug1219363.js b/js/src/jit-test/tests/basic/bug1219363.js new file mode 100644 index 0000000000..03e4008ab0 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1219363.js @@ -0,0 +1,9 @@ +var x = [1, 2, , 4] +x[100000] = 1; +var y = Object.create(x); +y.a = 1; +y.b = 1; +var arr = []; +for (var z in y) + arr.push(z); +assertEq(arr.join(), "a,b,0,1,3,100000"); diff --git a/js/src/jit-test/tests/basic/bug1232269.js b/js/src/jit-test/tests/basic/bug1232269.js new file mode 100644 index 0000000000..c979d3b400 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1232269.js @@ -0,0 +1,30 @@ + +function f() { + for (var i=0; i<100; i++) { + var obj = {data: {id:1}}; + } + Object.defineProperty(obj, "id", { + configurable: true, + enumerable: false, + get: function() { + return this.data.id; + } + }); + return obj.id; +} +assertEq(f(), 1); + +function f2() { + for (var i=0; i<100; i++) { + var obj = {data: {id:1}}; + } + Object.defineProperty(obj, "id", { + configurable: true, + enumerable: false, + get: function() { return this.data.id; }, + set: function(v) { this.data.id = v; } + }); + obj.id = 3; + return obj.id; +} +assertEq(f2(), 3); diff --git a/js/src/jit-test/tests/basic/bug1234414.js b/js/src/jit-test/tests/basic/bug1234414.js new file mode 100644 index 0000000000..2aeda2c897 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1234414.js @@ -0,0 +1,11 @@ +// |jit-test| skip-if: !('oomTest' in this) + +oomTest(() => { + var max = 400; + function f(b) { + if (b) { + f(b - 1); + } else eval('"use strict"; const z = w; z = 1 + w; c = 5'); + } + f(max - 1); +}); diff --git a/js/src/jit-test/tests/basic/bug1236476.js b/js/src/jit-test/tests/basic/bug1236476.js new file mode 100644 index 0000000000..4e34a0a762 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1236476.js @@ -0,0 +1,18 @@ +// |jit-test| allow-oom; allow-unhandlable-oom +// 1236476 + +if (typeof oomTest !== 'function' || + typeof offThreadCompileToStencil !== 'function' || + typeof finishOffThreadStencil !== 'function' || + typeof evalStencil !== 'function') + quit(); + +oomTest(() => { + offThreadCompileToStencil(` + "use asm"; + return assertEq; + `); + var stencil = finishOffThreadStencil(); + evalStencil(); +}); + diff --git a/js/src/jit-test/tests/basic/bug1237564.js b/js/src/jit-test/tests/basic/bug1237564.js new file mode 100644 index 0000000000..a67174c757 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1237564.js @@ -0,0 +1,8 @@ +// |jit-test| error:ReferenceError: can't access lexical +try { + evaluate("let x = (() => { throw 3 })();"); +} catch(e) { + assertEq(e, 3); +} +Object.defineProperty(this, "x", {}); +(function() { x = 3; })(); diff --git a/js/src/jit-test/tests/basic/bug1238003.js b/js/src/jit-test/tests/basic/bug1238003.js new file mode 100644 index 0000000000..64c89cb273 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1238003.js @@ -0,0 +1,15 @@ +function f(str) { + if (typeof str === 'string') + str = new RegExp(str); + for (var i = 0; i < 2000; i++) + str.test('foo'); +} +f("abc"); + +function g(str) { + if (typeof str === 'string') + str = new RegExp(str); + for (var i = 0; i < 2000; i++) + str.exec('foo'); +} +g("abc"); diff --git a/js/src/jit-test/tests/basic/bug1238630.js b/js/src/jit-test/tests/basic/bug1238630.js new file mode 100644 index 0000000000..021b66af55 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1238630.js @@ -0,0 +1,7 @@ +var g = /1/g; +g.exec('1234561'); +g.exec(); +var r = /uDC38/ug; +r.lastIndex = 1; +var str = "\uD83D\uDC38"; +r.exec(str); diff --git a/js/src/jit-test/tests/basic/bug1240502.js b/js/src/jit-test/tests/basic/bug1240502.js new file mode 100644 index 0000000000..08d6619460 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1240502.js @@ -0,0 +1,2 @@ +// |jit-test| skip-if: !('oomTest' in this) +oomTest(() => eval(`Array(..."ABC")`)); diff --git a/js/src/jit-test/tests/basic/bug1247926.js b/js/src/jit-test/tests/basic/bug1247926.js new file mode 100644 index 0000000000..e93198db31 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1247926.js @@ -0,0 +1,6 @@ + +JSON.parse('[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0]', function(k, v) { return ""; }); +str = "["; +for (i = 0; i < 2048; i++) str += "1," +str += "1]"; +JSON.parse(str); diff --git a/js/src/jit-test/tests/basic/bug1263868.js b/js/src/jit-test/tests/basic/bug1263868.js new file mode 100644 index 0000000000..ba678d71d5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1263868.js @@ -0,0 +1,11 @@ +// |jit-test| skip-if: !('oomTest' in this) +function g(f, params) { + entryPoints(params); +} +function entry1() {}; +s = "g(entry1, {function: entry1});"; +f(s); +f(s); +function f(x) { + oomTest(() => eval(x)); +} diff --git a/js/src/jit-test/tests/basic/bug1264954.js b/js/src/jit-test/tests/basic/bug1264954.js new file mode 100644 index 0000000000..e9d6422798 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1264954.js @@ -0,0 +1,7 @@ +// |jit-test| skip-if: !('oomTest' in this) +function f(x) { + oomTest(() => eval(x)); +} +f(""); +f(""); +f(`eval([ "x = \`\${new Error.lineNumber}" ].join())`); diff --git a/js/src/jit-test/tests/basic/bug1265693.js b/js/src/jit-test/tests/basic/bug1265693.js new file mode 100644 index 0000000000..9922999d1b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1265693.js @@ -0,0 +1,2 @@ +// |jit-test| skip-if: !('oomTest' in this) +oomTest(Function("Function.hasOwnProperty(1.1)")); diff --git a/js/src/jit-test/tests/basic/bug1276882.js b/js/src/jit-test/tests/basic/bug1276882.js new file mode 100644 index 0000000000..4e88122be9 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1276882.js @@ -0,0 +1,5 @@ +// |jit-test| error: sleep interval is not a number +sleep(0.001); +1; +sleep(0.1); +sleep(this); diff --git a/js/src/jit-test/tests/basic/bug1278839.js b/js/src/jit-test/tests/basic/bug1278839.js new file mode 100644 index 0000000000..3756e95d68 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1278839.js @@ -0,0 +1,3 @@ +// |jit-test| skip-if: !('oomTest' in this) +for (var i=0; i<2; i++) + oomTest(() => eval("setJitCompilerOption(eval + Function, 0);")); diff --git a/js/src/jit-test/tests/basic/bug1280252.js b/js/src/jit-test/tests/basic/bug1280252.js new file mode 100644 index 0000000000..486d2d2a51 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1280252.js @@ -0,0 +1,9 @@ +function f() { + x = arguments; + delete x[1]; +} +f(0, 1); +gc(); +assertEq(x.length, 2); +assertEq(0 in x, true); +assertEq(1 in x, false); diff --git a/js/src/jit-test/tests/basic/bug1285227.js b/js/src/jit-test/tests/basic/bug1285227.js new file mode 100644 index 0000000000..7611337082 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1285227.js @@ -0,0 +1,4 @@ +// |jit-test| skip-if: helperThreadCount() === 0 +evalInWorker(` + (new WeakMap).set(FakeDOMObject.prototype, this) +`); diff --git a/js/src/jit-test/tests/basic/bug1292858.js b/js/src/jit-test/tests/basic/bug1292858.js new file mode 100644 index 0000000000..5fde05f6f7 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1292858.js @@ -0,0 +1,60 @@ +// |jit-test| --ion-warmup-threshold=50 +setJitCompilerOption("offthread-compilation.enable", 0); +gcPreserveCode(); + +function test1() { + var caughtInvalidArguments = false; + var a = -1 + try { + var buf = new Uint8ClampedArray(a); + throw new Error("didn't throw"); + } catch (e) { + assertEq(e instanceof RangeError, true, + "expected RangeError, instead threw: " + e); + caughtInvalidArguments = true; + } + assertEq(caughtInvalidArguments, true); +} +test1(); + +function test2() { + var caughtInvalidArguments = false; + var i = 0; + while (true) { + i = (i + 1) | 0; + var a = inIon() ? -1 : 300; + try { + var buf = new Uint8ClampedArray(a); + assertEq(buf.length, 300); + } catch (e) { + assertEq(a, -1); + assertEq(e instanceof RangeError, true, + "expected RangeError, instead threw: " + e); + caughtInvalidArguments = true; + break; + } + } + assertEq(caughtInvalidArguments, true); +} +test2(); + +function test3() { + var caughtInvalidArguments = false; + var i = 0; + while (true) { + i = (i + 1) | 0; + var a = inIon() ? -1 : 0; + try { + var buf = new Uint8ClampedArray(a); + assertEq(buf.length, 0); + } catch (e) { + assertEq(a, -1); + assertEq(e instanceof RangeError, true, + "expected RangeError, instead threw: " + e); + caughtInvalidArguments = true; + break; + } + } + assertEq(caughtInvalidArguments, true); +} +test3(); diff --git a/js/src/jit-test/tests/basic/bug1293258.js b/js/src/jit-test/tests/basic/bug1293258.js new file mode 100644 index 0000000000..79d4dcbd5d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1293258.js @@ -0,0 +1,10 @@ +try { + function test() { + var arr = new Int8Array(400); + var o = new test(true); + arr[idx] = 9; + } + test(); +} catch(e) { + assertEq(""+e, "InternalError: too much recursion"); +} diff --git a/js/src/jit-test/tests/basic/bug1293575.js b/js/src/jit-test/tests/basic/bug1293575.js new file mode 100644 index 0000000000..3e88699e0f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1293575.js @@ -0,0 +1,9 @@ + +function f(y) { + y = 123456; + for (var x = 0; x < 9; ++x) { + z = arguments.callee.arguments; + assertEq(z[0], Math); + } +} +f(Math); diff --git a/js/src/jit-test/tests/basic/bug1295031.js b/js/src/jit-test/tests/basic/bug1295031.js new file mode 100644 index 0000000000..b8afb38025 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1295031.js @@ -0,0 +1,24 @@ +// |jit-test| --ion-warmup-threshold=50 +setJitCompilerOption("offthread-compilation.enable", 0); +gcPreserveCode(); + +try { + while (true) { + a = inIon() ? 0 : 300; + try { + buf = new Uint8ClampedArray(a); + assertEq(buf.length, 300); + } catch (e) { + assertEqa; + } + } +} catch(exc1) {} +loadFile() +function loadFile() { + try { + switch (lfRunTypeId) { + case 1: + eval(); + } + } catch (lfVare) {} +} diff --git a/js/src/jit-test/tests/basic/bug1296015.js b/js/src/jit-test/tests/basic/bug1296015.js new file mode 100644 index 0000000000..824344c6f1 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1296015.js @@ -0,0 +1,13 @@ +// |jit-test| --ion-warmup-threshold=50 +setJitCompilerOption("offthread-compilation.enable", 0); +gcPreserveCode(); + +function f() { + for (var i=0; i<30000; i++) { + var a = inIon() ? 0 : 300; + var buf = new Uint8ClampedArray(a); + (function() {}) * this; + } + try {} catch(e) {} +} +f(); diff --git a/js/src/jit-test/tests/basic/bug1296016.js b/js/src/jit-test/tests/basic/bug1296016.js new file mode 100644 index 0000000000..3411b7114a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1296016.js @@ -0,0 +1,6 @@ +// |jit-test| skip-if: helperThreadCount() === 0 +offThreadCompileToStencil(``); +evalInWorker(` +var stencil = finishOffThreadStencil(); +evalStencil(stencil); +`); diff --git a/js/src/jit-test/tests/basic/bug1296249.js b/js/src/jit-test/tests/basic/bug1296249.js new file mode 100644 index 0000000000..7c8b7c5df4 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1296249.js @@ -0,0 +1,7 @@ +// |jit-test| slow; skip-if: !('oomTest' in this) +function f(x) { + new Int32Array(x); +} + +f(0); +oomTest(() => f(2147483647)); diff --git a/js/src/jit-test/tests/basic/bug1300548.js b/js/src/jit-test/tests/basic/bug1300548.js new file mode 100644 index 0000000000..6f3def77c2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1300548.js @@ -0,0 +1,13 @@ +var g1 = newGlobal(); +var g2 = newGlobal({sameZoneAs: g1}); +function f() { + var o = Object.create(null); + for (var p in o) {}; +} +g1.eval(f.toString()); +g2.eval(f.toString()); + +for (var i=0; i<10; i++) { + g1.eval("f()"); + g2.eval("f()"); +} diff --git a/js/src/jit-test/tests/basic/bug1300904.js b/js/src/jit-test/tests/basic/bug1300904.js new file mode 100644 index 0000000000..2274129366 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1300904.js @@ -0,0 +1,6 @@ +// |jit-test| skip-if: !('oomTest' in this) +Object.getOwnPropertyNames(this); +oomTest(function() { + this[0] = null; + Object.freeze(this); +}); diff --git a/js/src/jit-test/tests/basic/bug1301797.js b/js/src/jit-test/tests/basic/bug1301797.js new file mode 100644 index 0000000000..0822943e38 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1301797.js @@ -0,0 +1,4 @@ +var arr = new Uint8ClampedArray(10*1024*1024); +var sum = 0; +for (var i = 0; i < 10000; i++) + sum += arr[i]; diff --git a/js/src/jit-test/tests/basic/bug1302682.js b/js/src/jit-test/tests/basic/bug1302682.js new file mode 100644 index 0000000000..12808092b0 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1302682.js @@ -0,0 +1,10 @@ +// |jit-test| --ion-warmup-threshold=50 +setJitCompilerOption("offthread-compilation.enable", 0); +gcPreserveCode(); + +for (var i = 0; i < 30000; i++) { + var a = inIon() ? 7 : 300; + var buf = new Uint8ClampedArray(a); + (function() {}) * this; + try {} catch (e) {} +} diff --git a/js/src/jit-test/tests/basic/bug1310418.js b/js/src/jit-test/tests/basic/bug1310418.js new file mode 100644 index 0000000000..abbfa6127a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1310418.js @@ -0,0 +1,9 @@ +(function(stdlib, n, heap) { + "use asm"; + var Uint8ArrayView = new stdlib.Uint8Array(heap); + function f(d1) { + d1 = +d1; + var d2 = .0; + Uint8ArrayView[d1 < d2] = 0 + 3 + (d2 > -0); + } +})(this, 0>>0, new Int32Array(0)) diff --git a/js/src/jit-test/tests/basic/bug1317402.js b/js/src/jit-test/tests/basic/bug1317402.js new file mode 100644 index 0000000000..127af2e62d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1317402.js @@ -0,0 +1,8 @@ +gczeal(9); +let o = {p1:0, p2:0, set p3({}) {}, p4:1, p5:1, + p6:1, p7:1, p8:1, p9:1, p10:1, p11:1}; +for (let p in o) + x = o[p]; +delete o.p3; +for (let i = 0; i < 100; i++) + x = -o; diff --git a/js/src/jit-test/tests/basic/bug1341326.js b/js/src/jit-test/tests/basic/bug1341326.js new file mode 100644 index 0000000000..9bacd45270 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1341326.js @@ -0,0 +1,14 @@ +// |jit-test| skip-if: helperThreadCount() === 0 +function eval(source) { + offThreadCompileModuleToStencil(source); +} +var N = 10000; +var left = repeat_str('(1&', N); +var right = repeat_str(')', N); +var str = 'actual = '.concat(left, '1', right, ';'); +eval(str); +function repeat_str(str, repeat_count) { + var arr = new Array(--repeat_count); + while (repeat_count != 0) arr[--repeat_count] = str; + return str.concat.apply(str, arr); +} diff --git a/js/src/jit-test/tests/basic/bug1344265.js b/js/src/jit-test/tests/basic/bug1344265.js new file mode 100644 index 0000000000..2ffc2f7e5c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1344265.js @@ -0,0 +1,3 @@ +// |jit-test| allow-unhandlable-oom; allow-oom; skip-if: !('oomAfterAllocations' in this) +oomAfterAllocations(1); +newString("a", {external: true}); diff --git a/js/src/jit-test/tests/basic/bug1348407.js b/js/src/jit-test/tests/basic/bug1348407.js new file mode 100644 index 0000000000..133a49018c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1348407.js @@ -0,0 +1,5 @@ +// |jit-test| skip-if: !('oomTest' in this) +x = evalcx("lazy"); +oomTest(function () { + x.eval("1"); +}); diff --git a/js/src/jit-test/tests/basic/bug1355573.js b/js/src/jit-test/tests/basic/bug1355573.js new file mode 100644 index 0000000000..ce2e34c4a1 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1355573.js @@ -0,0 +1,10 @@ +// |jit-test| skip-if: getBuildConfiguration("debug") === true +function f(){}; +Object.defineProperty(f, "name", {value: "a".repeat((1<<30)-2)}); +var ex = null; +try { + len = f.bind().name.length; +} catch (e) { + ex = e; +} +assertEq(ex === "out of memory" || (ex instanceof InternalError), true); diff --git a/js/src/jit-test/tests/basic/bug1372956.js b/js/src/jit-test/tests/basic/bug1372956.js new file mode 100644 index 0000000000..c45fb085f0 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1372956.js @@ -0,0 +1,5 @@ +// |jit-test| error: TypeError +x = {}; +Array.prototype.push.call(x, 0); +Object.freeze(x); +Array.prototype.unshift.call(x, 0); diff --git a/js/src/jit-test/tests/basic/bug1373356.js b/js/src/jit-test/tests/basic/bug1373356.js new file mode 100644 index 0000000000..bf0cef93e4 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1373356.js @@ -0,0 +1,6 @@ +// |jit-test| error:TypeError +x = [0, 0]; +x.shift(); +x.pop(); +Object.preventExtensions(x); +x.unshift(0); diff --git a/js/src/jit-test/tests/basic/bug1380962.js b/js/src/jit-test/tests/basic/bug1380962.js new file mode 100644 index 0000000000..b05624b989 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1380962.js @@ -0,0 +1,11 @@ +// |jit-test| skip-if: !Function.prototype.toSource + +// Source string has balanced parentheses even when the source code was discarded. + +function test() { +eval("var f = function() { return 0; };"); +assertEq(f.toSource(), "(function() {\n [native code]\n})"); +} + +var g = newGlobal({ discardSource: true }); +g.evaluate(test.toString() + "test()"); diff --git a/js/src/jit-test/tests/basic/bug1403679.js b/js/src/jit-test/tests/basic/bug1403679.js new file mode 100644 index 0000000000..72bb046203 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1403679.js @@ -0,0 +1,195 @@ +load(libdir + "asserts.js"); + +const thisGlobal = this; +const otherGlobalSameCompartment = newGlobal({sameCompartmentAs: thisGlobal}); +const otherGlobalNewCompartment = newGlobal({newCompartment: true}); + +const globals = [thisGlobal, otherGlobalSameCompartment, otherGlobalNewCompartment]; + +function testWithOptions(fn, variants = [undefined]) { + for (let variant of variants) { + for (let global of globals) { + for (let options of [ + {}, + {proxy: true}, + {object: new FakeDOMObject()}, + ]) { + fn(options, global, variant); + } + } + } +} + +function testWithGlobals(fn) { + for (let global of globals) { + fn(global); + } +} + +function testBasic(options, global) { + let {object: source, transplant} = transplantableObject(options); + + // Validate that |source| is an object and |transplant| is a function. + assertEq(typeof source, "object"); + assertEq(typeof transplant, "function"); + + // |source| is created in the current global. + assertEq(objectGlobal(source), this); + + // |source|'s prototype is %ObjectPrototype%, unless it's a FakeDOMObject. + let oldPrototype; + if (options.object) { + oldPrototype = FakeDOMObject.prototype; + } else { + oldPrototype = Object.prototype; + } + assertEq(Object.getPrototypeOf(source), oldPrototype); + + // Properties can be created on |source|. + assertEq(source.foo, undefined); + source.foo = 1; + assertEq(source.foo, 1); + + // Calling |transplant| transplants the object and then returns undefined. + assertEq(transplant(global), undefined); + + // |source| was moved into the new global. If the new global is in a + // different compartment, |source| is a now a CCW. + if (global !== otherGlobalNewCompartment) { + assertEq(objectGlobal(source), global); + } else { + assertEq(objectGlobal(source), null); + assertEq(isProxy(source), true); + } + + // The properties are copied over to the swapped object. + assertEq(source.foo, 1); + + // The prototype was changed to %ObjectPrototype% of |global| or the + // FakeDOMObject.prototype. + let newPrototype; + if (options.object) { + newPrototype = global.FakeDOMObject.prototype; + } else { + newPrototype = global.Object.prototype; + } + assertEq(Object.getPrototypeOf(source), newPrototype); +} +testWithOptions(testBasic); + +// Objects can be transplanted multiple times between globals. +function testTransplantMulti(options, global1, global2) { + let {object: source, transplant} = transplantableObject(options); + + transplant(global1); + transplant(global2); +} +testWithOptions(testTransplantMulti, globals); + +// Test the case when the source object already has a wrapper in the target global. +function testHasWrapperInTarget(options, global) { + let {object: source, transplant} = transplantableObject(options); + + // Create a wrapper for |source| in the other global. + global.p = source; + assertEq(global.eval("p"), source); + + if (options.proxy) { + // It's a proxy object either way. + assertEq(global.eval("isProxy(p)"), true); + } else { + if (global === otherGlobalNewCompartment) { + // |isProxy| returns true because |p| is a CCW. + assertEq(global.eval("isProxy(p)"), true); + } else { + // |isProxy| returns false because |p| is not a CCW. + assertEq(global.eval("isProxy(p)"), false); + } + } + + // And now transplant it into that global. + transplant(global); + + assertEq(global.eval("p"), source); + + if (options.proxy) { + // It's a proxy object either way. + assertEq(global.eval("isProxy(p)"), true); + } else { + // The previous CCW was replaced with a same-compartment object. + assertEq(global.eval("isProxy(p)"), false); + } +} +testWithOptions(testHasWrapperInTarget); + +// Test the case when the source object has a wrapper, but in a different compartment. +function testHasWrapperOtherCompartment(options, global) { + let thirdGlobal = newGlobal({newCompartment: true}); + let {object: source, transplant} = transplantableObject(options); + + // Create a wrapper for |source| in the new global. + thirdGlobal.p = source; + assertEq(thirdGlobal.eval("p"), source); + + // And now transplant the object. + transplant(global); + + assertEq(thirdGlobal.eval("p"), source); +} +testWithOptions(testHasWrapperOtherCompartment); + +// Ensure a transplanted object is correctly handled by (weak) collections. +function testCollections(options, global, AnySet) { + let {object, transplant} = transplantableObject(options); + + let set = new AnySet(); + + assertEq(set.has(object), false); + set.add(object); + assertEq(set.has(object), true); + + transplant(global); + + assertEq(set.has(object), true); +} +testWithOptions(testCollections, [Set, WeakSet]); + +// Ensure DOM object slot is correctly transplanted. +function testDOMObjectSlot(global) { + let domObject = new FakeDOMObject(); + let expectedValue = domObject.x; + assertEq(typeof expectedValue, "number"); + + let {object, transplant} = transplantableObject({object: domObject}); + assertEq(object, domObject); + + transplant(global); + + assertEq(object, domObject); + assertEq(domObject.x, expectedValue); +} +testWithGlobals(testDOMObjectSlot); + +function testArgumentValidation() { + // Throws an error if too many arguments are present. + assertThrowsInstanceOf(() => transplantableObject(thisGlobal, {}), Error); + + let {object, transplant} = transplantableObject(); + + // Throws an error if called with no arguments. + assertThrowsInstanceOf(() => transplant(), Error); + + // Throws an error if called with too many arguments. + assertThrowsInstanceOf(() => transplant(thisGlobal, {}), Error); + + // Throws an error if the first argument isn't an object + assertThrowsInstanceOf(() => transplant(null), Error); + + // Throws an error if the argument isn't a global object. + assertThrowsInstanceOf(() => transplant({}), Error); + + // Throws an error if the 'object' option isn't a FakeDOMObject. + assertThrowsInstanceOf(() => transplant({object: null}), Error); + assertThrowsInstanceOf(() => transplant({object: {}}), Error); +} +testArgumentValidation(); diff --git a/js/src/jit-test/tests/basic/bug1407058.js b/js/src/jit-test/tests/basic/bug1407058.js new file mode 100644 index 0000000000..7c0953986b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1407058.js @@ -0,0 +1,16 @@ +"use strict"; +function f() { + var o = {}; + Object.defineProperty(o, "x", {get: undefined, set: undefined}); + for (var i = 0; i < 20; i++) { + var ex = null; + try { + o.x = 9; + } catch (e) { + ex = e; + } + assertEq(ex instanceof TypeError, true); + assertEq(o.x, undefined); + } +} +f(); diff --git a/js/src/jit-test/tests/basic/bug1411294.js b/js/src/jit-test/tests/basic/bug1411294.js new file mode 100644 index 0000000000..327c808bcf --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1411294.js @@ -0,0 +1,12 @@ +// |jit-test| skip-if: !('oomTest' in this) +oomTest(function() { + eval(`var clonebuffer = serialize("abc"); + clonebuffer.clonebuffer = "\ +\\x00\\x00\\x00\\x00\\b\\x00\\xFF\\xFF\\f\ +\\x00\\x00\\x00\\x03\\x00\\xFF\\xFF\\x00\\x00\\x00\\x00\\x00\\x00\\x00\ +\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xF0?\\x00\\x00\\x00\\\x00\\x00\ +\\x00\\xFF\\xFF" + var obj = deserialize(clonebuffer) + assertEq(new ({ get }).keys(obj).toString(), "12,ab"); +`); +}); diff --git a/js/src/jit-test/tests/basic/bug1420961.js b/js/src/jit-test/tests/basic/bug1420961.js new file mode 100644 index 0000000000..24b2c355e5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1420961.js @@ -0,0 +1,5 @@ +var g = newGlobal(); +g.eval("azx918 = 1"); +for (var x in g) { + assertEq(x, x); +} diff --git a/js/src/jit-test/tests/basic/bug1445854.js b/js/src/jit-test/tests/basic/bug1445854.js new file mode 100644 index 0000000000..2bd7f30659 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1445854.js @@ -0,0 +1,4 @@ +// |jit-test| skip-if: !this.hasOwnProperty("ReadableStream") +load(libdir + "asserts.js"); +assertThrowsInstanceOf(() => ReadableStream.prototype.tee(), + TypeError); diff --git a/js/src/jit-test/tests/basic/bug1447996.js b/js/src/jit-test/tests/basic/bug1447996.js new file mode 100644 index 0000000000..ec7cc5a25a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1447996.js @@ -0,0 +1,10 @@ +// |jit-test| skip-if: !('stackTest' in this) + +var x = 0; +function f() { + var s = "abcdef(((((((a|b)a|b)a|b)a|b)a|b)a|b)a|b)" + x; + res = "abcdefa".match(new RegExp(s)); + x++; +} +f(); +stackTest(f, true); diff --git a/js/src/jit-test/tests/basic/bug1459258.js b/js/src/jit-test/tests/basic/bug1459258.js new file mode 100644 index 0000000000..d29231a34a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1459258.js @@ -0,0 +1,7 @@ +// |jit-test| skip-if: !('oomTest' in this) +oomTest(function() { + return [0, Math.PI, NaN, Infinity, true, false, Symbol(), Math.tan, + Reflect, Proxy, print, assertEq, Array, String, Boolean, Number, parseInt, + parseFloat, Math.sin, Math.cos, Math.abs, Math.pow, Math.sqrt, + Uint8Array, Int8Array, Int32Array, Int16Array, Uint16Array]; +}); diff --git a/js/src/jit-test/tests/basic/bug1470732.js b/js/src/jit-test/tests/basic/bug1470732.js new file mode 100644 index 0000000000..fd854d70a2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1470732.js @@ -0,0 +1,10 @@ +// |jit-test| skip-if: helperThreadCount() === 0 +var i = 0; +while(i++ < 500) { + evalInWorker(` + assertFloat32(0x23456789 | 0, false); + `); + let m = parseModule(""); + moduleLink(m); +} + diff --git a/js/src/jit-test/tests/basic/bug1473256.js b/js/src/jit-test/tests/basic/bug1473256.js new file mode 100644 index 0000000000..b0d748cd6d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1473256.js @@ -0,0 +1,5 @@ +var a1 = Reflect.construct(Array, [], Object); +var g = newGlobal({sameZoneAs: this}); +var a2 = new g.Array(1, 2, 3); +assertEq(a1.length, 0); +assertEq(a2.length, 3); diff --git a/js/src/jit-test/tests/basic/bug1483182.js b/js/src/jit-test/tests/basic/bug1483182.js new file mode 100644 index 0000000000..75e7f2e873 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1483182.js @@ -0,0 +1,15 @@ +var lfLogBuffer = ` + function testOuterForInVar() { + return eval("for (var x in {}); (function() { return delete x; })"); + } + testOuterForInVar(); +`; +loadFile(lfLogBuffer); +loadFile(lfLogBuffer); +function loadFile(lfVarx) { + try { + oomTest(function() { + eval(lfVarx); + }); + } catch (lfVare) {} +} diff --git a/js/src/jit-test/tests/basic/bug1492920.js b/js/src/jit-test/tests/basic/bug1492920.js new file mode 100644 index 0000000000..ac7bc57dce --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1492920.js @@ -0,0 +1,41 @@ +var N = 20; +var k = 15; // k < N + +/* test 1: insertion of new blank object in ctor.__proto__ chain */ + +function C() {} +C.__proto__ = Object.create(Function.prototype); + +for (var i = 0; i < N; i++) { + var o = new C(); + assertEq(o instanceof C, true); +} + +/* test 2: overriding of @@hasInstance on the proto chain, partway + * through execution (should trigger a guard) */ + +function D() {} + +for (var i = 0; i < N; i++) { + var o = new D(); + if (i == k) { + D.__proto__ = {[Symbol.hasInstance]() { return false; }}; + } + assertEq(o instanceof D, i < k); +} + +/* test 3: overriding of @@hasInstance on an intermediate object in the proto + * chain */ + +function E() {} + +E.__proto__ = Object.create(Object.create(Object.create(Function.prototype))); +var intermediateProto = E.__proto__.__proto__; + +for (var i = 0; i < N; i++) { + var o = new E; + if (i == k) { + intermediateProto.__proto__ = {[Symbol.hasInstance]() { return false; }}; + } + assertEq(o instanceof E, i < k); +} diff --git a/js/src/jit-test/tests/basic/bug1493627.js b/js/src/jit-test/tests/basic/bug1493627.js new file mode 100644 index 0000000000..ee0525128c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1493627.js @@ -0,0 +1,4 @@ +// |jit-test| skip-if: !('stackTest' in this) +stackTest(function() { + eval(`var g = newGlobal(); recomputeWrappers(this, g);`); +}); diff --git a/js/src/jit-test/tests/basic/bug1516406.js b/js/src/jit-test/tests/basic/bug1516406.js new file mode 100644 index 0000000000..9a513fc1a2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1516406.js @@ -0,0 +1,2 @@ +// |jit-test| skip-if: !('oomTest' in this) +oomTest(() => dumpScopeChain(eval(`b => 1`))); diff --git a/js/src/jit-test/tests/basic/bug1520783.js b/js/src/jit-test/tests/basic/bug1520783.js new file mode 100644 index 0000000000..4142f45385 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1520783.js @@ -0,0 +1,2 @@ +// |jit-test| error: Error +createMappedArrayBuffer(""); diff --git a/js/src/jit-test/tests/basic/bug1527592.js b/js/src/jit-test/tests/basic/bug1527592.js new file mode 100644 index 0000000000..109bc88dc5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1527592.js @@ -0,0 +1,7 @@ +// |jit-test| error:dead object +var g1 = newGlobal(); +var g2 = newGlobal({newCompartment: true}); +var f = g2.Function(""); +nukeAllCCWs(); +var c = new class extends f {}; +c(); diff --git a/js/src/jit-test/tests/basic/bug1532265.js b/js/src/jit-test/tests/basic/bug1532265.js new file mode 100644 index 0000000000..500b6e4a64 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1532265.js @@ -0,0 +1,33 @@ +// |jit-test| allow-oom; skip-if: !('oomTest' in this) + +ignoreUnhandledRejections(); + +var v = {} +async function f() { + // Increasing level of stack size during await to make OOM more likely when + // saving the stack state. + [await v]; + [[await v]]; + [[[await v]]]; + [[[[await v]]]]; + [[[[[await v]]]]]; + [[[[[[await v]]]]]]; + [[[[[[[await v]]]]]]]; + [[[[[[[[await v]]]]]]]]; + [[[[[[[[[await v]]]]]]]]]; + [[[[[[[[[[await v]]]]]]]]]]; +} + +oomTest(function() { + for (var i = 0; i < 8; ++i) { + f(); + } + + // Drain all jobs, ignoring any OOM errors. + while (true) { + try { + drainJobQueue(); + break; + } catch {} + } +}); diff --git a/js/src/jit-test/tests/basic/bug1548759-1.js b/js/src/jit-test/tests/basic/bug1548759-1.js new file mode 100644 index 0000000000..6e6f795cad --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1548759-1.js @@ -0,0 +1,6 @@ +// |jit-test| skip-if: !('oomTest' in this) +(function() { + oomTest(async function() { + x; + }) +})(); diff --git a/js/src/jit-test/tests/basic/bug1548759-2.js b/js/src/jit-test/tests/basic/bug1548759-2.js new file mode 100644 index 0000000000..5e0eef54cc --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1548759-2.js @@ -0,0 +1,8 @@ +// |jit-test| skip-if: !('oomTest' in this) +oomTest(function() { + return { + x: async function() { + y + }(), z + } +}); diff --git a/js/src/jit-test/tests/basic/bug1549035.js b/js/src/jit-test/tests/basic/bug1549035.js new file mode 100644 index 0000000000..f1d85bcbe3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1549035.js @@ -0,0 +1,11 @@ +var expected = 2; +for (var i = 0; i < 100; ++i) { + if (i === 50) { + expected = 0; + String.prototype[Symbol.split] = function() { + return []; + }; + } + var r = "ab".split(""); + assertEq(r.length, expected); +} diff --git a/js/src/jit-test/tests/basic/bug1554748.js b/js/src/jit-test/tests/basic/bug1554748.js new file mode 100644 index 0000000000..a272db1de5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1554748.js @@ -0,0 +1 @@ +undefined + { valueOf: Object }; diff --git a/js/src/jit-test/tests/basic/bug1568029.js b/js/src/jit-test/tests/basic/bug1568029.js new file mode 100644 index 0000000000..0400d4573c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1568029.js @@ -0,0 +1,19 @@ +function TestObject(a) { + this.a = 1; + if (a >= 0) { + this.b = 2; + } + + if (a > 0) { + new TestObject(a - 1); + } +} + +// Force analysis. There may be a better way. +for (let i = 0; i < 1000; i++) { + new TestObject(-1); +} + +let x = new TestObject(1); +assertEq(x.a, 1); +assertEq(x.b, 2); diff --git a/js/src/jit-test/tests/basic/bug1574725.js b/js/src/jit-test/tests/basic/bug1574725.js new file mode 100644 index 0000000000..f7ccb27d92 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1574725.js @@ -0,0 +1,5 @@ +// |jit-test| skip-if: !('oomTest' in this) || helperThreadCount() === 0 +for (let i = 0; i < 15; ++i) { + evalInWorker("for (var i = 0; i < 100; i++) {}"); +} +oomTest(() => {}); diff --git a/js/src/jit-test/tests/basic/bug1584027.js b/js/src/jit-test/tests/basic/bug1584027.js new file mode 100644 index 0000000000..82fa1b1776 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1584027.js @@ -0,0 +1,3 @@ +// |jit-test| error:unsafe filename: +setTestFilenameValidationCallback(); +evaluate("throw 2", {fileName: "\uDEFF"}); diff --git a/js/src/jit-test/tests/basic/bug1589002.js b/js/src/jit-test/tests/basic/bug1589002.js new file mode 100644 index 0000000000..9ea89923a8 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1589002.js @@ -0,0 +1,7 @@ +var g = newGlobal({newCompartment: true}); +g.parent = this; +g.eval(` + x = "12"; + x += "3"; + parent.evaluate("", {global: this, sourceMapURL: x}); +`); diff --git a/js/src/jit-test/tests/basic/bug1601074.js b/js/src/jit-test/tests/basic/bug1601074.js new file mode 100644 index 0000000000..63bf9a91f6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1601074.js @@ -0,0 +1,13 @@ +for (let y of [ + { x: 1 }, + { x: 2 }, + { x: 3 }, + { x: 4 }, + { x: 5 }, + { x: 6 }, + { x: 7 }, + { x: 8 }, + { x: 9 }, + { x: 10 }, + { x: 11 }, +]) {} diff --git a/js/src/jit-test/tests/basic/bug1610192.js b/js/src/jit-test/tests/basic/bug1610192.js new file mode 100644 index 0000000000..96d1201b75 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1610192.js @@ -0,0 +1,5 @@ +// |jit-test| slow; skip-if: getBuildConfiguration("debug") + +var s = ''; +s += new Uint8Array(2 ** 23 + 2); +eval("[" + s + "1]"); diff --git a/js/src/jit-test/tests/basic/bug1644839-2.js b/js/src/jit-test/tests/basic/bug1644839-2.js new file mode 100644 index 0000000000..cf0f7d8981 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1644839-2.js @@ -0,0 +1,5 @@ +// |jit-test| skip-if: !('oomTest' in this) +var code = ` + (\`\${key}: \${(args[1]?.toString)?.()}\`) +`; +oomTest(function() { return parseModule(code); }); diff --git a/js/src/jit-test/tests/basic/bug1644839.js b/js/src/jit-test/tests/basic/bug1644839.js new file mode 100644 index 0000000000..b83b662358 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1644839.js @@ -0,0 +1,5 @@ +// |jit-test| skip-if: !('oomTest' in this) +var code = ` + (\`\${key}: \${args[1]?.toString()}\`) +`; +oomTest(function() { return parseModule(code); }); diff --git a/js/src/jit-test/tests/basic/bug1656744.js b/js/src/jit-test/tests/basic/bug1656744.js new file mode 100644 index 0000000000..b1fd7cfc61 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1656744.js @@ -0,0 +1,8 @@ +Array.prototype[0] = 'x'; +Array.prototype[1] = 'x'; +var arr = []; +for (var p in arr) { + arr[0] = 0; + arr[1] = 1; + arr.reverse(); +} diff --git a/js/src/jit-test/tests/basic/bug1666856.js b/js/src/jit-test/tests/basic/bug1666856.js new file mode 100644 index 0000000000..ea6e6942d2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1666856.js @@ -0,0 +1,8 @@ +// |jit-test| skip-if: !this.oomTest + +let i = 10000; +oomTest(() => { + let arr = []; + arr[i++] = 1; + for (var key in arr) {} +}); diff --git a/js/src/jit-test/tests/basic/bug1669616.js b/js/src/jit-test/tests/basic/bug1669616.js new file mode 100644 index 0000000000..7c48b229a5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1669616.js @@ -0,0 +1,9 @@ +enableLastWarning(); +eval(` + function blah() { + return 0; + if (true) {} /* no newline here */ 400n == "abc"; + } +`); +assertEq(getLastWarning().message, "unreachable code after return statement"); +blah(); diff --git a/js/src/jit-test/tests/basic/bug1678442.js b/js/src/jit-test/tests/basic/bug1678442.js new file mode 100644 index 0000000000..d2f3dd5823 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1678442.js @@ -0,0 +1,6 @@ +var fun = function() {}; +var newTarget = (function(){}).bind(); +Object.defineProperty(newTarget, "prototype", {get() { relazifyFunctions() }}); +for (var i = 0; i < 10; i++) { + Reflect.construct(fun, [], newTarget); +} diff --git a/js/src/jit-test/tests/basic/bug1700525.js b/js/src/jit-test/tests/basic/bug1700525.js new file mode 100644 index 0000000000..80424f7e2f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1700525.js @@ -0,0 +1,14 @@ +// Get a dictionary object. +var o = {x: 1, y: 2, z: 3}; +delete o.x; + +// Redefine |y| as an accessor. +var val = 0; +Object.defineProperty(o, "y", {get: () => val, set: v => { val = v; }}); + +// Optimized Object.assign path should fail. +Object.assign(o, {x: 3, y: 4, z: 5}); +assertEq(val, 4); +assertEq(o.x, 3); +assertEq(o.y, 4); +assertEq(o.z, 5); diff --git a/js/src/jit-test/tests/basic/bug1707820.js b/js/src/jit-test/tests/basic/bug1707820.js new file mode 100644 index 0000000000..d635965f7a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1707820.js @@ -0,0 +1,9 @@ +gczeal(4); +let a = "x".repeat(100); +for (let i = 0; i < 50; i++) { + let s = new String(a); + s.a = 0; + s.b = 0; + delete s.a; + Object.keys(s); +} diff --git a/js/src/jit-test/tests/basic/bug1717408.js b/js/src/jit-test/tests/basic/bug1717408.js new file mode 100644 index 0000000000..5ee6fbfaa1 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1717408.js @@ -0,0 +1,5 @@ +let g = newGlobal({newCompartment: true}); +g.evaluate("obj = {}") +g.obj.__proto__ = {}; +recomputeWrappers(); +g.evaluate("obj.x = 1"); diff --git a/js/src/jit-test/tests/basic/bug1721006.js b/js/src/jit-test/tests/basic/bug1721006.js new file mode 100644 index 0000000000..1f48286175 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1721006.js @@ -0,0 +1,15 @@ +// |jit-test| --no-threads; --baseline-warmup-threshold=10; --ion-warmup-threshold=100 + +function foo() { + let x = 1; + let y = 1; + let z = 1; + for (let i = 0; i < 4; i++) {} + for (let i = 0; i < 1000; i++) { + y &= x; + for (let j = 0; j < 100; j++) {} + x = z; + for (let j = 0; j < 8; j++) {} + } +} +foo(); diff --git a/js/src/jit-test/tests/basic/bug1731540.js b/js/src/jit-test/tests/basic/bug1731540.js new file mode 100644 index 0000000000..fc445cc58f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1731540.js @@ -0,0 +1,4 @@ +// |jit-test| exitstatus: 6 +v11 = undefined; +interruptIf(true); +for (v63 in v11); diff --git a/js/src/jit-test/tests/basic/bug1733899.js b/js/src/jit-test/tests/basic/bug1733899.js new file mode 100644 index 0000000000..4d829be655 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1733899.js @@ -0,0 +1,14 @@ +a = {} +a[Symbol.iterator] = function() { + return { + next() { + return { + done: this + } + } + } +} +function b([[]] = a) {} +try { + b(); +} catch {} diff --git a/js/src/jit-test/tests/basic/bug1754968.js b/js/src/jit-test/tests/basic/bug1754968.js new file mode 100644 index 0000000000..534b4631cc --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1754968.js @@ -0,0 +1,4 @@ +const root = {a:0, b:0}; +const subclass = Object.create(root); +const instance = Object.create(subclass); +Object.assign(subclass, root); diff --git a/js/src/jit-test/tests/basic/bug1757476.js b/js/src/jit-test/tests/basic/bug1757476.js new file mode 100644 index 0000000000..b103a89f5c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1757476.js @@ -0,0 +1,16 @@ +// |jit-test| --blinterp-eager; --ion-warmup-threshold=0; --fast-warmup; --no-threads + +function bar(x, y) { + return ((Math.fround(x) && Math.fround(y)) >>> 0) + y & x | 0 + undef(); +}; + +function foo(f, inputs) { + for (var j = 0; j < inputs.length; ++j) + for (var k = 0; k < inputs.length; ++k) + try { + f(inputs[j], inputs[k]); + } catch {} + +} + +foo(bar, [1, 1, 1, 1, 1, 1, 1, 1, -0x080000001, -0x0ffffffff]); diff --git a/js/src/jit-test/tests/basic/bug1759029-1.js b/js/src/jit-test/tests/basic/bug1759029-1.js new file mode 100644 index 0000000000..2f379cab5c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1759029-1.js @@ -0,0 +1,26 @@ +// |jit-test| --fast-warmup; --no-threads + +var arr = []; +arr[0] = 1; +arr[NaN] = 0; + +function foo() { + for (let i = 0; i < 7; i++) { + const a = i % i; + counter += a >>> a; + + try { + throw 3; + } catch { + counter += arr[a]; + } + } + for (let i = 0; i < 100; i++) { } +} + +let counter = 0; +for (var i = 0; i < 10; i++) { + foo(); +} + +assertEq(counter, 60); diff --git a/js/src/jit-test/tests/basic/bug1759029-2.js b/js/src/jit-test/tests/basic/bug1759029-2.js new file mode 100644 index 0000000000..9e5b725c3c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1759029-2.js @@ -0,0 +1,27 @@ +// |jit-test| --fast-warmup; --no-threads + +var arr = []; +arr[0] = 1; +arr[NaN] = 0; + +function foo(a) { + "use strict"; + for (let i = 0; i < 7; i++) { + a = i % i; + counter += a >>> a; + + try { + throw 3; + } catch { + counter += arr[a]; + } + } + for (let i = 0; i < 100; i++) { } +} + +let counter = 0; +for (var i = 0; i < 10; i++) { + foo(); +} + +assertEq(counter, 60); diff --git a/js/src/jit-test/tests/basic/bug1797486.js b/js/src/jit-test/tests/basic/bug1797486.js new file mode 100644 index 0000000000..e901a15f34 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1797486.js @@ -0,0 +1,5 @@ +let v2 = []; +for (let v6 = 0; v6 < 550000; v6++) { + v2[v6] = 0; + delete v2[v6]; +} diff --git a/js/src/jit-test/tests/basic/bug1814000.js b/js/src/jit-test/tests/basic/bug1814000.js new file mode 100644 index 0000000000..1a0d47f947 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1814000.js @@ -0,0 +1,12 @@ +// Don't crash because we're exposing a ScriptSourceObject to JS. +evaluate(` +const src = \` + [function f() { + const v = eval("[]"); + v[0] = function() {}; + newGlobal({sameZoneAs: this}).findPath(v, src); + }] +\`; +var arr = eval(src); +arr[0](); +`, {envChainObject: {}}); diff --git a/js/src/jit-test/tests/basic/bug1816311.js b/js/src/jit-test/tests/basic/bug1816311.js new file mode 100644 index 0000000000..e3683922e3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1816311.js @@ -0,0 +1,13 @@ +const v1 = ["foo"]; +const v17 = {...this}; +const glob = newGlobal({sameZoneAs: this}); +const dbg = glob.Debugger({}); +const v0 = eval(` + const frame = dbg.getNewestFrame(); + with (frame) { + for (const v13 in eval("function f9() {}")) {} + } + const v15 = [v1]; + findPath(v15, v15); +`); +JSON.stringify(v0); diff --git a/js/src/jit-test/tests/basic/bug1821959.js b/js/src/jit-test/tests/basic/bug1821959.js new file mode 100644 index 0000000000..d7fbe7260f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1821959.js @@ -0,0 +1,7 @@ +// Transplant an object that is using the shifted-dense-elements optimization +const v1 = this.transplantableObject(); +const v2 = v1.object; +Array.prototype.push.call(v2, 0); +Array.prototype.push.call(v2, 0); +Array.prototype.shift.call(v2); +v1.transplant(newGlobal()); diff --git a/js/src/jit-test/tests/basic/bug1822962.js b/js/src/jit-test/tests/basic/bug1822962.js new file mode 100644 index 0000000000..ca04b0b753 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1822962.js @@ -0,0 +1,2 @@ +newGlobal({newCompartment: true}).help(/a|b/); +gc(); diff --git a/js/src/jit-test/tests/basic/bug1827072.js b/js/src/jit-test/tests/basic/bug1827072.js new file mode 100644 index 0000000000..9e47c26cd7 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1827072.js @@ -0,0 +1,19 @@ +assertThrows(() => newString("", { capacity: 1 })); +assertThrows(() => newString("x", { capacity: 2 })); + +// Too large for an inline string. +const nonInlineLinear = "123456789012345678901234567890"; +assertEq(nonInlineLinear.length, 30); + +newString(nonInlineLinear, { capacity: 29, tenured: true }); +newString(nonInlineLinear, { capacity: 30, tenured: true }); +newString(nonInlineLinear, { capacity: 31, tenured: true }); + +function assertThrows(f) { + try { + f(); + } catch { + return; + } + throw new Error("missing error"); +} diff --git a/js/src/jit-test/tests/basic/bug1833517.js b/js/src/jit-test/tests/basic/bug1833517.js new file mode 100644 index 0000000000..798ddbc325 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1833517.js @@ -0,0 +1,6 @@ +enableShellAllocationMetadataBuilder(); +(function f() { + (function () { + f; + }); +})(); diff --git a/js/src/jit-test/tests/basic/bug1845698.js b/js/src/jit-test/tests/basic/bug1845698.js new file mode 100644 index 0000000000..1dc569879b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1845698.js @@ -0,0 +1,9 @@ +function f() { + var o = {x: 1, y: 2}; + Object.defineProperty(o, "z", {value: 3, configurable: false}); + delete o.x; + var snapshot = createShapeSnapshot(o); + delete o.y; + checkShapeSnapshot(snapshot); +} +f(); diff --git a/js/src/jit-test/tests/basic/bug1866540.js b/js/src/jit-test/tests/basic/bug1866540.js new file mode 100644 index 0000000000..b02a80b63f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1866540.js @@ -0,0 +1,10 @@ +// |jit-test| skip-if: helperThreadCount() === 0 + +// On x86, MaxCodePages is 2240. Because we sometimes leave a one-page +// gap, this will guarantee there are no free two-page chunks. +for (var i = 0; i < 2200; i++) { + evalcx("function s(){}", evalcx('lazy')); +} + +// Allocating trampolines for the JitRuntime requires two pages. +evalInWorker(""); diff --git a/js/src/jit-test/tests/basic/bug1870747.js b/js/src/jit-test/tests/basic/bug1870747.js new file mode 100644 index 0000000000..c97e056f06 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1870747.js @@ -0,0 +1,7 @@ +// |jit-test| --fast-warmup; --no-threads; --ion-check-range-analysis; --arm-hwcap=vfp +function foo(x) { return x % -1; } + +with ({}) {} +for (var i = 0; i < 1000; i++) { + foo(i); +} diff --git a/js/src/jit-test/tests/basic/bug1875363.js b/js/src/jit-test/tests/basic/bug1875363.js new file mode 100644 index 0000000000..67dd8b6d1b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1875363.js @@ -0,0 +1,8 @@ +// |jit-test| --fuzzing-safe; --baseline-eager; --arm-hwcap=vfp +function f() {}; +f(); +f(); +f(); +try { + print(disnative(f)); +} catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug1877586.js b/js/src/jit-test/tests/basic/bug1877586.js new file mode 100644 index 0000000000..d6ff5b1ae3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1877586.js @@ -0,0 +1,9 @@ +// |jit-test| skip-if: !('oomAtAllocation' in this); allow-oom +try { + for (let i = 0; i < 5; i++) { + WebAssembly.instantiateStreaming( + wasmTextToBinary('(module (func) (export "" (func 0)))') + ); + } +} catch (e) {} +oomAtAllocation(7, 7); diff --git a/js/src/jit-test/tests/basic/bug504587-1.js b/js/src/jit-test/tests/basic/bug504587-1.js new file mode 100644 index 0000000000..a489f99cac --- /dev/null +++ b/js/src/jit-test/tests/basic/bug504587-1.js @@ -0,0 +1,13 @@ +// This test case failed a WIP patch. See https://bugzilla.mozilla.org/show_bug.cgi?id=504587#c68 + +function B() {} +B.prototype.x = 1; +var d = new B; + +var names = ['z', 'z', 'z', 'z', 'z', 'z', 'z', 'x']; +for (var i = 0; i < names.length; i++) { + x = d.x; // guard on shapeOf(d) + d[names[i]] = 2; // unpredicted shape change + y = d.x; // guard here is elided +} +assertEq(y, 2); // Assertion failed: got 1, expected 2 diff --git a/js/src/jit-test/tests/basic/bug507180.js b/js/src/jit-test/tests/basic/bug507180.js new file mode 100644 index 0000000000..9d8fb19580 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug507180.js @@ -0,0 +1,69 @@ +var o = { + valueOf : function() { + return { + toString : function() { return "fail" } + } + }, + toString : function() { return "good" } +}; + +var p = { + valueOf : function() { + return { + toString : function() { return "0" } + } + }, + toString : function() { return "7" } +}; + +var q = { + toString : function() { + return { + valueOf : function() { return "0" } + } + }, + valueOf : function() { return "7" } +}; + +function assert(b, s) { + if (b) + return; + assertEq("imacro produces incorrect result for " + s, "fail"); +} + +function run() { + for (var i = 0; i < 5; ++i) { + // equality / inequality + assert(!(o == "fail"), "obj == any"); + assert(!("fail" == o), "any == obj"); + assert(!(o != "good"), "obj != any"); + assert(!("good" != o), "any != obj"); + + // binary + assert(!((p | 3) != 7), "obj | any"); + assert(!((3 | p) != 7), "any | obj"); + assert(!((p | p) != 7), "obj | obj"); + assert(!((p & 3) != 3), "obj & any"); + assert(!((3 & p) != 3), "any & obj"); + assert(!((p & p) != 7), "obj & obj"); + assert(!((p * 3) != 21), "obj * any"); + assert(!((3 * p) != 21), "any * obj"); + assert(!((p * p) != 49), "obj * obj"); + + // addition + assert(!(o + "" != "good"), "obj + any"); + assert(!("" + o != "good"), "any + obj"); + assert(!(o + o != "goodgood"), "any + any"); + + // sign + assert(!(-p != -7), "-obj"); + assert(!(+p != 7), "+obj"); + + // String + assert(!(String(q) != "7"), "String(obj)"); + assert(!(new String(q) != "7"), "new String(obj)"); + } + return true; +} + +run(); diff --git a/js/src/jit-test/tests/basic/bug509639.js b/js/src/jit-test/tests/basic/bug509639.js new file mode 100644 index 0000000000..7c5b0c7919 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug509639.js @@ -0,0 +1,3 @@ +// don't crash + +(function(){ var c; eval("for(c in [1,2,3,4]) {}") })(); diff --git a/js/src/jit-test/tests/basic/bug509982.js b/js/src/jit-test/tests/basic/bug509982.js new file mode 100644 index 0000000000..36b9364a1f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug509982.js @@ -0,0 +1,15 @@ +function g() { + const e = 0; + return function () { + switch (7) { + case e: + } + }; +} + +for (var i = 0; i < 2; i++) { + let f = g; + f(); +} + +// Just test that we don't crash. diff --git a/js/src/jit-test/tests/basic/bug510434.js b/js/src/jit-test/tests/basic/bug510434.js new file mode 100644 index 0000000000..253352e29d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug510434.js @@ -0,0 +1,2 @@ +var f = function(){ var arguments = 3; for (var j=0;j<4;++j) print(arguments); }; +f(); diff --git a/js/src/jit-test/tests/basic/bug510437-2.js b/js/src/jit-test/tests/basic/bug510437-2.js new file mode 100644 index 0000000000..1fca2067f0 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug510437-2.js @@ -0,0 +1,13 @@ +function f() { + eval("g=function() { \ + for (let x=0; x < 2; ++x) { \ + d=x \ + } \ + }") + g(); + eval("var d") + g(); +} + +f(); +assertEq(d, 1); diff --git a/js/src/jit-test/tests/basic/bug511214.js b/js/src/jit-test/tests/basic/bug511214.js new file mode 100644 index 0000000000..611d86e45a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug511214.js @@ -0,0 +1,18 @@ +eval(1); // avoid global shape change when we call eval below +function q() { + var x = 1; + function f() { + function g() { + var t=0; + for (var i=0; i<3; i++) + x = i; + }; + g(); + eval("var x = 3"); + g(); + assertEq(x, 2); + } + f(); + assertEq(x, 2); +} +q(); diff --git a/js/src/jit-test/tests/basic/bug511241.js b/js/src/jit-test/tests/basic/bug511241.js new file mode 100644 index 0000000000..fe28febb93 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug511241.js @@ -0,0 +1,15 @@ +var d = 1; +function heavy(x) { + eval(x); + return function lite() { + var s = 0; + for (var i = 0; i < 9; i++) + s += d; + return s; + }; +} + +var f1 = heavy("1"); +var f2 = heavy("var d = 100;"); +assertEq(f1(), 9); +assertEq(f2(), 900); diff --git a/js/src/jit-test/tests/basic/bug513038.js b/js/src/jit-test/tests/basic/bug513038.js new file mode 100644 index 0000000000..21cf1c3264 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug513038.js @@ -0,0 +1,16 @@ +// Just don't assert or crash. + +function f() { + let c + try { + (eval("\ + (function(){\ + with(\ + this.__defineGetter__(\"x\", function(){for(a = 0; a < 3; a++){c=a}})\ + ){}\ + })\ + "))() + } catch(e) {} +} +f() +print(x) diff --git a/js/src/jit-test/tests/basic/bug513898-regexp.js b/js/src/jit-test/tests/basic/bug513898-regexp.js new file mode 100644 index 0000000000..48a5d9fd41 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug513898-regexp.js @@ -0,0 +1,51 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: haytjes <hv1989@gmail.com> + */ + +/* Check the undefined pattern is equivalent to empty string. */ + +assertEq(RegExp(undefined).source, '(?:)'); +assertEq(RegExp(undefined).global, false); +assertEq("test".replace(RegExp(undefined), "*"), '*test'); +assertEq(new RegExp(undefined).source, '(?:)'); +assertEq(new RegExp(undefined).global, false); +assertEq('test'.replace(new RegExp(undefined), "*"), '*test'); + +/* Global flags. */ + +assertEq(new RegExp(undefined, "g").global, true); +assertEq("test".replace(new RegExp(undefined, "g"), "*"), "*t*e*s*t*"); +assertEq(RegExp(undefined, "g").global, true); +assertEq("test".replace(RegExp(undefined, "g"), "*"), "*t*e*s*t*"); + +/* Undefined flags. */ + +var re = new RegExp(undefined, undefined); +assertEq(re.multiline, false); +assertEq(re.global, false); +assertEq(re.ignoreCase, false); + +var re = new RegExp("test", undefined); +assertEq(re.multiline, false); +assertEq(re.global, false); +assertEq(re.ignoreCase, false); + +/* Flags argument that requires toString. */ + +function Flags() {}; + +Flags.prototype.toString = function dogToString() { return ""; } + +var re = new RegExp(undefined, new Flags()); +assertEq(re.multiline, false); +assertEq(re.global, false); +assertEq(re.ignoreCase, false); + +Flags.prototype.toString = function dogToString() { return "gim"; } + +var re = new RegExp(undefined, new Flags()); +assertEq(re.multiline, true); +assertEq(re.global, true); +assertEq(re.ignoreCase, true); diff --git a/js/src/jit-test/tests/basic/bug516009.js b/js/src/jit-test/tests/basic/bug516009.js new file mode 100644 index 0000000000..db3a359425 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug516009.js @@ -0,0 +1,20 @@ +var gFutureCalls = []; + +function add_future_call(index, func) +{ + if (!(index in gFutureCalls)) { + gFutureCalls[index] = []; + } +} + +function check_reset_test(time) +{ +} + +check_reset_test(0); + +for (var i = 1; i <= 8; ++i) { + (function(j) { + add_future_call(j, function() { check_reset_test(j); }); + })(i); +} diff --git a/js/src/jit-test/tests/basic/bug517721.js b/js/src/jit-test/tests/basic/bug517721.js new file mode 100644 index 0000000000..77a2c944e6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug517721.js @@ -0,0 +1,8 @@ +try { + for (var j = 0; j < 2; ++j) { + if (j == 1) { + ++(null[2]); + } + } +} catch(e) { +} diff --git a/js/src/jit-test/tests/basic/bug519129.js b/js/src/jit-test/tests/basic/bug519129.js new file mode 100644 index 0000000000..89ba1f9daa --- /dev/null +++ b/js/src/jit-test/tests/basic/bug519129.js @@ -0,0 +1 @@ +(function(){eval("for(l in[0,0,0]){}",0)})() diff --git a/js/src/jit-test/tests/basic/bug520498.js b/js/src/jit-test/tests/basic/bug520498.js new file mode 100644 index 0000000000..55324f6f30 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug520498.js @@ -0,0 +1,9 @@ +var Q = 0; +try { + (function f(i) { Q = i; if (i == 100000) return; f(i+1); })(1) +} catch (e) { +} + +if (Q == 100000) + assertEq(Q, "fail"); + diff --git a/js/src/jit-test/tests/basic/bug522136.js b/js/src/jit-test/tests/basic/bug522136.js new file mode 100644 index 0000000000..98b16df3ae --- /dev/null +++ b/js/src/jit-test/tests/basic/bug522136.js @@ -0,0 +1,10 @@ +var Q = 0; +var thrown = false; +try { + (function f(i) { Q = i; if (i == 200000) return; f(i+1); })(1) +} catch (e) { + thrown = true; +} + +// Exact behavior of recursion check depends on which JIT we use. +assertEq(thrown && Q > 350, true); diff --git a/js/src/jit-test/tests/basic/bug522817.js b/js/src/jit-test/tests/basic/bug522817.js new file mode 100644 index 0000000000..25b5b99f37 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug522817.js @@ -0,0 +1,17 @@ +// This test should not assert in a debug build. + +var q1={}; +var $native = function () { + for (var i = 0, l = arguments.length; i < l; i++) { + arguments[i].extend = function (props) {}; + } +}; +$native(q1, Array, String, Number); +Array.extend({}); +Number.extend({}); +Object.Native = function () { + for (var i = 0; i < arguments.length; i++) { + arguments[i].eeeeee = (function(){}); + } +}; +new Object.Native(q1, Array, String, Number); diff --git a/js/src/jit-test/tests/basic/bug524826-2.js b/js/src/jit-test/tests/basic/bug524826-2.js new file mode 100644 index 0000000000..38e3c27285 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug524826-2.js @@ -0,0 +1,11 @@ +var x = 42; + +function f() { + var a = [{}, {}, {}, {}, {}]; + for (var i = 0; i < 5; i++) + a[i].m = function () {return x}; + for (i = 0; i < 4; i++) + if (a[i].m == a[i+1].m) + throw "FAIL!"; +} +f(); diff --git a/js/src/jit-test/tests/basic/bug524826.js b/js/src/jit-test/tests/basic/bug524826.js new file mode 100644 index 0000000000..225c3591fa --- /dev/null +++ b/js/src/jit-test/tests/basic/bug524826.js @@ -0,0 +1,10 @@ +var x = 42; +function f() { + var a = [new Date, new Date, new Date, new Date, new Date]; + for (var i = 0; i < 5; i++) + a[i].m = function () {return x}; + for (i = 0; i < 4; i++) + if (a[i].m == a[i+1].m) + throw "FAIL!"; +} +f(); diff --git a/js/src/jit-test/tests/basic/bug525028.js b/js/src/jit-test/tests/basic/bug525028.js new file mode 100644 index 0000000000..90200b6bc0 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug525028.js @@ -0,0 +1,16 @@ +// don't crash + +function f() { + var _L1 = arguments; + for (var i = 0; i < _L1.length; i++) { + if (typeof _L1[i] == "string") + _L1[i] = new Object(); + } + print(arguments[2]); +} + +f(1, 2, "3", 4, 5); +f(1, 2, "3", 4, 5); +f(1, 2, "3", 4, 5); +f(1, 2, "3", 4, 5); + diff --git a/js/src/jit-test/tests/basic/bug528116.js b/js/src/jit-test/tests/basic/bug528116.js new file mode 100644 index 0000000000..8a47778f71 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug528116.js @@ -0,0 +1,8 @@ +(function() { + var x = [null, [], null]; + for (var i = 0; i != x.length; ++i) { + eval("for (var b = 0; b < 2; ++b);", x[i]); + } +})(); + +// Just test that we don't crash. diff --git a/js/src/jit-test/tests/basic/bug532568-2.js b/js/src/jit-test/tests/basic/bug532568-2.js new file mode 100644 index 0000000000..47f705810f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug532568-2.js @@ -0,0 +1,20 @@ +var before = ''; +var after = ''; + +function g(b) { + for (var i = 0; i < 10; ++i) { + } +} + +function f(xa_arg) { + var xa = xa_arg; + for (var i = 0; i < 5; ++i) { + var j = i + xa[i]; + before += j + ','; + g(); + after += j + ','; + } +} + +f([ 0, 1, 2, 3, 4 ]); +assertEq(before, after); diff --git a/js/src/jit-test/tests/basic/bug532568.js b/js/src/jit-test/tests/basic/bug532568.js new file mode 100644 index 0000000000..b1cf86c15f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug532568.js @@ -0,0 +1,19 @@ +var actual = ""; + +function f() { + var x = 10; + + var g = function(p) { + for (var i = 0; i < 10; ++i) + x = p + i; + } + + for (var i = 0; i < 10; ++i) { + g(100 * i + x); + actual += x + ','; + } +} + +f(); + +assertEq(actual, "19,128,337,646,1055,1564,2173,2882,3691,4600,"); diff --git a/js/src/jit-test/tests/basic/bug532823.js b/js/src/jit-test/tests/basic/bug532823.js new file mode 100644 index 0000000000..c2b2dc6d5f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug532823.js @@ -0,0 +1,23 @@ +function loop(f) { + var p; + for (var i = 0; i < 10; ++i) { + p = f(); + } + return p; +} + +function f(j, k) { + var g = function() { return k; } + + var ans = ''; + + for (k = 0; k < 5; ++k) { + ans += loop(g); + } + return ans; +} + +var t0 = new Date; +var actual = f(1); + +assertEq(actual, '01234'); diff --git a/js/src/jit-test/tests/basic/bug535474.js b/js/src/jit-test/tests/basic/bug535474.js new file mode 100644 index 0000000000..6e34298a2b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug535474.js @@ -0,0 +1,27 @@ +function f() { + var _76 = {}; + for (var i = 0; i < arguments.length; i++) { + var typ = arguments[i]; + _76[typ] = typ; + } + return function () { + for (var i = 0; i < arguments.length; i++) { + if (!(typeof (arguments[i]) in _76)) { + return false; + } + } + return true; + } +} + +g = f("number", "boolean", "object"); + +g("a", "b", "c", "d", "e", "f", 2); +g(2, "a", "b", "c", "d", "e", "f", 2); + +/* + * Don't assert -- + * Assertion failed: frame entry -4 wasn't freed + * : _activation.entry[i] == 0 (../nanojit/Assembler.cpp:786) + */ + diff --git a/js/src/jit-test/tests/basic/bug535760.js b/js/src/jit-test/tests/basic/bug535760.js new file mode 100644 index 0000000000..dd00b96152 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug535760.js @@ -0,0 +1,13 @@ +/* vim: set ts=8 sts=4 et sw=4 tw=99: */ +function foundit(items, n) { + for (var i = 0; i < 10; i++) + arguments[2](items, this); +} + +function dostuff() { + print(this); +} +foundit('crab', 'crab', dostuff); + +/* Don't crash or assert */ + diff --git a/js/src/jit-test/tests/basic/bug535930.js b/js/src/jit-test/tests/basic/bug535930.js new file mode 100644 index 0000000000..ac985d18ef --- /dev/null +++ b/js/src/jit-test/tests/basic/bug535930.js @@ -0,0 +1,19 @@ +(function () { + p = function () { + Set() + }; + var Set = function () {}; + for (var x = 0; x < 5; x++) { + Set = function (z) { + return function () { + [z] + } + } (x) + } +})() + +/* + * bug 535930, mistakenly generated code to GetUpvar and crashed inside the call. + * so don't crash. + */ + diff --git a/js/src/jit-test/tests/basic/bug536445.js b/js/src/jit-test/tests/basic/bug536445.js new file mode 100644 index 0000000000..16808bb305 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug536445.js @@ -0,0 +1,10 @@ +var x; +var str = "a"; +assertEq(str.charCodeAt(Infinity) | 0, 0); +for (var i = 0; i < 10; ++i) + x = str.charCodeAt(Infinity) | 0; +assertEq(x, 0); +for (var i = 0; i < 10; ++i) + x = str.charCodeAt(Infinity); +assertEq(x | 0, 0); + diff --git a/js/src/jit-test/tests/basic/bug536748.js b/js/src/jit-test/tests/basic/bug536748.js new file mode 100644 index 0000000000..42d8200895 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug536748.js @@ -0,0 +1,8 @@ +// Do not assert. + +var s = "a"; +var b = 32767; + +for (var i = 0; i < 10; ++i) { + b = b & s.charCodeAt(); +} diff --git a/js/src/jit-test/tests/basic/bug539379.js b/js/src/jit-test/tests/basic/bug539379.js new file mode 100644 index 0000000000..dab57f507f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug539379.js @@ -0,0 +1,9 @@ +try { + // On X64 this was crashing rather than causing a "too much recursion" exception. + x = /x/; + (function f() { + x.r = x; + return f() + })(); +} catch (e) {} + diff --git a/js/src/jit-test/tests/basic/bug539553-2.js b/js/src/jit-test/tests/basic/bug539553-2.js new file mode 100644 index 0000000000..244355bccb --- /dev/null +++ b/js/src/jit-test/tests/basic/bug539553-2.js @@ -0,0 +1,9 @@ +// |jit-test| skip-if: !Object.prototype.toSource + +function f() { + var x = arguments; + arguments.length = {}; + for (var i = 0; i < 9; i++) + x.length.toSource(); +} +f(); diff --git a/js/src/jit-test/tests/basic/bug539553-3.js b/js/src/jit-test/tests/basic/bug539553-3.js new file mode 100644 index 0000000000..44b7d41f53 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug539553-3.js @@ -0,0 +1,11 @@ +function g(x) { + assertEq(arguments.length, 1); + assertEq(x.length, 4); +} + +function f() { + for (var i = 0; i < 9; i++) + g(arguments); +} + +f(1, 2, 3, 4); diff --git a/js/src/jit-test/tests/basic/bug539553.js b/js/src/jit-test/tests/basic/bug539553.js new file mode 100644 index 0000000000..41f12c7948 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug539553.js @@ -0,0 +1,11 @@ +function g(x) { + assertEq(x.length, 1); +} + +function f() { + arguments.length = 1; + for (var i = 0; i < 9; i++) + g(arguments); +} + +f(); diff --git a/js/src/jit-test/tests/basic/bug541191-1.js b/js/src/jit-test/tests/basic/bug541191-1.js new file mode 100644 index 0000000000..74ccae8297 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug541191-1.js @@ -0,0 +1,23 @@ +/* vim: set ts=8 sts=4 et sw=4 tw=99: */ + +function g(a, b, c, d) { + return "" + a + b + c + d; +} + +var x = 1; +function f(a, b, c) { + arguments[1] = 2; + arguments[2] = 3; + arguments[3] = 4; + if (!x) + arguments.length = 4; + var k; + for (var i = 0; i < 10; i++) + k = g.apply(this, arguments); + return k; +} + +assertEq(f(1), "1undefinedundefinedundefined"); +x = 0; +assertEq(f(1), "1234"); + diff --git a/js/src/jit-test/tests/basic/bug541191-2.js b/js/src/jit-test/tests/basic/bug541191-2.js new file mode 100644 index 0000000000..d270b7de1e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug541191-2.js @@ -0,0 +1,23 @@ +/* vim: set ts=8 sts=4 et sw=4 tw=99: */ + +function g(a, b, c, d) { + return "" + a + b + c + d; +} + +var x = 1; +function f(a, b, c) { + arguments[1] = 2; + arguments[2] = 3; + arguments[3] = 4; + if (x) + arguments.length = 4; + var k; + for (var i = 0; i < 9; i++) + k = g.apply(this, arguments); + return k; +} + +assertEq(f(1), "1234"); +x = 0; +assertEq(f(1), "1undefinedundefinedundefined"); + diff --git a/js/src/jit-test/tests/basic/bug541191-3.js b/js/src/jit-test/tests/basic/bug541191-3.js new file mode 100644 index 0000000000..f447d49d1e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug541191-3.js @@ -0,0 +1,23 @@ +/* vim: set ts=8 sts=4 et sw=4 tw=99: */ + +function g(a, b, c, d) { + return "" + a + b + c + d; +} + +var x = 1; +function f(a, b, c) { + arguments[1] = 2; + arguments[2] = 3; + arguments[3] = 4; + if (x) + arguments.length = 1; + var k; + for (var i = 0; i < 10; i++) + k = g.apply(this, arguments); + return k; +} + +assertEq(f(1), "1undefinedundefinedundefined"); +x = 0; +assertEq(f(1), "1undefinedundefinedundefined"); + diff --git a/js/src/jit-test/tests/basic/bug541191-4.js b/js/src/jit-test/tests/basic/bug541191-4.js new file mode 100644 index 0000000000..5d15bedb5c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug541191-4.js @@ -0,0 +1,27 @@ +/* vim: set ts=8 sts=4 et sw=4 tw=99: */ + +function g(a, b, c, d) { + return "" + a + b + c + d; +} + +var x = 1; +function f(a, b, c) { + arguments[1] = 2; + arguments[2] = 3; + arguments[3] = 4; + if (x) { + arguments.length = 1; + delete arguments.length; + arguments.__defineGetter__('length', function () { return eval('1'); }); + } + var k; + for (var i = 0; i < 10; i++) + k = g.apply(this, arguments); + return k; +} + +assertEq(f(1), "1undefinedundefinedundefined"); +x = 0; +assertEq(f(1), "1undefinedundefinedundefined"); + + diff --git a/js/src/jit-test/tests/basic/bug541191-5.js b/js/src/jit-test/tests/basic/bug541191-5.js new file mode 100644 index 0000000000..f87217b2cc --- /dev/null +++ b/js/src/jit-test/tests/basic/bug541191-5.js @@ -0,0 +1,24 @@ +/* vim: set ts=8 sts=4 et sw=4 tw=99: */ + +function g(a, b, c, d) { + return "" + a + b + c + d; +} + +var x = 1; +function f(a, b, c) { + arguments[1] = 2; + arguments[2] = 3; + arguments[3] = 4; + if (x) + arguments.length = 1; + var k; + for (var i = 0; i < 10; i++) + k = g.apply(this, arguments); + return k; +} + +assertEq(f(1), "1undefinedundefinedundefined"); +x = 0; +assertEq(f(1), "1undefinedundefinedundefined"); + + diff --git a/js/src/jit-test/tests/basic/bug552196.js b/js/src/jit-test/tests/basic/bug552196.js new file mode 100644 index 0000000000..d526234851 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug552196.js @@ -0,0 +1,12 @@ +(Function("\ + for (a = 0; a < 5; a++)\n\ + (function f(b) {\n\ + if (b > 0) {\n\ + f(b - 1)\n\ + }\n\ + })\n\ + (3)\n\ +"))() + +/* Don't assert. */ + diff --git a/js/src/jit-test/tests/basic/bug557841.js b/js/src/jit-test/tests/basic/bug557841.js new file mode 100644 index 0000000000..903490e6ed --- /dev/null +++ b/js/src/jit-test/tests/basic/bug557841.js @@ -0,0 +1 @@ +eval("for(a = 0; a < 4; a++) x = 1;", []); diff --git a/js/src/jit-test/tests/basic/bug558530.js b/js/src/jit-test/tests/basic/bug558530.js new file mode 100644 index 0000000000..31fa78eadb --- /dev/null +++ b/js/src/jit-test/tests/basic/bug558530.js @@ -0,0 +1,14 @@ +// There's no assertEq() here; the test is just that it doesn't crash. +(function () { + new function () {} +}()); +[function () {}] +gc() +for (z = 0; z < 6; ++z) { + x = [] +} +for (w in [0]) { + x._ = w +} +gc() + diff --git a/js/src/jit-test/tests/basic/bug558531.js b/js/src/jit-test/tests/basic/bug558531.js new file mode 100644 index 0000000000..ddabce8799 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug558531.js @@ -0,0 +1,46 @@ +function f2(c) { + return { + g: c.match(/:/) & c.match(/:/) & c.match(/f/) & c.m & c.a & c.match(/f/) & + c.match(/c/) & c.match(/a/) & (/s/) & c.match(/e/) & c.match(/s/) & + (c.match(/./) & c.i) & (c.match(/\*/)) & (c.match(/n/)), + y: c.a & c.a & c.match(/\)/) & c.match(/\)/) & c.match(/\)/) + & c.match(/\\/), + c: c.match(/f/) + } +} +function f1(c) { + t = f2(c.replace(/s/)) + try { + eval(c) + } catch(e) {} + f4(); + if (c.indexOf("<") == -1 || c.indexOf()) + try {} catch(e) {} + try { + try { + l + } catch(e) {} + if ("unwatch" in this) {} + g + } catch(e) {} + try {} catch(p) {} +} +function f4() { + try {} catch(e) {} { + try { + eval(s + "") + } catch(e) {} + } +} [{}] +s = [{},{}]; +(function(){}()) +s[{},{},{}] = [function(){}] +a = [{},{},{}].concat([{},{}]) +f1("") +f1("") +f1("n") +f1("") +f1("(__proto__=null)") +f1("for(var z=0;z<1;z++){gc()(*::*)}") +f1("gc()") +f1("<") diff --git a/js/src/jit-test/tests/basic/bug558814.js b/js/src/jit-test/tests/basic/bug558814.js new file mode 100644 index 0000000000..63a9f877ba --- /dev/null +++ b/js/src/jit-test/tests/basic/bug558814.js @@ -0,0 +1,10 @@ +function f() +{ + var a = []; + a.length = 10; + for (var i = 0; i < 100; i++) { + var y = a[a.length]; + } +} +f(); +// No assertEq() call, the test is just that it shouldn't assert or crash. diff --git a/js/src/jit-test/tests/basic/bug559912.js b/js/src/jit-test/tests/basic/bug559912.js new file mode 100644 index 0000000000..8f05ff5a3a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug559912.js @@ -0,0 +1,12 @@ + +function s(f) { this._m = f; } +function C() { + Object.defineProperty(this, "m", {set: s}); + this.m = function () {}; +} +var last = {}; +for (var i = 0; i < 20; i++) { + var a = new C; + assertEq(a._m === last._m, false); + last = a; +} diff --git a/js/src/jit-test/tests/basic/bug560234.js b/js/src/jit-test/tests/basic/bug560234.js new file mode 100644 index 0000000000..dc2956a76b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug560234.js @@ -0,0 +1,10 @@ +function test() { + var a = ['x', '', '', '', '', '', '', 'x']; + var b = ''; + for (var i = 0; i < a.length; i++) { + (function() { + a[i].replace(/x/, function() { return b; }); + }()); + } +} +test(); // should NOT get a ReferenceError for b on trace diff --git a/js/src/jit-test/tests/basic/bug560234b.js b/js/src/jit-test/tests/basic/bug560234b.js new file mode 100644 index 0000000000..a008b5f42a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug560234b.js @@ -0,0 +1,12 @@ +function f(a) { + function* g() { + yield function () { return a; }; + } + if (a == 8) + return g(); + a = 3; +} +var x; +for (var i = 0; i < 9; i++) + x = f(i); +x.next().value(); // ReferenceError: a is not defined. diff --git a/js/src/jit-test/tests/basic/bug561279.js b/js/src/jit-test/tests/basic/bug561279.js new file mode 100644 index 0000000000..2160be51b9 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug561279.js @@ -0,0 +1,4 @@ +{ + let y; + eval('eval("for (z = 0; z < 6; z++) a = z;")'); +} diff --git a/js/src/jit-test/tests/basic/bug561359-1.js b/js/src/jit-test/tests/basic/bug561359-1.js new file mode 100644 index 0000000000..4439174e06 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug561359-1.js @@ -0,0 +1,4 @@ +for (let z = 0; z < 2; z++) { + with ({x: function () {}}) + f = x; +} diff --git a/js/src/jit-test/tests/basic/bug561359-2.js b/js/src/jit-test/tests/basic/bug561359-2.js new file mode 100644 index 0000000000..017b9bf338 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug561359-2.js @@ -0,0 +1,8 @@ +function f(s) { + var obj = {m: function () { return a; }}; + eval(s); + return obj; +} +var obj = f("var a = 'right';"); +var a = 'wrong'; +assertEq(obj.m(), 'right'); diff --git a/js/src/jit-test/tests/basic/bug563125.js b/js/src/jit-test/tests/basic/bug563125.js new file mode 100644 index 0000000000..79e43eae4f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug563125.js @@ -0,0 +1,5 @@ +var array = new Array(4294967295); +for (var j = 0; j < 9; ++j) { '' + array.length; } + +// Don't assert. + diff --git a/js/src/jit-test/tests/basic/bug563243.js b/js/src/jit-test/tests/basic/bug563243.js new file mode 100644 index 0000000000..64dc830e83 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug563243.js @@ -0,0 +1,7 @@ +// |jit-test| error:SyntaxError + +(function () { + for (a in (function () { + yield Array.reduce() + })()) function () {} +})() diff --git a/js/src/jit-test/tests/basic/bug566136.js b/js/src/jit-test/tests/basic/bug566136.js new file mode 100644 index 0000000000..2d5f7ffb08 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug566136.js @@ -0,0 +1,11 @@ +load(libdir + "immutable-prototype.js"); + +Object.prototype.length = 0; +if (globalPrototypeChainIsMutable()) + this.__proto__ = []; + +function f() { + eval('Math'); + length = 2; +} +f(); diff --git a/js/src/jit-test/tests/basic/bug566637.js b/js/src/jit-test/tests/basic/bug566637.js new file mode 100644 index 0000000000..6623dbabf8 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug566637.js @@ -0,0 +1,5 @@ +for (var j = 0; j < 9; j++) {
+ var a = j;
+ var b = this.a;
+}
+assertEq(b, 8);
diff --git a/js/src/jit-test/tests/basic/bug568276.js b/js/src/jit-test/tests/basic/bug568276.js new file mode 100644 index 0000000000..4f3f6e7e51 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug568276.js @@ -0,0 +1 @@ +function outer(a) { var b, c, d, e, f, g, h, i; function a() {} } diff --git a/js/src/jit-test/tests/basic/bug569651.js b/js/src/jit-test/tests/basic/bug569651.js new file mode 100644 index 0000000000..58f9c13626 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug569651.js @@ -0,0 +1,3 @@ +// don't crash or assert
+
++Function("switch(\"\"){case 1:case 8:}");
\ No newline at end of file diff --git a/js/src/jit-test/tests/basic/bug570385-1.js b/js/src/jit-test/tests/basic/bug570385-1.js new file mode 100644 index 0000000000..ec9007c010 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug570385-1.js @@ -0,0 +1,9 @@ +var actual = '';
+
+var a = [0, 1];
+for (var i in a) {
+ appendToActual(i);
+ a.pop();
+}
+
+assertEq(actual, "0,");
diff --git a/js/src/jit-test/tests/basic/bug570385-2.js b/js/src/jit-test/tests/basic/bug570385-2.js new file mode 100644 index 0000000000..dc189dd5c0 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug570385-2.js @@ -0,0 +1,9 @@ +var actual = '';
+
+var a = [0, 1];
+for (var i in a) {
+ appendToActual(i);
+ delete a[1];
+}
+
+assertEq(actual, "0,");
diff --git a/js/src/jit-test/tests/basic/bug570385-3.js b/js/src/jit-test/tests/basic/bug570385-3.js new file mode 100644 index 0000000000..f65fabccd4 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug570385-3.js @@ -0,0 +1,11 @@ +var actual = '';
+
+var a = [0, 1];
+a.x = 10;
+delete a.x;
+for (var i in a) {
+ appendToActual(i);
+ a.pop();
+}
+
+assertEq(actual, "0,");
diff --git a/js/src/jit-test/tests/basic/bug570663-1.js b/js/src/jit-test/tests/basic/bug570663-1.js new file mode 100644 index 0000000000..08f14ecf7a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug570663-1.js @@ -0,0 +1,4 @@ +// don't crash +for (var a = 0; a < 4; a++) { + switch (NaN) {} +} diff --git a/js/src/jit-test/tests/basic/bug570663-2.js b/js/src/jit-test/tests/basic/bug570663-2.js new file mode 100644 index 0000000000..bc4b08869d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug570663-2.js @@ -0,0 +1,12 @@ +function f() { + var x; + for (var a = 0; a < 4; a++) { + switch (NaN) { + default: + x = a; + } + } + assertEq(x, 3); +} + +f(); diff --git a/js/src/jit-test/tests/basic/bug572229.js b/js/src/jit-test/tests/basic/bug572229.js new file mode 100644 index 0000000000..c45cea0b6c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug572229.js @@ -0,0 +1,12 @@ +// Don't crash
+
+function f(o, s) {
+ var k = s.substr(0, 1);
+ var c;
+ for (var i = 0; i < 10; ++i) {
+ c = k in o;
+ }
+ return c;
+}
+
+assertEq(f({ a: 66 }, 'abc'), true);
diff --git a/js/src/jit-test/tests/basic/bug572232.js b/js/src/jit-test/tests/basic/bug572232.js new file mode 100644 index 0000000000..f651ca9867 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug572232.js @@ -0,0 +1,4 @@ +// |jit-test| error: TypeError +gczeal(11); +var o = { valueOf: function() { new Object(); gc(); return 17; } }; +(new String.prototype.substring(o)).toString; diff --git a/js/src/jit-test/tests/basic/bug576823-regexp.js b/js/src/jit-test/tests/basic/bug576823-regexp.js new file mode 100644 index 0000000000..175ecb2bce --- /dev/null +++ b/js/src/jit-test/tests/basic/bug576823-regexp.js @@ -0,0 +1,3 @@ +// Sticky should work across disjunctions. + +assertEq(/A|B/y.exec("CB"), null); diff --git a/js/src/jit-test/tests/basic/bug576837-regexp.js b/js/src/jit-test/tests/basic/bug576837-regexp.js new file mode 100644 index 0000000000..956b3eae99 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug576837-regexp.js @@ -0,0 +1,41 @@ +/* + * Check that builtin character classes within ranges produce syntax + * errors. + * + * Note: /\b/ is the backspace escape, which is a single pattern character, + * though it looks deceptively like a character class. + */ + +function isRegExpSyntaxError(pattern) { + try { + var re = new RegExp(pattern); + } catch (e) { + if (e instanceof SyntaxError) + return true; + } + return false; +} + +//assertEq(isRegExpSyntaxError('[C-\\s]'), false); +//assertEq(isRegExpSyntaxError('[C-\\d]'), false); +//assertEq(isRegExpSyntaxError('[C-\\W]'), false); +assertEq(isRegExpSyntaxError('[C-]'), false); +assertEq(isRegExpSyntaxError('[-C]'), false); +assertEq(isRegExpSyntaxError('[C-C]'), false); +assertEq(isRegExpSyntaxError('[C-C]'), false); +assertEq(isRegExpSyntaxError('[\\b-\\b]'), false); +assertEq(isRegExpSyntaxError('[\\B-\\B]'), false); +assertEq(isRegExpSyntaxError('[\\b-\\B]'), false); +assertEq(isRegExpSyntaxError('[\\B-\\b]'), true); +//assertEq(isRegExpSyntaxError('[\\b-\\w]'), false); +//assertEq(isRegExpSyntaxError('[\\B-\\w]'), false); + +/* Extension. */ +assertEq(isRegExpSyntaxError('[\\s-\\s]'), false); +assertEq(isRegExpSyntaxError('[\\W-\\s]'), false); +assertEq(isRegExpSyntaxError('[\\s-\\W]'), false); +assertEq(isRegExpSyntaxError('[\\W-C]'), false); +assertEq(isRegExpSyntaxError('[\\d-C]'), false); +assertEq(isRegExpSyntaxError('[\\s-C]'), false); +assertEq(isRegExpSyntaxError('[\\w-\\b]'), false); +assertEq(isRegExpSyntaxError('[\\w-\\B]'), false); diff --git a/js/src/jit-test/tests/basic/bug576891.js b/js/src/jit-test/tests/basic/bug576891.js new file mode 100644 index 0000000000..5abae94ce2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug576891.js @@ -0,0 +1 @@ +/[&@!)OZ%3,#]/; diff --git a/js/src/jit-test/tests/basic/bug578041.js b/js/src/jit-test/tests/basic/bug578041.js new file mode 100644 index 0000000000..59a1f2910d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug578041.js @@ -0,0 +1,3 @@ +this.__defineGetter__('x', () => new Float32Array()); +with(this) + x; diff --git a/js/src/jit-test/tests/basic/bug579740.js b/js/src/jit-test/tests/basic/bug579740.js new file mode 100644 index 0000000000..26fa1ce22a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug579740.js @@ -0,0 +1,7 @@ +try { + for (a = 0; a < 4; a++) { + new Math.round(0).t + } +} +catch (e) {} +/* Don't assert. */ diff --git a/js/src/jit-test/tests/basic/bug582161.js b/js/src/jit-test/tests/basic/bug582161.js new file mode 100644 index 0000000000..09f9a89194 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug582161.js @@ -0,0 +1,3 @@ +// |jit-test| error: RangeError; +var vs = [1, 1, 1, 1, 3.5, 1]; +for (var i = 0, sz = vs.length; i < sz; i++) new Array(vs[i]); diff --git a/js/src/jit-test/tests/basic/bug582479.js b/js/src/jit-test/tests/basic/bug582479.js new file mode 100644 index 0000000000..246c66780d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug582479.js @@ -0,0 +1,4 @@ +for (b = 0; b < 2; b++) { + / /.exec(function(){}) +} + diff --git a/js/src/jit-test/tests/basic/bug583757.js b/js/src/jit-test/tests/basic/bug583757.js new file mode 100644 index 0000000000..3a7f910bab --- /dev/null +++ b/js/src/jit-test/tests/basic/bug583757.js @@ -0,0 +1,24 @@ +var arr = []; + +function f() {} + +function g(n, h) { + var a = f; + if (n <= 0) + return f; + + var t = g(n - 1, h); + var r = function(x) { + if (x) + return a; + return a(h(function() { return t(); })); + }; + arr.push(r); + return r; +} + +g(80, f); +g(80, f); +g(80, f); +for (var i = 0; i < arr.length; i++) + assertEq(arr[i](1), f); diff --git a/js/src/jit-test/tests/basic/bug584499-1.js b/js/src/jit-test/tests/basic/bug584499-1.js new file mode 100644 index 0000000000..bc98953799 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug584499-1.js @@ -0,0 +1,6 @@ +// |jit-test| error: TypeError +var s = "12345"; +for(var i=0; i<7; i++) { + print(s[i].length); +} + diff --git a/js/src/jit-test/tests/basic/bug584499-2.js b/js/src/jit-test/tests/basic/bug584499-2.js new file mode 100644 index 0000000000..bb31a731e3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug584499-2.js @@ -0,0 +1,12 @@ +function f(x) { + var s = "a"; + var last = ""; + for (var i = 0; i < 10; i++) { + last = s[x]; + } + return last; +} + +f(0); + +assertEq(f(1), undefined); diff --git a/js/src/jit-test/tests/basic/bug584565.js b/js/src/jit-test/tests/basic/bug584565.js new file mode 100644 index 0000000000..ad7d4b4757 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug584565.js @@ -0,0 +1,10 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ +// Contributor: Luke Wagner <lw@mozilla.com> + +var x, f; +for (var i = 0; i < 100; i++) { + f = function() {}; + f.foo; + x = f.length; +} diff --git a/js/src/jit-test/tests/basic/bug584603.js b/js/src/jit-test/tests/basic/bug584603.js new file mode 100644 index 0000000000..4e7607939f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug584603.js @@ -0,0 +1,13 @@ +var f = 99;
+
+function g(a) {
+ if (a) {
+ var e = 55;
+ function f() {
+ print("f");
+ }
+ assertEq(f == 99, false);
+ }
+}
+
+g(true);
diff --git a/js/src/jit-test/tests/basic/bug585542.js b/js/src/jit-test/tests/basic/bug585542.js new file mode 100644 index 0000000000..9ea3de6be6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug585542.js @@ -0,0 +1,11 @@ +function f() { return 2; } +function g(o) { + with (o) { + var f = function() { return 4; } + } + return f(); +} + +assertEq(g({}), 4); + + diff --git a/js/src/jit-test/tests/basic/bug586499-regexp.js b/js/src/jit-test/tests/basic/bug586499-regexp.js new file mode 100644 index 0000000000..3f7f451cff --- /dev/null +++ b/js/src/jit-test/tests/basic/bug586499-regexp.js @@ -0,0 +1,2 @@ +// Don't crash. +var re = /^(?:\s*.){0,16}/; diff --git a/js/src/jit-test/tests/basic/bug586917.js b/js/src/jit-test/tests/basic/bug586917.js new file mode 100644 index 0000000000..7b8b5072a3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug586917.js @@ -0,0 +1,1834 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* The tracer should properly parse JSOP_TABLESWITCHX instructions. */ +var x = 1; +for (i = 0; i < 8; i++) { + switch (x) { + case 2: + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + try {} catch (e) {} + } +} diff --git a/js/src/jit-test/tests/basic/bug587346-regexp-01.js b/js/src/jit-test/tests/basic/bug587346-regexp-01.js new file mode 100644 index 0000000000..cf341a4f63 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug587346-regexp-01.js @@ -0,0 +1 @@ +var re = /(?:){1,60}/ diff --git a/js/src/jit-test/tests/basic/bug587366.js b/js/src/jit-test/tests/basic/bug587366.js new file mode 100644 index 0000000000..9934d987a2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug587366.js @@ -0,0 +1,3 @@ +// Test flat string replacement, per ECMAScriptv5 15.5.4.11. +assertEq("1+2".replace("1+2", "$&+3"), "1+2+3"); +assertEq(")".replace(")","*$&*"), "*)*"); diff --git a/js/src/jit-test/tests/basic/bug589318.js b/js/src/jit-test/tests/basic/bug589318.js new file mode 100644 index 0000000000..98902b0b96 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug589318.js @@ -0,0 +1,10 @@ +// Use arguments in an eval. +code = " \ +function f(a) { var x = a; } \ +for (var i = 0; i < 10; i++) { f(5); } \ +"; + +eval(code); + + +// Test it doesn't assert. diff --git a/js/src/jit-test/tests/basic/bug590006.js b/js/src/jit-test/tests/basic/bug590006.js new file mode 100644 index 0000000000..233aeb2928 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug590006.js @@ -0,0 +1,12 @@ +function f() { + var ret; + for (var i = 0; i < 10; ++i) { + { + let local = 3; + ret = function() { print(local++); } + } + } + return ret; +} +f()(); // test.js:5: ReferenceError: local is not defined + diff --git a/js/src/jit-test/tests/basic/bug590036.js b/js/src/jit-test/tests/basic/bug590036.js new file mode 100644 index 0000000000..25add41ff1 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug590036.js @@ -0,0 +1,13 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +load(libdir + 'eqArrayHelper.js'); + +assertEqArray(eval('[]'), []); +assertEqArray(eval('[,]'), [,]); +assertEqArray(eval('[,,]'), [,,]); +assertEqArray(eval('[1, 1, ]'), [1,1, ]); +assertEqArray(eval('[1, 1, true]'), [1, 1, true]); +assertEqArray(eval('[1, false, true]'), [1, false, true]); diff --git a/js/src/jit-test/tests/basic/bug592927.js b/js/src/jit-test/tests/basic/bug592927.js new file mode 100644 index 0000000000..69f0bd237e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug592927.js @@ -0,0 +1,27 @@ +// vim: set ts=8 sts=4 et sw=4 tw=99: +function f(x, y) { + x(f); + assertEq(y, "hello"); +} + +function g(x) { + assertEq(x.arguments[1], "hello"); + x.arguments[1] = "bye"; + assertEq(x.arguments[1], "hello"); +} + +function f2(x, y) { + arguments; + x(f2); + assertEq(y, "hello"); +} + +function g2(x) { + assertEq(x.arguments[1], "hello"); + x.arguments[1] = "bye"; + assertEq(x.arguments[1], "hello"); +} + +f(g, "hello"); +f2(g2, "hello"); + diff --git a/js/src/jit-test/tests/basic/bug593611.js b/js/src/jit-test/tests/basic/bug593611.js new file mode 100644 index 0000000000..6106c0f5ce --- /dev/null +++ b/js/src/jit-test/tests/basic/bug593611.js @@ -0,0 +1,11 @@ +var global = this; +(function() { + global.__defineGetter__("x", /x/.constructor) +})() +for (var a = 0; a < 4; ++a) { + if (a % 4 == 1) { + gc() + } else { + print(x); + } +} diff --git a/js/src/jit-test/tests/basic/bug593663-regexp.js b/js/src/jit-test/tests/basic/bug593663-regexp.js new file mode 100644 index 0000000000..012a7fb4cd --- /dev/null +++ b/js/src/jit-test/tests/basic/bug593663-regexp.js @@ -0,0 +1,111 @@ +/* + * Ensure that flat matches with metachars in them don't have their metachars + * interpreted as special. + */ + +function isPatternSyntaxError(pattern) { + try { + new RegExp(pattern); + return false; + } catch (e) { + if (!(e instanceof SyntaxError)) + throw e; + return true; + } +} + +// Bug example. +assertEq("1+2".replace("1+2", "$&+3"), "1+2+3"); +assertEq("1112".replace("1+2", ""), "1112"); + +// ^ +assertEq("leading text^my hat".replace("^my hat", ""), "leading text"); +assertEq("my hat".replace("^my hat", ""), "my hat"); + +// $ +assertEq("leading text$my money".replace("leading text$", ""), "my money"); +assertEq("leading text".replace("leading text$", ""), "leading text"); + +// \ +var BSL = '\\'; +assertEq(("dir C:" + BSL + "Windoze").replace("C:" + BSL, ""), + "dir Windoze"); +assertEq(isPatternSyntaxError("C:" + BSL), true); + +// . +assertEq("This is a sentence. It has words.".replace(".", "!"), + "This is a sentence! It has words."); +assertEq("This is an unterminated sentence".replace(".", ""), + "This is an unterminated sentence"); + +// * +assertEq("Video killed the radio *".replace(" *", ""), "Video killed the radio"); +assertEq("aaa".replace("a*", ""), "aaa"); + +// + +assertEq("On the + side".replace(" +", ""), "On the side"); +assertEq("1111111111111".replace("1+", ""), "1111111111111"); + +// \+ +assertEq(("Inverse cone head: " + BSL + "++/").replace(BSL + "+", ""), + "Inverse cone head: +/"); +assertEq((BSL + BSL + BSL).replace(BSL + "+", ""), + BSL + BSL + BSL); + +// \\+ +assertEq((BSL + BSL + "+").replace(BSL + BSL + "+", ""), ""); +assertEq((BSL + BSL + BSL).replace(BSL + BSL + "+", ""), (BSL + BSL + BSL)); + +// \\\ +assertEq((BSL + BSL + BSL + BSL).replace(BSL + BSL + BSL, ""), BSL); +assertEq(isPatternSyntaxError(BSL + BSL + BSL), true); + +// \\\\ +assertEq((BSL + BSL + BSL + BSL).replace(BSL + BSL + BSL + BSL, "", "i"), ""); +assertEq((BSL + BSL).replace(BSL + BSL + BSL + BSL, ""), BSL + BSL); + + +// ? +assertEq("Pressing question?".replace("?", "."), "Pressing question."); +assertEq("a".replace("a?", ""), "a"); + +// ( +assertEq("(a".replace("(", ""), "a"); + +// ) +assertEq("a)".replace(")", ""), "a"); + +// ( and ) +assertEq("(foo)".replace("(foo)", ""), ""); +assertEq("a".replace("(a)", ""), "a"); + +// [ +assertEq("[a".replace("[", ""), "a"); + +// ] +assertEq("a]".replace("]", ""), "a"); + +// [ and ] +assertEq("a".replace("[a-z]", ""), "a"); +assertEq("You would write your regexp as [a-z]".replace("[a-z]", ""), + "You would write your regexp as "); + +// { +assertEq("Numbers may be specified in the interval {1,100}".replace("{1,", ""), + "Numbers may be specified in the interval 100}"); + +// } +assertEq("Numbers may be specified in the interval {1,100}".replace(",100}", ""), + "Numbers may be specified in the interval {1"); + +// { and } +assertEq("Numbers may be specified in the interval {1,100}".replace(" {1,100}", ""), + "Numbers may be specified in the interval"); +assertEq("aaa".replace("a{1,10}", ""), "aaa"); + +// | +assertEq("Mr. Gorbachev|Tear down this wall!".replace("|Tear down this wall!", ""), + "Mr. Gorbachev"); +assertEq("foobar".replace("foo|bar", ""), "foobar"); + +print("PASS"); diff --git a/js/src/jit-test/tests/basic/bug594108.js b/js/src/jit-test/tests/basic/bug594108.js new file mode 100644 index 0000000000..3a250db9f3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug594108.js @@ -0,0 +1,8 @@ +var res; +for (var i = 0; i < 10; i++) { + var re = /a(b)c/; + var b = (re.exec(""), v = re.exec("abc")) !== null; + assertEq(v[0], "abc"); + assertEq(v[1], "b"); +} + diff --git a/js/src/jit-test/tests/basic/bug594205.js b/js/src/jit-test/tests/basic/bug594205.js new file mode 100644 index 0000000000..beaeaa1644 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug594205.js @@ -0,0 +1,16 @@ +var re = /a(b)c/; + +for (var i = 0; i < 10; i++) { + // These two are of a form where we can convert exec() to test(). + if (!re.exec("abc")) print("huh?"); + re.exec("abc"); +} + +RegExp.prototype.test = 1; + +for (var i = 0; i < 10; i++) { + // These two are the same form, but we've replaced test(), so we must + // not convert. + if (!re.exec("abc")) print("huh?"); // don't crash/assert + re.exec("abc"); // don't crash/assert +} diff --git a/js/src/jit-test/tests/basic/bug595963-1.js b/js/src/jit-test/tests/basic/bug595963-1.js new file mode 100644 index 0000000000..2cccfac400 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug595963-1.js @@ -0,0 +1,19 @@ +function remove(k, L) { + for (var i in k) { + if (i == L) + k.splice(L, 1); + } +} +function f(k) { + var L = 0; + for (var i in k) { + if (L == 1) + remove(k, L); + L++; + assertEq(k[i], 3); + } + assertEq(L, 6); +} + +var a = [3, 3, 3, 3, 3, 3, 3]; +f(a); diff --git a/js/src/jit-test/tests/basic/bug595963-2.js b/js/src/jit-test/tests/basic/bug595963-2.js new file mode 100644 index 0000000000..651a38064e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug595963-2.js @@ -0,0 +1,19 @@ +function remove(k, L) { + for (var i in k) { + if (i == L) + k.splice(L, 3); + } +} +function f(k) { + var L = 0; + for (var i in k) { + if (L == 1) + remove(k, L); + L++; + assertEq(k[i], 3); + } + assertEq(L, 4); +} + +var a = [3, 3, 3, 3, 3, 3, 3]; +f(a); diff --git a/js/src/jit-test/tests/basic/bug596351-1.js b/js/src/jit-test/tests/basic/bug596351-1.js new file mode 100644 index 0000000000..f4d764a6d0 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug596351-1.js @@ -0,0 +1,5 @@ +// |jit-test| error: TypeError +"use strict" +var g = newGlobal(); +g.eval("foo = {}; Object.defineProperty(foo, 'a', {value: 2, writable: false});"); +g.foo.a = 3; diff --git a/js/src/jit-test/tests/basic/bug596351-2.js b/js/src/jit-test/tests/basic/bug596351-2.js new file mode 100644 index 0000000000..2a014ad15a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug596351-2.js @@ -0,0 +1,7 @@ +// |jit-test| error: TypeError + +"use strict" +var g = newGlobal(); + +g.eval("bar = {}; Object.freeze(bar);"); +g.bar.a = 4; diff --git a/js/src/jit-test/tests/basic/bug599854.js b/js/src/jit-test/tests/basic/bug599854.js new file mode 100644 index 0000000000..19e3f7c722 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug599854.js @@ -0,0 +1,4 @@ +load(libdir + 'eqArrayHelper.js'); +assertEqArray(/(?:(?:(")(c)")?)*/.exec('"c"'), [ '"c"', '"', "c" ]); +assertEqArray(/(?:(?:a*?(")(c)")?)*/.exec('"c"'), [ '"c"', '"', "c" ]); +assertEqArray(/<script\s*(?![^>]*type=['"]?(?:dojo\/|text\/html\b))(?:[^>]*?(?:src=(['"]?)([^>]*?)\1[^>]*)?)*>([\s\S]*?)<\/script>/gi.exec('<script type="text/javascript" src="..."></script>'), ['<script type="text/javascript" src="..."></script>', '"', "...", ""]); diff --git a/js/src/jit-test/tests/basic/bug601046.js b/js/src/jit-test/tests/basic/bug601046.js new file mode 100644 index 0000000000..45f3bf82e5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug601046.js @@ -0,0 +1,8 @@ +// don't assert
+var f = function(){};
+for (var p in f);
+Object.defineProperty(f, "j", ({configurable: true, value: "a"}));
+Object.defineProperty(f, "k", ({configurable: true, value: "b"}));
+Object.defineProperty(f, "j", ({configurable: true, get: function() {}}));
+delete f.k;
+Object.defineProperty(f, "j", ({configurable: false}));
diff --git a/js/src/jit-test/tests/basic/bug601398.js b/js/src/jit-test/tests/basic/bug601398.js new file mode 100644 index 0000000000..f3eaddccbf --- /dev/null +++ b/js/src/jit-test/tests/basic/bug601398.js @@ -0,0 +1,8 @@ +(function () { + try {} finally { + { + let z; + return; + } + } +})() diff --git a/js/src/jit-test/tests/basic/bug601401.js b/js/src/jit-test/tests/basic/bug601401.js new file mode 100644 index 0000000000..5c4a4f36c4 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug601401.js @@ -0,0 +1,6 @@ +{ + let e; + with({}) try {} catch (x) {} finally { + { let y; } + } +} diff --git a/js/src/jit-test/tests/basic/bug601428.js b/js/src/jit-test/tests/basic/bug601428.js new file mode 100644 index 0000000000..b9419f822c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug601428.js @@ -0,0 +1,2 @@ +// |jit-test| error: SyntaxError; +let({}=[c for(x in[])]){let diff --git a/js/src/jit-test/tests/basic/bug605754-regexp.js b/js/src/jit-test/tests/basic/bug605754-regexp.js new file mode 100644 index 0000000000..9acd314377 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug605754-regexp.js @@ -0,0 +1,2 @@ +var result = "foobarbaz".replace(/foo(bar)?bar/, "$1"); +assertEq(result, "baz"); diff --git a/js/src/jit-test/tests/basic/bug606083.js b/js/src/jit-test/tests/basic/bug606083.js new file mode 100644 index 0000000000..d8049b94fa --- /dev/null +++ b/js/src/jit-test/tests/basic/bug606083.js @@ -0,0 +1,32 @@ +// vim: set ts=8 sts=4 et sw=4 tw=99: +function f(L) { + do { + L: for (var i = 0; i < L; i++) { + break L; + } + } while (0); +} +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); diff --git a/js/src/jit-test/tests/basic/bug606882-1.js b/js/src/jit-test/tests/basic/bug606882-1.js new file mode 100644 index 0000000000..3d8bdf4a2a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug606882-1.js @@ -0,0 +1,3 @@ +// don't crash + +"ABC".match("A+(?:X?(?:|(?:))(?:(?:B)?C+w?w?)?)*"); diff --git a/js/src/jit-test/tests/basic/bug606882-2.js b/js/src/jit-test/tests/basic/bug606882-2.js new file mode 100644 index 0000000000..b7542170f5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug606882-2.js @@ -0,0 +1,16 @@ +// don't crash +var book = 'Ps'; +var pattern = "(?:" ++ "(?:" ++ "(?:" ++ "(?:-|)" ++ "\\s?" ++ ")" ++ "|" ++ ")" ++ " ?" ++ "\\d+" ++ "\\w?" ++ ")*"; +var re = new RegExp(pattern); +'8:5-8'.match(re); diff --git a/js/src/jit-test/tests/basic/bug608313.js b/js/src/jit-test/tests/basic/bug608313.js new file mode 100644 index 0000000000..1bd20df4a8 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug608313.js @@ -0,0 +1,11 @@ + +function testInt8Array(L) { + var f = new Int8Array(8); + f[0] = 0; // Don't assert. +} + +for (var i = 0; i < 10; i++) { + testInt8Array(0); +} + + diff --git a/js/src/jit-test/tests/basic/bug608980.js b/js/src/jit-test/tests/basic/bug608980.js new file mode 100644 index 0000000000..53ad2cbadc --- /dev/null +++ b/js/src/jit-test/tests/basic/bug608980.js @@ -0,0 +1,11 @@ + +/* Don't trip bogus assert. */ + +function foo() +{ + var x; + while (x = 0) { + x = 1; + } +} +foo(); diff --git a/js/src/jit-test/tests/basic/bug609502-1.js b/js/src/jit-test/tests/basic/bug609502-1.js new file mode 100644 index 0000000000..a62316d604 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug609502-1.js @@ -0,0 +1,9 @@ +for(var i = 0; i < 9; i++) { + x = ''.charCodeAt(NaN); +} + +for(var i = 0; i < 9; i++) { + x = ''.charAt(NaN); +} + +// Don't assert diff --git a/js/src/jit-test/tests/basic/bug609502-2.js b/js/src/jit-test/tests/basic/bug609502-2.js new file mode 100644 index 0000000000..4c1469dcea --- /dev/null +++ b/js/src/jit-test/tests/basic/bug609502-2.js @@ -0,0 +1,5 @@ +for (var i = 0; i < 9; i++) { + Math.abs(-2147483648) +} + +// Don't assert diff --git a/js/src/jit-test/tests/basic/bug610592.js b/js/src/jit-test/tests/basic/bug610592.js new file mode 100644 index 0000000000..da825d2843 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug610592.js @@ -0,0 +1,29 @@ + +/* Don't confuse JIT code by making slow arrays that use inline slots inconsistently. */ + +function foo(a) +{ + assertEq(a.x, 5); +} + +function bar() +{ + for (var i = 0; i < 50; i++) { + var a = []; + a[i] = 0; + delete a[i]; + a.x = 5; + foo(a); + } + + var b = [1,,2,,3,,4,,5]; + assertEq(b.toString(), "1,,2,,3,,4,,5"); + b.x = 0; + assertEq(b.toString(), "1,,2,,3,,4,,5"); + delete b.x; + delete b[8]; + delete b[6]; + delete b[4]; + assertEq(b.toString(), "1,,2,,,,,,"); +} +bar(); diff --git a/js/src/jit-test/tests/basic/bug613122.js b/js/src/jit-test/tests/basic/bug613122.js new file mode 100644 index 0000000000..64c6b06883 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug613122.js @@ -0,0 +1,4 @@ +var a = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +a.push(1); +a.splice(0, a.length); +a.d = ""; diff --git a/js/src/jit-test/tests/basic/bug613151.js b/js/src/jit-test/tests/basic/bug613151.js new file mode 100644 index 0000000000..6a3a24ae3a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug613151.js @@ -0,0 +1,18 @@ +// Iterating over a property with an Array id. +function n() {} +function g() {} +eval("\ + function a() {}\ + function b() {\ + for (w in this) {}\ + Object.defineProperty(\ + this, \ + new Array, \ + ({enumerable: true})\ + )\ + }\ + for (z in [0, 0, 0]) b()\ +") + +// Test it doesn't assert. + diff --git a/js/src/jit-test/tests/basic/bug613399.js b/js/src/jit-test/tests/basic/bug613399.js new file mode 100644 index 0000000000..b2431c9f91 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug613399.js @@ -0,0 +1,3 @@ +// don't assert
+/((?=()+))?/.exec("");
+
diff --git a/js/src/jit-test/tests/basic/bug614688.js b/js/src/jit-test/tests/basic/bug614688.js new file mode 100644 index 0000000000..c075cadab8 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug614688.js @@ -0,0 +1,7 @@ +function Foo() { + u = 0; +} + +var x = new Foo(); +assertEq(Object.getPrototypeOf(x) === Foo.prototype, true); +assertEq(Object.getPrototypeOf(x) === Object.prototype, false); diff --git a/js/src/jit-test/tests/basic/bug614915.js b/js/src/jit-test/tests/basic/bug614915.js new file mode 100644 index 0000000000..b4ab9491ae --- /dev/null +++ b/js/src/jit-test/tests/basic/bug614915.js @@ -0,0 +1,2 @@ +var s = [undefined, undefined].sort();
+assertEq(s.length, 2);
diff --git a/js/src/jit-test/tests/basic/bug616009.js b/js/src/jit-test/tests/basic/bug616009.js new file mode 100644 index 0000000000..ecfbc65062 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug616009.js @@ -0,0 +1,35 @@ +function run() { + var obj = { + toJSON: function() { + return { + key: { + toJSON: function() { + for (i=0; i!=1<<10; ++i) + new Object(); + var big = unescape("%udddd"); + while (big.length != 0x100000) + big += big; + for (i=0; i!=32; ++i) + new String(big+i); + return "whatever"; + } + }, + __iterator__: function() { + return { + next: function() { + return "key"; + } + } + } + } + } + }; + + var repl = function(id, val) { + this[0]++; + return val; + }; + + JSON.stringify(obj, repl); +} +run(); diff --git a/js/src/jit-test/tests/basic/bug616170.js b/js/src/jit-test/tests/basic/bug616170.js new file mode 100644 index 0000000000..efcd468ba5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug616170.js @@ -0,0 +1,17 @@ +/* Don't trip bogus assert. */ + +function e() +{ + try + { + var t = undefined; + } + catch (e) + { + var t = null; + } + while (t && (t.tagName.toUpperCase() != "BODY")) + continue; +} +for (var i = 0; i < 20; i++) + e(); diff --git a/js/src/jit-test/tests/basic/bug616762.js b/js/src/jit-test/tests/basic/bug616762.js new file mode 100644 index 0000000000..02f5c953cf --- /dev/null +++ b/js/src/jit-test/tests/basic/bug616762.js @@ -0,0 +1,26 @@ +// vim: set ts=8 sts=4 et sw=4 tw=99: +document = { + ready: function (x) { + this.exec = x; + } +}; + +var $ = function (x) { + return document; +}; + +(function ($) { + eval("(function(){\n" + + " var Private={};\n" + + " $(document).ready(function(){\n" + + " init()\n" + + " });\n" + + " function init(){\n" + + " $(Private)\n" + + " };\n" + + "})();"); +})($); +document.exec(); + +// Don't crash or assert. + diff --git a/js/src/jit-test/tests/basic/bug617139.js b/js/src/jit-test/tests/basic/bug617139.js new file mode 100644 index 0000000000..d53456e657 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug617139.js @@ -0,0 +1,9 @@ +// |jit-test| error: InternalError +// don't assert + +gczeal(2) +function x() { + [null].some(x) +} +x(); + diff --git a/js/src/jit-test/tests/basic/bug617171.js b/js/src/jit-test/tests/basic/bug617171.js new file mode 100644 index 0000000000..c4305f957d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug617171.js @@ -0,0 +1,4 @@ +var a = 6;
+Object.defineProperty(this, "a", {writable: false});
+a = 7;
+assertEq(a, 6);
diff --git a/js/src/jit-test/tests/basic/bug617745.js b/js/src/jit-test/tests/basic/bug617745.js new file mode 100644 index 0000000000..f7f60e20eb --- /dev/null +++ b/js/src/jit-test/tests/basic/bug617745.js @@ -0,0 +1,4 @@ + +var array1 = ['0']; +var array2 = (new Array(1)).splice(0,0, array1); +assertEq("" + array2, ""); diff --git a/js/src/jit-test/tests/basic/bug618350.js b/js/src/jit-test/tests/basic/bug618350.js new file mode 100644 index 0000000000..61e72d0a0e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug618350.js @@ -0,0 +1,24 @@ + +var global = 0; + +Object.defineProperty(Object.prototype, 0, {set: function() { global++; }}); + +for (var x = 0; x < 20; ++x) + [1,2]; +assertEq(global, 0); + +Object.defineProperty(Object.prototype, 1, {set: function() { global++; }}); + +for (var x = 0; x < 20; ++x) + [1,2]; +assertEq(global, 0); + +Object.defineProperty(Object.prototype, "b", {set: function() { global++; }}); + +for (var x = 0; x < 20; ++x) { + var s = { a:0, b:1, 0: 2, 1: 3 }; +} +assertEq(global, 0); + +assertEq([42][0], 42); +assertEq([42].length, 1); diff --git a/js/src/jit-test/tests/basic/bug618577.js b/js/src/jit-test/tests/basic/bug618577.js new file mode 100644 index 0000000000..a41f820cb4 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug618577.js @@ -0,0 +1,5 @@ +var x = new Uint32Array(); +for (var i = 0; i < 100; i++) + x[77] = x[77]; + +// Don't assert. diff --git a/js/src/jit-test/tests/basic/bug618853.js b/js/src/jit-test/tests/basic/bug618853.js new file mode 100644 index 0000000000..9c80b7fee2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug618853.js @@ -0,0 +1,12 @@ + +try { new isNaN; } catch (e) {} +new Array; +new Boolean; +new Date; +new Number; +new Object; +new String; +try { new [].push(4); } catch (e) {} +try { new [1,2,3].pop(); } catch (e) {} +try { new "a,b,c".split(","); } catch (e) {} +try { new Array.concat(3); } catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug619004.js b/js/src/jit-test/tests/basic/bug619004.js new file mode 100644 index 0000000000..90d3bca993 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug619004.js @@ -0,0 +1,3 @@ +// don't crash +gczeal(2); +evalcx('lazy'); diff --git a/js/src/jit-test/tests/basic/bug619338.js b/js/src/jit-test/tests/basic/bug619338.js new file mode 100644 index 0000000000..2548c0c710 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug619338.js @@ -0,0 +1 @@ +try { new Function.prototype } catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug620532.js b/js/src/jit-test/tests/basic/bug620532.js new file mode 100644 index 0000000000..4a2f6f664b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug620532.js @@ -0,0 +1,15 @@ +for (var i = 0; i < 20; i++) { + m = Math.min(0xffffffff, 0); +} +assertEq(m == 0, true); + +var buffer = new ArrayBuffer(4); +var int32View = new Int32Array(buffer); +var uint32View = new Uint32Array(buffer); +int32View[0] = -1; +var m; +for (var i = 0; i < 20; i++) { + m = Math.min(uint32View[0], 0); // uint32View[0] == 0xffffffff +} +assertEq(m == 0, true); + diff --git a/js/src/jit-test/tests/basic/bug620838.js b/js/src/jit-test/tests/basic/bug620838.js new file mode 100644 index 0000000000..c82933ae80 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug620838.js @@ -0,0 +1,22 @@ +function g() { + return "global"; +} + +function q(fun) { + return fun(); +} + +function f(x) { + if (x) { + function g() { + return "local"; + } + var ans = q(function() { + return g(); + }); + } + g = null; + return ans; +} + +assertEq(f(true), "local"); diff --git a/js/src/jit-test/tests/basic/bug621022-1.js b/js/src/jit-test/tests/basic/bug621022-1.js new file mode 100644 index 0000000000..aab5bf90f7 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug621022-1.js @@ -0,0 +1,14 @@ +function f(x) { + delete arguments[0]; + undefined != arguments[0]; + undefined == arguments[0]; + undefined != arguments[0]; + undefined === arguments[0]; +} + +for(var i=0; i<20; i++) { + f(1); +} + +// Don't assert. + diff --git a/js/src/jit-test/tests/basic/bug621022-2.js b/js/src/jit-test/tests/basic/bug621022-2.js new file mode 100644 index 0000000000..0f3549c026 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug621022-2.js @@ -0,0 +1,13 @@ +function f(j) { + var a = [[1],[1],[1],[1],[1],[1],[1],[1],[1],arguments]; + var b; + for (var i = 0; i < a.length; i++) { + delete a[i][0]; + b = arguments[0]; + } + assertEq(b === undefined, true); +} + +f(1); + + diff --git a/js/src/jit-test/tests/basic/bug621487.js b/js/src/jit-test/tests/basic/bug621487.js new file mode 100644 index 0000000000..ebe92e3d53 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug621487.js @@ -0,0 +1,4 @@ + +(function() { while (0) { var a, a = b; } })(); + +(function(b) { do { var a, a = b; } while (0); assertEq(a, 10); })(10); diff --git a/js/src/jit-test/tests/basic/bug623859.js b/js/src/jit-test/tests/basic/bug623859.js new file mode 100644 index 0000000000..e712f40103 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug623859.js @@ -0,0 +1,10 @@ +// |jit-test| allow-oom; allow-unhandlable-oom +var size = 1000000; +var a = []; +for (var i = 0; i < size; ++i) { + a[i] = null; +} +gcparam("maxBytes", gcparam("gcBytes") + 4*1024); +for (var i = 0; i < size; ++i) { + a[i] = []; +} diff --git a/js/src/jit-test/tests/basic/bug623863.js b/js/src/jit-test/tests/basic/bug623863.js new file mode 100644 index 0000000000..d9ba4f79ee --- /dev/null +++ b/js/src/jit-test/tests/basic/bug623863.js @@ -0,0 +1,5 @@ +// Contributor: Christian Holler <decoder@own-hero.net> +if (typeof gczeal === 'function') gczeal(2); +Function.prototype.prototype = function() { return 42; }; +try { foo(Function); } catch (e) { } +Function.prototype.prototype = function() { return 42; }; diff --git a/js/src/jit-test/tests/basic/bug624041-1.js b/js/src/jit-test/tests/basic/bug624041-1.js new file mode 100644 index 0000000000..4eef9e9a99 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug624041-1.js @@ -0,0 +1,8 @@ +var count = 0; + +var a = [0, 1]; +for (var i in a) { + assertEq(++count <= 1, true); + a.shift(); +} + diff --git a/js/src/jit-test/tests/basic/bug624041-2.js b/js/src/jit-test/tests/basic/bug624041-2.js new file mode 100644 index 0000000000..6eb1b78f96 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug624041-2.js @@ -0,0 +1,11 @@ +var s = ''; + +var a = [, 0, 1]; +for (var i in a) { + a.reverse(); + s += i + ','; +} + +// Index of the element with value '0'. +assertEq(s, '1,'); + diff --git a/js/src/jit-test/tests/basic/bug625141-1.js b/js/src/jit-test/tests/basic/bug625141-1.js new file mode 100644 index 0000000000..9f79cf7b25 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug625141-1.js @@ -0,0 +1,13 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +function f() { + var arr = new Int32Array(10); + x = function () { return arr.length; } + for (var i = 0; i < arr.length; i++) { + arr[i] = i; + } + assertEq(arr[5], 5); +} +f(); diff --git a/js/src/jit-test/tests/basic/bug625141-2.js b/js/src/jit-test/tests/basic/bug625141-2.js new file mode 100644 index 0000000000..d97cdf4dfb --- /dev/null +++ b/js/src/jit-test/tests/basic/bug625141-2.js @@ -0,0 +1,13 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +function f() { + var arr = new Int8Array(10); + x = function () { return arr.length; } + for (var i = 0; i < arr.length; i++) { + arr[i] = i; + } + assertEq(arr[5], 5); +} +f(); diff --git a/js/src/jit-test/tests/basic/bug625399.js b/js/src/jit-test/tests/basic/bug625399.js new file mode 100644 index 0000000000..01b616df40 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug625399.js @@ -0,0 +1,7 @@ +function a(bb) { + "use strict"; + return; + this.d = function() { bb; }; +} +for (var i = 0; i <= 9; i++) + a(); diff --git a/js/src/jit-test/tests/basic/bug626398.js b/js/src/jit-test/tests/basic/bug626398.js new file mode 100644 index 0000000000..f9571e9333 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug626398.js @@ -0,0 +1,30 @@ + +function g(n) { + var s; + switch (n) { + case 0: + s = "c"+n; + break; + + default: + s = "d"+n; + break; + } + return s; +} + +// Do it twice with different initial values for 'i' to allow for 8 +// being even or odd. + +var s = ""; +for (let i = 0; i != 30; i+=2) { + s += g(i%4/2); +} +assertEq(s, "c0d1c0d1c0d1c0d1c0d1c0d1c0d1c0"); + +var s = ""; +for (let i = 2; i != 30; i+=2) { + s += g(i%4/2); +} +assertEq(s, "d1c0d1c0d1c0d1c0d1c0d1c0d1c0"); + diff --git a/js/src/jit-test/tests/basic/bug627609.js b/js/src/jit-test/tests/basic/bug627609.js new file mode 100644 index 0000000000..c36a995567 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug627609.js @@ -0,0 +1,2 @@ +load(libdir + 'eqArrayHelper.js'); +assertEqArray(/((a|)+b)+/.exec('bb'), [ "bb", "b", "" ]); diff --git a/js/src/jit-test/tests/basic/bug629858.js b/js/src/jit-test/tests/basic/bug629858.js new file mode 100644 index 0000000000..a931e4faf6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug629858.js @@ -0,0 +1,9 @@ +// |jit-test| error: strict +options("strict"); +options("warn"); // Exit with error code on lint failures. +eval("\n\ +function f(a) {\n\ + if (a > 3)\n\ + return 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';\n\ +}"); + diff --git a/js/src/jit-test/tests/basic/bug630865-5.js b/js/src/jit-test/tests/basic/bug630865-5.js new file mode 100644 index 0000000000..67fdb7e5b0 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug630865-5.js @@ -0,0 +1,13 @@ +function C(a, b) { + this.a = a; + this.b = b; +} +var f = C.bind(null, 2); +Object.defineProperty(f, "prototype", {get: function () { throw "FAIL"; }}); +var x; +for (var i = 0; i < 10; i++) + x = new f(i); +assertEq(toString.call(x), "[object Object]"); +assertEq(Object.getPrototypeOf(x), C.prototype); +assertEq(x.a, 2); +assertEq(x.b, 9); diff --git a/js/src/jit-test/tests/basic/bug630865-6.js b/js/src/jit-test/tests/basic/bug630865-6.js new file mode 100644 index 0000000000..0532101bd0 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug630865-6.js @@ -0,0 +1,11 @@ +var a = []; +var x, i; +for (i = 0; i < 18; i++) { + a[i] = function (b) { this.b = b; }; + if (i != 17) + x = a[i].prototype; +} +for (i = 0; i < 18; i++) + x = new a[i]; +assertEq(toString.call(x), "[object Object]"); +assertEq(Object.getPrototypeOf(x), a[17].prototype); diff --git a/js/src/jit-test/tests/basic/bug631082.js b/js/src/jit-test/tests/basic/bug631082.js new file mode 100644 index 0000000000..19d61b1a77 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug631082.js @@ -0,0 +1,13 @@ +var t;
+(function () {
+ t = (function*() {
+ yield k();
+ })();
+ function h() {
+ }
+ function k() {
+ return function() { h(); };
+ }
+})();
+t.next();
+
diff --git a/js/src/jit-test/tests/basic/bug631219.js b/js/src/jit-test/tests/basic/bug631219.js new file mode 100644 index 0000000000..5b33919bdd --- /dev/null +++ b/js/src/jit-test/tests/basic/bug631219.js @@ -0,0 +1,10 @@ +// don't assert or crash
+function g(o) {
+ o.__proto__ = arguments;
+ o.length = 123;
+}
+function f() {
+ g(arguments);
+}
+f();
+
diff --git a/js/src/jit-test/tests/basic/bug631788.js b/js/src/jit-test/tests/basic/bug631788.js new file mode 100644 index 0000000000..503d32f04e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug631788.js @@ -0,0 +1 @@ +for (var j = 1; j < 10; ++j) { switch(0/j) { } } // don't assert diff --git a/js/src/jit-test/tests/basic/bug632778-1.js b/js/src/jit-test/tests/basic/bug632778-1.js new file mode 100644 index 0000000000..b982727a61 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug632778-1.js @@ -0,0 +1,5 @@ +function f() { + "use strict"; +} +g = new Proxy(f, {}); +Object.defineProperty(g, "arguments", {set: function(){}}); diff --git a/js/src/jit-test/tests/basic/bug632778-2.js b/js/src/jit-test/tests/basic/bug632778-2.js new file mode 100644 index 0000000000..b135b560ff --- /dev/null +++ b/js/src/jit-test/tests/basic/bug632778-2.js @@ -0,0 +1,2 @@ +obj = new Proxy(Number.bind(), {}); +Object.defineProperty(obj, "caller", {set: function () {}}); diff --git a/js/src/jit-test/tests/basic/bug632901.js b/js/src/jit-test/tests/basic/bug632901.js new file mode 100644 index 0000000000..3039318c2b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug632901.js @@ -0,0 +1,9 @@ +// don't crash when tracing +function f(o) { + var prop = "arguments"; + f[prop] = f[prop]; +} +for(var i = 0; i < 50; i++) { + f(); +} + diff --git a/js/src/jit-test/tests/basic/bug632964-regexp.js b/js/src/jit-test/tests/basic/bug632964-regexp.js new file mode 100644 index 0000000000..75612dbc73 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug632964-regexp.js @@ -0,0 +1,14 @@ +var sText = "s"; + +for (var i = 0; i < 250000; ++i) + sText += 'a\n'; + +sText += 'e'; + +var start = new Date(); +var match = sText.match(/s(\s|.)*?e/gi); +//var match = sText.match(/s([\s\S]*?)e/gi); +//var match = sText.match(/s(?:[\s\S]*?)e/gi); +var end = new Date(); + +assertEq(match.length, 1); diff --git a/js/src/jit-test/tests/basic/bug633409-1.js b/js/src/jit-test/tests/basic/bug633409-1.js new file mode 100644 index 0000000000..20eaa6cda5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug633409-1.js @@ -0,0 +1,13 @@ +// vim: set ts=8 sts=4 et sw=4 tw=99: +x = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 }; + +for (i in x) + delete x.d; + +x = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 }; +y = []; +for (i in x) + y.push(i) + +assertEq(y[3], "d"); + diff --git a/js/src/jit-test/tests/basic/bug633409-2.js b/js/src/jit-test/tests/basic/bug633409-2.js new file mode 100644 index 0000000000..d3c498d6d2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug633409-2.js @@ -0,0 +1,13 @@ +// vim: set ts=8 sts=4 et sw=4 tw=99: + +var o1 = {p1: 1}; +var o2 = {p1: 1, p2: 2}; + +for(var x in o1) { + for(var y in o2) { + delete o2.p2; + } +} + +/* Don't fail cx->enumerators == obj assert, see bug comment #31 */ + diff --git a/js/src/jit-test/tests/basic/bug633752.js b/js/src/jit-test/tests/basic/bug633752.js new file mode 100644 index 0000000000..522f642778 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug633752.js @@ -0,0 +1,11 @@ +function f(o) { + var p = "arguments"; + for(var i=0; i<10; i++) { + f[p]; + } +} +f({}); +f({}); +f({}); +f({}); + diff --git a/js/src/jit-test/tests/basic/bug633828.js b/js/src/jit-test/tests/basic/bug633828.js new file mode 100644 index 0000000000..6b71d095bd --- /dev/null +++ b/js/src/jit-test/tests/basic/bug633828.js @@ -0,0 +1,6 @@ +// |jit-test| error: SyntaxError; +(function() { + function a() {} + function a() {} +} +for diff --git a/js/src/jit-test/tests/basic/bug634593.js b/js/src/jit-test/tests/basic/bug634593.js new file mode 100644 index 0000000000..b4241a8a4c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug634593.js @@ -0,0 +1,4 @@ +this.__defineGetter__("x3", Function); +parseInt = x3; +parseInt.prototype = []; +for (var z = 0; z < 10; ++z) { new parseInt() }
\ No newline at end of file diff --git a/js/src/jit-test/tests/basic/bug635417.js b/js/src/jit-test/tests/basic/bug635417.js new file mode 100644 index 0000000000..94dd10163c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug635417.js @@ -0,0 +1,2 @@ +assertEq(/^@(A*)x(B)*/.test("@xB"), true); + diff --git a/js/src/jit-test/tests/basic/bug638981.js b/js/src/jit-test/tests/basic/bug638981.js new file mode 100644 index 0000000000..944daa76ea --- /dev/null +++ b/js/src/jit-test/tests/basic/bug638981.js @@ -0,0 +1,4 @@ +/* Don't crash. */ + +delete Function; +Object.getOwnPropertyNames(this); diff --git a/js/src/jit-test/tests/basic/bug639126.js b/js/src/jit-test/tests/basic/bug639126.js new file mode 100644 index 0000000000..7283fe6ca7 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug639126.js @@ -0,0 +1,4 @@ +Array.__proto__ = Array.__proto__; +gc(); +Array["name" + ""]; +Array(); diff --git a/js/src/jit-test/tests/basic/bug639128.js b/js/src/jit-test/tests/basic/bug639128.js new file mode 100644 index 0000000000..fadd559aae --- /dev/null +++ b/js/src/jit-test/tests/basic/bug639128.js @@ -0,0 +1,10 @@ +function f(o) { + Object.seal(o); +} +gc(); +if(2 != 2) { + g = new f(g); +} +with({}) { + f({}); +} diff --git a/js/src/jit-test/tests/basic/bug639311.js b/js/src/jit-test/tests/basic/bug639311.js new file mode 100644 index 0000000000..277d0c3d10 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug639311.js @@ -0,0 +1,18 @@ +/* Avoid use-after-free while sweeping type objects. */ + +try { + Reflparse("") +} catch(e) {} +Reflect.parse("for(var a;a;j){if(a%2==0){c()}}") +try { + (function() { + for (a = 0;; j) { + gc() + } + })() +} catch(e) { + delete this.Math +} +gc() +Reflect.parse("{ let x; }") +gc() diff --git a/js/src/jit-test/tests/basic/bug639591.js b/js/src/jit-test/tests/basic/bug639591.js new file mode 100644 index 0000000000..435cc31fc1 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug639591.js @@ -0,0 +1,4 @@ +gczeal(2); +var x; +[eval("x")] ? eval("x") : 3; +eval("Object()"); diff --git a/js/src/jit-test/tests/basic/bug639759.js b/js/src/jit-test/tests/basic/bug639759.js new file mode 100644 index 0000000000..ede9713748 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug639759.js @@ -0,0 +1,9 @@ +gczeal(2); +function f() { + for(var i=0; i<10; i++) { + [1, [1, 2, 3]]; + eval(""); + } +} +eval("Array(f() ? 0 : 1)"); +eval("Array((eval(\"f()\")) ? true : eval(''))"); diff --git a/js/src/jit-test/tests/basic/bug639797.js b/js/src/jit-test/tests/basic/bug639797.js new file mode 100644 index 0000000000..f061fac46d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug639797.js @@ -0,0 +1 @@ +Function("with([]){const x=0}")() diff --git a/js/src/jit-test/tests/basic/bug639807.js b/js/src/jit-test/tests/basic/bug639807.js new file mode 100644 index 0000000000..42702b46bd --- /dev/null +++ b/js/src/jit-test/tests/basic/bug639807.js @@ -0,0 +1,4 @@ + +try { + eval("const[]=*,[x]=r") +} catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug640203.js b/js/src/jit-test/tests/basic/bug640203.js new file mode 100644 index 0000000000..aa066bfb27 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug640203.js @@ -0,0 +1,2 @@ +var x = [,].splice(0); +assertEq(x[0], undefined); diff --git a/js/src/jit-test/tests/basic/bug640993.js b/js/src/jit-test/tests/basic/bug640993.js new file mode 100644 index 0000000000..45ce0856a3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug640993.js @@ -0,0 +1,7 @@ +function f() { + return f; +} +f.__proto__ = null; +gc(); +f(); +new f(); diff --git a/js/src/jit-test/tests/basic/bug641229.js b/js/src/jit-test/tests/basic/bug641229.js new file mode 100644 index 0000000000..4ae5427b26 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug641229.js @@ -0,0 +1,2 @@ +this.__defineSetter__("x",Math.max) +Function("({x}=[])")() diff --git a/js/src/jit-test/tests/basic/bug641231.js b/js/src/jit-test/tests/basic/bug641231.js new file mode 100644 index 0000000000..0e778a0244 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug641231.js @@ -0,0 +1 @@ +try { Function("function a(){this(*)}new a")() } catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug641235.js b/js/src/jit-test/tests/basic/bug641235.js new file mode 100644 index 0000000000..8534b53c04 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug641235.js @@ -0,0 +1,21 @@ +try { +function g(code) { + code = code.replace(/\/\*DUPTRY\d+\*\//, function(k) { + var n = parseInt(k.substr(8), 10); + return aa("try{}catch(e){}", n); + }); + var f = new Function(code); + f() +} +function aa(s, n) { + if (n == 1) { + return s; + } + var s2 = s + s; + var r = n % 2; + var d = (n - r) / 2; + var m = aa(s2, d); + return r ? m + s : m; +} +g("switch(x){default:case l:/*DUPTRY5338*/case 0:x}"); +} catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug641491.js b/js/src/jit-test/tests/basic/bug641491.js new file mode 100644 index 0000000000..653e47a6ab --- /dev/null +++ b/js/src/jit-test/tests/basic/bug641491.js @@ -0,0 +1,19 @@ +function f1() { +} +function f2() { +} +function f3(o) { + f2 = Date.prototype; +} +var key = Object.getOwnPropertyNames(f1)[30]; +if(key) { + f3 = f1[key]; +} +gc(); +gc(); +try { +for(var i=0; i<10; i++) { + delete f2[1]; + f3(function() {}); +} +} catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug641525.js b/js/src/jit-test/tests/basic/bug641525.js new file mode 100644 index 0000000000..4c7c8b85ca --- /dev/null +++ b/js/src/jit-test/tests/basic/bug641525.js @@ -0,0 +1,34 @@ + +var o2 = new Proxy({}, {}); +function f1() {} +function f2() {} +function f4(o) { + var key = Object.getOwnPropertyNames(o)[18]; + o4 = o[key]; + o.prototype = {}; +} +f4(f1); +f4(f1); +f4(f2); +new f2(o2); + +// these will hold only if type inference is enabled. +//assertEq(shapeOf(f1) == shapeOf(f2), false); +//assertEq(shapeOf(f1) == shapeOf(f4), false); + +function factory() { + function foo() {} + foo.x = 0; + return foo; +} + +var fobjs = []; +for (var i = 0; i < 10; i++) { + var of = fobjs[i] = factory(); + if (i > 0) { + assertEq(fobjs[i - 1] === of, false); + assertEq(shapeOf(fobjs[i - 1]), shapeOf(of)); + } +} + +assertEq(shapeOf(fobjs[0]) == shapeOf(f1), false); diff --git a/js/src/jit-test/tests/basic/bug641563.js b/js/src/jit-test/tests/basic/bug641563.js new file mode 100644 index 0000000000..e3d60afefb --- /dev/null +++ b/js/src/jit-test/tests/basic/bug641563.js @@ -0,0 +1,3 @@ +// |jit-test| error: SyntaxError; +Function("(x)\nfor(var b,x in") + diff --git a/js/src/jit-test/tests/basic/bug641741.js b/js/src/jit-test/tests/basic/bug641741.js new file mode 100644 index 0000000000..760f7ec51f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug641741.js @@ -0,0 +1 @@ +try { eval("var[]=(++false[x])()=[],x") } catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug642154.js b/js/src/jit-test/tests/basic/bug642154.js new file mode 100644 index 0000000000..8518e2f878 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642154.js @@ -0,0 +1,16 @@ +assertEq(Math.pow(1, undefined), NaN); +assertEq(Math.pow(1, null), 1); +assertEq(Math.pow(1, true), 1); +assertEq(Math.pow(1, false), 1); +assertEq(Math.pow(1, 0), 1); +assertEq(Math.pow(1, -0), 1); +assertEq(Math.pow(1, NaN), NaN); +assertEq(Math.pow(1, {}), NaN); +assertEq(Math.pow(1, {valueOf: function() { return undefined; }}), NaN); + +x = 2.2; +assertEq(Math.pow(x - 1.2, undefined), NaN); + +var y; +assertEq(Math.pow(1, y), NaN); + diff --git a/js/src/jit-test/tests/basic/bug642161.js b/js/src/jit-test/tests/basic/bug642161.js new file mode 100644 index 0000000000..18679dd9ed --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642161.js @@ -0,0 +1 @@ +assertEq(JSON.stringify(0 | "prefix" || Boolean), undefined); diff --git a/js/src/jit-test/tests/basic/bug642164.js b/js/src/jit-test/tests/basic/bug642164.js new file mode 100644 index 0000000000..6b97e82ea7 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642164.js @@ -0,0 +1,14 @@ +function raisesException(exception) { + return function (code) { + eval(code); + }; +}; +function obj() { + var o = { assertEq: true, y: 1 }; + Object.defineProperty(o, 'x', { writable: false }); + return o; +} +function in_strict_with(expr) { + return "with(obj()) { (function () { 'use strict'; " + expr + " })(); }"; +} +try { assertEq(raisesException(TypeError)(in_strict_with('x++;')), true); } catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug642206.js b/js/src/jit-test/tests/basic/bug642206.js new file mode 100644 index 0000000000..775e4c6e17 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642206.js @@ -0,0 +1,30 @@ +Function.prototype.__proto__ = null; + +function testLenientAndStrict(code, lenient_pred, strict_pred) { + return (strict_pred("'use strict'; " + code) && + lenient_pred(code)); +} +function raisesException(exception) { + return function (code) { + try { + eval(code); + } catch (actual) { + } + }; +}; +try { +function arr() { + return Object.defineProperty(Object()* delete Object, 0, {writable: false}); +} +assertEq(testLenientAndStrict('var a = arr(); [a.splice(0, 1), a]', + raisesException(TypeError), + raisesException(TypeError)), + true); +} catch (e) {} +ForIn_2(this); +function ForIn_2(object) { + for ( property in object ) { + with ( object ) { + } + } +} diff --git a/js/src/jit-test/tests/basic/bug642248.js b/js/src/jit-test/tests/basic/bug642248.js new file mode 100644 index 0000000000..8c37b76759 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642248.js @@ -0,0 +1,10 @@ +function test(makeNonArray) { + function C() {} + C.prototype = [] + c = new C(); + c.push("foo"); + return c.length +} +assertEq(test(true), 1); +var a = []; +var b = Object.create(a); diff --git a/js/src/jit-test/tests/basic/bug642254.js b/js/src/jit-test/tests/basic/bug642254.js new file mode 100644 index 0000000000..a603920fe3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642254.js @@ -0,0 +1,4 @@ +function f(i) { + for (var n = 0; n < 0; n = i) { } +} +actual = f(.5); diff --git a/js/src/jit-test/tests/basic/bug642319.js b/js/src/jit-test/tests/basic/bug642319.js new file mode 100644 index 0000000000..6be3a4c59d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642319.js @@ -0,0 +1,10 @@ + +test(); +function test() { + function f() { + function test( ) { summary( summary, test, false ); } + } + f.__proto__ = this; +} +gc(); +test(); diff --git a/js/src/jit-test/tests/basic/bug642326.js b/js/src/jit-test/tests/basic/bug642326.js new file mode 100644 index 0000000000..8b91ecacfe --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642326.js @@ -0,0 +1,8 @@ +load(libdir + "immutable-prototype.js"); + +if (globalPrototypeChainIsMutable()) + this.__proto__ = null; + +gczeal(2); +gc(); +var box = evalcx('lazy'); diff --git a/js/src/jit-test/tests/basic/bug642422.js b/js/src/jit-test/tests/basic/bug642422.js new file mode 100644 index 0000000000..bb9cfea83a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642422.js @@ -0,0 +1,4 @@ +gczeal(2); +var x; +var foo = "for (var z = 0; z < 2; ++z) { new Object(new String(this), x)}"; +eval(foo); diff --git a/js/src/jit-test/tests/basic/bug642569.js b/js/src/jit-test/tests/basic/bug642569.js new file mode 100644 index 0000000000..6f84492d8b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642569.js @@ -0,0 +1,13 @@ +function main() { + var v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, + v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, + v43, v44, v45, v46, v47; + var v48 = 0, v49 = 0; + if (true) { + var v50 = v48 - 1; + var v51 = v49 + 1; + return v51; + } +} +assertEq(main(), 1); diff --git a/js/src/jit-test/tests/basic/bug642592.js b/js/src/jit-test/tests/basic/bug642592.js new file mode 100644 index 0000000000..57e40facac --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642592.js @@ -0,0 +1,2 @@ +var strings = new Array(); +strings[0x7fffffff] = 0; diff --git a/js/src/jit-test/tests/basic/bug642758.js b/js/src/jit-test/tests/basic/bug642758.js new file mode 100644 index 0000000000..e92e657309 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642758.js @@ -0,0 +1,4 @@ +function Integer( value, exception ) { } +try { +new Integer( Math.LN2, ++INVALID_INTEGER_VALUE? exception+1.1: 1900 ); +} catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug642772-1.js b/js/src/jit-test/tests/basic/bug642772-1.js new file mode 100644 index 0000000000..b7dc483fcc --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642772-1.js @@ -0,0 +1,19 @@ +var n1 = Number.prototype.toFixed; +var s1 = String.prototype.split; +delete Number; +delete String; + +var n2 = (5).toFixed; +var s2 = ("foo").split; + +// Check enumeration doesn't resurrect deleted standard classes +for (x in this) {} + +// Ensure the prototypes are shared. +var n3 = (5).toFixed; +var s3 = ("foo").split; + +assertEq(s1, s2); +assertEq(s1, s3); +assertEq(n1, n2); +assertEq(n1, n3); diff --git a/js/src/jit-test/tests/basic/bug642772-2.js b/js/src/jit-test/tests/basic/bug642772-2.js new file mode 100644 index 0000000000..d797664bfb --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642772-2.js @@ -0,0 +1,101 @@ +function failWrapper(callback) { + try { + callback(); // this should fail + throw "test-error"; // and if it didn't we have a problem` + } catch (e) { + if (e == "test-error") + throw ("Testing error when running " + callback.toString()); + } +} + + +print ("Deleting standard classes"); +delete Function; +delete Object; +delete Array; +delete Boolean; +delete JSON; +delete Date; +delete Math; +delete Number; +delete String; +delete Regexp; +delete Reflect; +delete Proxy; +delete Error; +delete Iterator; +delete Generator; +delete StopIteration; +delete Float32Array; +delete Float64Array; +delete Int16Array; +delete Int32Array; +delete Int32Array; +delete Uint16Array; +delete Uint32Array; +delete Uint8Array; +delete Uint8ClampedArray; +delete Weakmap; + + +print ("Accessing standard classes shouldn't recreate them"); +failWrapper(function () { Function; }); +failWrapper(function () { Object; }); +failWrapper(function () { Array; }); +failWrapper(function () { Boolean; }); +failWrapper(function () { JSON; }); +failWrapper(function () { Date; }); +failWrapper(function () { Math; }); +failWrapper(function () { Number; }); +failWrapper(function () { String; }); +failWrapper(function () { Regexp; }); +failWrapper(function () { Reflect; }); +failWrapper(function () { Proxy; }); +failWrapper(function () { Error; }); +failWrapper(function () { Iterator; }); +failWrapper(function () { Generator; }); +failWrapper(function () { StopIteration; }); +failWrapper(function () { Float32Array; }); +failWrapper(function () { Float64Array; }); +failWrapper(function () { Int16Array; }); +failWrapper(function () { Int32Array; }); +failWrapper(function () { Int32Array; }); +failWrapper(function () { Uint16Array; }); +failWrapper(function () { Uint32Array; }); +failWrapper(function () { Uint8Array; }); +failWrapper(function () { Uint8ClampedArray; }); +failWrapper(function () { Weakmap; }); + + +print ("Enumerate over the global object"); +for (c in this) {} + +print ("That shouldn't have recreated the standard classes either"); +failWrapper(function () { Function; }); +failWrapper(function () { Object; }); +failWrapper(function () { Array; }); +failWrapper(function () { Boolean; }); +failWrapper(function () { JSON; }); +failWrapper(function () { Date; }); +failWrapper(function () { Math; }); +failWrapper(function () { Number; }); +failWrapper(function () { String; }); +failWrapper(function () { Regexp; }); +failWrapper(function () { Reflect; }); +failWrapper(function () { Proxy; }); +failWrapper(function () { Error; }); +failWrapper(function () { Iterator; }); +failWrapper(function () { Generator; }); +failWrapper(function () { StopIteration; }); +failWrapper(function () { Float32Array; }); +failWrapper(function () { Float64Array; }); +failWrapper(function () { Int16Array; }); +failWrapper(function () { Int32Array; }); +failWrapper(function () { Int32Array; }); +failWrapper(function () { Uint16Array; }); +failWrapper(function () { Uint32Array; }); +failWrapper(function () { Uint8Array; }); +failWrapper(function () { Uint8ClampedArray; }); +failWrapper(function () { Weakmap; }); + +print ("success"); diff --git a/js/src/jit-test/tests/basic/bug642772-3.js b/js/src/jit-test/tests/basic/bug642772-3.js new file mode 100644 index 0000000000..8280b389ad --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642772-3.js @@ -0,0 +1,5 @@ +// Catch memory leaks when enumerating over the global object. + +for (let z = 1; z <= 1600; ++z) { + for (y in this); +} diff --git a/js/src/jit-test/tests/basic/bug642894.js b/js/src/jit-test/tests/basic/bug642894.js new file mode 100644 index 0000000000..5de6f3597e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642894.js @@ -0,0 +1,9 @@ + +function foo() { + var x = {}; + x.__proto__ = function() { return 0 } + return x; +} +var a = foo(); +var b = foo(); +assertEq(a.__proto__ === b.__proto__, false); diff --git a/js/src/jit-test/tests/basic/bug642985-1.js b/js/src/jit-test/tests/basic/bug642985-1.js new file mode 100644 index 0000000000..fb90691a94 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642985-1.js @@ -0,0 +1,23 @@ +gczeal(2); +function complex(aReal, aImag) {} +function mandelbrotValueOO (aC, aIterMax) { + for (var iter = 0; iter < aIterMax; iter++) { } +} +function f(trace) { + const width = 5; + const height = 5; + const max_iters = 5; + var output = []; + for (let img_x = 0; img_x < width; img_x++) { + for (let img_y = 0; img_y < height; img_y++) { + let C = new complex(-2 + (img_x / width) * 3, + -1.5 + (img_y / height) * 3); + var res = mandelbrotValueOO(C, max_iters); + if (output.length > 0 && complex(5)) { + } else { + output.push([res, 1]); + } + } + } +} +var timenonjit = f(false); diff --git a/js/src/jit-test/tests/basic/bug642985-2.js b/js/src/jit-test/tests/basic/bug642985-2.js new file mode 100644 index 0000000000..478b585591 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug642985-2.js @@ -0,0 +1,23 @@ +function f(N) +{ + for (var i = 0; i != N; ++i) { + var obj1 = {}, obj2 = {}; + obj1['a'+i] = 0; + obj2['b'+i] = 0; + for (var repeat = 0;repeat != 2; ++repeat) { + for (var j in obj1) { + for (var k in obj2) { + gc(); + } + } + } + } +} +var array = [function() { f(10); }, + function(array) { f(50); }, + function() { propertyIsEnumerable.call(undefined, {}); }, + ]; +try { + for (var i = 0; i != array.length; ++i) + array[i](); +} catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug643113.js b/js/src/jit-test/tests/basic/bug643113.js new file mode 100644 index 0000000000..54ade98916 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug643113.js @@ -0,0 +1,11 @@ +function printBugNumber (num) +{ + print ('BUGNUMBER: ' + num); +} +try { test(); } catch (e) {} +function test() +{ + printBugNumber(typeof BUGNUMBER == 'undefined'); + 1|| q + 48? new q( printBugNumber, + eval("var EXP_1 = new MyValuelessObject('string'); var EXP_2 = new MyValuelessObject(false); EXP_1 + EXP_2") ): 1; +} diff --git a/js/src/jit-test/tests/basic/bug643169.js b/js/src/jit-test/tests/basic/bug643169.js new file mode 100644 index 0000000000..28f3ac0252 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug643169.js @@ -0,0 +1,7 @@ +for(var i=0; i<3; i++) { + var x; + function ff() {} + with(this) {} + x; + x = true; +} diff --git a/js/src/jit-test/tests/basic/bug643243.js b/js/src/jit-test/tests/basic/bug643243.js new file mode 100644 index 0000000000..71530c56a1 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug643243.js @@ -0,0 +1,11 @@ +{ + function newSandbox(n) {} +} +var o12 = Float32Array.prototype; +function f12(o) { + eval('o')['__proto_' + '_'] = null; +} +for (var i = 0; i < 14; i++) { + gc() + new f12(o12); +} diff --git a/js/src/jit-test/tests/basic/bug643244.js b/js/src/jit-test/tests/basic/bug643244.js new file mode 100644 index 0000000000..90e2d510eb --- /dev/null +++ b/js/src/jit-test/tests/basic/bug643244.js @@ -0,0 +1,2 @@ +delete(0).__proto__.valueOf +eval("(function(){(0).valueOf();})")() diff --git a/js/src/jit-test/tests/basic/bug643249.js b/js/src/jit-test/tests/basic/bug643249.js new file mode 100644 index 0000000000..86a000228e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug643249.js @@ -0,0 +1,13 @@ +{ + function x() {} +} +for (i = 0; i < 10; i++) { + _someglobal_ = /a/; + (function() { + return function() { + return _someglobal_ + } () + } () == /a/); + gc(); + try { _someglobal_ = new Function.__lookupSetter__ } catch (e) {} +} diff --git a/js/src/jit-test/tests/basic/bug643285.js b/js/src/jit-test/tests/basic/bug643285.js new file mode 100644 index 0000000000..0f8d755923 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug643285.js @@ -0,0 +1,4 @@ +function fun() { + (new Function ("function ff () { actual = '' + ff. caller; } function f () { ff (); } f ();")) ('function pf' + fun + '() {}'); +} +fun(); diff --git a/js/src/jit-test/tests/basic/bug643733.js b/js/src/jit-test/tests/basic/bug643733.js new file mode 100644 index 0000000000..89a6695b3d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug643733.js @@ -0,0 +1,4 @@ +var x; +assertEq(-(typeof (x+x)), NaN); +assertEq(-(typeof Math.abs()), NaN); + diff --git a/js/src/jit-test/tests/basic/bug645293.js b/js/src/jit-test/tests/basic/bug645293.js new file mode 100644 index 0000000000..366c498fa2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug645293.js @@ -0,0 +1,12 @@ +/* Don't assert. */ +function f() { + NaN++; + --NaN; + Infinity--; + ++Infinity; + undefined++; + --undefined; + ++Math; + Math--; +} +f();
\ No newline at end of file diff --git a/js/src/jit-test/tests/basic/bug645632.js b/js/src/jit-test/tests/basic/bug645632.js new file mode 100644 index 0000000000..dbb5b8fd75 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug645632.js @@ -0,0 +1,6 @@ + +function f(o) { + o[{}] = 1; + with(Object) {} +} +f(Object.prototype); diff --git a/js/src/jit-test/tests/basic/bug646393.js b/js/src/jit-test/tests/basic/bug646393.js new file mode 100644 index 0000000000..5d98e15410 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug646393.js @@ -0,0 +1,4 @@ +try { + x.y; +} catch(ex) {} +x = Number(1); diff --git a/js/src/jit-test/tests/basic/bug646968-3.js b/js/src/jit-test/tests/basic/bug646968-3.js new file mode 100644 index 0000000000..a02cb3f682 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug646968-3.js @@ -0,0 +1,16 @@ +var s, v = "NOPE"; + +s = ''; +for (let v = 0, x = v; x < 3; x++) + s += x; +assertEq(s, '012'); + +s = ''; +for (let v = 0, x = eval('v'); x < 3; x++) + s += x; +assertEq(s, '012'); + +s = '' +for (let v = 0, x = function () { with ({}) return v; }(); x < 3; x++) + s += x; +assertEq(s, '012'); diff --git a/js/src/jit-test/tests/basic/bug646968-4.js b/js/src/jit-test/tests/basic/bug646968-4.js new file mode 100644 index 0000000000..fdcafbb2b1 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug646968-4.js @@ -0,0 +1,10 @@ +load(libdir + "asserts.js"); + +// Scoping: `x` in the head of a `for (let x...)` loop refers to the loop variable. + +assertThrowsInstanceOf(function () { +var s = "", x = {a: 1, b: 2, c: 3}; +for (let x in eval('x')) + s += x; +assertEq(s, ""); +}, ReferenceError); diff --git a/js/src/jit-test/tests/basic/bug646968-5.js b/js/src/jit-test/tests/basic/bug646968-5.js new file mode 100644 index 0000000000..abc372a853 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug646968-5.js @@ -0,0 +1,9 @@ +var y = 7; + +switch (function () { with ({}) return y; }()) { +case 7: + let y; + break; +default: + throw 'FAIL'; +} diff --git a/js/src/jit-test/tests/basic/bug646968-6.js b/js/src/jit-test/tests/basic/bug646968-6.js new file mode 100644 index 0000000000..11b1fa1c18 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug646968-6.js @@ -0,0 +1,16 @@ +// In `for (let x = EXPR; ;)`, if `x` appears within EXPR, it refers to the +// loop variable. Actually doing this is typically a TDZ error. + +load(libdir + "asserts.js"); + +assertThrowsInstanceOf(() => { + for (let x = x; null.foo; null.foo++) {} +}, ReferenceError); + +assertThrowsInstanceOf(() => { + for (let x = eval('x'); null.foo; null.foo++) {} +}, ReferenceError); + +assertThrowsInstanceOf(() => { + for (let x = function () { with ({}) return x; }(); null.foo; null.foo++) {} +}, ReferenceError); diff --git a/js/src/jit-test/tests/basic/bug646968-7.js b/js/src/jit-test/tests/basic/bug646968-7.js new file mode 100644 index 0000000000..7fac119f56 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug646968-7.js @@ -0,0 +1,10 @@ +load(libdir + "evalInFrame.js"); + +function test(s) { + eval(s); + { + let y = evalInFrame(0, '3'), x = x0; + assertEq(x, 5); + } +} +test('var x0= 5;'); diff --git a/js/src/jit-test/tests/basic/bug646968-8.js b/js/src/jit-test/tests/basic/bug646968-8.js new file mode 100644 index 0000000000..9214f0798f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug646968-8.js @@ -0,0 +1,8 @@ +load(libdir + "evalInFrame.js"); + +var x = 5; +{ + let x = eval("this.x++"); + assertEq(evalInFrame(0, "x"), 5); +} +assertEq(x, 6); diff --git a/js/src/jit-test/tests/basic/bug647463.js b/js/src/jit-test/tests/basic/bug647463.js new file mode 100644 index 0000000000..0f3d5cd57a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug647463.js @@ -0,0 +1,6 @@ + +try { + eval("\ + [0].sort()\ + ") +} catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug648357.js b/js/src/jit-test/tests/basic/bug648357.js new file mode 100644 index 0000000000..9c2c939e08 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug648357.js @@ -0,0 +1,3 @@ +var x = [1, 2, 3, 4, 5, 6, 7, 8]; +x.pop(); +x.push(9); diff --git a/js/src/jit-test/tests/basic/bug648773.js b/js/src/jit-test/tests/basic/bug648773.js new file mode 100644 index 0000000000..2ab57ed240 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug648773.js @@ -0,0 +1,4 @@ +gczeal(2); +for (var loopa2 = 0; loopa2 < 13; loopa2++) { + [, , , , , , ][new Float64Array()] = 72413.8139177333; +} diff --git a/js/src/jit-test/tests/basic/bug649439.js b/js/src/jit-test/tests/basic/bug649439.js new file mode 100644 index 0000000000..0f19afca8c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug649439.js @@ -0,0 +1,3 @@ +var o1 = new String("abc"); +var o2 = o1[1]; +o2[1]; diff --git a/js/src/jit-test/tests/basic/bug649771.js b/js/src/jit-test/tests/basic/bug649771.js new file mode 100644 index 0000000000..6ecc2d83e6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug649771.js @@ -0,0 +1,7 @@ +function f(o) { + f = o.constructor; + eval('delete o.x'); +} +for(var i=0; i<3; i++) { + f(RegExp.prototype); +} diff --git a/js/src/jit-test/tests/basic/bug651451-2.js b/js/src/jit-test/tests/basic/bug651451-2.js new file mode 100644 index 0000000000..d5594b8922 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug651451-2.js @@ -0,0 +1,6 @@ +var arr = [1, 2, 3, 4, 5]; +arr.length = 100; +arr.pop(); +assertEq(arr.length, 99); +arr.pop(); +assertEq(arr.length, 98);
\ No newline at end of file diff --git a/js/src/jit-test/tests/basic/bug651451.js b/js/src/jit-test/tests/basic/bug651451.js new file mode 100644 index 0000000000..e547fa4d78 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug651451.js @@ -0,0 +1,4 @@ +var arr = [2]; +arr.pop(); +arr[0] = 2; +assertEq(arr.length, 1); diff --git a/js/src/jit-test/tests/basic/bug651966.js b/js/src/jit-test/tests/basic/bug651966.js new file mode 100644 index 0000000000..35e0c1049b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug651966.js @@ -0,0 +1,38 @@ + +function f(code) { + g = eval("(function(){" + code + "})"); + g() +} +f(); +f(); +f(); +f(); +f(); +f(); +f(); +f(); +f(); +f(); +f(); +f(); +f(); +f(); +f(); +f(); +try { f("function x(){}(x())"); } catch (e) {} + +function f2() { + a = { + x + } = x, (x._) + function + x(){ return ({}); } +} +try { f2(); } catch (e) {} + +function f3() { + var x = 0; + with ({}) { x = 'three'; } + return x; +} +f3(); diff --git a/js/src/jit-test/tests/basic/bug652054.js b/js/src/jit-test/tests/basic/bug652054.js new file mode 100644 index 0000000000..3e43d36733 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug652054.js @@ -0,0 +1,55 @@ +var M4x4 = {};
+M4x4.mul = function M4x4_mul(a, b, r) {
+ a11 = a[0]
+ a21 = a[1]
+ a31 = a[2]
+ a12 = a[4]
+ a22 = a[5]
+ a32 = a[6]
+ a13 = a[8]
+ a23 = a[9]
+ a33 = a[10]
+ a14 = a[12]
+ a24 = a[13]
+ a34 = a[14]
+ b[3]
+ b[4]
+ b13 = b[8]
+ b23 = b[9]
+ b33 = b[10]
+ b43 = b[11]
+ r[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43
+ r[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43
+ r[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43
+ return r;
+};
+M4x4.scale3 = function M4x4_scale3(x, y, z, m) {
+ m[0] *= x;
+ m[3] *= x;
+ m[4] *= y;
+ m[11] *= z;
+};
+M4x4.makeLookAt = function M4x4_makeLookAt() {
+ tm1 = new Float32Array(16);
+ tm2 = new Float32Array(16);
+ r = new Float32Array(16)
+ return M4x4.mul(tm1, tm2, r);
+};
+var jellyfish = {};
+jellyfish.order = [];
+function jellyfishInstance() {}
+jellyfishInstance.prototype.drawShadow = function () {
+ pMatrix = M4x4.makeLookAt();
+ M4x4.mul(M4x4.makeLookAt(), pMatrix, pMatrix);
+ M4x4.scale3(6, 180, 0, pMatrix);
+}
+function drawScene() {
+ jellyfish.order.push([0, 0])
+ jellyfish[0] = new jellyfishInstance()
+ for (var i = 0, j = 0; i < jellyfish.count, j < 30; ++j) {
+ jellyfish.order[i][0]
+ jellyfish[0].drawShadow();
+ }
+}
+drawScene();
+
diff --git a/js/src/jit-test/tests/basic/bug652060.js b/js/src/jit-test/tests/basic/bug652060.js new file mode 100644 index 0000000000..d7d5609a09 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug652060.js @@ -0,0 +1,9 @@ +var x = -false; +var y = -0; +assertEq(-x === x, true); +assertEq(-x === y, true); +assertEq(-y !== y, false); + +assertEq(-x == x, true); +assertEq(-x == y, true); +assertEq(-y != y, false); diff --git a/js/src/jit-test/tests/basic/bug652422.js b/js/src/jit-test/tests/basic/bug652422.js new file mode 100644 index 0000000000..64525ee36a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug652422.js @@ -0,0 +1,6 @@ +try { (function() { + var o = {}; + with (o) o='recorder not started, '; + ('arguments' in o, false, + "property deletion observable") +})() } catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug652646.js b/js/src/jit-test/tests/basic/bug652646.js new file mode 100644 index 0000000000..5f54c32dea --- /dev/null +++ b/js/src/jit-test/tests/basic/bug652646.js @@ -0,0 +1,11 @@ +function foo() { + try { + return 0; + } catch (e) { + try { + return 1; + } catch (e) { + } + } +} +foo(); diff --git a/js/src/jit-test/tests/basic/bug653153.js b/js/src/jit-test/tests/basic/bug653153.js new file mode 100644 index 0000000000..c06e3b82b8 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug653153.js @@ -0,0 +1,76 @@ +// ES5 15.1.2.2 step 1 + +/* + * Boundary testing for super-large positive numbers between non-exponential + * and in-exponential-form. + * + * NB: While 1e21 is exactly representable as an IEEE754 double-precision + * number, its nearest neighboring representable values are a good distance + * away, 65536 to be precise. + */ + +// This is the boundary in theory. +assertEq(parseInt(1e21), 1); + +// This is the boundary in practice. +assertEq(parseInt(1e21 - 65537) > 1e20, true); +assertEq(parseInt(1e21 - 65536), 1); +assertEq(parseInt(1e21 + 65536), 1); + +// Check that we understand floating point accuracy near the boundary +assertEq(1e21 - 65537 !== 1e21 - 65536, true); +assertEq(1e21 - 65536, 1e21); +assertEq(1e21 + 65535, 1e21); +assertEq(1e21 + 65536, 1e21); + +// ES5 leaves exact precision in ToString(bigMagNum) undefined, which +// might make this value inconsistent across implementations (maybe, +// nobody's done the math here). Regardless, it's definitely a number +// very close to 1, and not a large-magnitude positive number. +assertEq(1e21 + 65537 !== 1e21, true); +assertEq(parseInt(1e21 + 65537) < 1.001, true); + + +/* + * Now do the same tests for super-large negative numbers crossing the + * opposite boundary. + */ + +// This is the boundary in theory. +assertEq(parseInt(-1e21), -1); + +// This is the boundary in practice. +assertEq(parseInt(-1e21 + 65537) < -1e20, true); +assertEq(parseInt(-1e21 + 65536), -1); +assertEq(parseInt(-1e21 - 65536), -1); + +// Check that we understand floating point accuracy near the boundary +assertEq(-1e21 + 65537 !== -1e21 + 65536, true); +assertEq(-1e21 + 65536, -1e21); +assertEq(-1e21 - 65535, -1e21); +assertEq(-1e21 - 65536, -1e21); + +// ES5 leaves exact precision in ToString(bigMagNum) undefined, which +// might make this value inconsistent across implementations (maybe, +// nobody's done the math here). Regardless, it's definitely a number +// very close to -1, and not a large-magnitude negative number. +assertEq(-1e21 - 65537 !== 1e21, true); +assertEq(parseInt(-1e21 - 65537) > -1.001, true); + + +/* Check values around the boundary. */ +arr = [1e0, 5e1, 9e19, 0.1e20, 1.3e20, 1e20, 9e20, 9.99e20, 0.1e21, + 1e21, 1.0e21, 2e21, 2e20, 2.1e22, 9e21, 0.1e22, 1e22, 3e46, 3e23, 3e100, 3.4e200, 7e1000, + 1e21, 1e21+65537, 1e21+65536, 1e21-65536, 1e21-65537]; + +/* Check across a range of values in case we missed anything. */ +for (var i = 0; i < 4000; i++) { + arr.push(1e19 + i*1e19); +} + +for (var i in arr) { + assertEq(parseInt( arr[i]), parseInt(String( arr[i]))); + assertEq(parseInt(-arr[i]), parseInt(String(-arr[i]))); +} + + diff --git a/js/src/jit-test/tests/basic/bug653262.js b/js/src/jit-test/tests/basic/bug653262.js new file mode 100644 index 0000000000..9a488bbaa1 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug653262.js @@ -0,0 +1,4 @@ +with(evalcx(''))(function eval() {}, this.__defineGetter__("x", Function)); +var i = 0; +var o; +new(x); diff --git a/js/src/jit-test/tests/basic/bug653438.js b/js/src/jit-test/tests/basic/bug653438.js new file mode 100644 index 0000000000..23cd086ba2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug653438.js @@ -0,0 +1,2 @@ +assertEq((123456789).toExponential(), "1.23456789e+8"); +assertEq((123456789).toExponential(undefined), "1.23456789e+8"); diff --git a/js/src/jit-test/tests/basic/bug653672.js b/js/src/jit-test/tests/basic/bug653672.js new file mode 100644 index 0000000000..c9d5e202b4 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug653672.js @@ -0,0 +1,5 @@ +// don't crash + +var regexp1 = /(?:(?=g))|(?:m).{2147483648,}/; +var regexp2 = /(?:(?=g)).{2147483648,}/; + diff --git a/js/src/jit-test/tests/basic/bug654073.js b/js/src/jit-test/tests/basic/bug654073.js new file mode 100644 index 0000000000..7659d534b8 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug654073.js @@ -0,0 +1,11 @@ +load(libdir + "immutable-prototype.js"); + +if (globalPrototypeChainIsMutable()) { + this.__proto__ = null; + Object.prototype.__proto__ = this; +} + +for (var y in Object.prototype) + continue; +for (var x in this) + continue; diff --git a/js/src/jit-test/tests/basic/bug654668.js b/js/src/jit-test/tests/basic/bug654668.js new file mode 100644 index 0000000000..8706c154a2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug654668.js @@ -0,0 +1,10 @@ +var summary = 'foo'; +function X(n) { + var y = []; + while (summary + y[0]) { + break; + } +} +X(); + +// Don't crash wthi -m -n -a diff --git a/js/src/jit-test/tests/basic/bug656261.js b/js/src/jit-test/tests/basic/bug656261.js new file mode 100644 index 0000000000..8757508045 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug656261.js @@ -0,0 +1,31 @@ +function build_getter(i) { + var x = [i]; + return function f() { return x; } +} + +function test() +{ + var N = internalConst("MARK_STACK_BASE_CAPACITY") + 2; + var o = {}; + var descriptor = { enumerable: true}; + for (var i = 0; i != N; ++i) { + descriptor.get = build_getter(i); + Object.defineProperty(o, i, descriptor); + } + + // At this point we have an object o with N getters. Each getter in turn + // is a closure storing an array. During the GC we push to the object + // marking stack all the getters found in an object after we mark it. As N + // exceeds the size of the object marking stack, this requires to run the + // dealyed scanning for some closures to mark the array objects stored in + // them. + // + // We run the GC twice to make sure that the background finalization + // finishes before we access the objects. + gc(); + gc(); + for (var i = 0; i != N; ++i) + assertEq(o[i][0], i); +} + +test(); diff --git a/js/src/jit-test/tests/basic/bug657197.js b/js/src/jit-test/tests/basic/bug657197.js new file mode 100644 index 0000000000..fde956abee --- /dev/null +++ b/js/src/jit-test/tests/basic/bug657197.js @@ -0,0 +1,5 @@ +try { (function() { + new function() { + throw []; + } +})() } catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug657225.js b/js/src/jit-test/tests/basic/bug657225.js new file mode 100644 index 0000000000..510b768515 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug657225.js @@ -0,0 +1,9 @@ + +function reportCompare(expected, actual, description) { return + ++actual + "'"; } +var summary = 'Object.prototype.toLocaleString() should track Object.prototype.toString() '; +var o = { + toString: function () {} +}; +expect = o; +actual = o.toLocaleString(); +reportCompare(expect, actual, summary); diff --git a/js/src/jit-test/tests/basic/bug657245.js b/js/src/jit-test/tests/basic/bug657245.js new file mode 100644 index 0000000000..15bea1c94f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug657245.js @@ -0,0 +1,4 @@ + +var length = 4294967295; +var array1 = Array(length); +array1.pop(); diff --git a/js/src/jit-test/tests/basic/bug657901.js b/js/src/jit-test/tests/basic/bug657901.js new file mode 100644 index 0000000000..a0531ae758 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug657901.js @@ -0,0 +1,8 @@ +function f() {}; +function g(o) { + f = new Function(""); + eval(""); +} +g({}); +g({}); +f++; diff --git a/js/src/jit-test/tests/basic/bug658539.js b/js/src/jit-test/tests/basic/bug658539.js new file mode 100644 index 0000000000..0454394113 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug658539.js @@ -0,0 +1,2 @@ +with(newGlobal('same-compartment')) +new Number() diff --git a/js/src/jit-test/tests/basic/bug660081.js b/js/src/jit-test/tests/basic/bug660081.js new file mode 100644 index 0000000000..1c62a654c3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug660081.js @@ -0,0 +1 @@ +(function() { "length" in (true && arguments); })() diff --git a/js/src/jit-test/tests/basic/bug660173.js b/js/src/jit-test/tests/basic/bug660173.js new file mode 100644 index 0000000000..99d0f8ed8c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug660173.js @@ -0,0 +1,4 @@ +(function() {}).apply(null, (function() { + var x; + return (x = arguments); +})()); diff --git a/js/src/jit-test/tests/basic/bug660203.js b/js/src/jit-test/tests/basic/bug660203.js new file mode 100644 index 0000000000..faed7b6864 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug660203.js @@ -0,0 +1,9 @@ + +function throwsRangeError(t) { + try { + var date = arguments; + date.setTime + } catch (err) { + } +} +throwsRangeError(); diff --git a/js/src/jit-test/tests/basic/bug660204.js b/js/src/jit-test/tests/basic/bug660204.js new file mode 100644 index 0000000000..eddd4ba839 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug660204.js @@ -0,0 +1,12 @@ + +eval("try { name(); } catch(e) {}"); +function Employee ( name, dept ) { + this.name=name || "" + this.dept +} +function WorkerBee ( name, dept, projs ) { + this.base=Employee + this.base( name, print("WHAT")) +} +new WorkerBee; +WorkerBee(); diff --git a/js/src/jit-test/tests/basic/bug660597.js b/js/src/jit-test/tests/basic/bug660597.js new file mode 100644 index 0000000000..207a828e71 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug660597.js @@ -0,0 +1,5 @@ + +function foo() { + with(foo) this["00"]=function(){} +} +new foo; diff --git a/js/src/jit-test/tests/basic/bug662044.js b/js/src/jit-test/tests/basic/bug662044.js new file mode 100644 index 0000000000..bebabef84f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug662044.js @@ -0,0 +1,12 @@ +eval("var OBJ = new MyObject(true); OBJ.valueOf()") +function MyObject( value ) { + this.valueOf = new Function( "return this.value" ); +} +eval("\ +var VERSION = \"ECMA_1\";\ +var DATE1 = new Date();\ +var MYOB1 = new MyObject( DATE1 );\ +function MyProtoValuelessObject() {}\ +function Function() {\ + __proto__[MyProtoValuelessObject] = VERSION;\ +}"); diff --git a/js/src/jit-test/tests/basic/bug662841.js b/js/src/jit-test/tests/basic/bug662841.js new file mode 100644 index 0000000000..351bb97a9b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug662841.js @@ -0,0 +1,4 @@ +var e = newGlobal(); +for (let w in [0, 0, 0, 0, 0, 0, 0, 0]) { + -e; +} diff --git a/js/src/jit-test/tests/basic/bug663338.js b/js/src/jit-test/tests/basic/bug663338.js new file mode 100644 index 0000000000..efc038972b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug663338.js @@ -0,0 +1,26 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + + +assertEq(parseInt(1.0e-7, 10), 1); +assertEq(parseInt(-1.0e-7, 10), -1); + +assertEq(parseInt(9e-8, 10), 9); +assertEq(parseInt(-9e-8, 10), -9); + +assertEq(parseInt(1.5e-8, 10), 1); +assertEq(parseInt(-1.5e-8, 10), -1); + +assertEq(parseInt(1.0e-6, 10), 0); + +assertEq(parseInt(0, 10), 0); +assertEq(parseInt(-0, 10), 0); + +assertEq(parseInt('0', 10), 0); +assertEq(parseInt('-0', 10), -0); + +// Test with 0 typed as a double instead of int. +assertEq(parseInt(numberToDouble(0), 10), 0); +assertEq(parseInt(numberToDouble(-0), 10), 0); diff --git a/js/src/jit-test/tests/basic/bug665289.js b/js/src/jit-test/tests/basic/bug665289.js new file mode 100644 index 0000000000..a5e9d7e548 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug665289.js @@ -0,0 +1,4 @@ +delete this.Function; +a = evalcx("lazy"); +a["Object"] = this; +if (typeof a.isPrototypeOf == "") {} diff --git a/js/src/jit-test/tests/basic/bug666448.js b/js/src/jit-test/tests/basic/bug666448.js new file mode 100644 index 0000000000..aef626265d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug666448.js @@ -0,0 +1 @@ +assertEq(["a"].map(escape)[0], ["a"].map(function(s) {return escape(s);})[0]); diff --git a/js/src/jit-test/tests/basic/bug667504-syntax.js b/js/src/jit-test/tests/basic/bug667504-syntax.js new file mode 100644 index 0000000000..6069220206 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug667504-syntax.js @@ -0,0 +1,3 @@ +for (var x in x) { +function x() {} +} diff --git a/js/src/jit-test/tests/basic/bug667507.js b/js/src/jit-test/tests/basic/bug667507.js new file mode 100644 index 0000000000..883857a1e7 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug667507.js @@ -0,0 +1,6 @@ +for (i = 0; i < 10; i++) { + Object.defineProperty({}, "", { + get: function() {} + }) + gc() +} diff --git a/js/src/jit-test/tests/basic/bug673468.js b/js/src/jit-test/tests/basic/bug673468.js new file mode 100644 index 0000000000..90749115b3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug673468.js @@ -0,0 +1,8 @@ +var g = newGlobal(); +var k = g.eval('var u = new Object(); u'); +var m = new WeakMap(); +m.set(k, {}); +k = null; +gc(); +k = g.eval('u'); +assertEq(m.has(k), true); diff --git a/js/src/jit-test/tests/basic/bug673469.js b/js/src/jit-test/tests/basic/bug673469.js new file mode 100644 index 0000000000..21dbf43fe3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug673469.js @@ -0,0 +1,9 @@ +var a = Boolean(); +false.__proto__; +var c = ({}).__proto__; +var d = {}; +gc() +c[0] = d; +for (var x in a) { + a[x]; +} diff --git a/js/src/jit-test/tests/basic/bug673569.js b/js/src/jit-test/tests/basic/bug673569.js new file mode 100644 index 0000000000..05f031d9ce --- /dev/null +++ b/js/src/jit-test/tests/basic/bug673569.js @@ -0,0 +1,18 @@ +function qualified_tests(prefix) { + let scope = evalReturningScope(prefix + "var x = 1"); + assertEq(scope.x, 1); +} + +qualified_tests(""); +qualified_tests("'use strict'; "); + +let scope = evalReturningScope("x = 1"); +assertEq(scope.x, 1); + +let fail = true; +try { + evalReturningScope("'use strict'; x = 1"); +} catch (e) { + fail = false; +} +assertEq(fail, false); diff --git a/js/src/jit-test/tests/basic/bug673705-1.js b/js/src/jit-test/tests/basic/bug673705-1.js new file mode 100644 index 0000000000..42fc30591c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug673705-1.js @@ -0,0 +1,10 @@ +function bug673705() { + var x; + try { + } catch (e) { + } finally { + print(x); + } + return x; +} +assertEq(bug673705(), undefined); diff --git a/js/src/jit-test/tests/basic/bug673705-2.js b/js/src/jit-test/tests/basic/bug673705-2.js new file mode 100644 index 0000000000..28076f9c46 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug673705-2.js @@ -0,0 +1,12 @@ +function bug673705() { + var x; + try { + try { + } catch (e) { + } + } finally { + } + print(x); + return x; +} +assertEq(bug673705(), undefined); diff --git a/js/src/jit-test/tests/basic/bug673715.js b/js/src/jit-test/tests/basic/bug673715.js new file mode 100644 index 0000000000..b204069061 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug673715.js @@ -0,0 +1,10 @@ +function g() { + "use strict"; + for (var i = 0; i < 50; i++) + arguments[0]; + eval(""); +} +function f() { + g.call(arguments); +} +f(); diff --git a/js/src/jit-test/tests/basic/bug673731.js b/js/src/jit-test/tests/basic/bug673731.js new file mode 100644 index 0000000000..ca249828e6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug673731.js @@ -0,0 +1,3 @@ +// |jit-test| error: ReferenceError + +const IS_TOKEN_ARRAY = [ printBugNumber && this() ? this() : this() ]; diff --git a/js/src/jit-test/tests/basic/bug673766.js b/js/src/jit-test/tests/basic/bug673766.js new file mode 100644 index 0000000000..d1bdc3d45c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug673766.js @@ -0,0 +1,20 @@ +function TestCase(n, d, e, a) { + this.name = n + this.description = d +} +function reportCompare(expected, actual, description) { + new TestCase +} +var actual = ''; +var expect = ''; +for (var i = 0; i < 2; ++i) reportCompare(expect, actual, ': 2'); +try { + ({ + valueOf: gc + } - []) +} catch (prop) {} +function addThis() { return reportCompare(expect, actual, 'ok'); } +Object.defineProperty(Object.prototype, "name", { + set: function (newValue) {} +}); +addThis() diff --git a/js/src/jit-test/tests/basic/bug673767.js b/js/src/jit-test/tests/basic/bug673767.js new file mode 100644 index 0000000000..5a7fb07b7d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug673767.js @@ -0,0 +1,2 @@ +var stack = {}; +stack.length += 3; diff --git a/js/src/jit-test/tests/basic/bug674085.js b/js/src/jit-test/tests/basic/bug674085.js new file mode 100644 index 0000000000..0147621e7a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug674085.js @@ -0,0 +1,6 @@ +function f(x) { + for (var i = 0; i < 50; i++) {}; + [1][arguments[0]]++; + x = 1.2; +} +f(0); diff --git a/js/src/jit-test/tests/basic/bug674776.js b/js/src/jit-test/tests/basic/bug674776.js new file mode 100644 index 0000000000..2693029caa --- /dev/null +++ b/js/src/jit-test/tests/basic/bug674776.js @@ -0,0 +1,18 @@ +// |jit-test| slow + +/* Make a lot of functions of the form: +function x1(){x1();} +function x2(){x2();} +function x3(){x3();} +... +*/ + +var g = newGlobal({newCompartment: true}); +var dbg = new g.Debugger(this); + +var s = ''; +for (var i = 0; i < 70000; i++) { + s += 'function x' + i + '() { x' + i + '(); }\n'; +} +s += 'pc2line(1);\n' +evaluate(s); diff --git a/js/src/jit-test/tests/basic/bug677635.js b/js/src/jit-test/tests/basic/bug677635.js new file mode 100644 index 0000000000..fffc67cc59 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug677635.js @@ -0,0 +1,7 @@ + +index = 0; +test(); +function test() { + var [message,prettyPrinting]=[arguments,__lookupGetter__]; + message<index; +} diff --git a/js/src/jit-test/tests/basic/bug678211.js b/js/src/jit-test/tests/basic/bug678211.js new file mode 100644 index 0000000000..6918be3fce --- /dev/null +++ b/js/src/jit-test/tests/basic/bug678211.js @@ -0,0 +1,3 @@ +var g = newGlobal(); +g.eval("function f(n) { for (var i = 0; i < n; i++) f(0); }"); +g.f(10); diff --git a/js/src/jit-test/tests/basic/bug679977.js b/js/src/jit-test/tests/basic/bug679977.js new file mode 100644 index 0000000000..f11311945d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug679977.js @@ -0,0 +1,26 @@ +var Test = function (foo) { + var a = []; + + this.fillArray = function() { + a = []; + for (var i = 0; i < 10; i++) + a.push(0); + assertEq(a.length, 10); + } + + foo.go(this); +}; + +// Import assertEq now to prevent global object shape from changing. +assertEq(true, true); + +(new Test({ go: function(p) { + p.fill = function() { + p.fillArray(); + } +}})).fill(); + +new Test({ go: function(p) { + for (var k = 0; k < 10; k++) + p.fillArray(); +}}); diff --git a/js/src/jit-test/tests/basic/bug679986-1.js b/js/src/jit-test/tests/basic/bug679986-1.js new file mode 100644 index 0000000000..e1e5128104 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug679986-1.js @@ -0,0 +1,2 @@ +// don't assert +var m = "aaaa".match(/(?:|a)*/); diff --git a/js/src/jit-test/tests/basic/bug679986-2.js b/js/src/jit-test/tests/basic/bug679986-2.js new file mode 100644 index 0000000000..95e84901b0 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug679986-2.js @@ -0,0 +1,2 @@ +// don't hang +var m = "aaaa".match(/(?:a?)*/); diff --git a/js/src/jit-test/tests/basic/bug680217.js b/js/src/jit-test/tests/basic/bug680217.js new file mode 100644 index 0000000000..90f6b38fb2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug680217.js @@ -0,0 +1,13 @@ +try { + for (var BUGNUMBER = 0, sz = Math.pow(2, 12); i < sz; i++) + str += '0,'; +} catch (exc1) {} +var str = '['; +for (var i = 0, BUGNUMBER; i < sz; i++) + str += '0,'; +var obj = { + p: { __proto__: null }, +}; +for (var i = 0; i < sz; i++) + str += '0,'; +gc(); diff --git a/js/src/jit-test/tests/basic/bug683140.js b/js/src/jit-test/tests/basic/bug683140.js new file mode 100644 index 0000000000..23b9982147 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug683140.js @@ -0,0 +1,13 @@ + +var g = newGlobal("same-compartment"); +g.eval("this.f = function(a) {" + + "assertEq(a instanceof Array, false);" + + "a = Array.prototype.slice.call(a);" + + "assertEq(a instanceof Array, true); }"); +g.f([1, 2, 3]); + +var g2 = newGlobal(); +g2.a = g2.Array(10); +assertEq(g2.a instanceof Array, false); +g2.a = Array.prototype.slice(g2.a); +assertEq(g2.a instanceof Array, true); diff --git a/js/src/jit-test/tests/basic/bug683838.js b/js/src/jit-test/tests/basic/bug683838.js new file mode 100644 index 0000000000..841376c031 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug683838.js @@ -0,0 +1,3 @@ +var rg = /(X(?:.(?!X))*?Y)|(Y(?:.(?!Y))*?Z)/g;
+var str = "Y aaa X Match1 Y aaa Y Match2 Z";
+assertEq(str.match(rg) + "", "X Match1 Y,Y Match2 Z");
diff --git a/js/src/jit-test/tests/basic/bug685313.js b/js/src/jit-test/tests/basic/bug685313.js new file mode 100644 index 0000000000..f791e5e66b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug685313.js @@ -0,0 +1,11 @@ + +function foo() { + function D(){} + arr = [ + new (function D ( ) { + D += '' + foo; + }), + new D + ]; +} +foo(); diff --git a/js/src/jit-test/tests/basic/bug685321-1.js b/js/src/jit-test/tests/basic/bug685321-1.js new file mode 100644 index 0000000000..789651fc93 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug685321-1.js @@ -0,0 +1,11 @@ +function f() { + function g() { + for (var i = 0; i < 3; i++) + x = i; + }; + var [x] = []; + g(); + assertEq(x, 2); + print(x); +} +f(); diff --git a/js/src/jit-test/tests/basic/bug685321-2.js b/js/src/jit-test/tests/basic/bug685321-2.js new file mode 100644 index 0000000000..3cc6718cc5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug685321-2.js @@ -0,0 +1,13 @@ +var o = {};
+function f() {
+ function g() {
+ x = 80;
+ return x;
+ };
+ Object.defineProperty(o, "f", {get:g});
+ var [x] = [];
+ x = {};
+ 2 + o.f;
+ print(x);
+}
+f();
diff --git a/js/src/jit-test/tests/basic/bug686296.js b/js/src/jit-test/tests/basic/bug686296.js new file mode 100644 index 0000000000..f83917d777 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug686296.js @@ -0,0 +1,3 @@ +load(libdir + "asserts.js"); +var o = Object.preventExtensions(new ArrayBuffer); +assertThrowsInstanceOf(function () { o.__proto__ = {}; }, TypeError); diff --git a/js/src/jit-test/tests/basic/bug686396.js b/js/src/jit-test/tests/basic/bug686396.js new file mode 100644 index 0000000000..8123fc99c3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug686396.js @@ -0,0 +1,16 @@ + +(function () { + assertEquals = function assertEquals(expected, found, name_opt) { }; +})(); +function testOne(receiver, key, result) { + for(var i = 0; i != 10; i++ ) { + assertEquals(result, receiver[key]()); + } +} +function TypeOfThis() { return typeof this; } +Number.prototype.type = TypeOfThis; +String.prototype.type = TypeOfThis; +Boolean.prototype.type = TypeOfThis; +testOne(2.3, 'type', 'object'); +testOne('x', 'type', 'object'); +testOne(true, 'type', 'object'); diff --git a/js/src/jit-test/tests/basic/bug688939.js b/js/src/jit-test/tests/basic/bug688939.js new file mode 100644 index 0000000000..c2bf473a7e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug688939.js @@ -0,0 +1,4 @@ +gczeal(2); +string="" +for (var i = 0; i < 100; i++ ) + hex=newGlobal('same-compartment'); diff --git a/js/src/jit-test/tests/basic/bug689916-regexp.js b/js/src/jit-test/tests/basic/bug689916-regexp.js new file mode 100644 index 0000000000..620b302eb4 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug689916-regexp.js @@ -0,0 +1,4 @@ +/* should not crash on SPARC */ +var http_string = 'https://easylist-downloads.adblockplus.org/easylist.txt'; +var regexp = /^[\w\-]+:\/+(?!\/)(?:[^.\/]+\.)*?reports\.adblockplus\.org(?:[\x00-\x24\x26-\x2C\x2F\x3A-\x40\x5B-\x5E\x60\x7B-\x80]|$)/i; +assertEq(http_string.match(regexp), null); diff --git a/js/src/jit-test/tests/basic/bug690732.js b/js/src/jit-test/tests/basic/bug690732.js new file mode 100644 index 0000000000..bfcb728914 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug690732.js @@ -0,0 +1,4 @@ + +var o4 = Object.freeze({ + set: function(summary) {} +}); diff --git a/js/src/jit-test/tests/basic/bug691797-regexp-1.js b/js/src/jit-test/tests/basic/bug691797-regexp-1.js new file mode 100644 index 0000000000..b78c0cb063 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug691797-regexp-1.js @@ -0,0 +1,4 @@ +var re = /.*star.*/i; +var str = "The Shawshank Redemption (1994)"; +for (var k = 0; k < 100; k++) + assertEq(false, re.test(str)); diff --git a/js/src/jit-test/tests/basic/bug691797-regexp-2.js b/js/src/jit-test/tests/basic/bug691797-regexp-2.js new file mode 100644 index 0000000000..a8c0c44864 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug691797-regexp-2.js @@ -0,0 +1,6 @@ +var re = /.*(a\w).*/i; +var str = "abccccccad"; +for (var k = 0; k < 100; k++) { + re.test(str); + assertEq('ad', RegExp['$1']); +} diff --git a/js/src/jit-test/tests/basic/bug695922-syntax.js b/js/src/jit-test/tests/basic/bug695922-syntax.js new file mode 100644 index 0000000000..599888080e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug695922-syntax.js @@ -0,0 +1,2 @@ +load(libdir + "asserts.js"); +assertThrowsInstanceOf(function () { eval("({p:"); }, SyntaxError); // don't crash diff --git a/js/src/jit-test/tests/basic/bug696748.js b/js/src/jit-test/tests/basic/bug696748.js new file mode 100644 index 0000000000..33fb4d52f9 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug696748.js @@ -0,0 +1,13 @@ +eval("\ +var URI = '';\ +test();\ +function test() {\ + URI += '<zcti application=\"xxxx_demo\">';\ + URI += '<pstn_data>';\ + URI += '<dnis>877-485-xxxx</dnis>';\ + URI += '</pstn_data>';\ + URI >>= '<keyvalue key=\"name\" value=\"xxx\"/>';\ + URI += '<keyvalue key=\"phone\" value=\"6509309000\"/>';\ +}\ +test();\ +"); diff --git a/js/src/jit-test/tests/basic/bug699166.js b/js/src/jit-test/tests/basic/bug699166.js new file mode 100644 index 0000000000..1b75e174a2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug699166.js @@ -0,0 +1,7 @@ +a = "".__proto__ +b = String().__proto__ +for (var i = 0; i < 2; i++) { + a.__defineSetter__("valueOf", function() {}) + a + "" + delete b.valueOf +} diff --git a/js/src/jit-test/tests/basic/bug700300.js b/js/src/jit-test/tests/basic/bug700300.js new file mode 100644 index 0000000000..ccee3ecfd2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug700300.js @@ -0,0 +1,4 @@ +for (let j = 0; j < (20); ++(__lookupSetter__)) { + function g() { j; } + j++; +} diff --git a/js/src/jit-test/tests/basic/bug702426-regexp-gc.js b/js/src/jit-test/tests/basic/bug702426-regexp-gc.js new file mode 100644 index 0000000000..206e2fd957 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug702426-regexp-gc.js @@ -0,0 +1,5 @@ +function g(code) { + eval("(function(){" + code + "})")() +} +g("evalcx(\"(/a/g,function(){})\")"); +g("'a'.replace(/a/g,gc)") diff --git a/js/src/jit-test/tests/basic/bug702572.js b/js/src/jit-test/tests/basic/bug702572.js new file mode 100644 index 0000000000..50595d09e5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug702572.js @@ -0,0 +1,10 @@ +eval("function f() { function g() {} return g; }"); +assertEq(f().prototype !== f().prototype, true); + +function f1() { + function g1() { + function h1() { return h1; } + } + return g1; +} +assertEq(f1().prototype !== f1().prototype, true); diff --git a/js/src/jit-test/tests/basic/bug703157.js b/js/src/jit-test/tests/basic/bug703157.js new file mode 100644 index 0000000000..2acdd92ebd --- /dev/null +++ b/js/src/jit-test/tests/basic/bug703157.js @@ -0,0 +1,36 @@ +// Define a test object +var test = {x:1,y:2}; + +// Put the object into dictionary mode by deleting +// a property that was not the last one added. +delete test.x; + +// Define a an accessor property with a setter that +// itself calls Object.defineProperty +Object.defineProperty(test, "foo", { + get: function() { return 1; }, + set: function(v) { + Object.defineProperty(this, "foo", { value: v }); + // Prints the correct object descriptor + assertEq(this.foo, 33); + }, + configurable: true +}); + +// Add another property, so generateOwnShape does not replace the foo property. +test.other = 0; + +// This line prints 1, as expected +assertEq(test.foo, 1); + +// Now set the property. This calls the setter method above. +// And the setter method prints the expected value and property descriptor. +test.foo = 33; + +// Finally read the newly set value. +assertEq(test.foo, 33); + +// Check that enumeration order is correct. +var arr = []; +for (var x in test) arr.push(x); +assertEq("" + arr, "y,other"); diff --git a/js/src/jit-test/tests/basic/bug703544.js b/js/src/jit-test/tests/basic/bug703544.js new file mode 100644 index 0000000000..87d1a1b0d0 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug703544.js @@ -0,0 +1,7 @@ +gczeal(4); +function testInterpreterReentry7() { + var arr = [0, 1, 2, 3, 4]; + for (var i = (1); i < 5; i++) + arr[i] = "grue"; +} +testInterpreterReentry7(); diff --git a/js/src/jit-test/tests/basic/bug703818.js b/js/src/jit-test/tests/basic/bug703818.js new file mode 100644 index 0000000000..9d844986af --- /dev/null +++ b/js/src/jit-test/tests/basic/bug703818.js @@ -0,0 +1,3 @@ +Object.defineProperty(Array.prototype, "toString", { + enumerable: true +}) diff --git a/js/src/jit-test/tests/basic/bug704134.js b/js/src/jit-test/tests/basic/bug704134.js new file mode 100644 index 0000000000..947a0b13bb --- /dev/null +++ b/js/src/jit-test/tests/basic/bug704134.js @@ -0,0 +1,12 @@ +function f(s) { + eval(s); + return function() { + with({}) {}; + return b; + }; +} +var b = 1; +var g1 = f(""); +var g2 = f("var b = 2;"); +g1(''); +assertEq(g2(''), 2); diff --git a/js/src/jit-test/tests/basic/bug705895-1.js b/js/src/jit-test/tests/basic/bug705895-1.js new file mode 100644 index 0000000000..c2beca9f63 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug705895-1.js @@ -0,0 +1,16 @@ +load(libdir + "immutable-prototype.js"); + +c = Number.prototype; +function f(o) { + if (globalPrototypeChainIsMutable() || o !== Object.prototype) + o.__proto__ = null + for (x in o) {} +} +for (i = 0; i < 9; i++) { + f(c) + if (globalPrototypeChainIsMutable()) + Object.prototype.__proto__ = c; + for (x in Object.prototype) + continue; + f(Math.__proto__); +} diff --git a/js/src/jit-test/tests/basic/bug705895-2.js b/js/src/jit-test/tests/basic/bug705895-2.js new file mode 100644 index 0000000000..445efb56a8 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug705895-2.js @@ -0,0 +1,13 @@ +// |jit-test| error: TypeError +function f(o) { + for (j = 0; j < 9; j++) { + if (j) { + o.__proto__ = null + } + for (v in o) {} + } +} +for (i = 0; i < 9; i++) { + (new Boolean).__proto__.__defineGetter__("toString", function() {}) + f(Boolean.prototype) +} diff --git a/js/src/jit-test/tests/basic/bug706316.js b/js/src/jit-test/tests/basic/bug706316.js new file mode 100644 index 0000000000..d34aa79f78 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug706316.js @@ -0,0 +1,11 @@ +// |jit-test| error: ReferenceError
+gczeal(4);
+function setprop() {
+ var obj = { a:({ } ) };
+ var obj2 = { b:-1, a:-1 };
+ for (var i = 0; i < 20; (length(resultsY.global0, 42))) {
+ obj2.b = obj.a = i;
+ }
+}
+assertEq(setprop(), "19,-1,19");
+
diff --git a/js/src/jit-test/tests/basic/bug706795.js b/js/src/jit-test/tests/basic/bug706795.js new file mode 100644 index 0000000000..57d1a41a4e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug706795.js @@ -0,0 +1,7 @@ +executed = false; +Object.defineProperty(Object.prototype, 'x', { set: function() { executed = true; } }); +function A() { + this.x = 12; +} +new A(); +assertEq(executed, true); diff --git a/js/src/jit-test/tests/basic/bug706808.js b/js/src/jit-test/tests/basic/bug706808.js new file mode 100644 index 0000000000..8bbba9d98a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug706808.js @@ -0,0 +1,5 @@ + +Object.defineProperty(Object.prototype, "a", {}); +function t2(b) { this.a = b; } +var x = new t2(3); +assertEq(x.a, undefined); diff --git a/js/src/jit-test/tests/basic/bug707750.js b/js/src/jit-test/tests/basic/bug707750.js new file mode 100644 index 0000000000..56df1043c6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug707750.js @@ -0,0 +1,9 @@ +// |jit-test| error: ReferenceError +var lfcode = new Array(); +lfcode.push("gczeal(4);"); +lfcode.push('print(BUGNUMBER + ": " + (W -- ));'); +while (true) { + var file = lfcode.shift(); if (file == undefined) { break; } + eval(file); +} + diff --git a/js/src/jit-test/tests/basic/bug708228.js b/js/src/jit-test/tests/basic/bug708228.js new file mode 100644 index 0000000000..4a627fd1fb --- /dev/null +++ b/js/src/jit-test/tests/basic/bug708228.js @@ -0,0 +1,5 @@ +// |jit-test| error: TypeError +gczeal(4); +var g_rx = /(?:)/; +(3).replace(g_rx.compile("test", "g"), {}); + diff --git a/js/src/jit-test/tests/basic/bug708819.js b/js/src/jit-test/tests/basic/bug708819.js new file mode 100644 index 0000000000..8f3f0a552e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug708819.js @@ -0,0 +1,12 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +try { + var e = new Error(); + e.name = e; + "" + e; +} catch (e) { + assertEq(e.message, 'too much recursion'); +} diff --git a/js/src/jit-test/tests/basic/bug709634.js b/js/src/jit-test/tests/basic/bug709634.js new file mode 100644 index 0000000000..78691ca98d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug709634.js @@ -0,0 +1,6 @@ + +Function.prototype.toString = function () { return f(this, true); }; +function f(obj) { + f.caller.p +} +decodeURI + 3; diff --git a/js/src/jit-test/tests/basic/bug710947.js b/js/src/jit-test/tests/basic/bug710947.js new file mode 100644 index 0000000000..2782880206 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug710947.js @@ -0,0 +1,8 @@ +// |jit-test| allow-oom; +function startTest() { + if (typeof document != "object" + || !document.location.href.match(/jsreftest.html/)) {} +}; +gczeal(4); +startTest(); +new ArrayBuffer( 8192 ); diff --git a/js/src/jit-test/tests/basic/bug713226.js b/js/src/jit-test/tests/basic/bug713226.js new file mode 100644 index 0000000000..dc7e5adea4 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug713226.js @@ -0,0 +1,20 @@ +// |jit-test| +gczeal(4); +var optionNames = options().split(','); + for (var i = 0; i < optionNames.length; i++) + var optionName = optionNames[i]; +evaluate("\ +function addDebug(g, id) {\ + var debuggerGlobal = newGlobal({newCompartment: true});\ + debuggerGlobal.debuggee = g;\ + debuggerGlobal.id = id;\ + debuggerGlobal.print = function (s) { print(s); };\ + debuggerGlobal.eval('var dbg = new Debugger(debuggee);dbg.onDebuggerStatement = function () { print(id); debugger; };');\ + return debuggerGlobal;\ +}\ +var base = newGlobal({newCompartment: true});\ +var top = base;\ +for (var i = 0; i < 8; i++ )\ + top = addDebug(top, i);\ +base.eval('debugger;');\ +"); diff --git a/js/src/jit-test/tests/basic/bug714614.js b/js/src/jit-test/tests/basic/bug714614.js new file mode 100644 index 0000000000..fd01dce561 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug714614.js @@ -0,0 +1,5 @@ +function testForVarInWith(foo, foo) { + return eval("with ({}) { for (var x = 0; x < 5; x++); } (function() { return delete x; })"); +} +f = testForVarInWith()(); + diff --git a/js/src/jit-test/tests/basic/bug714616.js b/js/src/jit-test/tests/basic/bug714616.js new file mode 100644 index 0000000000..706594d055 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug714616.js @@ -0,0 +1,8 @@ +array1 = new Array(); +size = 10; +for (i = 0; i < size; (array1.length)++) +{ + array1.push(array1.shift()); + ++i +} + diff --git a/js/src/jit-test/tests/basic/bug716013.js b/js/src/jit-test/tests/basic/bug716013.js new file mode 100644 index 0000000000..defd30537b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug716013.js @@ -0,0 +1,4 @@ +f = (function*() { + for (x in [arguments, arguments]) yield(gczeal(4, function(){})) +}); +for (i of f()) {} diff --git a/js/src/jit-test/tests/basic/bug718852.js b/js/src/jit-test/tests/basic/bug718852.js new file mode 100644 index 0000000000..845b84cf3f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug718852.js @@ -0,0 +1,15 @@ +// |jit-test| error:ReferenceError + +function fannkuch(n) { + var perm1 = Array(n); + while (true) { + if (check < 30){ + for(var i=0; i<n; i++) s += (perm1[i]+1).toString(); + while (i < r) { + var j = this.abstract + 1; + perm1[i] = perm1[j]; + } + } + } +} +fannkuch(8); diff --git a/js/src/jit-test/tests/basic/bug719750.js b/js/src/jit-test/tests/basic/bug719750.js new file mode 100644 index 0000000000..a90535371f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug719750.js @@ -0,0 +1,12 @@ +function f( ) { + var [ [x], e ] = ["*", "/", "%"]; + function h() { + for (var i = 0; i < 5; ++i) { + x = i * 2; + } + } + h(); + assertEq(x, 8); +} +f(); + diff --git a/js/src/jit-test/tests/basic/bug720070.js b/js/src/jit-test/tests/basic/bug720070.js new file mode 100644 index 0000000000..859b0b8af8 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug720070.js @@ -0,0 +1,6 @@ +var bytes = [0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; // big-endian +bytes.reverse(); // if testing on little-endian +var result = new Float64Array(new Uint8Array(bytes).buffer)[0]; + +// Check that this doesn't crash +isNaN(result + 0); diff --git a/js/src/jit-test/tests/basic/bug720675.js b/js/src/jit-test/tests/basic/bug720675.js new file mode 100644 index 0000000000..4589867f41 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug720675.js @@ -0,0 +1,9 @@ +// |jit-test| allow-oom; allow-unhandlable-oom + +gcparam("maxBytes", gcparam("gcBytes") + 4*1024); +arr = [1e0, 5e1, 9e19, 0.1e20, 1.3e20, 1e20, 9e20, 9.99e20, + 0.1e21, 1e21, 1e21+65537, 1e21+65536, 1e21-65536, 1]; +for (var i = 0; i < 4000; i++) { + arr.push(1e19 + i*1e19); +} +for (var i in arr) {} diff --git a/js/src/jit-test/tests/basic/bug722028.js b/js/src/jit-test/tests/basic/bug722028.js new file mode 100644 index 0000000000..837e34460b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug722028.js @@ -0,0 +1,13 @@ + +gczeal(4); +var BUGNUMBER = 668024; +var summary = +print(BUGNUMBER + ": " + summary); +var arr = [0, 1, 2, 3, 4, 5, , 7]; +var seen = []; +for (var p in arr) { + if (seen.indexOf(unescape) >= 0) {} + arr.splice(2, 3); + seen.push(p); +} + diff --git a/js/src/jit-test/tests/basic/bug727223.js b/js/src/jit-test/tests/basic/bug727223.js new file mode 100644 index 0000000000..5011c134df --- /dev/null +++ b/js/src/jit-test/tests/basic/bug727223.js @@ -0,0 +1,15 @@ +try { + mjitChunkLimit(1) + function x() {} +} catch (e) {} +(function() { + for (let c in [0, 0, 0]) { + let c + for (y in decodeURI()) { + (function() { + c + }()) + } + } +}()) + diff --git a/js/src/jit-test/tests/basic/bug727921.js b/js/src/jit-test/tests/basic/bug727921.js new file mode 100644 index 0000000000..7c7e6418f4 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug727921.js @@ -0,0 +1,11 @@ +(function*() { + { + let d; + yield + } +})() +eval("\ + (function(){\ + schedulegc(5), 'a'.replace(/a/,function*(){yield})\ + })\ +")() diff --git a/js/src/jit-test/tests/basic/bug728086.js b/js/src/jit-test/tests/basic/bug728086.js new file mode 100644 index 0000000000..9d7a771026 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug728086.js @@ -0,0 +1,66 @@ +var expected = ''; +function TestCase(n, d, e, a) {} +function reportFailure (msg) {} +function toPrinted(value) { + value = value.replace(/\\\n/g, 'NL') + .replace(/[^\x20-\x7E]+/g, escapeString); +} +function escapeString (str) {} +function reportCompare (expected, actual, description) { + var expected_t = typeof expected; + var actual_t = typeof actual; + var output = ""; + var testcase = new TestCase("unknown-test-name", description, expected, actual); + reportFailure (description + " : " + output); +} +function enterFunc (funcName) { + return callStack.push(funcName); +} + try { + reportCompare(expectCompile, actualCompile, + summary + ': compile actual'); + } catch(ex) { } +var lfcode = new Array(); +lfcode.push("gczeal(2);\ +enterFunc ('test');\ +"); +lfcode.push("{}"); +lfcode.push("noexist.js"); +lfcode.push("var BUGNUMBER = 305064;\ +var summary = 'Tests the trim, trimRight and trimLeft methods';\ +var trimMethods = ['trim', 'trimLeft', 'trimRight'];\ +var whitespace = [\ + {s : '\\u0009', t : 'HORIZONTAL TAB'},\ + {s : '\\u200A', t : 'HAIR SPACE'},\ + ];\ +for (var j = 0; j < trimMethods.length; ++j)\ + var method = trimMethods[j];\ + reportCompare(true, true, 'Test skipped. String.prototype.' + method + ' is not supported');\ + str = '';\ + for (var i = 0; i < whitespace.length; ++i) {\ + var v = whitespace[i].s;\ + var t = (summary)[i].t;\ + v = v + v + v;\ + print('Test ' + method + ' with with leading whitespace. : ' + t);\ + actual = str[method]();\ + reportCompare(expected, actual, t + ':' + '\"' + toPrinted(str) + '\".' + method + '()');\ + str = v + 'a' + v;\ +}\ +"); +while (true) { + var file = lfcode.shift(); if (file == undefined) { break; } + if (file == "evaluate") { + } else { + loadFile(file); + } +} +function loadFile(lfVarx) { + try { + if (lfVarx.substr(-3) == ".js") { + switch (lfRunTypeId) { + } + } else { + eval(lfVarx); + } + } catch (lfVare) { } +} diff --git a/js/src/jit-test/tests/basic/bug728190.js b/js/src/jit-test/tests/basic/bug728190.js new file mode 100644 index 0000000000..0e2f29726e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug728190.js @@ -0,0 +1,24 @@ +// |jit-test| slow; + +function TestCase(n, d, e, a) {} +var lfcode = new Array(); +lfcode.push(""); +lfcode.push("\ + var summary = 'foo';\ + test();\ + function test() {\ + test(\"TEST-UNEXPECTED-FAIL | TestPerf | \" + summary);\ + }\ +"); +lfcode.push("gczeal(2);"); +lfcode.push("\ + new TestCase(TestFunction_3( \"P\", \"A\", \"S\", \"S\" ) +\"\");\ + new TestCase(TestFunction_4( \"F\", \"A\", (\"length\"), \"L\" ) +\"\");\ + function TestFunction_3( a, b, c, d, e ) {\ + TestFunction_3(arguments);\ + }\ +"); +while (true) { + var file = lfcode.shift(); if (file == undefined) { break; } + try { evaluate(file); } catch (lfVare) {} +} diff --git a/js/src/jit-test/tests/basic/bug728609.js b/js/src/jit-test/tests/basic/bug728609.js new file mode 100644 index 0000000000..cd6f088e79 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug728609.js @@ -0,0 +1,23 @@ +var lfcode = new Array(); +lfcode.push("\ +test();\ +function test() {\ + function removeAllProperties(o) {\ + bar() = thaw, patterns;\ + }\ + var o = { method: function() { this.first.method(); } };\ + o.first = { method: function() { removeAllProperties(o); } };\ + return o.method();\ +}\ +"); +lfcode.push("test();"); +gczeal(4); +while (true) { + var file = lfcode.shift(); if (file == undefined) { break; } + loadFile(file); +} +function loadFile(lfVarx) { + try { + evaluate(lfVarx); + } catch (lfVare) { } +} diff --git a/js/src/jit-test/tests/basic/bug730085.js b/js/src/jit-test/tests/basic/bug730085.js new file mode 100644 index 0000000000..f2f6cb6994 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug730085.js @@ -0,0 +1,6 @@ +load(libdir + "asserts.js"); +var calledToString = false; +assertThrowsInstanceOf(function () { Object.prototype.hasOwnProperty.call(null, + {toString: function () { calledToString = true; }}); }, + TypeError); +assertEq(calledToString, true); diff --git a/js/src/jit-test/tests/basic/bug730888.js b/js/src/jit-test/tests/basic/bug730888.js new file mode 100644 index 0000000000..5d328d6aa5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug730888.js @@ -0,0 +1,14 @@ + +(function() { + for (var i = 0; i < 64; ++i) { + var name; + switch (this) { + case 0: name = 'firstAttr'; break; + case 1: name = 'secondAttr'; + case 2: name = 'thirdAttr'; break; + } + switch (name) { + case 'firstAttr': assertEq(result, 'value'); break; + } + } +})(); diff --git a/js/src/jit-test/tests/basic/bug731642.js b/js/src/jit-test/tests/basic/bug731642.js new file mode 100644 index 0000000000..5459dfa657 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug731642.js @@ -0,0 +1,2 @@ +Object.defineProperty(Object.prototype, 1, {get: function() { this.foo++; return 23 }}); +assertEq([1,,].pop(), 23); diff --git a/js/src/jit-test/tests/basic/bug732693.js b/js/src/jit-test/tests/basic/bug732693.js new file mode 100644 index 0000000000..d82da1e24e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug732693.js @@ -0,0 +1,10 @@ +var res = 0; +var o = {__proto__: function() { res++; }}; + +function f() { + for (var i=0; i<70; i++) { + o.__proto__(); + } +} +f(); +assertEq(res, 70); diff --git a/js/src/jit-test/tests/basic/bug737384.js b/js/src/jit-test/tests/basic/bug737384.js new file mode 100644 index 0000000000..6ec87ec784 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug737384.js @@ -0,0 +1,10 @@ +a = evalcx(''); +for (var i = 0; i < 1000; i++) { + a[i] = i; +} +function foo(x) { + for (var i in x) + var summary = "Basic support for iterable objects and for-in"; +} +schedulegc(1234); +foo(a); diff --git a/js/src/jit-test/tests/basic/bug738841.js b/js/src/jit-test/tests/basic/bug738841.js new file mode 100644 index 0000000000..3429aea5b3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug738841.js @@ -0,0 +1,49 @@ +try { + for (let z = 0; z < 1; ++evalcx("[]", newGlobal())) {} +} catch (e) {} +try { + for (y in [schedulegc(58)]) { + b + } +} catch (e) {} +try { + e +} catch (e) {} +try { + (function() { + h + }()) +} catch (e) {} +try { + (function() { + this.m.f = function() {} + }()) +} catch (e) {} +try { + t() +} catch (e) {} +try { + p +} catch (e) {} +try { + gc() + p +} catch (e) {} +try { + (function() { + for (var v of m) {} + }()) +} catch (e) {} +try { + m +} catch (e) {} +try { + var f = function() { + { + print(new function(q) { return ("", s); }) + let u + } + }; + dis(f); + f(); +} catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug738846.js b/js/src/jit-test/tests/basic/bug738846.js new file mode 100644 index 0000000000..32f973bdc0 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug738846.js @@ -0,0 +1,49 @@ +try { + (function() { + var m + new ArrayBuffer() + var _ = t + var _2 = [] + }()) +} catch (e) {} +try { + for (y in [schedulegc(58)]) { + m + } +} catch (e) {} +try { + (function() { + true + }()) +} catch (e) {} +try { + (function() { + s + }()) +} catch (e) {} +try { + e +} catch (e) {} +try { + "" () +} catch (e) {} +try { + gc() + s +} catch (e) {} +try { + (function() { + for (v of m) {} + }()) +} catch (e) {} +try { + t +} catch (e) {} +try { + (function() { + "use strict"; + print(new function() { + r + }(this)) + }()) +} catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug739694-2.js b/js/src/jit-test/tests/basic/bug739694-2.js new file mode 100644 index 0000000000..41cc4b6e46 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug739694-2.js @@ -0,0 +1,8 @@ +try { + ({ + f: evalcx("evalcx(\"e\",newGlobal())", + newGlobal()) + }) +} catch (e) {} +gc() +gc() diff --git a/js/src/jit-test/tests/basic/bug743961.js b/js/src/jit-test/tests/basic/bug743961.js new file mode 100644 index 0000000000..6c1f253d46 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug743961.js @@ -0,0 +1,2 @@ +var n = (evalcx('lazy')); +try { var nbuf = serialize(n); } catch(e) {} // Don't crash diff --git a/js/src/jit-test/tests/basic/bug744285.js b/js/src/jit-test/tests/basic/bug744285.js new file mode 100644 index 0000000000..a1033f764a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug744285.js @@ -0,0 +1,71 @@ +// |jit-test| error: TypeError; +var TZ_DIFF = getTimeZoneDiff(); +var now = new Date; +var TZ_DIFF = getTimeZoneDiff(); +var now = new Date; +var MAX_UNIX_TIMET = 2145859200; +var RANGE_EXPANSION_AMOUNT = 60; +function tzOffsetFromUnixTimestamp(timestamp) { + new Date + } +function clearDSTOffsetCache(undesiredTimestamp) { + tzOffsetFromUnixTimestamp() + tzOffsetFromUnixTimestamp() + tzOffsetFromUnixTimestamp() + tzOffsetFromUnixTimestamp() + tzOffsetFromUnixTimestamp() + } +function computeCanonicalTZOffset(timestamp) { + clearDSTOffsetCache() + tzOffsetFromUnixTimestamp() + } +var TEST_TIMESTAMPS_SECONDS = [ + 0, + RANGE_EXPANSION_AMOUNT, + MAX_UNIX_TIMET, + ]; +var TEST_TIMESTAMPS = TEST_TIMESTAMPS_SECONDS.map(function(v) { }); +var CORRECT_TZOFFSETS = TEST_TIMESTAMPS.map(computeCanonicalTZOffset); +var TZ_DIFF = getTimeZoneDiff(); +var now = new Date; +var TZ_DIFF = getTimeZoneDiff(); +var now = new Date;function getTimeZoneDiff() { + new Date/60 +} +function check(b, desc) { + function classOf(obj) { + return Object.prototype.toString.call(obj); + } + function ownProperties(obj) { + return Object.getOwnPropertyNames(obj). + map(function (p) { return [p, Object.getOwnPropertyDescriptor(obj, p)]; }); + } + function isCloneable(pair) { } + function assertIsCloneOf(a, b, path) { + ca = classOf(a) + assertEq(ca, classOf(b), path) + assertEq(Object.getPrototypeOf(a), ca == "[object Object]" ? Object.prototype : Array.prototype, path) + pb = ownProperties(b).filter(isCloneable) + pa = ownProperties(a) + function byName(a, b) { return 0; } + byName + (pa.length, pb.length, "should see the same number of properties " + path) + for (var i = 0; i < pa.length; i++) { + gczeal(4) + } + } + banner = desc || String() + a = deserialize(serialize(b)) + var queue = [[a, b, banner]]; + while (queue.length) { + var triple = queue.shift(); + assertIsCloneOf(triple[0], triple[1], triple[2]) + } +} +check({x: 0.7, p: "forty-two", y: null, z: undefined}); +check(Object.prototype); +b=[, , 2, 3]; +b.expando=true; +b[5]=5; +b[0]=0;b[4]=4; +check(b)([, , , , , , 6]) diff --git a/js/src/jit-test/tests/basic/bug744287.js b/js/src/jit-test/tests/basic/bug744287.js new file mode 100644 index 0000000000..534b644e61 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug744287.js @@ -0,0 +1,6 @@ +function callbackfn(v) { + gczeal(4); + return arr[0] + (Uint8ClampedArray); +} +arr = [1,2,3,4,5]; +arr = arr.map(callbackfn); diff --git a/js/src/jit-test/tests/basic/bug744356.js b/js/src/jit-test/tests/basic/bug744356.js new file mode 100644 index 0000000000..9487f5f4d5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug744356.js @@ -0,0 +1,14 @@ +// |jit-test| error: ReferenceError; +gczeal(4); +function* gen() { + var c = [1, "x"]; + try { + yield c; + } finally { + gc(); + } +} +var iter = gen(); +for (i of iter) { + (SECTION)(); +} diff --git a/js/src/jit-test/tests/basic/bug745360.js b/js/src/jit-test/tests/basic/bug745360.js new file mode 100644 index 0000000000..7d17b722c6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug745360.js @@ -0,0 +1,2 @@ +// |jit-test| error: TypeError +newGlobal().eval("eval.arguments") diff --git a/js/src/jit-test/tests/basic/bug749039.js b/js/src/jit-test/tests/basic/bug749039.js new file mode 100644 index 0000000000..6461de7774 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug749039.js @@ -0,0 +1,11 @@ +// |jit-test| error: ReferenceError; +gczeal(4); +try { jsTestDriverEnd(); } catch(exc1) {} +evaluate("\ +schedulegc(10);\ +for(var i=0; i<3; i++) {\ + var obj = { first: 'first', second: 'second' };\ + for (var elem in obj) {}\ + x.push(count);\ +}\ +"); diff --git a/js/src/jit-test/tests/basic/bug749620.js b/js/src/jit-test/tests/basic/bug749620.js new file mode 100644 index 0000000000..75d11db362 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug749620.js @@ -0,0 +1,16 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var v = [0, 0x7fffffff]; +v.sort(); + +assertEq(v[0], 0); +assertEq(v[1], 0x7fffffff); + +v = [0x7fffffff, 0]; +v.sort(); + +assertEq(v[0], 0); +assertEq(v[1], 0x7fffffff); diff --git a/js/src/jit-test/tests/basic/bug750307.js b/js/src/jit-test/tests/basic/bug750307.js new file mode 100644 index 0000000000..b60ad08941 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug750307.js @@ -0,0 +1,5 @@ +load(libdir + "asserts.js"); +var g = newGlobal(); +var a = g.RegExp("x"); +Object.defineProperty(a, "ignoreCase", {value: undefined}); +a.toString(); diff --git a/js/src/jit-test/tests/basic/bug754150.js b/js/src/jit-test/tests/basic/bug754150.js new file mode 100644 index 0000000000..c66c16dbc3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug754150.js @@ -0,0 +1,49 @@ +// |jit-test| error: TypeError; + +// String.prototype.replace takes too long time with gczeal(4) if +// --no-baseline --no-ion options. +if (typeof inJit == "function" && typeof inJit() == "string") { + assertEq(inJit(), "Baseline is disabled."); + // This test expects TypeError. + toPrinted(null); +} + +function printStatus (msg) {} +function toPrinted(value) { + value = value.replace(/\\n/g, 'NL') +} +function reportCompare (expected, actual, description) { + printStatus ("Expected value '" + toPrinted(expected) + "' matched actual value '" + toPrinted(actual) + "'"); +} +var UBound = 0; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; +testThis('x()'); +testThis('"abc"()'); +testThis('x()'); +testThis('Date(12345)()'); +testThis('x()'); +testThis('1()'); +testThis('x()'); +testThis('void(0)()'); +testThis('x()'); +testThis('[1,2,3,4,5](1)'); +gczeal(4); +testThis('x(1)'); +checkThis('(function (y) {return y+1;})("abc")'); +checkThis('f("abc")'); +function testThis(sInvalidSyntax) { + expectedvalues[UBound] = expect; + actualvalues[UBound] = actual; + UBound++; +} +function checkThis(sValidSyntax) { + for (var i=0; i<UBound; i++) + reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); +} +var actualvalues = []; +for (var i=0; i<UBound; i++) + reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); diff --git a/js/src/jit-test/tests/basic/bug754242.js b/js/src/jit-test/tests/basic/bug754242.js new file mode 100644 index 0000000000..fe5d6aafed --- /dev/null +++ b/js/src/jit-test/tests/basic/bug754242.js @@ -0,0 +1,7 @@ +var g1 = newGlobal(); +schedulezone(g1); +gcslice(1); +function testEq(b) { + var a = deserialize(serialize(b)); +} +testEq(Array(1024).join(Array(1024).join((false)))); diff --git a/js/src/jit-test/tests/basic/bug756851.js b/js/src/jit-test/tests/basic/bug756851.js new file mode 100644 index 0000000000..d45ace6613 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug756851.js @@ -0,0 +1,10 @@ +o0 = {}; +g = new ArrayBuffer; +g2 = this; +v = g2.o0.t; +o0 = Object; +var y = { + x: gc(gcPreserveCode()) +} +y.toString(); +for (z = 0; z < 100; z++) {} diff --git a/js/src/jit-test/tests/basic/bug757199.js b/js/src/jit-test/tests/basic/bug757199.js new file mode 100644 index 0000000000..73adacd8e2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug757199.js @@ -0,0 +1,23 @@ +function ctor() +{ + this.a = 1; + this.b = 2; +} +function f2(o) +{ + o.c = 12; +} +function f() +{ + var x = new ctor(); + verifyprebarriers(); + f2(x); + verifyprebarriers(); +} +f(); +f(); +var o = {}; +for (var i=0; i<1000; i++) + o['a'+i] = 3; +f(); +f(); diff --git a/js/src/jit-test/tests/basic/bug757431.js b/js/src/jit-test/tests/basic/bug757431.js new file mode 100644 index 0000000000..326f31efdf --- /dev/null +++ b/js/src/jit-test/tests/basic/bug757431.js @@ -0,0 +1,18 @@ + +function setterFunction(v) { called = true; } +function getterFunction(v) { return "getter"; } +Object.defineProperty(Array.prototype, 1,{ + get: getterFunction, + set: setterFunction +}); +gczeal(4); +var N = 350; +var source = "".concat( + repeat_str("try { f(); } finally {\n", N), + repeat_str("}", N)); +function repeat_str(str, repeat_count) { + var arr = new Array(--repeat_count); + while (repeat_count != 0) + arr[--repeat_count] = str; + return str.concat.apply(str, arr); +} diff --git a/js/src/jit-test/tests/basic/bug763440.js b/js/src/jit-test/tests/basic/bug763440.js new file mode 100644 index 0000000000..babc4f5ab0 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug763440.js @@ -0,0 +1,26 @@ +load(libdir + "immutable-prototype.js"); + +var summary = ''; +var actual = ''; +gcPreserveCode() +function TestCase(n, d, e, a) { + this.name=n; +} +function reportCompare (expected, actual, description) { + new TestCase +} +reportCompare(true, eval++, "Dummy description."); +var p = new Proxy({}, { + has : function(id) {}, + set : function() {} +}); +if (globalPrototypeChainIsMutable()) + Object.prototype.__proto__ = p; +new TestCase; +var expect = ''; +reportCompare(expect, actual, summary); +gczeal(4); +try { + evalcx("."); +} catch (e) {} +reportCompare(expect, actual, summary); diff --git a/js/src/jit-test/tests/basic/bug767074.js b/js/src/jit-test/tests/basic/bug767074.js new file mode 100644 index 0000000000..76704c6571 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug767074.js @@ -0,0 +1,11 @@ +var callStack = new Array(); +function exitFunc (funcName) { + var lastFunc = callStack.pop(); +} +gczeal(4); +var sb = evalcx(''); +sb.parent = this; +this.f = function name(outer) { + return (exitFunc ('test')); +} +evalcx('this.f = parent.f; var s = ""; for (i = 0; i < 10; ++i) s += f(true); s', sb); diff --git a/js/src/jit-test/tests/basic/bug767234.js b/js/src/jit-test/tests/basic/bug767234.js new file mode 100644 index 0000000000..71844b2f19 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug767234.js @@ -0,0 +1,14 @@ +function* gen() +{ + var local = new Date(); + yield 1; + local = null; + gc(); + gcslice(0); // Start IGC, but don't mark anything. + yield 2; +} + +var g = gen(); +g.next(); +g.next(); +gcslice(); diff --git a/js/src/jit-test/tests/basic/bug767273.js b/js/src/jit-test/tests/basic/bug767273.js new file mode 100644 index 0000000000..2d8e99d3ca --- /dev/null +++ b/js/src/jit-test/tests/basic/bug767273.js @@ -0,0 +1,7 @@ +var prox = new Proxy({}, { + getOwnPropertyDescriptor: function() { return undefined; }, + has: function() { return true; }, +}); + +// Don't crash. +newGlobal().__lookupSetter__.call(prox, "e"); diff --git a/js/src/jit-test/tests/basic/bug768732.js b/js/src/jit-test/tests/basic/bug768732.js new file mode 100644 index 0000000000..5be491c691 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug768732.js @@ -0,0 +1,6 @@ +a = '' +b = [] +a = b.concat(a) +Object.defineProperty(a, 3, { + e: gczeal(4, 2) +}) diff --git a/js/src/jit-test/tests/basic/bug769433.js b/js/src/jit-test/tests/basic/bug769433.js new file mode 100644 index 0000000000..3eefcaa5bf --- /dev/null +++ b/js/src/jit-test/tests/basic/bug769433.js @@ -0,0 +1,8 @@ + +function stringConvert() { + var a = Uint32Array.prototype; + for (var i = 0; i < 10; i++) { + a[0] = i; + } +} +stringConvert(); diff --git a/js/src/jit-test/tests/basic/bug770952.js b/js/src/jit-test/tests/basic/bug770952.js new file mode 100644 index 0000000000..2a6efeeb7a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug770952.js @@ -0,0 +1,7 @@ +// |jit-test| error: TypeError +load(libdir + "iteration.js"); + +eval("var x; typeof x") +Array.prototype[Symbol.iterator] = function () { for(y in x); }; +for (var v of ['a', 'b', 'c', 'd']) + s = v; diff --git a/js/src/jit-test/tests/basic/bug773153.js b/js/src/jit-test/tests/basic/bug773153.js new file mode 100644 index 0000000000..6eacea853d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug773153.js @@ -0,0 +1,3 @@ +function f() { + "" < ""; +} diff --git a/js/src/jit-test/tests/basic/bug774859.js b/js/src/jit-test/tests/basic/bug774859.js new file mode 100644 index 0000000000..b1d4255bde --- /dev/null +++ b/js/src/jit-test/tests/basic/bug774859.js @@ -0,0 +1,16 @@ +gczeal(4,1); +function g() +{ + try { + return []; + } catch (e) {} +} +function f() +{ + for (var i=0; i<2; i++) { + var o = {a: g(), + a: g()}; + print(i); + } +} +f(); diff --git a/js/src/jit-test/tests/basic/bug777776.js b/js/src/jit-test/tests/basic/bug777776.js new file mode 100644 index 0000000000..fc0753ffe4 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug777776.js @@ -0,0 +1,5 @@ +gczeal(9, 2) +for (a = 0; a < 4; ++a) { + b = + evaluate("/x/g"); +} diff --git a/js/src/jit-test/tests/basic/bug777992.js b/js/src/jit-test/tests/basic/bug777992.js new file mode 100644 index 0000000000..c86f41ceb7 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug777992.js @@ -0,0 +1,9 @@ +verifyprebarriers() +x = [] +function z() {} +Object.defineProperty(x, 2, { + value: z +}) +gczeal(2, 2) +y = x.slice(2) +y.e = (function() {}) diff --git a/js/src/jit-test/tests/basic/bug781393.js b/js/src/jit-test/tests/basic/bug781393.js new file mode 100644 index 0000000000..2559b6fa0a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug781393.js @@ -0,0 +1,14 @@ +gczeal(4,1); +function check(o) +{ + print(o); + assertEq(o.b, 3); +} +function f() +{ + for (var i=0; i<3; i++) { + var o = {b: 3}; + check(o); + } +} +f(); diff --git a/js/src/jit-test/tests/basic/bug782337.js b/js/src/jit-test/tests/basic/bug782337.js new file mode 100644 index 0000000000..6f956ae56e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug782337.js @@ -0,0 +1,15 @@ +gc(); + +function recur(n) +{ + if (n == 0) { + gcslice(); + gc(); + } else { + recur(n-1); + } + var obj = new Object(); +} + +gcslice(1); +recur(10); diff --git a/js/src/jit-test/tests/basic/bug783989.js b/js/src/jit-test/tests/basic/bug783989.js new file mode 100644 index 0000000000..88a9b627c7 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug783989.js @@ -0,0 +1,2 @@ +// |jit-test| error: Error +wrapWithProto(0); diff --git a/js/src/jit-test/tests/basic/bug785094.js b/js/src/jit-test/tests/basic/bug785094.js new file mode 100644 index 0000000000..7c30f834ef --- /dev/null +++ b/js/src/jit-test/tests/basic/bug785094.js @@ -0,0 +1,2 @@ +// |jit-test| --dump-bytecode +Function("for(let b; true; x) \nfalse"); diff --git a/js/src/jit-test/tests/basic/bug785175.js b/js/src/jit-test/tests/basic/bug785175.js new file mode 100644 index 0000000000..f6a36fd9bc --- /dev/null +++ b/js/src/jit-test/tests/basic/bug785175.js @@ -0,0 +1,9 @@ +var str = ' '; +// Generate a 4MB string = 2^(20+2) +for (var i = 0; i < 22; i++) { + str = str + str; +} +str += 'var a = 1 + 1;'; + +// don't throw an exception even though the column numbers cannot be maintained +eval(str); diff --git a/js/src/jit-test/tests/basic/bug786114.js b/js/src/jit-test/tests/basic/bug786114.js new file mode 100644 index 0000000000..718d0426c6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug786114.js @@ -0,0 +1,32 @@ +let expected = 'o!o!o!'; +let actual = ''; + +// g is a function that needs an implicit |this| if called within a |with| +// statement. If we fail to provide that implicit |this|, it will append +// "[object global]" instead of "o!". +let o = { + g: function() { actual += this.toString(); }, + toString: function() { return "o!"; } +} + +// g's presence within the |with| is detected by simple tracking of |with|s +// during parsing. +with (o) { + (function() { g(); })(); +} + +// The eval() defeats the tracking of |with| during parsing. Instead, g's +// presence within the |with| is detected by looking at the scopeChain of the +// ParseContext. +with (o) { + eval("(function() { g(); })()"); +} + +// This is like the above case, but the knowledge of the |with| presence must +// be inherited by the inner function. This is the case that was missed in bug +// 786114. +with (o) { + eval("(function() { (function() { g(); })(); })()"); +} + +assertEq(actual, expected); diff --git a/js/src/jit-test/tests/basic/bug787847.js b/js/src/jit-test/tests/basic/bug787847.js new file mode 100644 index 0000000000..3adc68fc2b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug787847.js @@ -0,0 +1,22 @@ +var g = true; + +function get(name) +{ + if (g) + return 8; +} + +var p = new Proxy({}, { get: get } ); +var o2 = Object.create(p); + +function test(x, expected) { + for (var i=0; i<3; i++) { + var v = x.hello; + if (g) assertEq(v, 8); + } +} + +g = false +test(o2); +g = true; +test(o2); diff --git a/js/src/jit-test/tests/basic/bug791465.js b/js/src/jit-test/tests/basic/bug791465.js new file mode 100644 index 0000000000..13460a11f0 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug791465.js @@ -0,0 +1,75 @@ +load(libdir + "asserts.js"); + +var valid_strict_funs = [ + // directive ends on next line + function () { + "use strict" + ; + }, + function () { + "use strict" + }, + // directive ends on same line + function () { "use strict"; }, + function () { "use strict" }, +]; + +for (var f of valid_strict_funs) { + assertThrowsInstanceOf(function() { f.caller }, TypeError); +} + + +var binary_ops = [ + "||", "&&", + "|", "^", "&", + "==", "!=", "===", "!==", + "<", "<=", ">", ">=", "in", "instanceof", + "<<", ">>", ">>>", + "+", "-", + "*", "/", "%", +]; + +var invalid_strict_funs = [ + function () { + "use strict" + , "not"; + }, + function () { + "use strict" + ? 1 : 0; + }, + function () { + "use strict" + .length; + }, + function () { + "use strict" + [0]; + }, + function () { + "use strict" + (); + }, + ...([]), + ...(binary_ops.map(op => Function("'use strict'\n " + op + " 'not'"))), +]; + +for (var f of invalid_strict_funs) { + f.caller; +} + + +var assignment_ops = [ + "=", "+=", "-=", + "|=", "^=", "&=", + "<<=", ">>=", ">>>=", + "*=", "/=", "%=", +]; + +var invalid_strict_funs_syntax_error = assignment_ops.map(op => ("'use strict'\n " + op + " 'not'")); + +// assignment with string literal as LHS is an early error, therefore we +// can only test for SyntaxError +for (var f of invalid_strict_funs_syntax_error) { + assertThrowsInstanceOf(function() { Function(f) }, SyntaxError); +} diff --git a/js/src/jit-test/tests/basic/bug792239.js b/js/src/jit-test/tests/basic/bug792239.js new file mode 100644 index 0000000000..0635acf114 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug792239.js @@ -0,0 +1,6 @@ +var f = String.prototype.m = function () { + return [this.m, this]; +}; +var a = "s".m(); +gczeal(4); +evaluate("for (a = 0; a < 13; a++) {}", { noScriptRval: true }); diff --git a/js/src/jit-test/tests/basic/bug794025.js b/js/src/jit-test/tests/basic/bug794025.js new file mode 100644 index 0000000000..c76eab73e5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug794025.js @@ -0,0 +1,15 @@ +// |jit-test| error:RangeError + +function getterFunction(v) { return "getter"; } +Object.defineProperty(Array.prototype, 1,{ + get: getterFunction, +}); +var N = (10000); +repeat_str("try { f(); } finally {\n", N), +repeat_str("}", ("" )); +function repeat_str(str, repeat_count) { + var arr = new Array(--repeat_count); + while (repeat_count != 0) + arr[--repeat_count] = str; + return str.concat.apply(str, arr); +} diff --git a/js/src/jit-test/tests/basic/bug794286.js b/js/src/jit-test/tests/basic/bug794286.js new file mode 100644 index 0000000000..a3c1a13cdd --- /dev/null +++ b/js/src/jit-test/tests/basic/bug794286.js @@ -0,0 +1,6 @@ +// |jit-test| error: TypeError +for (var i = 0; i < 1; i++) { + let y + if (undefined) continue + undefined.e +} diff --git a/js/src/jit-test/tests/basic/bug794947.js b/js/src/jit-test/tests/basic/bug794947.js new file mode 100644 index 0000000000..e8a2829da2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug794947.js @@ -0,0 +1,10 @@ +function f(o) +{ + print(o instanceof String); +} + +var g = newGlobal(); +f(new Object()); +var o1 = g.eval('new Object()'); +var o2 = Object.create(o1); +f(o2); diff --git a/js/src/jit-test/tests/basic/bug797496.js b/js/src/jit-test/tests/basic/bug797496.js new file mode 100644 index 0000000000..d8bc1897c5 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug797496.js @@ -0,0 +1,8 @@ +// |jit-test| error: TypeError +var set = new Set(['a']); +var n = 5; +for (let v of set) { + if (n === 0) + break; + let g = set(new Set(0xffffffff, n), 1); +} diff --git a/js/src/jit-test/tests/basic/bug798678.js b/js/src/jit-test/tests/basic/bug798678.js new file mode 100644 index 0000000000..e68dae4d0c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug798678.js @@ -0,0 +1,10 @@ +var w = new WeakMap(); +var g = newGlobal(); +var k = g.eval('for (var i=0; i<100; i++) new Object(); var q = new Object(); q'); +w.set(k, {}); +k = null; + +gc(); +g.eval('q = null'); +gc(g); +gc(); diff --git a/js/src/jit-test/tests/basic/bug798834.js b/js/src/jit-test/tests/basic/bug798834.js new file mode 100644 index 0000000000..669fe20d34 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug798834.js @@ -0,0 +1,5 @@ +(function(start, stop, step) { + stop = start; + step = arguments[2]; + assertEq(stop, true); +})(true); diff --git a/js/src/jit-test/tests/basic/bug806522.js b/js/src/jit-test/tests/basic/bug806522.js new file mode 100644 index 0000000000..1507276c1a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug806522.js @@ -0,0 +1,7 @@ +load(libdir + "asserts.js"); + +var g = evalcx("lazy"); +assertThrowsInstanceOf( + () => evaluate("{ let eval; eval()}", {global: g}), + g.TypeError); // eval is not a function +assertEq(evaluate("{ let eval = parseInt; eval()}", {global: g}), NaN); diff --git a/js/src/jit-test/tests/basic/bug807623.js b/js/src/jit-test/tests/basic/bug807623.js new file mode 100644 index 0000000000..35c34d3cb3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug807623.js @@ -0,0 +1,12 @@ +var objectProxy = new Proxy({}, {}); +var functionProxy = new Proxy(function() {}, {}); + +assertEq(Object.prototype.toString.call(objectProxy), '[object Object]'); +assertEq(Object.prototype.toString.call(functionProxy), '[object Function]'); + +try { + Function.prototype.toString.call(objectProxy); + assertEq(true, false); +} catch (e) { + assertEq(!!/incompatible/.exec(e), true); +} diff --git a/js/src/jit-test/tests/basic/bug808067.js b/js/src/jit-test/tests/basic/bug808067.js new file mode 100644 index 0000000000..34abc2a11d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug808067.js @@ -0,0 +1,20 @@ +function TestCase(n, d, e, a) { + return this.reason = ''; +} +function reportCompare (expected, actual, description) { + var output = ""; + var testcase = new TestCase("unknown-test-name", description, expected, actual); + testcase.reason = output; +} +gcPreserveCode(); +var summary = 'return with argument and lazy generator detection'; +expect = "generator function foo returns a value"; +actual = (function (j) {}).message; +reportCompare(expect, actual, summary + ": 1"); +reportCompare(expect, actual, summary + ": 2"); +gcslice(1); +gcslice(2); +gc(); +var strings = [ (0), ]; +for (var i = 0; i < strings.length; i++) + reportCompare(expect, actual, summary + (5e1) + strings[i]); diff --git a/js/src/jit-test/tests/basic/bug808483.js b/js/src/jit-test/tests/basic/bug808483.js new file mode 100644 index 0000000000..9dd2be0293 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug808483.js @@ -0,0 +1,16 @@ +pSandbox = newGlobal(); +evalcx("\ + x = ArrayBuffer;\ + y = new Map();\ + x += 1;\ + w = x;\ + x += '0';\ + z = x;\ +", pSandbox); +evalcx("\ + x + '0';\ +", pSandbox); +evalcx("\ + y.delete(z);\ + w.slice(2);\ +", pSandbox) diff --git a/js/src/jit-test/tests/basic/bug817002.js b/js/src/jit-test/tests/basic/bug817002.js new file mode 100644 index 0000000000..e6839680bf --- /dev/null +++ b/js/src/jit-test/tests/basic/bug817002.js @@ -0,0 +1,13 @@ +gc() +evalcx("\ + if (!(\"gcslice\" in this))\ + gcslice = function() { };\ + array = new Uint8Array;\ + t0 = array.subarray();\ + gcslice(12); \ + array.subarray();\ + gc();\ + gc();\ + array.subarray().a = 1;\ + gc();", +newGlobal('')) diff --git a/js/src/jit-test/tests/basic/bug820124-1.js b/js/src/jit-test/tests/basic/bug820124-1.js new file mode 100644 index 0000000000..6b6ec5d7b9 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug820124-1.js @@ -0,0 +1,5 @@ +// Don't assert. +verifyprebarriers(); +r = /()()()\3/.test(); +gc(); +RegExp().test(); diff --git a/js/src/jit-test/tests/basic/bug820124-2.js b/js/src/jit-test/tests/basic/bug820124-2.js new file mode 100644 index 0000000000..a4a8dd9ecc --- /dev/null +++ b/js/src/jit-test/tests/basic/bug820124-2.js @@ -0,0 +1,3 @@ +// Don't assert. +'123456'.replace(/1(\d+)3/, ''); +RegExp.lastMatch.toString(); diff --git a/js/src/jit-test/tests/basic/bug820124-3.js b/js/src/jit-test/tests/basic/bug820124-3.js new file mode 100644 index 0000000000..1f0dfd0fa3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug820124-3.js @@ -0,0 +1,8 @@ +// Don't assert. +eval("\ + x = RegExp(\"()\", \"y\");\ + x.test();\ + x = {};\ +") +gc() +RegExp.$6 diff --git a/js/src/jit-test/tests/basic/bug820124-4.js b/js/src/jit-test/tests/basic/bug820124-4.js new file mode 100644 index 0000000000..606a1e498e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug820124-4.js @@ -0,0 +1,8 @@ +// Don't assert. +eval("\ + r = RegExp(\"(?!()(((!))))\", \"g\");\ + \"^\".replace(r, '');\ + r = (\"1+\")\ +") +gc() +RegExp.$8 diff --git a/js/src/jit-test/tests/basic/bug821850.js b/js/src/jit-test/tests/basic/bug821850.js new file mode 100644 index 0000000000..fb0819c7b6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug821850.js @@ -0,0 +1,9 @@ +load(libdir + "asserts.js"); + +m={} +Object.defineProperty(m, 'p', {value: 3}); +assertThrowsInstanceOf(function() {"use strict"; delete m.p;}, TypeError); + +x = new Proxy(m, {}) +assertEq(x.p, 3); +assertThrowsInstanceOf(function fun() {"use strict"; return delete x.p; }, TypeError); diff --git a/js/src/jit-test/tests/basic/bug824856.js b/js/src/jit-test/tests/basic/bug824856.js new file mode 100644 index 0000000000..d2c31d5798 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug824856.js @@ -0,0 +1,6 @@ +// |jit-test| error: TypeError +RegExp("(&)??\\1}").test("&D") +"xy".match(/((x)??){2}y/) +"\u66d6J".split(/((\u66d6)??){7}J/) +"2\"".match("(((2)??)+\")")() + diff --git a/js/src/jit-test/tests/basic/bug826581.js b/js/src/jit-test/tests/basic/bug826581.js new file mode 100644 index 0000000000..bfeade6106 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug826581.js @@ -0,0 +1,12 @@ +// Don't crash. + +try { + x = " () "; + for (var y = 0; y < 19; y++) { + x += x; + } +} catch (e) {} + +try { + "".replace(x, "", "gy"); +} catch (e) { } diff --git a/js/src/jit-test/tests/basic/bug827104.js b/js/src/jit-test/tests/basic/bug827104.js new file mode 100644 index 0000000000..a4ae50201f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug827104.js @@ -0,0 +1,14 @@ +function f() { + var a = []; + for (var i = 0; i < 1000; i++) { + a.x = {} + } + a[i][0] = 0; +} + +var e; +try { + f(); +} catch (error) {e = error;} +assertEq(e.constructor.name, "TypeError"); +assertEq(e.message.includes("a[i] is undefined"), true); diff --git a/js/src/jit-test/tests/basic/bug829795.js b/js/src/jit-test/tests/basic/bug829795.js new file mode 100644 index 0000000000..236b5e68d6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug829795.js @@ -0,0 +1,7 @@ +// |jit-test| error: TypeError + +try { + x = []; + Array.prototype.forEach() +} catch (e) {} +x.forEach() diff --git a/js/src/jit-test/tests/basic/bug829813.js b/js/src/jit-test/tests/basic/bug829813.js new file mode 100644 index 0000000000..c3f9b145c8 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug829813.js @@ -0,0 +1,6 @@ + +for (x in [0]) { + (function() { + return Object.propertyIsEnumerable + })().call([0], x) +} diff --git a/js/src/jit-test/tests/basic/bug829821.js b/js/src/jit-test/tests/basic/bug829821.js new file mode 100644 index 0000000000..9825e6e2b6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug829821.js @@ -0,0 +1,5 @@ +// |jit-test| error:TypeError + +x = []; +x.unshift(Uint8ClampedArray); +x.forEach(Array.prototype.push.bind(new Uint8ClampedArray)) diff --git a/js/src/jit-test/tests/basic/bug830045.js b/js/src/jit-test/tests/basic/bug830045.js new file mode 100644 index 0000000000..de1350f772 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug830045.js @@ -0,0 +1,6 @@ + +Array.prototype[1] = 'y'; +var a = [0, (8)]; +for (var i in a) { + delete a[1]; +} diff --git a/js/src/jit-test/tests/basic/bug830049.js b/js/src/jit-test/tests/basic/bug830049.js new file mode 100644 index 0000000000..641134a27f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug830049.js @@ -0,0 +1,12 @@ +// |jit-test| error: TypeError +load(libdir + "immutable-prototype.js"); + +Object.defineProperty(Object.prototype, "name", + { set(v) { throw new TypeError("hit name"); }, + enumerable: true, + configurable: true }); + +function TestCase(n) { + this.name = n; +} +new TestCase(); diff --git a/js/src/jit-test/tests/basic/bug830967.js b/js/src/jit-test/tests/basic/bug830967.js new file mode 100644 index 0000000000..3fe77edc60 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug830967.js @@ -0,0 +1,4 @@ +var x = Array.prototype.concat.call(Object.freeze([{}])); +assertEq(x.length, 1); +assertEq(0 in x, true); +assertEq(JSON.stringify(x[0]), "{}"); diff --git a/js/src/jit-test/tests/basic/bug831658.js b/js/src/jit-test/tests/basic/bug831658.js new file mode 100644 index 0000000000..ae7d6a5a13 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug831658.js @@ -0,0 +1,4 @@ +// Don't assert. +String.prototype.search = evalcx('').String.prototype.search +x = /./.test() +''.search(/()/) diff --git a/js/src/jit-test/tests/basic/bug832197-1.js b/js/src/jit-test/tests/basic/bug832197-1.js new file mode 100644 index 0000000000..4caf7cc2c8 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug832197-1.js @@ -0,0 +1,4 @@ +// Don't assert. +''.search(evalcx("/(?:}?)/", undefined)) +gc() +gc() diff --git a/js/src/jit-test/tests/basic/bug832197-2.js b/js/src/jit-test/tests/basic/bug832197-2.js new file mode 100644 index 0000000000..b4e4ca47a1 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug832197-2.js @@ -0,0 +1,13 @@ +// Don't assert. +try { + var r = evalcx("new RegExp(\"\",\"\")", w); + var s = ""; + (s.search(r))(x) +} catch (e) {} + r = /()()()()/; +try { + for (let x = 0; x < 3; ++x) { + gc() + } +} catch (e) {} +var w diff --git a/js/src/jit-test/tests/basic/bug832203.js b/js/src/jit-test/tests/basic/bug832203.js new file mode 100644 index 0000000000..d850819b0d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug832203.js @@ -0,0 +1,11 @@ +// Don't assert. +gczeal(2,1); +eval("(function() { " + "\ +var g1 = newGlobal('same-compartment');\ +function test(str, f) {\ + var x = f(eval(str));\ + assertEq(x, f(g1.eval(str)));\ +}\ +test('new RegExp(\"1\")', function(r) { return assertEq('a1'.search(r), 1); });\ +" + " })();"); +eval("(function() { " + "" + " })();"); diff --git a/js/src/jit-test/tests/basic/bug836563.js b/js/src/jit-test/tests/basic/bug836563.js new file mode 100644 index 0000000000..1b1c610956 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug836563.js @@ -0,0 +1,5 @@ + +var x = {}; +Object.defineProperty(x, 0, { configurable: true, value: null }); +x.p = 0 +Object.defineProperty(x, 0, { value: 2 }); diff --git a/js/src/jit-test/tests/basic/bug836623.js b/js/src/jit-test/tests/basic/bug836623.js new file mode 100644 index 0000000000..d0d90dc780 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug836623.js @@ -0,0 +1,13 @@ + +x = [] +Object.defineProperty(x, 4, { + configurable: true +}) +Array.prototype.pop.call(x) +for (let y = 0; y < 9; ++y) { + Object.defineProperty(x, 7, { + configurable: true, + enumerable: (y != 2), + writable: true + }) +} diff --git a/js/src/jit-test/tests/basic/bug839420.js b/js/src/jit-test/tests/basic/bug839420.js new file mode 100644 index 0000000000..66b2c87ef8 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug839420.js @@ -0,0 +1,17 @@ +function f() { + var x = undefined; + try { + [1, 2, 3].map(x); + assertEq(0, 1); + } catch(e) { + assertEq(e.toString().includes("x is not"), true); + } + + try { + [1, 2, 3].filter(x, 1, 2); + assertEq(0, 1); + } catch(e) { + assertEq(e.toString().includes("x is not"), true); + } +} +f(); diff --git a/js/src/jit-test/tests/basic/bug842425.js b/js/src/jit-test/tests/basic/bug842425.js new file mode 100644 index 0000000000..f951787768 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug842425.js @@ -0,0 +1,12 @@ +// |jit-test| error: TypeError + +function g() { + var a = []; + for (var i = 0; i < 10; i++) + a.push(i, 1.5); + for (var i = 0; i < 32 ; i++) { + print(i); + a[i].m = function() {} + } +} +g(); diff --git a/js/src/jit-test/tests/basic/bug842482.js b/js/src/jit-test/tests/basic/bug842482.js new file mode 100644 index 0000000000..79e71e0435 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug842482.js @@ -0,0 +1,2 @@ +var g = newGlobal(); +new g.DataView(new g.ArrayBuffer()); diff --git a/js/src/jit-test/tests/basic/bug842940.js b/js/src/jit-test/tests/basic/bug842940.js new file mode 100644 index 0000000000..015b18bb3e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug842940.js @@ -0,0 +1 @@ +try { for (let v of wrapWithProto(new Proxy({}, {}), [])) { } } catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug846080.js b/js/src/jit-test/tests/basic/bug846080.js new file mode 100644 index 0000000000..2cc363d685 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug846080.js @@ -0,0 +1,3 @@ +// |jit-test| error: TypeError +this.__defineSetter__("x", [].map); +evaluate('[x]="";'); diff --git a/js/src/jit-test/tests/basic/bug851635.js b/js/src/jit-test/tests/basic/bug851635.js new file mode 100644 index 0000000000..993fbb3131 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug851635.js @@ -0,0 +1,7 @@ + +gcPreserveCode() +try { + eval("({a1:1});e i") +} catch (e) {} +gc() +eval("({a1:1})") diff --git a/js/src/jit-test/tests/basic/bug851756.js b/js/src/jit-test/tests/basic/bug851756.js new file mode 100644 index 0000000000..fb98ed2b6f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug851756.js @@ -0,0 +1,3 @@ + +({ x: false })[String] = 7 +eval("[{x:3}]") diff --git a/js/src/jit-test/tests/basic/bug852016-2.js b/js/src/jit-test/tests/basic/bug852016-2.js new file mode 100644 index 0000000000..3efc589648 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug852016-2.js @@ -0,0 +1,8 @@ + +function* foo(str) { + var x = eval(str); yield x[0]; +} +for (var i = 0; i < 5; i++) + assertEq(foo("[4,5,6]").next().value, 4); +for (var i = 0; i < 5; i++) + assertEq(foo("arguments").next().value, "arguments"); diff --git a/js/src/jit-test/tests/basic/bug852016.js b/js/src/jit-test/tests/basic/bug852016.js new file mode 100644 index 0000000000..971d426a83 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug852016.js @@ -0,0 +1,9 @@ +//|jit-test| error: SyntaxError + +(function() { + x = "arguments"; + f = eval("(function(){return(c for (x in eval('print(arguments[0])')))})"); + for (e in f()) { + (function() {}); + } +})(3) diff --git a/js/src/jit-test/tests/basic/bug854124.js b/js/src/jit-test/tests/basic/bug854124.js new file mode 100644 index 0000000000..505ed2dfb6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug854124.js @@ -0,0 +1,8 @@ +// Don't assert. +"p".match(/(p)/); +assertEq(RegExp.$1, "p"); +assertEq(RegExp.$2, ""); + +"x\ny\n".replace(/(^\n*)/, ""); +assertEq(RegExp.$1, ""); +assertEq(RegExp.$2, ""); diff --git a/js/src/jit-test/tests/basic/bug854137.js b/js/src/jit-test/tests/basic/bug854137.js new file mode 100644 index 0000000000..d1f6b69764 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug854137.js @@ -0,0 +1,6 @@ +// Don't assert. +try { + eval("function x(y = {\ + x: (7) ? 0 : yield(0)\ + }"); +} catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug855088.js b/js/src/jit-test/tests/basic/bug855088.js new file mode 100644 index 0000000000..9d1145616d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug855088.js @@ -0,0 +1,5 @@ + +(function (y) { + arguments.y = 2; + with (0) var arguments=5; +})(1); diff --git a/js/src/jit-test/tests/basic/bug858097.js b/js/src/jit-test/tests/basic/bug858097.js new file mode 100644 index 0000000000..9420eada4d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug858097.js @@ -0,0 +1,7 @@ +// |jit-test| allow-oom; allow-unhandlable-oom +gczeal(0); +function MyObject( value ) {} +gcparam("maxBytes", gcparam("gcBytes") + 4*(1)); +gczeal(4); +function test() {} +var obj = new test(); diff --git a/js/src/jit-test/tests/basic/bug862228.js b/js/src/jit-test/tests/basic/bug862228.js new file mode 100644 index 0000000000..c151d91543 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug862228.js @@ -0,0 +1,3 @@ +// |jit-test| error: SyntaxError + +({"":y=""}= diff --git a/js/src/jit-test/tests/basic/bug863084.js b/js/src/jit-test/tests/basic/bug863084.js new file mode 100644 index 0000000000..1bcb9cd477 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug863084.js @@ -0,0 +1,17 @@ +// |jit-test| error: too much recursion +function f(code) { + try { + eval(code) + } catch (e) {} + eval(code) +} +f("\ + z=evalcx('');\ + gc();\ + z.toString=(function(){\ + v=evaluate(\"(Math.atan2(\\\"\\\",this))\",{\ + global:z,catchTermination:this\ + });\ + });\ + String(z)\ +") diff --git a/js/src/jit-test/tests/basic/bug867946.js b/js/src/jit-test/tests/basic/bug867946.js new file mode 100644 index 0000000000..a673966f42 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug867946.js @@ -0,0 +1,7 @@ +// |jit-test| error: InternalError: too much recursion +b = {}; +b.__proto__ = evalcx("lazy"); +function g() { + g(b.toString()) +} +g(); diff --git a/js/src/jit-test/tests/basic/bug876226.js b/js/src/jit-test/tests/basic/bug876226.js new file mode 100644 index 0000000000..4fb779b4f9 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug876226.js @@ -0,0 +1,6 @@ +// |jit-test| error: SyntaxError +try { + evaluate("throw 3"); +} catch(e) {} + +evaluate("()", {}); diff --git a/js/src/jit-test/tests/basic/bug877378.js b/js/src/jit-test/tests/basic/bug877378.js new file mode 100644 index 0000000000..06d63c10ee --- /dev/null +++ b/js/src/jit-test/tests/basic/bug877378.js @@ -0,0 +1,18 @@ +evalcx("\ + let z = 'x';\ + for (var v of z) {\ + y = evaluate(\"Object.defineProperty(this,\\\"y\\\",\ + {get: function() {}}\ + );\",\ + {catchTermination: true}\ + );\ + }", + newGlobal('') +) + +evalcx("\ + for (x = 0; x < 1; ++x) { \ + v = evaluate(\"gc\",{ \ + })\ + }\ +", newGlobal('')); diff --git a/js/src/jit-test/tests/basic/bug880377.js b/js/src/jit-test/tests/basic/bug880377.js new file mode 100644 index 0000000000..4332bd2a94 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug880377.js @@ -0,0 +1,10 @@ +var actual = ''; +var obj0 = {} +obj2 = {}; +obj2['b'+1] = 1; +if (actual[0] != 0[0]) + throw new i(); +for (var k in obj2) { + for (var apply in obj0) + ++count; +}
\ No newline at end of file diff --git a/js/src/jit-test/tests/basic/bug882416.js b/js/src/jit-test/tests/basic/bug882416.js new file mode 100644 index 0000000000..48dde94163 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug882416.js @@ -0,0 +1,5 @@ +// |jit-test| error: SyntaxError +Error.prototype.toString = Function; +evaluate("n f", { + noScriptRval: true, +}); diff --git a/js/src/jit-test/tests/basic/bug883523.js b/js/src/jit-test/tests/basic/bug883523.js new file mode 100644 index 0000000000..c448b70c91 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug883523.js @@ -0,0 +1 @@ +if(1) /a/.test("a"); // should not be a SyntaxError. diff --git a/js/src/jit-test/tests/basic/bug883623.js b/js/src/jit-test/tests/basic/bug883623.js new file mode 100644 index 0000000000..d5599fb1f9 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug883623.js @@ -0,0 +1,7 @@ + +(function() { + eval("\ + arguments.valueOf();\ + with (function(){}){};\ + "); +})()
\ No newline at end of file diff --git a/js/src/jit-test/tests/basic/bug884920.js b/js/src/jit-test/tests/basic/bug884920.js new file mode 100644 index 0000000000..7f5737d30f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug884920.js @@ -0,0 +1,7 @@ +// |jit-test| error:SyntaxError + +function testcase({}, a = b, ... x) { + "use strict"; + function f() { }; + with ( f(3) ); +} diff --git a/js/src/jit-test/tests/basic/bug886803.js b/js/src/jit-test/tests/basic/bug886803.js new file mode 100644 index 0000000000..c89e9bce9c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug886803.js @@ -0,0 +1,3 @@ + +f = Function("with({}) { var i; }"); +f(); diff --git a/js/src/jit-test/tests/basic/bug908915.js b/js/src/jit-test/tests/basic/bug908915.js new file mode 100644 index 0000000000..a35a08bed1 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug908915.js @@ -0,0 +1,47 @@ +// |jit-test| error: 42; skip-if: getBuildConfiguration("wasi") +load(libdir + "immutable-prototype.js"); + +// Suppress the large quantity of output on stdout (eg from calling +// dumpHeap()). +os.file.redirect(null); + +var ignorelist = { + 'quit': true, + 'crash': true, + 'readline': true, + 'terminate': true, + 'nukeAllCCWs': true, + 'cacheIRHealthReport': true, + 'getInnerMostEnvironmentObject': true, + 'getEnclosingEnvironmentObject': true, + 'getEnvironmentObjectType' : true, +}; + +function f(y) {} +for (let e of Object.values(newGlobal())) { + if (e.name in ignorelist) + continue; + print(e.name); + try { + e(); + } catch (r) {} +} +(function() { + arguments; + if (globalPrototypeChainIsMutable()) + Object.prototype.__proto__ = newGlobal() + function f(y) { + y() + } + var arr = []; + arr.__proto__ = newGlobal(); + for (b of Object.values(arr)) { + if (b.name in ignorelist) + continue; + try { + f(b) + } catch (e) {} + } +})(); + +throw 42; diff --git a/js/src/jit-test/tests/basic/bug911368.js b/js/src/jit-test/tests/basic/bug911368.js new file mode 100644 index 0000000000..3006155f25 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug911368.js @@ -0,0 +1,10 @@ +// |jit-test| +(function (stdlib, heap) { + "use asm"; + function f(i0) { + i0 = i0 | 0; + switch (0xc << (0xa % 1)) { + case -2: + }; + } +})() diff --git a/js/src/jit-test/tests/basic/bug913445.js b/js/src/jit-test/tests/basic/bug913445.js new file mode 100644 index 0000000000..c6d1d74da3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug913445.js @@ -0,0 +1,19 @@ +// |jit-test| skip-if: !this.uneval + +// uneval works on objects with no callable .toSource method. + +var obj = Object.create(null); +assertEq(uneval(obj), "({})"); +assertEq(Function.prototype.toSource.call(obj), "({})"); +obj.x = 1; +obj.y = 2; +assertEq(uneval(obj), "({x:1, y:2})"); + +var d = new Date(); +delete Date.prototype.toSource; +assertEq(uneval(d), "({})"); + +delete Object.prototype.toSource; +assertEq(uneval({p: 2+2}), "({p:4})"); + +assertEq(uneval({toSource: [0]}), "({toSource:[0]})"); diff --git a/js/src/jit-test/tests/basic/bug920484.js b/js/src/jit-test/tests/basic/bug920484.js new file mode 100644 index 0000000000..34c1ff6a76 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug920484.js @@ -0,0 +1,27 @@ +load(libdir + "asserts.js"); + +// Add an invalid "localeMatcher" option to Object.prototype, the exact value does not matter, +// any value except "best fit" or "lookup" is okay. +Object.prototype.localeMatcher = "invalid matcher option"; + +// The Intl API may not be available in the testing environment. +if (this.hasOwnProperty("Intl")) { + // Intl constructors still work perfectly fine. The default options object doesn't inherit + // from Object.prototype and the invalid "localeMatcher" value from Object.prototype isn't + // consulted. + new Intl.Collator().compare("a", "b"); + new Intl.NumberFormat().format(10); + new Intl.DateTimeFormat().format(new Date); + + // If an explicit "localeMatcher" option is given, the default from Object.prototype is ignored. + new Intl.Collator(void 0, {localeMatcher: "lookup"}).compare("a", "b"); + new Intl.NumberFormat(void 0, {localeMatcher: "lookup"}).format(10); + new Intl.DateTimeFormat(void 0, {localeMatcher: "lookup"}).format(new Date); + + delete Object.prototype.localeMatcher; + + // After removing the default option from Object.prototype, everything still works as expected. + new Intl.Collator().compare("a", "b"); + new Intl.NumberFormat().format(10); + new Intl.DateTimeFormat().format(new Date); +} diff --git a/js/src/jit-test/tests/basic/bug934789-1.js b/js/src/jit-test/tests/basic/bug934789-1.js new file mode 100644 index 0000000000..3b290e135b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug934789-1.js @@ -0,0 +1,13 @@ +if (typeof dis === "function") { + (function() { + function foo() {} + + dis(function bar(e) { + try { + (function() { e; }); + } catch (e) { + foo(); + } + }); + }()); +} diff --git a/js/src/jit-test/tests/basic/bug934789-2.js b/js/src/jit-test/tests/basic/bug934789-2.js new file mode 100644 index 0000000000..5272d63e01 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug934789-2.js @@ -0,0 +1,15 @@ +load(libdir + "asserts.js"); +assertThrowsInstanceOf( + function() { + function foo() {} + foo = null; + (function bar(e) { + try { + (function() { e; }); + throw 1; + } catch (e) { + foo(); + } + })(); + }, + TypeError); diff --git a/js/src/jit-test/tests/basic/bug934997.js b/js/src/jit-test/tests/basic/bug934997.js new file mode 100644 index 0000000000..91d81f0294 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug934997.js @@ -0,0 +1,30 @@ +function test1() { + var BUGNUMBER = ''; + var summary = ''; + var actual = ''; + test(BUGNUMBER); + function test() { + try { + (function () { eval("'foo'.b()", arguments) })(); + } catch(ex) { + actual = ex + ''; + } + } + assertEq(actual, 'TypeError: "foo".b is not a function'); +} +test1(); + +function test2() { + var BUGNUMBER = ''; + var summary = ''; + function g() { + 'use strict'; + try { + eval('function foo() { var a, arguments, b;}'); + } catch (x) { + return (x instanceof SyntaxError); + } + }; + assertEq(g(), true); +} +test2(); diff --git a/js/src/jit-test/tests/basic/bug935294.js b/js/src/jit-test/tests/basic/bug935294.js new file mode 100644 index 0000000000..c6dfc36e7e --- /dev/null +++ b/js/src/jit-test/tests/basic/bug935294.js @@ -0,0 +1,5 @@ +// |jit-test| error: ReferenceError +for (var c in foo) + try { + throw new Error(); + } catch (e) {} diff --git a/js/src/jit-test/tests/basic/bug937089.js b/js/src/jit-test/tests/basic/bug937089.js new file mode 100644 index 0000000000..09eedbe030 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug937089.js @@ -0,0 +1,10 @@ + +function test1() { + eval("with (arguments) var arguments = 0;"); +} +test1(); + +function test2() { + eval("eval('with (arguments) var arguments = 0;')"); +} +test2(); diff --git a/js/src/jit-test/tests/basic/bug942390.js b/js/src/jit-test/tests/basic/bug942390.js new file mode 100644 index 0000000000..9b661a4f44 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug942390.js @@ -0,0 +1,21 @@ +load(libdir + "immutable-prototype.js"); + +var count = 0; +if (globalPrototypeChainIsMutable()) { + Object.defineProperty(__proto__, "__iterator__", { + get: (function() { + count++; + }) + }); +} else { + count = 7; +} + +if (globalPrototypeChainIsMutable()) + __proto__ = (function(){}); + +for (var m = 0; m < 7; ++m) { + for (var a in 6) {} +} + +assertEq(count, 7); diff --git a/js/src/jit-test/tests/basic/bug943126.js b/js/src/jit-test/tests/basic/bug943126.js new file mode 100644 index 0000000000..319274fb2f --- /dev/null +++ b/js/src/jit-test/tests/basic/bug943126.js @@ -0,0 +1,16 @@ +// Test fast-path for String.split(""). + +load(libdir + 'eqArrayHelper.js'); + +assertEqArray("".split(""), []); +assertEqArray("a".split(""), ["a"]); +assertEqArray("abc".split(""), ["a", "b", "c"]); + +assertEqArray("abcd".split("", 2), ["a", "b"]); +assertEqArray("abcd".split("", 0), []); +assertEqArray("abcd".split("", -1), ["a", "b", "c", "d"]); + +// Note: V8 disagrees about this one, but we are correct by ecma-262 15.5.4.14 part 9. +assertEqArray("abcd".split(undefined, 0), []); + +assertEqArray("abcd".split(undefined, 1), ["abcd"]); diff --git a/js/src/jit-test/tests/basic/bug950725.js b/js/src/jit-test/tests/basic/bug950725.js new file mode 100644 index 0000000000..c036ee0410 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug950725.js @@ -0,0 +1,12 @@ +function test() { + + T[g].act +} +gc(); +var c = 0; +for (var i = 0; i < 20; test['$+']) { + if (c++ > 110) + break; + try { + __count__(f(2), 1); + } catch (e) {} +} diff --git a/js/src/jit-test/tests/basic/bug951213.js b/js/src/jit-test/tests/basic/bug951213.js new file mode 100644 index 0000000000..37454491dd --- /dev/null +++ b/js/src/jit-test/tests/basic/bug951213.js @@ -0,0 +1,8 @@ + +enableShellAllocationMetadataBuilder(); +function foo(x, y) { + this.g = x + y; +} +var a = 0; +var b = { valueOf: function() { return Object.defineProperty(Object.prototype, 'g', {}); } }; +var c = new foo(a, b); diff --git a/js/src/jit-test/tests/basic/bug951346.js b/js/src/jit-test/tests/basic/bug951346.js new file mode 100644 index 0000000000..c1a006264d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug951346.js @@ -0,0 +1,3 @@ + +enableShellAllocationMetadataBuilder(); +eval(`(${JSON.stringify({'-1':true})})`); diff --git a/js/src/jit-test/tests/basic/bug951632.js b/js/src/jit-test/tests/basic/bug951632.js new file mode 100644 index 0000000000..9c5c17e8ee --- /dev/null +++ b/js/src/jit-test/tests/basic/bug951632.js @@ -0,0 +1,9 @@ +enableShellAllocationMetadataBuilder(); +var g = newGlobal({newCompartment: true}) +g.eval("function f(a) { return h(); }"); +g.h = function () { + return [1, 2, 3]; +}; +var o = getAllocationMetadata(g.f(5)); +assertEq(o.stack.length, 1); +assertEq(o.stack[0], g.h); diff --git a/js/src/jit-test/tests/basic/bug970643.js b/js/src/jit-test/tests/basic/bug970643.js new file mode 100644 index 0000000000..758754fa0a --- /dev/null +++ b/js/src/jit-test/tests/basic/bug970643.js @@ -0,0 +1,18 @@ +// |jit-test| exitstatus: 6; skip-if: getBuildConfiguration("wasi") + +setJitCompilerOption("baseline.warmup.trigger", 1); +setJitCompilerOption("ion.warmup.trigger", 2); + +// The timepout function is made to trigger the interruption callback. The +// interruption callback will protect the code while a GC might be +// marking/updating pointers in it. +var x = 0; +function interrupt_gc() { + if (x++ >= 20) + return; + timeout(0.1, interrupt_gc); + while(x < 20) + gc(); +} + +interrupt_gc(); diff --git a/js/src/jit-test/tests/basic/bug972961.js b/js/src/jit-test/tests/basic/bug972961.js new file mode 100644 index 0000000000..10df12cad8 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug972961.js @@ -0,0 +1,40 @@ +// Bug 972961 - Test compiler with very long chains of property accesses + +// Return true if we can compile a chain of n property accesses, +// false if we cannot. Throw if compilation fails in an unexpected way. +function test(n) { + print("testing " + n); + try { + eval('if (false) {' + Array(n).join(("a.")) + 'a}'); + } catch (exc) { + // Expected outcome if the expression is too deeply nested is an InternalError. + if (!(exc instanceof InternalError)) + throw exc; + print(exc.message); + return false; + } + print("no exception"); + return true; +} + +// Find out how long a chain is enough to break the compiler. +var n = 4, LIMIT = 0x000fffff; +var lo = 1, hi = 1; +while (n <= LIMIT && test(n)) { + lo = n; + n *= 4; +} + +// Using binary search, find a pass/fail boundary (in order to +// test the edge case). +if (n <= LIMIT) { + hi = n; + while (lo !== hi) { + var mid = Math.floor((lo + hi) / 2); + if (test(mid)) + lo = mid + 1; + else + hi = mid; + } + print((lo - 1) + " attributes should be enough for anyone"); +} diff --git a/js/src/jit-test/tests/basic/bug976446.js b/js/src/jit-test/tests/basic/bug976446.js new file mode 100644 index 0000000000..e99e221311 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug976446.js @@ -0,0 +1,16 @@ + +try { + +function f() {} +f("".match(/(?:(?=g)).{2147483648,}/ + (/[]/)), null); + +} catch (e) {} // Yarr throws on the above regexp + +var re = new RegExp("a[\x01-\\xDE]+M", "gi"); +re.exec(""); + +var re = new RegExp("a[\x01-\\u00b8]+?c", "gi"); +re.exec(""); + +var re = new RegExp("a[\x01-\\u00f8]?c", "gi"); +re.exec(""); diff --git a/js/src/jit-test/tests/basic/bug980013.js b/js/src/jit-test/tests/basic/bug980013.js new file mode 100644 index 0000000000..d84295285b --- /dev/null +++ b/js/src/jit-test/tests/basic/bug980013.js @@ -0,0 +1,9 @@ + +x = new Uint8ClampedArray; +x.__proto__ = {}; +Object.defineProperty(this, "y", { + get: function() { + return x.length; + } +}); +assertEq(y, undefined); diff --git a/js/src/jit-test/tests/basic/bug980450.js b/js/src/jit-test/tests/basic/bug980450.js new file mode 100644 index 0000000000..afe1c5fac3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug980450.js @@ -0,0 +1,4 @@ + +var f32 = new Float32Array(1); +for(var n = 100; n; --n) + f32.hasOwnProperty(4) diff --git a/js/src/jit-test/tests/basic/bug984766.js b/js/src/jit-test/tests/basic/bug984766.js new file mode 100644 index 0000000000..bd44fc31bc --- /dev/null +++ b/js/src/jit-test/tests/basic/bug984766.js @@ -0,0 +1,17 @@ + +for (var i = 0; i < 10; i++) { + x = new ArrayBuffer(4) + x.f = (function() {}) + new Uint16Array(x).set(JSON.parse) + gcslice() +} + +if (!this.SharedArrayBuffer) + quit(0); + +for (var i = 0; i < 10; i++) { + x = new SharedArrayBuffer(4) + x.f = (function() {}) + new Uint16Array(x).set(JSON.parse) + gcslice() +} diff --git a/js/src/jit-test/tests/basic/builtinLocals.js b/js/src/jit-test/tests/basic/builtinLocals.js new file mode 100644 index 0000000000..032b801d00 --- /dev/null +++ b/js/src/jit-test/tests/basic/builtinLocals.js @@ -0,0 +1,35 @@ + +/* Resolve 'arguments' and the name of the function itself in the presence of such local variables. */ + +function f() { + return typeof arguments; + function arguments() { + return 7; + } +} +assertEq(f(), "function"); + +function g() { + var arguments = 0; + return typeof arguments; +} +assertEq(g(), "number"); + +function h() { + return typeof h; + function h() { + return 7; + } +} +assertEq(h(), "function"); + +function i() { + return typeof i; + var i; +} +assertEq(i(), "undefined"); + +function j() { + return typeof j; +} +assertEq(j(), "function"); diff --git a/js/src/jit-test/tests/basic/call-construct-hook.js b/js/src/jit-test/tests/basic/call-construct-hook.js new file mode 100644 index 0000000000..ed6cb23e01 --- /dev/null +++ b/js/src/jit-test/tests/basic/call-construct-hook.js @@ -0,0 +1,100 @@ +// Tests for invoking JSClass call/construct hooks. + +function testBasic() { + let obj = {fun: newObjectWithCallHook()}; + for (var i = 0; i < 1000; i++) { + let res = obj.fun(1, 2, 3); + assertEq(res.this, obj); + assertEq(res.callee, obj.fun); + assertEq(JSON.stringify(res.arguments), "[1,2,3]"); + assertEq(res.newTarget, undefined); + + res = new obj.fun(1, 2, 3); + assertEq(res.this, "<is_constructing>"); + assertEq(res.callee, obj.fun); + assertEq(JSON.stringify(res.arguments), "[1,2,3]"); + assertEq(res.newTarget, obj.fun); + } +} +testBasic(); + +function testSpread() { + let obj = {fun: newObjectWithCallHook()}; + for (var i = 0; i < 1000; i++) { + let res = obj.fun(...[1, 2, 3]); + assertEq(res.this, obj); + assertEq(res.callee, obj.fun); + assertEq(JSON.stringify(res.arguments), "[1,2,3]"); + assertEq(res.newTarget, undefined); + + res = new obj.fun(...[1, 2, 3]); + assertEq(res.this, "<is_constructing>"); + assertEq(res.callee, obj.fun); + assertEq(JSON.stringify(res.arguments), "[1,2,3]"); + assertEq(res.newTarget, obj.fun); + } +} +testSpread(); + +function testNewTarget() { + let obj = newObjectWithCallHook(); + let newTargetVal = function() {}; + for (var i = 0; i < 1000; i++) { + let res = Reflect.construct(obj, [], newTargetVal); + assertEq(res.this, "<is_constructing>"); + assertEq(res.callee, obj); + assertEq(res.arguments.length, 0); + assertEq(res.newTarget, newTargetVal); + } +} +testNewTarget(); + +function testRealmSwitch() { + // We currently switch to the callable's realm for class hook calls (similar to + // JS function calls). This might change at some point, but for now assert the + // returned object's realm matches that of the callee. + + let g = newGlobal({sameCompartmentAs: this}); + let obj = g.newObjectWithCallHook(); + assertEq(objectGlobal(obj), g); + + for (var i = 0; i < 1000; i++) { + let res = obj(1, 2); + assertEq(objectGlobal(res), g); + assertEq(res.this, undefined); + assertEq(res.callee, obj); + assertEq(JSON.stringify(res.arguments), "[1,2]"); + + res = new obj(1, 2); + assertEq(objectGlobal(res), g); + assertEq(res.this, "<is_constructing>"); + assertEq(res.callee, obj); + assertEq(JSON.stringify(res.arguments), "[1,2]"); + assertEq(res.newTarget, obj); + } +} +testRealmSwitch(); + +function testCrossCompartmentWrapper() { + // Call/construct hooks can be called through cross-compartment wrappers. + + let g = newGlobal({newCompartment: true}); + let obj = g.newObjectWithCallHook(); + assertEq(isProxy(obj), true); // It's a CCW. + + for (var i = 0; i < 1000; i++) { + let res = obj(1, 2); + assertEq(isProxy(res), true); + assertEq(res.this, undefined); + assertEq(res.callee, obj); + assertEq(JSON.stringify(res.arguments), "[1,2]"); + + res = new obj(1, 2); + assertEq(isProxy(res), true); + assertEq(res.this, "<is_constructing>"); + assertEq(res.callee, obj); + assertEq(JSON.stringify(res.arguments), "[1,2]"); + assertEq(res.newTarget, obj); + } +} +testCrossCompartmentWrapper(); diff --git a/js/src/jit-test/tests/basic/call.js b/js/src/jit-test/tests/basic/call.js new file mode 100644 index 0000000000..8e6b647b60 --- /dev/null +++ b/js/src/jit-test/tests/basic/call.js @@ -0,0 +1,28 @@ +function glob_f1() { + return 1; +} +function glob_f2() { + return glob_f1(); +} +function call() +{ + var q1 = 0, q2 = 0, q3 = 0, q4 = 0, q5 = 0; + var o = {}; + function f1() { + return 1; + } + function f2(f) { + return f(); + } + o.f = f1; + for (var i = 0; i < 100; ++i) { + q1 += f1(); + q2 += f2(f1); + q3 += glob_f1(); + q4 += o.f(); + q5 += glob_f2(); + } + var ret = String([q1, q2, q3, q4, q5]); + return ret; +} +assertEq(call(), "100,100,100,100,100"); diff --git a/js/src/jit-test/tests/basic/call2.js b/js/src/jit-test/tests/basic/call2.js new file mode 100644 index 0000000000..9e68bb20ae --- /dev/null +++ b/js/src/jit-test/tests/basic/call2.js @@ -0,0 +1,13 @@ +function g(x) { + if ((x & 1) == 1) return 1; + return 2; +} + +function f(n) { + var q = 0; + for (var i = 0; i < n; i++) + q += g(i); + return q; +} + +assertEq(f(1000), 1500); diff --git a/js/src/jit-test/tests/basic/change-code-write-protect.js b/js/src/jit-test/tests/basic/change-code-write-protect.js new file mode 100644 index 0000000000..d44a30a3b1 --- /dev/null +++ b/js/src/jit-test/tests/basic/change-code-write-protect.js @@ -0,0 +1,3 @@ +// |jit-test| error:Can't change code write protection at runtime +var value = getJitCompilerOptions()["write-protect-code"]; +setJitCompilerOption("write-protect-code", Number(!value)); diff --git a/js/src/jit-test/tests/basic/compression-random-data.js b/js/src/jit-test/tests/basic/compression-random-data.js new file mode 100644 index 0000000000..fa416142d3 --- /dev/null +++ b/js/src/jit-test/tests/basic/compression-random-data.js @@ -0,0 +1,26 @@ +// Deterministic Math.random, from Octane. +var seed = 49734321; +function rand() { + // Robert Jenkins' 32 bit integer hash function. + seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff; + seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; + seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; + seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; + seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; + seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; + return (seed & 0xfffffff) / 0x10000000; +} +var randomS = ""; +function test(len) { + const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + var s = "var data = '"; + while (randomS.length < len) { + randomS += chars.charAt((rand() * chars.length)|0); + } + s += randomS; + s += "'; function f() {}; assertEq(f.toString(), 'function f() {}');"; + eval(s); +} +for (var i=32740; i<32780; i += 5) { + test(i); +} diff --git a/js/src/jit-test/tests/basic/constAssignError.js b/js/src/jit-test/tests/basic/constAssignError.js new file mode 100644 index 0000000000..3e93fb464c --- /dev/null +++ b/js/src/jit-test/tests/basic/constAssignError.js @@ -0,0 +1,23 @@ +// Can't assign to const is a runtime TypeError + +load(libdir + 'asserts.js'); + +function assertTypeError(str) { + assertThrowsInstanceOf(function () { eval(str); }, TypeError); +} + +assertTypeError("(function() { const x = 3; (() => x++)(); return x })()"); +assertTypeError("(function() { const x = 3; (() => x++)(); return x++ })()"); +assertTypeError("(function() { const x = 2; (() => x++)(); return ++x })()"); +assertTypeError("(function() { const x = 2; (() => x++)(); return x += 1 })()"); + +assertTypeError("(function() { const x = 3; x = 1; return (function() { return x})() })()"); +assertTypeError("(function() { const x = 3; x = 1; return (function() { return x})() })()"); +assertTypeError("(function() { const x = 3; x++; return (function() { return x})() })()"); +assertTypeError("(function() { const x = 3; ++x; return (function() { return x})() })()"); +assertTypeError("(function() { const x = 3; x--; return (function() { return x})() })()"); +assertTypeError("(function() { const x = 3; --x; return (function() { return x})() })()"); +assertTypeError("(function() { const x = 3; x += 1; return (function() { return x})() })()"); +assertTypeError("(function() { const x = 3; x -= 1; return (function() { return x})() })()"); + +assertTypeError("(function() { const x = 3; [x] = [1]; })()"); diff --git a/js/src/jit-test/tests/basic/constGlobalAssignError.js b/js/src/jit-test/tests/basic/constGlobalAssignError.js new file mode 100644 index 0000000000..87c7b78f04 --- /dev/null +++ b/js/src/jit-test/tests/basic/constGlobalAssignError.js @@ -0,0 +1,3 @@ +// |jit-test| error: TypeError + +const x = 1; x = 2; diff --git a/js/src/jit-test/tests/basic/constant-folding-1.js b/js/src/jit-test/tests/basic/constant-folding-1.js new file mode 100644 index 0000000000..851a0a804a --- /dev/null +++ b/js/src/jit-test/tests/basic/constant-folding-1.js @@ -0,0 +1,45 @@ +function bytecode(f) { + if (typeof disassemble !== "function") + return "unavailable"; + var d = disassemble(f); + // Remove line numbers. + d = d.replace(/(\n\d{5}:).*\d+/g, "$1"); + return d.slice(d.indexOf("main:"), d.indexOf("\n\n")); +} +assertEq(bytecode(() => "hello" + "world"), + bytecode(() => "helloworld")); +assertEq(bytecode(() => 2 + "2" + "2"), + bytecode(() => "222")); +assertEq(bytecode(() => "x" + "3"), + bytecode(() => "x3")); + +var s = "hoge"; +assertEq(bytecode(() => "fo" + "o" + s + "ba" + "r"), + bytecode(() => "foo" + s + "bar")); +assertEq(bytecode(() => "fo" + "o" + 1 + s + 1 + "ba" + "r"), + bytecode(() => "foo1" + s + "1bar")); +assertEq(bytecode(() => 1 + (2 * 2) + "x"), + bytecode(() => 5 + "x")); +assertEq(s + 1 + 2, "hoge12"); +assertEq((() => s + 1 + 2)(), "hoge12"); + +// SpiderMonkey knows that 1 + 1 == "11". +assertEq(bytecode(() => "x" + s + 1 + 1), + bytecode(() => "x" + s + "11")); + +var n = 5; +assertEq(1 + n + 1 + "ba" + "r", "7bar"); +assertEq(1 + 2 + {valueOf: () => 3, toString: () => 'x'} + 4 + 5,15); +assertEq(1+2+n,8); +assertEq(bytecode(() => 1 + 2 + n + 1 + 2), + bytecode(() => 3 + n + 1 + 2)); +assertEq(1 + 2 + n + 1 + 2, 11); +assertEq(bytecode(() => 1 + 2 + s + 1 + 2), + bytecode(() => 3 + s + 1 + 2)); +assertEq(1 + 2 + s + 1 + 2, "3hoge12"); + +assertEq(bytecode(() => ["a" + "b" + n]), + bytecode(() => ["ab" + n])); +var a = ["a" + "b" + n]; +assertEq(a[0], "ab5"); + diff --git a/js/src/jit-test/tests/basic/construct-primitive-Function.prototype.prototype.js b/js/src/jit-test/tests/basic/construct-primitive-Function.prototype.prototype.js new file mode 100644 index 0000000000..0b83325cfe --- /dev/null +++ b/js/src/jit-test/tests/basic/construct-primitive-Function.prototype.prototype.js @@ -0,0 +1,5 @@ +Object.defineProperty(Function.prototype, "prototype", { + get: function() { throw 17; }, + set: function() { throw 42; } +}); +this.hasOwnProperty("Intl"); diff --git a/js/src/jit-test/tests/basic/consume-interpreter-stack-bug1473289.js b/js/src/jit-test/tests/basic/consume-interpreter-stack-bug1473289.js new file mode 100644 index 0000000000..13c3c88dd1 --- /dev/null +++ b/js/src/jit-test/tests/basic/consume-interpreter-stack-bug1473289.js @@ -0,0 +1,495 @@ +// |jit-test| slow; allow-overrecursed + +(function f(x) { + f(x - 1); + Array.prototype.unshift.call(a1, s2, a1, t2, a0, p2, t2); + var r2; + var r3; + var r4; + var r5; + var r6; + var r7; + var r8; + var r9; + var r10; + var r11; + var r12; + var r13; + var r14; + var r15; + var r16; + var r17; + var r18; + var r19; + var r20; + var r21; + var r22; + var r23; + var r24; + var r25; + var r26; + var r27; + var r28; + var r29; + var r30; + var r31; + var r32; + var r33; + var r34; + var r35; + var r36; + var r37; + var r38; + var r39; + var r40; + var r41; + var r42; + var r43; + var r44; + var r45; + var r46; + var r47; + var r48; + var r49; + var r50; + var r51; + var r52; + var r53; + var r54; + var r55; + var r56; + var r57; + var r58; + var r59; + var r60; + var r61; + var r62; + var r63; + var r64; + var r65; + var r66; + var r67; + var r68; + var r69; + var r70; + var r71; + var r72; + var r73; + var r74; + var r75; + var r76; + var r77; + var r78; + var r79; + var r80; + var r81; + var r82; + var r83; + var r84; + var r85; + var r86; + var r87; + var r88; + var r89; + var r90; + var r91; + var r92; + var r93; + var r149; + var r150; + var r151; + var r152; + var r153; + var r154; + var r155; + var r156; + var r157; + var r158; + var r159; + var r160; + var r161; + var r162; + var r163; + var r164; + var r165; + var r166; + var r167; + var r168; + var r169; + var r170; + var r171; + var r172; + var r173; + var r174; + var r175; + var r176; + var r177; + var r178; + var r179; + var r180; + var r181; + var r182; + var r183; + var r184; + var r185; + var r186; + var r187; + var r188; + var r189; + var r190; + var r191; + var r192; + var r193; + var r194; + var r195; + var r196; + var r197; + var r198; + var r199; + var r200; + var r201; + var r202; + var r203; + var r204; + var r205; + var r206; + var r207; + var r208; + var r209; + var r210; + var r211; + var r212; + var r213; + var r214; + var r215; + var r216; + var r217; + var r218; + var r219; + var r220; + var r221; + var r222; + var r223; + var r224; + var r225; + var r226; + var r227; + var r228; + var r229; + var r230; + var r231; + var r232; + var r233; + var r234; + var r235; + var r236; + var r237; + var r238; + var r239; + var r240; + var r241; + var r242; + var r243; + var r244; + var r245; + var r246; + var r247; + var r248; + var r249; + var r250; + var r251; + var r252; + var r253; + var r254; + var r255; + var r256; + var r257; + var r258; + var r259; + var r260; + var r261; + var r262; + var r263; + var r264; + var r265; + var r266; + var r267; + var r268; + var r269; + var r270; + var r271; + var r272; + var r273; + var r274; + var r275; + var r276; + var r277; + var r278; + var r279; + var r280; + var r281; + var r282; + var r283; + var r284; + var r285; + var r286; + var r287; + var r288; + var r289; + var r290; + var r291; + var r292; + var r293; + var r294; + var r295; + var r296; + var r297; + var r298; + var r299; + var r300; + var r301; + var r302; + var r303; + var r304; + var r305; + var r306; + var r307; + var r308; + var r309; + var r310; + var r311; + var r312; + var r313; + var r314; + var r315; + var r316; + var r317; + var r318; + var r319; + var r320; + var r321; + var r322; + var r323; + var r324; + var r325; + var r326; + var r327; + var r328; + var r329; + var r330; + var r331; + var r332; + var r333; + var r334; + var r335; + var r336; + var r337; + var r338; + var r339; + var r340; + var r341; + var r342; + var r343; + var r344; + var r345; + var r346; + var r347; + var r348; + var r349; + var r350; + var r351; + var r352; + var r353; + var r354; + var r355; + var r356; + var r357; + var r358; + var r359; + var r360; + var r361; + var r362; + var r363; + var r364; + var r365; + var r366; + var r367; + var r368; + var r369; + var r370; + var r371; + var r372; + var r373; + var r374; + var r375; + var r376; + var r377; + var r378; + var r379; + var r380; + var r381; + var r382; + var r383; + var r384; + var r385; + var r386; + var r387; + var r388; + var r389; + var r390; + var r391; + var r392; + var r393; + var r394; + var r395; + var r396; + var r397; + var r398; + var r399; + var r400; + var r401; + var r402; + var r403; + var r404; + var r405; + var r406; + var r407; + var r408; + var r409; + var r410; + var r411; + var r412; + var r413; + var r414; + var r415; + var r416; + var r417; + var r418; + var r419; + var r420; + var r421; + var r422; + var r423; + var r424; + var r425; + var r426; + var r427; + var r428; + var r429; + var r430; + var r431; + var r432; + var r433; + var r434; + var r435; + var r436; + var r437; + var r438; + var r439; + var r440; + var r441; + var r442; + var r443; + var r444; + var r445; + var r446; + var r447; + var r448; + var r449; + var r450; + var r451; + var r452; + var r453; + var r454; + var r455; + var r456; + var r457; + var r458; + var r459; + var r460; + var r461; + var r462; + var r463; + var r464; + var r465; + var r466; + var r467; + var r468; + var r469; + var r470; + var r471; + var r472; + var r473; + var r474; + var r475; + var r476; + var r477; + var r478; + var r479; + var r480; + var r481; + var r482; + var r483; + var r484; + var r485; + var r486; + var r487; + var r488; + var r489; + var r490; + var r491; + var r492; + var r493; + var r494; + var r495; + var r496; + var r497; + var r498; + var r499; + var r500; + var r501; + var r502; + var r503; + var r504; + var r505; + var r506; + var r507; + var r508; + var r509; + var r510; + var r511; + var r512; + var r513; + var r514; + var r515; + var r516; + var r517; + var r518; + var r519; + var r520; + var r521; + var r522; + var r523; + var r524; + var r525; + var r526; + var r527; + var r528; + var r529; + var r530; + var r531; + var r532; + var r533; + var r534; + var r535; + var r536; + var r537; + var r538; + var r539; + var r540; + var r541; + var r542; + var r543; + var r544; + var r545; +})(32769); diff --git a/js/src/jit-test/tests/basic/cross-global-for-in.js b/js/src/jit-test/tests/basic/cross-global-for-in.js new file mode 100644 index 0000000000..3fd7720525 --- /dev/null +++ b/js/src/jit-test/tests/basic/cross-global-for-in.js @@ -0,0 +1,11 @@ +var global = newGlobal(); + +var arrayIter = (new global.Array())[global.Symbol.iterator](); +var ArrayIteratorPrototype = Object.getPrototypeOf(arrayIter); +var arrayIterProtoBase = Object.getPrototypeOf(ArrayIteratorPrototype); +var IteratorPrototype = arrayIterProtoBase; +delete IteratorPrototype.next; + +var obj = global.eval('({a: 1})') +for (var x in obj) {} +assertEq(x, "a"); diff --git a/js/src/jit-test/tests/basic/cross-realm-iterator-suppression.js b/js/src/jit-test/tests/basic/cross-realm-iterator-suppression.js new file mode 100644 index 0000000000..cded3d4c88 --- /dev/null +++ b/js/src/jit-test/tests/basic/cross-realm-iterator-suppression.js @@ -0,0 +1,32 @@ +function foo(o) { + // Ensure a NativeIterator exists for o. + for (var s in o) {} + + // Loop over the keys, deleting y. + // If y is correctly suppressed, then result should + // be the name of the first property. + var result = ""; + for (var s in o) { + delete o.y; + result += s; + } + assertEq(o[result], 42); +} + +with ({}) {} +for (var i = 0; i < 100; i++) { + var o = {}; + o["x" + i] = 42; + o.y = 1; + foo(o); +} + +// Cross-realm, same-compartment +var g = newGlobal({newCompartment: false}); +g.eval("var o = {x: 42, y: 1}"); +foo(g.o); + +// Cross-realm, cross-compartment +var g2 = newGlobal({newCompartment: true}); +g2.eval("var o = {x: 42, y: 1}"); +foo(g2.o); diff --git a/js/src/jit-test/tests/basic/date-getLocale-oom.js b/js/src/jit-test/tests/basic/date-getLocale-oom.js new file mode 100644 index 0000000000..7c0b1a7190 --- /dev/null +++ b/js/src/jit-test/tests/basic/date-getLocale-oom.js @@ -0,0 +1,5 @@ +// |jit-test| skip-if: !('oomTest' in this) + +oomTest(function () { + new Date(NaN).toString(); +}, {keepFailing: true}); diff --git a/js/src/jit-test/tests/basic/date-late-weekday-warning.js b/js/src/jit-test/tests/basic/date-late-weekday-warning.js new file mode 100644 index 0000000000..ca6730e56c --- /dev/null +++ b/js/src/jit-test/tests/basic/date-late-weekday-warning.js @@ -0,0 +1,34 @@ +/** + * Test deprecation warning for late weekday in Date.parse + */ + +function testWarn(date) { + const g = newGlobal(); + g.eval(`Date.parse("${date}")`); + const warning = getLastWarning(); + assertEq(warning !== null, true, `warning should be caught for ${date}`); + assertEq(warning.name, "Warning", warning.name); + + clearLastWarning(); + + g.eval(`Date.parse("${date}")`); + assertEq(getLastWarning(), null, "warning should not be caught for 2nd ocurrence"); +} + +function testNoWarn(date) { + Date.parse(date); + assertEq(getLastWarning(), null, `warning should not be caught for ${date}`); +} + +enableLastWarning(); + +testWarn("Sep 26 1995 Tues"); +testWarn("Sep 26 Tues 1995"); +testWarn("Sep 26 Tues 1995 Tues"); +testWarn("Sep 26 1995 10:Tues:00"); + +testNoWarn("Sep 26 1995"); +testNoWarn("Tues Sep 26 1995"); +testNoWarn("Sep Tues 26 1995"); + +disableLastWarning(); diff --git a/js/src/jit-test/tests/basic/date-methods-this-error.js b/js/src/jit-test/tests/basic/date-methods-this-error.js new file mode 100644 index 0000000000..b075a6e37d --- /dev/null +++ b/js/src/jit-test/tests/basic/date-methods-this-error.js @@ -0,0 +1,18 @@ +load(libdir + "asserts.js"); + +let ignored = [ + "constructor", + "toJSON", // Generic, but calls toISOString + "toGMTString", // Same method as toUTCString +] + +let methods = Object.getOwnPropertyNames(Date.prototype) + .filter(name => !ignored.includes(name)); + +for (let method of methods) { + assertTypeErrorMessage(() => Date.prototype[method].call(new Map), + `Date.prototype.${method} called on incompatible Map`); + + assertTypeErrorMessage(() => Date.prototype[method].call(false), + `Date.prototype.${method} called on incompatible boolean`); +} diff --git a/js/src/jit-test/tests/basic/decompile-script.js b/js/src/jit-test/tests/basic/decompile-script.js new file mode 100644 index 0000000000..b5926d79c1 --- /dev/null +++ b/js/src/jit-test/tests/basic/decompile-script.js @@ -0,0 +1,6 @@ +function example(a, b, c) { + var complicated = 3; + perform_some_operations(); +} +var myfun = function (a, b) { return a + b; } +assertEq(decompileThis(), snarf(thisFilename())); diff --git a/js/src/jit-test/tests/basic/deep2.js b/js/src/jit-test/tests/basic/deep2.js new file mode 100644 index 0000000000..2cf30b814b --- /dev/null +++ b/js/src/jit-test/tests/basic/deep2.js @@ -0,0 +1,11 @@ +function deep1(x) { + if (x > 90) + return 1; + return 2; +} +function deep2() { + for (var i = 0; i < 100; ++i) + deep1(i); + return "ok"; +} +assertEq(deep2(), "ok"); diff --git a/js/src/jit-test/tests/basic/deepForInLoop.js b/js/src/jit-test/tests/basic/deepForInLoop.js new file mode 100644 index 0000000000..8bae45eb15 --- /dev/null +++ b/js/src/jit-test/tests/basic/deepForInLoop.js @@ -0,0 +1,12 @@ +function deepForInLoop() { + // NB: the number of props set in C is arefully tuned to match 8 = 2. + function C(){this.p = 1, this.q = 2} + C.prototype = {p:1, q:2, r:3, s:4, t:5}; + var o = new C; + var j = 0; + var a = []; + for (var i in o) + a[j++] = i; + return a.join(""); +} +assertEq(deepForInLoop(), "pqrst"); diff --git a/js/src/jit-test/tests/basic/defaultvalue-toString-is-noncallable-object-elem.js b/js/src/jit-test/tests/basic/defaultvalue-toString-is-noncallable-object-elem.js new file mode 100644 index 0000000000..b5a28be554 --- /dev/null +++ b/js/src/jit-test/tests/basic/defaultvalue-toString-is-noncallable-object-elem.js @@ -0,0 +1,4 @@ +var arr = ["foo", "bar"]; +var obj = { toString: {}, valueOf: function() { return 1; } }; +for (var i = 0; i < 25; i++) + assertEq(arr[obj], "bar"); diff --git a/js/src/jit-test/tests/basic/defaultvalue-toString-is-noncallable-object.js b/js/src/jit-test/tests/basic/defaultvalue-toString-is-noncallable-object.js new file mode 100644 index 0000000000..f0a30d1158 --- /dev/null +++ b/js/src/jit-test/tests/basic/defaultvalue-toString-is-noncallable-object.js @@ -0,0 +1,3 @@ +var obj = { toString: {}, valueOf: function() { return "foopy"; } }; +for (var i = 0; i < 25; i++) + assertEq(String(obj), "foopy"); diff --git a/js/src/jit-test/tests/basic/defaultvalue-valueOf-is-noncallable-object.js b/js/src/jit-test/tests/basic/defaultvalue-valueOf-is-noncallable-object.js new file mode 100644 index 0000000000..9bb2126b93 --- /dev/null +++ b/js/src/jit-test/tests/basic/defaultvalue-valueOf-is-noncallable-object.js @@ -0,0 +1,3 @@ +var obj = { valueOf: {}, toString: function() { return 0; } }; +for (var i = 0; i < 25; i++) + assertEq(obj < 1, true); diff --git a/js/src/jit-test/tests/basic/define-frozen-dense-strict.js b/js/src/jit-test/tests/basic/define-frozen-dense-strict.js new file mode 100644 index 0000000000..a1e82e9c58 --- /dev/null +++ b/js/src/jit-test/tests/basic/define-frozen-dense-strict.js @@ -0,0 +1,16 @@ +"use strict"; +var t = [4]; +var stop; +Object.freeze(t); +do { + let ok = false; + stop = inIon(); + try { + t[1] = 2; + } catch(e) { + ok = true; + } + assertEq(ok, true); + assertEq(t.length, 1); + assertEq(t[1], undefined); +} while (!stop); diff --git a/js/src/jit-test/tests/basic/define-frozen-dense.js b/js/src/jit-test/tests/basic/define-frozen-dense.js new file mode 100644 index 0000000000..7a7e2a97f3 --- /dev/null +++ b/js/src/jit-test/tests/basic/define-frozen-dense.js @@ -0,0 +1,9 @@ +var t = [4]; +var stop; +Object.freeze(t); +do { + stop = inIon(); + t[1] = 2; + assertEq(t.length, 1); + assertEq(t[1], undefined); +} while (!stop); diff --git a/js/src/jit-test/tests/basic/define-frozen-property-strict.js b/js/src/jit-test/tests/basic/define-frozen-property-strict.js new file mode 100644 index 0000000000..7e2b2d818b --- /dev/null +++ b/js/src/jit-test/tests/basic/define-frozen-property-strict.js @@ -0,0 +1,14 @@ +function foo(x) { + "use strict"; + var ok = false; + try { + x.c = 10; + } catch(e) { + ok = true; + } + assertEq(ok, true); + assertEq(x.c, undefined); +} +x = {a:0,b:1}; +Object.freeze(x); +foo(x); diff --git a/js/src/jit-test/tests/basic/define-frozen-property.js b/js/src/jit-test/tests/basic/define-frozen-property.js new file mode 100644 index 0000000000..759552c58c --- /dev/null +++ b/js/src/jit-test/tests/basic/define-frozen-property.js @@ -0,0 +1,7 @@ +function foo(x) { + x.c = 10; + assertEq(x.c, undefined); +} +x = {a:0,b:1}; +Object.freeze(x); +foo(x); diff --git a/js/src/jit-test/tests/basic/delete-all-dict-props.js b/js/src/jit-test/tests/basic/delete-all-dict-props.js new file mode 100644 index 0000000000..3a68a02e69 --- /dev/null +++ b/js/src/jit-test/tests/basic/delete-all-dict-props.js @@ -0,0 +1,15 @@ +function f(o) { + for (var i = 0; i < 100; i++) { + o["a" + i] = i; + } + for (var i = 0; i < 100; i++) { + delete o["a" + i]; + } + o.x = 123; + assertEq(Object.keys(o).length, 1); +} +f({}); +f([]); +let obj = newObjectWithManyReservedSlots(); +f(obj); +checkObjectWithManyReservedSlots(obj); diff --git a/js/src/jit-test/tests/basic/delete-array-elements.js b/js/src/jit-test/tests/basic/delete-array-elements.js new file mode 100644 index 0000000000..e56fa36bd0 --- /dev/null +++ b/js/src/jit-test/tests/basic/delete-array-elements.js @@ -0,0 +1,7 @@ +var a = [0,1,2,3,4,5,6,7,8,9,10]; +for (var i = 0; i < 10; i++) + delete a[9 - i]; +assertEq(a.length, 11); +for (i = 0; i < 10; i++) + assertEq(a.hasOwnProperty(i), false); + diff --git a/js/src/jit-test/tests/basic/delete-indexed-names.js b/js/src/jit-test/tests/basic/delete-indexed-names.js new file mode 100644 index 0000000000..d65a1acba2 --- /dev/null +++ b/js/src/jit-test/tests/basic/delete-indexed-names.js @@ -0,0 +1,7 @@ +var a = ['p', 'q', 'r', 's', 't']; +var o = {p:1, q:2, r:3, s:4, t:5}; +for (var i in o) + delete o[i]; +for (var i of a) + assertEq(o.hasOwnProperty(i), false); + diff --git a/js/src/jit-test/tests/basic/delete-integer-nonid.js b/js/src/jit-test/tests/basic/delete-integer-nonid.js new file mode 100644 index 0000000000..e016227cba --- /dev/null +++ b/js/src/jit-test/tests/basic/delete-integer-nonid.js @@ -0,0 +1,24 @@ +var JSID_INT_MIN = -(1 << 30); +var JSID_INT_MAX = (1 << 30) - 1; + +var o = {}; + + +for (var i = 0; i < 10; i++) + delete o[JSID_INT_MIN - 1]; + +for (var i = 0; i < 10; i++) + delete o[JSID_INT_MIN]; + +for (var i = 0; i < 10; i++) + delete o[JSID_INT_MIN + 1]; + + +for (var i = 0; i < 10; i++) + delete o[JSID_INT_MAX - 1]; + +for (var i = 0; i < 10; i++) + delete o[JSID_INT_MAX]; + +for (var i = 0; i < 10; i++) + delete o[JSID_INT_MAX + 1]; diff --git a/js/src/jit-test/tests/basic/delete-last-check-proto.js b/js/src/jit-test/tests/basic/delete-last-check-proto.js new file mode 100644 index 0000000000..5384c8e336 --- /dev/null +++ b/js/src/jit-test/tests/basic/delete-last-check-proto.js @@ -0,0 +1,8 @@ +// Test that removing a non-dictionary property does not roll back the object's +// shape to the previous one if the protos are different. + +var o = {x: 1}; +o.y = 2; +Object.setPrototypeOf(o, null); +delete o.y; +assertEq(Object.getPrototypeOf(o), null); diff --git a/js/src/jit-test/tests/basic/delete-named-names.js b/js/src/jit-test/tests/basic/delete-named-names.js new file mode 100644 index 0000000000..ce2443cd69 --- /dev/null +++ b/js/src/jit-test/tests/basic/delete-named-names.js @@ -0,0 +1,12 @@ +var a = ['p', 'q', 'r', 's', 't']; +var o = {p:1, q:2, r:3, s:4, t:5}; +for (var i in o) { + delete o.p; + delete o.q; + delete o.r; + delete o.s; + delete o.t; +} +for (var i of a) + assertEq(o.hasOwnProperty(i), false); + diff --git a/js/src/jit-test/tests/basic/delete-non-config.js b/js/src/jit-test/tests/basic/delete-non-config.js new file mode 100644 index 0000000000..da6020cad8 --- /dev/null +++ b/js/src/jit-test/tests/basic/delete-non-config.js @@ -0,0 +1,4 @@ +var a = [0,1,2,3,4,5,6,7,8,9,10]; +for (var i = 0; i < 10; i++) + assertEq(delete a.length, false); +assertEq(delete a.length, false); diff --git a/js/src/jit-test/tests/basic/deleteToString.js b/js/src/jit-test/tests/basic/deleteToString.js new file mode 100644 index 0000000000..0b8dfc59d4 --- /dev/null +++ b/js/src/jit-test/tests/basic/deleteToString.js @@ -0,0 +1,5 @@ + +/* Inheritance of shadowed function properties from Object.prototype. */ + +delete Function.prototype.toString; +assertEq(Function.prototype.toString, Object.prototype.toString); diff --git a/js/src/jit-test/tests/basic/dense-elements-appear.js b/js/src/jit-test/tests/basic/dense-elements-appear.js new file mode 100644 index 0000000000..351f8f6763 --- /dev/null +++ b/js/src/jit-test/tests/basic/dense-elements-appear.js @@ -0,0 +1,28 @@ +function f() { + var x = [1, 2, 3]; + var y = {}; + x.__proto__ = y; + + for (var i = 0; i < 200; i++) { + if (i == 100) + y[100000] = 15; + else + assertEq(typeof x[100000], i > 100 ? "number" : "undefined"); + } +} + +function g() { + var x = [1, 2, 3]; + var y = {}; + x.__proto__ = y; + + for (var i = 0; i < 200; i++) { + if (i == 100) + y[4] = 15; + else + assertEq(typeof x[4], i > 100 ? "number" : "undefined"); + } +} + +f(); +g(); diff --git a/js/src/jit-test/tests/basic/dense-elements-hole-negative.js b/js/src/jit-test/tests/basic/dense-elements-hole-negative.js new file mode 100644 index 0000000000..cf63da92e0 --- /dev/null +++ b/js/src/jit-test/tests/basic/dense-elements-hole-negative.js @@ -0,0 +1,31 @@ +// The index is negative before code generation. + +let v = {}; +let negativeIndex = -1; + +function f(obj) { + assertEq(obj[negativeIndex] === v, true); +} +for (let i = 0; i < 2000; i++) { + let obj = {}; + obj[1] = {}; + obj[negativeIndex] = v; + f(obj); +} + +// The sign of the index changes after the code generation. + +function g(obj, i) { + for (let j = 0; j < 4; j++) { + assertEq(obj[i-j] === v, true); + } +} +for (let i = 0; i < 2000; i++) { + let obj = {}; + obj[1] = {}; + let X = 2000 - i; + for (let j = 0; j < 10; j++) { + obj[X-j] = v; + } + g(obj, X); +} diff --git a/js/src/jit-test/tests/basic/densify-elements.js b/js/src/jit-test/tests/basic/densify-elements.js new file mode 100644 index 0000000000..f2944c0e55 --- /dev/null +++ b/js/src/jit-test/tests/basic/densify-elements.js @@ -0,0 +1,15 @@ +function f(o) { + for (var i = 1; i <= 5; i += 4) { + var start = i * 4000; + var end = (start * 1.4)|0; + for (var j = end; j > start; j--) { + o[j] = j; + } + } + assertEq(Object.keys(o).length, 9600); +} +f({}); +f([]); +let obj = newObjectWithManyReservedSlots(); +f(obj); +checkObjectWithManyReservedSlots(obj); diff --git a/js/src/jit-test/tests/basic/dependentStrings.js b/js/src/jit-test/tests/basic/dependentStrings.js new file mode 100644 index 0000000000..1dd38bbacb --- /dev/null +++ b/js/src/jit-test/tests/basic/dependentStrings.js @@ -0,0 +1,11 @@ +function dependentStrings() +{ + var a = []; + var t = "abcdefghijklmnopqrst"; + for (var i = 0; i < 10; i++) { + var s = t.substring(2*i, 2*i + 2); + a[i] = s + s.length; + } + return a.join(""); +} +assertEq(dependentStrings(), "ab2cd2ef2gh2ij2kl2mn2op2qr2st2"); diff --git a/js/src/jit-test/tests/basic/destructuring-default.js b/js/src/jit-test/tests/basic/destructuring-default.js new file mode 100644 index 0000000000..49a908b8aa --- /dev/null +++ b/js/src/jit-test/tests/basic/destructuring-default.js @@ -0,0 +1,251 @@ + +load(libdir + 'asserts.js'); +load(libdir + 'eqArrayHelper.js'); + +var arrayPattern = '[a = 1, b = 2, c = 3, d = 4, e = 5, f = 6]'; +var objectPattern = '{0: a = 1, 1: b = 2, 2: c = 3, 3: d = 4, 4: e = 5, 5: f = 6}'; +var objectPatternShorthand = '{a = 1, b = 2, c = 3, d = 4, e = 5, f = 6}'; +var nestedPattern = '{a: a = 1, b: [b = 2] = [], c: {c: [c]} = {c: [3]}, d: {d, e} = {d: 4, e: 5}, f: f = 6}'; + +function testAll(fn) { + assertEqArray(fn(arrayPattern, []), [1, 2, 3, 4, 5, 6]); + assertEqArray(fn(arrayPattern, [2, 3, 4, 5, 6, 7, 8, 9]), [2, 3, 4, 5, 6, 7]); + assertEqArray(fn(arrayPattern, [undefined, 0, false, null, "", undefined]), [1, 0, false, null, "", 6]); + assertEqArray(fn(arrayPattern, [0, false]), [0, false, 3, 4, 5, 6]); + + assertEqArray(fn(objectPattern, []), [1, 2, 3, 4, 5, 6]); + assertEqArray(fn(objectPattern, [2, 3, 4, 5, 6, 7, 8, 9]), [2, 3, 4, 5, 6, 7]); + assertEqArray(fn(objectPattern, [undefined, 0, false, null, "", undefined]), [1, 0, false, null, "", 6]); + assertEqArray(fn(objectPattern, [0, false]), [0, false, 3, 4, 5, 6]); + + assertEqArray(fn(objectPatternShorthand, {}), [1, 2, 3, 4, 5, 6]); + assertEqArray(fn(objectPatternShorthand, {a: 2, b: 3, c: 4, d: 5, e: 6, f: 7, g: 8, h: 9}), [2, 3, 4, 5, 6, 7]); + assertEqArray(fn(objectPatternShorthand, {a: undefined, b: 0, c: false, d: null, e: "", f: undefined}), + [1, 0, false, null, "", 6]); + assertEqArray(fn(objectPatternShorthand, {a: 0, b: false}), [0, false, 3, 4, 5, 6]); + assertEqArray(fn(nestedPattern, {}), [1, 2, 3, 4, 5, 6]); + assertEqArray(fn(nestedPattern, {a: 2, b: [], c: undefined}), [2, 2, 3, 4, 5, 6]); + assertEqArray(fn(nestedPattern, {a: undefined, b: [3], c: {c: [4]}}), [1, 3, 4, 4, 5, 6]); + assertEqArray(fn(nestedPattern, {a: undefined, b: [3], c: {c: [4]}, d: {d: 5, e: 6}}), [1, 3, 4, 5, 6, 6]); +} + +function testVar(pattern, input) { + return new Function('input', + 'var ' + pattern + ' = input;' + + 'return [a, b, c, d, e, f];' + )(input); +} +testAll(testVar); + +function testLet(pattern, input) { + return new Function('input', + 'let ' + pattern + ' = input;' + + 'return [a, b, c, d, e, f];' + )(input); +} +testAll(testLet); + +function testConst(pattern, input) { + return new Function('input', + 'const ' + pattern + ' = input;' + + 'return [a, b, c, d, e, f];' + )(input); +} +testAll(testConst); + +function testGlobal(pattern, input) { + return new Function('input', + '(' + pattern + ' = input);' + + 'return [a, b, c, d, e, f];' + )(input); +} +testAll(testGlobal); + +function testClosure(pattern, input) { + return new Function('input', + 'var rest; (function () {' + + '(' + pattern + ' = input);' + + '})();' + + 'return [a, b, c, d, e, f];' + )(input); +} +testAll(testClosure); + +function testArgument(pattern, input) { + return new Function('input', + 'return (function (' + pattern + ') {' + + 'return [a, b, c, d, e, f]; })(input);' + )(input); +} +testAll(testArgument); + +function testArgumentFunction(pattern, input) { + return new Function(pattern, + 'return [a, b, c, d, e, f];' + )(input); +} +testAll(testArgumentFunction); + +function testThrow(pattern, input) { + return new Function('input', + 'try { throw input }' + + 'catch(' + pattern + ') {' + + 'return [a, b, c, d, e, f]; }' + )(input); +} +testAll(testThrow); + +// test global const +const [ca = 1, cb = 2] = []; +assertEq(ca, 1); +assertEq(cb, 2); + +const {a: {a: cc = 3} = {a: undefined}} = {}; +assertEq(cc, 3); + +// test that the assignment happens in source order +var a = undefined, b = undefined, c = undefined; +({a: a = 1, c: c = 2, b: b = 3} = { + get a() { + assertEq(a, undefined); + assertEq(c, undefined); + assertEq(b, undefined); + return undefined; + }, + get b() { + assertEq(a, 1); + assertEq(c, 2); + assertEq(b, undefined); + return 4; + }, + get c() { + assertEq(a, 1); + assertEq(c, undefined); + assertEq(b, undefined); + return undefined; + } +}); +assertEq(b, 4); + +assertThrowsInstanceOf(() => { var {a: {a} = null} = {}; }, TypeError); +assertThrowsInstanceOf(() => { var [[a] = 2] = []; }, TypeError); + +// destructuring assignment might have duplicate variable names. +var [a = 1, a = 2] = [3]; +assertEq(a, 2); + +// assignment to properties of default params +[a = {y: 2}, a.x = 1] = []; +assertEq(typeof a, 'object'); +assertEq(a.x, 1); +assertEq(a.y, 2); + +// defaults are evaluated even if there is no binding +var evaled = false; +({a: {} = (evaled = true, {})} = {}); +assertEq(evaled, true); +evaled = false; +assertThrowsInstanceOf(() => { [[] = (evaled = true, 2)] = [] }, TypeError); +assertEq(evaled, true); + +assertThrowsInstanceOf(() => new Function('var [...rest = defaults] = [];'), SyntaxError); + +new Function(` + b = undefined; + for (var [a, b = 10] in " ") {} + assertEq(b, 10);`)(); + +new Function(` + b = undefined; + for (let [a, c = 10] in " ") { b = c; } + assertEq(b, 10);`)(); + +new Function(` + b = undefined; + for (let [a, c = (x => y)] in " ") { b = c; } + assertEq(typeof b, "function");`)(); + +new Function(` + b = undefined; + for (let [a, __proto__ = 10] in " ") { b = __proto__; } + assertEq(b, 10);`)(); + +new Function(` + b = undefined; + for (let [a, __proto__ = (x => y)] in " ") { b = __proto__; } + assertEq(typeof b, "function");`)(); + +new Function(` + b = undefined; + for (var {1: b = 10} in " ") {} + assertEq(b, 10);`)(); + +new Function(` + b = undefined; + for (let {1: c = 10} in " ") { b = c; } + assertEq(b, 10);`)(); + +new Function(` + b = undefined; + for (let { c = 10 } in " ") { b = c; } + assertEq(b, 10);`)(); + +new Function(` + b = undefined; + assertEq(Number.prototype.a, undefined); + for (var { a: c = (x => y) } in [{}]) { b = c; } + assertEq(typeof b, "function");`)(); + +new Function(` + b = undefined; + Object.defineProperty(String.prototype, "__proto__", + { value: undefined, configurable: true }); + for (var { __proto__: c = (x => y) } in [{}]) { b = c; } + delete String.prototype.__proto__; + assertEq(typeof b, "function");`)(); + +new Function(` + b = undefined; + for (var { a: c = (x => y) } of [{ a: undefined }]) { b = c; } + assertEq(typeof b, "function");`)(); + +new Function(` + b = undefined; + for (var { __proto__: c = (x => y) } of [{ ["__proto__"]: undefined }]) { b = c; } + assertEq(typeof b, "function");`)(); + +new Function(` + b = undefined; + var ts = Function.prototype.toString; + Function.prototype.toString = () => 'hi'; + String.prototype.hi = 42; + for (var { [(x => y)]: c } in [0]) { b = c; } + Function.prototype.toString = ts; + delete String.prototype.hi; + assertEq(b, 42);`)(); + +new Function(` + b = undefined; + var ts = Function.prototype.toString; + Function.prototype.toString = () => 'hi'; + String.prototype.hi = 42; + for (var { [(x => y)]: __proto__ } in [0]) { b = __proto__; } + Function.prototype.toString = ts; + delete String.prototype.hi; + assertEq(b, 42);`)(); + +new Function(` + b = undefined; + var ts = Function.prototype.toString; + Function.prototype.toString = () => 'hi'; + for (var { [(x => y)]: c } of [{ 'hi': 42 }]) { b = c; } + Function.prototype.toString = ts; + assertEq(b, 42);`)(); + +new Function(` + b = undefined; + var ts = Function.prototype.toString; + Function.prototype.toString = () => 'hi'; + for (var { [(x => y)]: __proto__ } of [{ hi: 42 }]) { b = __proto__; } + Function.prototype.toString = ts; + assertEq(b, 42);`)(); diff --git a/js/src/jit-test/tests/basic/destructuring-iterator.js b/js/src/jit-test/tests/basic/destructuring-iterator.js new file mode 100644 index 0000000000..ca65930242 --- /dev/null +++ b/js/src/jit-test/tests/basic/destructuring-iterator.js @@ -0,0 +1,124 @@ + +load(libdir + 'asserts.js'); +load(libdir + 'iteration.js'); +load(libdir + 'eqArrayHelper.js'); + +// throw on non-iterables +assertThrowsInstanceOf(() => { [a, b, c] = {0: 0, 1: 1, 2: 2} }, TypeError); + +var nextcalls = 0, donecalls = 0, valuecalls = 0; +var doneafter = 0; +var iterable = {}; +iterable[Symbol.iterator] = function () { + return { + next: function () { + assertEq(arguments.length, 0, 'iterator.next() should be called with no arguments'); + nextcalls++; + return { + get done() { + donecalls++; + return --doneafter < 0; + }, + get value() { + valuecalls++; + return valuecalls; + } + }; + } + } +}; + +function assertIterable(expectCalls, fn, expectResult) { + [nextcalls, donecalls, valuecalls, doneafter] = [0,0,0, expectCalls[3]]; + assertEqArray(fn(iterable), expectResult); + assertEq(nextcalls, expectCalls[0], 'calls to iterator.next()'); + assertEq(donecalls, expectCalls[1], 'getting iterator.next().done'); + assertEq(valuecalls, expectCalls[2], 'getting iterator.next().value'); +} + +assertIterable([1,1,1,1], + it => { var [a] = it; return [a]; }, + [1]); +assertIterable([2,2,1,1], + it => { var [a,b,c] = it; return [a,b,c]; }, + [1,undefined,undefined]); +assertIterable([2,2,1,1], + it => { var [a,b,...rest] = it; return [a,b,...rest]; }, + [1,undefined]); +assertIterable([5,5,4,4], + it => { var [,,...rest] = it; return rest; }, + [3,4]); + +// the iterator should be exhausted before any error is thrown +assertIterable([5,5,4,4], + it => { + assertThrowsInstanceOf(function () { + "use strict"; + [...{0: "".x}] = it; + }, TypeError); + return []; + }, + []); + +var arraycalls = 0; +var ArrayIterator = Array.prototype[Symbol.iterator]; +Array.prototype[Symbol.iterator] = function () { + arraycalls++; + return ArrayIterator.apply(this, arguments); +}; +// [...rest] should not call Array#@@iterator for the LHS +var [...rest] = iterable; +assertEq(arraycalls, 0, 'calls to Array#@@iterator'); +// [...[...rest]] should do so, since it creates an implicit array for the +// first rest pattern, then destructures that again using @@iterator() for the +// second rest pattern. +var [...[...rest]] = iterable; +assertEq(arraycalls, 1, 'calls to Array#@@iterator'); + +// loop `fn` a few times, to get it JIT-compiled +function loop(fn) { + var i = 1e4; + while (i--) fn(); +} + +loop(() => { doneafter = 4; var [a] = iterable; return a; }); +loop(() => { doneafter = 4; var [a,b,...[...rest]] = iterable; return rest; }); + + +// destructuring assignment should always use iterators and not optimize +// to a "group assignment" +delete Array.prototype[Symbol.iterator]; +assertThrowsInstanceOf(() => { var [a,b] = [1,2]; }, TypeError); +Array.prototype[Symbol.iterator] = ArrayIterator; + +// observe the binding order +a = undefined, b = undefined, c = undefined; +var obj = {}; +obj[Symbol.iterator] = function* () { + // normal fields should be initialized right after |.next()| + yield 1; + assertEq(a, 1); + yield 2; + yield 3; + assertEq(b, 3); + yield 4; + yield 5; + // rest should be initialized after the iterator is exhausted + assertEq(c, undefined); +}; +[a, , b, ...c] = obj; +assertEqArray(c, [4,5]); + +// a throw inside the destructuring of the "catch" value should not enter +// the "catch" block + +assertThrowsValue(function () { + try { + Array.prototype[Symbol.iterator] = function () { throw 'from iterator'; }; + throw [1, 2]; + } catch ([x, y]) { + throw 'not reached'; + } +}, 'from iterator'); +Array.prototype[Symbol.iterator] = ArrayIterator; + diff --git a/js/src/jit-test/tests/basic/destructuring-null-or-undefined-into-computed-property-name.js b/js/src/jit-test/tests/basic/destructuring-null-or-undefined-into-computed-property-name.js new file mode 100644 index 0000000000..c5d75801ab --- /dev/null +++ b/js/src/jit-test/tests/basic/destructuring-null-or-undefined-into-computed-property-name.js @@ -0,0 +1,47 @@ +load(libdir + 'asserts.js'); +load(libdir + 'iteration.js'); + +var outer = "unmodified"; + +function f(v) +{ + if (v + "") + ({ [(outer = "modified")]: v } = v); +} + +assertEq(outer, "unmodified"); +f(true); +assertEq(outer, "modified"); + +outer = "unmodified"; +f({}); +assertEq(outer, "modified"); + +outer = "unmodified"; +assertThrowsInstanceOf(() => f(null), TypeError); +assertEq(outer, "unmodified"); + +assertThrowsInstanceOf(() => f(undefined), TypeError); +assertEq(outer, "unmodified"); + + +function g(v) +{ + if (v + "") + ({ [{ toString() { outer = "modified"; return 0; } }]: v } = v); +} + +outer = "unmodified"; +g(true); +assertEq(outer, "modified"); + +outer = "unmodified"; +g({}); +assertEq(outer, "modified"); + +outer = "unmodified"; +assertThrowsInstanceOf(() => g(undefined), TypeError); +assertEq(outer, "unmodified"); + +assertThrowsInstanceOf(() => g(null), TypeError); +assertEq(outer, "unmodified"); diff --git a/js/src/jit-test/tests/basic/destructuring-requireobjectcoercible.js b/js/src/jit-test/tests/basic/destructuring-requireobjectcoercible.js new file mode 100644 index 0000000000..c2b1403d30 --- /dev/null +++ b/js/src/jit-test/tests/basic/destructuring-requireobjectcoercible.js @@ -0,0 +1,107 @@ +load(libdir + 'asserts.js'); +load(libdir + 'iteration.js'); + +function f(v) +{ + if (v + "") + ({} = v); +} + +f(true); +f({}); +assertThrowsInstanceOf(() => f(null), TypeError); +assertThrowsInstanceOf(() => f(undefined), TypeError); + +function g(v) +{ + if (v + "") + ({} = v); +} + +g(true); +g({}); +assertThrowsInstanceOf(() => g(undefined), TypeError); +assertThrowsInstanceOf(() => g(null), TypeError); + +function h(v) +{ + if (v + "") + ([] = v); +} + +h([true]); +h("foo"); +assertThrowsInstanceOf(() => h(undefined), TypeError); +assertThrowsInstanceOf(() => h(null), TypeError); + +Object.defineProperty(Boolean.prototype, "v", + { get() { "use strict"; return typeof this; }, + enumerable: true, + configurable: true }); + +Object.defineProperty(Number.prototype, "v", + { get() { "use strict"; return typeof this; }, + enumerable: true, + configurable: true }); + +Object.defineProperty(String.prototype, "v", + { get() { "use strict"; return typeof this; }, + enumerable: true, + configurable: true }); + +Object.defineProperty(Symbol.prototype, "v", + { get() { "use strict"; return typeof this; }, + enumerable: true, + configurable: true }); + +function primitiveThisSupported() +{ + return 3.14.custom === "number"; +} + +function primitiveThisTests() +{ + function f(v) + { + var type = typeof v; + + ({ v } = v); + + assertEq(v, type); + } + + f(true); + f(3.14); + f(72); + f("ohai"); + f(Symbol.iterator); + + assertThrowsInstanceOf(() => f(undefined), TypeError); + assertThrowsInstanceOf(() => f(null), TypeError); + + function g(v) + { + var type = typeof v; + + ({ v } = v); + + assertEq(v, type); + } + + g(true); + g(3.14); + g(72); + g("ohai"); + g(Symbol.iterator); + + assertThrowsInstanceOf(() => g(null), TypeError); + assertThrowsInstanceOf(() => g(undefined), TypeError); +} +if (primitiveThisSupported()) + primitiveThisTests(); + +// Ensure the internal implementation of destructuring object pattern +// assignment -- using a self-hosted intrinsic function -- works even when lazy +// standard class initialization hasn't occurred. Unfortunately we can't use +// |newGlobal()| because that method eagerly initializes standard classes. +evalcx("({} = 1);", evalcx("lazy")); diff --git a/js/src/jit-test/tests/basic/destructuring-rest-identifiers.js b/js/src/jit-test/tests/basic/destructuring-rest-identifiers.js new file mode 100644 index 0000000000..8276ff6e2a --- /dev/null +++ b/js/src/jit-test/tests/basic/destructuring-rest-identifiers.js @@ -0,0 +1,69 @@ + +load(libdir + 'asserts.js'); +load(libdir + 'eqArrayHelper.js'); + +var reserved = [ + 'break', + 'do', + 'in', + 'typeof', + 'case', + 'else', + 'instanceof', + 'var', + 'catch', + 'export', + 'new', + 'void', + 'class', + 'extends', + 'return', + 'while', + 'const', + 'finally', + 'super', + 'with', + 'continue', + 'for', + 'switch', + 'debugger', + 'function', + 'this', + 'delete', + 'import', + 'try', + 'enum', + 'null', + 'true', + 'false' +]; +reserved.forEach(ident => { + assertThrowsInstanceOf(() => new Function('var [...' + ident + '] = []'), SyntaxError); +}); + +var strictIdentifiers = [ + 'yield', + 'let', + 'eval', + 'arguments', + 'implements', + 'interface', + 'package', + 'private', + 'protected', + 'public', + 'static' +]; + +strictIdentifiers.forEach(ident => + assertThrowsInstanceOf(() => + new Function('"use strict"; [...' + ident + '] = []'), SyntaxError)); + +var globalEval = eval; +strictIdentifiers.forEach(ident => { + globalEval(ident + ' = null'); + assertEqArray(new Function('input', '[, ...' + ident + '] = input;' + + 'return ' + ident + )([1, 2, 3]), [2, 3]); +}); + diff --git a/js/src/jit-test/tests/basic/destructuring-rest.js b/js/src/jit-test/tests/basic/destructuring-rest.js new file mode 100644 index 0000000000..fcb7b79bba --- /dev/null +++ b/js/src/jit-test/tests/basic/destructuring-rest.js @@ -0,0 +1,147 @@ + +load(libdir + 'asserts.js'); +load(libdir + 'eqArrayHelper.js'); + +assertThrowsInstanceOf(() => new Function('[...a, ,] = []'), SyntaxError, 'trailing elision'); +assertThrowsInstanceOf(() => new Function('[a, ...b, c] = []'), SyntaxError, 'trailing param'); +assertThrowsInstanceOf(() => new Function('[...a=b] = []'), SyntaxError, 'assignment expression'); +assertThrowsInstanceOf(() => new Function('[...a()] = []'), SyntaxError, 'call expression'); +assertThrowsInstanceOf(() => new Function('[...(a,b)] = []'), SyntaxError, 'comma expression'); +assertThrowsInstanceOf(() => new Function('[...a++] = []'), SyntaxError, 'postfix expression'); +assertThrowsInstanceOf(() => new Function('[...!a] = []'), SyntaxError, 'unary expression'); +assertThrowsInstanceOf(() => new Function('[...a+b] = []'), SyntaxError, 'binary expression'); +assertThrowsInstanceOf(() => new Function('var [...a.x] = []'), SyntaxError, 'lvalue expression in declaration'); +assertThrowsInstanceOf(() => new Function('var [...(b)] = []'), SyntaxError); +assertThrowsInstanceOf(() => new Function('[...b,] = []'), SyntaxError); + +assertThrowsInstanceOf(() => { + try { + eval('let [...[...x]] = (() => { throw "foo"; } )();'); + } catch(e) { + assertEq(e, "foo"); + } + x; +}, ReferenceError); + +var inputArray = [1, 2, 3]; +var inputDeep = [1, inputArray]; +var inputObject = {a: inputArray}; +var inputStr = 'str'; +function *inputGenerator() { + yield 1; + yield 2; + yield 3; +} + +var o = {prop: null, call: function () { return o; }}; + +var expected = [2, 3]; +var expectedStr = ['t', 'r']; + +function testAll(fn) { + testDeclaration(fn); + + o.prop = null; + assertEqArray(fn('[, ...(o.prop)]', inputArray, 'o.prop'), expected); + o.prop = null; + assertEqArray(fn('[, ...(o.call().prop)]', inputArray, 'o.prop'), expected); + + o.prop = null; + assertEqArray(fn('[, ...[...(o.prop)]]', inputArray, 'o.prop'), expected); + o.prop = null; + assertEqArray(fn('[, ...[...(o.call().prop)]]', inputArray, 'o.prop'), expected); +} +function testDeclaration(fn) { + testStr(fn); + + assertEqArray(fn('[, ...rest]', inputArray), expected); + assertEqArray(fn('[, ...rest]', inputGenerator()), expected); + assertEqArray(fn('[, [, ...rest]]', inputDeep), expected); + assertEqArray(fn('{a: [, ...rest]}', inputObject), expected); + + assertEqArray(fn('[, ...[...rest]]', inputArray), expected); + assertEqArray(fn('[, ...[...rest]]', inputGenerator()), expected); + assertEqArray(fn('[, [, ...[...rest]]]', inputDeep), expected); + assertEqArray(fn('{a: [, ...[...rest]]}', inputObject), expected); + + assertEqArray(fn('[, ...{0: a, 1: b}]', inputArray, '[a, b]'), expected); + assertEqArray(fn('[, ...{0: a, 1: b}]', inputGenerator(), '[a, b]'), expected); + assertEqArray(fn('[, [, ...{0: a, 1: b}]]', inputDeep, '[a, b]'), expected); + assertEqArray(fn('{a: [, ...{0: a, 1: b}]}', inputObject, '[a, b]'), expected); +} + +function testStr(fn) { + assertEqArray(fn('[, ...rest]', inputStr), expectedStr); + + assertEqArray(fn('[, ...[...rest]]', inputStr), expectedStr); + + assertEqArray(fn('[, ...{0: a, 1: b}]', inputStr, '[a, b]'), expectedStr); +} + +function testForIn(pattern, input, binding) { + binding = binding || 'rest'; + return new Function('input', + 'for (var ' + pattern + ' in {[input]: 1}) {}' + + 'return ' + binding + )(input); +} +testStr(testForIn); + +function testVar(pattern, input, binding) { + binding = binding || 'rest'; + return new Function('input', + 'var ' + pattern + ' = input;' + + 'return ' + binding + )(input); +} +testDeclaration(testVar); + +function testGlobal(pattern, input, binding) { + binding = binding || 'rest'; + return new Function('input', + '(' + pattern + ' = input);' + + 'return ' + binding + )(input); +} +testAll(testGlobal); + +function testClosure(pattern, input, binding) { + binding = binding || 'rest'; + const decl = binding.replace('[', '').replace(']', ''); + return new Function('input', + 'var ' + decl + '; (function () {' + + '(' + pattern + ' = input);' + + '})();' + + 'return ' + binding + )(input); +} +testDeclaration(testClosure); + +function testArgument(pattern, input, binding) { + binding = binding || 'rest'; + return new Function('input', + 'return (function (' + pattern + ') {' + + 'return ' + binding + '; })(input);' + )(input); +} +testDeclaration(testArgument); + +function testArgumentFunction(pattern, input, binding) { + binding = binding || 'rest'; + return new Function(pattern, + 'return ' + binding + )(input); +} +// ES6 requires the `Function` constructor to accept arbitrary +// `BindingElement`s as formal parameters. +testDeclaration(testArgumentFunction); + +function testThrow(pattern, input, binding) { + binding = binding || 'rest'; + return new Function('input', + 'try { throw input }' + + 'catch(' + pattern + ') {' + + 'return ' + binding + '; }' + )(input); +} +testDeclaration(testThrow); diff --git a/js/src/jit-test/tests/basic/dict-object-freeze-or-seal.js b/js/src/jit-test/tests/basic/dict-object-freeze-or-seal.js new file mode 100644 index 0000000000..595e5ca55a --- /dev/null +++ b/js/src/jit-test/tests/basic/dict-object-freeze-or-seal.js @@ -0,0 +1,26 @@ +let sym = Symbol(); + +let o = {x: 1, y: 2, z: 3, a: 4, b: 5, 12345678: 6, [sym]: 7}; +for (let i = 0; i < 100; i++) { + o["foo" + i] = 1; +} +delete o.x; + +Object.seal(o); +assertEq(Object.getOwnPropertyNames(o).length, 105); +assertEq(Object.getOwnPropertySymbols(o).length, 1); + +assertEq(Object.isSealed(o), true); +assertEq(Object.isFrozen(o), false); + +let desc = Object.getOwnPropertyDescriptor(o, "y"); +assertEq(desc.writable, true); +assertEq(desc.configurable, false); + +Object.freeze(o); +assertEq(Object.isSealed(o), true); +assertEq(Object.isFrozen(o), true); + +desc = Object.getOwnPropertyDescriptor(o, "y"); +assertEq(desc.writable, false); +assertEq(desc.configurable, false); diff --git a/js/src/jit-test/tests/basic/dictionary-add-prop-oom.js b/js/src/jit-test/tests/basic/dictionary-add-prop-oom.js new file mode 100644 index 0000000000..e393cfca6b --- /dev/null +++ b/js/src/jit-test/tests/basic/dictionary-add-prop-oom.js @@ -0,0 +1,9 @@ +// |jit-test| skip-if: !('oomTest' in this) +enableShapeConsistencyChecks(); +oomTest(() => { + var obj = {a: 1, b: 2, c: 3}; + delete obj.a; + for (var i = 0; i < 100; i++) { + obj["x" + i] = i; + } +}); diff --git a/js/src/jit-test/tests/basic/dictionary-delete-compact.js b/js/src/jit-test/tests/basic/dictionary-delete-compact.js new file mode 100644 index 0000000000..73887c978c --- /dev/null +++ b/js/src/jit-test/tests/basic/dictionary-delete-compact.js @@ -0,0 +1,74 @@ +// Stress test dictionary object/map property deletion/addition/compaction. + +const numProps = 1000; + +// Delete a range of properties and check correctness. +function deleteRange(deleteStart, deleteEnd) { + for (var i = 0; i < numProps; i++) { + o["x" + i] = i; + } + for (var i = deleteStart; i < deleteEnd; i++) { + delete o["x" + i]; + } + assertEq(Object.getOwnPropertyNames(o).length, + numProps - (deleteEnd - deleteStart)); + for (var i = 0; i < numProps; i++) { + if (deleteStart <= i && i < deleteEnd) { + assertEq(("x" + i) in o, false); + } else { + assertEq(o["x" + i], i); + } + } +} + +// For every "stride" properties, delete all of them except one. +function deleteMany(stride) { + for (var i = 0; i < numProps; i++) { + o["x" + i] = i; + } + var propsNotDeleted = 0; + for (var i = 0; i < numProps; i++) { + if ((i % stride) === 1) { + propsNotDeleted++; + continue; + } + delete o["x" + i]; + } + assertEq(Object.getOwnPropertyNames(o).length, propsNotDeleted); + for (var i = 0; i < numProps; i++) { + if ((i % stride) !== 1) { + assertEq(("x" + i) in o, false); + } else { + assertEq(o["x" + i], i); + } + } +} + +var o = {}; + +function test(useFreshObject) { + function testOne(f) { + if (useFreshObject) { + o = {}; + } + f(); + } + + for (var i = 6; i < 12; i++) { + testOne(_ => deleteRange(i, 1000)); + } + testOne(_ => deleteRange(100, 1000)); + testOne(_ => deleteRange(0, 1000)); + testOne(_ => deleteRange(1, 1000)); + testOne(_ => deleteRange(8, 990)); + + testOne(_ => deleteMany(3)); + testOne(_ => deleteMany(7)); + testOne(_ => deleteMany(8)); + testOne(_ => deleteMany(15)); + testOne(_ => deleteMany(111)); +} + +test(true); +o = {}; +test(false); diff --git a/js/src/jit-test/tests/basic/disable-jit-backend.js b/js/src/jit-test/tests/basic/disable-jit-backend.js new file mode 100644 index 0000000000..2eb0fa84eb --- /dev/null +++ b/js/src/jit-test/tests/basic/disable-jit-backend.js @@ -0,0 +1,19 @@ +// |jit-test| --no-jit-backend + +assertEq(wasmIsSupportedByHardware(), false); +assertEq(wasmIsSupported(), false); +assertEq(isAsmJSCompilationAvailable(), false); + +function test() { + var sum = 0; + for (var i = 0; i < 15; i++) { + sum += i; + } + return sum; +} +assertEq(test(), 105); + +var re = /[\d][a-z]{3}[\d]/; +for (var i = 0; i < 10; i++) { + assertEq(re.exec("123foo456")[0], "3foo4"); +} diff --git a/js/src/jit-test/tests/basic/disassemble-filename.js b/js/src/jit-test/tests/basic/disassemble-filename.js new file mode 100644 index 0000000000..3c97e229d3 --- /dev/null +++ b/js/src/jit-test/tests/basic/disassemble-filename.js @@ -0,0 +1,10 @@ +if (typeof disassemble !== "function") { + quit(); +} + +const out = evaluate(` +disassemble(); +`, { + fileName: String.fromCharCode(3823486100), +}); +assertEq(out.includes(`"file": "\uC494",`), true); diff --git a/js/src/jit-test/tests/basic/display-url-in-stack-trace.js b/js/src/jit-test/tests/basic/display-url-in-stack-trace.js new file mode 100644 index 0000000000..acab47ab61 --- /dev/null +++ b/js/src/jit-test/tests/basic/display-url-in-stack-trace.js @@ -0,0 +1,27 @@ +eval(` + function a() { + return b(); + } + //# sourceURL=source-a.js +`); + +eval(` + function b() { + return c(); + } + //# sourceURL=source-b.js +`); + +eval(` + function c() { + return Error().stack; + } + //# sourceURL=source-c.js +`); + +let filenames = a().split(/\n/) + .map(f => f.slice(f.indexOf("@") + 1, f.indexOf(":"))); +print(filenames.join("\n")); +assertEq(filenames[0], "source-c.js"); +assertEq(filenames[1], "source-b.js"); +assertEq(filenames[2], "source-a.js"); diff --git a/js/src/jit-test/tests/basic/doMath.js b/js/src/jit-test/tests/basic/doMath.js new file mode 100644 index 0000000000..8129a466e2 --- /dev/null +++ b/js/src/jit-test/tests/basic/doMath.js @@ -0,0 +1,60 @@ +function map_test(t, cases) +{ + for (var i = 0; i < cases.length; i++) { + function c() { return t(cases[i].input); } + var expected = cases[i].expected; + assertEq(c(), expected); + } +} + +function lsh_inner(n) +{ + var r; + for (var i = 0; i < 35; i++) + r = 0x1 << n; + return r; +} +map_test (lsh_inner, + [{input: 15, expected: 32768}, + {input: 55, expected: 8388608}, + {input: 1, expected: 2}, + {input: 0, expected: 1}]); + +function rsh_inner(n) +{ + var r; + for (var i = 0; i < 35; i++) + r = 0x11010101 >> n; + return r; +} +map_test (rsh_inner, + [{input: 8, expected: 1114369}, + {input: 5, expected: 8914952}, + {input: 35, expected: 35659808}, + {input: -1, expected: 0}]); + +function ursh_inner(n) +{ + var r; + for (var i = 0; i < 35; i++) + r = -55 >>> n; + return r; +} +map_test (ursh_inner, + [{input: 8, expected: 16777215}, + {input: 33, expected: 2147483620}, + {input: 0, expected: 4294967241}, + {input: 1, expected: 2147483620}]); + +function doMath_inner(cos) +{ + var s = 0; + var sin = Math.sin; + for (var i = 0; i < 200; i++) + s = -Math.pow(sin(i) + cos(i * 0.75), 4); + return s; +} +function doMath() { + return doMath_inner(Math.cos); +} +assertEq(doMath(), -0.5405549555611059); diff --git a/js/src/jit-test/tests/basic/dumpStringRepresentation.js b/js/src/jit-test/tests/basic/dumpStringRepresentation.js new file mode 100644 index 0000000000..049d46ba30 --- /dev/null +++ b/js/src/jit-test/tests/basic/dumpStringRepresentation.js @@ -0,0 +1,88 @@ +// |jit-test| skip-if: typeof dumpStringRepresentation !== 'function' + +// Try the dumpStringRepresentation shell function on various types of +// strings, and make sure it doesn't crash. + +print("Empty string:"); +dumpStringRepresentation(""); + +print("\nResult of coercion to string:"); +dumpStringRepresentation(); + +print("\nString with an index value:"); +dumpStringRepresentation((12345).toString()); + +print("\ns = Simple short atom:"); +var s = "xxxxxxxx"; +dumpStringRepresentation(s); + +// Simple non-atom flat. +print("\ns + s: Non-atom flat:"); +var s2 = s + s; +dumpStringRepresentation(s2); + +print("\nNon-Latin1 flat:"); +var j = "渋谷区"; +dumpStringRepresentation(j); + +print("\nt = Non-inline atom:"); +var t = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // 31 characters +dumpStringRepresentation(t); + +print("\nr1 = t + s: Simple rope:"); +var r1 = t + s; +dumpStringRepresentation(r1); + +// Flatten that rope, and re-examine the representations of both the result and +// its former leaves. This should be an extensible string. +print("\nr1, former rope after flattening, now extensible:"); +r1.match(/x/); +dumpStringRepresentation(r1); + +print("\nt, s: Original leaves, representation unchanged:"); +dumpStringRepresentation(t); +dumpStringRepresentation(s); + +// Create a new rope with the extensible string as its left child. +print("\nr2 = r1 + s: Rope with extensible leftmost child:"); +var r2 = r1 + s; +dumpStringRepresentation(r2); + +// Flatten that; this should re-use the extensible string's buffer. +print("\nr2: flattened, stole r1's buffer:"); +r2.match(/x/); +dumpStringRepresentation(r2); + +print("\nr1: mutated into a dependent string:"); +dumpStringRepresentation(r1); + +print("\nr3 = r2 + s: a new rope with an extensible leftmost child:"); +r3 = r2 + s; +r3.match(/x/); +dumpStringRepresentation(r3); + +print("\nr2: now mutated into a dependent string"); +dumpStringRepresentation(r2); + +print("\nr1: now a doubly-dependent string, because of r2's mutation:"); +dumpStringRepresentation(r1); + +print("\nt, s: Original leaves, representation unchanged:"); +dumpStringRepresentation(t); +dumpStringRepresentation(s); + +// Extensible string, created directly. +print("\nExtensible:"); +var e = newString("一二三四五六七八九*一二三四五六七八", { capacity: 80 }); +dumpStringRepresentation(e); + +// Reuse an extensible string's storage when flattening a rope whose DAG contains +// the extensible string multiple times. +print("\nFlattened dag with shared leaves:"); +var e_flat = newRope(e, newRope(e, "!")); +ensureLinearString(e_flat); +dumpStringRepresentation(e_flat); +assertEq(e_flat.charAt(e.length), e_flat.charAt(0)); + +for (var str of representativeStringArray()) + dumpStringRepresentation(str); diff --git a/js/src/jit-test/tests/basic/dumpValue.js b/js/src/jit-test/tests/basic/dumpValue.js new file mode 100644 index 0000000000..6bf4ffcb8d --- /dev/null +++ b/js/src/jit-test/tests/basic/dumpValue.js @@ -0,0 +1,134 @@ +// |jit-test| skip-if: typeof dumpValue !== 'function' || getBuildConfiguration("windows") + +// FIXME: Fix backslash handling on windows (bug 1880003). + +// Try the dumpValue and dumpValueToString shell functions on various types of +// values, and make sure theyit don't crash, and the result is valid JSON. + +function testDump(v) { + dumpValue(v); + + const s = dumpValueToString(v); + + const result = JSON.parse(s); + assertEq(typeof result, "object"); + assertEq(typeof result.type, "string"); +} + + +testDump(1); +testDump(1.1); +testDump(-0.1); + +testDump(100n); + +testDump(true); +testDump(false); + +testDump(null); + +testDump(undefined); + +// dumpStringRepresentation.js covers more strings. +testDump("foo"); + +testDump(/foo/ig); + +testDump(Symbol.iterator); +testDump(Symbol("hello")); +testDump(Symbol.for("hello")); + +testDump({}); +testDump({ prop1: 10, prop2: 20 }); + +testDump([]); +testDump([1, , 3, 4]); + +testDump(function f() {}); +testDump(function* f() {}); +testDump(async function f() {}); +testDump(async function* f() {}); + +testDump(Promise.withResolvers()); + +var p1 = new Promise(() => {}); p1.then(() => {}); +testDump(p1); +var p2 = new Promise(() => {}); p2.then(() => {}); p2.then(() => {}); +testDump(p2); +var p3 = Promise.reject(10).catch(() => {}); +testDump(p3); + +testDump(new ArrayBuffer([1, 2, 3])); +testDump(new Int8Array([1, 2, 3])); +testDump(new Int8Array(new Int8Array([1, 2, 3]).buffer, 1)); +testDump(new Int32Array([1, 2, 3])); +testDump(new Int32Array(new Int32Array([1, 2, 3]).buffer, 4)); +testDump(new Float64Array([1, 2, 3])); + +testDump(new Date()); +testDump(new Map([[1, 2]])); +testDump(new Set([1, 2])); +testDump(new WeakMap([ [{}, 10], [{}, 20] ])); +testDump(new WeakSet([{}, {}])); +testDump(new Proxy({}, {})); + +testDump(Array); +testDump(Array.prototype); +testDump(this); + +testDump([ + 1, + 1.1, + -0.1, + + 100n, + + true, + false, + + null, + + undefined, + + "foo", + + /foo/ig, + + Symbol.iterator, + Symbol("hello"), + Symbol.for("hello"), + + {}, + { prop1: 10, prop2: 20 }, + + [], + [1, , 3, 4], + + function f() {}, + function* f() {}, + async function f() {}, + async function* f() {}, + + Promise.withResolvers(), + p1, + p2, + p3, + + new ArrayBuffer([1, 2, 3]), + new Int8Array([1, 2, 3]), + new Int8Array(new Int8Array([1, 2, 3]).buffer, 1), + new Int32Array([1, 2, 3]), + new Int32Array(new Int32Array([1, 2, 3]).buffer, 4), + new Float64Array([1, 2, 3]), + new Float64Array([1, 2, 3]), + + new Map([[1, 2]]), + new Set([1, 2]), + new WeakMap([ [{}, 10], [{}, 20] ]), + new WeakSet([{}, {}]), + new Proxy({}, {}), + + Array, + Array.prototype, + this, +]); diff --git a/js/src/jit-test/tests/basic/eif-generator.js b/js/src/jit-test/tests/basic/eif-generator.js new file mode 100644 index 0000000000..afd6e427f0 --- /dev/null +++ b/js/src/jit-test/tests/basic/eif-generator.js @@ -0,0 +1,58 @@ +load(libdir + "evalInFrame.js"); + +function* f() { + { + let x = 1; + while (true) { + yield evalInFrame(0, "x"); + x++; + { + let y = 1; + yield evalInFrame(0, "++y"); + yield evalInFrame(0, "++y"); + } + } + } +} + +var gen = f(); +assertEq(gen.next().value, 1); +assertEq(gen.next().value, 2); +gc(); +assertEq(gen.next().value, 3); +gc(); +assertEq(gen.next().value, 2); +assertEq(gen.next().value, 2); +gc(); +assertEq(gen.next().value, 3); +gc(); +assertEq(gen.next().value, 3); +assertEq(gen.next().value, 2); +gc(); +assertEq(gen.next().value, 3); +gen = null; +gc(); + +function* g() { + { + let x = 1; + while (true) { + var inner = function (inc) { x += inc; return evalInFrame(0, "x") }; + assertEq(inner(0), x); + yield inner; + assertEq(inner(0), x); + } + } +} + +var gen = g(); +var g1 = gen.next().value; +var g2 = gen.next().value; +gc(); +assertEq(g1(1), 2); +assertEq(g2(1), 3); +gc(); +assertEq(g1(1), 4); +assertEq(g2(1), 5); +gen = g1 = g2 = null; +gc(); diff --git a/js/src/jit-test/tests/basic/emulates-undefined.js b/js/src/jit-test/tests/basic/emulates-undefined.js new file mode 100644 index 0000000000..3e379d8746 --- /dev/null +++ b/js/src/jit-test/tests/basic/emulates-undefined.js @@ -0,0 +1,18 @@ +function test() { + var values = [undefined, null, Math, createIsHTMLDDA()]; + var expected = [true, true, false, true]; + + for (var i=0; i<100; i++) { + var idx = i % values.length; + if (values[idx] == undefined) + assertEq(expected[idx], true); + else + assertEq(expected[idx], false); + + if (null != values[idx]) + assertEq(expected[idx], false); + else + assertEq(expected[idx], true); + } +} +test(); diff --git a/js/src/jit-test/tests/basic/equalInt.js b/js/src/jit-test/tests/basic/equalInt.js new file mode 100644 index 0000000000..d63c8815db --- /dev/null +++ b/js/src/jit-test/tests/basic/equalInt.js @@ -0,0 +1,29 @@ +function equalInt() +{ + var i1 = 55, one = 1, zero = 0, undef; + var o1 = { }, o2 = { }; + var s = "5"; + var hits = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; + for (var i = 0; i < 5000; i++) { + if (i1 == 55) hits[0]++; + if (i1 != 56) hits[1]++; + if (i1 < 56) hits[2]++; + if (i1 > 50) hits[3]++; + if (i1 <= 60) hits[4]++; + if (i1 >= 30) hits[5]++; + if (i1 == 7) hits[6]++; + if (i1 != 55) hits[7]++; + if (i1 < 30) hits[8]++; + if (i1 > 90) hits[9]++; + if (i1 <= 40) hits[10]++; + if (i1 >= 70) hits[11]++; + if (o1 == o2) hits[12]++; + if (o2 != null) hits[13]++; + if (s < 10) hits[14]++; + if (true < zero) hits[15]++; + if (undef > one) hits[16]++; + if (undef < zero) hits[17]++; + } + return hits.toString(); +} +assertEq(equalInt(), "5000,5000,5000,5000,5000,5000,0,0,0,0,0,0,0,5000,5000,0,0,0"); diff --git a/js/src/jit-test/tests/basic/error-stack-accessors.js b/js/src/jit-test/tests/basic/error-stack-accessors.js new file mode 100644 index 0000000000..9bbcae14ba --- /dev/null +++ b/js/src/jit-test/tests/basic/error-stack-accessors.js @@ -0,0 +1,31 @@ +// Test the Error.prototype.stack getter/setter with various "fun" edge cases. + +load(libdir + "asserts.js"); + +// Stack should be accessible in subclasses. The accessor should walk up the +// prototype chain. +assertEq(typeof Object.create(Error()).stack, "string"); +assertEq(Object.create(Error.prototype).stack, ""); + +// Stack should be overridable in subclasses. +{ + let myError = Object.create(Error()); + myError.stack = 5; + assertEq(myError.stack, 5); + + let myOtherError = Object.create(Error.prototype); + myOtherError.stack = 2; + assertEq(myOtherError.stack, 2); +} + +// Should throw when there is no Error in the `this` object's prototype chain. +var obj = Object.create(null); +var desc = Object.getOwnPropertyDescriptor(Error.prototype, "stack"); +Object.defineProperty(obj, "stack", desc); +assertThrowsInstanceOf(() => obj.stack, TypeError); + +// Should throw with non-object `this` values. +assertThrowsInstanceOf(desc.set, TypeError); +assertThrowsInstanceOf(desc.set.bind("string"), TypeError); +assertThrowsInstanceOf(desc.get, TypeError); +assertThrowsInstanceOf(desc.get.bind("string"), TypeError); diff --git a/js/src/jit-test/tests/basic/error-toString.js b/js/src/jit-test/tests/basic/error-toString.js new file mode 100644 index 0000000000..44839333d9 --- /dev/null +++ b/js/src/jit-test/tests/basic/error-toString.js @@ -0,0 +1,9 @@ +var errorToString = Error.prototype.toString; + + +assertEq(errorToString.call({message: "", name: ""}), ""); +assertEq(errorToString.call({name: undefined, message: ""}), "Error"); +assertEq(errorToString.call({name: "Test", message: undefined}), "Test"); +assertEq(errorToString.call({name: "Test", message: ""}), "Test"); +assertEq(errorToString.call({name: "", message: "Test"}), "Test"); +assertEq(errorToString.call({name: "Test", message: "it!"}), "Test: it!"); diff --git a/js/src/jit-test/tests/basic/eval-introduction-principals.js b/js/src/jit-test/tests/basic/eval-introduction-principals.js new file mode 100644 index 0000000000..25eb1bea82 --- /dev/null +++ b/js/src/jit-test/tests/basic/eval-introduction-principals.js @@ -0,0 +1,16 @@ +// Ensure the introduction info for eval scripts respects principal checks. + +function myAPI(f) { return f(); } + +var contentGlobal = newGlobal({principal: 0x1}); +contentGlobal.chrome = this; +contentGlobal.eval("\n" + + "function contentTest() { chrome.myAPI(eval.bind(undefined, 'chrome.stack = Error().stack;')) };\n" + + "contentTest();"); + +// Note that the stack below does not include the current filename or file +// line numbers, and there's no trace of the myAPI call between the two +// evals. +assertEq(stack, "@eval line 2 > eval:1:16\n" + + "contentTest@eval:2:33\n" + + "@eval:3:1\n"); diff --git a/js/src/jit-test/tests/basic/eval-json-differences.js b/js/src/jit-test/tests/basic/eval-json-differences.js new file mode 100644 index 0000000000..eb7ff3389b --- /dev/null +++ b/js/src/jit-test/tests/basic/eval-json-differences.js @@ -0,0 +1,25 @@ +load(libdir + "asserts.js"); + +// eval({__proto__}) changes [[Prototype]] +var obj = eval('({"__proto__": null})'); +assertEq(Object.getPrototypeOf(obj), null); +assertEq(Object.prototype.hasOwnProperty.call(obj, "__proto__"), false); + +// JSON.parse({__proto__}) creates new property __proto__ +obj = JSON.parse('{"__proto__": null}'); +assertEq(Object.getPrototypeOf(obj), Object.prototype); +assertEq(Object.prototype.hasOwnProperty.call(obj, "__proto__"), true); + +// If __proto__ appears more than once as quoted or unquoted property name in an +// object initializer expression, that's an error. +//(No other property name has this restriction.)" +assertThrowsInstanceOf(() => + eval('({ "__proto__" : null, "__proto__" : null })'), SyntaxError); + +assertThrowsInstanceOf(() => + eval(' ({ "__proto__" : null, "__proto__" : null })'), SyntaxError); + +// JSON.parse doesn't care about duplication, the last definition counts. +obj = JSON.parse('{"__proto__": null, "__proto__": 5}'); +assertEq(Object.getPrototypeOf(obj), Object.prototype); +assertEq(obj["__proto__"], 5); diff --git a/js/src/jit-test/tests/basic/eval-scopes.js b/js/src/jit-test/tests/basic/eval-scopes.js new file mode 100644 index 0000000000..695adb8a79 --- /dev/null +++ b/js/src/jit-test/tests/basic/eval-scopes.js @@ -0,0 +1,74 @@ +function bytecode(f) { + if (typeof disassemble !== "function") + return "unavailable"; + var d = disassemble(f); + return d.slice(d.indexOf("main:"), d.indexOf("\n\n")); +} + +function hasGname(f, v, hasIt = true) { + // Do a try-catch that prints the full stack, so we can tell + // _which_ part of this test failed. + try { + var b = bytecode(f); + if (b != "unavailable") { + assertEq(b.includes(`GetGName "${v}"`), hasIt); + assertEq(b.includes(`GetName "${v}"`), !hasIt); + } + } catch (e) { + print(e.stack); + throw e; + } +} + +var x = "outer"; + +{ + let x = "inner"; + eval("function h() { assertEq(x, 'inner');} h()"); + eval("function h2() { (function nest() { assertEq(x, 'inner'); })(); } h2()"); +} + +// GNAME optimizations should work through lazy parsing. +eval(` + function h3() { + assertEq(x, 'outer'); + } + h3(); + hasGname(h3, 'x', true); + `); +eval(` + function h4() { + function nest() { assertEq(x, 'outer'); } + nest(); + return nest; + } + hasGname(h4(), 'x', true); + `); + +with ({}) { + let x = "inner"; + eval("function j() { assertEq(x, 'inner');} j()"); + eval("function j2() { (function nest() { assertEq(x, 'inner'); })(); } j2()"); +} + +(function () { + let x = "inner"; + eval("function l() { assertEq(x, 'inner');} l()"); + eval("function l2() { (function nest() { assertEq(x, 'inner'); })(); } l2()"); +})(); + +var y1 = 5; +eval(` + 'use strict'; + var y1 = 6; + assertEq(y1, 6); + (function() { assertEq(y1, 6); })() + `); +assertEq(y1, 5); + +eval(` + 'use strict'; + var y2 = 6; + assertEq(y2, 6); + (function() { assertEq(y2, 6); })() + `); diff --git a/js/src/jit-test/tests/basic/evalInWorker-interrupt.js b/js/src/jit-test/tests/basic/evalInWorker-interrupt.js new file mode 100644 index 0000000000..acd09f0077 --- /dev/null +++ b/js/src/jit-test/tests/basic/evalInWorker-interrupt.js @@ -0,0 +1,2 @@ +// |jit-test| skip-if: helperThreadCount() === 0 +evalInWorker("setInterruptCallback(function() {}); timeout(1000);"); diff --git a/js/src/jit-test/tests/basic/evalInWorker-jit-options.js b/js/src/jit-test/tests/basic/evalInWorker-jit-options.js new file mode 100644 index 0000000000..24c624539f --- /dev/null +++ b/js/src/jit-test/tests/basic/evalInWorker-jit-options.js @@ -0,0 +1,11 @@ +// |jit-test| skip-if: helperThreadCount() === 0 +var fun = function() { + var ex; + try { + setJitCompilerOption("baseline.warmup.trigger", 5); + } catch(e) { + ex = e; + } + assertEq(ex && ex.toString().includes("Can't set"), true); +} +evalInWorker("(" + fun.toString() + ")()"); diff --git a/js/src/jit-test/tests/basic/evalInWorker-nested.js b/js/src/jit-test/tests/basic/evalInWorker-nested.js new file mode 100644 index 0000000000..1ae4805038 --- /dev/null +++ b/js/src/jit-test/tests/basic/evalInWorker-nested.js @@ -0,0 +1,5 @@ +try { + evalInWorker("evalInWorker('evalInWorker(\"assertEq(1, 1)\")')"); +} catch(e) { + assertEq(e.toString().includes("--no-threads"), true); +} diff --git a/js/src/jit-test/tests/basic/evalInWorker-stack-limit.js b/js/src/jit-test/tests/basic/evalInWorker-stack-limit.js new file mode 100644 index 0000000000..c1a1f472f1 --- /dev/null +++ b/js/src/jit-test/tests/basic/evalInWorker-stack-limit.js @@ -0,0 +1,8 @@ +try { + evalInWorker(` + function f() { f(); } + try { f(); } catch(e) {} + `); +} catch(e) { + assertEq(e.toString().includes("--no-threads"), true); +} diff --git a/js/src/jit-test/tests/basic/evalReturningScope-global.js b/js/src/jit-test/tests/basic/evalReturningScope-global.js new file mode 100644 index 0000000000..e8411b59f2 --- /dev/null +++ b/js/src/jit-test/tests/basic/evalReturningScope-global.js @@ -0,0 +1,14 @@ +// Passing global with discardSource shouldn't crash. + +const g = newGlobal({ + discardSource: true +}); + +evalReturningScope(` +var f = function(){ + var g = function(){ + }; + g(); +}; +f(); +`, g); diff --git a/js/src/jit-test/tests/basic/evaluate-catchTermination.js b/js/src/jit-test/tests/basic/evaluate-catchTermination.js new file mode 100644 index 0000000000..6a9d3c74a7 --- /dev/null +++ b/js/src/jit-test/tests/basic/evaluate-catchTermination.js @@ -0,0 +1,6 @@ +// Test evaluate's catchTermination option. + +var x = 0; +assertEq(evaluate('x = 1; terminate(); x = 2;', { catchTermination: true }), + "terminated"); +assertEq(x, 1); diff --git a/js/src/jit-test/tests/basic/evaluate-global-debuggee.js b/js/src/jit-test/tests/basic/evaluate-global-debuggee.js new file mode 100644 index 0000000000..cdc88bafb5 --- /dev/null +++ b/js/src/jit-test/tests/basic/evaluate-global-debuggee.js @@ -0,0 +1,5 @@ +var a = newGlobal({ newCompartment: true }); +Debugger(a); +evaluate("function h() { 'use asm'; return {}}", { + global: a +}); diff --git a/js/src/jit-test/tests/basic/evaluate-global-discardSource.js b/js/src/jit-test/tests/basic/evaluate-global-discardSource.js new file mode 100644 index 0000000000..9bacbacbab --- /dev/null +++ b/js/src/jit-test/tests/basic/evaluate-global-discardSource.js @@ -0,0 +1,11 @@ +load(libdir + "asserts.js"); + +let g = newGlobal({newCompartment: true}); + +let g_discardSource = newGlobal({ + discardSource: true, +}); + +g.evaluate("function f() { (function(){})(); }; f();", { + global: g_discardSource, +}); diff --git a/js/src/jit-test/tests/basic/evaluate-negative-column.js b/js/src/jit-test/tests/basic/evaluate-negative-column.js new file mode 100644 index 0000000000..c86bd20447 --- /dev/null +++ b/js/src/jit-test/tests/basic/evaluate-negative-column.js @@ -0,0 +1,3 @@ +// Negative column number should be handled as the first column. +const column = evaluate("new Error().columnNumber;", { columnNumber: -1 }); +assertEq(column, 1); diff --git a/js/src/jit-test/tests/basic/evaluate-restore-options.js b/js/src/jit-test/tests/basic/evaluate-restore-options.js new file mode 100644 index 0000000000..263cc7272a --- /dev/null +++ b/js/src/jit-test/tests/basic/evaluate-restore-options.js @@ -0,0 +1,11 @@ +// Bug 791157: the shell 'evaluate' function should properly restore the +// context's options. + +try { + evaluate('%', {noScriptRval: true}); +} catch(e) {} +new Function(""); + +try { + evaluate('new Function("");', {noScriptRval: true}); +} catch (e) {} diff --git a/js/src/jit-test/tests/basic/evaluate-worker.js b/js/src/jit-test/tests/basic/evaluate-worker.js new file mode 100644 index 0000000000..a382ee339d --- /dev/null +++ b/js/src/jit-test/tests/basic/evaluate-worker.js @@ -0,0 +1,19 @@ +// |jit-test| slow; skip-if: typeof evalInWorker === 'undefined' || helperThreadCount() === 0 + +gcslice(11); +evalInWorker("print('helo world');"); +for (i = 0; i < 100000; i++) {} + +evalInWorker("\ + for (var i = 0; i < 10; i++) { \ + var o = {}; \ + for (var j = 0; j < 100; j++) \ + o['a' + j] = j; \ + JSON.stringify(o); \ + o = null; \ + gc(); \ +}"); +for (var i = 0; i < 10; i++) { + gc(); + for (var j = 0; j < 100000; j++) {} +} diff --git a/js/src/jit-test/tests/basic/exception-column-number.js b/js/src/jit-test/tests/basic/exception-column-number.js new file mode 100644 index 0000000000..1df01b4848 --- /dev/null +++ b/js/src/jit-test/tests/basic/exception-column-number.js @@ -0,0 +1,11 @@ +try { + Array.from(); +} catch (e) { + assertEq(e.columnNumber, 11); + // Filter the filename from the stack, since we have no clue what + // to expect there. Search for ':' from the end, because the file + // path may contain ':' in it. + var lastColon = e.stack.lastIndexOf(':'); + var afterPath = e.stack.lastIndexOf(':', lastColon - 1); + assertEq(e.stack.substring(afterPath), ":2:11\n"); +} diff --git a/js/src/jit-test/tests/basic/expr-decompiler-bug1475953.js b/js/src/jit-test/tests/basic/expr-decompiler-bug1475953.js new file mode 100644 index 0000000000..5b1b93b75e --- /dev/null +++ b/js/src/jit-test/tests/basic/expr-decompiler-bug1475953.js @@ -0,0 +1,35 @@ +Object.defineProperty(this, "fuzzutils", { value:{} }); +try { evaluate(` + var f = 396684; + var src = "return f(" +Array(10*1000).join("0,")+"Math.atan2());"; + var result = new Function(src)(); +`); +} catch (exc) {} +try { + evalInWorker(` + function lfEvalInCache(lfCode, lfIncremental = false, lfRunOnce = false) { + ctx = Object.create(ctx, {}); + } + try { evaluate(\` + var f = 396684; + var src = "return f(" +Array(10*1000).join("0,")+"Math.atan2());"; + var result = new Function(src)(); + \`); } catch(exc) {} + `); + evalInWorker(` + Object.defineProperty(this, "fuzzutils", { value:{} }); + try { evaluate(\` + var f = 396684; + var src = "return f(" +Array(10*1000).join("0,")+"Math.atan2());"; + var result = new Function(src)(); + \`); } catch(exc) {} + `); +} catch (exc) {} +try { evalInWorker(` + try { evaluate(\` + var f = 396684; + var src = "return f(" +Array(10*1000).join("0,")+"Math.atan2());"; + var result = new Function(src)(); + \`); } catch(exc) {} +`); +} catch (exc) {} diff --git a/js/src/jit-test/tests/basic/expression-autopsy.js b/js/src/jit-test/tests/basic/expression-autopsy.js new file mode 100644 index 0000000000..a5c4801719 --- /dev/null +++ b/js/src/jit-test/tests/basic/expression-autopsy.js @@ -0,0 +1,287 @@ +// |jit-test| skip-if: getBuildConfiguration('pbl') +load(libdir + "asserts.js"); +load(libdir + "iteration.js"); + +function check_one(expected, f, err) { + var failed = true; + try { + f(); + failed = false; + } catch (ex) { + assertEq(ex.constructor.name, "TypeError"); + var s = ex.message; + assertEq(s.slice(-err.length), err); + assertEq(s.slice(-(err.length + expected.length), -err.length), expected); + } + if (!failed) + throw new Error("didn't fail"); +} +ieval = eval; +function check(expr, expected=expr, testStrict=true) { + var end, err; + for ([end, err] of [[".random_prop", " is undefined"], ["()", " is not a function"]]) { + var statement = "o = {};" + expr + end, f; + var cases = [ + // Global scope + function () { + ieval("var o, undef;\n" + statement); + }, + // Function scope + Function("o", "undef", statement), + // Function scope with variables + Function("var o, undef;\n" + statement), + // Function scope with some different arugments + Function("arg1", "arg2", "var o, undef;\n" + statement), + // Deoptimized function scope + Function("o", "undef", "with (Object) {}\n" + statement), + // Inside with + Function("with (Object) { " + statement + " }"), + // Closure + Function("o", "undef", "function myfunc() { return o + undef; }\n" + statement), + // Let definitions in a block + Function("{ let o, undef;\n" + statement + "}"), + // Let in a switch + Function("var x = 4; switch (x) { case 4: let o, undef;" + statement + "\ncase 6: break;}"), + // Try-catch blocks + Function("o", "undef", "try { let q = 4; try { let p = 4; } catch (e) {} } catch (e) {} { let o, undef; " + statement + " }"), + // Let in for-in (uses with to prevent jit compilation: bug 942804, bug 831120 and bug 1041586) + Function("with ({}) {} var undef, o; for (let z in [1, 2]) { " + statement + " }"), + ]; + + if (testStrict) { + // Strict mode. + cases.push(Function("o", "undef", "\"use strict\";\n" + statement)); + } + + for (var f of cases) { + check_one(expected, f, err); + } + } +} + +check("undef"); +check("o.b"); +check("o.length"); +check("o[true]"); +check("o[false]"); +check("o[null]"); +check("o[0]"); +check("o[1]"); +check("o[3]"); +check("o[256]"); +check("o[65536]"); +check("o[268435455]"); +check("o['1.1']"); +check("o[4 + 'h']", "o['4h']"); +check("ieval(undef)", "ieval(...)"); +check("ieval.call()", "ieval.call()"); +check("ieval(...[])", "ieval(...)"); +check("ieval(...[undef])", "ieval(...)"); +check("ieval(...[undef, undef])", "ieval(...)"); +check("(o[0] = 4).foo", "o[0].foo"); +// NOTE: This one produces different output in strict mode since "this" is +// undefined in that case. +check("this.x", "this.x", false); + +for (let tok of ["|", "^", "&", "==", "!==", "===", "!==", "<", "<=", ">", ">=", + ">>", "<<", ">>>", "+", "-", "*", "/", "%"]) { + check("o[(undef " + tok + " 4)]"); +} + +check("o[(!o)]"); +check("o[(~o)]"); +check("o[(+ o)]"); +check("o[(- o)]"); + +check("o[(!(o + 1))]"); +check("o[(~(o + 1))]"); +check("o[(+ (o + 1))]"); +check("o[(- (o + 1))]"); + +// A few one off tests +check_one("6", (function () { 6() }), " is not a function"); +check_one("4", (function() { (4||eval)(); }), " is not a function"); +check_one("0", (function () { Array.prototype.reverse.call('123'); }), " is read-only"); +check_one("[...][Symbol.iterator]().next().value", + function () { ieval("{ let x; var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined"); +check_one("(void 1)", function() { (void 1)(); }, " is not a function"); +check_one("(void o[1])", function() { var o = []; (void o[1])() }, " is not a function"); + +check_one("(typeof 1)", function() { (typeof 1)(); }, " is not a function"); +check_one("(typeof o[1])", function() { var o = []; (typeof o[1])() }, " is not a function"); + +check_one("(delete foo)", + function() { (delete foo)(); }, + " is not a function"); +check_one("(delete obj.foo)", + function() { var obj = {}; (delete obj.foo)(); }, + " is not a function"); +check_one("(delete obj.foo)", + function() { "use strict"; var obj = {}; (delete obj.foo)(); }, + " is not a function"); +check_one("(delete obj[y])", + function() { var obj = {}, y = {}; (delete obj[y])(); }, + " is not a function"); +check_one("(delete obj[y])", + function() { "use strict"; var obj = {}, y = {}; (delete obj[y])(); }, + " is not a function"); + +check_one("foo.apply()", + function() { function foo() {} foo.apply()(); }, + " is not a function"); + +check_one("super()", + function() { + class X extends Object { + constructor() { + super()(); + } + } + new X(); + }, + " is not a function"); +check_one("super(...)", + function() { + class X extends Object { + constructor() { + super(...[])(); + } + } + new X(); + }, + " is not a function"); + +check_one("super.a", + function() { + class X extends Object { + test() { + super.a(); + } + } + var x = new X(); + x.test(); + }, + " is not a function"); + +check_one("super[a]", + function() { + var a = "a"; + class X extends Object { + test() { + super[a](); + } + } + var x = new X(); + x.test(); + }, + " is not a function"); + +check_one("super.a()", + function() { + class Y { + a() { + return 5; + } + } + + class X extends Y { + test() { + super.a()(); + } + } + + var x = new X(); + x.test(); + }, + " is not a function"); + +check_one("super[a]()", + function() { + class Y { + a() { + return 5; + } + } + + var a = "a"; + class X extends Y { + test() { + super[a]()(); + } + } + + var x = new X(); + x.test(); + }, + " is not a function"); + +check_one("super[1]", + function() { + class X extends Object { + foo() { + return super[1](); + } + } + new X().foo(); + }, + " is not a function"); + +check_one("eval(...)", + function() { eval("")(); }, + " is not a function"); +check_one("eval(...)", + function() { "use strict"; eval("")(); }, + " is not a function"); +check_one("eval(...)", + function() { eval(...[""])(); }, + " is not a function"); +check_one("eval(...)", + function() { "use strict"; eval(...[""])(); }, + " is not a function"); + +check_one("(new foo())", + function() { function foo() {}; new foo()(); }, + " is not a function"); +check_one("(new foo(...))", + function() { function foo() {}; new foo(...[])(); }, + " is not a function"); +check_one("(new foo.x())", + function() { var foo = { x: function() {} }; new foo.x()(); }, + " is not a function"); +check_one("(new foo.x(...))", + function() { var foo = { x: function() {} }; new foo.x(...[])(); }, + " is not a function"); + +check_one("[...].foo", + function() { [undefined].foo(); }, + " is not a function"); +check_one("[...].foo", + function() { [undefined, ...[]].foo(); }, + " is not a function"); + +check_one("[...][Symbol.iterator]().next().value", + function () { var [{x}] = [null, {}]; }, " is null"); +check_one("[...][Symbol.iterator]().next().value", + function () { var [{x}] = [void 0, {}]; }, " is undefined"); + +check_one("(a += b)", + function() { var a, b; (a += b)(); }, + " is not a function"); + +try { + (function() { + "use strict"; + var o = []; + Object.freeze(o); + o[0] = "foo"; + }()); + throw new Error("didn't throw"); +} catch (e) { + assertEq(e instanceof TypeError, true, + "expected TypeError, got " + e); + assertEq(e.message, + "can't define array index property past the end of an array with non-writable length"); +} + +// Check fallback behavior +assertThrowsInstanceOf(function () { for (let x of undefined) {} }, TypeError); diff --git a/js/src/jit-test/tests/basic/external-strings-cgc.js b/js/src/jit-test/tests/basic/external-strings-cgc.js new file mode 100644 index 0000000000..aa64172122 --- /dev/null +++ b/js/src/jit-test/tests/basic/external-strings-cgc.js @@ -0,0 +1,7 @@ +gczeal(0); +startgc(1, "shrinking"); +for (var i=0; i<100; i++) { + gcslice(100000); + var s = "abcdefghi0"; + assertEq(newString(s, {maybeExternal: true}), s); +} diff --git a/js/src/jit-test/tests/basic/external-strings.js b/js/src/jit-test/tests/basic/external-strings.js new file mode 100644 index 0000000000..fd5faa27ef --- /dev/null +++ b/js/src/jit-test/tests/basic/external-strings.js @@ -0,0 +1,48 @@ +assertEq(newString("", {external: true}), ""); +assertEq(newString("abc", {external: true}), "abc"); +assertEq(newString("abc\0def\u1234", {external: true}), "abc\0def\u1234"); + +var o = {foo: 2, "foo\0": 4}; +var ext = newString("foo", {external: true}); +assertEq(o[ext], 2); +var ext2 = newString("foo\0", {external: true}); +assertEq(o[ext2], 4); + +eval(newString("assertEq(1, 1)", {external: true})); + +// Make sure ensureLinearString does the right thing for external strings. +ext = newString("abc\0defg\0", {external: true}); +assertEq(ensureLinearString(ext), "abc\0defg\0"); +assertEq(ensureLinearString(ext), "abc\0defg\0"); + +for (var s of representativeStringArray()) + assertEq(ensureLinearString(s), s); + +for (var s of representativeStringArray()) + assertEq(newString(s, {external: true}), s); + +function testQuote() { + for (var data of [["abc", "abc"], + ["abc\t", "abc\\t"], + ["abc\t\t\0", "abc\\t\\t\\x00"], + ["abc\\def", "abc\\\\def"]]) { + try { + assertEq(newString(data[0], {external: true}), false); + } catch(e) { + assertEq(e.toString().includes('got "' + data[1] + '",'), true) + } + } +} +testQuote(); + +function testMaybeExternal() { + for (var i=0; i<10; i++) { + var s = "abcdef4321" + i; + assertEq(newString(s, {maybeExternal: true}), s); + if ((i % 2) === 0) + assertEq(ensureLinearString(newString(s, {maybeExternal: true})), s); + } +} +testMaybeExternal(); +gc(); +testMaybeExternal(); diff --git a/js/src/jit-test/tests/basic/fannkuch.js b/js/src/jit-test/tests/basic/fannkuch.js new file mode 100644 index 0000000000..a6154f2dfa --- /dev/null +++ b/js/src/jit-test/tests/basic/fannkuch.js @@ -0,0 +1,17 @@ +function fannkuch() { + var count = Array(8); + var r = 8; + var done = 0; + while (done < 40) { + // write-out the first 30 permutations + done += r; + while (r != 1) { count[r - 1] = r; r--; } + while (true) { + count[r] = count[r] - 1; + if (count[r] > 0) break; + r++; + } + } + return done; +} +assertEq(fannkuch(), 41); diff --git a/js/src/jit-test/tests/basic/fdlibm-for-sin-cos-tan-argument.js b/js/src/jit-test/tests/basic/fdlibm-for-sin-cos-tan-argument.js new file mode 100644 index 0000000000..e46a8259bc --- /dev/null +++ b/js/src/jit-test/tests/basic/fdlibm-for-sin-cos-tan-argument.js @@ -0,0 +1,7 @@ +// |jit-test| --use-fdlibm-for-sin-cos-tan +// Test that fdlibm is being used for sin, cos, and tan. + +// Tests adapted from https://github.com/arkenfox/TZP/blob/master/tests/math.html#L158-L319 +assertEq(Math.cos(1e284), 0.7086865671674247); +assertEq(Math.sin(7*Math.LOG10E), 0.10135692924965616); +assertEq(Math.tan(6*Math.E), 0.6866761546452431); diff --git a/js/src/jit-test/tests/basic/finally-implicit-return.js b/js/src/jit-test/tests/basic/finally-implicit-return.js new file mode 100644 index 0000000000..3bbd78d380 --- /dev/null +++ b/js/src/jit-test/tests/basic/finally-implicit-return.js @@ -0,0 +1,45 @@ +// Implicit return at the end of a function should return |undefined|, +// even if we initially set another return value and then executed a finally +// block. + +function test1() { + try { + try { + return 3; + } finally { + throw 4; + } + } catch (e) {} +} +assertEq(test1(), undefined); + +function test2() { + L: try { + return 3; + } finally { + break L; + } +} +assertEq(test2(), undefined); + +function test3() { + for (var i=0; i<2; i++) { + try { + return 5; + } finally { + continue; + } + } +} +assertEq(test3(), undefined); + +// "return;" should work the same way. +function test4() { + L: try { + return 6; + } finally { + break L; + } + return; +} +assertEq(test4(), undefined); diff --git a/js/src/jit-test/tests/basic/firstSlotConflict.js b/js/src/jit-test/tests/basic/firstSlotConflict.js new file mode 100644 index 0000000000..fe6ef51c7c --- /dev/null +++ b/js/src/jit-test/tests/basic/firstSlotConflict.js @@ -0,0 +1,10 @@ +(function(x) { + function f1() { return 1; } + function f2() { return 2; } + function f3() { return 3; } + function f4() { return 4; } + var g = function () { return x; } + var a = [f1, f2, f3, f4, g]; + for (var v of a) + v.adhoc = 42; // Don't assertbotch in jsbuiltins.cpp setting g.adhoc +})(33); diff --git a/js/src/jit-test/tests/basic/folding-bug767660.js b/js/src/jit-test/tests/basic/folding-bug767660.js new file mode 100644 index 0000000000..7fc8b7c2cb --- /dev/null +++ b/js/src/jit-test/tests/basic/folding-bug767660.js @@ -0,0 +1,2 @@ +var j, w; +if (j && w && w && true) {} diff --git a/js/src/jit-test/tests/basic/for-in-densified-elements.js b/js/src/jit-test/tests/basic/for-in-densified-elements.js new file mode 100644 index 0000000000..4874901f17 --- /dev/null +++ b/js/src/jit-test/tests/basic/for-in-densified-elements.js @@ -0,0 +1,21 @@ +function test() { + // An array with sparse elements... + var arr = []; + arr[10_000] = 1; + arr[10_001] = 1; + + for (var prop in arr) { + assertEq(prop, "10000"); + assertEq(arr.length, 10_002); + + // Densify the elements. + for (var i = 0; i < arr.length; i++) { + arr[i] = 1; + } + + // Delete the last dense element (10001). It should not be visited by the + // active for-in (checked above). + arr.length = 10_001; + } +} +test(); diff --git a/js/src/jit-test/tests/basic/for-in-proto-properties.js b/js/src/jit-test/tests/basic/for-in-proto-properties.js new file mode 100644 index 0000000000..a8f2279c4e --- /dev/null +++ b/js/src/jit-test/tests/basic/for-in-proto-properties.js @@ -0,0 +1,41 @@ +function testNonEnumerableVisited() { + // Non-enumerable properties must still be included in the duplicate-property + // checking. + + var proto1 = Object.create(null); + Object.defineProperty(proto1, "x", {enumerable: true, value: 1}); + + var proto2 = Object.create(proto1); + Object.defineProperty(proto2, "x", {enumerable: false, value: 1}); + + for (var p in proto2) { + throw "Shouldn't enumerate any properties"; + } + + var o = Object.create(proto2); + for (var p in o) { + throw "Shouldn't enumerate any properties"; + } +} +testNonEnumerableVisited(); + +function testEnumerableOnProto() { + var iter = o => { + var props = []; + for (var p in o) { props.push(p); } + return props; + }; + + // Test dense elements on the proto chain are included. + var props = iter(Object.create({0: 1})); + assertEq(JSON.stringify(props), '["0"]'); + + // Test typed array elements on the proto chain are included. + props = iter(Object.create(new Int32Array(2))); + assertEq(JSON.stringify(props), '["0","1"]'); + + // Test sparse elements on the proto chain are included. + props = iter(Object.create({1234567: 1})); + assertEq(JSON.stringify(props), '["1234567"]'); +} +testEnumerableOnProto(); diff --git a/js/src/jit-test/tests/basic/for-in-replace-sparse.js b/js/src/jit-test/tests/basic/for-in-replace-sparse.js new file mode 100644 index 0000000000..2a89ec6679 --- /dev/null +++ b/js/src/jit-test/tests/basic/for-in-replace-sparse.js @@ -0,0 +1,12 @@ +// Array with sparse element (because non-writable). +var arr = []; +Object.defineProperty(arr, 0, {writable: false, configurable: true, enumerable: true, value: 0}); + +for (var p in arr) { + // Replace sparse element with dense element. + assertEq(p, "0"); + delete arr[0]; + arr[0] = 0; + arr[1] = 1; + arr.reverse(); +} diff --git a/js/src/jit-test/tests/basic/forVarInWith.js b/js/src/jit-test/tests/basic/forVarInWith.js new file mode 100644 index 0000000000..593805642d --- /dev/null +++ b/js/src/jit-test/tests/basic/forVarInWith.js @@ -0,0 +1,12 @@ +function forVarInWith() { + function foo() { return {notk:42}; } + function bar() { return {p:1, q:2, r:3, s:4, t:5}; }; + var o = foo(); + var a = []; + with (o) { + for (var k in bar()) + a[a.length] = k; + } + return a.join(""); +} +assertEq(forVarInWith(), "pqrst"); diff --git a/js/src/jit-test/tests/basic/freeze-builtins.js b/js/src/jit-test/tests/basic/freeze-builtins.js new file mode 100644 index 0000000000..086551135a --- /dev/null +++ b/js/src/jit-test/tests/basic/freeze-builtins.js @@ -0,0 +1,37 @@ +var g = newGlobal({freezeBuiltins: true}); + +g.evaluate("" + function checkFrozen(name) { + // Check constructor on the global is non-writable/non-configurable. + let desc = Object.getOwnPropertyDescriptor(this, name); + assertEq(desc.writable, false); + assertEq(desc.configurable, false); + + // Constructor must be frozen. + let ctor = desc.value; + assertEq(Object.isFrozen(ctor), true); + + // Prototype must be sealed. + if (ctor.prototype) { + assertEq(Object.isSealed(ctor.prototype), true); + } +}); + +g.checkFrozen("Object"); +g.checkFrozen("Array"); +g.checkFrozen("Function"); + +g.checkFrozen("ArrayBuffer"); +g.checkFrozen("Int32Array"); +g.checkFrozen("Number"); +g.checkFrozen("String"); +g.checkFrozen("Proxy"); +g.checkFrozen("Promise"); +g.checkFrozen("RegExp"); +g.checkFrozen("Map"); +g.checkFrozen("WeakMap"); +g.checkFrozen("WeakRef"); +g.checkFrozen("Error"); +g.checkFrozen("TypeError"); + +g.checkFrozen("JSON"); +g.checkFrozen("Math"); diff --git a/js/src/jit-test/tests/basic/function-apply-proxy.js b/js/src/jit-test/tests/basic/function-apply-proxy.js new file mode 100644 index 0000000000..9a00fdb3de --- /dev/null +++ b/js/src/jit-test/tests/basic/function-apply-proxy.js @@ -0,0 +1,26 @@ +// fun.apply(null, proxy) should not invoke the proxy's Has trap. + +var proxy = new Proxy({}, { + get: function (target, name, proxy) { + switch (name) { + case "length": + return 2; + case "0": + return 15; + case "1": + return undefined; + default: + assertEq(false, true); + } + }, + has: function (target, name) { + assertEq(false, true); + } +}); +function foo() { + assertEq(arguments.length, 2); + assertEq(arguments[0], 15); + assertEq(1 in arguments, true); + assertEq(arguments[1], undefined); +} +foo.apply(null, proxy); diff --git a/js/src/jit-test/tests/basic/function-bind.js b/js/src/jit-test/tests/basic/function-bind.js new file mode 100644 index 0000000000..7831ef068b --- /dev/null +++ b/js/src/jit-test/tests/basic/function-bind.js @@ -0,0 +1,21 @@ +var A = Array.bind(1, 1, 2); + +var a1; +for (var i = 0; i < 5; i++) + a1 = A(3, 4); + +assertEq(a1.length, 4); +assertEq(a1[0], 1); +assertEq(a1[1], 2); +assertEq(a1[2], 3); +assertEq(a1[3], 4); + +var a2; +for (var i = 0; i < 5; i++) + a2 = new A(3, 4); + +assertEq(a2.length, 4); +assertEq(a2[0], 1); +assertEq(a2[1], 2); +assertEq(a2[2], 3); +assertEq(a2[3], 4); diff --git a/js/src/jit-test/tests/basic/function-cloning-2.js b/js/src/jit-test/tests/basic/function-cloning-2.js new file mode 100644 index 0000000000..755a178e78 --- /dev/null +++ b/js/src/jit-test/tests/basic/function-cloning-2.js @@ -0,0 +1,9 @@ +if (typeof oomAtAllocation === 'object') { + var a = []; + oomAtAllocation(1); + try { + a.forEach(); + } catch (e) { + } + a.forEach(()=>1); +} diff --git a/js/src/jit-test/tests/basic/function-gname.js b/js/src/jit-test/tests/basic/function-gname.js new file mode 100644 index 0000000000..061bb08761 --- /dev/null +++ b/js/src/jit-test/tests/basic/function-gname.js @@ -0,0 +1,34 @@ +function bytecode(f) { + if (typeof disassemble !== "function") + return "unavailable"; + var d = disassemble(f); + return d.slice(d.indexOf("main:"), d.indexOf("\n\n")); +} + +function hasGname(f, v) { + // Do a try-catch that prints the full stack, so we can tell + // _which_ part of this test failed. + try { + var b = bytecode(f); + if (b != "unavailable") { + assertEq(b.includes(`GetGName "${v}"`), true); + assertEq(b.includes(`GetName "${v}"`), false); + } + } catch (e) { + print(e.stack); + throw e; + } +} + +var x = "outer"; + +var f1 = new Function("assertEq(x, 'outer')"); +f1(); +hasGname(f1, 'x'); + +{ + let x = "inner"; + var f3 = new Function("assertEq(x, 'outer')"); + f3(); + hasGname(f3, 'x'); +} diff --git a/js/src/jit-test/tests/basic/function-tosource-bug779694.js b/js/src/jit-test/tests/basic/function-tosource-bug779694.js new file mode 100644 index 0000000000..782b2594bc --- /dev/null +++ b/js/src/jit-test/tests/basic/function-tosource-bug779694.js @@ -0,0 +1,8 @@ +// This test creates poorly compressible input, which tests certain paths in +// source code compression. +var x = ""; +for (var i=0; i<400; ++i) { + x += String.fromCharCode(i * 289); +} +var s = "'" + x + "'"; +assertEq(Function("evt", s).toString(), "function anonymous(evt\n) {\n" + s + "\n}"); diff --git a/js/src/jit-test/tests/basic/function-tosource-constructor.js b/js/src/jit-test/tests/basic/function-tosource-constructor.js new file mode 100644 index 0000000000..26817d9eed --- /dev/null +++ b/js/src/jit-test/tests/basic/function-tosource-constructor.js @@ -0,0 +1,16 @@ +var f = Function("a", "b", "return a + b;"); +assertEq(f.toString(), "function anonymous(a,b\n) {\nreturn a + b;\n}"); +if (Function.prototype.toSource) { + assertEq(f.toSource(), "(function anonymous(a,b\n) {\nreturn a + b;\n})"); +} +assertEq(decompileFunction(f), f.toString()); +f = Function("a", "...rest", "return rest[42] + b;"); +assertEq(f.toString(), "function anonymous(a,...rest\n) {\nreturn rest[42] + b;\n}"); +if (Function.prototype.toSource) { + assertEq(f.toSource(), "(function anonymous(a,...rest\n) {\nreturn rest[42] + b;\n})") +} +assertEq(decompileFunction(f), f.toString()); +f = Function(""); +assertEq(f.toString(), "function anonymous(\n) {\n\n}"); +f = Function("", "(abc)"); +assertEq(f.toString(), "function anonymous(\n) {\n(abc)\n}"); diff --git a/js/src/jit-test/tests/basic/function-tosource-exprbody-bug777834.js b/js/src/jit-test/tests/basic/function-tosource-exprbody-bug777834.js new file mode 100644 index 0000000000..be5d60ccd5 --- /dev/null +++ b/js/src/jit-test/tests/basic/function-tosource-exprbody-bug777834.js @@ -0,0 +1,5 @@ +load(libdir + "asserts.js"); + +assertThrowsInstanceOf(function () { + eval("function f()((l()))++2s"); +}, SyntaxError); diff --git a/js/src/jit-test/tests/basic/function-tosource-func-proto.js b/js/src/jit-test/tests/basic/function-tosource-func-proto.js new file mode 100644 index 0000000000..34bcdf965e --- /dev/null +++ b/js/src/jit-test/tests/basic/function-tosource-func-proto.js @@ -0,0 +1,4 @@ +assertEq(Function.prototype.toString(), "function () {\n [native code]\n}"); +if (Function.prototype.toSource) { + assertEq(Function.prototype.toSource(), "function () {\n [native code]\n}"); +} diff --git a/js/src/jit-test/tests/basic/function-tosource-getset.js b/js/src/jit-test/tests/basic/function-tosource-getset.js new file mode 100644 index 0000000000..c8e8007513 --- /dev/null +++ b/js/src/jit-test/tests/basic/function-tosource-getset.js @@ -0,0 +1,13 @@ +var o = {get prop() { a + b; }, set prop(x) { a + b; }}; +var prop = Object.getOwnPropertyDescriptor(o, "prop"); +assertEq(prop.get.toString(), "get prop() { a + b; }"); +if (Function.prototype.toSource) { + assertEq(prop.get.toSource(), "get prop() { a + b; }"); +} +assertEq(prop.set.toString(), "set prop(x) { a + b; }"); +if (Function.prototype.toSource) { + assertEq(prop.set.toSource(), "set prop(x) { a + b; }"); +} +if (Object.prototype.toSource) { + assertEq(o.toSource(), "({get prop() { a + b; }, set prop(x) { a + b; }})"); +} diff --git a/js/src/jit-test/tests/basic/function-tosource-lambda.js b/js/src/jit-test/tests/basic/function-tosource-lambda.js new file mode 100644 index 0000000000..97f28b40ff --- /dev/null +++ b/js/src/jit-test/tests/basic/function-tosource-lambda.js @@ -0,0 +1,18 @@ +var f1 = function f0(a, b) { return a + b; } +if (Function.prototype.toSource) { + assertEq(f1.toSource(), "(function f0(a, b) { return a + b; })"); +} +assertEq(f1.toString(), "function f0(a, b) { return a + b; }"); +assertEq(decompileFunction(f1), f1.toString()); +var f2 = function (a, b) { return a + b; }; +if (Function.prototype.toSource) { + assertEq(f2.toSource(), "(function (a, b) { return a + b; })"); +} +assertEq(f2.toString(), "function (a, b) { return a + b; }"); +assertEq(decompileFunction(f2), f2.toString()); +var f3 = (function (a, b) { return a + b; }); +if (Function.prototype.toSource) { + assertEq(f3.toSource(), "(function (a, b) { return a + b; })"); +} +assertEq(f3.toString(), "function (a, b) { return a + b; }"); +assertEq(decompileFunction(f3), f3.toString()); diff --git a/js/src/jit-test/tests/basic/function-tosource-statement.js b/js/src/jit-test/tests/basic/function-tosource-statement.js new file mode 100644 index 0000000000..e5d1bb7c24 --- /dev/null +++ b/js/src/jit-test/tests/basic/function-tosource-statement.js @@ -0,0 +1,13 @@ +function f1(a, b) { + return a + b; +} +assertEq(f1.toString(), "function f1(a, b) {\n return a + b;\n}"); +if (Function.prototype.toSource) { + assertEq(f1.toSource(), f1.toString()); +} +function f2(a, /* ))))pernicious comment */ b, + c, // another comment(( + d) {} +assertEq(f2.toString(), "function f2(a, /* ))))pernicious comment */ b,\n c, // another comment((\n d) {}"); +function f3() { } +assertEq(f3.toString(), "function f3() { }"); diff --git a/js/src/jit-test/tests/basic/functionRedeclConst.js b/js/src/jit-test/tests/basic/functionRedeclConst.js new file mode 100644 index 0000000000..fd7fec6559 --- /dev/null +++ b/js/src/jit-test/tests/basic/functionRedeclConst.js @@ -0,0 +1,5 @@ +// |jit-test| error: SyntaxError +{ + const x = 0; + function x() { } +} diff --git a/js/src/jit-test/tests/basic/functionRedeclGlobalConst.js b/js/src/jit-test/tests/basic/functionRedeclGlobalConst.js new file mode 100644 index 0000000000..117811b6bb --- /dev/null +++ b/js/src/jit-test/tests/basic/functionRedeclGlobalConst.js @@ -0,0 +1,3 @@ +// |jit-test| error: SyntaxError +const x = 0; +function x() { } diff --git a/js/src/jit-test/tests/basic/functionRedeclLet.js b/js/src/jit-test/tests/basic/functionRedeclLet.js new file mode 100644 index 0000000000..7014c3ba89 --- /dev/null +++ b/js/src/jit-test/tests/basic/functionRedeclLet.js @@ -0,0 +1,5 @@ +// |jit-test| error: SyntaxError +{ + let x; + function x() { } +} diff --git a/js/src/jit-test/tests/basic/functionnames.js b/js/src/jit-test/tests/basic/functionnames.js new file mode 100644 index 0000000000..8b046db8b9 --- /dev/null +++ b/js/src/jit-test/tests/basic/functionnames.js @@ -0,0 +1,160 @@ +// |jit-test| skip-if: isLcovEnabled() + +/* + * Most of these test cases are adapted from: + * http://johnjbarton.github.com/nonymous/index.html + */ + +function assertName(fn, name) { + assertEq(displayName(fn), name) +} + +/* simple names */ +var a = function b() {}; +function c() {}; +assertName(a, 'b'); +assertName(c, 'c'); + +var a = function(){}, + b = function(){}; +assertName(a, 'a'); +assertName(b, 'b'); + +/* nested names */ +var main = function() { + function Foo(a) { assertName(a, 'main/foo<') } + var foo = new Foo(function() {}); +}; +assertName(main, 'main') +main(); + +/* duplicated */ +var Baz = Bar = function(){} +assertName(Baz, 'Bar'); +assertName(Bar, 'Bar'); + +/* returned from an immediate function */ +var Foo = function (){ + assertName(arguments.callee, 'Foo<') + return function(){}; +}(); +assertName(Foo, 'Foo</<'); + +/* various properties and such */ +var x = {fox: { bax: function(){} } }; +assertName(x.fox.bax, 'bax'); +var foo = {foo: {foo: {}}}; +foo.foo.foo = function(){}; +assertName(foo.foo.foo, 'foo.foo.foo'); +var z = { + foz: function() { + var baz = function() { + var y = {bay: function() {}}; + assertName(y.bay, 'bay'); + }; + assertName(baz, 'baz'); + baz(); + } +}; +assertName(z.foz, 'foz'); +z.foz(); + +var outer = function() { + x.fox.bax.nx = function(){}; + var w = {fow: { baw: function(){} } }; + assertName(x.fox.bax.nx, 'outer/x.fox.bax.nx') + assertName(w.fow.baw, 'baw'); +}; +assertName(outer, 'outer'); +outer(); +function Fuz(){}; +Fuz.prototype = { + add: function() {} +} +assertName(Fuz.prototype.add, 'add'); + +var x = 1; +x = function(){}; +assertName(x, 'x'); + +var a = {b: {}}; +a.b.c = (function() { + assertName(arguments.callee, 'a.b.c<') +}()); + +a.b = function() { + function foo(f) { assertName(f, 'a.b/<'); }; + return foo(function(){}); +} +a.b(); + +var bar = 'bar'; +a.b[bar] = function(){}; +assertName(a.b.bar, 'a.b[bar]'); + +a.b = function() { + assertName(arguments.callee, 'a.b<'); + return { a: function() {} } +}(); +assertName(a.b.a, 'a'); + +a = { + b: function(a) { + if (a) + return function() {}; + else + return function() {}; + } +}; +assertName(a.b, 'b'); +assertName(a.b(true), 'b/<') +assertName(a.b(false), 'b/<') + +function f(g) { + assertName(g, 'x<'); + return g(); +} +var x = f(function () { return function() {}; }); +assertName(x, 'x</<'); + +var a = {'b': function(){}}; +assertName(a.b, 'b'); + +function g(f) { + assertName(f, ''); +} +label: g(function () {}); + +var z = [function() {}]; +assertName(z[0], 'z<'); + +/* fuzz bug from 785089 */ +odeURIL:(function(){}) + +a = { 1: function () {} }; +assertName(a[1], '1'); + +a = { + "embedded spaces": function(){}, + "dots.look.like.property.references": function(){}, + "\"\'quotes\'\"": function(){}, + "!@#$%": function(){} +}; +assertName(a["embedded spaces"], 'embedded spaces'); +assertName(a["dots.look.like.property.references"], 'dots.look.like.property.references'); +assertName(a["\"\'quotes\'\""], '"\'quotes\'"'); +assertName(a["!@#$%"], '!@#$%'); + +a.b = {}; +a.b.c = {}; +a.b["c"]["d e"] = { f: { 1: { "g": { "h i": function() {} } } } }; +assertName(a.b.c["d e"].f[1].g["h i"], 'h i'); + +this.m = function () {}; +assertName(m, "this.m"); + +function N() { + this.o = function () {} +} +let n = new N() +assertName(n.o, "N/this.o"); diff --git a/js/src/jit-test/tests/basic/getBacktrace-invalid.js b/js/src/jit-test/tests/basic/getBacktrace-invalid.js new file mode 100644 index 0000000000..2a3f449895 --- /dev/null +++ b/js/src/jit-test/tests/basic/getBacktrace-invalid.js @@ -0,0 +1,5 @@ +const backtrace = evaluate(` +this.getBacktrace(this); +`, { fileName: "\u86D9" }); + +assertEq(backtrace.includes(`["\u86D9":2:6]`), true); diff --git a/js/src/jit-test/tests/basic/getelem.js b/js/src/jit-test/tests/basic/getelem.js new file mode 100644 index 0000000000..cfc2a70edc --- /dev/null +++ b/js/src/jit-test/tests/basic/getelem.js @@ -0,0 +1,30 @@ +var a; +function setelem() +{ + a = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; + a = a.concat(a, a, a); + var l = a.length; + for (var i = 0; i < l; i++) { + a[i] = i; + } + return a.toString(); +} + +setelem(); + +function getelem_inner(a) +{ + var accum = 0; + var l = a.length; + for (var i = 0; i < l; i++) { + accum += a[i]; + } + return accum; +} + +function getelem() +{ + return getelem_inner(a); +} + +assertEq(getelem(), 3486); diff --git a/js/src/jit-test/tests/basic/getprop.js b/js/src/jit-test/tests/basic/getprop.js new file mode 100644 index 0000000000..126af690b5 --- /dev/null +++ b/js/src/jit-test/tests/basic/getprop.js @@ -0,0 +1,16 @@ +var a = 2; +function getprop_inner(o2) +{ + var o = {a:5}; + var t = this; + var x = 0; + for (var i = 0; i < 20; i++) { + t = this; + x += o.a + o2.a + this.a + t.a; + } + return x; +} +function getprop() { + return getprop_inner({a:9}); +} +assertEq(getprop(), 360); diff --git a/js/src/jit-test/tests/basic/global-lexicals-function.js b/js/src/jit-test/tests/basic/global-lexicals-function.js new file mode 100644 index 0000000000..52b56c8bb5 --- /dev/null +++ b/js/src/jit-test/tests/basic/global-lexicals-function.js @@ -0,0 +1,18 @@ +class Foo {}; +let x = 1; +const y = 2; +var z = 3; + +var obj = globalLexicals(); +assertEq(Object.keys(obj).length >= 3, true); +assertEq(obj.Foo, Foo); +assertEq(obj.x, 1); +assertEq(obj.y, 2); +assertEq("z" in obj, false); + +assertEq("uninit" in obj, false); +let uninit; + +// It's just a copy. +obj.x = 2; +assertEq(x, 1); diff --git a/js/src/jit-test/tests/basic/globalGet.js b/js/src/jit-test/tests/basic/globalGet.js new file mode 100644 index 0000000000..53d73a6f60 --- /dev/null +++ b/js/src/jit-test/tests/basic/globalGet.js @@ -0,0 +1,6 @@ +globalName = 907; +var globalInt = 0; +for (var i = 0; i < 500; i++) + globalInt = globalName + i; + +assertEq(globalInt, globalName + 499); diff --git a/js/src/jit-test/tests/basic/globalOptimize-1.js b/js/src/jit-test/tests/basic/globalOptimize-1.js new file mode 100644 index 0000000000..f90114c334 --- /dev/null +++ b/js/src/jit-test/tests/basic/globalOptimize-1.js @@ -0,0 +1,5 @@ +/* Test that NaN does not trigger js_InitMathClass & constants while parsing. */ +var NaN + +var x = 2; + diff --git a/js/src/jit-test/tests/basic/globalSet.js b/js/src/jit-test/tests/basic/globalSet.js new file mode 100644 index 0000000000..ceb2852d06 --- /dev/null +++ b/js/src/jit-test/tests/basic/globalSet.js @@ -0,0 +1,4 @@ +for (var i = 0; i < 500; i++) + globalInt = i; + +assertEq(globalInt, 499); diff --git a/js/src/jit-test/tests/basic/hasnativemethodpure-optimization.js b/js/src/jit-test/tests/basic/hasnativemethodpure-optimization.js new file mode 100644 index 0000000000..2f5e991864 --- /dev/null +++ b/js/src/jit-test/tests/basic/hasnativemethodpure-optimization.js @@ -0,0 +1,21 @@ +load(libdir + "asserts.js"); + +let string = Object.defineProperty(new String("123"), "valueOf", { + get: function() { throw "get-valueOf"; } +}); +assertThrowsValue(() => "" + string, "get-valueOf"); + +string = Object.defineProperty(new String("123"), "toString", { + get: function() { throw "get-toString"; } +}); +assertThrowsValue(() => string.toLowerCase(), "get-toString"); + +string = Object.defineProperty(new String("123"), Symbol.toPrimitive, { + get: function() { throw "get-toPrimitive"; } +}); +assertThrowsValue(() => string.toLowerCase(), "get-toPrimitive"); + +let number = Object.defineProperty(new Number(123), "valueOf", { + get: function() { throw "get-valueOf"; } +}); +assertThrowsValue(() => +number, "get-valueOf");
\ No newline at end of file diff --git a/js/src/jit-test/tests/basic/homogenous-literals.js b/js/src/jit-test/tests/basic/homogenous-literals.js new file mode 100644 index 0000000000..d9e3e77610 --- /dev/null +++ b/js/src/jit-test/tests/basic/homogenous-literals.js @@ -0,0 +1,50 @@ + +function processNoProperty(a) { + var total = 0; + for (var i = 0; i < a.length; i++) { + var sa = a[i]; + for (var j = 0; j < sa.length; j++) + total += sa[j]; + } + assertEq(total, 22); +} + +var literalArray = [ + [1,2,3,4], + [1.5,2.5,3.5,4.5] +]; + +var jsonArray = JSON.parse(`[ + [1,2,3,4], + [1.5,2.5,3.5,4.5] +]`); + +for (var i = 0; i < 1000; i++) { + processNoProperty(literalArray); + processNoProperty(jsonArray); +} + +function processWithProperty(a) { + var total = 0; + for (var i = 0; i < a.length; i++) { + var sa = a[i].p; + for (var j = 0; j < sa.length; j++) + total += sa[j]; + } + assertEq(total, 22); +} + +var literalPropertyArray = [ + {p:[1,2,3,4]}, + {p:[1.5,2.5,3.5,4.5]} +]; + +var jsonPropertyArray = JSON.parse(`[ + {"p":[1,2,3,4]}, + {"p":[1.5,2.5,3.5,4.5]} +]`); + +for (var i = 0; i < 1000; i++) { + processWithProperty(literalPropertyArray); + processWithProperty(jsonPropertyArray); +} diff --git a/js/src/jit-test/tests/basic/html-extensions.js b/js/src/jit-test/tests/basic/html-extensions.js new file mode 100644 index 0000000000..5cf52aefd1 --- /dev/null +++ b/js/src/jit-test/tests/basic/html-extensions.js @@ -0,0 +1,87 @@ +var noParamFuns = ["".bold, "".italics, "".fixed, "".strike, "".small, "".big, + "".blink, "".sup, "".sub]; +var noParamTags = ["b", "i", "tt", "strike", "small", "big", + "blink", "sup", "sub"]; + +function testNoParam(s) { + for (var i=0; i<noParamFuns.length; i++) { + var fun = noParamFuns[i]; + assertEq(fun.length, 0); + var res = fun.call(s); + var tag = noParamTags[i]; + assertEq(res, "<" + tag + ">" + String(s) + "</" + tag + ">"); + } +} +testNoParam("Foo"); +testNoParam('aaa"bbb\'c<>123'); +testNoParam(123); + +// toString should be called, not valueOf +testNoParam({toString: () => 1, valueOf: () => { throw "fail"; } }); + +assertEq("".anchor.length, 1); +assertEq("".link.length, 1); +assertEq("".fontsize.length, 1); +assertEq("".fontcolor.length, 1); + +// Ensure @@replace on String.prototype isn't called. +String.prototype[Symbol.replace] = function() { + throw "Shouldn't call @@replace"; +}; + +// " in the attribute value is escaped (") +assertEq("bla\"<>'".anchor("foo'<>\"\"123\"/\\"), + "<a name=\"foo'<>""123"/\\\">bla\"<>'</a>"); +assertEq("bla\"<>'".link("foo'<>\"\"123\"/\\"), + "<a href=\"foo'<>""123"/\\\">bla\"<>'</a>"); +assertEq("bla\"<>'".fontsize("foo'<>\"\"123\"/\\"), + "<font size=\"foo'<>""123"/\\\">bla\"<>'</font>"); +assertEq("bla\"<>'".fontcolor("foo'<>\"\"123\"/\\"), + "<font color=\"foo'<>""123"/\\\">bla\"<>'</font>"); + +assertEq("".anchor('"'), '<a name="""></a>'); +assertEq("".link('"'), '<a href="""></a>'); +assertEq("".fontcolor('"'), '<font color="""></font>'); +assertEq("".fontsize('"'), '<font size="""></font>'); + +assertEq("".anchor('"1'), '<a name=""1"></a>'); +assertEq("".link('"1'), '<a href=""1"></a>'); +assertEq("".fontcolor('"1'), '<font color=""1"></font>'); +assertEq("".fontsize('"1'), '<font size=""1"></font>'); + +assertEq("".anchor('"""a"'), '<a name=""""a""></a>'); +assertEq("".link('"""a"'), '<a href=""""a""></a>'); +assertEq("".fontcolor('"""a"'), '<font color=""""a""></font>'); +assertEq("".fontsize('"""a"'), '<font size=""""a""></font>'); + +assertEq("".anchor(""), '<a name=""></a>'); +assertEq("".link(""), '<a href=""></a>'); +assertEq("".fontcolor(""), '<font color=""></font>'); +assertEq("".fontsize(""), '<font size=""></font>'); + +assertEq("foo".anchor(), "<a name=\"undefined\">foo</a>"); +assertEq("foo".link(), "<a href=\"undefined\">foo</a>"); +assertEq("foo".fontcolor(), "<font color=\"undefined\">foo</font>"); +assertEq("foo".fontsize(), "<font size=\"undefined\">foo</font>"); + +assertEq("foo".anchor(3.14), '<a name="3.14">foo</a>'); +assertEq("foo".link(3.14), '<a href="3.14">foo</a>'); +assertEq("foo".fontcolor(3.14), '<font color="3.14">foo</font>'); +assertEq("foo".fontsize(3.14), '<font size="3.14">foo</font>'); + +assertEq("foo".anchor({}), '<a name="[object Object]">foo</a>'); +assertEq("foo".link(Math), '<a href="[object Math]">foo</a>'); +assertEq("foo".fontcolor([1,2]), '<font color="1,2">foo</font>'); +assertEq("foo".fontsize({}), '<font size="[object Object]">foo</font>'); + +// toString should be called, not valueOf, and toString must be called on |this| +// before it's called on the argument. Also makes sure toString is called only +// once. +var count = 0; +var o1 = {toString: () => { return count += 1; }, valueOf: () => { throw "fail"; } }; +var o2 = {toString: () => { return count += 5; }, valueOf: () => { throw "fail"; } }; +assertEq("".anchor.call(o1, o2), '<a name="6">1</a>'); +assertEq("".link.call(o1, o2), '<a href="12">7</a>'); +assertEq("".fontcolor.call(o1, o2), '<font color="18">13</font>'); +assertEq("".fontsize.call(o1, o2), '<font size="24">19</font>'); +assertEq(count, 24); diff --git a/js/src/jit-test/tests/basic/hypot-approx.js b/js/src/jit-test/tests/basic/hypot-approx.js new file mode 100644 index 0000000000..b848b1fe60 --- /dev/null +++ b/js/src/jit-test/tests/basic/hypot-approx.js @@ -0,0 +1,34 @@ +load(libdir + "math.js"); + +for (var i = -20; i < 20; i++) { + assertEq(Math.hypot(+0, i), Math.abs(i)); + assertEq(Math.hypot(-0, i), Math.abs(i)); +} + +// The implementation must avoid underlow. +// The implementation must avoid overflow, where possible. +// The implementation must minimise rounding errors. + +assertNear(Math.hypot(1e-300, 1e-300), 1.414213562373095e-300); +assertNear(Math.hypot(1e-300, 1e-300, 1e-300), 1.732050807568877e-300); + +assertNear(Math.hypot(1e-3, 1e-3, 1e-3), 0.0017320508075688772); + +assertNear(Math.hypot(1e300, 1e300), 1.4142135623730952e+300); +assertNear(Math.hypot(1e100, 1e200, 1e300), 1e300); + +assertNear(Math.hypot(1e3, 1e-3), 1000.0000000005); +assertNear(Math.hypot(1e-300, 1e300), 1e300); +assertNear(Math.hypot(1e3, 1e-3, 1e3, 1e-3), 1414.2135623738021555); + +assertNear(Math.hypot(1e1, 1e2, 1e3), Math.sqrt(1e2 + 1e4 + 1e6)); +assertNear(Math.hypot(1e1, 1e2, 1e3, 1e4), Math.sqrt(1e2 + 1e4 + 1e6 + 1e8)); + +for (var i = 1, j = 2; i < 2; i += 0.05, j += 0.05) + assertNear(Math.hypot(i, j), Math.sqrt(i * i + j * j)); + +for (var i = 1, j = 2, k = 3; i < 2; i += 0.05, j += 0.05, k += 0.05) + assertNear(Math.hypot(i, j, k), Math.sqrt(i * i + j * j + k * k)); + +for (var i = 1, j = 2, k = 3, l = 4; i < 2; i += 0.05, j += 0.05, k += 0.05, l += 0.5) + assertNear(Math.hypot(i, j, k, l), Math.sqrt(i * i + j * j + k * k + l * l)); diff --git a/js/src/jit-test/tests/basic/hypot-exact.js b/js/src/jit-test/tests/basic/hypot-exact.js new file mode 100644 index 0000000000..7c208d5143 --- /dev/null +++ b/js/src/jit-test/tests/basic/hypot-exact.js @@ -0,0 +1,74 @@ +// Properties of Math.hypot that are guaranteed by the spec. + +// If no arguments are passed, the result is +0. +assertEq(Math.hypot(), +0); + +// If any argument is +∞, the result is +∞. +// If any argument is −∞, the result is +∞. +for (var inf of [Infinity, -Infinity]) { + assertEq(Math.hypot(inf, 0), Infinity); + assertEq(Math.hypot(0, inf), Infinity); + assertEq(Math.hypot(inf, inf), Infinity); + assertEq(Math.hypot(inf, -inf), Infinity); + + assertEq(Math.hypot(inf, -0), Infinity); + assertEq(Math.hypot(-0, inf), Infinity); + assertEq(Math.hypot(inf, Math.MIN_VALUE), Infinity); + assertEq(Math.hypot(Math.MIN_VALUE, inf), Infinity); + assertEq(Math.hypot(inf, 1), Infinity); + assertEq(Math.hypot(1, inf), Infinity); + + assertEq(Math.hypot(inf, 0, 0), Infinity); + assertEq(Math.hypot(0, inf, 0), Infinity); + assertEq(Math.hypot(0, 0, inf), Infinity); + + assertEq(Math.hypot(inf, NaN), Infinity); + assertEq(Math.hypot(NaN, inf), Infinity); + + assertEq(Math.hypot(inf, NaN, NaN), Infinity); + assertEq(Math.hypot(NaN, inf, NaN), Infinity); + assertEq(Math.hypot(NaN, NaN, inf), Infinity); + + assertEq(Math.hypot(inf, NaN, NaN, NaN), Infinity); + assertEq(Math.hypot(NaN, inf, NaN, NaN), Infinity); + assertEq(Math.hypot(NaN, NaN, inf, NaN), Infinity); + assertEq(Math.hypot(NaN, NaN, NaN, inf), Infinity); +} + +// If no argument is +∞ or −∞, and any argument is NaN, the result is NaN. +assertEq(Math.hypot(NaN), NaN); + +assertEq(Math.hypot(NaN, 0), NaN); +assertEq(Math.hypot(0, NaN), NaN); + +assertEq(Math.hypot(NaN, NaN), NaN); + +assertEq(Math.hypot(NaN, 0, 0), NaN); +assertEq(Math.hypot(0, NaN, 0), NaN); +assertEq(Math.hypot(0, 0, NaN), NaN); + +assertEq(Math.hypot(NaN, 0, 0, 0), NaN); +assertEq(Math.hypot(0, NaN, 0, 0), NaN); +assertEq(Math.hypot(0, 0, NaN, 0), NaN); +assertEq(Math.hypot(0, 0, 0, NaN), NaN); + +assertEq(Math.hypot(Number.MAX_VALUE, Number.MIN_VALUE, NaN), NaN); +assertEq(Math.hypot(Number.MAX_VALUE, Number.MIN_VALUE, Number.MIN_VALUE, NaN), NaN); + +// If all arguments are either +0 or -0, the result is +0. +assertEq(Math.hypot(-0, -0), +0); +assertEq(Math.hypot(+0, -0), +0); + +assertEq(Math.hypot(-0, -0, -0), +0); +assertEq(Math.hypot(+0, -0, -0), +0); +assertEq(Math.hypot(-0, +0, -0), +0); +assertEq(Math.hypot(+0, +0, -0), +0); + +assertEq(Math.hypot(-0, -0, -0, -0), +0); +assertEq(Math.hypot(+0, -0, -0, -0), +0); +assertEq(Math.hypot(-0, -0, +0, -0), +0); +assertEq(Math.hypot(+0, +0, +0, -0), +0); +assertEq(Math.hypot(-0, -0, -0, +0), +0); + +// The length property of the hypot function is 2. +assertEq(Math.hypot.length, 2); diff --git a/js/src/jit-test/tests/basic/ifInsideLoop.js b/js/src/jit-test/tests/basic/ifInsideLoop.js new file mode 100644 index 0000000000..296e3f82d5 --- /dev/null +++ b/js/src/jit-test/tests/basic/ifInsideLoop.js @@ -0,0 +1,12 @@ +function ifInsideLoop() +{ + var cond = true, intCond = 5, count = 0; + for (var i = 0; i < 100; i++) { + if (cond) + count++; + if (intCond) + count++; + } + return count; +} +assertEq(ifInsideLoop(), 200); diff --git a/js/src/jit-test/tests/basic/inArrayTest.js b/js/src/jit-test/tests/basic/inArrayTest.js new file mode 100644 index 0000000000..d57f013fd3 --- /dev/null +++ b/js/src/jit-test/tests/basic/inArrayTest.js @@ -0,0 +1,9 @@ +function inArrayTest() { + var a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + for (var i = 0; i < a.length; i++) { + if (!(i in a)) + break; + } + return i; +} +assertEq(inArrayTest(), 10); diff --git a/js/src/jit-test/tests/basic/inObjectTest.js b/js/src/jit-test/tests/basic/inObjectTest.js new file mode 100644 index 0000000000..f19fdbe429 --- /dev/null +++ b/js/src/jit-test/tests/basic/inObjectTest.js @@ -0,0 +1,13 @@ +function inObjectTest() { + var o = {p: 1, q: 2, r: 3, s: 4, t: 5}; + var r = 0; + for (var i in o) { + if (!(i in o)) + break; + if ((i + i) in o) + break; + ++r; + } + return r; +} +assertEq(inObjectTest(), 5); diff --git a/js/src/jit-test/tests/basic/indexed-iteration.js b/js/src/jit-test/tests/basic/indexed-iteration.js new file mode 100644 index 0000000000..952aa105ba --- /dev/null +++ b/js/src/jit-test/tests/basic/indexed-iteration.js @@ -0,0 +1,20 @@ + +// Don't use NativeIterator cache for objects with dense elements. + +function bar(a) { + var n = 0; + for (var b in a) { n++; } + return n; +} + +function foo() { + var x = {a:0,b:1}; + var y = {a:0,b:1}; + y[0] = 2; + y[1] = 3; + for (var i = 0; i < 10; i++) { + assertEq(bar(x), 2); + assertEq(bar(y), 4); + } +} +foo(); diff --git a/js/src/jit-test/tests/basic/indexof-equal.js b/js/src/jit-test/tests/basic/indexof-equal.js new file mode 100644 index 0000000000..f6e3256048 --- /dev/null +++ b/js/src/jit-test/tests/basic/indexof-equal.js @@ -0,0 +1,10 @@ +var x = "abc"; +assertEq(x.indexOf(x), 0); +assertEq(x.indexOf(x, -1), 0); +assertEq(x.indexOf(x, 1), -1); +assertEq(x.indexOf(x, 100), -1); + +assertEq(x.lastIndexOf(x), 0); +assertEq(x.lastIndexOf(x, -1), 0); +assertEq(x.lastIndexOf(x, 1), 0); +assertEq(x.lastIndexOf(x, 100), 0); diff --git a/js/src/jit-test/tests/basic/inflate-oom.js b/js/src/jit-test/tests/basic/inflate-oom.js new file mode 100644 index 0000000000..645980789f --- /dev/null +++ b/js/src/jit-test/tests/basic/inflate-oom.js @@ -0,0 +1,14 @@ +// |jit-test| skip-if: !('oomTest' in this) +function test() { + function foo() { + return 1; + }; + oomTest(() => { + gc(); + foo.toString(); + }); +} +var s = ";".repeat(70000); +s += test.toString() + "test()"; +s += ";".repeat(70000); +eval(s); diff --git a/js/src/jit-test/tests/basic/innerLoopIntOuterDouble.js b/js/src/jit-test/tests/basic/innerLoopIntOuterDouble.js new file mode 100644 index 0000000000..be820f956d --- /dev/null +++ b/js/src/jit-test/tests/basic/innerLoopIntOuterDouble.js @@ -0,0 +1,11 @@ +function innerLoopIntOuterDouble() { + var n = 1000, i=0, j=0, count=0, limit=0; + for (i = 1; i <= n; ++i) { + limit = i * 1; + for (j = 0; j < limit; ++j) { + ++count; + } + } + return "" + count; +} +assertEq(innerLoopIntOuterDouble(), "500500"); diff --git a/js/src/jit-test/tests/basic/inner_double_outer_int.js b/js/src/jit-test/tests/basic/inner_double_outer_int.js new file mode 100644 index 0000000000..4051aa21aa --- /dev/null +++ b/js/src/jit-test/tests/basic/inner_double_outer_int.js @@ -0,0 +1,10 @@ +function inner_double_outer_int() { + function f(i) { + for (var m = 0; m < 20; ++m) + for (var n = 0; n < 100; n += i) + ; + return n; + } + return f(.5); +} +assertEq(inner_double_outer_int(), 100); diff --git a/js/src/jit-test/tests/basic/invokeFunctionMagic.js b/js/src/jit-test/tests/basic/invokeFunctionMagic.js new file mode 100644 index 0000000000..9fc364315f --- /dev/null +++ b/js/src/jit-test/tests/basic/invokeFunctionMagic.js @@ -0,0 +1,20 @@ +// JS_IS_CONSTRUCTING +var g = newGlobal(); +do { + new g.String(); // jit::CreateThis passes JS_IS_CONSTRUCTING +} while (!inIon()); + +// JS_UNINITIALIZED_LEXICAL +function dontAbortWholeCompilation() { + class B {}; + class D extends B { + constructor() { super(); } + }; + + return D; +} +var classImpl = dontAbortWholeCompilation(); + +do { + new classImpl(); // jit::CreateThis passes JS_UNINITIALIZED_LEXICAL +} while (!inIon()); diff --git a/js/src/jit-test/tests/basic/is-valid-json.js b/js/src/jit-test/tests/basic/is-valid-json.js new file mode 100644 index 0000000000..ea30518f1d --- /dev/null +++ b/js/src/jit-test/tests/basic/is-valid-json.js @@ -0,0 +1,25 @@ +assertEq(isValidJSON(`0`), true); +assertEq(isValidJSON(`1.2`), true); +assertEq(isValidJSON(`-2.3`), true); +assertEq(isValidJSON(`true`), true); +assertEq(isValidJSON(`false`), true); +assertEq(isValidJSON(`null`), true); +assertEq(isValidJSON(`"foo"`), true); +assertEq(isValidJSON(`[]`), true); +assertEq(isValidJSON(`[0, true, false, null]`), true); +assertEq(isValidJSON(`{}`), true); +assertEq(isValidJSON(`{"foo": 10}`), true); + +assertEq(isValidJSON(``), false); +assertEq(isValidJSON(`.2`), false); +assertEq(isValidJSON(`2.`), false); +assertEq(isValidJSON(`undefined`), false); +assertEq(isValidJSON(`'foo'`), false); +assertEq(isValidJSON(`'foo`), false); +assertEq(isValidJSON(`"foo`), false); +assertEq(isValidJSON(`[`), false); +assertEq(isValidJSON(`[,]`), false); +assertEq(isValidJSON(`[1,]`), false); +assertEq(isValidJSON(`{foo: 10}`), false); +assertEq(isValidJSON(`{"foo": 10,}`), false); +assertEq(isValidJSON(`{`), false); diff --git a/js/src/jit-test/tests/basic/iter-cache-null-proto.js b/js/src/jit-test/tests/basic/iter-cache-null-proto.js new file mode 100644 index 0000000000..8e6af52a6b --- /dev/null +++ b/js/src/jit-test/tests/basic/iter-cache-null-proto.js @@ -0,0 +1,11 @@ +function f() { + var o = {x: 0}; + for (var i = 0; i < 20; i++) { + if ((i % 4) === 0) + Object.setPrototypeOf(o, null); + else + Object.setPrototypeOf(o, Object.prototype); + for (var x in o) {} + } +} +f(); diff --git a/js/src/jit-test/tests/basic/iterable-error-messages.js b/js/src/jit-test/tests/basic/iterable-error-messages.js new file mode 100644 index 0000000000..7b9002580c --- /dev/null +++ b/js/src/jit-test/tests/basic/iterable-error-messages.js @@ -0,0 +1,41 @@ +// |jit-test| skip-if: getBuildConfiguration('pbl') + +function assertThrowsMsgEndsWith(f, msg) { + try { + f(); + assertEq(0, 1); + } catch(e) { + assertEq(e instanceof TypeError, true); + assertEq(e.message.endsWith(msg), true); + } +} + +// For-of +function testForOf(val) { + for (var x of val) {} +} +for (v of [{}, Math, new Proxy({}, {})]) { + assertThrowsMsgEndsWith(() => testForOf(v), "val is not iterable"); +} +assertThrowsMsgEndsWith(() => testForOf(null), "val is null"); +assertThrowsMsgEndsWith(() => { for (var x of () => 1) {}}, "() => 1 is not iterable"); + +// Destructuring +function testDestr(val) { + var [a, b] = val; +} +for (v of [{}, Math, new Proxy({}, {})]) { + assertThrowsMsgEndsWith(() => testDestr(v), "val is not iterable"); +} +assertThrowsMsgEndsWith(() => testDestr(null), "val is null"); +assertThrowsMsgEndsWith(() => { [a, b] = () => 1; }, "() => 1 is not iterable"); + +// Spread +function testSpread(val) { + [...val]; +} +for (v of [{}, Math, new Proxy({}, {})]) { + assertThrowsMsgEndsWith(() => testSpread(v), "val is not iterable"); +} +assertThrowsMsgEndsWith(() => testSpread(null), "val is null"); +assertThrowsMsgEndsWith(() => { [...() => 1]; }, "() => 1 is not iterable"); diff --git a/js/src/jit-test/tests/basic/iterator-cache-invalidation.js b/js/src/jit-test/tests/basic/iterator-cache-invalidation.js new file mode 100644 index 0000000000..33adc5a16a --- /dev/null +++ b/js/src/jit-test/tests/basic/iterator-cache-invalidation.js @@ -0,0 +1,52 @@ +function test(obj, expected) { + var result = ""; + for (var s in obj) { + result += s + ","; + } + assertEq(result, expected); +} + +function runTest(mutate, expectedAfter) { + var p = {px: 1, py: 2}; + var o = Object.create(p); + o.x = 3; + o.y = 4; + + var expectedBefore = "x,y,px,py,"; + test(o, expectedBefore); + mutate(o, p); + test(o, expectedAfter); +} + + +function testAddElement() { + runTest((o,p) => { o[0] = 5; }, "0,x,y,px,py,"); +} +function testAddProtoElement() { + runTest((o,p) => { p[0] = 5; }, "x,y,0,px,py,"); +} +function testDelete() { + runTest((o,p) => { delete o.x; }, "y,px,py,"); +} +function testProtoDelete() { + runTest((o,p) => { delete p.px; }, "x,y,py,"); +} +function testMakeUnenumerable() { + runTest((o,p) => { + Object.defineProperty(o, "x", { value: 1, enumerable: false }); + }, "y,px,py,"); +} +function testMakeProtoUnenumerable() { + runTest((o,p) => { + Object.defineProperty(p, "px", { value: 1, enumerable: false }); + }, "x,y,py,"); +} + +for (var i = 0; i < 10; i++) { + testAddElement(); + testAddProtoElement(); + testDelete(); + testProtoDelete(); + testMakeUnenumerable() + testMakeProtoUnenumerable() +} diff --git a/js/src/jit-test/tests/basic/jemalloc-settings.js b/js/src/jit-test/tests/basic/jemalloc-settings.js new file mode 100644 index 0000000000..a5693614ec --- /dev/null +++ b/js/src/jit-test/tests/basic/jemalloc-settings.js @@ -0,0 +1,7 @@ +for (var i = -5; i <= 16; i++) { + setMallocMaxDirtyPageModifier(i); + for (var j = 0; j < 20; j++) { + var arr = Array(j).fill(j); + } + gc(); +} diff --git a/js/src/jit-test/tests/basic/joinTest.js b/js/src/jit-test/tests/basic/joinTest.js new file mode 100644 index 0000000000..1988da4f41 --- /dev/null +++ b/js/src/jit-test/tests/basic/joinTest.js @@ -0,0 +1,15 @@ +function joinTest() +{ + var s = ""; + var a = []; + for (var i = 0; i < 8; i++) + a[i] = [String.fromCharCode(97 + i)]; + for (i = 0; i < 8; i++) { + for (var j = 0; j < 8; j++) + a[i][1 + j] = j; + } + for (i = 0; i < 8; i++) + s += a[i].join(","); + return s; +} +assertEq(joinTest(), "a,0,1,2,3,4,5,6,7b,0,1,2,3,4,5,6,7c,0,1,2,3,4,5,6,7d,0,1,2,3,4,5,6,7e,0,1,2,3,4,5,6,7f,0,1,2,3,4,5,6,7g,0,1,2,3,4,5,6,7h,0,1,2,3,4,5,6,7"); diff --git a/js/src/jit-test/tests/basic/json-parse-object-edge-cases.js b/js/src/jit-test/tests/basic/json-parse-object-edge-cases.js new file mode 100644 index 0000000000..2a93cd4211 --- /dev/null +++ b/js/src/jit-test/tests/basic/json-parse-object-edge-cases.js @@ -0,0 +1,49 @@ +// Array includes objects with duplicate keys and integer keys. +let json = `[ + {"x1": 1}, + {"x2": 2}, + {"x3": 3}, + {"x1": 1, "y": 0}, + {"x2": 1, "y": 0}, + {"x3": 1, "y": 0}, + {"x1": 1, "x1": 2, "y": 0}, + {"x1": 1, "x1": 2, "y": 0}, + {"x1": 1, "x1": 2, "y": 0}, + {"0": 1, "x1": 1}, + {"0": 1, "0": 2, "x1": 1}, + {"0": 1, "0": 2, "x1": 1}, + {"2147483648": 1}, + {"2147483648": 2}, + {"2147483648": 0, "x": 0, "2147483648": 3}, + {"4294967295": 4}, + {"4294967295": 5}, + {"-1": 6}, + {"-1": 7}, + {"__proto__": 1}, + {"__proto__": 2} +]`; +for (let i = 0; i < 3; i++) { + let res = JSON.parse(json); + assertEq(JSON.stringify(res), + `[{"x1":1},` + + `{"x2":2},` + + `{"x3":3},` + + `{"x1":1,"y":0},` + + `{"x2":1,"y":0},` + + `{"x3":1,"y":0},` + + `{"x1":2,"y":0},` + + `{"x1":2,"y":0},` + + `{"x1":2,"y":0},` + + `{"0":1,"x1":1},` + + `{"0":2,"x1":1},` + + `{"0":2,"x1":1},` + + `{"2147483648":1},` + + `{"2147483648":2},` + + `{"2147483648":3,"x":0},` + + `{"4294967295":4},` + + `{"4294967295":5},` + + `{"-1":6},` + + `{"-1":7},` + + `{"__proto__":1},` + + `{"__proto__":2}]`); +} diff --git a/js/src/jit-test/tests/basic/json-stringify-large-length.js b/js/src/jit-test/tests/basic/json-stringify-large-length.js new file mode 100644 index 0000000000..d362d1c763 --- /dev/null +++ b/js/src/jit-test/tests/basic/json-stringify-large-length.js @@ -0,0 +1,10 @@ +// |jit-test| error:InternalError +var arr = [1, 2, 3]; +var proxy = new Proxy(arr, { + get(target, prop) { + if (prop === "length") { + return Math.pow(2, 33); + } + } +}); +JSON.stringify(proxy); diff --git a/js/src/jit-test/tests/basic/key-gc.js b/js/src/jit-test/tests/basic/key-gc.js new file mode 100644 index 0000000000..5b684aa136 --- /dev/null +++ b/js/src/jit-test/tests/basic/key-gc.js @@ -0,0 +1,46 @@ +function f(o) { + return Object.keys(o) +} + +function test(o) { + for (var i = 0; i<10; i++) { + res = f(o); + assertEq(true, res.includes("cakebread") ); + + // Initialize for-in cache for o. + for (var prop in o) { + if (prop == "abra") print(prop); + } + + } +} + +let obj = {about: 5, + ballisitic: 6, + cakebread: 8, + dalespeople: 9, + evilproof: 20, + fairgoing: 30, + gargoylish: 2, + harmonici: 1, + jinniwink: 12, + kaleidoscopical: 2, + labellum: 1, + macadamization: 4, + neutrino: 1, + observership: 0, + quadratomandibular: 9, + rachicentesis: 1, + saltcat: 0, + trousseau: 1, + view: 10, + wheelbox: 2, + xerography: 1, + yez: 3, +} + +// Verify things. + +// Collect after every allocation to shake loose issues +gczeal(2,1); +test(obj) diff --git a/js/src/jit-test/tests/basic/keys-testing.js b/js/src/jit-test/tests/basic/keys-testing.js new file mode 100644 index 0000000000..d02ac7be5d --- /dev/null +++ b/js/src/jit-test/tests/basic/keys-testing.js @@ -0,0 +1,134 @@ +function f(o) { + return Object.keys(o) +} + +po = { + failure: 'hello' +} + +o = {about: 5, + ballisitic: 6, + cakebread: 8, + dalespeople: 9, + evilproof: 20, + fairgoing: 30, + gargoylish: 2, + harmonici: 1, + jinniwink: 12, + kaleidoscopical: 2, + labellum: 1, + macadamization: 4, + neutrino: 1, + observership: 0, + quadratomandibular: 9, + rachicentesis: 1, + saltcat: 0, + trousseau: 1, + view: 10, + wheelbox: 2, + xerography: 1, + yez: 3, +} +Object.setPrototypeOf(o, po); + +// Initialize for-in cache for o. +for (var prop in o) { + print(prop) +} + +function test(o) { + for (var i = 0; i<10; i++) { + res = f(o); + assertEq(false, res.includes("failure") ); + // assertEq(true, res.includes("1") ); + } +} + +// Verify things. +test(o) + + +po[2] = "hi"; +test(o); + +po[3] = "bye"; +for (var prop in o) { + assertEq(prop == "gnome", false); +} +test(o); + + +o2 = {about: 5, + ballisitic: 6, + cakebread: 8, + dalespeople: 9, + evilproof: 20, + fairgoing: 30, + gargoylish: 2, + harmonici: 1, + jinniwink: 12, + kaleidoscopical: 2, + labellum: 1, + macadamization: 4, + neutrino: 1, + observership: 0, + quadratomandibular: 9, + rachicentesis: 1, + saltcat: 0, + trousseau: 1, + view: 10, + wheelbox: 2, + xerography: 1, + yez: 3, + "1": 10, +} + +// Initialize for-in cache for o. +for (var prop in o2) { + if (prop == "abra") print(prop); +} + +// Verify things. +test(o2) + + +for (var i = 0; i < 20; i++) { + assertEq(Object.keys(o2).includes("1"), true); +} + +let o3 = {about: 5, + ballisitic: 6, + cakebread: 8, + dalespeople: 9, + evilproof: 20, + fairgoing: 30, + gargoylish: 2, + harmonici: 1, + jinniwink: 12, + kaleidoscopical: 2, + labellum: 1, + macadamization: 4, + neutrino: 1, + observership: 0, + quadratomandibular: 9, + rachicentesis: 1, + saltcat: 0, + trousseau: 1, + view: 10, + wheelbox: 2, + xerography: 1, + yez: 3, +} + +// Initialize for-in cache for o. +for (var prop in o2) { + if (prop == "abra") print(prop); +} + +// Verify things. +test(o3) + + +for (var i = 0; i < 20; i++) { + assertEq(Object.keys(o3).includes("yez"), true); +} diff --git a/js/src/jit-test/tests/basic/lazyparse.js b/js/src/jit-test/tests/basic/lazyparse.js new file mode 100644 index 0000000000..b878c6302e --- /dev/null +++ b/js/src/jit-test/tests/basic/lazyparse.js @@ -0,0 +1,45 @@ + +function outer() { + var xyz = 0; + function foo() { + function bar() { xyz++; } + bar(); + let x = 3; + } + foo(); + assertEq(xyz, 1); +} +outer(); + +function mapfloor(a) { + var b = a.map(function(v) { + "use strict"; + try { + eval("delete String;"); + } catch (e) { + return e instanceof res; + } + }); + var res = ""; +} +try { + mapfloor([1,2]); +} catch (e) {} + +test(); +function test() { + try { + eval('let(z) { with({}) let y = 3; }'); + } catch(ex) { + (function(x) { return !(x) })(0/0) + } +} + +testCatch(15); +function testCatch(y) { + try { + throw 5; + } catch(ex) { + (function(x) { assertEq(x + y + ex, 25); })(5) + } +} diff --git a/js/src/jit-test/tests/basic/letTDZAfterInitializer.js b/js/src/jit-test/tests/basic/letTDZAfterInitializer.js new file mode 100644 index 0000000000..575615c176 --- /dev/null +++ b/js/src/jit-test/tests/basic/letTDZAfterInitializer.js @@ -0,0 +1,19 @@ +function throwSomething() { + throw "something"; +} + +try { + // Use eval to force BINDNAME. Should throw "something" instead of the TDZ + // ReferenceError. + eval("x = throwSomething()"); + let x; +} catch (e) { + assertEq(e, "something"); +} + +try { + eval("x = 42"); + let x; +} catch (e) { + assertEq(e instanceof ReferenceError, true); +} diff --git a/js/src/jit-test/tests/basic/letTDZEffectful.js b/js/src/jit-test/tests/basic/letTDZEffectful.js new file mode 100644 index 0000000000..62245d8c16 --- /dev/null +++ b/js/src/jit-test/tests/basic/letTDZEffectful.js @@ -0,0 +1,13 @@ +function assertThrowsReferenceError(f) { + var e = null; + try { + f(); + } catch (ex) { + e = ex; + } + assertEq(e instanceof ReferenceError, true); +} + +// TDZ is effectful, don't optimize out x. +assertThrowsReferenceError(function () { x; let x; }); +assertThrowsReferenceError(function () { x; const x = undefined; }); diff --git a/js/src/jit-test/tests/basic/letTDZSwitchClosure.js b/js/src/jit-test/tests/basic/letTDZSwitchClosure.js new file mode 100644 index 0000000000..c601f9858d --- /dev/null +++ b/js/src/jit-test/tests/basic/letTDZSwitchClosure.js @@ -0,0 +1,60 @@ +function assertThrowsReferenceError(f) { + var err; + try { + f(); + } catch (e) { + err = e; + } + assertEq(err instanceof ReferenceError, true); +} + +function f() { + switch (0) { + case 1: + let x + case function() { + print(x) + }(): + } +} +assertThrowsReferenceError(f); + +function g() { + switch (0) { + case 1: + let x; + case 0: + var inner = function () { + print(x); + } + inner(); + break; + } +} +assertThrowsReferenceError(g); + +function h() { + switch (0) { + case 0: + var inner = function () { + print(x); + } + inner(); + case 1: + let x; + } +} +assertThrowsReferenceError(h); + +// Tests that a dominating lexical doesn't throw. +function F() { + switch (0) { + case 0: + let x = 42; + var inner = function () { + assertEq(x, 42); + } + inner(); + } +} +F(); diff --git a/js/src/jit-test/tests/basic/local.js b/js/src/jit-test/tests/basic/local.js new file mode 100644 index 0000000000..0f8b12b3fb --- /dev/null +++ b/js/src/jit-test/tests/basic/local.js @@ -0,0 +1,3 @@ +// A file in the same directory as testPaths.js + +x = 'local'; diff --git a/js/src/jit-test/tests/basic/matchInLoop.js b/js/src/jit-test/tests/basic/matchInLoop.js new file mode 100644 index 0000000000..89f40ac5fd --- /dev/null +++ b/js/src/jit-test/tests/basic/matchInLoop.js @@ -0,0 +1,8 @@ +function matchInLoop() { + var k = "hi"; + for (var i = 0; i < 10; i++) { + var result = k.match(/hi/) != null; + } + return result; +} +assertEq(matchInLoop(), true); diff --git a/js/src/jit-test/tests/basic/math-jit-tests.js b/js/src/jit-test/tests/basic/math-jit-tests.js new file mode 100644 index 0000000000..32da64fed0 --- /dev/null +++ b/js/src/jit-test/tests/basic/math-jit-tests.js @@ -0,0 +1,520 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */ + +// Apply FUNCNAME to ARGS, and check against EXPECTED. +// Expect a loop containing such a call to be traced. +// FUNCNAME and ARGS are both strings. +// ARGS has the form of an argument list: a comma-separated list of expressions. +// Certain Tracemonkey limitations require us to pass FUNCNAME as a string. +// Passing ARGS as a string allows us to assign better test names: +// expressions like Math.PI/4 haven't been evaluated to big hairy numbers. +function testmath(funcname, args, expected) { + var i, j; + + var arg_value_list = eval("[" + args + "]"); + var arity = arg_value_list.length; + + // Build the string "a[i][0],...,a[i][ARITY-1]". + var actuals = [] + for (i = 0; i < arity; i++) + actuals.push("a[i][" + i + "]"); + actuals = actuals.join(","); + + // Create a function that maps FUNCNAME across an array of input values. + // Unless we eval here, the call to funcname won't get traced. + // FUNCNAME="Infinity/Math.abs" and cases like that happen to + // parse, too, in a twisted way. + var mapfunc = eval("(function(a) {\n" + + " for (var i = 0; i < a.length; i++)\n" + + " a[i] = " + funcname + "(" + actuals +");\n" + + " })\n"); + + // To prevent the compiler from doing constant folding, produce an + // array to pass to mapfunc that contains enough dummy + // values at the front to get the loop body jitted, and then our + // actual test value. + var dummies_and_input = []; + for (i = 0; i < 9; i++) { + var dummy_list = []; + for (j = 0; j < arity; j++) + dummy_list[j] = .0078125 * ((i + j) % 128); + dummies_and_input[i] = dummy_list; + } + dummies_and_input[9] = arg_value_list; + + function testfunc() { + // Map the function across the dummy values and the test input. + mapfunc(dummies_and_input); + return dummies_and_input[9]; + } + + assertEq(close_enough(testfunc(), expected), true); +} + +function close_enough(expected, actual) +{ + if (typeof expected != typeof actual) + return false; + if (typeof expected != 'number') + return actual == expected; + + // Distinguish NaN from other values. Using x != x comparisons here + // works even if tests redefine isNaN. + if (actual != actual) + return expected != expected + if (expected != expected) + return false; + + // Tolerate a certain degree of error. + if (actual != expected) + return Math.abs(actual - expected) <= 1E-10; + + // Distinguish 0 and -0. + if (actual == 0) + return (1 / actual > 0) == (1 / expected > 0); + + return true; +} + +testmath("Math.abs", "void 0", Number.NaN) +testmath("Math.abs", "null", 0) +testmath("Math.abs", "true", 1) +testmath("Math.abs", "false", 0) +testmath("Math.abs", "\"a string primitive\"", Number.NaN) +testmath("Math.abs", "new String( 'a String object' )", Number.NaN) +testmath("Math.abs", "Number.NaN", Number.NaN) +testmath("Math.abs", "0", 0) +testmath("Math.abs", "-0", 0) +testmath("Infinity/Math.abs", "-0", Infinity) +testmath("Math.abs", "Number.NEGATIVE_INFINITY", Number.POSITIVE_INFINITY) +testmath("Math.abs", "Number.POSITIVE_INFINITY", Number.POSITIVE_INFINITY) +testmath("Math.abs", "- Number.MAX_VALUE", Number.MAX_VALUE) +testmath("Math.abs", "-Number.MIN_VALUE", Number.MIN_VALUE) +testmath("Math.abs", "Number.MAX_VALUE", Number.MAX_VALUE) +testmath("Math.abs", "Number.MIN_VALUE", Number.MIN_VALUE) +testmath("Math.abs", "-1", 1) +testmath("Math.abs", "new Number(-1)", 1) +testmath("Math.abs", "1", 1) +testmath("Math.abs", "Math.PI", Math.PI) +testmath("Math.abs", "-Math.PI", Math.PI) +testmath("Math.abs", "-1/100000000", 1/100000000) +testmath("Math.abs", "-Math.pow(2,32)", Math.pow(2,32)) +testmath("Math.abs", "Math.pow(2,32)", Math.pow(2,32)) +testmath("Math.abs", "-0xfff", 4095) +testmath("Math.abs", "-0777", 511) +testmath("Math.abs", "'-1e-1'", 0.1) +testmath("Math.abs", "'0xff'", 255) +testmath("Math.abs", "'077'", 77) +testmath("Math.abs", "'Infinity'", Infinity) +testmath("Math.abs", "'-Infinity'", Infinity) + +testmath("Math.acos", "void 0", Number.NaN) +testmath("Math.acos", "null", Math.PI/2) +testmath("Math.acos", "Number.NaN", Number.NaN) +testmath("Math.acos", "\"a string\"", Number.NaN) +testmath("Math.acos", "'0'", Math.PI/2) +testmath("Math.acos", "'1'", 0) +testmath("Math.acos", "'-1'", Math.PI) +testmath("Math.acos", "1.00000001", Number.NaN) +testmath("Math.acos", "-1.00000001", Number.NaN) +testmath("Math.acos", "1", 0) +testmath("Math.acos", "-1", Math.PI) +testmath("Math.acos", "0", Math.PI/2) +testmath("Math.acos", "-0", Math.PI/2) +testmath("Math.acos", "Math.SQRT1_2", Math.PI/4) +testmath("Math.acos", "-Math.SQRT1_2", Math.PI/4*3) +testmath("Math.acos", "0.9999619230642", Math.PI/360) +testmath("Math.acos", "-3.0", Number.NaN) + +testmath("Math.asin", "void 0", Number.NaN) +testmath("Math.asin", "null", 0) +testmath("Math.asin", "Number.NaN", Number.NaN) +testmath("Math.asin", "\"string\"", Number.NaN) +testmath("Math.asin", "\"0\"", 0) +testmath("Math.asin", "\"1\"", Math.PI/2) +testmath("Math.asin", "\"-1\"", -Math.PI/2) +testmath("Math.asin", "Math.SQRT1_2+''", Math.PI/4) +testmath("Math.asin", "-Math.SQRT1_2+''", -Math.PI/4) +testmath("Math.asin", "1.000001", Number.NaN) +testmath("Math.asin", "-1.000001", Number.NaN) +testmath("Math.asin", "0", 0) +testmath("Math.asin", "-0", -0) +testmath("Infinity/Math.asin", "-0", -Infinity) +testmath("Math.asin", "1", Math.PI/2) +testmath("Math.asin", "-1", -Math.PI/2) +testmath("Math.asin", "Math.SQRT1_2", Math.PI/4) +testmath("Math.asin", "-Math.SQRT1_2", -Math.PI/4) + +testmath("Math.atan", "void 0", Number.NaN) +testmath("Math.atan", "null", 0) +testmath("Math.atan", "Number.NaN", Number.NaN) +testmath("Math.atan", "\"a string\"", Number.NaN) +testmath("Math.atan", "'0'", 0) +testmath("Math.atan", "'1'", Math.PI/4) +testmath("Math.atan", "'-1'", -Math.PI/4) +testmath("Math.atan", "'Infinity'", Math.PI/2) +testmath("Math.atan", "'-Infinity'", -Math.PI/2) +testmath("Math.atan", "0", 0) +testmath("Math.atan", "-0", -0) +testmath("Infinity/Math.atan", "-0", -Infinity) +testmath("Math.atan", "Number.POSITIVE_INFINITY", Math.PI/2) +testmath("Math.atan", "Number.NEGATIVE_INFINITY", -Math.PI/2) +testmath("Math.atan", "1", Math.PI/4) +testmath("Math.atan", "-1", -Math.PI/4) + +testmath("Math.atan2", "Number.NaN,0", Number.NaN) +testmath("Math.atan2", "null, null", 0) +testmath("Math.atan2", "void 0, void 0", Number.NaN) +testmath("Math.atan2", "0,Number.NaN", Number.NaN) +testmath("Math.atan2", "1,0", Math.PI/2) +testmath("Math.atan2", "1,-0", Math.PI/2) +testmath("Math.atan2", "0,0.001", 0) +testmath("Math.atan2", "0,0", 0) +testmath("Math.atan2", "0,-0", Math.PI) +testmath("Math.atan2", "0, -1", Math.PI) +testmath("Math.atan2", "-0, 1", -0) +testmath("Infinity/Math.atan2", "-0,1", -Infinity) +testmath("Math.atan2", "-0,0", -0) +testmath("Math.atan2", "-0, -0", -Math.PI) +testmath("Math.atan2", "-0, -1", -Math.PI) +testmath("Math.atan2", "-1, 0", -Math.PI/2) +testmath("Math.atan2", "-1, -0", -Math.PI/2) +testmath("Math.atan2", "1, Number.POSITIVE_INFINITY", 0) +testmath("Math.atan2", "1, Number.NEGATIVE_INFINITY", Math.PI) +testmath("Math.atan2", "-1,Number.POSITIVE_INFINITY", -0) +testmath("Infinity/Math.atan2", "-1,Infinity", -Infinity) +testmath("Math.atan2", "-1,Number.NEGATIVE_INFINITY", -Math.PI) +testmath("Math.atan2", "Number.POSITIVE_INFINITY, 0", Math.PI/2) +testmath("Math.atan2", "Number.POSITIVE_INFINITY, 1", Math.PI/2) +testmath("Math.atan2", "Number.POSITIVE_INFINITY,-1", Math.PI/2) +testmath("Math.atan2", "Number.POSITIVE_INFINITY,-0", Math.PI/2) +testmath("Math.atan2", "Number.NEGATIVE_INFINITY, 0", -Math.PI/2) +testmath("Math.atan2", "Number.NEGATIVE_INFINITY,-0", -Math.PI/2) +testmath("Math.atan2", "Number.NEGATIVE_INFINITY, 1", -Math.PI/2) +testmath("Math.atan2", "Number.NEGATIVE_INFINITY,-1", -Math.PI/2) +testmath("Math.atan2", "Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY", Math.PI/4) +testmath("Math.atan2", "Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY", 3*Math.PI/4) +testmath("Math.atan2", "Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY", -Math.PI/4) +testmath("Math.atan2", "Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY", -3*Math.PI/4) +testmath("Math.atan2", "-1, 1", -Math.PI/4) + +testmath("Math.ceil", "Number.NaN", Number.NaN) +testmath("Math.ceil", "null", 0) +testmath("Math.ceil", "void 0", Number.NaN) +testmath("Math.ceil", "'0'", 0) +testmath("Math.ceil", "'-0'", -0) +testmath("Infinity/Math.ceil", "'0'", Infinity) +testmath("Infinity/Math.ceil", "'-0'", -Infinity) +testmath("Math.ceil", "0", 0) +testmath("Math.ceil", "-0", -0) +testmath("Infinity/Math.ceil", "0", Infinity) +testmath("Infinity/Math.ceil", "-0", -Infinity) +testmath("Math.ceil", "Number.POSITIVE_INFINITY", Number.POSITIVE_INFINITY) +testmath("Math.ceil", "Number.NEGATIVE_INFINITY", Number.NEGATIVE_INFINITY) +testmath("Math.ceil", "-Number.MIN_VALUE", -0) +testmath("Infinity/Math.ceil", "-Number.MIN_VALUE", -Infinity) +testmath("Math.ceil", "1", 1) +testmath("Math.ceil", "-1", -1) +testmath("Math.ceil", "-0.9", -0) +testmath("Infinity/Math.ceil", "-0.9", -Infinity) +testmath("Math.ceil", "0.9", 1) +testmath("Math.ceil", "-1.1", -1) +testmath("Math.ceil", "1.1", 2) +testmath("Math.ceil", "Number.POSITIVE_INFINITY", -Math.floor(-Infinity)) +testmath("Math.ceil", "Number.NEGATIVE_INFINITY", -Math.floor(Infinity)) +testmath("Math.ceil", "-Number.MIN_VALUE", -Math.floor(Number.MIN_VALUE)) +testmath("Math.ceil", "1", -Math.floor(-1)) +testmath("Math.ceil", "-1", -Math.floor(1)) +testmath("Math.ceil", "-0.9", -Math.floor(0.9)) +testmath("Math.ceil", "0.9", -Math.floor(-0.9)) +testmath("Math.ceil", "-1.1", -Math.floor(1.1)) +testmath("Math.ceil", "1.1", -Math.floor(-1.1)) + +testmath("Math.cos", "void 0", Number.NaN) +testmath("Math.cos", "false", 1) +testmath("Math.cos", "null", 1) +testmath("Math.cos", "'0'", 1) +testmath("Math.cos", "\"Infinity\"", Number.NaN) +testmath("Math.cos", "'3.14159265359'", -1) +testmath("Math.cos", "Number.NaN", Number.NaN) +testmath("Math.cos", "0", 1) +testmath("Math.cos", "-0", 1) +testmath("Math.cos", "Number.POSITIVE_INFINITY", Number.NaN) +testmath("Math.cos", "Number.NEGATIVE_INFINITY", Number.NaN) +testmath("Math.cos", "0.7853981633974", 0.7071067811865) +testmath("Math.cos", "1.570796326795", 0) +testmath("Math.cos", "2.356194490192", -0.7071067811865) +testmath("Math.cos", "3.14159265359", -1) +testmath("Math.cos", "3.926990816987", -0.7071067811865) +testmath("Math.cos", "4.712388980385", 0) +testmath("Math.cos", "5.497787143782", 0.7071067811865) +testmath("Math.cos", "Math.PI*2", 1) +testmath("Math.cos", "Math.PI/4", Math.SQRT2/2) +testmath("Math.cos", "Math.PI/2", 0) +testmath("Math.cos", "3*Math.PI/4", -Math.SQRT2/2) +testmath("Math.cos", "Math.PI", -1) +testmath("Math.cos", "5*Math.PI/4", -Math.SQRT2/2) +testmath("Math.cos", "3*Math.PI/2", 0) +testmath("Math.cos", "7*Math.PI/4", Math.SQRT2/2) +testmath("Math.cos", "2*Math.PI", 1) +testmath("Math.cos", "-0.7853981633974", 0.7071067811865) +testmath("Math.cos", "-1.570796326795", 0) +testmath("Math.cos", "2.3561944901920", -.7071067811865) +testmath("Math.cos", "3.14159265359", -1) +testmath("Math.cos", "3.926990816987", -0.7071067811865) +testmath("Math.cos", "4.712388980385", 0) +testmath("Math.cos", "5.497787143782", 0.7071067811865) +testmath("Math.cos", "6.28318530718", 1) +testmath("Math.cos", "-Math.PI/4", Math.SQRT2/2) +testmath("Math.cos", "-Math.PI/2", 0) +testmath("Math.cos", "-3*Math.PI/4", -Math.SQRT2/2) +testmath("Math.cos", "-Math.PI", -1) +testmath("Math.cos", "-5*Math.PI/4", -Math.SQRT2/2) +testmath("Math.cos", "-3*Math.PI/2", 0) +testmath("Math.cos", "-7*Math.PI/4", Math.SQRT2/2) +testmath("Math.cos", "-Math.PI*2", 1) + +testmath("Math.exp", "null", 1) +testmath("Math.exp", "void 0", Number.NaN) +testmath("Math.exp", "1", Math.E) +testmath("Math.exp", "true", Math.E) +testmath("Math.exp", "false", 1) +testmath("Math.exp", "'1'", Math.E) +testmath("Math.exp", "'0'", 1) +testmath("Math.exp", "Number.NaN", Number.NaN) +testmath("Math.exp", "0", 1) +testmath("Math.exp", "-0", 1) +testmath("Math.exp", "Number.POSITIVE_INFINITY", Number.POSITIVE_INFINITY) +testmath("Math.exp", "Number.NEGATIVE_INFINITY", 0) + +testmath("Math.floor", "void 0", Number.NaN) +testmath("Math.floor", "null", 0) +testmath("Math.floor", "true", 1) +testmath("Math.floor", "false", 0) +testmath("Math.floor", "\"1.1\"", 1) +testmath("Math.floor", "\"-1.1\"", -2) +testmath("Math.floor", "\"0.1\"", 0) +testmath("Math.floor", "\"-0.1\"", -1) +testmath("Math.floor", "Number.NaN", Number.NaN) +testmath("Math.floor(Number.NaN) == -Math.ceil", "-Number.NaN", false) +testmath("Math.floor", "0", 0) +testmath("Math.floor(0) == -Math.ceil", "-0", true) +testmath("Math.floor", "-0", -0) +testmath("Infinity/Math.floor", "-0", -Infinity) +testmath("Math.floor(-0)== -Math.ceil", "0", true) +testmath("Math.floor", "Number.POSITIVE_INFINITY", Number.POSITIVE_INFINITY) +testmath("Math.floor(Number.POSITIVE_INFINITY) == -Math.ceil", "Number.NEGATIVE_INFINITY", true) +testmath("Math.floor", "Number.NEGATIVE_INFINITY", Number.NEGATIVE_INFINITY) +testmath("Math.floor(Number.NEGATIVE_INFINITY) == -Math.ceil", "Number.POSITIVE_INFINITY", true) +testmath("Math.floor", "0.0000001", 0) +testmath("Math.floor(0.0000001)==-Math.ceil", "-0.0000001", true) +testmath("Math.floor", "-0.0000001", -1) +testmath("Math.floor(-0.0000001)==-Math.ceil", "0.0000001", true) + +testmath("Math.log", "void 0", Number.NaN) +testmath("Math.log", "null", Number.NEGATIVE_INFINITY) +testmath("Math.log", "true", 0) +testmath("Math.log", "false", -Infinity) +testmath("Math.log", "'0'", -Infinity) +testmath("Math.log", "'1'", 0) +testmath("Math.log", "\"Infinity\"", Infinity) +testmath("Math.log", "Number.NaN", Number.NaN) +testmath("Math.log", "-0.000001", Number.NaN) +testmath("Math.log", "-1", Number.NaN) +testmath("Math.log", "0", Number.NEGATIVE_INFINITY) +testmath("Math.log", "-0", Number.NEGATIVE_INFINITY) +testmath("Math.log", "1", 0) +testmath("Math.log", "Number.POSITIVE_INFINITY", Number.POSITIVE_INFINITY) +testmath("Math.log", "Number.NEGATIVE_INFINITY", Number.NaN) + +testmath("Math.max", "void 0, 1", Number.NaN) +testmath("Math.max", "void 0, void 0", Number.NaN) +testmath("Math.max", "null, 1", 1) +testmath("Math.max", "-1, null", 0) +testmath("Math.max", "true,false", 1) +testmath("Math.max", "\"-99\",\"99\"", 99) +testmath("Math.max", "Number.NaN,Number.POSITIVE_INFINITY", Number.NaN) +testmath("Math.max", "Number.NaN, 0", Number.NaN) +testmath("Math.max", "\"a string\", 0", Number.NaN) +testmath("Math.max", "Number.NaN,1", Number.NaN) +testmath("Math.max", "\"a string\", Number.POSITIVE_INFINITY", Number.NaN) +testmath("Math.max", "Number.POSITIVE_INFINITY, Number.NaN", Number.NaN) +testmath("Math.max", "Number.NaN, Number.NaN", Number.NaN) +testmath("Math.max", "0,Number.NaN", Number.NaN) +testmath("Math.max", "1, Number.NaN", Number.NaN) +testmath("Math.max", "0,0", 0) +testmath("Math.max", "0,-0", 0) +testmath("Math.max", "-0,0", 0) +testmath("Math.max", "-0,-0", -0) +testmath("Infinity/Math.max", "-0,-0", -Infinity) +testmath("Math.max", "Number.POSITIVE_INFINITY, Number.MAX_VALUE", Number.POSITIVE_INFINITY) +testmath("Math.max", "Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY", Number.POSITIVE_INFINITY) +testmath("Math.max", "Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY", Number.NEGATIVE_INFINITY) +testmath("Math.max", "1,.99999999999999", 1) +testmath("Math.max", "-1,-.99999999999999", -.99999999999999) + +testmath("Math.min", "void 0, 1", Number.NaN) +testmath("Math.min", "void 0, void 0", Number.NaN) +testmath("Math.min", "null, 1", 0) +testmath("Math.min", "-1, null", -1) +testmath("Math.min", "true,false", 0) +testmath("Math.min", "\"-99\",\"99\"", -99) +testmath("Math.min", "Number.NaN,0", Number.NaN) +testmath("Math.min", "Number.NaN,1", Number.NaN) +testmath("Math.min", "Number.NaN,-1", Number.NaN) +testmath("Math.min", "0,Number.NaN", Number.NaN) +testmath("Math.min", "1,Number.NaN", Number.NaN) +testmath("Math.min", "-1,Number.NaN", Number.NaN) +testmath("Math.min", "Number.NaN,Number.NaN", Number.NaN) +testmath("Math.min", "1,1.0000000001", 1) +testmath("Math.min", "1.0000000001,1", 1) +testmath("Math.min", "0,0", 0) +testmath("Math.min", "0,-0", -0) +testmath("Math.min", "-0,-0", -0) +testmath("Infinity/Math.min", "0,-0", -Infinity) +testmath("Infinity/Math.min", "-0,-0", -Infinity) + +testmath("Math.pow", "null,null", 1) +testmath("Math.pow", "void 0, void 0", Number.NaN) +testmath("Math.pow", "true, false", 1) +testmath("Math.pow", "false,true", 0) +testmath("Math.pow", "'2','32'", 4294967296) +testmath("Math.pow", "1,Number.NaN", Number.NaN) +testmath("Math.pow", "0,Number.NaN", Number.NaN) +testmath("Math.pow", "Number.NaN,0", 1) +testmath("Math.pow", "Number.NaN,-0", 1) +testmath("Math.pow", "Number.NaN, 1", Number.NaN) +testmath("Math.pow", "Number.NaN, .5", Number.NaN) +testmath("Math.pow", "1.00000001, Number.POSITIVE_INFINITY", Number.POSITIVE_INFINITY) +testmath("Math.pow", "1.00000001, Number.NEGATIVE_INFINITY", 0) +testmath("Math.pow", "-1.00000001,Number.POSITIVE_INFINITY", Number.POSITIVE_INFINITY) +testmath("Math.pow", "-1.00000001,Number.NEGATIVE_INFINITY", 0) +testmath("Math.pow", "1, Number.POSITIVE_INFINITY", Number.NaN) +testmath("Math.pow", "1, Number.NEGATIVE_INFINITY", Number.NaN) +testmath("Math.pow", "-1, Number.POSITIVE_INFINITY", Number.NaN) +testmath("Math.pow", "-1, Number.NEGATIVE_INFINITY", Number.NaN) +testmath("Math.pow", ".0000000009, Number.POSITIVE_INFINITY", 0) +testmath("Math.pow", "-.0000000009, Number.POSITIVE_INFINITY", 0) +testmath("Math.pow", "-.0000000009, Number.NEGATIVE_INFINITY", Number.POSITIVE_INFINITY) +testmath("Math.pow", "Number.POSITIVE_INFINITY,.00000000001", Number.POSITIVE_INFINITY) +testmath("Math.pow", "Number.POSITIVE_INFINITY, 1", Number.POSITIVE_INFINITY) +testmath("Math.pow", "Number.POSITIVE_INFINITY, -.00000000001", 0) +testmath("Math.pow", "Number.POSITIVE_INFINITY, -1", 0) +testmath("Math.pow", "Number.NEGATIVE_INFINITY, 1", Number.NEGATIVE_INFINITY) +testmath("Math.pow", "Number.NEGATIVE_INFINITY, 333", Number.NEGATIVE_INFINITY) +testmath("Math.pow", "Number.POSITIVE_INFINITY, 2", Number.POSITIVE_INFINITY) +testmath("Math.pow", "Number.NEGATIVE_INFINITY, 666", Number.POSITIVE_INFINITY) +testmath("Math.pow", "Number.NEGATIVE_INFINITY, 0.5", Number.POSITIVE_INFINITY) +testmath("Math.pow", "Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY", Number.POSITIVE_INFINITY) +testmath("Math.pow", "Number.NEGATIVE_INFINITY, -1", -0) +testmath("Infinity/Math.pow", "Number.NEGATIVE_INFINITY, -1", -Infinity) +testmath("Math.pow", "Number.NEGATIVE_INFINITY, -3", -0) +testmath("Math.pow", "Number.NEGATIVE_INFINITY, -2", 0) +testmath("Math.pow", "Number.NEGATIVE_INFINITY,-0.5", 0) +testmath("Math.pow", "Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY", 0) +testmath("Math.pow", "0,1", 0) +testmath("Math.pow", "0,0", 1) +testmath("Math.pow", "1,0", 1) +testmath("Math.pow", "-1,0", 1) +testmath("Math.pow", "0,0.5", 0) +testmath("Math.pow", "0,1000", 0) +testmath("Math.pow", "0, Number.POSITIVE_INFINITY", 0) +testmath("Math.pow", "0, -1", Number.POSITIVE_INFINITY) +testmath("Math.pow", "0, -0.5", Number.POSITIVE_INFINITY) +testmath("Math.pow", "0, -1000", Number.POSITIVE_INFINITY) +testmath("Math.pow", "0, Number.NEGATIVE_INFINITY", Number.POSITIVE_INFINITY) +testmath("Math.pow", "-0, 1", -0) +testmath("Math.pow", "-0,3", -0) +testmath("Infinity/Math.pow", "-0, 1", -Infinity) +testmath("Infinity/Math.pow", "-0,3", -Infinity) +testmath("Math.pow", "-0,2", 0) +testmath("Math.pow", "-0, Number.POSITIVE_INFINITY", 0) +testmath("Math.pow", "-0, -1", Number.NEGATIVE_INFINITY) +testmath("Math.pow", "-0, -10001", Number.NEGATIVE_INFINITY) +testmath("Math.pow", "-0, -2", Number.POSITIVE_INFINITY) +testmath("Math.pow", "-0, 0.5", 0) +testmath("Math.pow", "-0, Number.POSITIVE_INFINITY", 0) +testmath("Math.pow", "-1, 0.5", Number.NaN) +testmath("Math.pow", "-1, Number.NaN", Number.NaN) +testmath("Math.pow", "-1, -0.5", Number.NaN) + +testmath("Math.round", "0", 0) +testmath("Math.round", "void 0", Number.NaN) +testmath("Math.round", "true", 1) +testmath("Math.round", "false", 0) +testmath("Math.round", "'.99999'", 1) +testmath("Math.round", "'12345e-2'", 123) +testmath("Math.round", "Number.NaN", Number.NaN) +testmath("Math.round", "0", 0) +testmath("Math.round", "-0", -0) +testmath("Infinity/Math.round", "-0", -Infinity) +testmath("Math.round", "Number.POSITIVE_INFINITY", Number.POSITIVE_INFINITY) +testmath("Math.round", "Number.NEGATIVE_INFINITY", Number.NEGATIVE_INFINITY) +testmath("Math.round", "0.49", 0) +testmath("Math.round", "0.5", 1) +testmath("Math.round", "0.51", 1) +testmath("Math.round", "-0.49", -0) +testmath("Math.round", "-0.5", -0) +testmath("Infinity/Math.round", "-0.49", -Infinity) +testmath("Infinity/Math.round", "-0.5", -Infinity) +testmath("Math.round", "-0.51", -1) +testmath("Math.round", "3.5", 4) +testmath("Math.round", "-3", -3) + +testmath("Math.sin", "null", 0) +testmath("Math.sin", "void 0", Number.NaN) +testmath("Math.sin", "false", 0) +testmath("Math.sin", "'2.356194490192'", 0.7071067811865) +testmath("Math.sin", "Number.NaN", Number.NaN) +testmath("Math.sin", "0", 0) +testmath("Math.sin", "-0", -0) +testmath("Math.sin", "Number.POSITIVE_INFINITY", Number.NaN) +testmath("Math.sin", "Number.NEGATIVE_INFINITY", Number.NaN) +testmath("Math.sin", "0.7853981633974", 0.7071067811865) +testmath("Math.sin", "1.570796326795", 1) +testmath("Math.sin", "2.356194490192", 0.7071067811865) +testmath("Math.sin", "3.14159265359", 0) + +testmath("Math.sqrt", "void 0", Number.NaN) +testmath("Math.sqrt", "null", 0) +testmath("Math.sqrt", "1", 1) +testmath("Math.sqrt", "false", 0) +testmath("Math.sqrt", "'225'", 15) +testmath("Math.sqrt", "Number.NaN", Number.NaN) +testmath("Math.sqrt", "Number.NEGATIVE_INFINITY", Number.NaN) +testmath("Math.sqrt", "-1", Number.NaN) +testmath("Math.sqrt", "-0.5", Number.NaN) +testmath("Math.sqrt", "0", 0) +testmath("Math.sqrt", "-0", -0) +testmath("Infinity/Math.sqrt", "-0", -Infinity) +testmath("Math.sqrt", "Number.POSITIVE_INFINITY", Number.POSITIVE_INFINITY) +testmath("Math.sqrt", "1", 1) +testmath("Math.sqrt", "2", Math.SQRT2) +testmath("Math.sqrt", "0.5", Math.SQRT1_2) +testmath("Math.sqrt", "4", 2) +testmath("Math.sqrt", "9", 3) +testmath("Math.sqrt", "16", 4) +testmath("Math.sqrt", "25", 5) +testmath("Math.sqrt", "36", 6) +testmath("Math.sqrt", "49", 7) +testmath("Math.sqrt", "64", 8) +testmath("Math.sqrt", "256", 16) +testmath("Math.sqrt", "10000", 100) +testmath("Math.sqrt", "65536", 256) +testmath("Math.sqrt", "0.09", 0.3) +testmath("Math.sqrt", "0.01", 0.1) +testmath("Math.sqrt", "0.00000001", 0.0001) + +testmath("Math.tan", "void 0", Number.NaN) +testmath("Math.tan", "null", 0) +testmath("Math.tan", "false", 0) +testmath("Math.tan", "Number.NaN", Number.NaN) +testmath("Math.tan", "0", 0) +testmath("Math.tan", "-0", -0) +testmath("Math.tan", "Number.POSITIVE_INFINITY", Number.NaN) +testmath("Math.tan", "Number.NEGATIVE_INFINITY", Number.NaN) +testmath("Math.tan", "Math.PI/4", 1) +testmath("Math.tan", "3*Math.PI/4", -1) +testmath("Math.tan", "Math.PI", -0) +testmath("Math.tan", "5*Math.PI/4", 1) +testmath("Math.tan", "7*Math.PI/4", -1) +testmath("Infinity/Math.tan", "-0", -Infinity) diff --git a/js/src/jit-test/tests/basic/math-random.js b/js/src/jit-test/tests/basic/math-random.js new file mode 100644 index 0000000000..e9efab5882 --- /dev/null +++ b/js/src/jit-test/tests/basic/math-random.js @@ -0,0 +1,43 @@ +function test() { + setRNGState(0x12341234, 0x98765); + + function f() { + let x = []; + for (let i = 0; i < 10000; i++) { + x.push(Math.random()); + } + return x; + } + let x = f(); + assertEq(x[0], 0.28443027522441433); + assertEq(x[10], 0.5283908544644392); + assertEq(x[100], 0.5593668121538891); + assertEq(x[1000], 0.7008807796441313); + assertEq(x[2000], 0.11737403776989574); + assertEq(x[3000], 0.08573924080320472); + assertEq(x[4000], 0.22428965439295678); + assertEq(x[5000], 0.4657521920883555); + assertEq(x[6000], 0.11816220100329233); + assertEq(x[7000], 0.6306689010335697); + assertEq(x[8000], 0.8654862148946609); + assertEq(x[9000], 0.31734259460387015); + assertEq(x[9999], 0.013959566914027777); + + // Test some other (arbitrary) seeds. + setRNGState(0, 1); + x = f(); + assertEq(x[0], 2.220446049250313e-16); + assertEq(x[2000], 0.8259328082050756); + assertEq(x[6000], 0.01060492365550314); + assertEq(x[9999], 0.7402370773147143); + + setRNGState(0x0fff0101, 0x44440001); + x = f(); + assertEq(x[0], 0.24994062119568194); + assertEq(x[2000], 0.4375430448883283); + assertEq(x[6000], 0.7298689950209452); + assertEq(x[9999], 0.13284280897626954); +} + +if (typeof setRNGState == "function") + test(); diff --git a/js/src/jit-test/tests/basic/mathImul.js b/js/src/jit-test/tests/basic/mathImul.js new file mode 100644 index 0000000000..aa1861e5a7 --- /dev/null +++ b/js/src/jit-test/tests/basic/mathImul.js @@ -0,0 +1,71 @@ + +var table = [ + [NaN, 0, 0], + [Infinity, Infinity, 0], + [NaN, 1000, 0], + + [-1, -2, 2], + [1, 2, 2], + [-1, 2, -2], + [1, -2, -2], + [-0, 0, 0], + [0, -0, 0], + [-1, -0, 0], + [1, -0, 0], + + [0xffffffff, 1, -1], + + [0xffffffff, 0xffffffff, 1], + [0xffffffff, -0xffffffff, -1], + [0xffffffff, 0xfffffffe, 2], + [0xffffffff, -0xfffffffe, -2], + [0x10000, 0x10000, 0], + + [{}, {}, 0], + [[], [], 0], + [{}, [], 0], + [[], {}, 0], + + [{valueOf: function() { return -1; }}, 0x100000, -1048576], + ["3", "-4", -12], + [3.4, 6, 18] +]; + +try { + Math.imul({ valueOf: function() { throw "ha ha ha"; } }); + assertEq(true, false, "no error thrown"); +} catch (e) { + assertEq(e, "ha ha ha"); +} + +var order = []; +assertEq(Math.imul({ valueOf: function() { order.push("first"); return 0; } }, + { valueOf: function() { order.push("second"); return 0; } }), + 0); +assertEq(order[0], "first"); +assertEq(order[1], "second"); + +var seen = []; +try +{ + Math.imul({ valueOf: function() { seen.push("one"); return 17; } }, + { valueOf: function() { throw "abort!"; } }); + assertEq(true, false, "no error thrown"); +} +catch (e) +{ + assertEq(e, "abort!", "should have thrown partway through, instead threw " + e); +} +assertEq(seen.length, 1); +assertEq(seen[0], "one"); + +assertEq(Math.imul(), 0); +assertEq(Math.imul(100), 0); +assertEq(Math.imul(NaN, 100), 0); +assertEq(Math.imul(NaN, NaN), 0); +assertEq(Math.imul(5, Infinity), 0); + +for (var i = 0; i < table.length; i++) { + assertEq(Math.imul(table[i][0], table[i][1]), table[i][2]); + assertEq(Math.imul(table[i][1], table[i][0]), table[i][2]); +} diff --git a/js/src/jit-test/tests/basic/mathRoundBig.js b/js/src/jit-test/tests/basic/mathRoundBig.js new file mode 100644 index 0000000000..e01ffa4f54 --- /dev/null +++ b/js/src/jit-test/tests/basic/mathRoundBig.js @@ -0,0 +1,10 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +assertEq(Math.round(9007199254740991), 9007199254740991); +assertEq(Math.round(-19007199254740990), -19007199254740990); + +assertEq(Math.round("9007199254740991"), 9007199254740991); +assertEq(Math.round("-19007199254740990"), -19007199254740990); diff --git a/js/src/jit-test/tests/basic/max-string-length.js b/js/src/jit-test/tests/basic/max-string-length.js new file mode 100644 index 0000000000..95daaa640a --- /dev/null +++ b/js/src/jit-test/tests/basic/max-string-length.js @@ -0,0 +1,18 @@ +load(libdir + "asserts.js"); + +const MaxStringLength = 2**30 - 2; + +// First check MaxStringLength is accurate. +assertThrowsInstanceOf(() => "a".repeat(MaxStringLength + 1), + RangeError); + +// escape() must handle uint32_t overflow correctly. +var s = "\u0390".repeat(MaxStringLength); +assertEq(s.length, MaxStringLength); +var ex = null; +try { + escape(s); +} catch (e) { + ex = e; +} +assertEq(ex === "out of memory" || (ex instanceof InternalError), true); diff --git a/js/src/jit-test/tests/basic/maxConvertAllArgs.js b/js/src/jit-test/tests/basic/maxConvertAllArgs.js new file mode 100644 index 0000000000..9fd9198404 --- /dev/null +++ b/js/src/jit-test/tests/basic/maxConvertAllArgs.js @@ -0,0 +1,11 @@ +//Bug 818620
+
+load(libdir + "asserts.js");
+
+assertThrowsInstanceOf(function () {
+ Math.max(NaN, { valueOf: function () { throw new Error() } });
+}, Error);
+
+assertThrowsInstanceOf(function () {
+ Math.min(NaN, { valueOf: function () { throw new Error() } });
+}, Error);
diff --git a/js/src/jit-test/tests/basic/megamorphic-setelem-plain.js b/js/src/jit-test/tests/basic/megamorphic-setelem-plain.js new file mode 100644 index 0000000000..0a60a116e8 --- /dev/null +++ b/js/src/jit-test/tests/basic/megamorphic-setelem-plain.js @@ -0,0 +1,53 @@ +setJitCompilerOption("ic.force-megamorphic", 1); + +// The megamorphic SetElem. +function doSet(obj, prop, v) { + "use strict"; + obj[prop] = v; +} +function test() { + with ({}) {} // No inlining. + for (var i = 0; i < 10; i++) { + var obj = {}; + + // Test simple add/set cases. + for (var j = 0; j < 10; j++) { + doSet(obj, "x" + (j % 8), j); + } + + // Ensure __proto__ is handled correctly. + var setterCalls = 0; + var proto = {set someSetter(v) { setterCalls++; }}; + doSet(obj, "__proto__", proto); + assertEq(Object.getPrototypeOf(obj), proto); + + // Can't shadow a non-writable data property. + Object.defineProperty(proto, "readonly", + {value: 1, writable: false, configurable: true}); + var ex = null; + try { + doSet(obj, "readonly", 2); + } catch (e) { + ex = e; + } + assertEq(ex instanceof TypeError, true); + assertEq(obj.readonly, 1); + + // Setter on the proto chain must be called. + doSet(obj, "someSetter", 1); + assertEq(setterCalls, 1); + + // Can't add properties if non-extensible. + Object.preventExtensions(obj); + ex = null; + try { + doSet(obj, "foo", 1); + } catch (e) { + ex = e; + } + assertEq(ex instanceof TypeError, true); + + assertEq(JSON.stringify(obj), '{"x0":8,"x1":9,"x2":2,"x3":3,"x4":4,"x5":5,"x6":6,"x7":7}'); + } +} +test(); diff --git a/js/src/jit-test/tests/basic/merge_type_maps.js b/js/src/jit-test/tests/basic/merge_type_maps.js new file mode 100644 index 0000000000..1be4b9df57 --- /dev/null +++ b/js/src/jit-test/tests/basic/merge_type_maps.js @@ -0,0 +1,9 @@ +var merge_type_maps_x = 0, merge_type_maps_y = 0; +function merge_type_maps() { + for (merge_type_maps_x = 0; merge_type_maps_x < 50; ++merge_type_maps_x) + if ((merge_type_maps_x & 1) == 1) + ++merge_type_maps_y; + return [merge_type_maps_x,merge_type_maps_y].join(","); +} +merge_type_maps(); + diff --git a/js/src/jit-test/tests/basic/metadata-hook-regexp-result.js b/js/src/jit-test/tests/basic/metadata-hook-regexp-result.js new file mode 100644 index 0000000000..cad570db78 --- /dev/null +++ b/js/src/jit-test/tests/basic/metadata-hook-regexp-result.js @@ -0,0 +1,20 @@ +var g = newGlobal({sameCompartmentAs: this}); +g.evaluate(`enableShellAllocationMetadataBuilder()`); + +function f() { + // Ensure a match stub is created for the zone. + var re = /abc.+/; + for (var i = 0; i < 100; i++) { + assertEq(re.exec("..abcd").index, 2); + } + // Allocated match result objects in the realm with the metadata hook + // must have metadata. + g.evaluate(` + var re = /abc.+/; + for (var i = 0; i < 100; i++) { + var obj = re.exec("..abcd"); + assertEq(getAllocationMetadata(obj).stack.length > 0, true); + } + `) +} +f(); diff --git a/js/src/jit-test/tests/basic/metadata-hook.js b/js/src/jit-test/tests/basic/metadata-hook.js new file mode 100644 index 0000000000..2b251ab8c6 --- /dev/null +++ b/js/src/jit-test/tests/basic/metadata-hook.js @@ -0,0 +1,30 @@ + +enableShellAllocationMetadataBuilder(); + +function Foo() { + this.x = 0; + this.y = 1; +} + +function hello() { + function there() { + w = new Foo(); + x = [1,2,3]; + y = [2,3,5]; + z = {a:0,b:1}; + } + callee = there; + callee(); +} +hello(); + +var wc = getAllocationMetadata(w).index; +var xc = getAllocationMetadata(x).index; +var yc = getAllocationMetadata(y).index; +var zc = getAllocationMetadata(z).index; + +assertEq(xc > wc, true); +assertEq(yc > xc, true); +assertEq(zc > yc, true); +assertEq(getAllocationMetadata(x).stack[0], callee); +assertEq(getAllocationMetadata(x).stack[1], hello); diff --git a/js/src/jit-test/tests/basic/missingArgTest.js b/js/src/jit-test/tests/basic/missingArgTest.js new file mode 100644 index 0000000000..28fe79036a --- /dev/null +++ b/js/src/jit-test/tests/basic/missingArgTest.js @@ -0,0 +1,12 @@ +function arity1(x) +{ + return (x == undefined) ? 1 : 0; +} +function missingArgTest() { + var q; + for (var i = 0; i < 10; i++) { + q = arity1(); + } + return q; +} +assertEq(missingArgTest(), 1); diff --git a/js/src/jit-test/tests/basic/missingArgTest2.js b/js/src/jit-test/tests/basic/missingArgTest2.js new file mode 100644 index 0000000000..3d48a369df --- /dev/null +++ b/js/src/jit-test/tests/basic/missingArgTest2.js @@ -0,0 +1,26 @@ +JSON = function () { + return { + stringify: function stringify(value, whitelist) { + switch (typeof(value)) { + case "object": + return value.constructor.name; + } + } + }; +}(); + +function missingArgTest2() { + var testPairs = [ + ["{}", {}], + ["[]", []], + ['{"foo":"bar"}', {"foo":"bar"}], + ] + + var a = []; + for (var i=0; i < testPairs.length; i++) { + var s = JSON.stringify(testPairs[i][1]) + a[i] = s; + } + return a.join(","); +} +assertEq(missingArgTest2(), "Object,Array,Object"); diff --git a/js/src/jit-test/tests/basic/mod-double-power-of-two.js b/js/src/jit-test/tests/basic/mod-double-power-of-two.js new file mode 100644 index 0000000000..30dc7f78f4 --- /dev/null +++ b/js/src/jit-test/tests/basic/mod-double-power-of-two.js @@ -0,0 +1,152 @@ +const isLittleEndian = new Uint8Array(new Uint16Array([1]).buffer)[0] === 1; + +function fromRawBits(s) { + let bits = s.split(" ").map(n => parseInt(n, 16)); + assertEq(bits.length, 8); + if (isLittleEndian) { + bits.reverse(); + } + return new Float64Array(new Uint8Array(bits).buffer)[0]; +} + +function toRawBits(d) { + let bits = [...new Uint8Array(new Float64Array([d]).buffer)]; + if (isLittleEndian) { + bits.reverse(); + } + return bits.map(n => n.toString(16).padStart(2, "0")).join(" "); +} + +assertEq(fromRawBits("7f ef ff ff ff ff ff ff"), Number.MAX_VALUE); +assertEq(toRawBits(Number.MAX_VALUE), "7f ef ff ff ff ff ff ff"); + +assertEq(fromRawBits("00 00 00 00 00 00 00 01"), Number.MIN_VALUE); +assertEq(toRawBits(Number.MIN_VALUE), "00 00 00 00 00 00 00 01"); + +let values = [ + 0, 0.000001, 0.1, 0.125, 1/6, 0.25, 0.3, 1/3, 0.5, 2/3, 0.8, 0.9, + 1, 2, 3, 4, 5, 10, 14, 15, 16, + 100.1, 100.2, + + Number.MAX_SAFE_INTEGER + 4, + Number.MAX_SAFE_INTEGER + 3, + Number.MAX_SAFE_INTEGER + 2, + Number.MAX_SAFE_INTEGER + 1, + Number.MAX_SAFE_INTEGER, + Number.MAX_SAFE_INTEGER - 1, + Number.MAX_SAFE_INTEGER - 2, + Number.MAX_SAFE_INTEGER - 3, + Number.MAX_SAFE_INTEGER - 4, + + // Largest normal (Number.MAX_VALUE) + fromRawBits("7f ef ff ff ff ff ff ff"), + fromRawBits("7f ef ff ff ff ff ff fe"), + fromRawBits("7f ef ff ff ff ff ff fd"), + fromRawBits("7f ef ff ff ff ff ff fc"), + fromRawBits("7f ef ff ff ff ff ff fb"), + fromRawBits("7f ef ff ff ff ff ff fa"), + fromRawBits("7f ef ff ff ff ff ff f9"), + fromRawBits("7f ef ff ff ff ff ff f8"), + fromRawBits("7f ef ff ff ff ff ff f7"), + fromRawBits("7f ef ff ff ff ff ff f6"), + fromRawBits("7f ef ff ff ff ff ff f5"), + fromRawBits("7f ef ff ff ff ff ff f4"), + fromRawBits("7f ef ff ff ff ff ff f3"), + fromRawBits("7f ef ff ff ff ff ff f2"), + fromRawBits("7f ef ff ff ff ff ff f1"), + fromRawBits("7f ef ff ff ff ff ff f0"), + + // Smallest subnormal (Number.MIN_VALUE) + fromRawBits("00 00 00 00 00 00 00 01"), + fromRawBits("00 00 00 00 00 00 00 02"), + fromRawBits("00 00 00 00 00 00 00 03"), + fromRawBits("00 00 00 00 00 00 00 04"), + fromRawBits("00 00 00 00 00 00 00 05"), + fromRawBits("00 00 00 00 00 00 00 06"), + fromRawBits("00 00 00 00 00 00 00 07"), + fromRawBits("00 00 00 00 00 00 00 08"), + fromRawBits("00 00 00 00 00 00 00 09"), + fromRawBits("00 00 00 00 00 00 00 0a"), + fromRawBits("00 00 00 00 00 00 00 0b"), + fromRawBits("00 00 00 00 00 00 00 0c"), + fromRawBits("00 00 00 00 00 00 00 0d"), + fromRawBits("00 00 00 00 00 00 00 0e"), + fromRawBits("00 00 00 00 00 00 00 0f"), + + // Largest subnormal + fromRawBits("00 0f ff ff ff ff ff ff"), + fromRawBits("00 0f ff ff ff ff ff fe"), + fromRawBits("00 0f ff ff ff ff ff fd"), + fromRawBits("00 0f ff ff ff ff ff fc"), + fromRawBits("00 0f ff ff ff ff ff fb"), + fromRawBits("00 0f ff ff ff ff ff fa"), + fromRawBits("00 0f ff ff ff ff ff f9"), + fromRawBits("00 0f ff ff ff ff ff f8"), + fromRawBits("00 0f ff ff ff ff ff f7"), + fromRawBits("00 0f ff ff ff ff ff f6"), + fromRawBits("00 0f ff ff ff ff ff f5"), + fromRawBits("00 0f ff ff ff ff ff f4"), + fromRawBits("00 0f ff ff ff ff ff f3"), + fromRawBits("00 0f ff ff ff ff ff f2"), + fromRawBits("00 0f ff ff ff ff ff f1"), + fromRawBits("00 0f ff ff ff ff ff f0"), + + // Least positive normal + fromRawBits("00 10 00 00 00 00 00 00"), + fromRawBits("00 10 00 00 00 00 00 01"), + fromRawBits("00 10 00 00 00 00 00 02"), + fromRawBits("00 10 00 00 00 00 00 03"), + fromRawBits("00 10 00 00 00 00 00 04"), + fromRawBits("00 10 00 00 00 00 00 05"), + fromRawBits("00 10 00 00 00 00 00 06"), + fromRawBits("00 10 00 00 00 00 00 07"), + fromRawBits("00 10 00 00 00 00 00 08"), + fromRawBits("00 10 00 00 00 00 00 09"), + fromRawBits("00 10 00 00 00 00 00 0a"), + fromRawBits("00 10 00 00 00 00 00 0b"), + fromRawBits("00 10 00 00 00 00 00 0c"), + fromRawBits("00 10 00 00 00 00 00 0d"), + fromRawBits("00 10 00 00 00 00 00 0e"), + fromRawBits("00 10 00 00 00 00 00 0f"), + + Infinity, + NaN, + + Math.E, Math.LN10, Math.LN2, Math.LOG10E, Math.LOG2E, + Math.PI, Math.SQRT1_2, Math.SQRT2, +]; + +// Also test with sign bit set. +values = values.concat(values.map(x => -x)); + +function mod(n, d) { + with ({}); // disable Ion + return n % d; +} + +function makeTest(divisor) { + function test() { + let expected = values.map(x => mod(x, divisor)); + + for (let i = 0; i < 2000; ++i) { + let j = i % values.length; + assertEq(values[j] % divisor, expected[j]); + } + } + + // Create a new function for each divisor to ensure we have proper compile-time constants. + return Function(`return ${test.toString().replaceAll("divisor", divisor)}`)(); +} + +// The optimisation is used for power of two values up to 2^31. +for (let i = 0; i <= 31; ++i) { + let divisor = 2 ** i; + let f = makeTest(divisor); + f(); +} + +// Also cover some cases which don't trigger the optimisation +for (let divisor of [-3, -2, -1, -0.5, 0, 0.5, 3, 5, 10]) { + let f = makeTest(divisor); + f(); +} diff --git a/js/src/jit-test/tests/basic/mod.js b/js/src/jit-test/tests/basic/mod.js new file mode 100644 index 0000000000..cd8f6f6b96 --- /dev/null +++ b/js/src/jit-test/tests/basic/mod.js @@ -0,0 +1,14 @@ +function mod() +{ + var mods = [-1,-1,-1,-1]; + var a = 9.5, b = -5, c = 42, d = (1/0); + for (var i = 0; i < 20; i++) { + mods[0] = a % b; + mods[1] = b % 1; + mods[2] = c % d; + mods[3] = c % a; + mods[4] = b % 0; + } + return mods.toString(); +} +assertEq(mod(), "4.5,0,42,4,NaN"); diff --git a/js/src/jit-test/tests/basic/more-compartments-flag.js b/js/src/jit-test/tests/basic/more-compartments-flag.js new file mode 100644 index 0000000000..fa0e13f165 --- /dev/null +++ b/js/src/jit-test/tests/basic/more-compartments-flag.js @@ -0,0 +1,8 @@ +// |jit-test| --more-compartments + +// With --more-compartments we should default to creating a new compartment for +// new globals. + +var g = newGlobal(); +assertEq(isSameCompartment(this, g), false); +assertEq(isProxy(g), true); diff --git a/js/src/jit-test/tests/basic/multiple-declared-args-syntax.js b/js/src/jit-test/tests/basic/multiple-declared-args-syntax.js new file mode 100644 index 0000000000..d41a98fcca --- /dev/null +++ b/js/src/jit-test/tests/basic/multiple-declared-args-syntax.js @@ -0,0 +1 @@ +assertEq((function (a, b, a) { return a; })(2, 4, 6), 6); diff --git a/js/src/jit-test/tests/basic/mutable-proto-teleporting.js b/js/src/jit-test/tests/basic/mutable-proto-teleporting.js new file mode 100644 index 0000000000..a52faf1c58 --- /dev/null +++ b/js/src/jit-test/tests/basic/mutable-proto-teleporting.js @@ -0,0 +1,18 @@ +// The teleporting optimization should work correctly +// when we modify an object's proto. + +var A = {x: 1}; +var B = Object.create(A); + +var C = {}; +C.__proto__ = B; + +function f() { + for (var i=0; i<25; i++) { + assertEq(C.x, (i <= 20) ? 1 : 3); + if (i === 20) { + B.x = 3; + } + } +} +f(); diff --git a/js/src/jit-test/tests/basic/name-inactive-del.js b/js/src/jit-test/tests/basic/name-inactive-del.js new file mode 100644 index 0000000000..ba2f69f09e --- /dev/null +++ b/js/src/jit-test/tests/basic/name-inactive-del.js @@ -0,0 +1,28 @@ +function mp(g) { + var ans = ''; + for (var i = 0; i < 5; ++i) { + ans += g(); + } + + return ans; +} + +function f() { + var k = 5; + + function g() { + return k; + } + + ans = ''; + + k = 6; + ans += mp(g); + + delete k; + ans += mp(g); + + return ans; +} + +assertEq(f(), '6666666666'); diff --git a/js/src/jit-test/tests/basic/name-inactive-eval-del.js b/js/src/jit-test/tests/basic/name-inactive-eval-del.js new file mode 100644 index 0000000000..593ab39ffe --- /dev/null +++ b/js/src/jit-test/tests/basic/name-inactive-eval-del.js @@ -0,0 +1,10 @@ +function mp(g) { + ans = '' + for (var i = 0; i < 5; ++i) { + ans += g(); + } + return ans; +} + +var f = eval("(function() { var k = 5; function g() { return k; } k = 6; mp(g); delete k; return mp(g); })"); +assertEq(f(), "66666"); diff --git a/js/src/jit-test/tests/basic/name-inactive-inferflags.js b/js/src/jit-test/tests/basic/name-inactive-inferflags.js new file mode 100644 index 0000000000..0bbd3fb2cf --- /dev/null +++ b/js/src/jit-test/tests/basic/name-inactive-inferflags.js @@ -0,0 +1,18 @@ +function addAccumulations(f) { + var a = f(); + var b = f(); + return a() + b(); +} + +function loopingAccumulator() { + var x = 0; + return function () { + for (var i = 0; i < 10; ++i) { + ++x; + } + return x; + } +} + +var x = addAccumulations(loopingAccumulator); +assertEq(x, 20); diff --git a/js/src/jit-test/tests/basic/name-inactive.js b/js/src/jit-test/tests/basic/name-inactive.js new file mode 100644 index 0000000000..6f3b9c4c0a --- /dev/null +++ b/js/src/jit-test/tests/basic/name-inactive.js @@ -0,0 +1,15 @@ +function f(k) { + function g(j) { + return j + k; + } + return g; +} + +g = f(10); +var ans = ''; +for (var i = 0; i < 5; ++i) { + ans += g(i) + ','; +} + +assertEq(ans, '10,11,12,13,14,'); + diff --git a/js/src/jit-test/tests/basic/name.js b/js/src/jit-test/tests/basic/name.js new file mode 100644 index 0000000000..92b76d0225 --- /dev/null +++ b/js/src/jit-test/tests/basic/name.js @@ -0,0 +1,9 @@ +globalName = 907; +function name() +{ + var a = 0; + for (var i = 0; i < 100; i++) + a = globalName; + return a; +} +assertEq(name(), 907); diff --git a/js/src/jit-test/tests/basic/negative-zero-index.js b/js/src/jit-test/tests/basic/negative-zero-index.js new file mode 100644 index 0000000000..7f585a115e --- /dev/null +++ b/js/src/jit-test/tests/basic/negative-zero-index.js @@ -0,0 +1,20 @@ +function test() { + const array = [1]; + for (let i = 0; i < 10; i++) { + assertEq(array[0], 1); + assertEq(array[0.0], 1); + assertEq(array[-0.0], 1); + // ToPropertyKey(-0.0) is "0", but "-0" is distinct! + assertEq(array["-0"], undefined); + } + + const string = "a"; + for (let i = 0; i < 10; i++) { + assertEq(string[0], "a"); + assertEq(string[0.0], "a"); + assertEq(string[-0.0], "a"); + assertEq(string["-0"], undefined); + } +} + +test(); diff --git a/js/src/jit-test/tests/basic/nestedContinue.js b/js/src/jit-test/tests/basic/nestedContinue.js new file mode 100644 index 0000000000..23cd702bf9 --- /dev/null +++ b/js/src/jit-test/tests/basic/nestedContinue.js @@ -0,0 +1,11 @@ +x = 10; +outer: +while (x < 10) { + while (x < 10) { + if (x < 10) + continue outer; + while (x < 10) { + y = 0; + } + } +} diff --git a/js/src/jit-test/tests/basic/nestedExit2.js b/js/src/jit-test/tests/basic/nestedExit2.js new file mode 100644 index 0000000000..a868954f28 --- /dev/null +++ b/js/src/jit-test/tests/basic/nestedExit2.js @@ -0,0 +1,17 @@ +function bitsinbyte(b) { + var m = 1, c = 0; + while(m<0x100) { + if(b & m) c++; + m <<= 1; + } + return 1; +} +function TimeFunc(func) { + var x,y; + for(var y=0; y<256; y++) func(y); +} +function nestedExit2() { + TimeFunc(bitsinbyte); + return "ok"; +} +assertEq(nestedExit2(), "ok"); diff --git a/js/src/jit-test/tests/basic/nestedExitLoop.js b/js/src/jit-test/tests/basic/nestedExitLoop.js new file mode 100644 index 0000000000..fffc8573bd --- /dev/null +++ b/js/src/jit-test/tests/basic/nestedExitLoop.js @@ -0,0 +1,14 @@ +function nestedExit(x) { + var q = 0; + for (var i = 0; i < 10; ++i) + { + if (x) + ++q; + } +} +function nestedExitLoop() { + for (var j = 0; j < 10; ++j) + nestedExit(j < 7); + return "ok"; +} +assertEq(nestedExitLoop(), "ok"); diff --git a/js/src/jit-test/tests/basic/new-Function-prototype.js b/js/src/jit-test/tests/basic/new-Function-prototype.js new file mode 100644 index 0000000000..65198cabb1 --- /dev/null +++ b/js/src/jit-test/tests/basic/new-Function-prototype.js @@ -0,0 +1,16 @@ +var funProto = Function.prototype; +assertEq(Object.getOwnPropertyDescriptor(funProto, "prototype"), undefined); +assertEq(parseInt.prototype, undefined); +var oldObj; +for (var i = 0, sz = 9; i < sz; oldObj = obj, i++) +{ + + try { + var obj = new funProto; + } + catch (e) {} + assertEq(Object.getOwnPropertyDescriptor(funProto, "prototype"), undefined); + assertEq(Object.getOwnPropertyDescriptor(parseInt, "prototype"), undefined); + assertEq(parseInt.prototype, undefined); +} + diff --git a/js/src/jit-test/tests/basic/new-bound-function.js b/js/src/jit-test/tests/basic/new-bound-function.js new file mode 100644 index 0000000000..49d06d8c3c --- /dev/null +++ b/js/src/jit-test/tests/basic/new-bound-function.js @@ -0,0 +1,20 @@ +var funProto = Function.prototype; +assertEq(Object.getOwnPropertyDescriptor(funProto, "prototype"), undefined); + +function Point(x, y) { this.x = x; this.y = y; } + +var YAxisPoint = Point.bind(null, 0); + +assertEq(YAxisPoint.prototype, undefined); + +var oldPoint; +for (var i = 0, sz = 9; i < sz; oldPoint = point, i++) +{ + var point = new YAxisPoint(5); + assertEq(point === oldPoint, false); + assertEq(point.x, 0); + assertEq(point.y, 5); + assertEq(Object.getOwnPropertyDescriptor(funProto, "prototype"), undefined); + assertEq(Object.getOwnPropertyDescriptor(YAxisPoint, "prototype"), undefined); +} + diff --git a/js/src/jit-test/tests/basic/new-read-before-write.js b/js/src/jit-test/tests/basic/new-read-before-write.js new file mode 100644 index 0000000000..a5259b2116 --- /dev/null +++ b/js/src/jit-test/tests/basic/new-read-before-write.js @@ -0,0 +1,24 @@ + +function Foo() { + var x = this.property; + this.property = 5; + glob = x; +} +Foo.prototype.property = 10; +for (var i = 0; i < 10; i++) { + new Foo(); + assertEq(glob, 10); +} + +function Bar() { + this.property; + this.other = 5; +} +Bar.prototype.other = 10; +Object.defineProperty(Bar.prototype, "property", { + get: function() { glob = this.other; } +}); +for (var i = 0; i < 10; i++) { + new Bar(); + assertEq(glob, 10); +} diff --git a/js/src/jit-test/tests/basic/newArrayTest.js b/js/src/jit-test/tests/basic/newArrayTest.js new file mode 100644 index 0000000000..aca33bcfd1 --- /dev/null +++ b/js/src/jit-test/tests/basic/newArrayTest.js @@ -0,0 +1,8 @@ +function newArrayTest() +{ + var a = []; + for (var i = 0; i < 10; i++) + a[i] = new Array(); + return a.map(x => x.length).toString(); +} +assertEq(newArrayTest(), "0,0,0,0,0,0,0,0,0,0"); diff --git a/js/src/jit-test/tests/basic/newTargetOSR.js b/js/src/jit-test/tests/basic/newTargetOSR.js new file mode 100644 index 0000000000..b90e96cf1b --- /dev/null +++ b/js/src/jit-test/tests/basic/newTargetOSR.js @@ -0,0 +1,6 @@ +function testOSRNewTarget(expected) { + for (let i = 0; i < 1100; i++) + assertEq(new.target, expected); +} + +new testOSRNewTarget(testOSRNewTarget); diff --git a/js/src/jit-test/tests/basic/newTargetRectifier.js b/js/src/jit-test/tests/basic/newTargetRectifier.js new file mode 100644 index 0000000000..78716869fb --- /dev/null +++ b/js/src/jit-test/tests/basic/newTargetRectifier.js @@ -0,0 +1,12 @@ +function testBailoutNewTarget() { + function Inner(ex, forceRectifier) { + bailout(); + assertEq(new.target, ex); + } + + for (let i = 0; i < 1100; i++) + new Inner(Inner); +} + +for (let i = 0; i < 15; i++) + testBailoutNewTarget(); diff --git a/js/src/jit-test/tests/basic/newTest.js b/js/src/jit-test/tests/basic/newTest.js new file mode 100644 index 0000000000..5defbe9f26 --- /dev/null +++ b/js/src/jit-test/tests/basic/newTest.js @@ -0,0 +1,14 @@ +function MyConstructor(i) +{ + this.i = i; +} +MyConstructor.prototype.toString = function() {return this.i + ""}; + +function newTest() +{ + var a = []; + for (var i = 0; i < 10; i++) + a[i] = new MyConstructor(i); + return a.join(""); +} +assertEq(newTest(), "0123456789"); diff --git a/js/src/jit-test/tests/basic/non-constructor-msg.js b/js/src/jit-test/tests/basic/non-constructor-msg.js new file mode 100644 index 0000000000..dc86f05d19 --- /dev/null +++ b/js/src/jit-test/tests/basic/non-constructor-msg.js @@ -0,0 +1,7 @@ +load(libdir + 'asserts.js'); + +// Censor potentially existing toSource to trigger fallback in ValueToSource. +Function.prototype.toSource = null; + +assertTypeErrorMessage(() => { new (function*() {}) }, + "(function*() {}) is not a constructor"); diff --git a/js/src/jit-test/tests/basic/non-extensible-array.js b/js/src/jit-test/tests/basic/non-extensible-array.js new file mode 100644 index 0000000000..133ec2bf12 --- /dev/null +++ b/js/src/jit-test/tests/basic/non-extensible-array.js @@ -0,0 +1,7 @@ + +function foo(x) { + Object.seal(x); + x[3] = 4; + assertEq("" + x, "1,2,3"); +} +foo([1,2,3]); diff --git a/js/src/jit-test/tests/basic/non-extensible-elements1.js b/js/src/jit-test/tests/basic/non-extensible-elements1.js new file mode 100644 index 0000000000..01831931a8 --- /dev/null +++ b/js/src/jit-test/tests/basic/non-extensible-elements1.js @@ -0,0 +1,50 @@ +function testTestIntegrityLevel(a, hasElems) { + assertEq(Object.isExtensible(a), true); + assertEq(Object.isSealed(a), false); + assertEq(Object.isFrozen(a), false); + + Object.preventExtensions(a); + assertEq(Object.isExtensible(a), false); + assertEq(Object.isSealed(a), !hasElems); + assertEq(Object.isFrozen(a), false); + + Object.seal(a); + assertEq(Object.isExtensible(a), false); + assertEq(Object.isSealed(a), true); + assertEq(Object.isFrozen(a), false); + + Object.freeze(a); + assertEq(Object.isExtensible(a), false); + assertEq(Object.isSealed(a), true); + assertEq(Object.isFrozen(a), true); +} +testTestIntegrityLevel([1, 2, 3], true); +testTestIntegrityLevel([1, , , 2], true); +testTestIntegrityLevel([1, , , ], true); +testTestIntegrityLevel([, , , ], false); +testTestIntegrityLevel([], false); +testTestIntegrityLevel({0: 0}, true); +var a = [,,,,,,, 1]; +a.pop(); +testTestIntegrityLevel(a, false); + +function testDescriptor() { + var a = [1]; + Object.preventExtensions(a); + assertEq(JSON.stringify(Object.getOwnPropertyDescriptors(a)), + `{"0":{"value":1,"writable":true,"enumerable":true,"configurable":true},` + + `"length":{"value":1,"writable":true,"enumerable":false,"configurable":false}}`); + + a = [1]; + Object.seal(a); + assertEq(JSON.stringify(Object.getOwnPropertyDescriptors(a)), + `{"0":{"value":1,"writable":true,"enumerable":true,"configurable":false},` + + `"length":{"value":1,"writable":true,"enumerable":false,"configurable":false}}`); + + a = [1]; + Object.freeze(a); + assertEq(JSON.stringify(Object.getOwnPropertyDescriptors(a)), + `{"0":{"value":1,"writable":false,"enumerable":true,"configurable":false},` + + `"length":{"value":1,"writable":false,"enumerable":false,"configurable":false}}`); +} +testDescriptor(); diff --git a/js/src/jit-test/tests/basic/non-extensible-elements2.js b/js/src/jit-test/tests/basic/non-extensible-elements2.js new file mode 100644 index 0000000000..dd31b81ce5 --- /dev/null +++ b/js/src/jit-test/tests/basic/non-extensible-elements2.js @@ -0,0 +1,279 @@ +load(libdir + "asserts.js"); + +function testPopSimple() { + var a = [4, 3, 2, 1, 0]; + Object.preventExtensions(a); + for (var i = 0; i < 5; i++) + assertEq(a.pop(), i); + assertEq(a.length, 0); + + a = [1, 2, 3]; + Object.seal(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.pop(), TypeError); + assertEq(a.toString(), "1,2,3"); + + a = [1, 2, 3]; + Object.freeze(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.pop(), TypeError); + assertEq(a.toString(), "1,2,3"); +} +testPopSimple(); + +function testPopHoles() { + var a = [1, , 3]; + Object.preventExtensions(a); + assertEq(a.pop(), 3); + assertEq(a.pop(), undefined); + assertEq(a.pop(), 1); + assertEq(a.length, 0); + + a = [1, ,]; + Object.seal(a); + assertEq(a.pop(), undefined); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.pop(), TypeError); + assertEq(a.toString(), "1"); + + a = [1, ,]; + Object.freeze(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.pop(), TypeError); + assertEq(a.toString(), "1,"); +} +testPopHoles(); + +function testPushSimple() { + var a = [1, 2, 3]; + Object.preventExtensions(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.push(4), TypeError); + assertEq(a.length, 3); + assertEq(a.toString(), "1,2,3"); + + a = [1, 2, 3]; + Object.seal(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.push(4), TypeError); + assertEq(a.toString(), "1,2,3"); + + a = [1, 2, 3]; + Object.freeze(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.push(4), TypeError); + assertEq(a.toString(), "1,2,3"); +} +testPushSimple(); + +function testPushHoles() { + var a = [,,,]; + Object.preventExtensions(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.push(4), TypeError); + assertEq(a.length, 3); + assertEq(a.toString(), ",,"); + + a = [,,,]; + Object.seal(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.push(4), TypeError); + assertEq(a.toString(), ",,"); + + a = [,,,]; + Object.freeze(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.push(4), TypeError); + assertEq(a.toString(), ",,"); +} +testPushHoles(); + +function testReverseSimple() { + var a = [1, 2, 3]; + Object.preventExtensions(a); + a.reverse(); + assertEq(a.toString(), "3,2,1"); + + a = [1, 2, 3]; + Object.seal(a); + a.reverse(); + assertEq(a.toString(), "3,2,1"); + + a = [1, 2, 3]; + Object.freeze(a); + assertThrowsInstanceOf(() => a.reverse(), TypeError); + assertEq(a.toString(), "1,2,3"); +} +testReverseSimple(); + +function testReverseHoles() { + var a = [1, 2, , 4]; + Object.preventExtensions(a); + assertThrowsInstanceOf(() => a.reverse(), TypeError); + assertEq(a.toString(), "4,,,1"); + + a = [1, 2, , 4]; + Object.seal(a); + assertThrowsInstanceOf(() => a.reverse(), TypeError); + assertEq(a.toString(), "4,2,,1"); + + a = [1, 2, , 4]; + Object.freeze(a); + assertThrowsInstanceOf(() => a.reverse(), TypeError); + assertEq(a.toString(), "1,2,,4"); +} +testReverseHoles(); + +function testShiftSimple() { + var a = [1, 2, 3]; + Object.preventExtensions(a); + assertEq(a.shift(), 1); + assertEq(a.toString(), "2,3"); + for (var i = 0; i < 10; i++) + a.shift(); + assertEq(a.length, 0); + + a = [1, 2, 3]; + Object.seal(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.shift(), TypeError); + assertEq(a.toString(), "3,3,3"); + + a = [1, 2, 3]; + Object.freeze(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.shift(), TypeError); + assertEq(a.toString(), "1,2,3"); +} +testShiftSimple(); +testShiftSimple(); + +function testShiftHoles() { + var a = [1, 2, , 4]; + Object.preventExtensions(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.shift(), TypeError); + assertEq(a.toString(), ",,,4"); + + a = [1, 2, , 4]; + Object.seal(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.shift(), TypeError); + assertEq(a.toString(), "2,2,,4"); + + a = [1, 2, , 4]; + Object.freeze(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.shift(), TypeError); + assertEq(a.toString(), "1,2,,4"); +} +testShiftHoles(); +testShiftHoles(); + +function testUnshiftSimple() { + var a = [1, 2, 3]; + Object.preventExtensions(a); + assertThrowsInstanceOf(() => a.unshift(0), TypeError); + assertEq(a.toString(), "1,2,3"); + + a = [1, 2, 3]; + Object.seal(a); + assertThrowsInstanceOf(() => a.unshift(0), TypeError); + assertEq(a.toString(), "1,2,3"); + + a = [1, 2, 3]; + Object.freeze(a); + assertThrowsInstanceOf(() => a.unshift(0), TypeError); + assertEq(a.toString(), "1,2,3"); +} +testUnshiftSimple(); + +function testUnshiftHoles() { + var a = [,,,]; + Object.preventExtensions(a); + assertThrowsInstanceOf(() => a.unshift(0), TypeError); + assertEq(a.toString(), ",,"); + + a = [,,,]; + Object.seal(a); + assertThrowsInstanceOf(() => a.unshift(0), TypeError); + assertEq(a.toString(), ",,"); + + a = [,,,]; + Object.freeze(a); + assertThrowsInstanceOf(() => a.unshift(0), TypeError); + assertEq(a.toString(), ",,"); +} +testUnshiftHoles(); + +function testSpliceDelete() { + var a = [1, 2, 3]; + Object.preventExtensions(a); + a.splice(1, 2); + assertEq(a.toString(), "1"); + + a = [1, 2, 3]; + Object.seal(a); + assertThrowsInstanceOf(() => a.splice(1, 2), TypeError); + assertEq(a.toString(), "1,2,3"); + + a = [1, 2, 3]; + Object.freeze(a); + assertThrowsInstanceOf(() => a.splice(1, 2), TypeError); + assertEq(a.toString(), "1,2,3"); +} +testSpliceDelete(); + +function testSpliceAdd() { + var a = [1, 2, 3]; + Object.preventExtensions(a); + assertThrowsInstanceOf(() => a.splice(2, 1, 4, 5), TypeError); + assertEq(a.toString(), "1,2,4"); + + a = [1, 2, 3]; + Object.seal(a); + assertThrowsInstanceOf(() => a.splice(2, 1, 4, 5), TypeError); + assertEq(a.toString(), "1,2,4"); + + a = [1, 2, 3]; + Object.freeze(a); + assertThrowsInstanceOf(() => a.splice(2, 1, 4, 5), TypeError); + assertEq(a.toString(), "1,2,3"); +} +testSpliceAdd(); + +function testSortSimple() { + var a = [3, 1, 2]; + Object.preventExtensions(a); + a.sort(); + assertEq(a.toString(), "1,2,3"); + + a = [3, 1, 2]; + Object.seal(a); + a.sort(); + assertEq(a.toString(), "1,2,3"); + + a = [3, 1, 2]; + Object.freeze(a); + assertThrowsInstanceOf(() => a.sort(), TypeError); + assertEq(a.toString(), "3,1,2"); +} +testSortSimple(); + +function testSortHoles() { + var a = [, , 3, 1, 2]; + Object.preventExtensions(a); + assertThrowsInstanceOf(() => a.sort(), TypeError); + assertEq(a.toString(), ",,3,1,2"); + + a = [, , 3, 1, 2]; + Object.seal(a); + assertThrowsInstanceOf(() => a.sort(), TypeError); + assertEq(a.toString(), ",,3,1,2"); + + a = [, , 3, 1, 2]; + Object.freeze(a); + assertThrowsInstanceOf(() => a.sort(), TypeError); + assertEq(a.toString(), ",,3,1,2"); +} +testSortHoles(); diff --git a/js/src/jit-test/tests/basic/non-extensible-elements3.js b/js/src/jit-test/tests/basic/non-extensible-elements3.js new file mode 100644 index 0000000000..eed7e0c1bd --- /dev/null +++ b/js/src/jit-test/tests/basic/non-extensible-elements3.js @@ -0,0 +1,65 @@ +function testAdd() { + var a = []; + Object.preventExtensions(a); + for (var i = 0; i < 20; i++) + a[i] = i; + assertEq(a.length, 0); + + a = []; + Object.seal(a); + for (var i = 0; i < 20; i++) + a[i] = i; + assertEq(a.length, 0); + + a = []; + Object.freeze(a); + for (var i = 0; i < 20; i++) + a[i] = i; + assertEq(a.length, 0); +} +testAdd(); +testAdd(); + +function testSet() { + var a = [1, 2, 3]; + Object.preventExtensions(a); + for (var i = 0; i < 20; i++) + a[2] = i; + assertEq(a.toString(), "1,2,19"); + + a = [1, 2, 3]; + Object.seal(a); + for (var i = 0; i < 20; i++) + a[0] = i; + assertEq(a.toString(), "19,2,3"); + + a = [1, 2, 3]; + Object.freeze(a); + for (var i = 0; i < 20; i++) + a[1] = i; + assertEq(a.toString(), "1,2,3"); +} +testSet(); +testSet(); + +function testSetHole() { + var a = [1, , 3]; + Object.preventExtensions(a); + for (var i = 0; i < 30; i++) + a[1] = i; + assertEq(a.toString(), "1,,3"); + + a = [1, , 3]; + Object.seal(a); + for (var i = 0; i < 30; i++) + a[1] = i; + assertEq(a.toString(), "1,,3"); + + a = [1, , 3]; + Object.freeze(a); + for (var i = 0; i < 30; i++) + a[1] = i; + assertEq(a.toString(), "1,,3"); +} +testSetHole(); +testSetHole(); diff --git a/js/src/jit-test/tests/basic/non-extensible-elements4.js b/js/src/jit-test/tests/basic/non-extensible-elements4.js new file mode 100644 index 0000000000..6b14b97c6f --- /dev/null +++ b/js/src/jit-test/tests/basic/non-extensible-elements4.js @@ -0,0 +1,27 @@ +// When an already-non-extensible object is frozen, its Shape doesn't change. +// Make sure SetElement ICs handle this correctly. + +function doStore(a) { + for (var i = 0; i < 100; i++) { + a[1] = i; + } +} +function test() { + with(this) {} // Don't Ion-compile. + + var a = {0: 0, 1: 1}; + Object.preventExtensions(a); + doStore(a); + assertEq(a[1], 99); + + a[1] = 0; + Object.freeze(a); + doStore(a); + assertEq(a[1], 0); +} + +setJitCompilerOption("ion.forceinlineCaches", 1); +test(); + +setJitCompilerOption("ion.forceinlineCaches", 0); +test(); diff --git a/js/src/jit-test/tests/basic/non-extensible-elements5.js b/js/src/jit-test/tests/basic/non-extensible-elements5.js new file mode 100644 index 0000000000..00cfee2a39 --- /dev/null +++ b/js/src/jit-test/tests/basic/non-extensible-elements5.js @@ -0,0 +1,15 @@ +// Make sure a non-extensible proto object that's later frozen is handled +// correctly by AddElement ICs. +function f() { + var proto = {60: "ok"}; + Object.preventExtensions(proto); + var o = Object.create(proto); + for (var i = 0; i < 65; i++) { + o[i] = i; + if (i === 50) + Object.freeze(proto); + } + assertEq(o[60], "ok"); + assertEq(o[61], 61); +} +f(); diff --git a/js/src/jit-test/tests/basic/non-extensible-elements6.js b/js/src/jit-test/tests/basic/non-extensible-elements6.js new file mode 100644 index 0000000000..9e865be910 --- /dev/null +++ b/js/src/jit-test/tests/basic/non-extensible-elements6.js @@ -0,0 +1,144 @@ +load(libdir + "asserts.js"); + +function testNonExtensible() { + var a = [1, 2, 3, , 5]; + Object.preventExtensions(a); + + // Can change the value. + Object.defineProperty(a, 1, {value:7, enumerable: true, configurable: true, writable: true}); + assertEq(JSON.stringify(Object.getOwnPropertyDescriptor(a, 1)), + `{"value":7,"writable":true,"enumerable":true,"configurable":true}`); + + // Can make non-writable, non-configurable, non-enumerable. + Object.defineProperty(a, 1, {value:9, enumerable: true, configurable: true, writable: false}); + assertEq(JSON.stringify(Object.getOwnPropertyDescriptor(a, 1)), + `{"value":9,"writable":false,"enumerable":true,"configurable":true}`); + Object.defineProperty(a, 0, {value:4, enumerable: true, configurable: false, writable: true}); + assertEq(JSON.stringify(Object.getOwnPropertyDescriptor(a, 0)), + `{"value":4,"writable":true,"enumerable":true,"configurable":false}`); + Object.defineProperty(a, 2, {value:3, enumerable: false, configurable: true, writable: true}); + assertEq(JSON.stringify(Object.getOwnPropertyDescriptor(a, 2)), + `{"value":3,"writable":true,"enumerable":false,"configurable":true}`); + + // Turn into an accessor. + Object.defineProperty(a, 4, {get:() => -2, enumerable: true, configurable: true}); + + // Can't add new properties. + assertThrowsInstanceOf(() => Object.defineProperty(a, 3, + {value:4, enumerable: true, + configurable: true, + writable: true}), + TypeError); + assertThrowsInstanceOf(() => Object.defineProperty(a, 10, + {value:4, + enumerable: true, + configurable: true, + writable: true}), + TypeError); + + assertEq(a.toString(), "4,9,3,,-2"); +} +for (var i = 0; i < 15; i++) + testNonExtensible(); + +function testSealed() { + var a = [1, 2, 3, , 5]; + Object.seal(a); + + // Can change the value. + Object.defineProperty(a, 1, {value:7, enumerable: true, configurable: false, writable: true}); + assertEq(JSON.stringify(Object.getOwnPropertyDescriptor(a, 1)), + `{"value":7,"writable":true,"enumerable":true,"configurable":false}`); + + // Can make non-writable. + Object.defineProperty(a, 0, {value:4, enumerable: true, configurable: false, writable: false}); + + // Can't make configurable, non-enumerable. + assertThrowsInstanceOf(() => Object.defineProperty(a, 2, + {value:7, + enumerable: true, + configurable: true, + writable: true}), + TypeError); + assertThrowsInstanceOf(() => Object.defineProperty(a, 2, + {value:7, + enumerable: false, + configurable: false, + writable: true}), + TypeError); + + // Can't turn into an accessor. + assertThrowsInstanceOf(() => Object.defineProperty(a, 4, {get:() => -2, + enumerable: true, + configurable: true}), + TypeError); + + // Can't add new properties. + assertThrowsInstanceOf(() => Object.defineProperty(a, 3, + {value:4, enumerable: true, + configurable: true, + writable: true}), + TypeError); + assertThrowsInstanceOf(() => Object.defineProperty(a, 10, + {value:4, + enumerable: true, + configurable: true, + writable: true}), + TypeError); + + assertEq(a.toString(), "4,7,3,,5"); +} +for (var i = 0; i < 15; i++) + testSealed(); + +function testFrozen() { + var a = [1, 2, 3, , 5]; + Object.freeze(a); + + // Can redefine with same value/attributes. + Object.defineProperty(a, 0, {value:1, enumerable: true, configurable: false, writable: false}); + + // Can't change the value. + assertThrowsInstanceOf(() => Object.defineProperty(a, 1, + {value:7, + enumerable: true, + configurable: false, + writable: false}), + TypeError); + + // Can't make configurable, non-enumerable. + assertThrowsInstanceOf(() => Object.defineProperty(a, 2, + {value:3, + enumerable: true, + configurable: true, + writable: false}), + TypeError); + assertThrowsInstanceOf(() => Object.defineProperty(a, 2, + {value:3, + enumerable: false, + configurable: false, + writable: false}), + TypeError); + // Can't turn into an accessor. + assertThrowsInstanceOf(() => Object.defineProperty(a, 4, {get:() => -2, + enumerable: true, + configurable: true}), + TypeError); + + // Can't add new properties. + assertThrowsInstanceOf(() => Object.defineProperty(a, 3, + {value:4, enumerable: true, + configurable: true, + writable: true}), + TypeError); + assertThrowsInstanceOf(() => Object.defineProperty(a, 10, + {value:4, + enumerable: true, + configurable: true, + writable: true}), + TypeError); + + assertEq(a.toString(), "1,2,3,,5"); +} +for (var i = 0; i < 15; i++) + testFrozen(); diff --git a/js/src/jit-test/tests/basic/non-extensible-elements7.js b/js/src/jit-test/tests/basic/non-extensible-elements7.js new file mode 100644 index 0000000000..6c4d2a3485 --- /dev/null +++ b/js/src/jit-test/tests/basic/non-extensible-elements7.js @@ -0,0 +1,42 @@ +// Test array.length setter on non-extensible/sealed/frozen arrays. +"use strict"; + +load(libdir + "asserts.js"); + +function testNonExtensible() { + var a = [1, 2, 3, , ,]; + Object.preventExtensions(a); + for (var i = 0; i < 10; i++) + a.length = 10; + assertEq(a.length, 10); + for (var i = 0; i < 10; i++) + a.length = 0; + assertEq(a.length, 0); + assertEq(a.toString(), ""); +} +testNonExtensible(); + +function testSealed() { + var a = [1, 2, 3, , ,]; + Object.seal(a); + for (var i = 0; i < 10; i++) + a.length = 10; + assertEq(a.length, 10); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.length = 0, TypeError); + assertEq(a.length, 3); + assertEq(a.toString(), "1,2,3"); +} +testSealed(); + +function testFrozen() { + var a = [1, 2, 3, , ,]; + Object.freeze(a); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.length = 10, TypeError); + for (var i = 0; i < 10; i++) + assertThrowsInstanceOf(() => a.length = 0, TypeError); + assertEq(a.length, 5); + assertEq(a.toString(), "1,2,3,,"); +} +testFrozen(); diff --git a/js/src/jit-test/tests/basic/non-extensible-elements8.js b/js/src/jit-test/tests/basic/non-extensible-elements8.js new file mode 100644 index 0000000000..6139cac32a --- /dev/null +++ b/js/src/jit-test/tests/basic/non-extensible-elements8.js @@ -0,0 +1,43 @@ +function testSealNonExtensibleArray() { + var obj = Object.preventExtensions([0]); + var desc = {value: 0, writable: true, enumerable: true, configurable: true}; + + var errorAt = -1; + var N = 100; + + for (var i = 0; i <= N; ++i) { + if (i === N) { + Object.seal(obj); + } + try { + Object.defineProperty(obj, 0, desc); + } catch { + errorAt = i; + } + } + assertEq(errorAt, N); +} +for (var i = 0; i < 15; i++) + testSealNonExtensibleArray(); + +function testSealNonExtensibleObject() { + var obj = Object.preventExtensions({0:1}); + var desc = {value: 0, writable: true, enumerable: true, configurable: true}; + + var errorAt = -1; + var N = 100; + + for (var i = 0; i <= N; ++i) { + if (i === N) { + Object.seal(obj); + } + try { + Object.defineProperty(obj, 0, desc); + } catch { + errorAt = i; + } + } + assertEq(errorAt, N); +} +for (var i = 0; i < 15; i++) + testSealNonExtensibleObject(); diff --git a/js/src/jit-test/tests/basic/non-extensible-elements9.js b/js/src/jit-test/tests/basic/non-extensible-elements9.js new file mode 100644 index 0000000000..847a7d006e --- /dev/null +++ b/js/src/jit-test/tests/basic/non-extensible-elements9.js @@ -0,0 +1,187 @@ +function testNonExtensibleStoreFallibleT() { + // Create an array with initialized-length = capacity = 2. + var x = [8, 0]; + + // Make it non-extensible. + Object.preventExtensions(x); + + // Now reduce initialized-length by one, so that initialized-length < capacity is true. + x.length = 1; + + // There's enough capacity in the elements storage to save the new element, + // but we still need to reject the store since the object is non-extensible. + x[1] = 4; + + assertEq(x.length, 1); + assertEq(x[0], 8); +} + +for (var i = 0; i < 15; ++i) + testNonExtensibleStoreFallibleT(); + +// Repeat testNonExtensibleStoreFallibleT for the MIRType::Value specialization. +function testNonExtensibleStoreFallibleV(i) { + // Create an array with initialized-length = capacity = 2. + var x = [8, ""]; + + // Make it non-extensible. + Object.preventExtensions(x); + + // Now reduce initialized-length by one, so that initialized-length < capacity is true. + x.length = 1; + + // There's enough capacity in the elements storage to save the new element, + // but we still need to reject the store since the object is non-extensible. + x[1] = [true, 1][i & 1]; + + assertEq(x.length, 1); + assertEq(x[0], 8); +} + +for (var i = 0; i < 15; ++i) + testNonExtensibleStoreFallibleV(i); + +function testForInIterationNonExtensibleStoreFallibleT() { + // Create an array with initialized-length = capacity = 2. + var x = [8, 0]; + + // Make it non-extensible. + Object.preventExtensions(x); + + // Modifying an array's length takes a different path during for-in + // iteration of the array. + for (var k in x) { + // Now reduce initialized-length by one, so that initialized-length < capacity is true. + x.length = 1; + } + + // There's enough capacity in the elements storage to save the new element, + // but we still need to reject the store since the object is non-extensible. + x[1] = 4; + + assertEq(x.length, 1); + assertEq(x[0], 8); +} + +for (var i = 0; i < 15; ++i) + testForInIterationNonExtensibleStoreFallibleT(); + +// Repeat testForInIterationNonExtensibleStoreFallibleT for the MIRType::Value specialization. +function testForInIterationNonExtensibleStoreFallibleV(i) { + // Create an array with initialized-length = capacity = 2. + var x = [8, ""]; + + // Make it non-extensible. + Object.preventExtensions(x); + + // Modifying an array's length takes a different path during for-in + // iteration of the array. + for (var k in x) { + // Now reduce initialized-length by one, so that initialized-length < capacity is true. + x.length = 1; + break; + } + + // There's enough capacity in the elements storage to save the new element, + // but we still need to reject the store since the object is non-extensible. + x[1] = [true, 1][i & 1]; + + assertEq(x.length, 1); + assertEq(x[0], 8); +} + +for (var i = 0; i < 15; ++i) + testForInIterationNonExtensibleStoreFallibleV(i); + +function testNonExtensibleArrayPop() { + // Create an array with initialized-length = capacity = 2. + var x = [8, 0]; + + // Make it non-extensible. + Object.preventExtensions(x); + + // Now reduce initialized-length by one, so that initialized-length < capacity is true. + x.pop(); + + // There's enough capacity in the elements storage to save the new element, + // but we still need to reject the store since the object is non-extensible. + x[1] = 4; + + assertEq(x.length, 1); + assertEq(x[0], 8); +} + +for (var i = 0; i < 15; ++i) + testNonExtensibleArrayPop(); + +function testNonExtensibleArrayPopNonWritable() { + // Create an array with initialized-length = capacity = 2. + var x = [8, 0]; + + // Make it non-extensible. + Object.preventExtensions(x); + + // And make the "length" property non-writable. + Object.defineProperty(x, "length", {writable: false}); + + // Now reduce initialized-length by one, so that initialized-length < capacity is true. + // This doesn't update |x.length|, because the "length" property is non-writable. + try { + x.pop(); + } catch {} + + // There's enough capacity in the elements storage to save the new element, + // but we still need to reject the store since the object is non-extensible. + for (var i = 0; i < 100; ++i) + x[1] = 4; + + assertEq(x.length, 2); + assertEq(x[0], 8); + assertEq(x[1], undefined); + assertEq(1 in x, false); +} + +for (var i = 0; i < 15; ++i) + testNonExtensibleArrayPopNonWritable(); + +function testNonExtensibleArrayShift() { + // Create an array with initialized-length = capacity = 2. + var x = [8, 0]; + + // Make it non-extensible. + Object.preventExtensions(x); + + // Now reduce initialized-length by one, so that initialized-length < capacity is true. + x.shift(); + + // There's enough capacity in the elements storage to save the new element, + // but we still need to reject the store since the object is non-extensible. + x[1] = 4; + + assertEq(x.length, 1); + assertEq(x[0], 0); +} + +for (var i = 0; i < 15; ++i) + testNonExtensibleArrayShift(); + +function testNonExtensibleArraySplice() { + // Create an array with initialized-length = capacity = 2. + var x = [8, 0]; + + // Make it non-extensible. + Object.preventExtensions(x); + + // Now reduce initialized-length by one, so that initialized-length < capacity is true. + x.splice(1, 1); + + // There's enough capacity in the elements storage to save the new element, + // but we still need to reject the store since the object is non-extensible. + x[1] = 4; + + assertEq(x.length, 1); + assertEq(x[0], 8); +} + +for (var i = 0; i < 15; ++i) + testNonExtensibleArraySplice(); diff --git a/js/src/jit-test/tests/basic/nonEmptyStack1.js b/js/src/jit-test/tests/basic/nonEmptyStack1.js new file mode 100644 index 0000000000..b3b2603868 --- /dev/null +++ b/js/src/jit-test/tests/basic/nonEmptyStack1.js @@ -0,0 +1,13 @@ +function nonEmptyStack1Helper(o, farble) { + var a = []; + var j = 0; + for (var i in o) + a[j++] = i; + return a.join(""); +} + +function nonEmptyStack1() { + return nonEmptyStack1Helper({a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8}, "hi"); +} + +assertEq(nonEmptyStack1(), "abcdefgh"); diff --git a/js/src/jit-test/tests/basic/nonEmptyStack2.js b/js/src/jit-test/tests/basic/nonEmptyStack2.js new file mode 100644 index 0000000000..fb83942457 --- /dev/null +++ b/js/src/jit-test/tests/basic/nonEmptyStack2.js @@ -0,0 +1,10 @@ +function nonEmptyStack2() +{ + var a = 0; + for (var c in {a:1, b:2, c:3}) { + for (var i = 0; i < 10; i++) + a += i; + } + return String(a); +} +assertEq(nonEmptyStack2(), "135"); diff --git a/js/src/jit-test/tests/basic/null-filename-Error.js b/js/src/jit-test/tests/basic/null-filename-Error.js new file mode 100644 index 0000000000..acba373462 --- /dev/null +++ b/js/src/jit-test/tests/basic/null-filename-Error.js @@ -0,0 +1,11 @@ +// Compiling a script with null filename does not break the Error constructor. + +var exc = null; +try { + evaluate("throw Error('pass');", {fileName: null}); +} catch (x) { + exc = x; +} +assertEq(exc.constructor, Error); +assertEq(exc.message, "pass"); +assertEq(exc.fileName, ""); diff --git a/js/src/jit-test/tests/basic/number-isfinite.js b/js/src/jit-test/tests/basic/number-isfinite.js new file mode 100644 index 0000000000..fc58b4c667 --- /dev/null +++ b/js/src/jit-test/tests/basic/number-isfinite.js @@ -0,0 +1,15 @@ +assertEq(Number.isFinite(Infinity), false); +assertEq(Number.isFinite(-Infinity), false); +assertEq(Number.isFinite(NaN), false); +assertEq(Number.isFinite(4), true); +assertEq(Number.isFinite(4.5), true); +assertEq(Number.isFinite("hi"), false); +assertEq(Number.isFinite("1.3"), false); +assertEq(Number.isFinite("51"), false); +assertEq(Number.isFinite(0), true); +assertEq(Number.isFinite(-0), true); +assertEq(Number.isFinite({valueOf: function () { return 3; }}), false); +assertEq(Number.isFinite({valueOf: function () { return 0/0; }}), false); +assertEq(Number.isFinite({ valueOf: function() { throw 17; } }), false); +assertEq(Number.isFinite({ toString: function() { throw 17; } }), false); +assertEq(Number.isFinite({ valueOf: function() { throw 17; }, toString: function() { throw 42; } }), false); diff --git a/js/src/jit-test/tests/basic/number-isinteger.js b/js/src/jit-test/tests/basic/number-isinteger.js new file mode 100644 index 0000000000..750a987871 --- /dev/null +++ b/js/src/jit-test/tests/basic/number-isinteger.js @@ -0,0 +1,15 @@ +assertEq(Number.isInteger(4), true); +assertEq(Number.isInteger(4.), true); +assertEq(Number.isInteger(4.2), false); +assertEq(Number.isInteger(0.), true); +assertEq(Number.isInteger(-0.), true); +assertEq(Number.isInteger(Infinity), false); +assertEq(Number.isInteger(-Infinity), false); +assertEq(Number.isInteger(NaN), false); +assertEq(Number.isInteger(true), false); +assertEq(Number.isInteger(false), false); +assertEq(Number.isInteger({valueOf: function () { return 3; }}), false); +assertEq(Number.isInteger({valueOf: function () { return 0/0; }}), false); +assertEq(Number.isInteger({ valueOf: function() { throw 17; } }), false); +assertEq(Number.isInteger({ toString: function() { throw 17; } }), false); +assertEq(Number.isInteger({ valueOf: function() { throw 17; }, toString: function() { throw 42; } }), false); diff --git a/js/src/jit-test/tests/basic/number-isnan.js b/js/src/jit-test/tests/basic/number-isnan.js new file mode 100644 index 0000000000..78e8345918 --- /dev/null +++ b/js/src/jit-test/tests/basic/number-isnan.js @@ -0,0 +1,15 @@ +assertEq(Number.isNaN(NaN), true); +assertEq(Number.isNaN(0/0), true); +assertEq(Number.isNaN(Number("NaN")), true); +assertEq(Number.isNaN(4), false); +assertEq(Number.isNaN(4.5), false); +assertEq(Number.isNaN("hi"), false); +assertEq(Number.isNaN("1.3"), false); +assertEq(Number.isNaN("51"), false); +assertEq(Number.isNaN(0), false); +assertEq(Number.isNaN(-0), false); +assertEq(Number.isNaN({valueOf: function () { return 3; }}), false); +assertEq(Number.isNaN({valueOf: function () { return 0/0; }}), false); +assertEq(Number.isNaN({ valueOf: function() { throw 17; } }), false); +assertEq(Number.isNaN({ toString: function() { throw 17; } }), false); +assertEq(Number.isNaN({ valueOf: function() { throw 17; }, toString: function() { throw 42; } }), false); diff --git a/js/src/jit-test/tests/basic/number-methods-this-error.js b/js/src/jit-test/tests/basic/number-methods-this-error.js new file mode 100644 index 0000000000..6d5a710bb1 --- /dev/null +++ b/js/src/jit-test/tests/basic/number-methods-this-error.js @@ -0,0 +1,12 @@ +load(libdir + "asserts.js"); + +let methods = Object.getOwnPropertyNames(Number.prototype) + .filter(n => n != "constructor"); + +for (let method of methods) { + assertTypeErrorMessage(() => Number.prototype[method].call(new Map), + `Number.prototype.${method} called on incompatible Map`); + + assertTypeErrorMessage(() => Number.prototype[method].call(false), + `Number.prototype.${method} called on incompatible boolean`); +} diff --git a/js/src/jit-test/tests/basic/object-assign-plain-cache.js b/js/src/jit-test/tests/basic/object-assign-plain-cache.js new file mode 100644 index 0000000000..8c6c163857 --- /dev/null +++ b/js/src/jit-test/tests/basic/object-assign-plain-cache.js @@ -0,0 +1,68 @@ +// The cache lookup must happen after ensuring there are no dense elements. +function testNewDenseElement() { + var from = {x: 1, y: 2, z: 3}; + + for (var i = 0; i < 10; i++) { + if (i === 6) { + from[0] = 1; + } + var to = Object.assign({}, from); + if (i >= 6) { + assertEq(JSON.stringify(to), '{"0":1,"x":1,"y":2,"z":3}'); + } else { + assertEq(JSON.stringify(to), '{"x":1,"y":2,"z":3}'); + } + } +} +testNewDenseElement(); + +// The cache lookup must happen after ensuring there are non-writable +// properties on the proto chain. +function testProtoNonWritable() { + var proto = {x: 1}; + var from = {x: 1, y: 2, z: 3}; + + for (var i = 0; i < 10; i++) { + if (i === 6) { + Object.freeze(proto); + } + + var to = Object.create(proto); + var ex = null; + try { + Object.assign(to, from); + } catch (e) { + ex = e; + } + + assertEq(ex instanceof TypeError, i > 5); + + if (i <= 5) { + assertEq(JSON.stringify(to), '{"x":1,"y":2,"z":3}'); + } else { + assertEq(JSON.stringify(to), '{}'); + } + } +} +testProtoNonWritable(); + +function testDictionary1() { + var from = {a: 1, b: 2, c: 3}; + delete from.a; + for (var i = 0; i < 10; i++) { + var to = Object.assign({}, from); + assertEq(JSON.stringify(to), '{"b":2,"c":3}'); + } +} +testDictionary1(); + +function testDictionary2() { + var from = {a: 1, b: 2, c: 3}; + delete from.a; + from.a = 4; + for (var i = 0; i < 10; i++) { + var to = Object.assign({}, from); + assertEq(JSON.stringify(to), '{"b":2,"c":3,"a":4}'); + } +} +testDictionary2(); diff --git a/js/src/jit-test/tests/basic/object-assign-plain.js b/js/src/jit-test/tests/basic/object-assign-plain.js new file mode 100644 index 0000000000..cf0db7134e --- /dev/null +++ b/js/src/jit-test/tests/basic/object-assign-plain.js @@ -0,0 +1,148 @@ +// Tests for Object.assign's fast path for plain objects. + +load(libdir + "asserts.js"); + +function testProtoSetter() { + var from = Object.create(null); + from.__proto__ = {}; + assertEq(Object.getPrototypeOf(from), null); + + var to = Object.assign({}, from); + assertEq(Object.getPrototypeOf(to), from.__proto__); + assertEq(Object.getOwnPropertyNames(to).length, 0); +} +testProtoSetter(); +testProtoSetter(); +testProtoSetter(); + +function testProtoDataProp() { + var to = Object.create(null); + to.__proto__ = 1; + var from = Object.create(null); + from.__proto__ = 2; + Object.assign(to, from); + assertEq(Object.getPrototypeOf(to), null); + assertEq(to.__proto__, 2); +} +testProtoDataProp(); +testProtoDataProp(); +testProtoDataProp(); + +function testNonExtensible() { + var to = Object.preventExtensions({x: 1}); + Object.assign(to, {x: 2}); + assertEq(to.x, 2); + assertThrowsInstanceOf(() => Object.assign(to, {x: 3, y: 4}), TypeError); + assertEq(to.x, 3); + assertEq("y" in to, false); +} +testNonExtensible(); +testNonExtensible(); +testNonExtensible(); + +function testNonExtensibleNoProps() { + var to = Object.preventExtensions({}); + Object.assign(to, {}); // No exception. +} +testNonExtensibleNoProps(); +testNonExtensibleNoProps(); +testNonExtensibleNoProps(); + +function testDenseElements() { + var to = Object.assign({}, {0: 1, 1: 2}); + assertEq(to[0], 1); + assertEq(to[1], 2); +} +testDenseElements(); +testDenseElements(); +testDenseElements(); + +function testNonWritableOnProto() { + var proto = {}; + Object.defineProperty(proto, "x", {value: 1, enumerable: true, configurable: true}); + var to = Object.create(proto); + assertThrowsInstanceOf(() => Object.assign(to, {x: 2}), TypeError); + assertEq(to.x, 1); + assertEq(Object.getOwnPropertyNames(to).length, 0); +} +testNonWritableOnProto(); +testNonWritableOnProto(); +testNonWritableOnProto(); + +function testAccessorOnProto() { + var setterVal; + var proto = {set a(v) { setterVal = v; }}; + var to = Object.assign(Object.create(proto), {a: 9}); + assertEq(setterVal, 9); + assertEq(Object.getOwnPropertyNames(to).length, 0); +} +testAccessorOnProto(); +testAccessorOnProto(); +testAccessorOnProto(); + +function testSetAndAdd() { + var to = Object.assign({x: 1, y: 2}, {x: 3, y: 4, z: 5}); + assertEq(to.x, 3); + assertEq(to.y, 4); + assertEq(to.z, 5); +} +testSetAndAdd(); +testSetAndAdd(); +testSetAndAdd(); + +function testNonConfigurableFrom() { + var from = {}; + Object.defineProperty(from, "x", {value: 1, enumerable: true, writable: true}); + var to = Object.assign({}, from); + assertEq(to.x, 1); + assertEq(Object.getOwnPropertyDescriptor(to, "x").configurable, true); +} +testNonConfigurableFrom(); +testNonConfigurableFrom(); +testNonConfigurableFrom(); + +function testNonEnumerableFrom() { + var from = {}; + Object.defineProperty(from, "x", {value: 1, configurable: true, writable: true}); + var to = Object.assign({}, from); + assertEq(Object.getOwnPropertyNames(to).length, 0); + assertEq(to.x, undefined); +} +testNonEnumerableFrom(); +testNonEnumerableFrom(); +testNonEnumerableFrom(); + +function testNonWritableFrom() { + var from = {}; + Object.defineProperty(from, "x", {value: 1, configurable: true, enumerable: true}); + var to = Object.assign({}, from); + assertEq(to.x, 1); + assertEq(Object.getOwnPropertyDescriptor(to, "x").writable, true); +} +testNonWritableFrom(); +testNonWritableFrom(); +testNonWritableFrom(); + +function testFrozenProto() { + var proto = Object.freeze({x: 1}); + var target = Object.create(proto); + Object.assign(target, {foo: 1}); + assertEq(target.foo, 1); + assertThrowsInstanceOf(() => Object.assign(target, {x: 2}), TypeError); + assertEq(target.x, 1); +} +testFrozenProto(); +testFrozenProto(); +testFrozenProto(); + +function testReuseShape() { + var from = {}; + from.x = 1; + from.y = 2; + var to = Object.assign({}, from); + assertEq(to.x, 1); + assertEq(to.y, 2); +} +testReuseShape(); +testReuseShape(); +testReuseShape(); diff --git a/js/src/jit-test/tests/basic/object-assign.js b/js/src/jit-test/tests/basic/object-assign.js new file mode 100644 index 0000000000..0b1297849a --- /dev/null +++ b/js/src/jit-test/tests/basic/object-assign.js @@ -0,0 +1,135 @@ +function test() { + var from, to; + + // Property changes value. + from = {x: 1, y: 2}; + to = {set x(v) { from.y = 5; }}; + Object.assign(to, from); + assertEq(to.y, 5); + + // Property becomes a getter. + from = {x: 1, y: 2}; + to = {set x(v) { Object.defineProperty(from, "y", {get: () => 4}); }}; + Object.assign(to, from); + assertEq(to.y, 4); + + // Property becomes non-enumerable. + from = {x: 1, y: 2}; + to = {set x(v) { Object.defineProperty(from, "y", {value: 2, + enumerable: false, + configurable: true, + writable: true}); }}; + Object.assign(to, from); + assertEq("y" in to, false); + to = {}; + Object.assign(to, from); + assertEq("y" in to, false); + + // Property is deleted. Should NOT get Object.prototype.toString. + from = {x: 1, toString: 2}; + to = {set x(v) { delete from.toString; }}; + Object.assign(to, from); + assertEq(to.hasOwnProperty("toString"), false); + + from = {toString: 2, x: 1}; + to = {set x(v) { delete from.toString; }}; + Object.assign(to, from); + assertEq(to.toString, 2); + + from = {x: 1, toString: 2, y: 3}; + to = {set x(v) { delete from.toString; }}; + Object.assign(to, from); + assertEq(to.hasOwnProperty("toString"), false); + assertEq(to.y, 3); + + // New property is added. + from = {x: 1, y: 2}; + to = {set x(v) { from.z = 3; }}; + Object.assign(to, from); + assertEq("z" in to, false); + + // From getter. + var c = 7; + from = {x: 1, get y() { return ++c; }}; + to = {}; + Object.assign(to, from); + Object.assign(to, from, from); + assertEq(to.y, 10); + + // Frozen object. + from = {x: 1, y: 2}; + to = {x: 4}; + Object.freeze(to); + var ex; + try { + Object.assign(to, from); + } catch (e) { + ex = e; + } + assertEq(ex instanceof TypeError, true); + assertEq(to.x, 4); + + // Non-writable property. + from = {x: 1, y: 2, z: 3}; + to = {}; + Object.defineProperty(to, "y", {value: 9, writable: false}); + ex = null; + try { + Object.assign(to, from); + } catch(e) { + ex = e; + } + assertEq(ex instanceof TypeError, true); + assertEq(to.x, 1); + assertEq(to.y, 9); + assertEq(to.z, undefined); + + // Array with dense elements. + from = [1, 2, 3]; + to = {}; + Object.assign(to, from); + assertEq(to[2], 3); + assertEq("length" in to, false); + + // Object with sparse elements and symbols. + from = {x: 1, 1234567: 2, 1234560: 3,[Symbol.iterator]: 5, z: 3}; + to = {}; + Object.assign(to, from); + assertEq(to[1234567], 2); + assertEq(Object.keys(to).toString(), "1234560,1234567,x,z"); + assertEq(to[Symbol.iterator], 5); + + // Symbol properties need to be assigned last. + from = {x: 1, [Symbol.iterator]: 2, y: 3}; + to = {set y(v) { throw 9; }}; + ex = null; + try { + Object.assign(to, from); + } catch (e) { + ex = e; + } + assertEq(ex, 9); + assertEq(to.x, 1); + assertEq(to.hasOwnProperty(Symbol.iterator), false); + + // Typed array. + from = new Int32Array([1, 2, 3]); + to = {}; + Object.assign(to, from); + assertEq(to[1], 2); + + // Primitive string. + from = "foo"; + to = {}; + Object.assign(to, from); + assertEq(to[0], "f"); + + // String object. + from = new String("bar"); + to = {}; + Object.assign(to, from); + assertEq(to[2], "r"); +} +test(); +test(); +test(); diff --git a/js/src/jit-test/tests/basic/object-is-inlined.js b/js/src/jit-test/tests/basic/object-is-inlined.js new file mode 100644 index 0000000000..0220175c11 --- /dev/null +++ b/js/src/jit-test/tests/basic/object-is-inlined.js @@ -0,0 +1,48 @@ +function SameValue(x, y) { + if (x === y) { + return (x !== 0) || (1 / x === 1 / y); + } + return (x !== x && y !== y); +} + +function* cartesian(a, b = a) { + for (var pa of a) { + for (var pb of b) { + yield [pa, pb]; + } + } +} + +var testValues = { + Double: `[-0.0, +0.0, 1.0, NaN]`, + Int32: `[-1, 0, 1, 2]`, + Value: `[-0.0, +0.0, "", NaN]`, +}; + +for (var [xs, ys] of cartesian(Object.values(testValues))) { + var fn = Function(` + var xs = ${xs}; + var ys = ${ys}; + assertEq(xs.length, 4); + assertEq(ys.length, 4); + + // Compare each entry in xs with each entry in ys and ensure Object.is + // computes the same result as SameValue. + var actual = 0, expected = 0; + for (var i = 0; i < 1000; ++i) { + // 0 1 2 3 + var xi = i & 3; + + // 0 1 2 3 1 2 3 0 2 3 0 1 3 0 1 2 + var yi = (i + ((i >> 2) & 3)) & 3; + + actual += Object.is(xs[xi], ys[yi]) ? 1 : 0; + expected += SameValue(xs[xi], ys[yi]) ? 1 : 0; + } + assertEq(actual, expected); + `); + for (var i = 0; i < 3; ++i) { + fn(); + } +} + diff --git a/js/src/jit-test/tests/basic/object-is-polymorphic.js b/js/src/jit-test/tests/basic/object-is-polymorphic.js new file mode 100644 index 0000000000..137c710c15 --- /dev/null +++ b/js/src/jit-test/tests/basic/object-is-polymorphic.js @@ -0,0 +1,20 @@ +function foo(arr) { + var result = 0; + for (var i = 0; i < arr.length; i++) { + for (var j = 0; j < arr.length; j++) { + if (Object.is(arr[i], arr[j])) { + result++; + } + } + } + return result; +} + +var input = [1,"one",{x:1}, + 1,"one",{x:1}]; + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(input); +} +assertEq(sum, 1000); diff --git a/js/src/jit-test/tests/basic/object-is.js b/js/src/jit-test/tests/basic/object-is.js new file mode 100644 index 0000000000..a62b5dfe80 --- /dev/null +++ b/js/src/jit-test/tests/basic/object-is.js @@ -0,0 +1,41 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var list = [ + [1, 1, true], + [0, 1, false], + [3.5, 3.5, true], + [0, 0, true], + [0, -0, false], + [-0, 0, false], + [-0, -0, true], + + [true, true, true], + [true, false, false], + [false, false, true], + + [NaN, NaN, true], + [NaN, undefined, false], + [Infinity, -Infinity, false], + [Infinity, Infinity, true], +] + +for (var test of list) { + assertEq(Object.is(test[0], test[1]), test[2]) +} + +var obj = {} +assertEq(Object.is(obj, obj), true); +assertEq(Object.is(obj, {}), false); +assertEq(Object.is([], []), false); + +assertEq(Object.is(null, null, null), true); + +/* Not defined parameters are undefined ... */ +assertEq(Object.is(null), false); +assertEq(Object.is(undefined), true); +assertEq(Object.is(), true); + +assertEq(Object.is.length, 2); diff --git a/js/src/jit-test/tests/basic/object-lookup-shadowing.js b/js/src/jit-test/tests/basic/object-lookup-shadowing.js new file mode 100644 index 0000000000..927727e32a --- /dev/null +++ b/js/src/jit-test/tests/basic/object-lookup-shadowing.js @@ -0,0 +1,5 @@ +var x = {get prop() { return 2; }, set prop(v) {}}; +var y = {__proto__: x, prop: 1}; + +assertEq(y.__lookupGetter__("prop"), undefined); +assertEq(y.__lookupSetter__("prop"), undefined); diff --git a/js/src/jit-test/tests/basic/object-loose-equality.js b/js/src/jit-test/tests/basic/object-loose-equality.js new file mode 100644 index 0000000000..b1f72960b3 --- /dev/null +++ b/js/src/jit-test/tests/basic/object-loose-equality.js @@ -0,0 +1,58 @@ +var obj = {}; +var sym = Symbol(); + +var notEqual = [ + [obj, sym], + + [0, {valueOf() { return null; }}], + [0, {toString() { return null; }}], + [null, {valueOf() { return null; }}], + [null, {toString() { return null; }}], + [undefined, {valueOf() { return null; }}], + [undefined, {toString() { return null; }}], + ["", {valueOf() { return null; }}], + ["", {toString() { return null; }}], + ["0", {valueOf() { return null; }}], + ["0", {toString() { return null; }}], + + [0, {valueOf() { return undefined; }}], + [0, {toString() { return undefined; }}], + [null, {valueOf() { return undefined; }}], + [null, {toString() { return undefined; }}], + [undefined, {valueOf() { return undefined; }}], + [undefined, {toString() { return undefined; }}], + ["", {valueOf() { return undefined; }}], + ["", {toString() { return undefined; }}], + ["0", {valueOf() { return undefined; }}], + ["0", {toString() { return undefined; }}], +] + +var equal = [ + [sym, {valueOf() { return sym; }}], + [sym, {toString() { return sym; }}], + + ["abc", {valueOf() { return "abc"; }}], + ["abc", {toString() { return "abc"; }}], + + [1, {valueOf() { return 1; }}], + [1, {toString() { return 1; }}], + + [1, {valueOf() { return true; }}], + [1, {toString() { return true; }}], + + [true, {valueOf() { return true; }}], + [true, {toString() { return true; }}], + + [true, {valueOf() { return 1; }}], + [true, {toString() { return 1; }}], +] + +for (var [lhs, rhs] of notEqual) { + assertEq(lhs == rhs, false); + assertEq(rhs == lhs, false); +} + +for (var [lhs, rhs] of equal) { + assertEq(lhs == rhs, true); + assertEq(rhs == lhs, true); +} diff --git a/js/src/jit-test/tests/basic/object-rest.js b/js/src/jit-test/tests/basic/object-rest.js new file mode 100644 index 0000000000..b8fb8102ad --- /dev/null +++ b/js/src/jit-test/tests/basic/object-rest.js @@ -0,0 +1,90 @@ +function test() { + var from, to; + + // From values. + from = {x: 1, y: 2}; + ({...to} = from); + assertEq(to.y, 2); + + var z; + from = {x: 1, y: 2}; + ({x: z, ...to} = from); + assertEq(z, 1); + assertEq(to.y, 2); + + // From getter. + var c = 7; + from = {x: 1, get y() { return ++c; }}; + ({...to} = from); + assertEq(c, 8); + assertEq(to.y, 8); + + from = {x: 1, get y() { return ++c; }}; + ({y: z, ...to} = from); + assertEq(c, 9); + assertEq(z, 9); + assertEq(to.y, undefined); + + // Array with dense elements. + from = [1, 2, 3]; + ({...to} = from); + assertEq(to[2], 3); + assertEq("length" in to, false); + + from = [1, 2, 3]; + ({2: z, ...to} = from); + assertEq(z, 3); + assertEq(to[2], undefined); + assertEq(to[0], 1); + assertEq("length" in to, false); + + // Object with sparse elements and symbols. + from = {x: 1, 1234567: 2, 1234560: 3, [Symbol.iterator]: 5, z: 3}; + ({...to} = from); + assertEq(to[1234567], 2); + assertEq(Object.keys(to).toString(), "1234560,1234567,x,z"); + assertEq(to[Symbol.iterator], 5); + + from = {x: 1, 1234567: 2, 1234560: 3, [Symbol.iterator]: 5, z: 3}; + ({[Symbol.iterator]: z, ...to} = from); + assertEq(to[1234567], 2); + assertEq(Object.keys(to).toString(), "1234560,1234567,x,z"); + assertEq(to[Symbol.iterator], undefined); + assertEq(z, 5); + + // Typed array. + from = new Int32Array([1, 2, 3]); + ({...to} = from); + assertEq(to[1], 2); + + from = new Int32Array([1, 2, 3]); + ({1: z, ...to} = from); + assertEq(z, 2); + assertEq(to[1], undefined); + assertEq(to[2], 3); + + // Primitive string. + from = "foo"; + ({...to} = from); + assertEq(to[0], "f"); + + from = "foo"; + ({0: z, ...to} = from); + assertEq(z, "f"); + assertEq(to[0], undefined); + assertEq(to[1], "o"); + + // String object. + from = new String("bar"); + ({...to} = from); + assertEq(to[2], "r"); + + from = new String("bar"); + ({1: z, ...to} = from); + assertEq(z, "a"); + assertEq(to[1], undefined); + assertEq(to[2], "r"); +} +test(); +test(); +test(); diff --git a/js/src/jit-test/tests/basic/object-shorthand.js b/js/src/jit-test/tests/basic/object-shorthand.js new file mode 100644 index 0000000000..934f466800 --- /dev/null +++ b/js/src/jit-test/tests/basic/object-shorthand.js @@ -0,0 +1,90 @@ + +load(libdir + 'asserts.js'); + +// globals: +a = b = get = set = eval = arguments = 10; + +assertEq({arguments}.arguments, 10); + +var o = {a, b: b, get, set: set}; +assertEq(o.a, 10); +assertEq(o.b, 10); +assertEq(o.get, 10); +assertEq(o.set, 10); + +var names = ['a', 'get', 'set', 'eval']; +// global +names.forEach(ident => + assertEq(new Function('return {' + ident + '}.' + ident + ';')(), 10)); +// local +names.forEach(ident => + assertEq(new Function('var ' + ident + ' = 20; return {' + ident + '}.' + ident + ';')(), 20)); +// scope +names.forEach(ident => + assertEq(new Function('var ' + ident + ' = 30; return (function () {return {' + ident + '}.' + ident + ';})();')(), 30)); + +var reserved = [ + 'break', + 'do', + 'in', + 'typeof', + 'case', + 'else', + 'instanceof', + 'var', + 'catch', + 'export', + 'new', + 'void', + 'class', + 'extends', + 'return', + 'while', + 'const', + 'finally', + 'super', + 'with', + 'continue', + 'for', + 'switch', + 'debugger', + 'function', + 'this', + 'delete', + 'import', + 'try', + 'enum', + 'null', + 'true', + 'false' +]; + +// non-identifiers should also throw +var nonidents = [ + '"str"', + '0' +]; + +reserved.concat(nonidents).forEach(ident => + assertThrowsInstanceOf(() => new Function('return {' + ident + '}'), SyntaxError)); + +var reservedStrict = [ + 'implements', + 'interface', + 'package', + 'private', + 'protected', + 'public', + 'static', + // XXX: according to 12.1.1, these should only be errors in strict code: + // see https://bugzilla.mozilla.org/show_bug.cgi?id=1032150 + //'let', + //'yield' +]; + +reservedStrict.forEach(ident => + assertEq(new Function('var ' + ident + ' = 10; return {' + ident + '}.' + ident + ';')(), 10)); + +reservedStrict.concat(['let', 'yield']).forEach(ident => + assertThrowsInstanceOf(() => new Function('"use strict"; return {' + ident + '}'), SyntaxError)); + diff --git a/js/src/jit-test/tests/basic/object-spread.js b/js/src/jit-test/tests/basic/object-spread.js new file mode 100644 index 0000000000..c963dc1d43 --- /dev/null +++ b/js/src/jit-test/tests/basic/object-spread.js @@ -0,0 +1,49 @@ +function test() { + var from, to; + + // From values. + from = {x: 1, y: 2}; + to = {...from}; + assertEq(to.y, 2); + to = {...from, ...from}; + assertEq(to.y, 2); + + // From getter. + var c = 7; + from = {x: 1, get y() { return ++c; }}; + to = {...from}; + assertEq(to.y, 8); + to = {...from, ...from}; + assertEq(to.y, 10); + + // Array with dense elements. + from = [1, 2, 3]; + to = {...from}; + assertEq(to[2], 3); + assertEq("length" in to, false); + + // Object with sparse elements and symbols. + from = {x: 1, 1234567: 2, 1234560: 3, [Symbol.iterator]: 5, z: 3}; + to = {...from}; + assertEq(to[1234567], 2); + assertEq(Object.keys(to).toString(), "1234560,1234567,x,z"); + assertEq(to[Symbol.iterator], 5); + + // Typed array. + from = new Int32Array([1, 2, 3]); + to = {...from}; + assertEq(to[1], 2); + + // Primitive string. + from = "foo"; + to = {...from}; + assertEq(to[0], "f"); + + // String object. + from = new String("bar"); + to = {...from}; + assertEq(to[2], "r"); +} +test(); +test(); +test(); diff --git a/js/src/jit-test/tests/basic/object-tostring.js b/js/src/jit-test/tests/basic/object-tostring.js new file mode 100644 index 0000000000..5f6204d6dd --- /dev/null +++ b/js/src/jit-test/tests/basic/object-tostring.js @@ -0,0 +1,60 @@ + +function doTest(expected, v) { + assertEq(Object.prototype.toString.call(v), expected) +} + +function Dummy() {} + +// Basic primitive cases +doTest("[object Undefined]", undefined); +doTest("[object Null]", null); +doTest("[object String]", ""); +doTest("[object Number]", 12); +doTest("[object Number]", 12.34); +doTest("[object Boolean]", true); +doTest("[object Symbol]", Symbol()); +doTest("[object BigInt]", 1234n); + +// Exotic objects with builtinTag +doTest("[object Array]", []); +(function() { + doTest("[object Arguments]", arguments); +})(); +doTest("[object Function]", () => {}); +doTest("[object Error]", new Error); +doTest("[object Date]", new Date); +doTest("[object RegExp]", /i/); + +// Exotic objects with @@toStringTag +doTest("[object Map]", new Map); +doTest("[object Set]", new Set); +doTest("[object JSON]", JSON); +doTest("[object Math]", Math); + +// Normal object cases +doTest("[object Object]", {}); +doTest("[object Object]", new Dummy); +doTest("[object Foo]", { [Symbol.toStringTag]: "Foo" }); + +// Test the receiver of Symbol.toStringTag +let receiver1; +let object1 = { + __proto__: { + get [Symbol.toStringTag]() { + receiver1 = this; + } + } +}; +doTest("[object Object]", object1); +assertEq(receiver1, object1); + +//// BELOW THIS LINE TAMPERS WITH GLOBAL + +// Set a toStringTag on the global String.prototype +let receiver2; +Object.defineProperty(String.prototype, Symbol.toStringTag, { get: function() { + receiver2 = this; + return "XString"; +}}); +doTest("[object XString]", ""); +assertEq(Object.getPrototypeOf(receiver2), String.prototype); diff --git a/js/src/jit-test/tests/basic/offThreadCompileToStencil-01.js b/js/src/jit-test/tests/basic/offThreadCompileToStencil-01.js new file mode 100644 index 0000000000..461af86511 --- /dev/null +++ b/js/src/jit-test/tests/basic/offThreadCompileToStencil-01.js @@ -0,0 +1,30 @@ +// |jit-test| skip-if: helperThreadCount() === 0 + +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +// Test off-thread parsing. + +load(libdir + 'asserts.js'); + +offThreadCompileToStencil('Math.sin(Math.PI/2)'); +var stencil = finishOffThreadStencil(); +assertEq(evalStencil(stencil), 1); + +offThreadCompileToStencil('a string which cannot be reduced to the start symbol'); +assertThrowsInstanceOf(() => { + var stencil = finishOffThreadStencil(); + evalStencil(stencil); +}, SyntaxError); + +offThreadCompileToStencil('smerg;'); +assertThrowsInstanceOf(() => { + var stencil = finishOffThreadStencil(); + evalStencil(stencil); +}, ReferenceError); + +offThreadCompileToStencil('throw "blerg";'); +assertThrowsValue(() => { + var stencil = finishOffThreadStencil(); + evalStencil(stencil); +}, 'blerg'); diff --git a/js/src/jit-test/tests/basic/offThreadCompileToStencil-02.js b/js/src/jit-test/tests/basic/offThreadCompileToStencil-02.js new file mode 100644 index 0000000000..2273cb63dd --- /dev/null +++ b/js/src/jit-test/tests/basic/offThreadCompileToStencil-02.js @@ -0,0 +1,25 @@ +// |jit-test| skip-if: helperThreadCount() === 0 + +// Test offThreadCompileToStencil/evalStencil option handling. + +offThreadCompileToStencil("Error()"); +var stencil = finishOffThreadStencil(); +assertEq(!!evalStencil(stencil).stack.match(/^@<string>:1:1\n/), true); + +offThreadCompileToStencil("Error()", { fileName: "candelabra", lineNumber: 6502 }); +stencil = finishOffThreadStencil(); +assertEq(!!evalStencil(stencil).stack.match(/^@candelabra:6502:1\n/), true); + +var element = {}; +offThreadCompileToStencil("Error()"); // shouldn't crash +stencil = finishOffThreadStencil(); +evalStencil(stencil, { element }); + +var elementAttributeName = "molybdenum"; +elementAttributeName += + elementAttributeName + elementAttributeName + elementAttributeName; +offThreadCompileToStencil("Error()"); // shouldn't crash +stencil = finishOffThreadStencil(); +evalStencil(stencil, { + elementAttributeName, +}); diff --git a/js/src/jit-test/tests/basic/offThreadCompileToStencil-03.js b/js/src/jit-test/tests/basic/offThreadCompileToStencil-03.js new file mode 100644 index 0000000000..300497cd1c --- /dev/null +++ b/js/src/jit-test/tests/basic/offThreadCompileToStencil-03.js @@ -0,0 +1,54 @@ +// |jit-test| skip-if: helperThreadCount() === 0 + +// Test offThreadCompileToStencil for different function types. + +load(libdir + 'asserts.js'); + +var id, stencil; + +id = offThreadCompileToStencil(` + function f() { return "pass"; } + f(); +`); +stencil = finishOffThreadStencil(id); +assertEq(evalStencil(stencil), "pass"); + +id = offThreadCompileToStencil(` + function* f() { return "pass"; } + f().next(); +`); +stencil = finishOffThreadStencil(id); +assertDeepEq(evalStencil(stencil), {value: "pass", done: true}); + +id = offThreadCompileToStencil(` + async function f() { return "pass"; } + f(); +`); +stencil = finishOffThreadStencil(id); +assertEventuallyEq(evalStencil(stencil), "pass"); + +id = offThreadCompileToStencil(` + async function* f() { return "pass"; } + f().next(); +`); +stencil = finishOffThreadStencil(id); +assertEventuallyDeepEq(evalStencil(stencil), {value: "pass", done: true}); + +// Copied from js/src/tests/shell.js +function getPromiseResult(promise) { + var result, error, caught = false; + promise.then(r => { result = r; }, + e => { caught = true; error = e; }); + drainJobQueue(); + if (caught) + throw error; + return result; +} + +function assertEventuallyEq(promise, expected) { + assertEq(getPromiseResult(promise), expected); +} + +function assertEventuallyDeepEq(promise, expected) { + assertDeepEq(getPromiseResult(promise), expected); +} diff --git a/js/src/jit-test/tests/basic/offThreadCompileToStencil-04.js b/js/src/jit-test/tests/basic/offThreadCompileToStencil-04.js new file mode 100644 index 0000000000..1b10df8174 --- /dev/null +++ b/js/src/jit-test/tests/basic/offThreadCompileToStencil-04.js @@ -0,0 +1,21 @@ +// |jit-test| skip-if: helperThreadCount() === 0 + +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +// Ensure off-thread parse works for ergonomic brand checks. + +load(libdir + 'asserts.js'); + +offThreadCompileToStencil(` + class A { + #x + static hx(o) { return #x in o; } + }; + + throw "Yay"`); + +assertThrowsValue(() => { + var stencil = finishOffThreadStencil(); + evalStencil(stencil); +}, 'Yay'); diff --git a/js/src/jit-test/tests/basic/orNaNTest1.js b/js/src/jit-test/tests/basic/orNaNTest1.js new file mode 100644 index 0000000000..0b713b2c53 --- /dev/null +++ b/js/src/jit-test/tests/basic/orNaNTest1.js @@ -0,0 +1,3 @@ +load(libdir + 'orTestHelper.js'); +var orNaNTest1 = new Function("return orTestHelper(NaN, NaN, 10);"); +assertEq(orNaNTest1(), 0); diff --git a/js/src/jit-test/tests/basic/orNaNTest2.js b/js/src/jit-test/tests/basic/orNaNTest2.js new file mode 100644 index 0000000000..113fe038ff --- /dev/null +++ b/js/src/jit-test/tests/basic/orNaNTest2.js @@ -0,0 +1,3 @@ +load(libdir + 'orTestHelper.js'); +var orNaNTest2 = new Function("return orTestHelper(NaN, 1, 10);"); +assertEq(orNaNTest2(), 45); diff --git a/js/src/jit-test/tests/basic/outerline.js b/js/src/jit-test/tests/basic/outerline.js new file mode 100644 index 0000000000..8056864082 --- /dev/null +++ b/js/src/jit-test/tests/basic/outerline.js @@ -0,0 +1,15 @@ +function outerline(){ + var i=0; + var j=0; + + for (i = 3; i<= 100000; i+=2) + { + for (j = 3; j < 1000; j+=2) + { + if ((i & 1) == 1) + break; + } + } + return "ok"; +} +assertEq(outerline(), "ok"); diff --git a/js/src/jit-test/tests/basic/packed-arrays.js b/js/src/jit-test/tests/basic/packed-arrays.js new file mode 100644 index 0000000000..a6814d47aa --- /dev/null +++ b/js/src/jit-test/tests/basic/packed-arrays.js @@ -0,0 +1,51 @@ +var isPacked = getSelfHostedValue("IsPackedArray"); + +function test() { + var arr; + + // basic + arr = []; + assertEq(isPacked(arr), true); + arr[0] = 0; + assertEq(isPacked(arr), true); + arr[2] = 2; + assertEq(isPacked(arr), false); + + // delete + arr = [1, 2, 3]; + assertEq(isPacked(arr), true); + delete arr[1]; + assertEq(isPacked(arr), false); + + // setting .length + arr = [1]; + arr.length = 0; + assertEq(isPacked(arr), true); + arr.length = 1; + assertEq(isPacked(arr), false); + + // slice + arr = [1, 2, , 3]; + assertEq(isPacked(arr), false); + assertEq(isPacked(arr.slice(0, 2)), true); + assertEq(isPacked(arr.slice(0, 3)), false); + assertEq(isPacked(arr.slice(2, 3)), false); + assertEq(isPacked(arr.slice(3, 4)), true); + + // splice + arr = [1, 2, 3]; + assertEq(isPacked(arr.splice(0)), true); + arr = [1, , 2]; + assertEq(isPacked(arr.splice(0)), false); + arr = [1, , 2]; + assertEq(isPacked(arr.splice(0, 1)), true); + assertEq(arr.length, 2); + assertEq(isPacked(arr.splice(0, 1)), false); + assertEq(arr.length, 1); + assertEq(isPacked(arr.splice(0, 1)), true); + assertEq(arr.length, 0); + assertEq(isPacked(arr.splice(0)), true); +} +for (var i = 0; i < 5; i++) { + test(); +} diff --git a/js/src/jit-test/tests/basic/parseIntTests.js b/js/src/jit-test/tests/basic/parseIntTests.js new file mode 100644 index 0000000000..4138d07df8 --- /dev/null +++ b/js/src/jit-test/tests/basic/parseIntTests.js @@ -0,0 +1,24 @@ +function parseIntHelper(n) { + var a; + for (var i = 0; i < 5; i++) + a = parseInt(n); + return a; +} +function doParseIntTests() { + var inputs = [0, -0, .1, -.1, .7, -.7, 1.3, -1.3]; + var outputs = new Array(8); + //avoid jit, unrolled + outputs[0] = outputs[1] = outputs[2] = outputs[4] = 0; + outputs[3] = outputs[5] = -0; + outputs[6] = 1; + outputs[7] = -1; + for (var i = 0; i < 8; i++) { + var n = Object.is(inputs[i], -0) ? "-0" : String(inputs[i]); + var testfn = new Function('return parseIntHelper(' + n + ');'); + assertEq(testfn(), outputs[i]); + } +} +doParseIntTests(); + +assertEq(parseInt("08"), 8); +assertEq(parseInt("09"), 9); diff --git a/js/src/jit-test/tests/basic/parsingNumbers.js b/js/src/jit-test/tests/basic/parsingNumbers.js new file mode 100644 index 0000000000..1630612b69 --- /dev/null +++ b/js/src/jit-test/tests/basic/parsingNumbers.js @@ -0,0 +1,23 @@ +function parsingNumbers() { + var s1 = "123"; + var s1z = "123zzz"; + var s2 = "123.456"; + var s2z = "123.456zzz"; + + var e1 = 123; + var e2 = 123.456; + + var r1, r1z, r2, r2z; + + for (var i = 0; i < 10; i++) { + r1 = parseInt(s1); + r1z = parseInt(s1z); + r2 = parseFloat(s2); + r2z = parseFloat(s2z); + } + + if (r1 == e1 && r1z == e1 && r2 == e2 && r2z == e2) + return "ok"; + return "fail"; +} +assertEq(parsingNumbers(), "ok"); diff --git a/js/src/jit-test/tests/basic/plain-object-prototypes-error.js b/js/src/jit-test/tests/basic/plain-object-prototypes-error.js new file mode 100644 index 0000000000..d62d7fbe72 --- /dev/null +++ b/js/src/jit-test/tests/basic/plain-object-prototypes-error.js @@ -0,0 +1,40 @@ +// Make sure the error has a sensible error message. +function assertThrowsObjectError(f, name) { + try { + f(); + assertEq(true, false); + } catch (e) { + assertEq(e instanceof TypeError, true); + assertEq(e.message.includes("called on incompatible " + name), true, e.message); + } +} + +// Call methods on the prototypes where the methods themselves are defined. +assertThrowsObjectError(() => Map.prototype.has(0), "Map.prototype"); +assertThrowsObjectError(() => Set.prototype.has(0), "Set.prototype"); +assertThrowsObjectError(() => WeakMap.prototype.has({}), "WeakMap.prototype"); +assertThrowsObjectError(() => WeakSet.prototype.has({}), "WeakSet.prototype"); +assertThrowsObjectError(() => Date.prototype.getSeconds(), "Date.prototype"); +assertThrowsObjectError(() => RegExp.prototype.compile(), "RegExp.prototype"); + +// Call methods with different prototype objects. +assertThrowsObjectError(() => Map.prototype.has.call(ArrayBuffer.prototype), "ArrayBuffer.prototype"); +assertThrowsObjectError(() => Map.prototype.has.call(BigInt.prototype), "BigInt.prototype"); +assertThrowsObjectError(() => Map.prototype.has.call(DataView.prototype), "DataView.prototype"); +assertThrowsObjectError(() => Map.prototype.has.call(Date.prototype), "Date.prototype"); +assertThrowsObjectError(() => Map.prototype.has.call(FinalizationRegistry.prototype), "FinalizationRegistry.prototype"); +assertThrowsObjectError(() => Map.prototype.has.call(Int32Array.prototype), "Int32Array.prototype"); +assertThrowsObjectError(() => Map.prototype.has.call(Promise.prototype), "Promise.prototype"); +if (this.hasOwnProperty("ReadableStream")) { + // ReadableStream is only present for the JS Streams implementation + assertThrowsObjectError(() => Map.prototype.has.call(ReadableStream.prototype), "ReadableStream.prototype"); +} +assertThrowsObjectError(() => Map.prototype.has.call(RegExp.prototype), "RegExp.prototype"); +assertThrowsObjectError(() => Map.prototype.has.call(Set.prototype), "Set.prototype"); +assertThrowsObjectError(() => Map.prototype.has.call(TypeError.prototype), "TypeError.prototype"); +assertThrowsObjectError(() => Map.prototype.has.call(WeakMap.prototype), "WeakMap.prototype"); +assertThrowsObjectError(() => Map.prototype.has.call(WeakRef.prototype), "WeakRef.prototype"); + +// Call methods with different objects. +assertThrowsObjectError(() => Map.prototype.has.call(new Error), "Error"); +assertThrowsObjectError(() => Map.prototype.has.call(new TypeError), "TypeError"); diff --git a/js/src/jit-test/tests/basic/plain-object-prototypes.js b/js/src/jit-test/tests/basic/plain-object-prototypes.js new file mode 100644 index 0000000000..c53f0c9e16 --- /dev/null +++ b/js/src/jit-test/tests/basic/plain-object-prototypes.js @@ -0,0 +1,21 @@ +const prototypes = [ + Map.prototype, + Set.prototype, + WeakMap.prototype, + WeakSet.prototype, + Date.prototype, + Error.prototype, + InternalError.prototype, + EvalError.prototype, + RangeError.prototype, + ReferenceError.prototype, + SyntaxError.prototype, + TypeError.prototype, + URIError.prototype, + RegExp.prototype, +]; + +for (const prototype of prototypes) { + delete prototype[Symbol.toStringTag]; + assertEq(Object.prototype.toString.call(prototype), "[object Object]"); +} diff --git a/js/src/jit-test/tests/basic/plain-object-to-string.js b/js/src/jit-test/tests/basic/plain-object-to-string.js new file mode 100644 index 0000000000..8af972bb4a --- /dev/null +++ b/js/src/jit-test/tests/basic/plain-object-to-string.js @@ -0,0 +1,25 @@ +// Test for OrdinaryToPrimitive called on a plain object with hint "string". + +function assertStr(o, s) { + assertEq(String(o), s); +} +function test() { + assertStr({x: 1}, "[object Object]"); + assertStr({[Symbol.toStringTag]: "Foo"}, "[object Foo]"); + assertStr({toString() { return 123; }}, "123"); + assertStr({toString: Math.abs}, "NaN"); + assertStr({x: "hello", toString() { return this.x; }}, "hello"); + + let c = 0; + let fun = () => "hi-" + ++c; + assertStr({toString: fun}, "hi-1"); + assertStr({toString: "foo", valueOf: fun}, "hi-2"); + assertStr({toString() { return {}; }, valueOf: fun}, "hi-3"); + + let proto = {}; + proto[Symbol.toStringTag] = null; + assertStr(Object.create(proto), "[object Object]"); + proto[Symbol.toStringTag] = "Bar"; + assertStr(Object.create(proto), "[object Bar]"); +} +test(); diff --git a/js/src/jit-test/tests/basic/primitive-proto-properties.js b/js/src/jit-test/tests/basic/primitive-proto-properties.js new file mode 100644 index 0000000000..ea012e40e6 --- /dev/null +++ b/js/src/jit-test/tests/basic/primitive-proto-properties.js @@ -0,0 +1,47 @@ +function shadowing() { + Object.prototype.x = 1; + + for (var i = 0; i < 20; i++) { + var x = "a".x; + assertEq(x, i <= 15 ? 1 : "hello"); + + if (i == 15) { + String.prototype.x = "hello"; + } + } + + delete Object.prototype.x; +} + +function deleted() { + String.prototype.y = 1; + + for (var i = 0; i < 20; i++) { + var y = "a".y; + assertEq(y, i <= 15 ? 1 : undefined); + + if (i == 15) { + delete String.prototype.y; + } + } + + delete String.prototype.y; +} + + +function notdefined() { + for (var i = 0; i < 20; i++) { + var z = "a".z; + assertEq(z, i <= 15 ? undefined : "test"); + + if (i == 15) { + String.prototype.z = "test"; + } + } + + delete String.prototype.z; +} + +shadowing(); +deleted(); +notdefined(); diff --git a/js/src/jit-test/tests/basic/primitiveProto.js b/js/src/jit-test/tests/basic/primitiveProto.js new file mode 100644 index 0000000000..e9043225c8 --- /dev/null +++ b/js/src/jit-test/tests/basic/primitiveProto.js @@ -0,0 +1,24 @@ + +function fna() {} +fna.prototype = undefined; +new fna; + +function fnb() {} +fnb.prototype = null; +new fnb; + +function fnc() {} +fnc.prototype = 3; +new fnc; + +function fnd() {} +fnd.prototype = true; +new fnd; + +function fne() {} +fne.prototype = "foo"; +new fne; + +function fnf() {} +fnf.prototype = /foo/; +new fnf; diff --git a/js/src/jit-test/tests/basic/prop-access-error-message.js b/js/src/jit-test/tests/basic/prop-access-error-message.js new file mode 100644 index 0000000000..05a7f49a7c --- /dev/null +++ b/js/src/jit-test/tests/basic/prop-access-error-message.js @@ -0,0 +1,47 @@ +// |jit-test| skip-if: getBuildConfiguration('pbl') +// The decompiled expression used in the error messsage should not be confused +// by unrelated value on the stack. + +var a = {}; +var b = {}; +var p = "c"; + +function doPropAccess() { + // Both "a.c" and "b.e" are undefined. + // "a.c" should be used. + a.c.d = b.e; +} + +function testPropAccess() { + var caught = false; + try { + doPropAccess(); + } catch (e) { + assertEq(e.message.includes("a.c is undefined"), true); + caught = true; + } + assertEq(caught, true); +} + +function doElemAccess() { + // Both "a[x]" and "b.e" are undefined. + // "a[x]" should be used. + var x = "c"; + a[x].d = b.e; +} + +function testElemAccess() { + var caught = false; + try { + doElemAccess(); + } catch (e) { + assertEq(e.message.includes("a[x] is undefined"), true); + caught = true; + } + assertEq(caught, true); +} + +for (var i = 0; i < 10; i++) { + testPropAccess(); + testElemAccess(); +} diff --git a/js/src/jit-test/tests/basic/properly-remove-timeout-root-before-shutdown.js b/js/src/jit-test/tests/basic/properly-remove-timeout-root-before-shutdown.js new file mode 100644 index 0000000000..e42bbede4c --- /dev/null +++ b/js/src/jit-test/tests/basic/properly-remove-timeout-root-before-shutdown.js @@ -0,0 +1,6 @@ +// |jit-test| skip-if: getBuildConfiguration("wasi") +// Bug 857050: Remove the timeout function root before shutting down. +function timeoutfunc() {} +timeout(1, timeoutfunc); +var g = newGlobal({newCompartment: true}); +var dbg = Debugger(g); diff --git a/js/src/jit-test/tests/basic/property-enumeration-order.js b/js/src/jit-test/tests/basic/property-enumeration-order.js new file mode 100644 index 0000000000..2a891b4369 --- /dev/null +++ b/js/src/jit-test/tests/basic/property-enumeration-order.js @@ -0,0 +1,37 @@ +function check(obj, expected, expectedAll = expected) { + assertEq(Reflect.ownKeys(obj).join(""), expectedAll); + assertEq(Object.getOwnPropertyNames(obj).join(""), expectedAll); + assertEq(Object.keys(obj).join(""), expected); + var s = ""; + for (var x in obj) + s += x; + assertEq(s, expected); +} + +var obj = {2: 0, 0: 0, "foo": "bar", 4: 0, "-5": 1}; +check(obj, "024foo-5"); +obj.x = 1; +check(obj, "024foo-5x"); +obj[1] = 1; +check(obj, "0124foo-5x"); +obj[1.2] = 1; +check(obj, "0124foo-5x1.2"); +Object.defineProperty(obj, '3', {value:1,enumerable:false,configurable:false,writable:false}); +check(obj, "0124foo-5x1.2", "01234foo-5x1.2"); +delete obj[2]; +check(obj, "014foo-5x1.2", "0134foo-5x1.2"); +obj[2] = 1; +check(obj, "0124foo-5x1.2", "01234foo-5x1.2"); + +assertEq(JSON.stringify(obj), '{"0":0,"1":1,"2":1,"4":0,"foo":"bar","-5":1,"x":1,"1.2":1}'); + +var arr = [1, 2, 3]; +Object.defineProperty(arr, '3', {value:1,enumerable:true,configurable:true,writable:true}); +check(arr, "0123", "0123length"); +Object.defineProperty(arr, '1000', {value:1,enumerable:true,configurable:true,writable:false}); +check(arr, "01231000", "01231000length"); + +arr = [1, 2, , , 5]; +check(arr, "014", "014length"); +arr[0xfffffff] = 4; +check(arr, "014268435455", "014268435455length"); diff --git a/js/src/jit-test/tests/basic/property-error-message-fix-disabled.js b/js/src/jit-test/tests/basic/property-error-message-fix-disabled.js new file mode 100644 index 0000000000..542bada65f --- /dev/null +++ b/js/src/jit-test/tests/basic/property-error-message-fix-disabled.js @@ -0,0 +1,36 @@ +// |jit-test| --disable-property-error-message-fix; skip-if: getBuildConfiguration('pbl') + +function check(f, message) { + let caught = false; + try { + f(); + } catch (e) { + assertEq(e.message, message); + caught = true; + } + assertEq(caught, true); +} + +check(() => { + let obj = { + prop: undefined + }; + obj.prop.prop2(); +}, "obj.prop is undefined"); + +check(() => { + let obj = { + prop: null + }; + obj.prop.prop2(); +}, "obj.prop is null"); + +check(() => { + let prop = "prop"; + undefined[prop](); +}, "undefined has no properties"); + +check(() => { + let prop = "prop"; + null[prop](); +}, "null has no properties"); diff --git a/js/src/jit-test/tests/basic/property-error-message-fix.js b/js/src/jit-test/tests/basic/property-error-message-fix.js new file mode 100644 index 0000000000..6f27416496 --- /dev/null +++ b/js/src/jit-test/tests/basic/property-error-message-fix.js @@ -0,0 +1,36 @@ +// |jit-test| skip-if: getBuildConfiguration('pbl') + +function check(f, message) { + let caught = false; + try { + f(); + } catch (e) { + assertEq(e.message, message); + caught = true; + } + assertEq(caught, true); +} + +check(() => { + let obj = { + prop: undefined + }; + obj.prop.prop2(); +}, "can't access property \"prop2\", obj.prop is undefined"); + +check(() => { + let obj = { + prop: null + }; + obj.prop.prop2(); +}, "can't access property \"prop2\", obj.prop is null"); + +check(() => { + let prop = "prop"; + undefined[prop](); +}, "can't access property \"prop\" of undefined"); + +check(() => { + let prop = "prop"; + null[prop](); +}, "can't access property \"prop\" of null"); diff --git a/js/src/jit-test/tests/basic/putargsNoReturn.js b/js/src/jit-test/tests/basic/putargsNoReturn.js new file mode 100644 index 0000000000..73df78b49f --- /dev/null +++ b/js/src/jit-test/tests/basic/putargsNoReturn.js @@ -0,0 +1,6 @@ +function f(a) { + x = arguments; +} +for (var i = 0; i < 9; i++) + f(123); +assertEq(x[0], 123); diff --git a/js/src/jit-test/tests/basic/putargsReturn.js b/js/src/jit-test/tests/basic/putargsReturn.js new file mode 100644 index 0000000000..1a6f3c3588 --- /dev/null +++ b/js/src/jit-test/tests/basic/putargsReturn.js @@ -0,0 +1,7 @@ +function f(a) { + x = arguments; + return 99; +} +for (var i = 0; i < 9; i++) + f(123); +assertEq(x[0], 123); diff --git a/js/src/jit-test/tests/basic/recompute-wrappers.js b/js/src/jit-test/tests/basic/recompute-wrappers.js new file mode 100644 index 0000000000..cf45a37407 --- /dev/null +++ b/js/src/jit-test/tests/basic/recompute-wrappers.js @@ -0,0 +1,5 @@ +var g = newGlobal(); +var w1 = g.Math; +var w2 = g.evaluate("new Array"); +recomputeWrappers(this, g); +recomputeWrappers(); diff --git a/js/src/jit-test/tests/basic/regexp-removed-dot-star.js b/js/src/jit-test/tests/basic/regexp-removed-dot-star.js new file mode 100644 index 0000000000..5218494883 --- /dev/null +++ b/js/src/jit-test/tests/basic/regexp-removed-dot-star.js @@ -0,0 +1,49 @@ + +// Test that removal of leading or trailing .* from RegExp test() calls +// does not affect lastMatch or other RegExpStatics info. + +function first(input) { + var re = /.*b(cd)/; + for (var i = 0; i < 10; i++) + re.test(input); +} + +first("1234\nabcdefg\n1234"); +assertEq(RegExp.lastMatch, "abcd"); +assertEq(RegExp.$1, "cd"); +assertEq(RegExp.input, "1234\nabcdefg\n1234"); +assertEq(RegExp.leftContext, "1234\n"); +assertEq(RegExp.rightContext, "efg\n1234"); +assertEq(RegExp.lastParen, "cd"); + + +// Test that removal of leading or trailing .* from RegExp test() calls +// does not affect lastMatch or other RegExpStatics info. + +function second(input) { + var re = /bcd.*/; + for (var i = 0; i < 10; i++) + re.test(input); +} + +second("1234\nabcdefg\n1234"); +assertEq(RegExp.lastMatch, "bcdefg"); +assertEq(RegExp.$1, ""); +assertEq(RegExp.input, "1234\nabcdefg\n1234"); +assertEq(RegExp.leftContext, "1234\na"); +assertEq(RegExp.rightContext, "\n1234"); +assertEq(RegExp.lastParen, ""); + +function third(input) { + var re = /.*bcd.*/; + for (var i = 0; i < 10; i++) + re.test(input); +} + +third("1234\nabcdefg\n1234"); +assertEq(RegExp.lastMatch, "abcdefg"); +assertEq(RegExp.$1, ""); +assertEq(RegExp.input, "1234\nabcdefg\n1234"); +assertEq(RegExp.leftContext, "1234\n"); +assertEq(RegExp.rightContext, "\n1234"); +assertEq(RegExp.lastParen, ""); diff --git a/js/src/jit-test/tests/basic/regexp-reset-input.js b/js/src/jit-test/tests/basic/regexp-reset-input.js new file mode 100644 index 0000000000..77cdd69dd6 --- /dev/null +++ b/js/src/jit-test/tests/basic/regexp-reset-input.js @@ -0,0 +1,8 @@ +var re = /(pattern)/g; +var input = "patternpatternpattern"; +re.exec(input) +RegExp.input = "satturn"; +assertEq(RegExp.$1, "pattern"); +assertEq(RegExp.lastMatch, "pattern"); +assertEq(RegExp.lastParen, "pattern"); +assertEq(RegExp.rightContext, "patternpattern"); diff --git a/js/src/jit-test/tests/basic/regexp-sticky-undef-capture.js b/js/src/jit-test/tests/basic/regexp-sticky-undef-capture.js new file mode 100644 index 0000000000..3d96d4e44c --- /dev/null +++ b/js/src/jit-test/tests/basic/regexp-sticky-undef-capture.js @@ -0,0 +1,8 @@ +var re = /abc(WHOO!)?def/y; +var input = 'abcdefabcdefabcdef'; +var count = 0; +while ((match = re.exec(input)) !== null) { + print(count++); + assertEq(match[0], 'abcdef'); + assertEq(match[1], undefined); +} diff --git a/js/src/jit-test/tests/basic/regexp-test-direct-bug-694752.js b/js/src/jit-test/tests/basic/regexp-test-direct-bug-694752.js new file mode 100644 index 0000000000..7e0bae7dae --- /dev/null +++ b/js/src/jit-test/tests/basic/regexp-test-direct-bug-694752.js @@ -0,0 +1,15 @@ +function whoo() { + // Cause mjit to use the script's RegExpObject directly when it compiles this function. + assertEq(/foo.*baz/.test('foobarbaz'), true); +} + +var orig_test = RegExp.prototype.test +for (var i = 0; i < 50; ++i) + whoo(); +eval('RegExp.prototype.test = function(str) { return orig_test.call(this, str) }') +for (var i = 0; i < 50; ++i) + whoo(); +RegExp.prototype.test = orig_test; +gc(); +whoo(); + diff --git a/js/src/jit-test/tests/basic/regexp-undefined-match.js b/js/src/jit-test/tests/basic/regexp-undefined-match.js new file mode 100644 index 0000000000..cf1d799833 --- /dev/null +++ b/js/src/jit-test/tests/basic/regexp-undefined-match.js @@ -0,0 +1,9 @@ + +function f(str) { + for (var i=0; i<10; i++) { + arr = /foo(ba(r))?/.exec(str); + var x = arr[0] + " " + arr[1] + " " + arr[2]; + } +} +f("foobar"); +f("foo"); diff --git a/js/src/jit-test/tests/basic/regexpLastIndex.js b/js/src/jit-test/tests/basic/regexpLastIndex.js new file mode 100644 index 0000000000..80991fa4b9 --- /dev/null +++ b/js/src/jit-test/tests/basic/regexpLastIndex.js @@ -0,0 +1,13 @@ +function regexpLastIndex() +{ + var n = 0; + var re = /hi/g; + var ss = " hi hi hi hi hi hi hi hi hi hi"; + for (var i = 0; i < 10; i++) { + // re.exec(ss); + n += (re.lastIndex > 0) ? 3 : 0; + re.lastIndex = 0; + } + return n; +} +assertEq(regexpLastIndex(), 0); diff --git a/js/src/jit-test/tests/basic/regexpLastIndexReset.js b/js/src/jit-test/tests/basic/regexpLastIndexReset.js new file mode 100644 index 0000000000..dbe3c3b763 --- /dev/null +++ b/js/src/jit-test/tests/basic/regexpLastIndexReset.js @@ -0,0 +1,26 @@ +// Bug 1207922 - lastIndex should be reset to 0 when match fails. + +var pattern = /abc/; +var string = 'aaaaaaaa'; + +function test() { + pattern.lastIndex = 3; + var result = pattern.exec(string); + assertEq(result, null); + assertEq(pattern.lastIndex, 3); +} + +for (let i = 0; i < 10; i++) { + test(); +} + +function test2() { + pattern.lastIndex = 3; + var result = pattern.test(string); + assertEq(result, false); + assertEq(pattern.lastIndex, 3); +} + +for (let i = 0; i < 10; i++) { + test2(); +} diff --git a/js/src/jit-test/tests/basic/relazify-selfhosted.js b/js/src/jit-test/tests/basic/relazify-selfhosted.js new file mode 100644 index 0000000000..63cad1c2d1 --- /dev/null +++ b/js/src/jit-test/tests/basic/relazify-selfhosted.js @@ -0,0 +1,4 @@ +var g = newGlobal(); +g.eval("this.inner = getSelfHostedValue('outer')()"); +gc(); +g.inner(); diff --git a/js/src/jit-test/tests/basic/relazify.js b/js/src/jit-test/tests/basic/relazify.js new file mode 100644 index 0000000000..01e7dcd496 --- /dev/null +++ b/js/src/jit-test/tests/basic/relazify.js @@ -0,0 +1,16 @@ +function f(x) { + return x * 3; +} +for (var i=0; i<100; i++) { + f(i); +} +relazifyFunctions(); + +f(1); +f(1); + +relazifyFunctions(); + +for (var i=0; i<10; i++) { + f.call(null, i); +} diff --git a/js/src/jit-test/tests/basic/runOnceClosures.js b/js/src/jit-test/tests/basic/runOnceClosures.js new file mode 100644 index 0000000000..49c81b3827 --- /dev/null +++ b/js/src/jit-test/tests/basic/runOnceClosures.js @@ -0,0 +1,11 @@ + +compare = (function() { + function inner() { return inner.caller; }; + globalInner = inner; + globalClosure = inner(); + return function(f) { return f === inner; } +})(); + +assertEq(compare(globalInner), true); +globalClosure(); +assertEq(compare(globalInner), false); diff --git a/js/src/jit-test/tests/basic/script-filename-validation-1.js b/js/src/jit-test/tests/basic/script-filename-validation-1.js new file mode 100644 index 0000000000..fa440dd6d4 --- /dev/null +++ b/js/src/jit-test/tests/basic/script-filename-validation-1.js @@ -0,0 +1,51 @@ +load(libdir + "asserts.js"); + +setTestFilenameValidationCallback(); + +// Filenames starting with "safe" are fine. +assertEq(evaluate("2", {fileName: "safe.js"}), 2); +assertEq(evaluate("eval(3)", {fileName: "safe.js"}), 3); +assertEq(evaluate("Function('return 4')()", {fileName: "safe.js"}), 4); + +// Delazification is fine. +function foo(x) { + function bar(x) { return x + 1; } + return bar(x); +} +assertEq(foo(1), 2); + +// These are all blocked. +assertThrowsInstanceOf(() => evaluate("throw 2", {fileName: "unsafe.js"}), InternalError); +assertThrowsInstanceOf(() => evaluate("throw 2", {fileName: "system.js"}), InternalError); +assertThrowsInstanceOf(() => evaluate("throw 2", {fileName: ""}), InternalError); +assertThrowsInstanceOf(() => evaluate("throw 2"), InternalError); +assertThrowsInstanceOf(() => eval("throw 2"), InternalError); +assertThrowsInstanceOf(() => Function("return 1"), InternalError); +assertThrowsInstanceOf(() => parseModule("{ function x() {} }"), InternalError); + +// The error message must contain the filename. +var ex = null; +try { + evaluate("throw 2", {fileName: "file://foo.js"}); +} catch (e) { + ex = e; +} +assertEq(ex.toString(), "InternalError: unsafe filename: file://foo.js"); + +// Off-thread parse throws too, when finishing. +if (helperThreadCount() > 0) { + offThreadCompileToStencil('throw 1'); + var stencil = finishOffThreadStencil(); + assertThrowsInstanceOf(() => evalStencil(stencil), InternalError); +} + +// Unsafe filename is accepted if we opt-out. +assertEq(evaluate("2", {fileName: "unsafe.js", skipFileNameValidation: true}), 2); +assertEq(evaluate("3", {skipFileNameValidation: true}), 3); + +// In system realms we also accept filenames starting with "system". +var systemRealm = newGlobal({newCompartment: true, systemPrincipal: true}); +assertEq(systemRealm.evaluate("1 + 2", {fileName: "system.js"}), 3); +assertEq(systemRealm.evaluate("2 + 2", {fileName: "safe.js"}), 4); +assertThrowsInstanceOf(() => systemRealm.evaluate("1 + 2", {fileName: "unsafe.js"}), + systemRealm.InternalError); diff --git a/js/src/jit-test/tests/basic/script-filename-validation-2.js b/js/src/jit-test/tests/basic/script-filename-validation-2.js new file mode 100644 index 0000000000..432c26c0ce --- /dev/null +++ b/js/src/jit-test/tests/basic/script-filename-validation-2.js @@ -0,0 +1,22 @@ +load(libdir + "asserts.js"); +load(libdir + 'bytecode-cache.js'); + +// Install the callback after evaluating the script and saving the bytecode +// (generation 0). XDR decoding after this should throw. + +var g = newGlobal({cloneSingletons: true}); +test = ` + assertEq(generation, 0); +`; +assertThrowsInstanceOf(() => { + evalWithCache(test, { + global: g, + checkAfter: function (ctx) { + assertEq(g.generation, 0); + setTestFilenameValidationCallback(); + } + }); +}, g.InternalError); + +// Generation should be 1 (XDR decoding threw an exception). +assertEq(g.generation, 1); diff --git a/js/src/jit-test/tests/basic/setArgumentsLength.js b/js/src/jit-test/tests/basic/setArgumentsLength.js new file mode 100644 index 0000000000..775d3ef9f2 --- /dev/null +++ b/js/src/jit-test/tests/basic/setArgumentsLength.js @@ -0,0 +1,14 @@ +var count = 0; + +function f() { + arguments.length--; + for (var i = 0; i < arguments.length; ++i) { + ++count; + } +} + +f(1, 2); +f(1, 2); +f(2, 2); + +assertEq(count, 3); diff --git a/js/src/jit-test/tests/basic/setArgumentsLength2.js b/js/src/jit-test/tests/basic/setArgumentsLength2.js new file mode 100644 index 0000000000..2dcb174242 --- /dev/null +++ b/js/src/jit-test/tests/basic/setArgumentsLength2.js @@ -0,0 +1,12 @@ +// don't crash + +var q; + +function f() { + while (arguments.length > 0) { + q = arguments[arguments.length-1]; + arguments.length--; + } +} + +f(1, 2, 3, 4, 5); diff --git a/js/src/jit-test/tests/basic/setCall.js b/js/src/jit-test/tests/basic/setCall.js new file mode 100644 index 0000000000..0e4950e1c2 --- /dev/null +++ b/js/src/jit-test/tests/basic/setCall.js @@ -0,0 +1,22 @@ +function f() { + var x = 11; + + function g() { + var y = 12; + + function h() { + for (var i = 0; i < 5; ++i) { + y = 4; + x = i * 2; + } + } + h(); + + assertEq(y, 4); + } + g(); + + assertEq(x, 8); +} + +f(); diff --git a/js/src/jit-test/tests/basic/setCallEvalMiddle.js b/js/src/jit-test/tests/basic/setCallEvalMiddle.js new file mode 100644 index 0000000000..71de2ac69b --- /dev/null +++ b/js/src/jit-test/tests/basic/setCallEvalMiddle.js @@ -0,0 +1,17 @@ +eval(1); // avoid global shape change when we call eval below +function q() { + var x = 1; + function f() { + function g() { + var t=0; + for (var i=0; i<3; i++) + x = i; + }; + g(); + eval("var x = 3"); + g(); + assertEq(x, 2); + } + f(); +} +q(); diff --git a/js/src/jit-test/tests/basic/setCallEvalMiddle2.js b/js/src/jit-test/tests/basic/setCallEvalMiddle2.js new file mode 100644 index 0000000000..b93622f36c --- /dev/null +++ b/js/src/jit-test/tests/basic/setCallEvalMiddle2.js @@ -0,0 +1,18 @@ +eval(1); // avoid global shape change when we call eval below +function q() { + var x = 1; + function f() { + function g() { + var t=0; + for (var i=0; i<3; i++) + x = i; + assertEq(x, 2); + eval("var x = 3"); + }; + g(); + g(); + assertEq(x, 2); + } + f(); +} +q(); diff --git a/js/src/jit-test/tests/basic/setCallGlobal.js b/js/src/jit-test/tests/basic/setCallGlobal.js new file mode 100644 index 0000000000..a4ba54bae8 --- /dev/null +++ b/js/src/jit-test/tests/basic/setCallGlobal.js @@ -0,0 +1,14 @@ +var x = 1; +function f() { + function g() { + var t=0; + for (var i=0; i<3; i++) + x = i; + }; + g(); + eval("var x = 2"); + g(); + assertEq(x, 2); +} +f(); +assertEq(x, 2); diff --git a/js/src/jit-test/tests/basic/setPrototypeOf.js b/js/src/jit-test/tests/basic/setPrototypeOf.js new file mode 100644 index 0000000000..69558ac6c6 --- /dev/null +++ b/js/src/jit-test/tests/basic/setPrototypeOf.js @@ -0,0 +1,106 @@ +load(libdir + 'asserts.js'); + +function getObjects() { + function func(){} + return [func, + new func(), + {x: 5}, + /regexp/, + [1, 2, 3], + new Date(), + new Number(1), + new Boolean(true), + new String('str'), + Object.create(null)]; +} + +var coercibleValues = [1, + true, + 'string']; + +var nonCoercibleValues = [undefined, + null]; + +var valuesWithoutNull = coercibleValues.concat(undefined); + +function TestSetPrototypeOf(object, proto) { + assertEq(Object.setPrototypeOf(object, proto), object); + assertEq(Object.getPrototypeOf(object), proto); +} + +// check if Object.setPrototypeOf works with coercible values +for(var value of coercibleValues) { + assertEq(Object.setPrototypeOf(value, {}), value); +} + +// check if Object.setPrototypeOf fails on non-coercible values +for (var value of nonCoercibleValues) { + assertThrowsInstanceOf(() => Object.setPrototypeOf(value, {}), + TypeError, "Object.setPrototypeOf shouldn't work on non-coercible values"); +} + +// check if Object.setPrototypeOf works when prototype is set to non-objects +var objects = getObjects(); +for (var object of objects) { + for (var proto of valuesWithoutNull) { + assertThrowsInstanceOf(() => Object.setPrototypeOf(object, proto), + TypeError, "Object.setPrototypeOf fails when the prototype is set to non-objects"); + } +} + +// check if Object.setPrototypeOf works when prototype is set to objects +var objects1 = getObjects(); +var objects2 = getObjects(); +for (var object1 of objects1) { + for (var object2 of objects2) { + TestSetPrototypeOf(object1, object2); + } +} + +// check if Object.setPrototypeOf works when prototype is set to null +objects = getObjects(); +for (var object of objects) { + TestSetPrototypeOf(object, null); +} + +// check if Object.setPrototypeOf fails when object is not extensible +var objects = getObjects(); +var proto = {}; +for (var object of objects) { + Object.preventExtensions(object); + assertThrowsInstanceOf(() => Object.setPrototypeOf(object, proto), + TypeError, "Object.setPrototypeOf should fail when the object is not extensible"); +} + +// check if Object.setPrototypeof(A, B) succeeds on not extensible object A if +// prototype of A == B already +var objectProto = {}; +var nonExtensibleObject = Object.create(objectProto); +Object.preventExtensions(nonExtensibleObject); +assertEq(Object.setPrototypeOf(nonExtensibleObject, objectProto), nonExtensibleObject); + +// check if Object.setPrototypeOf works with prototype lookup +var object = {}; +assertEq('x' in object, false); +assertEq('y' in object, false); + +var oldProto = { + x: 'old x', + y: 'old y' +}; +Object.setPrototypeOf(object, oldProto); +assertEq(object.x, 'old x'); +assertEq(object.y, 'old y'); + +var newProto = { + x: 'new x' +}; +Object.setPrototypeOf(object, newProto); +assertEq(object.x, 'new x'); +assertEq('y' in object, false); + +// check if Object.setPrototypeOf throws TypeError on fewer arguments +assertThrowsInstanceOf(() => Object.setPrototypeOf(), + TypeError, "Object.setPrototypeOf throws TypeError when called without any parameters"); +assertThrowsInstanceOf(() => Object.setPrototypeOf({}), + TypeError, "Object.setPrototypeOf throws TypeError when called with 1 parameter"); diff --git a/js/src/jit-test/tests/basic/setelem.js b/js/src/jit-test/tests/basic/setelem.js new file mode 100644 index 0000000000..cdbe035b46 --- /dev/null +++ b/js/src/jit-test/tests/basic/setelem.js @@ -0,0 +1,12 @@ +var a; +function setelem() +{ + a = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; + a = a.concat(a, a, a); + var l = a.length; + for (var i = 0; i < l; i++) { + a[i] = i; + } + return a.toString(); +} +assertEq(setelem(), "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83"); diff --git a/js/src/jit-test/tests/basic/setprop-with-index.js b/js/src/jit-test/tests/basic/setprop-with-index.js new file mode 100644 index 0000000000..8d39c77600 --- /dev/null +++ b/js/src/jit-test/tests/basic/setprop-with-index.js @@ -0,0 +1,5 @@ +function f() +{ + arguments['4294967295'] = 2; +} +assertEq(f(), undefined); diff --git a/js/src/jit-test/tests/basic/setprop.js b/js/src/jit-test/tests/basic/setprop.js new file mode 100644 index 0000000000..bb93e1e498 --- /dev/null +++ b/js/src/jit-test/tests/basic/setprop.js @@ -0,0 +1,10 @@ +function setprop() +{ + var obj = { a:-1 }; + var obj2 = { b:-1, a:-1 }; + for (var i = 0; i < 20; i++) { + obj2.b = obj.a = i; + } + return [obj.a, obj2.a, obj2.b].toString(); +} +assertEq(setprop(), "19,-1,19"); diff --git a/js/src/jit-test/tests/basic/shape-checks.js b/js/src/jit-test/tests/basic/shape-checks.js new file mode 100644 index 0000000000..ba193a9cc2 --- /dev/null +++ b/js/src/jit-test/tests/basic/shape-checks.js @@ -0,0 +1,8 @@ +enableShapeConsistencyChecks(); +var o = {}; +for (var i = 0; i < 50; i++) { + o["x" + i] = i; +} +for (var i = 0; i < 50; i += 2) { + delete o["x" + i]; +} diff --git a/js/src/jit-test/tests/basic/shape-snapshots.js b/js/src/jit-test/tests/basic/shape-snapshots.js new file mode 100644 index 0000000000..866298caeb --- /dev/null +++ b/js/src/jit-test/tests/basic/shape-snapshots.js @@ -0,0 +1,37 @@ +function test1() { + var o = {x: 1, y: 2}; + var snapshot = createShapeSnapshot(o); + checkShapeSnapshot(snapshot); + Object.defineProperty(o, "z", {get: function() {}}); + checkShapeSnapshot(snapshot); + + snapshot = createShapeSnapshot(o); + checkShapeSnapshot(snapshot); + o[12345678] = 1; + checkShapeSnapshot(snapshot); + + snapshot = createShapeSnapshot(o); + Object.defineProperty(o, "a", {configurable: true, set: function(){}}); + checkShapeSnapshot(snapshot); + + snapshot = createShapeSnapshot(o); + checkShapeSnapshot(snapshot); + delete o.a; + checkShapeSnapshot(snapshot); +} +test1(); + +function test2() { + var dictObject = {x: 1, y: 2, z: 3}; + delete dictObject.x; + var objects = [this, {}, {x: 1}, {x: 2}, dictObject, function() {}, [1, 2], + Object.prototype, new Proxy({}, {})]; + var snapshots = objects.map(o => createShapeSnapshot(o)); + gc(); + snapshots.forEach(function(snapshot) { + objects.forEach(function(obj) { + checkShapeSnapshot(snapshot, obj); + }); + }); +} +test2(); diff --git a/js/src/jit-test/tests/basic/shape-teleporting-invalidation.js b/js/src/jit-test/tests/basic/shape-teleporting-invalidation.js new file mode 100644 index 0000000000..37769bcb5a --- /dev/null +++ b/js/src/jit-test/tests/basic/shape-teleporting-invalidation.js @@ -0,0 +1,144 @@ +// The shape teleporting optimization can be disabled for an object that's used +// as prototype when either it's involved in prototype changes or it had a property +// shadowed on another prototype object. + +function changeProps(o) { + Object.assign(o, {x: 1, y: 2, z: 3}); + o.foo = 4; + delete o.x; +} + +function testProtoChange() { + var receiver = {}; + var A = Object.create(null); + var B = Object.create(A); + + // Change |receiver|'s proto: receiver => B => A => null + // Because |receiver| is not used as a prototype object, this doesn't affect + // teleporting. + Object.setPrototypeOf(receiver, B); + assertEq(hasInvalidatedTeleporting(receiver), false); + assertEq(hasInvalidatedTeleporting(A), false); + assertEq(hasInvalidatedTeleporting(B), false); + + // Change B's proto to C: receiver => B => C => null + // Because B is used as prototype object, both A and B invalidate teleporting. + var C = Object.create(null); + Object.setPrototypeOf(B, C); + assertEq(hasInvalidatedTeleporting(receiver), false); + assertEq(hasInvalidatedTeleporting(A), true); + assertEq(hasInvalidatedTeleporting(B), true); + assertEq(hasInvalidatedTeleporting(C), false); + + // Change B's proto a second time: receiver => B => D => null + // Now C has teleporting invalidated too. + var D = Object.create(null); + Object.setPrototypeOf(B, D); + assertEq(hasInvalidatedTeleporting(receiver), false); + assertEq(hasInvalidatedTeleporting(A), true); + assertEq(hasInvalidatedTeleporting(B), true); + assertEq(hasInvalidatedTeleporting(C), true); + assertEq(hasInvalidatedTeleporting(D), false); + + // Changing properties (without shadowing) must not affect teleporting state. + changeProps(C); + changeProps(D); + assertEq(hasInvalidatedTeleporting(C), true); + assertEq(hasInvalidatedTeleporting(D), false); +} +testProtoChange(); + +function testShadowingProp() { + // receiver => C => B => A => null + var A = Object.create(null); + var B = Object.create(A); + var C = Object.create(B); + var receiver = Object.create(C); + + // Adding non-shadowing properties doesn't affect teleporting. + A.a = 1; + B.b = 1; + C.c = 1; + receiver.receiver = 1; + assertEq(hasInvalidatedTeleporting(receiver), false); + assertEq(hasInvalidatedTeleporting(C), false); + assertEq(hasInvalidatedTeleporting(B), false); + assertEq(hasInvalidatedTeleporting(A), false); + + // Objects not used as prototype can shadow properties without affecting + // teleporting. + receiver.a = 1; + receiver.b = 2; + receiver.c = 3; + assertEq(hasInvalidatedTeleporting(receiver), false); + assertEq(hasInvalidatedTeleporting(C), false); + assertEq(hasInvalidatedTeleporting(B), false); + assertEq(hasInvalidatedTeleporting(A), false); + + // Shadowing a property of B on C invalidates teleporting for B. + C.b = 1; + assertEq(hasInvalidatedTeleporting(receiver), false); + assertEq(hasInvalidatedTeleporting(C), false); + assertEq(hasInvalidatedTeleporting(B), true); + assertEq(hasInvalidatedTeleporting(A), false); + + // Shadowing a property of A on C invalidates teleporting for A. + C.a = 2; + assertEq(hasInvalidatedTeleporting(receiver), false); + assertEq(hasInvalidatedTeleporting(C), false); + assertEq(hasInvalidatedTeleporting(B), true); + assertEq(hasInvalidatedTeleporting(A), true); + + // Changing properties (without shadowing) must not affect teleporting state. + changeProps(C); + changeProps(B); + assertEq(hasInvalidatedTeleporting(C), false); + assertEq(hasInvalidatedTeleporting(B), true); +} +testShadowingProp(); + +function testShadowingPropStopsAtFirst() { + // receiver => C => B{x,y} => A{x,y,z} => null + var A = Object.create(null); + A.x = 1; + A.y = 2; + A.z = 3; + var B = Object.create(A); + B.x = 1; + B.y = 2; + var C = Object.create(B); + var receiver = Object.create(C); + + // Teleporting is supported. + assertEq(hasInvalidatedTeleporting(receiver), false); + assertEq(hasInvalidatedTeleporting(C), false); + assertEq(hasInvalidatedTeleporting(B), false); + assertEq(hasInvalidatedTeleporting(A), false); + + // Shadowing a property of B (and A) on C. + // This invalidates teleporting for B but not for A, because the search stops + // at B. + C.x = 1; + assertEq(hasInvalidatedTeleporting(receiver), false); + assertEq(hasInvalidatedTeleporting(C), false); + assertEq(hasInvalidatedTeleporting(B), true); + assertEq(hasInvalidatedTeleporting(A), false); + + // "y" is similar. + C.y = 2; + assertEq(hasInvalidatedTeleporting(receiver), false); + assertEq(hasInvalidatedTeleporting(C), false); + assertEq(hasInvalidatedTeleporting(B), true); + assertEq(hasInvalidatedTeleporting(A), false); + + // "z" is only defined on A, so now A is affected. + C.z = 3; + assertEq(hasInvalidatedTeleporting(receiver), false); + assertEq(hasInvalidatedTeleporting(C), false); + assertEq(hasInvalidatedTeleporting(B), true); + assertEq(hasInvalidatedTeleporting(A), true); +} +testShadowingPropStopsAtFirst(); + +// Ensure teleporting properties on Object.prototype is still possible. +assertEq(hasInvalidatedTeleporting(Object.prototype), false); diff --git a/js/src/jit-test/tests/basic/shape-teleporting-transplant-1.js b/js/src/jit-test/tests/basic/shape-teleporting-transplant-1.js new file mode 100644 index 0000000000..889fcaf7b0 --- /dev/null +++ b/js/src/jit-test/tests/basic/shape-teleporting-transplant-1.js @@ -0,0 +1,36 @@ +// Test for invalidating shape teleporting when transplanting objects on proto +// chains. + +function checkGetProp(obj, expected) { + for (var i = 0; i < 50; i++) { + assertEq(obj.prop, expected); + } +} + +Object.prototype.prop = 1234; + +// Construct the following proto chain: +// +// receiver => protoA (FakeDOMObject) => protoB {prop: 567} => null +const protoB = Object.create(null); +protoB.prop = 567; +const protoA = new FakeDOMObject(); +Object.setPrototypeOf(protoA, protoB); +const receiver = Object.create(protoA); + +// Ensure all objects we allocated are tenured. This way we don't need to trigger +// a GC later in TransplantableObject, which makes the test more reliable. +gc(); + +// Attach an IC for `receiver.prop`. +checkGetProp(receiver, 567); + +// Swap protoA with another object. This must invalidate shape teleporting, +// because the proto chain of `receiver` now looks like this: +// +// receiver => protoA (new FakeDOMObject) => FakeDOMObject.prototype => Object.prototype => null +const {transplant} = transplantableObject({object: protoA}); +transplant(this); + +// `receiver.prop` now gets `prop` from Object.prototype. +checkGetProp(receiver, 1234); diff --git a/js/src/jit-test/tests/basic/shape-teleporting-transplant-2.js b/js/src/jit-test/tests/basic/shape-teleporting-transplant-2.js new file mode 100644 index 0000000000..b3b7189ceb --- /dev/null +++ b/js/src/jit-test/tests/basic/shape-teleporting-transplant-2.js @@ -0,0 +1,16 @@ +// Put DOM object on prototype chain +let x = new FakeDOMObject; +let y = Object.create(x); + +// Transplant the DOM object while it is still a prototype +let g = newGlobal({newCompartment: true}); +let { transplant } = transplantableObject({ object: x }); + +// JIT an IC to access Object.prototype.toString +function f(o) { return o.toString; } +for (var i = 0; i < 20; ++i) { f(y) } + +// Transplanting should not interfere with teleporting +transplant(g); +x.toString = "override"; +assertEq(f(y), "override"); diff --git a/js/src/jit-test/tests/basic/shapelessCalleeTest.js b/js/src/jit-test/tests/basic/shapelessCalleeTest.js new file mode 100644 index 0000000000..6d12e7c9d8 --- /dev/null +++ b/js/src/jit-test/tests/basic/shapelessCalleeTest.js @@ -0,0 +1,67 @@ +// The following functions use a delay line of length 2 to change the value +// of the callee without exiting the traced loop. This is obviously tuned to +// match the current 8 setting of 2. +function shapelessArgCalleeLoop(f, g, h, a) +{ + for (var i = 0; i < 10; i++) { + f(i, a); + f = g; + g = h; + } +} + +function shapelessVarCalleeLoop(f0, g, h, a) +{ + var f = f0; + for (var i = 0; i < 10; i++) { + f(i, a); + f = g; + g = h; + } +} + +function shapelessLetCalleeLoop(f0, g, h, a) +{ + for (var i = 0; i < 10; i++) { + let f = f0; + f(i, a); + f = g; + g = h; + } +} + +function shapelessUnknownCalleeLoop(n, f, g, h, a) +{ + for (var i = 0; i < 10; i++) { + (n || f)(i, a); + f = g; + g = h; + } +} + +function shapelessCalleeTest() +{ + var a = []; + + var helper = function (i, a) { a[i] = i; }; + shapelessArgCalleeLoop(helper, helper, function (i, a) { a[i] = -i; }, a); + + helper = function (i, a) { a[10 + i] = i; }; + shapelessVarCalleeLoop(helper, helper, function (i, a) { a[10 + i] = -i; }, a); + + helper = function (i, a) { a[20 + i] = i; }; + shapelessLetCalleeLoop(helper, helper, function (i, a) { a[20 + i] = -i; }, a); + + helper = function (i, a) { a[30 + i] = i; }; + shapelessUnknownCalleeLoop(null, helper, helper, function (i, a) { a[30 + i] = -i; }, a); + + try { + helper = {hack: 42}; + shapelessUnknownCalleeLoop(null, helper, helper, helper, a); + } catch (e) { + if (e + "" != "TypeError: f is not a function") + print("shapelessUnknownCalleeLoop: unexpected exception " + e); + } + return a.join(""); +} +assertEq(shapelessCalleeTest(), "01-2-3-4-5-6-7-8-901-2-3-4-5-6-7-8-9012345678901-2-3-4-5-6-7-8-9"); diff --git a/js/src/jit-test/tests/basic/shell-prefs.js b/js/src/jit-test/tests/basic/shell-prefs.js new file mode 100644 index 0000000000..f0c2c8a251 --- /dev/null +++ b/js/src/jit-test/tests/basic/shell-prefs.js @@ -0,0 +1,24 @@ +// |jit-test| --setpref=site_based_pretenuring=false; --setpref=tests.uint32-pref=123450 + +let names = getAllPrefNames(); +assertEq(names.length > 0, true, "Expected at least one pref!"); +assertEq(new Set(names).size, names.length, "Unexpected duplicate pref name"); + +for (let name of names) { + let val = getPrefValue(name); + assertEq(typeof val === "number" || typeof val === "boolean", true); +} + +// Check that --setpref worked. Note: this is just an arbitrary pref. If we ever +// remove it, change this test to check a different one. +assertEq(getPrefValue("site_based_pretenuring"), false); +assertEq(getPrefValue("tests.uint32-pref"), 123450); + +// Must throw an exception for unknown pref names. +let ex; +try { + getPrefValue("some.invalid.pref"); +} catch (e) { + ex = e; +} +assertEq(ex.toString(), "Error: invalid pref name"); diff --git a/js/src/jit-test/tests/basic/shell-principals.js b/js/src/jit-test/tests/basic/shell-principals.js new file mode 100644 index 0000000000..4b330f6616 --- /dev/null +++ b/js/src/jit-test/tests/basic/shell-principals.js @@ -0,0 +1,55 @@ +// Test the JS shell's toy principals. + +var count = 0; + +// Given a string of letters |expected|, say "abc", assert that the stack +// contains calls to a series of functions named by the next letter from +// the string, say a, b, and then c. Younger frames appear earlier in +// |expected| than older frames. +function check(expected, stack) { + print("check(" + JSON.stringify(expected) + ") against:\n" + stack); + count++; + + // Extract only the function names from the stack trace. Omit the frames + // for the top-level evaluation, if it is present. + var split = stack.split(/(.)?@.*\n/).slice(0, -1); + if (split[split.length - 1] === undefined) + split = split.slice(0, -2); + + // Check the function names against the expected sequence. + assertEq(split.length, expected.length * 2); + for (var i = 0; i < expected.length; i++) + assertEq(split[i * 2 + 1], expected[i]); +} + +var low = newGlobal({ principal: 0 }); +var mid = newGlobal({ principal: 0xffff }); +var high = newGlobal({ principal: 0xfffff }); + + eval('function a() { check("a", Error().stack); b(); }'); +low .eval('function b() { check("b", Error().stack); c(); }'); +mid .eval('function c() { check("cba", Error().stack); d(); }'); +high.eval('function d() { check("dcba", Error().stack); e(); }'); + +// Globals created with no explicit principals get 0xffff. + eval('function e() { check("ecba", Error().stack); f(); }'); + +low .eval('function f() { check("fb", Error().stack); g(); }'); +mid .eval('function g() { check("gfecba", Error().stack); h(); }'); +high.eval('function h() { check("hgfedcba", Error().stack); }'); + +// Make everyone's functions visible to each other, as needed. + b = low .b; +low .c = mid .c; +mid .d = high.d; +high.e = e; + f = low .f; +low .g = mid .g; +mid .h = high.h; + +low.check = mid.check = high.check = check; + +// Kick the whole process off. +a(); + +assertEq(count, 8); diff --git a/js/src/jit-test/tests/basic/shell-watchdog.js b/js/src/jit-test/tests/basic/shell-watchdog.js new file mode 100644 index 0000000000..04ae0d9e71 --- /dev/null +++ b/js/src/jit-test/tests/basic/shell-watchdog.js @@ -0,0 +1,16 @@ +// |jit-test| exitstatus: 6; skip-if: getBuildConfiguration("wasi") + +/* This test will loop infinitely if the shell watchdog + fails to kick in. */ + +timeout(0.1); +var start = new Date(); + +while (true) { + var end = new Date(); + var duration = (end.getTime() - start.getTime()) / 1000; + if (duration > 1) { + print("tick"); + start = new Date(); + } +} 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 0000000000..ee001c5e35 --- /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 0000000000..f989db1542 --- /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 0000000000..6bbe296faa --- /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 0000000000..59bd836087 --- /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 0000000000..07e0bce5b5 --- /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 0000000000..671e493254 --- /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/jit-test/tests/basic/shifted-elements7.js b/js/src/jit-test/tests/basic/shifted-elements7.js new file mode 100644 index 0000000000..3adcb61be8 --- /dev/null +++ b/js/src/jit-test/tests/basic/shifted-elements7.js @@ -0,0 +1,47 @@ +function test1() { + var a = []; + for (var i = 0; i < 100; i++) + a.unshift("foo" + i); + for (var i = 99; i >= 0; i--) { + assertEq(a.shift(), "foo" + i); + a.unshift("foo" + (i - 1)); + } + assertEq(a.length, 100); +} +test1(); + +function sum(arr) { + var res = 0; + for (var i = 0; i < arr.length; i++) + res += arr[i]; + return res; +} +function test2() { + var a = []; + for (var i = 0; i < 200; i++) + a.push(i); + for (var i = 0; i < 100; i++) + a.shift(); + for (var i = 0; i < 200; i++) + a.unshift(i); + assertEq(a.length, 300); + assertEq(sum(a), 34850); +} +test2(); + +function test3() { + var a = []; + for (var i = 0; i < 200; i++) + a.push(i); + var toAdd = []; + var step = 1; + for (var i = 0; i < 2500; i += step) { + for (var j = 0; j < step; j++) + toAdd.unshift(i + j); + a.unshift(...toAdd); + step = Math.max((i / 16)|0, 1); + } + assertEq(a.length, 41463); + assertEq(sum(a), 26657756); +} +test3(); diff --git a/js/src/jit-test/tests/basic/singleton.js b/js/src/jit-test/tests/basic/singleton.js new file mode 100644 index 0000000000..8e7c4c8faf --- /dev/null +++ b/js/src/jit-test/tests/basic/singleton.js @@ -0,0 +1,12 @@ + +var a = [1,2,3,4]; +var b = [{a:0,b:1},{a:0,b:1},{a:0,b:1}]; +var c = {a:0,b:4.5}; +var d = [1,2,3,true]; +var e = {a:0,b:1,c:2}; +var f = {a:0,b:1,c:true}; + +var w = JSON.parse('[1,2,3,4]'); +var x = JSON.parse('{"a":0,"b":true,"c":4.5}'); +var y = JSON.parse('{"d":true,"b":true,"c":4.5}'); +var z = JSON.parse('[{"a":0,"b":1},{"a":0,"b":1},{"a":0,"b":1}]'); diff --git a/js/src/jit-test/tests/basic/sleep-without-timeout.js b/js/src/jit-test/tests/basic/sleep-without-timeout.js new file mode 100644 index 0000000000..c912b18792 --- /dev/null +++ b/js/src/jit-test/tests/basic/sleep-without-timeout.js @@ -0,0 +1,6 @@ +// sleep() should work without timeout() prior to it. + +sleep(0.001); +sleep(0.01); +sleep(0.1); +sleep(1); diff --git a/js/src/jit-test/tests/basic/sparse-and-dense-elements.js b/js/src/jit-test/tests/basic/sparse-and-dense-elements.js new file mode 100644 index 0000000000..2c18c98f93 --- /dev/null +++ b/js/src/jit-test/tests/basic/sparse-and-dense-elements.js @@ -0,0 +1,20 @@ +function f(o) { + for (var i = 0; i < 40; i++) { + if ((i > 10 && (i % 2) === 0) || i > 30) { + Object.defineProperty(o, i, {value: i, enumerable: false, + writable: true, configurable: true}); + } else { + o[i] = i; + } + } + for (var i = 0; i < 15; i++) { + var sum = 0; + for (var j = 0; j < 40; j++) { + o[j]++; + sum += o[j]; + } + assertEq(sum, 820 + i * 40); + } +} +f({}); +f([]); diff --git a/js/src/jit-test/tests/basic/splice-675164.js b/js/src/jit-test/tests/basic/splice-675164.js new file mode 100644 index 0000000000..10d0d97887 --- /dev/null +++ b/js/src/jit-test/tests/basic/splice-675164.js @@ -0,0 +1,15 @@ +function NPList() {} +NPList.prototype = new Array; + +var list = new NPList(); +list.push('a'); + +var cut = list.splice(0, 1); + +assertEq(cut[0], 'a'); +assertEq(cut.length, 1); +assertEq(list.length, 0); + +var desc = Object.getOwnPropertyDescriptor(list, "0"); +assertEq(desc, undefined); +assertEq("0" in list, false); diff --git a/js/src/jit-test/tests/basic/splice-call-plain-object-590780.js b/js/src/jit-test/tests/basic/splice-call-plain-object-590780.js new file mode 100644 index 0000000000..4a0dc5d159 --- /dev/null +++ b/js/src/jit-test/tests/basic/splice-call-plain-object-590780.js @@ -0,0 +1,8 @@ +var o = { 0: 1, 1: 2, 2: 3, length: 3 }; +Array.prototype.splice.call(o, 0, 1); + +assertEq(o[0], 2); +assertEq(o[1], 3); +assertEq(Object.getOwnPropertyDescriptor(o, 2), undefined); +assertEq("2" in o, false); +assertEq(o.length, 2); diff --git a/js/src/jit-test/tests/basic/splice-check-steps.js b/js/src/jit-test/tests/basic/splice-check-steps.js new file mode 100644 index 0000000000..25985e9f32 --- /dev/null +++ b/js/src/jit-test/tests/basic/splice-check-steps.js @@ -0,0 +1,297 @@ +/* + * Check the order of splice's internal operations, because the ordering is + * visible externally. + */ + +function handlerMaker(expected_exceptions) { + var order = []; + function note(trap, name) + { + order.push(trap + '-' + name); + if (expected_exceptions[trap] === name) { + throw ("fail"); + } + } + + return [{ + /* this is the only trap we care about */ + deleteProperty: function(target, name) { + note("del", name); + return Reflect.deleteProperty(target, name); + }, + // derived traps + has: function(target, name) { + note("has", name); + return name in target; + }, + get: function(target, name, receiver) { + note("get", name); + return Reflect.get(target, name, receiver); + }, + set: function(target, name, value, receiver) { + note("set", name); + return Reflect.set(target, name, value, receiver); + }, + }, order]; +} + +// arr: the array to splice +// expected_order: the expected order of operations on arr, stringified +function check_splice_proxy(arr, expected_order, expected_exceptions, expected_array, expected_result) { + print (arr); + var [handler, store] = handlerMaker(expected_exceptions); + var proxy = new Proxy(arr, handler); + + try { + var args = Array.prototype.slice.call(arguments, 5); + var result = Array.prototype.splice.apply(proxy, args); + assertEq(Object.keys(expected_exceptions).length, 0); + } catch (e) { + assertEq(Object.keys(expected_exceptions).length > 0, true); + } + + // check the order of the property accesses, etc + assertEq(store.toString(), expected_order); + + // The deleted elements are returned in an object that's always an Array. + assertEq(Array.isArray(result) || result === undefined, true); + + // check the return value + for (var i in expected_result) { + assertEq(result[i], expected_result[i]); + } + for (var i in result) { + assertEq(result[i], expected_result[i]); + } + + // check the value of arr + for (var i in expected_array) { + assertEq(arr[i], expected_array[i]); + } + for (var i in arr) { + assertEq(arr[i], expected_array[i]); + } + + return result; +} + +// Shrinking array +check_splice_proxy( + [10,1,2,3,4,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1,get-1,has-2,get-2," + + "has-3,get-3,set-0,has-4,get-4,set-1,has-5,get-5,set-2," + + "del-5,del-4,del-3," + + "set-length", + {}, + [3,4,5], + [10,1,2], + 0, 3 +); + +// Growing array +check_splice_proxy( + [11,1,2,3,4,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1,get-1,has-2,get-2," + + "has-5,get-5,set-9,has-4,get-4,set-8,has-3,get-3,set-7," + + "set-0,set-1,set-2,set-3,set-4,set-5,set-6," + + "set-length", + {}, + [9,9,9,9,9,9,9,3,4,5], + [11,1,2], + 0, 3, 9, 9, 9, 9, 9, 9, 9 +); + +// Same sized array +check_splice_proxy( + [12,1,2,3,4,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1,get-1,has-2,get-2," + + "set-0,set-1,set-2," + + "set-length", + {}, + [9,9,9,3,4,5], + [12,1,2], + 0, 3, 9, 9, 9 +); + + +/* + * Check that if we fail at a particular step in the algorithm, we don't + * continue with the algorithm beyond that step. + */ + + +// Step 3: fail when getting length +check_splice_proxy( + [13,1,2,3,4,5], + "get-length", + {get: 'length'}, + [13,1,2,3,4,5], + undefined, + 0, 3, 9, 9, 9 +); + +// Step 9b: fail when [[HasProperty]] +check_splice_proxy( + [14,1,2,3,4,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1", + {has: '1'}, + [14,1,2,3,4,5], + undefined, + 0, 3, 9, 9, 9 +); + +// Step 9c(i): fail when [[Get]] +check_splice_proxy( + [15,1,2,3,4,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1,get-1", + {get: '1'}, + [15,1,2,3,4,5], + undefined, + 0, 3, 9, 9, 9 +); + +// Step 12b(iii): fail when [[HasProperty]] +check_splice_proxy( + [16,1,2,3,4,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1,get-1,has-2,get-2," + + "has-3,get-3,set-0,has-4", + {has: '4'}, + [3,1,2,3,4,5], + undefined, + 0, 3 +); + + +// Step 12b(iv)1: fail when [[Get]] +check_splice_proxy( + [17,1,2,3,4,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1,get-1,has-2,get-2," + + "has-3,get-3,set-0,has-4,get-4", + {get: '4'}, + [3,1,2,3,4,5], + undefined, + 0, 3 +); + + +// Step 12b(iv)2: fail when [[Put]] +check_splice_proxy( + [18,1,2,3,4,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1,get-1,has-2,get-2," + + "has-3,get-3,set-0,has-4,get-4,set-1", + {set: '1'}, + [3,1,2,3,4,5], + undefined, + 0, 3 +); + +// Step 12b(v)1: fail when [[Delete]] +check_splice_proxy( + [19,1,2,3,,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1,get-1,has-2,get-2," + + "has-3,get-3,set-0,has-4,del-1", + {del: '1'}, + [3,1,2,3,,5], + undefined, + 0, 3 +); + +// Step 12d(i): fail when [[Delete]] +check_splice_proxy( + [20,1,2,3,4,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1,get-1,has-2,get-2," + + "has-3,get-3,set-0,has-4,get-4,set-1,has-5,get-5,set-2," + + "del-5,del-4", + {del: '4'}, + [3,4,5,3,4], + undefined, + 0, 3 +); + +// Step 13b(iii): fail when [[HasProperty]] +check_splice_proxy( + [21,1,2,3,4,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1,get-1,has-2,get-2," + + "has-5,get-5,set-8,has-4", + {has: '4'}, + [21,1,2,3,4,5,,,5], + undefined, + 0, 3, 9,9,9,9,9,9 +); + + +// Step 13b(iv)1: fail when [[Get]] +check_splice_proxy( + [22,1,2,3,4,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1,get-1,has-2,get-2," + + "has-5,get-5,set-8,has-4,get-4", + {get: '4'}, + [22,1,2,3,4,5,,,5], + undefined, + 0, 3, 9,9,9,9,9,9 +); + + +// Step 13b(iv)2: fail when [[Put]] +check_splice_proxy( + [23,1,2,3,4,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1,get-1,has-2,get-2," + + "has-5,get-5,set-8,has-4,get-4,set-7", + {set: '7'}, + [23,1,2,3,4,5,,,5], + undefined, + 0, 3, 9,9,9,9,9,9 +); + +// Step 13b(v)1: fail when [[Delete]] +check_splice_proxy( + [24,1,2,3,,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1,get-1,has-2,get-2," + + "has-5,get-5,set-8,has-4,del-7", + {del: '7'}, + [24,1,2,3,,5,,,5], + undefined, + 0, 3, 9,9,9,9,9,9 +); + +// Step 15b: fail when [[Put]] +check_splice_proxy( + [25,1,2,3,4,5], + "get-length," + + "get-constructor," + + "has-0,get-0,has-1,get-1,has-2,get-2," + + "has-5,get-5,set-8,has-4,get-4,set-7,has-3,get-3,set-6," + + "set-0,set-1,set-2", + {set: '2'}, + [9,9,2,3,4,5,3,4,5], + undefined, + 0, 3, 9,9,9,9,9,9 +); diff --git a/js/src/jit-test/tests/basic/splice-delete-non-configurable-during-shrink.js b/js/src/jit-test/tests/basic/splice-delete-non-configurable-during-shrink.js new file mode 100644 index 0000000000..93dddb5cc6 --- /dev/null +++ b/js/src/jit-test/tests/basic/splice-delete-non-configurable-during-shrink.js @@ -0,0 +1,26 @@ +/* Test that splice causing deletion of a non-configurable property stops at exactly step 12(v) of ES5 15.4.4.12 */ + +var O = [1,2,3,4,5,6]; +var A = undefined; +Object.defineProperty(O, 3, { configurable: false }); + +try +{ + A = O.splice(0, 6); + throw new Error("didn't throw, returned " + A); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "deleting O[3] should have caused a TypeError"); +} + +assertEq(O.length, 6); // setting length not reached +assertEq(A, undefined); // return value not reached + +assertEq(O[5], undefined); // deletion reached +assertEq(O[4], undefined); // deletion reached +assertEq(O[3], 4); // deletion caused exception +assertEq(O[2], 3); // deletion not reached +assertEq(O[1], 2); // deletion not reached +assertEq(O[0], 1); // deletion not reached diff --git a/js/src/jit-test/tests/basic/splice-fail-step-16.js b/js/src/jit-test/tests/basic/splice-fail-step-16.js new file mode 100644 index 0000000000..549ad0129d --- /dev/null +++ b/js/src/jit-test/tests/basic/splice-fail-step-16.js @@ -0,0 +1,25 @@ +/* Test that arrays resize normally during splice, even if .length is non-writable. */ + +var arr = [1, 2, 3, 4, 5, 6]; + +Object.defineProperty(arr, "length", {writable: false}); + +try +{ + var removed = arr.splice(3, 3, 9, 9, 9, 9); + throw new Error("splice didn't throw, returned [" + removed + "]"); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "should have thrown a TypeError, instead threw " + e + ", arr is " + arr); +} + +// The exception should happen in step 16, which means we've already removed the array elements. +assertEq(arr[0], 1); +assertEq(arr[1], 2); +assertEq(arr[2], 3); +assertEq(arr[3], 9); +assertEq(arr[4], 9); +assertEq(arr[5], 9); +assertEq(arr.length, 6); diff --git a/js/src/jit-test/tests/basic/splice-huge-array-finishes.js b/js/src/jit-test/tests/basic/splice-huge-array-finishes.js new file mode 100644 index 0000000000..d894e50888 --- /dev/null +++ b/js/src/jit-test/tests/basic/splice-huge-array-finishes.js @@ -0,0 +1,15 @@ +// Making the array huge and sparse shouldn't leave us iterating through the entire array. +// But it does, sadly. Disable, because it takes too long. +if (0) { + var arr = [1, 2, 3, 4, 5, 6, 7, 8]; + arr.length = Math.pow(2, 32) - 2; + arr.splice(5); // also test overflow + + assertEq(arr.length, 5); + assertEq(arr[0], 1); + assertEq(arr[1], 2); + assertEq(arr[2], 3); + assertEq(arr[3], 4); + assertEq(arr[4], 5); + assertEq(arr[5], undefined); +} diff --git a/js/src/jit-test/tests/basic/splice-on-arguments.js b/js/src/jit-test/tests/basic/splice-on-arguments.js new file mode 100644 index 0000000000..e36522ae0c --- /dev/null +++ b/js/src/jit-test/tests/basic/splice-on-arguments.js @@ -0,0 +1,39 @@ +// test whether splice works on arguments + +function splice_args () { + args = arguments; + return Array.prototype.splice.apply(args, [0, 5]); +} + +var args; +var O = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; +var A = splice_args.apply(undefined, O) + +// args: [5, 6, 7, 8, 9] +assertEq(args[0], 5); +assertEq(args[1], 6); +assertEq(args[2], 7); +assertEq(args[3], 8); +assertEq(args[4], 9); +assertEq(args.length, 5); + +// A: [0, 1, 2, 3, 4] +assertEq(A[0], 0); +assertEq(A[1], 1); +assertEq(A[2], 2); +assertEq(A[3], 3); +assertEq(A[4], 4); +assertEq(A.length, 5); + +// O: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +assertEq(O[0], 0); +assertEq(O[1], 1); +assertEq(O[2], 2); +assertEq(O[3], 3); +assertEq(O[4], 4); +assertEq(O[5], 5); +assertEq(O[6], 6); +assertEq(O[7], 7); +assertEq(O[8], 8); +assertEq(O[9], 9); +assertEq(O.length, 10); diff --git a/js/src/jit-test/tests/basic/splice-throwing-length-getter-668024.js b/js/src/jit-test/tests/basic/splice-throwing-length-getter-668024.js new file mode 100644 index 0000000000..695460b5c8 --- /dev/null +++ b/js/src/jit-test/tests/basic/splice-throwing-length-getter-668024.js @@ -0,0 +1,9 @@ +try +{ + Array.prototype.splice.call({ get length() { throw 'error'; } }); + throw new Error("should have thrown, didn't"); +} +catch (e) +{ + assertEq(e, "error", "wrong error thrown: " + e); +} diff --git a/js/src/jit-test/tests/basic/spread-array-bug842884.js b/js/src/jit-test/tests/basic/spread-array-bug842884.js new file mode 100644 index 0000000000..909bb5c6be --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-array-bug842884.js @@ -0,0 +1,5 @@ +load(libdir + "asserts.js"); + +assertThrowsInstanceOf(function () { + var [] = [x, ...d]; +}, ReferenceError); diff --git a/js/src/jit-test/tests/basic/spread-array-decompile.js b/js/src/jit-test/tests/basic/spread-array-decompile.js new file mode 100644 index 0000000000..10939664dd --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-array-decompile.js @@ -0,0 +1,14 @@ +var samples = [ + "[...a]", + "[...[1]]", + "[1, ...a, 2]", + "[1, ...[2, 3], 4]", + "[...[1], , ]", + "[1, , ...[2]]", + "[, 1, ...[2], ...[3], , 4, 5, , ]" +]; +for (var sample of samples) { + var source = "function f() {\n return " + sample + ";\n}"; + eval(source); + assertEq(f.toString(), source); +} diff --git a/js/src/jit-test/tests/basic/spread-array-evaluation-order.js b/js/src/jit-test/tests/basic/spread-array-evaluation-order.js new file mode 100644 index 0000000000..0887a05926 --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-array-evaluation-order.js @@ -0,0 +1,12 @@ +load(libdir + "eqArrayHelper.js"); + +var check = []; +function t(token) { + check.push(token); + return token; +} +[3, ...[t(1)],, ...[t(2), t(3)], 34, 42, ...[t(4)]]; +assertEqArray(check, [1, 2, 3, 4]); + +var arr = [1, 2, 3]; +assertEqArray([...arr, arr.pop()], [1, 2, 3, 3]); diff --git a/js/src/jit-test/tests/basic/spread-array-invalid-syntax.js b/js/src/jit-test/tests/basic/spread-array-invalid-syntax.js new file mode 100644 index 0000000000..a7bcd5205a --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-array-invalid-syntax.js @@ -0,0 +1,19 @@ +load(libdir + "asserts.js"); + +var offenders = [ + "(1 ... n)", + "[1 ... n]", + "(...x)", + "[...x for (x of y)]", + "[...x, x for (x of y)]", + "[...]", + "(...)", + "[...,]", + "[... ...[]]", + "(... ...[])", + "[x, ...]", + "(x, ...)" +]; +for (var sample of offenders) { + assertThrowsInstanceOf(function () { eval(sample); }, SyntaxError); +} diff --git a/js/src/jit-test/tests/basic/spread-array-wrap.js b/js/src/jit-test/tests/basic/spread-array-wrap.js new file mode 100644 index 0000000000..84a57bdd94 --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-array-wrap.js @@ -0,0 +1,5 @@ +load(libdir + "eqArrayHelper.js"); + +// XXX disabled bug 827449 +//assertEqArray([...wrap([1])], [1]); +//assertEqArray([1,, ...wrap([2, 3, 4]), 5, ...wrap([6])], [1,, 2, 3, 4, 5, 6]); diff --git a/js/src/jit-test/tests/basic/spread-array.js b/js/src/jit-test/tests/basic/spread-array.js new file mode 100644 index 0000000000..30d4cb52b4 --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-array.js @@ -0,0 +1,50 @@ +load(libdir + "asserts.js"); +load(libdir + "iteration.js"); +load(libdir + "eqArrayHelper.js"); + +assertEqArray([...[1, 2, 3]], [1, 2, 3]); +assertEqArray([1, ...[2, 3, 4], 5], [1, 2, 3, 4, 5]); +assertEqArray([1, ...[], 2], [1, 2]); +assertEqArray([1, ...[2, 3], 4, ...[5, 6]], [1, 2, 3, 4, 5, 6]); +assertEqArray([1, ...[], 2], [1, 2]); +assertEqArray([1,, ...[2]], [1,, 2]); +assertEqArray([1,, ...[2],, 3,, 4,], [1,, 2,, 3,, 4,]); +assertEqArray([...[1, 2, 3],,,,], [1, 2, 3,,,,]); +assertEqArray([,,...[1, 2, 3],,,,], [,,1,2,3,,,,]); +assertEqArray([...[1, 2, 3],,,,...[]], [1,2,3,,,,]); + +assertEqArray([...[undefined]], [undefined]); + +// other iterable objects +assertEqArray([...new Int32Array([1, 2, 3])], [1, 2, 3]); +assertEqArray([..."abc"], ["a", "b", "c"]); +assertEqArray([...[1, 2, 3][Symbol.iterator]()], [1, 2, 3]); +assertEqArray([...new Set([1, 2, 3])], [1, 2, 3]); +assertEqArray([...new Map([["a", "A"], ["b", "B"], ["c", "C"]])].map(([k, v]) => k + v), ["aA", "bB", "cC"]); +let itr = {}; +itr[Symbol.iterator] = function () { + return { + i: 1, + next: function() { + if (this.i < 4) + return { value: this.i++, done: false }; + else + return { value: undefined, done: true }; + } + }; +} +assertEqArray([...itr], [1, 2, 3]); +function* gen() { + for (let i = 1; i < 4; i ++) + yield i; +} +assertEqArray([...gen()], [1, 2, 3]); + +let a, b = [1, 2, 3]; +assertEqArray([...a=b], [1, 2, 3]); + +// 12.2.4.1.2 Runtime Semantics: ArrayAccumulation +// If Type(spreadObj) is not Object, then throw a TypeError exception. +assertThrowsInstanceOf(() => [...null], TypeError); +assertThrowsInstanceOf(() => [...undefined], TypeError); + diff --git a/js/src/jit-test/tests/basic/spread-call-eval.js b/js/src/jit-test/tests/basic/spread-call-eval.js new file mode 100644 index 0000000000..1fad8e7a59 --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-eval.js @@ -0,0 +1,54 @@ +load(libdir + "asserts.js"); +load(libdir + "iteration.js"); + +assertEq(eval(...[]), undefined); +assertEq(eval(...["1 + 2"]), 3); + +let a = 10, b = 1; +assertEq(eval(...["a + b"]), 11); + +(function() { + let a = 20; + assertEq(eval(...["a + b"]), 21); +})(); + +with ({ a: 30 }) { + assertEq(eval(...["a + b"]), 31); +} + +let line0 = Error().lineNumber; +try { // line0 + 1 + eval(...["("]); // line0 + 2 +} catch (e) { + assertEq(e.lineNumber, 1); +} + +// other iterable objects +assertEq(eval(...["a + b"][Symbol.iterator]()), 11); +assertEq(eval(...new Set(["a + b"])), 11); +let itr = {}; +itr[Symbol.iterator] = function() { + return { + i: 0, + next: function() { + this.i++; + if (this.i == 1) + return { value: "a + b", done: false }; + else + return { value: undefined, done: true }; + } + }; +}; +assertEq(eval(...itr), 11); +function* gen() { + yield "a + b"; +} +assertEq(eval(...gen()), 11); + +let c = ["C"], d = "D"; +assertEq(eval(...c=["c[0] + d"]), "c[0] + dD"); + +// 12.2.4.1.2 Runtime Semantics: ArrayAccumulation +// If Type(spreadObj) is not Object, then throw a TypeError exception. +assertThrowsInstanceOf(() => eval("a + b", ...null), TypeError); +assertThrowsInstanceOf(() => eval("a + b", ...undefined), TypeError); diff --git a/js/src/jit-test/tests/basic/spread-call-evaluation-order.js b/js/src/jit-test/tests/basic/spread-call-evaluation-order.js new file mode 100644 index 0000000000..2c2f53953c --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-evaluation-order.js @@ -0,0 +1,13 @@ +load(libdir + "eqArrayHelper.js"); + +var check = []; +function t(token) { + check.push(token); + return token; +} +let f = (...x) => x; +f(3, ...[t(1)], ...[t(2), t(3)], 34, 42, ...[t(4)]); +assertEqArray(check, [1, 2, 3, 4]); + +var arr = [1, 2, 3]; +assertEqArray(f(...arr, arr.pop()), [1, 2, 3, 3]); diff --git a/js/src/jit-test/tests/basic/spread-call-funapply.js b/js/src/jit-test/tests/basic/spread-call-funapply.js new file mode 100644 index 0000000000..a285d4e827 --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-funapply.js @@ -0,0 +1,88 @@ +load(libdir + "asserts.js"); +load(libdir + "eqArrayHelper.js"); +load(libdir + "iteration.js"); + +function checkCommon(f) { + assertEqArray(f.apply(null, ...[[1, 2, 3]]), [1, 2, 3]); + assertEqArray(f.apply(...[null], [1, 2, 3]), [1, 2, 3]); + assertEqArray(f.apply(...[null], ...[[1, 2, 3]]), [1, 2, 3]); + assertEqArray(f.apply(...[null, [1, 2, 3]]), [1, 2, 3]); + + // other iterable objects + assertEqArray(f.apply(...new Set([null, [1, 2, 3]])), [1, 2, 3]); + assertEqArray(f.apply(...[null, [1, 2, 3]][Symbol.iterator]()), [1, 2, 3]); + let itr = {}; + itr[Symbol.iterator] = function() { + return { + i: 0, + next: function() { + this.i++; + if (this.i == 1) + return { value: null, done: false }; + else if (this.i == 2) + return { value: [1, 2, 3], done: false }; + else + return { value: undefined, done: true }; + } + }; + }; + assertEqArray(f.apply(...itr), [1, 2, 3]); + function* gen() { + yield null; + yield [1, 2, 3]; + } + assertEqArray(f.apply(...gen()), [1, 2, 3]); + + let a; + assertEqArray(f.apply(null, ...a=[[1, 2, 3]]), [1, 2, 3]); + + // 12.2.4.1.2 Runtime Semantics: ArrayAccumulation + // If Type(spreadObj) is not Object, then throw a TypeError exception. + assertThrowsInstanceOf(() => f.apply(null, ...null, [1, 2, 3]), TypeError); + assertThrowsInstanceOf(() => f.apply(null, ...undefined, [1, 2, 3]), TypeError); +} + +function checkNormal(f) { + checkCommon(f); + + assertEqArray(f.apply(null, ...[[]]), [undefined, undefined, undefined]); + assertEqArray(f.apply(null, ...[[1]]), [1, undefined, undefined]); + assertEqArray(f.apply(null, ...[[1, 2]]), [1, 2, undefined]); + assertEqArray(f.apply(null, ...[[1, 2, 3, 4]]), [1, 2, 3]); + + assertEqArray(f.apply(null, ...[[undefined]]), [undefined, undefined, undefined]); +} + +checkNormal(function(a, b, c) { return [a, b, c]; }); +checkNormal((a, b, c) => [a, b, c]); + +function checkDefault(f) { + checkCommon(f); + + assertEqArray(f.apply(null, ...[[]]), [-1, -2, -3]); + assertEqArray(f.apply(null, ...[[1]]), [1, -2, -3]); + assertEqArray(f.apply(null, ...[[1, 2]]), [1, 2, -3]); + assertEqArray(f.apply(null, ...[[1, 2, 3, 4]]), [1, 2, 3]); + + assertEqArray(f.apply(null, ...[[undefined]]), [-1, -2, -3]); +} + +checkDefault(function(a = -1, b = -2, c = -3) { return [a, b, c]; }); +checkDefault((a = -1, b = -2, c = -3) => [a, b, c]); + +function checkRest(f) { + checkCommon(f); + + assertEqArray(f.apply(null, ...[[]]), []); + assertEqArray(f.apply(null, ...[[1]]), [1]); + assertEqArray(f.apply(null, ...[[1, 2]]), [1, 2]); + assertEqArray(f.apply(null, ...[[1, 2, 3, 4]]), [1, 2, 3, 4]); + + assertEqArray(f.apply(null, ...[[undefined]]), [undefined]); + + // other iterable objects + assertEqArray(f.apply(null, ...new Map([[["a", "A"], ["b", "B"]]])).map(([k, v]) => k + v), ["aA", "bB"]); +} + +checkRest(function(...x) { return x; }); +checkRest((...x) => x); diff --git a/js/src/jit-test/tests/basic/spread-call-funcall.js b/js/src/jit-test/tests/basic/spread-call-funcall.js new file mode 100644 index 0000000000..97edfb6599 --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-funcall.js @@ -0,0 +1,11 @@ +load(libdir + "eqArrayHelper.js"); + +function check(f) { + assertEqArray(f.call(...[null], 1, 2, 3), [1, 2, 3]); + assertEqArray(f.call(...[null], 1, ...[2, 3], 4, ...[5, 6]), [1, 2, 3, 4, 5, 6]); + assertEqArray(f.call(...[null, 1], ...[2, 3], 4, ...[5, 6]), [1, 2, 3, 4, 5, 6]); + assertEqArray(f.call(...[null, 1, ...[2, 3], 4, ...[5, 6]]), [1, 2, 3, 4, 5, 6]); +} + +check(function(...x) { return x; }); +check((...x) => x); diff --git a/js/src/jit-test/tests/basic/spread-call-invalid-syntax.js b/js/src/jit-test/tests/basic/spread-call-invalid-syntax.js new file mode 100644 index 0000000000..c3288736d4 --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-invalid-syntax.js @@ -0,0 +1,15 @@ +load(libdir + "asserts.js"); + +var offenders = [ + "f(1 ... n)", + "f(...x for (x in y))", + "f(...)", + "f(...,)", + "f(... ...[])", + "f(x, ...)", + "f(...x, x for (x in y))", + "f(x for (x in y), ...x)" +]; +for (var sample of offenders) { + assertThrowsInstanceOf(function() { eval(sample); }, SyntaxError); +} diff --git a/js/src/jit-test/tests/basic/spread-call-length.js b/js/src/jit-test/tests/basic/spread-call-length.js new file mode 100644 index 0000000000..1d84d046d8 --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-length.js @@ -0,0 +1,52 @@ +load(libdir + 'iteration.js'); + +let makeCall = farg => Function("f", "arg", "return f(" + farg + ");"); +let makeFunCall = farg => Function("f", "arg", "return f.call(null, " + farg + ");"); +let makeNew = farg => Function("f", "arg", "return new f(" + farg + ").length;"); + +function checkLength(f, makeFn) { + assertEq(makeFn("...[1, 2, 3]")(f), 3); + assertEq(makeFn("1, ...[2], 3")(f), 3); + assertEq(makeFn("1, ...[2], ...[3]")(f), 3); + assertEq(makeFn("1, ...[2, 3]")(f), 3); + assertEq(makeFn("1, ...[], 2, 3")(f), 3); + + assertEq(makeFn("...[1]")(f), 1); + assertEq(makeFn("...[1, 2]")(f), 2); + assertEq(makeFn("...[1, 2, 3, 4]")(f), 4); + assertEq(makeFn("1, ...[2, 3, 4], 5")(f), 5); + + assertEq(makeFn("...[undefined]")(f), 1); + + // other iterable objects + assertEq(makeFn("...arg")(f, new Int32Array([1, 2, 3])), 3); + assertEq(makeFn("...arg")(f, "abc"), 3); + assertEq(makeFn("...arg")(f, [1, 2, 3][Symbol.iterator]()), 3); + assertEq(makeFn("...arg")(f, new Set([1, 2, 3])), 3); + assertEq(makeFn("...arg")(f, new Map([["a", "A"], ["b", "B"], ["c", "C"]])), 3); + let itr = {}; + itr[Symbol.iterator] = function() { + return { + i: 1, + next: function() { + if (this.i < 4) + return { value: this.i++, done: false }; + else + return { value: undefined, done: true }; + } + }; + } + assertEq(makeFn("...arg")(f, itr), 3); + function* gen() { + for (let i = 1; i < 4; i ++) + yield i; + } + assertEq(makeFn("...arg")(f, gen()), 3); +} + +checkLength(function(x) { return arguments.length; }, makeCall); +checkLength(function(x) { return arguments.length; }, makeFunCall); +function lengthClass(x) { + this.length = arguments.length; +} +checkLength(lengthClass, makeNew); diff --git a/js/src/jit-test/tests/basic/spread-call-maxarg.js b/js/src/jit-test/tests/basic/spread-call-maxarg.js new file mode 100644 index 0000000000..5ba6eef558 --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-maxarg.js @@ -0,0 +1,71 @@ +// FIXME: ASAN and debug builds run this too slowly for now. +if (!getBuildConfiguration("debug") && !getBuildConfiguration("asan")) { + let longArray = []; + longArray.length = getMaxArgs() + 1; + let shortArray = []; + let a; + + let f = function() { + }; + + // Call_Scripted + // Optimized stub is used after some calls. + a = shortArray; + for (let i = 0; i < 4; i++) { + if (i == 3) { + a = longArray; + } + try { + f(...a); + } catch (e) { + assertEq(e.message, "too many function arguments"); + } + } + + // Call_Scripted (constructing) + a = shortArray; + for (let i = 0; i < 4; i++) { + if (i == 3) { + a = longArray; + } + try { + new f(...a); + } catch (e) { + assertEq(e.message, "too many constructor arguments"); + } + } + + // Call_Native + a = shortArray; + for (let i = 0; i < 4; i++) { + if (i == 3) { + a = longArray; + } + try { + Math.max(...a); + } catch (e) { + assertEq(e.message, "too many function arguments"); + } + } + + // Call_Native (constructing) + a = shortArray; + for (let i = 0; i < 4; i++) { + if (i == 3) { + a = longArray; + } + try { + new Date(...a); + } catch (e) { + assertEq(e.message, "too many constructor arguments"); + } + } + + // No optimized stub for eval. + a = longArray; + try { + eval(...a); + } catch (e) { + assertEq(e.message, "too many function arguments"); + } +} diff --git a/js/src/jit-test/tests/basic/spread-call-near-maxarg.js b/js/src/jit-test/tests/basic/spread-call-near-maxarg.js new file mode 100644 index 0000000000..0d2711c4c9 --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-near-maxarg.js @@ -0,0 +1,71 @@ +// FIXME: ASAN and debug builds run this too slowly for now. +if (!getBuildConfiguration("debug") && !getBuildConfiguration("asan")) { + let longArray = []; + longArray.length = getMaxArgs() - 1; + let shortArray = []; + let a; + + let f = function() { + }; + + // Call_Scripted + // Optimized stub is used after some calls. + a = shortArray; + for (let i = 0; i < 4; i++) { + if (i == 3) { + a = longArray; + } + try { + f(...a); + } catch (e) { + assertEq(e.message, "too much recursion"); + } + } + + // Call_Scripted (constructing) + a = shortArray; + for (let i = 0; i < 4; i++) { + if (i == 3) { + a = longArray; + } + try { + new f(...a); + } catch (e) { + assertEq(e.message, "too much recursion"); + } + } + + // Call_Native + a = shortArray; + for (let i = 0; i < 4; i++) { + if (i == 3) { + a = longArray; + } + try { + Math.max(...a); + } catch (e) { + assertEq(e.message, "too much recursion"); + } + } + + // Call_Native (constructing) + a = shortArray; + for (let i = 0; i < 4; i++) { + if (i == 3) { + a = longArray; + } + try { + new Date(...a); + } catch (e) { + assertEq(e.message, "too much recursion"); + } + } + + // No optimized stub for eval. + a = longArray; + try { + eval(...a); + } catch (e) { + assertEq(e.message, "too much recursion"); + } +} diff --git a/js/src/jit-test/tests/basic/spread-call-new.js b/js/src/jit-test/tests/basic/spread-call-new.js new file mode 100644 index 0000000000..dd26ff958a --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-new.js @@ -0,0 +1,9 @@ +load(libdir + "eqArrayHelper.js"); + +function g(a, b, c) { + this.value = [a, b, c]; + assertEq(Object.getPrototypeOf(this), g.prototype); + assertEq(arguments.callee, g); +} + +assertEqArray(new g(...[1, 2, 3]).value, [1, 2, 3]); diff --git a/js/src/jit-test/tests/basic/spread-call-not-iterable.js b/js/src/jit-test/tests/basic/spread-call-not-iterable.js new file mode 100644 index 0000000000..969d99bccf --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-not-iterable.js @@ -0,0 +1,28 @@ +load(libdir + "asserts.js"); +load(libdir + "iteration.js"); + +assertThrowsInstanceOf(() => Math.sin(...true), TypeError); +assertThrowsInstanceOf(() => Math.sin(...false), TypeError); +assertThrowsInstanceOf(() => Math.sin(...new Date()), TypeError); +assertThrowsInstanceOf(() => Math.sin(...Function("")), TypeError); +assertThrowsInstanceOf(() => Math.sin(...function () {}), TypeError); +assertThrowsInstanceOf(() => Math.sin(...(x => x)), TypeError); +assertThrowsInstanceOf(() => Math.sin(...1), TypeError); +assertThrowsInstanceOf(() => Math.sin(...{}), TypeError); +var foo = {} + +foo[Symbol.iterator] = 10; +assertThrowsInstanceOf(() => Math.sin(...foo), TypeError); + +foo[Symbol.iterator] = function() { return undefined; }; +assertThrowsInstanceOf(() => Math.sin(...foo), TypeError); + +foo[Symbol.iterator] = function() { return this; }; +assertThrowsInstanceOf(() => Math.sin(...foo), TypeError); + +foo[Symbol.iterator] = function() { return this; }; +foo.next = function() { throw 10; }; +assertThrowsValue(() => Math.sin(...foo), 10); + +assertThrowsInstanceOf(() => Math.sin(.../a/), TypeError); +assertThrowsInstanceOf(() => Math.sin(...new Error()), TypeError); diff --git a/js/src/jit-test/tests/basic/spread-call-optimized.js b/js/src/jit-test/tests/basic/spread-call-optimized.js new file mode 100644 index 0000000000..afb1368f13 --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-optimized.js @@ -0,0 +1,26 @@ +// Call_Scripted +let f = function(a, b, c, d, e) { + return a * 10000 + b * 1000 + c * 100 + d * 10 + e; +}; +for (let i = 0; i < 4; i++) { + assertEq(f(...[1, 2, 3, 4, 5]), 12345); +} + +// Call_Scripted (constructing) +let A = function(a, b, c, d, e) { + this.v = a * 10000 + b * 1000 + c * 100 + d * 10 + e; +}; +for (let i = 0; i < 4; i++) { + assertEq(new A(...[1, 2, 3, 4, 5]).v, 12345); +} + +// Call_Native +for (let i = 0; i < 4; i++) { + assertEq(Math.max(...[1, 2, 3, 4, 5]), 5); +} + +// Call_Native (constructing) +for (let i = 0; i < 4; i++) { + assertEq(new Date(...[2014, 4, 28, 8, 16, 1]).getTime(), + new Date(2014, 4, 28, 8, 16, 1).getTime()); +} diff --git a/js/src/jit-test/tests/basic/spread-call-recursion.js b/js/src/jit-test/tests/basic/spread-call-recursion.js new file mode 100644 index 0000000000..5d7caa341a --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-recursion.js @@ -0,0 +1,18 @@ +let a = []; +a.length = 30; + +function check(f) { + try { + f(); + } catch (e) { + assertEq(e.message, "too much recursion"); + } +} + +let f = function() { return f(...a) + 1; }; +let g = () => g(...a) + 1; +let h = function() { return new h(...a) + 1; }; + +check(f); +check(g); +check(h); diff --git a/js/src/jit-test/tests/basic/spread-call-rest-lookup.js b/js/src/jit-test/tests/basic/spread-call-rest-lookup.js new file mode 100644 index 0000000000..d57d65e48b --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-rest-lookup.js @@ -0,0 +1,14 @@ +var count = 0; +var scope = { + get args() { + count++; + return ""; + } +}; + +with (scope) { + [].push(...args); +} + +// Ensure |args| is only looked up once. +assertEq(count, 1); diff --git a/js/src/jit-test/tests/basic/spread-call-rest.js b/js/src/jit-test/tests/basic/spread-call-rest.js new file mode 100644 index 0000000000..6907ed34ba --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-rest.js @@ -0,0 +1,73 @@ +// bug 1235092 +// Optimize spread call with rest parameter. + +load(libdir + "asserts.js"); + +function makeArray(...args) { + return args; +} + +// Optimizable Case. +function test(...args) { + return makeArray(...args); +} +assertDeepEq(test(1, 2, 3), [1, 2, 3]); + +// Not optimizable case 1: the array has hole. +function hole1(...args) { + args[4] = 5; + return makeArray(...args); +} +assertDeepEq(hole1(1, 2, 3), [1, 2, 3, undefined, 5]); + +function hole2(...args) { + args.length = 5; + return makeArray(...args); +} +assertDeepEq(hole2(1, 2, 3), [1, 2, 3, undefined, undefined]); + +function hole3(...args) { + delete args[1]; + return makeArray(...args); +} +assertDeepEq(hole3(1, 2, 3), [1, undefined, 3]); + +// Not optimizable case 2: array[@@iterator] is modified. +function modifiedIterator(...args) { + args[Symbol.iterator] = function*() { + for (let i = 0; i < this.length; i++) + yield this[i] * 10; + }; + return makeArray(...args); +} +assertDeepEq(modifiedIterator(1, 2, 3), [10, 20, 30]); + +// Not optimizable case 3: the array's prototype is modified. +function modifiedProto(...args) { + args.__proto__ = { + __proto__: Array.prototype, + *[Symbol.iterator]() { + for (let i = 0; i < this.length; i++) + yield this[i] * 10; + } + }; + return makeArray(...args); +} +assertDeepEq(modifiedProto(1, 2, 3), [10, 20, 30]); + +// Not optimizable case 4: Array.prototype[@@iterator] is modified. +let ArrayValues = Array.prototype[Symbol.iterator]; +Array.prototype[Symbol.iterator] = function*() { + for (let i = 0; i < this.length; i++) + yield this[i] * 10; +}; +assertDeepEq(test(1, 2, 3), [10, 20, 30]); +Array.prototype[Symbol.iterator] = ArrayValues; + +// Not optimizable case 5: %ArrayIteratorPrototype%.next is modified. +let ArrayIteratorPrototype = Object.getPrototypeOf(Array.prototype[Symbol.iterator]()); +let i = 1; +ArrayIteratorPrototype.next = function() { + return { done: i % 4 == 0, value: 10 * i++ }; +}; +assertDeepEq(test(1, 2, 3), [10, 20, 30]); diff --git a/js/src/jit-test/tests/basic/spread-call-setcall.js b/js/src/jit-test/tests/basic/spread-call-setcall.js new file mode 100644 index 0000000000..5a1100b8e9 --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-setcall.js @@ -0,0 +1,29 @@ +load(libdir + "asserts.js"); + +function g() { +} + +let a = { + g: function() { + } +}; + +function check(expr) { + assertThrowsInstanceOf(Function(expr), ReferenceError); +} +function checkDestructuring(expr) { + assertThrowsInstanceOf(() => Function(expr), SyntaxError); +} + +check("g(...[]) = 1"); +check("a.g(...[]) = 1"); +check("eval(...['1']) = 1"); +check("g(...[]) ++"); +check("a.g(...[]) ++"); +check("eval(...['1']) ++"); +checkDestructuring("[g(...[])] = []"); +checkDestructuring("[a.g(...[])] = []"); +checkDestructuring("[eval(...['1'])] = []"); +checkDestructuring("({y: g(...[])} = 1)"); +checkDestructuring("({y: a.g(...[])} = 1)"); +checkDestructuring("({y: eval(...['1'])} = 1)"); diff --git a/js/src/jit-test/tests/basic/spread-call-this-strict.js b/js/src/jit-test/tests/basic/spread-call-this-strict.js new file mode 100644 index 0000000000..3c88b11176 --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-this-strict.js @@ -0,0 +1,105 @@ +"use strict"; + +let global = this; +let p = {}; +let q = {}; + +let g1 = function() { + assertEq(this, undefined); +}; +g1(...[]); + +let g2 = x => { + assertEq(this, global); +}; +g2(...[]); + +let g3 = function() { + assertEq(this, p); +}; +g3.apply(p, ...[]); +g3.call(p, ...[]); + +g2.apply(p, ...[]); +g2.call(p, ...[]); + +let o = { + f1: function() { + assertEq(this, o); + + let g1 = function() { + assertEq(this, undefined); + }; + g1(...[]); + + let g2 = x => { + assertEq(this, o); + }; + g2(...[]); + + let g3 = function() { + assertEq(this, q); + }; + g3.apply(q, ...[]); + g3.call(q, ...[]); + + let g4 = x => { + assertEq(this, o); + }; + g4.apply(q, ...[]); + g4.call(q, ...[]); + }, + f2: x => { + assertEq(this, global); + let g1 = function() { + assertEq(this, undefined); + }; + g1(...[]); + + let g2 = x => { + assertEq(this, global); + }; + g2(...[]); + + let g3 = function() { + assertEq(this, q); + }; + g3.apply(q, ...[]); + g3.call(q, ...[]); + + let g4 = x => { + assertEq(this, global); + }; + g4.apply(q, ...[]); + g4.call(q, ...[]); + }, + f3: function() { + assertEq(this, p); + + let g1 = function() { + assertEq(this, undefined); + }; + g1(...[]); + + let g2 = x => { + assertEq(this, p); + }; + g2(...[]); + + let g3 = function() { + assertEq(this, q); + }; + g3.apply(q, ...[]); + g3.call(q, ...[]); + + let g4 = x => { + assertEq(this, p); + }; + g4.apply(q, ...[]); + g4.call(q, ...[]); + } +}; +o.f1(...[]); +o.f2(...[]); +o.f3.apply(p, ...[]); +o.f2.apply(p, ...[]); diff --git a/js/src/jit-test/tests/basic/spread-call-this.js b/js/src/jit-test/tests/basic/spread-call-this.js new file mode 100644 index 0000000000..7dac8ca62c --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call-this.js @@ -0,0 +1,123 @@ +let global = this; +let p = {}; +let q = {}; + +let g1 = function() { + assertEq(this, global); + assertEq(arguments.callee, g1); +}; +g1(...[]); + +let g2 = x => { + assertEq(this, global); + // arguments.callee is unbound function object, and following assertion fails. + // see Bug 889158 + //assertEq(arguments.callee, g2); +}; +g2(...[]); + +let g3 = function() { + assertEq(this, p); + assertEq(arguments.callee, g3); +}; +g3.apply(p, ...[]); +g3.call(p, ...[]); + +g2.apply(p, ...[]); +g2.call(p, ...[]); + +let o = { + f1: function() { + assertEq(this, o); + assertEq(arguments.callee, o.f1); + + let g1 = function() { + assertEq(this, global); + assertEq(arguments.callee, g1); + }; + g1(...[]); + + let g2 = x => { + assertEq(this, o); + //assertEq(arguments.callee, g2); + }; + g2(...[]); + + let g3 = function() { + assertEq(this, q); + assertEq(arguments.callee, g3); + }; + g3.apply(q, ...[]); + g3.call(q, ...[]); + + let g4 = x => { + assertEq(this, o); + //assertEq(arguments.callee, g4); + }; + g4.apply(q, ...[]); + g4.call(q, ...[]); + }, + f2: x => { + assertEq(this, global); + //assertEq(arguments.callee, o.f2); + let g1 = function() { + assertEq(this, global); + assertEq(arguments.callee, g1); + }; + g1(...[]); + + let g2 = x => { + assertEq(this, global); + //assertEq(arguments.callee, g2); + }; + g2(...[]); + + let g3 = function() { + assertEq(this, q); + assertEq(arguments.callee, g3); + }; + g3.apply(q, ...[]); + g3.call(q, ...[]); + + let g4 = x => { + assertEq(this, global); + //assertEq(arguments.callee, g4); + }; + g4.apply(q, ...[]); + g4.call(q, ...[]); + }, + f3: function() { + assertEq(this, p); + assertEq(arguments.callee, o.f3); + + let g1 = function() { + assertEq(this, global); + assertEq(arguments.callee, g1); + }; + g1(...[]); + + let g2 = x => { + assertEq(this, p); + //assertEq(arguments.callee, g2); + }; + g2(...[]); + + let g3 = function() { + assertEq(this, q); + assertEq(arguments.callee, g3); + }; + g3.apply(q, ...[]); + g3.call(q, ...[]); + + let g4 = x => { + assertEq(this, p); + //assertEq(arguments.callee, g4); + }; + g4.apply(q, ...[]); + g4.call(q, ...[]); + } +}; +o.f1(...[]); +o.f2(...[]); +o.f3.apply(p, ...[]); +o.f2.apply(p, ...[]); diff --git a/js/src/jit-test/tests/basic/spread-call.js b/js/src/jit-test/tests/basic/spread-call.js new file mode 100644 index 0000000000..6604430733 --- /dev/null +++ b/js/src/jit-test/tests/basic/spread-call.js @@ -0,0 +1,110 @@ +load(libdir + "asserts.js"); +load(libdir + "eqArrayHelper.js"); +load(libdir + "iteration.js"); + +let makeCall = farg => Function("f", "arg", "return f(" + farg + ");"); +let makeFunCall = farg => Function("f", "arg", "return f.call(null, " + farg + ");"); +let makeNew = farg => Function("f", "arg", "return new f(" + farg + ").value;"); + +function checkCommon(f, makeFn) { + assertEqArray(makeFn("...[1, 2, 3]")(f), [1, 2, 3]); + assertEqArray(makeFn("1, ...[2], 3")(f), [1, 2, 3]); + assertEqArray(makeFn("1, ...[2], ...[3]")(f), [1, 2, 3]); + assertEqArray(makeFn("1, ...[2, 3]")(f), [1, 2, 3]); + assertEqArray(makeFn("1, ...[], 2, 3")(f), [1, 2, 3]); + + // other iterable objects + assertEqArray(makeFn("...arg")(f, new Int32Array([1, 2, 3])), [1, 2, 3]); + assertEqArray(makeFn("...arg")(f, "abc"), ["a", "b", "c"]); + assertEqArray(makeFn("...arg")(f, [1, 2, 3][Symbol.iterator]()), [1, 2, 3]); + assertEqArray(makeFn("...arg")(f, new Set([1, 2, 3])), [1, 2, 3]); + assertEqArray(makeFn("...arg")(f, new Map([["a", "A"], ["b", "B"], ["c", "C"]])).map(([k, v]) => k + v), ["aA", "bB", "cC"]); + let itr = {}; + itr[Symbol.iterator] = function() { + return { + i: 1, + next: function() { + if (this.i < 4) + return { value: this.i++, done: false }; + else + return { value: undefined, done: true }; + } + }; + }; + assertEqArray(makeFn("...arg")(f, itr), [1, 2, 3]); + function* gen() { + for (let i = 1; i < 4; i ++) + yield i; + } + assertEqArray(makeFn("...arg")(f, gen()), [1, 2, 3]); + + assertEqArray(makeFn("...arg=[1, 2, 3]")(f), [1, 2, 3]); + + // 12.2.4.1.2 Runtime Semantics: ArrayAccumulation + // If Type(spreadObj) is not Object, then throw a TypeError exception. + assertThrowsInstanceOf(makeFn("1, ...null, 2, 3"), TypeError); + assertThrowsInstanceOf(makeFn("1, ...undefined, 2, 3"), TypeError); +} + +function checkNormal(f, makeFn) { + checkCommon(f, makeFn); + + assertEqArray(makeFn("...[]")(f), [undefined, undefined, undefined]); + assertEqArray(makeFn("...[1]")(f), [1, undefined, undefined]); + assertEqArray(makeFn("...[1, 2]")(f), [1, 2, undefined]); + assertEqArray(makeFn("...[1, 2, 3, 4]")(f), [1, 2, 3]); + + assertEqArray(makeFn("...[undefined]")(f), [undefined, undefined, undefined]); +} + +checkNormal(function(a, b, c) { return [a, b, c]; }, makeCall); +checkNormal(function(a, b, c) { return [a, b, c]; }, makeFunCall); +checkNormal((a, b, c) => [a, b, c], makeCall); +checkNormal((a, b, c) => [a, b, c], makeFunCall); +function normalClass(a, b, c) { + this.value = [a, b, c]; + assertEq(Object.getPrototypeOf(this), normalClass.prototype); +} +checkNormal(normalClass, makeNew); + +function checkDefault(f, makeFn) { + checkCommon(f, makeFn); + + assertEqArray(makeFn("...[]")(f), [-1, -2, -3]); + assertEqArray(makeFn("...[1]")(f), [1, -2, -3]); + assertEqArray(makeFn("...[1, 2]")(f), [1, 2, -3]); + assertEqArray(makeFn("...[1, 2, 3, 4]")(f), [1, 2, 3]); + + assertEqArray(makeFn("...[undefined]")(f), [-1, -2, -3]); +} + +checkDefault(function(a = -1, b = -2, c = -3) { return [a, b, c]; }, makeCall); +checkDefault(function(a = -1, b = -2, c = -3) { return [a, b, c]; }, makeFunCall); +checkDefault((a = -1, b = -2, c = -3) => [a, b, c], makeCall); +checkDefault((a = -1, b = -2, c = -3) => [a, b, c], makeFunCall); +function defaultClass(a = -1, b = -2, c = -3) { + this.value = [a, b, c]; + assertEq(Object.getPrototypeOf(this), defaultClass.prototype); +} +checkDefault(defaultClass, makeNew); + +function checkRest(f, makeFn) { + checkCommon(f, makeFn); + + assertEqArray(makeFn("...[]")(f), []); + assertEqArray(makeFn("1, ...[2, 3, 4], 5")(f), [1, 2, 3, 4, 5]); + assertEqArray(makeFn("1, ...[], 2")(f), [1, 2]); + assertEqArray(makeFn("1, ...[2, 3], 4, ...[5, 6]")(f), [1, 2, 3, 4, 5, 6]); + + assertEqArray(makeFn("...[undefined]")(f), [undefined]); +} + +checkRest(function(...x) { return x; }, makeCall); +checkRest(function(...x) { return x; }, makeFunCall); +checkRest((...x) => x, makeCall); +checkRest((...x) => x, makeFunCall); +function restClass(...x) { + this.value = x; + assertEq(Object.getPrototypeOf(this), restClass.prototype); +} +checkRest(restClass, makeNew); diff --git a/js/src/jit-test/tests/basic/statement-after-return.js b/js/src/jit-test/tests/basic/statement-after-return.js new file mode 100644 index 0000000000..2a49c74577 --- /dev/null +++ b/js/src/jit-test/tests/basic/statement-after-return.js @@ -0,0 +1,496 @@ +// Warning should be shown for unreachable statement after return (bug 1151931). + +function testWarn(code, lineNumber, columnNumber) { + enableLastWarning(); + eval(code); + var warning = getLastWarning(); + assertEq(warning !== null, true, "warning should be caught for " + code); + assertEq(warning.name, "Warning"); + assertEq(warning.lineNumber, lineNumber); + assertEq(warning.columnNumber, columnNumber); + + clearLastWarning(); + Reflect.parse(code); + warning = getLastWarning(); + assertEq(warning !== null, true, "warning should be caught for " + code); + assertEq(warning.name, "Warning"); + // Warning generated by Reflect.parse has line/column number for Reflect.parse + // itself, not parsed code. + disableLastWarning(); +} + +function testPass(code) { + enableLastWarning(); + eval(code); + var warning = getLastWarning(); + assertEq(warning, null, "warning should not be caught for " + code); + + clearLastWarning(); + Reflect.parse(code); + warning = getLastWarning(); + assertEq(warning, null, "warning should not be caught for " + code); + disableLastWarning(); +} + +testPass(` +function f() { + return ( + 1 + 2 + ); +} +`); + +// unary expression +testWarn(` +function f() { + var i = 0; + return + ++i; +} +`, 5, 5); +testWarn(` +function f() { + var i = 0; + return + --i; +} +`, 5, 5); + +// array +testWarn(` +function f() { + return + [1, 2, 3]; +} +`, 4, 5); + +// block (object) +testWarn(` +function f() { + return + {x: 10}; +} +`, 4, 5); +testWarn(` +function f() { + return + { + method() + { + f(); + } + }; +} +`, 4, 3); + +// expression in paren +testWarn(` +function f() { + return + (1 + 2); +} +`, 4, 5); + +// name +testWarn(` +function f() { + return + f; +} +`, 4, 5); + +// binary expression +testWarn(` +function f() { + return + 1 + 2; +} +`, 4, 5); +testWarn(` +function f() { + return + .1 + .2; +} +`, 4, 5); + +// string +testWarn(` +function f() { + return + "foo"; +} +`, 4, 5); +testWarn(` +function f() { + return + "use struct"; +} +`, 4, 5); +testWarn(` +function f() { + return + 'foo'; +} +`, 4, 5); + +// template string +testWarn(` +function f() { + return + \`foo\${1 + 2}\`; +} +`, 4, 5); +testWarn(` +function f() { + return + \`foo\`; +} +`, 4, 5); + +// RegExp +testWarn(` +function f() { + return + /foo/; +} +`, 4, 5); + +// boolean +testWarn(` +function f() { + return + true; +} +`, 4, 5); +testWarn(` +function f() { + return + false; +} +`, 4, 5); + +// null +testWarn(` +function f() { + return + null; +} +`, 4, 5); + +// this +testWarn(` +function f() { + return + this; +} +`, 4, 5); + +// new +testWarn(` +function f() { + return + new Array(); +} +`, 4, 5); + +// delete +testWarn(` +function f() { + var a = {x: 10}; + return + delete a.x; +} +`, 5, 5); + +// yield +testWarn(` +function* f() { + return + yield 1; +} +`, 4, 5); + +// class +testWarn(` +function f() { + return + class A { constructor() {} }; +} +`, 4, 5); + +// unary expression +testWarn(` +function f() { + return + +1; +} +`, 4, 5); +testWarn(` +function f() { + return + -1; +} +`, 4, 5); +testWarn(` +function f() { + return + !1; +} +`, 4, 5); +testWarn(` +function f() { + return + ~1; +} +`, 4, 5); + +// eof +testPass(` +var f = new Function("return\\n"); +`); + +// empty statement +testPass(` +function f() { + return; + ; // empty statement +} +`); + +// end of block +testPass(` +function f() { + { + return + } +} +`); + +// function (hosted) +testPass(` +function f() { + g(); + return + function g() {} +} +`); + +// if +testWarn(` +function f() { + return + if (true) + 1 + 2; +} +`, 4, 3); + +// else +testPass(` +function f() { + if (true) + return + else + 1 + 2; +} +`); + +// switch +testWarn(` +function f() { + return + switch (1) { + case 1: + break; + } +} +`, 4, 3); + +// return in switch +testWarn(` +function f() { + switch (1) { + case 1: + return; + 1 + 2; + break; + } +} +`, 6, 7); + +// break in switch +testPass(` +function f() { + switch (1) { + case 1: + return; + break; + } +} +`); + +// case +testPass(` +function f() { + switch (1) { + case 0: + return + case 1: + break; + } +} +`); + +// default +testPass(` +function f() { + switch (1) { + case 0: + return + default: + break; + } +} +`); + +// while +testWarn(` +function f() { + return + while (false) + 1 + 2; +} +`, 4, 3); +testPass(` +function f() { + do + return + while (false); +} +`); + +// do +testWarn(` +function f() { + return + do { + 1 + 2; + } while (false); +} +`, 4, 3); + +// for +testWarn(` +function f() { + return + for (;;) { + break; + } +} +`, 4, 3); + +// break in for +testPass(` +function f() { + for (;;) { + return + break; + } +} +`, 5, 5); + +// continue +testWarn(` +function f() { + for (;;) { + return + continue; + } +} +`, 5, 5); + +// var (hosted) +testPass(` +function f() { + return + var a = 1; +} +`); + +// const +testWarn(` +function f() { + return + const a = 1; +} +`, 4, 3); + +// with +testWarn(` +function f() { + return + with ({}) { + 1; + } +} +`, 4, 3); + +// return +testWarn(` +function f() { + return + return; +} +`, 4, 3); + +// try +testWarn(` +function f() { + return + try { + } catch (e) { + } +} +`, 4, 3); + +// throw +testPass(` +function f() { + return + throw 1; +} +`); + +// debugger +testWarn(` +function f() { + return + debugger; +} +`, 4, 3); + +// let +testWarn(` +function f() { + return + let a = 1; +} +`, 4, 3); + +// skip hoisted + +testWarn(` +function f() { + return + var a = 0; + (1 + 2); +} +`, 5, 3); + +testWarn(` +function f() { + return + function f() {} + var a = 0; + (1 + 2); +} +`, 6, 3); diff --git a/js/src/jit-test/tests/basic/str-atom-cache-extensible.js b/js/src/jit-test/tests/basic/str-atom-cache-extensible.js new file mode 100644 index 0000000000..bee8f13847 --- /dev/null +++ b/js/src/jit-test/tests/basic/str-atom-cache-extensible.js @@ -0,0 +1,15 @@ +// Create an extensible string. +var extensible = "foo".repeat(50); +extensible += "bar"; +extensible.indexOf("X"); + +// Ensure it's in the StringToAtomCache. +var obj = {}; +obj[extensible] = 1; + +// Make it a dependent string. +var other = extensible + "baz"; +other.indexOf("X"); + +// Must still be in the cache. +obj[extensible] = 1; diff --git a/js/src/jit-test/tests/basic/strict-catch-ident-syntax.js b/js/src/jit-test/tests/basic/strict-catch-ident-syntax.js new file mode 100644 index 0000000000..2058e5aa29 --- /dev/null +++ b/js/src/jit-test/tests/basic/strict-catch-ident-syntax.js @@ -0,0 +1,9 @@ +/* Parse correctly. */ + +function assignToClassListStrict(e) { + "use strict"; + try { + e.classList = "foo"; + ok(false, "assigning to classList didn't throw"); + } catch (e) { } +} diff --git a/js/src/jit-test/tests/basic/strict-compare-same-operands.js b/js/src/jit-test/tests/basic/strict-compare-same-operands.js new file mode 100644 index 0000000000..57ca425054 --- /dev/null +++ b/js/src/jit-test/tests/basic/strict-compare-same-operands.js @@ -0,0 +1,49 @@ +function f(l, m) { + var a = NaN; + var b = 13; + var c = "test"; + var d = undefined; + var e = null; + var f = 15.7; + var g = Math.fround(189777.111); + var h = "ABC"; + var i = String.fromCharCode(65, 65, 65); + var j = {}; + var k = Math.fround("".charCodeAt(15)); + + // Special case rigt here: + assertEq(a === a, false); + assertEq(a !== a, true); + assertEq(k === k, false); + assertEq(k !== k, true); + assertEq(l === l, false); + assertEq(l !== l, true); + + assertEq(b === b, true); + assertEq(b !== b, false); + assertEq(c === c, true); + assertEq(c !== c, false); + assertEq(d === d, true); + assertEq(d !== d, false); + assertEq(e === e, true); + assertEq(e !== e, false); + assertEq(f === f, true); + assertEq(f !== f, false); + assertEq(g === g, true); + assertEq(g !== g, false); + assertEq(h === h, true); + assertEq(h !== h, false); + assertEq(i === i, true); + assertEq(i !== i, false); + assertEq(j === j, true); + assertEq(j !== j, false); + assertEq(m === m, true); + assertEq(m !== m, false); +} + +function test() { + for (var i = 0; i < 100; i++) + f("".charCodeAt(15), 42); +} + +test(); diff --git a/js/src/jit-test/tests/basic/strict-eval-loop-error.js b/js/src/jit-test/tests/basic/strict-eval-loop-error.js new file mode 100644 index 0000000000..f09ad44028 --- /dev/null +++ b/js/src/jit-test/tests/basic/strict-eval-loop-error.js @@ -0,0 +1,3 @@ +var COUNT = 9; +eval("'use strict'; for (let j = 0; j < COUNT; j++); try { x; throw new Error(); } catch (e) { if (!(e instanceof ReferenceError)) throw e; }"); +assertEq(typeof j, "undefined"); diff --git a/js/src/jit-test/tests/basic/strictParseIntOctal.js b/js/src/jit-test/tests/basic/strictParseIntOctal.js new file mode 100644 index 0000000000..59412f3179 --- /dev/null +++ b/js/src/jit-test/tests/basic/strictParseIntOctal.js @@ -0,0 +1,16 @@ +"use strict"; + +assertEq(parseInt("08"), 8); +assertEq(parseInt("09"), 9); +assertEq(parseInt("014"), 14); +assertEq(parseInt("0xA"), 10); +assertEq(parseInt("00123"), 123); + +for (var i = 0; i < 5; i++) +{ + assertEq(parseInt("08"), 8); + assertEq(parseInt("09"), 9); + assertEq(parseInt("014"), 14); + assertEq(parseInt("0xA"), 10); + assertEq(parseInt("00123"), 123); +} diff --git a/js/src/jit-test/tests/basic/string-endswith.js b/js/src/jit-test/tests/basic/string-endswith.js new file mode 100644 index 0000000000..6ba5a4f5d3 --- /dev/null +++ b/js/src/jit-test/tests/basic/string-endswith.js @@ -0,0 +1,262 @@ +/* +* Copyright (c) 2013 Mathias Bynens. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +*/ + +function assertThrows(fun, errorType) { + try { + fun(); + assertEq(true, false, "Expected error, but none was thrown"); + } catch (e) { + assertEq(e instanceof errorType, true, "Wrong error type thrown"); + } +} +assertEq(String.prototype.endsWith.length, 1); +assertEq(String.prototype.propertyIsEnumerable('endsWith'), false); + +assertEq('undefined'.endsWith(), true); +assertEq('undefined'.endsWith(undefined), true); +assertEq('undefined'.endsWith(null), false); +assertEq('null'.endsWith(), false); +assertEq('null'.endsWith(undefined), false); +assertEq('null'.endsWith(null), true); + +assertEq('abc'.endsWith(), false); +assertEq('abc'.endsWith(''), true); +assertEq('abc'.endsWith('\0'), false); +assertEq('abc'.endsWith('c'), true); +assertEq('abc'.endsWith('b'), false); +assertEq('abc'.endsWith('a'), false); +assertEq('abc'.endsWith('ab'), false); +assertEq('abc'.endsWith('bc'), true); +assertEq('abc'.endsWith('abc'), true); +assertEq('abc'.endsWith('bcd'), false); +assertEq('abc'.endsWith('abcd'), false); +assertEq('abc'.endsWith('bcde'), false); + +assertEq('abc'.endsWith('', NaN), true); +assertEq('abc'.endsWith('\0', NaN), false); +assertEq('abc'.endsWith('c', NaN), false); +assertEq('abc'.endsWith('b', NaN), false); +assertEq('abc'.endsWith('a', NaN), false); +assertEq('abc'.endsWith('ab', NaN), false); +assertEq('abc'.endsWith('bc', NaN), false); +assertEq('abc'.endsWith('abc', NaN), false); +assertEq('abc'.endsWith('bcd', NaN), false); +assertEq('abc'.endsWith('abcd', NaN), false); +assertEq('abc'.endsWith('bcde', NaN), false); + +assertEq('abc'.endsWith('', false), true); +assertEq('abc'.endsWith('\0', false), false); +assertEq('abc'.endsWith('c', false), false); +assertEq('abc'.endsWith('b', false), false); +assertEq('abc'.endsWith('a', false), false); +assertEq('abc'.endsWith('ab', false), false); +assertEq('abc'.endsWith('bc', false), false); +assertEq('abc'.endsWith('abc', false), false); +assertEq('abc'.endsWith('bcd', false), false); +assertEq('abc'.endsWith('abcd', false), false); +assertEq('abc'.endsWith('bcde', false), false); + +assertEq('abc'.endsWith('', undefined), true); +assertEq('abc'.endsWith('\0', undefined), false); +assertEq('abc'.endsWith('c', undefined), true); +assertEq('abc'.endsWith('b', undefined), false); +assertEq('abc'.endsWith('a', undefined), false); +assertEq('abc'.endsWith('ab', undefined), false); +assertEq('abc'.endsWith('bc', undefined), true); +assertEq('abc'.endsWith('abc', undefined), true); +assertEq('abc'.endsWith('bcd', undefined), false); +assertEq('abc'.endsWith('abcd', undefined), false); +assertEq('abc'.endsWith('bcde', undefined), false); + +assertEq('abc'.endsWith('', null), true); +assertEq('abc'.endsWith('\0', null), false); +assertEq('abc'.endsWith('c', null), false); +assertEq('abc'.endsWith('b', null), false); +assertEq('abc'.endsWith('a', null), false); +assertEq('abc'.endsWith('ab', null), false); +assertEq('abc'.endsWith('bc', null), false); +assertEq('abc'.endsWith('abc', null), false); +assertEq('abc'.endsWith('bcd', null), false); +assertEq('abc'.endsWith('abcd', null), false); +assertEq('abc'.endsWith('bcde', null), false); + +assertEq('abc'.endsWith('', -Infinity), true); +assertEq('abc'.endsWith('\0', -Infinity), false); +assertEq('abc'.endsWith('c', -Infinity), false); +assertEq('abc'.endsWith('b', -Infinity), false); +assertEq('abc'.endsWith('a', -Infinity), false); +assertEq('abc'.endsWith('ab', -Infinity), false); +assertEq('abc'.endsWith('bc', -Infinity), false); +assertEq('abc'.endsWith('abc', -Infinity), false); +assertEq('abc'.endsWith('bcd', -Infinity), false); +assertEq('abc'.endsWith('abcd', -Infinity), false); +assertEq('abc'.endsWith('bcde', -Infinity), false); + +assertEq('abc'.endsWith('', -1), true); +assertEq('abc'.endsWith('\0', -1), false); +assertEq('abc'.endsWith('c', -1), false); +assertEq('abc'.endsWith('b', -1), false); +assertEq('abc'.endsWith('a', -1), false); +assertEq('abc'.endsWith('ab', -1), false); +assertEq('abc'.endsWith('bc', -1), false); +assertEq('abc'.endsWith('abc', -1), false); +assertEq('abc'.endsWith('bcd', -1), false); +assertEq('abc'.endsWith('abcd', -1), false); +assertEq('abc'.endsWith('bcde', -1), false); + +assertEq('abc'.endsWith('', -0), true); +assertEq('abc'.endsWith('\0', -0), false); +assertEq('abc'.endsWith('c', -0), false); +assertEq('abc'.endsWith('b', -0), false); +assertEq('abc'.endsWith('a', -0), false); +assertEq('abc'.endsWith('ab', -0), false); +assertEq('abc'.endsWith('bc', -0), false); +assertEq('abc'.endsWith('abc', -0), false); +assertEq('abc'.endsWith('bcd', -0), false); +assertEq('abc'.endsWith('abcd', -0), false); +assertEq('abc'.endsWith('bcde', -0), false); + +assertEq('abc'.endsWith('', +0), true); +assertEq('abc'.endsWith('\0', +0), false); +assertEq('abc'.endsWith('c', +0), false); +assertEq('abc'.endsWith('b', +0), false); +assertEq('abc'.endsWith('a', +0), false); +assertEq('abc'.endsWith('ab', +0), false); +assertEq('abc'.endsWith('bc', +0), false); +assertEq('abc'.endsWith('abc', +0), false); +assertEq('abc'.endsWith('bcd', +0), false); +assertEq('abc'.endsWith('abcd', +0), false); +assertEq('abc'.endsWith('bcde', +0), false); + +assertEq('abc'.endsWith('', 1), true); +assertEq('abc'.endsWith('\0', 1), false); +assertEq('abc'.endsWith('c', 1), false); +assertEq('abc'.endsWith('b', 1), false); +assertEq('abc'.endsWith('ab', 1), false); +assertEq('abc'.endsWith('bc', 1), false); +assertEq('abc'.endsWith('abc', 1), false); +assertEq('abc'.endsWith('bcd', 1), false); +assertEq('abc'.endsWith('abcd', 1), false); +assertEq('abc'.endsWith('bcde', 1), false); + +assertEq('abc'.endsWith('', 2), true); +assertEq('abc'.endsWith('\0', 2), false); +assertEq('abc'.endsWith('c', 2), false); +assertEq('abc'.endsWith('b', 2), true); +assertEq('abc'.endsWith('ab', 2), true); +assertEq('abc'.endsWith('bc', 2), false); +assertEq('abc'.endsWith('abc', 2), false); +assertEq('abc'.endsWith('bcd', 2), false); +assertEq('abc'.endsWith('abcd', 2), false); +assertEq('abc'.endsWith('bcde', 2), false); + +assertEq('abc'.endsWith('', +Infinity), true); +assertEq('abc'.endsWith('\0', +Infinity), false); +assertEq('abc'.endsWith('c', +Infinity), true); +assertEq('abc'.endsWith('b', +Infinity), false); +assertEq('abc'.endsWith('a', +Infinity), false); +assertEq('abc'.endsWith('ab', +Infinity), false); +assertEq('abc'.endsWith('bc', +Infinity), true); +assertEq('abc'.endsWith('abc', +Infinity), true); +assertEq('abc'.endsWith('bcd', +Infinity), false); +assertEq('abc'.endsWith('abcd', +Infinity), false); +assertEq('abc'.endsWith('bcde', +Infinity), false); + +assertEq('abc'.endsWith('', true), true); +assertEq('abc'.endsWith('\0', true), false); +assertEq('abc'.endsWith('c', true), false); +assertEq('abc'.endsWith('b', true), false); +assertEq('abc'.endsWith('ab', true), false); +assertEq('abc'.endsWith('bc', true), false); +assertEq('abc'.endsWith('abc', true), false); +assertEq('abc'.endsWith('bcd', true), false); +assertEq('abc'.endsWith('abcd', true), false); +assertEq('abc'.endsWith('bcde', true), false); + +assertEq('abc'.endsWith('', 'x'), true); +assertEq('abc'.endsWith('\0', 'x'), false); +assertEq('abc'.endsWith('c', 'x'), false); +assertEq('abc'.endsWith('b', 'x'), false); +assertEq('abc'.endsWith('a', 'x'), false); +assertEq('abc'.endsWith('ab', 'x'), false); +assertEq('abc'.endsWith('bc', 'x'), false); +assertEq('abc'.endsWith('abc', 'x'), false); +assertEq('abc'.endsWith('bcd', 'x'), false); +assertEq('abc'.endsWith('abcd', 'x'), false); +assertEq('abc'.endsWith('bcde', 'x'), false); + +assertEq('[a-z]+(bar)?'.endsWith('(bar)?'), true); +assertThrows(function() { '[a-z]+(bar)?'.endsWith(/(bar)?/); }, TypeError); +assertEq('[a-z]+(bar)?'.endsWith('[a-z]+', 6), true); +assertThrows(function() { '[a-z]+(bar)?'.endsWith(/(bar)?/); }, TypeError); +assertThrows(function() { '[a-z]+/(bar)?/'.endsWith(/(bar)?/); }, TypeError); +var global = newGlobal(); +global.eval('this.re = /(bar)?/'); +assertThrows(function() { '[a-z]+/(bar)?/'.endsWith(global.re); }, TypeError); + +// http://mathiasbynens.be/notes/javascript-unicode#poo-test +var string = 'I\xF1t\xEBrn\xE2ti\xF4n\xE0liz\xE6ti\xF8n\u2603\uD83D\uDCA9'; +assertEq(string.endsWith(''), true); +assertEq(string.endsWith('\xF1t\xEBr'), false); +assertEq(string.endsWith('\xF1t\xEBr', 5), true); +assertEq(string.endsWith('\xE0liz\xE6'), false); +assertEq(string.endsWith('\xE0liz\xE6', 16), true); +assertEq(string.endsWith('\xF8n\u2603\uD83D\uDCA9'), true); +assertEq(string.endsWith('\xF8n\u2603\uD83D\uDCA9', 23), true); +assertEq(string.endsWith('\u2603'), false); +assertEq(string.endsWith('\u2603', 21), true); +assertEq(string.endsWith('\uD83D\uDCA9'), true); +assertEq(string.endsWith('\uD83D\uDCA9', 23), true); + +assertThrows(function() { String.prototype.endsWith.call(undefined); }, TypeError); +assertThrows(function() { String.prototype.endsWith.call(undefined, 'b'); }, TypeError); +assertThrows(function() { String.prototype.endsWith.call(undefined, 'b', 4); }, TypeError); +assertThrows(function() { String.prototype.endsWith.call(null); }, TypeError); +assertThrows(function() { String.prototype.endsWith.call(null, 'b'); }, TypeError); +assertThrows(function() { String.prototype.endsWith.call(null, 'b', 4); }, TypeError); +assertEq(String.prototype.endsWith.call(42, '2'), true); +assertEq(String.prototype.endsWith.call(42, '4'), false); +assertEq(String.prototype.endsWith.call(42, 'b', 4), false); +assertEq(String.prototype.endsWith.call(42, '2', 1), false); +assertEq(String.prototype.endsWith.call(42, '2', 4), true); +assertEq(String.prototype.endsWith.call({ 'toString': function() { return 'abc'; } }, 'b', 0), false); +assertEq(String.prototype.endsWith.call({ 'toString': function() { return 'abc'; } }, 'b', 1), false); +assertEq(String.prototype.endsWith.call({ 'toString': function() { return 'abc'; } }, 'b', 2), true); +assertThrows(function() { String.prototype.endsWith.call({ 'toString': function() { throw RangeError(); } }, /./); }, RangeError); +assertThrows(function() { String.prototype.endsWith.call({ 'toString': function() { return 'abc' } }, /./); }, TypeError); + +assertThrows(function() { String.prototype.endsWith.apply(undefined); }, TypeError); +assertThrows(function() { String.prototype.endsWith.apply(undefined, ['b']); }, TypeError); +assertThrows(function() { String.prototype.endsWith.apply(undefined, ['b', 4]); }, TypeError); +assertThrows(function() { String.prototype.endsWith.apply(null); }, TypeError); +assertThrows(function() { String.prototype.endsWith.apply(null, ['b']); }, TypeError); +assertThrows(function() { String.prototype.endsWith.apply(null, ['b', 4]); }, TypeError); +assertEq(String.prototype.endsWith.apply(42, ['2']), true); +assertEq(String.prototype.endsWith.apply(42, ['4']), false); +assertEq(String.prototype.endsWith.apply(42, ['b', 4]), false); +assertEq(String.prototype.endsWith.apply(42, ['2', 1]), false); +assertEq(String.prototype.endsWith.apply(42, ['2', 4]), true); +assertEq(String.prototype.endsWith.apply({ 'toString': function() { return 'abc'; } }, ['b', 0]), false); +assertEq(String.prototype.endsWith.apply({ 'toString': function() { return 'abc'; } }, ['b', 1]), false); +assertEq(String.prototype.endsWith.apply({ 'toString': function() { return 'abc'; } }, ['b', 2]), true); +assertThrows(function() { String.prototype.endsWith.apply({ 'toString': function() { throw RangeError(); } }, [/./]); }, RangeError); +assertThrows(function() { String.prototype.endsWith.apply({ 'toString': function() { return 'abc' } }, [/./]); }, TypeError); diff --git a/js/src/jit-test/tests/basic/string-includes.js b/js/src/jit-test/tests/basic/string-includes.js new file mode 100644 index 0000000000..f41b0c6d78 --- /dev/null +++ b/js/src/jit-test/tests/basic/string-includes.js @@ -0,0 +1,46 @@ +assertEq("abc".includes("a"), true); +assertEq("abc".includes("b"), true); +assertEq("abc".includes("abc"), true); +assertEq("abc".includes("bc"), true); +assertEq("abc".includes("d"), false); +assertEq("abc".includes("abcd"), false); +assertEq("abc".includes("ac"), false); +assertEq("abc".includes("abc", 0), true); +assertEq("abc".includes("bc", 0), true); +assertEq("abc".includes("de", 0), false); +assertEq("abc".includes("bc", 1), true); +assertEq("abc".includes("c", 1), true); +assertEq("abc".includes("a", 1), false); +assertEq("abc".includes("abc", 1), false); +assertEq("abc".includes("c", 2), true); +assertEq("abc".includes("d", 2), false); +assertEq("abc".includes("dcd", 2), false); +assertEq("abc".includes("a", 42), false); +assertEq("abc".includes("a", Infinity), false); +assertEq("abc".includes("ab", -43), true); +assertEq("abc".includes("cd", -42), false); +assertEq("abc".includes("ab", -Infinity), true); +assertEq("abc".includes("cd", -Infinity), false); +assertEq("abc".includes("ab", NaN), true); +assertEq("abc".includes("cd", NaN), false); +var myobj = {toString : () => "abc", includes : String.prototype.includes}; +assertEq(myobj.includes("abc"), true); +assertEq(myobj.includes("cd"), false); +var gotStr = false, gotPos = false; +myobj = {toString : (function () { + assertEq(gotPos, false); + gotStr = true; + return "xyz"; +}), +includes : String.prototype.includes}; +var idx = {valueOf : (function () { + assertEq(gotStr, true); + gotPos = true; + return 42; +})}; +myobj.includes("elephant", idx); +assertEq(gotPos, true); +assertEq("xyzzy".includes("zy\0", 2), false); +var dots = Array(10000).join('.'); +assertEq(dots.includes("\x01", 10000), false); +assertEq(dots.includes("\0", 10000), false); diff --git a/js/src/jit-test/tests/basic/string-index.js b/js/src/jit-test/tests/basic/string-index.js new file mode 100644 index 0000000000..aee56e4647 --- /dev/null +++ b/js/src/jit-test/tests/basic/string-index.js @@ -0,0 +1,86 @@ +function basic() { + var zero = "0"; + var one = "1"; + var thousand = String(1000); + var max = String(0xffff); + + assertEq(zero, "0"); + assertEq(Number(zero), 0); + assertEq(String(Number(zero)), "0"); + + assertEq(one, "1"); + assertEq(Number(one), 1); + assertEq(String(Number(one)), "1"); + + assertEq(thousand, "1000"); + assertEq(Number(thousand), 1000); + assertEq(String(Number(thousand)), "1000"); + + assertEq(max, "65535"); + assertEq(Number(max), 0xffff); + assertEq(String(Number(max)), "65535"); +} + +function index() { + var zero = "0"; + var trippleZero = "000"; + + var seven = "7"; + var doubleOhSeven = "007"; + + var object = {0: "a", "000": "b"}; + var object2 = {7: "a", "007": "b"}; + + var array = ["a"]; + array[trippleZero] = "b"; + var array2 = [0, 1, 2, 3, 4, 5, 6, "a"]; + array2[doubleOhSeven] = "b"; + + for (var i = 0; i < 30; i++) { + assertEq(object[zero], "a"); + assertEq(object[0], "a"); + assertEq(object[trippleZero], "b"); + + assertEq(object2[seven], "a"); + assertEq(object2[7], "a"); + assertEq(object2[doubleOhSeven], "b"); + + assertEq(array[zero], "a"); + assertEq(array[0], "a"); + assertEq(array[trippleZero], "b"); + + assertEq(array2[seven], "a"); + assertEq(array2[7], "a"); + assertEq(array2[doubleOhSeven], "b"); + } +} + +function forin() { + var array = [0, 1, 2, 3, 4, 5, 6]; + + var i = 0; + for (var name in array) { + assertEq(name, String(i)); + assertEq(Number(name), i); + + assertEq(array[name], i); + assertEq(array.hasOwnProperty(name), true); + + i++; + } +} + +function parse() { + var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1000, 0xffff]; + + for (var number of numbers) { + assertEq(parseInt(String(number)), number); + assertEq(parseInt(String(number), 10), number); + assertEq(parseInt(String(number), 0), number); + } +} + +basic(); +index(); +forin(); +parse(); diff --git a/js/src/jit-test/tests/basic/string-regexp-capture-groups.js b/js/src/jit-test/tests/basic/string-regexp-capture-groups.js new file mode 100644 index 0000000000..0fc1bb8a11 --- /dev/null +++ b/js/src/jit-test/tests/basic/string-regexp-capture-groups.js @@ -0,0 +1,21 @@ +"abcdefg".match(/(x)y(z)/g); +assertEq(RegExp.$1, ""); + +assertEq("abcdef".match(/a(b)cd/g)[0], "abcd"); +assertEq(RegExp.$1, "b"); +assertEq(RegExp.$2, ""); + +"abcdef".match(/(a)b(c)/g); +assertEq(RegExp.$1, "a"); +assertEq(RegExp.$2, "c"); +assertEq(RegExp.$3, ""); + +"abcabdabe".match(/(a)b(.)/g); +assertEq(RegExp.$1, "a"); +assertEq(RegExp.$2, "e"); + +"abcdefg".match(/(x)y(z)/g); +assertEq(RegExp.$1, "a"); //If there's no match, we don't update the statics. + +"abcdefg".match(/(g)/g); +assertEq(RegExp.$1, "g"); diff --git a/js/src/jit-test/tests/basic/string-repeat.js b/js/src/jit-test/tests/basic/string-repeat.js new file mode 100644 index 0000000000..8e9e9ee664 --- /dev/null +++ b/js/src/jit-test/tests/basic/string-repeat.js @@ -0,0 +1,30 @@ +/* Test String.prototype.repeat */
+
+load(libdir + 'asserts.js');
+
+assertEq("abc".repeat(1), "abc");
+assertEq("abc".repeat(2), "abcabc");
+assertEq("abc".repeat(3), "abcabcabc");
+assertEq("a".repeat(10), "aaaaaaaaaa");
+assertEq("abc".repeat(0), "");
+assertEq("abc".repeat(2.9), "abcabc");
+
+var myobj = {toString : () => "abc", repeat : String.prototype.repeat};
+assertEq(myobj.repeat(1), "abc");
+assertEq(myobj.repeat(2), "abcabc");
+
+assertThrowsInstanceOf(function() {
+ "abc".repeat(-1);
+ }, RangeError,
+ "String.prototype.repeat should raise RangeError on negative arguments");
+assertThrowsInstanceOf(function() {
+ "abc".repeat(Number.POSITIVE_INFINITY);
+ }, RangeError,
+ "String.prototype.repeat should raise RangeError on excedding maximum string length");
+assertThrowsInstanceOf(function() {
+ "abc".repeat(1 << 29);
+ }, RangeError,
+ "String.prototype.repeat should raise RangeError on excedding maximum string length");
+
+assertEq("".repeat(5), "");
+assertEq("".repeat(1 << 29), "");
diff --git a/js/src/jit-test/tests/basic/string-startswith.js b/js/src/jit-test/tests/basic/string-startswith.js new file mode 100644 index 0000000000..d788e30e8d --- /dev/null +++ b/js/src/jit-test/tests/basic/string-startswith.js @@ -0,0 +1,243 @@ +/* +* Copyright (c) 2013 Mathias Bynens. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +*/ + +function assertThrows(fun, errorType) { + try { + fun(); + assertEq(true, false, "Expected error, but none was thrown"); + } catch (e) { + assertEq(e instanceof errorType, true, "Wrong error type thrown"); + } +} + +Object.prototype[1] = 2; // try to break `arguments[1]` + +assertEq(String.prototype.startsWith.length, 1); +assertEq(String.prototype.propertyIsEnumerable('startsWith'), false); + +assertEq('undefined'.startsWith(), true); +assertEq('undefined'.startsWith(undefined), true); +assertEq('undefined'.startsWith(null), false); +assertEq('null'.startsWith(), false); +assertEq('null'.startsWith(undefined), false); +assertEq('null'.startsWith(null), true); + +assertEq('abc'.startsWith(), false); +assertEq('abc'.startsWith(''), true); +assertEq('abc'.startsWith('\0'), false); +assertEq('abc'.startsWith('a'), true); +assertEq('abc'.startsWith('b'), false); +assertEq('abc'.startsWith('ab'), true); +assertEq('abc'.startsWith('bc'), false); +assertEq('abc'.startsWith('abc'), true); +assertEq('abc'.startsWith('bcd'), false); +assertEq('abc'.startsWith('abcd'), false); +assertEq('abc'.startsWith('bcde'), false); + +assertEq('abc'.startsWith('', NaN), true); +assertEq('abc'.startsWith('\0', NaN), false); +assertEq('abc'.startsWith('a', NaN), true); +assertEq('abc'.startsWith('b', NaN), false); +assertEq('abc'.startsWith('ab', NaN), true); +assertEq('abc'.startsWith('bc', NaN), false); +assertEq('abc'.startsWith('abc', NaN), true); +assertEq('abc'.startsWith('bcd', NaN), false); +assertEq('abc'.startsWith('abcd', NaN), false); +assertEq('abc'.startsWith('bcde', NaN), false); + +assertEq('abc'.startsWith('', false), true); +assertEq('abc'.startsWith('\0', false), false); +assertEq('abc'.startsWith('a', false), true); +assertEq('abc'.startsWith('b', false), false); +assertEq('abc'.startsWith('ab', false), true); +assertEq('abc'.startsWith('bc', false), false); +assertEq('abc'.startsWith('abc', false), true); +assertEq('abc'.startsWith('bcd', false), false); +assertEq('abc'.startsWith('abcd', false), false); +assertEq('abc'.startsWith('bcde', false), false); + +assertEq('abc'.startsWith('', undefined), true); +assertEq('abc'.startsWith('\0', undefined), false); +assertEq('abc'.startsWith('a', undefined), true); +assertEq('abc'.startsWith('b', undefined), false); +assertEq('abc'.startsWith('ab', undefined), true); +assertEq('abc'.startsWith('bc', undefined), false); +assertEq('abc'.startsWith('abc', undefined), true); +assertEq('abc'.startsWith('bcd', undefined), false); +assertEq('abc'.startsWith('abcd', undefined), false); +assertEq('abc'.startsWith('bcde', undefined), false); + +assertEq('abc'.startsWith('', null), true); +assertEq('abc'.startsWith('\0', null), false); +assertEq('abc'.startsWith('a', null), true); +assertEq('abc'.startsWith('b', null), false); +assertEq('abc'.startsWith('ab', null), true); +assertEq('abc'.startsWith('bc', null), false); +assertEq('abc'.startsWith('abc', null), true); +assertEq('abc'.startsWith('bcd', null), false); +assertEq('abc'.startsWith('abcd', null), false); +assertEq('abc'.startsWith('bcde', null), false); + +assertEq('abc'.startsWith('', -Infinity), true); +assertEq('abc'.startsWith('\0', -Infinity), false); +assertEq('abc'.startsWith('a', -Infinity), true); +assertEq('abc'.startsWith('b', -Infinity), false); +assertEq('abc'.startsWith('ab', -Infinity), true); +assertEq('abc'.startsWith('bc', -Infinity), false); +assertEq('abc'.startsWith('abc', -Infinity), true); +assertEq('abc'.startsWith('bcd', -Infinity), false); +assertEq('abc'.startsWith('abcd', -Infinity), false); +assertEq('abc'.startsWith('bcde', -Infinity), false); + +assertEq('abc'.startsWith('', -1), true); +assertEq('abc'.startsWith('\0', -1), false); +assertEq('abc'.startsWith('a', -1), true); +assertEq('abc'.startsWith('b', -1), false); +assertEq('abc'.startsWith('ab', -1), true); +assertEq('abc'.startsWith('bc', -1), false); +assertEq('abc'.startsWith('abc', -1), true); +assertEq('abc'.startsWith('bcd', -1), false); +assertEq('abc'.startsWith('abcd', -1), false); +assertEq('abc'.startsWith('bcde', -1), false); + +assertEq('abc'.startsWith('', -0), true); +assertEq('abc'.startsWith('\0', -0), false); +assertEq('abc'.startsWith('a', -0), true); +assertEq('abc'.startsWith('b', -0), false); +assertEq('abc'.startsWith('ab', -0), true); +assertEq('abc'.startsWith('bc', -0), false); +assertEq('abc'.startsWith('abc', -0), true); +assertEq('abc'.startsWith('bcd', -0), false); +assertEq('abc'.startsWith('abcd', -0), false); +assertEq('abc'.startsWith('bcde', -0), false); + +assertEq('abc'.startsWith('', +0), true); +assertEq('abc'.startsWith('\0', +0), false); +assertEq('abc'.startsWith('a', +0), true); +assertEq('abc'.startsWith('b', +0), false); +assertEq('abc'.startsWith('ab', +0), true); +assertEq('abc'.startsWith('bc', +0), false); +assertEq('abc'.startsWith('abc', +0), true); +assertEq('abc'.startsWith('bcd', +0), false); +assertEq('abc'.startsWith('abcd', +0), false); +assertEq('abc'.startsWith('bcde', +0), false); + +assertEq('abc'.startsWith('', 1), true); +assertEq('abc'.startsWith('\0', 1), false); +assertEq('abc'.startsWith('a', 1), false); +assertEq('abc'.startsWith('b', 1), true); +assertEq('abc'.startsWith('ab', 1), false); +assertEq('abc'.startsWith('bc', 1), true); +assertEq('abc'.startsWith('abc', 1), false); +assertEq('abc'.startsWith('bcd', 1), false); +assertEq('abc'.startsWith('abcd', 1), false); +assertEq('abc'.startsWith('bcde', 1), false); + +assertEq('abc'.startsWith('', +Infinity), true); +assertEq('abc'.startsWith('\0', +Infinity), false); +assertEq('abc'.startsWith('a', +Infinity), false); +assertEq('abc'.startsWith('b', +Infinity), false); +assertEq('abc'.startsWith('ab', +Infinity), false); +assertEq('abc'.startsWith('bc', +Infinity), false); +assertEq('abc'.startsWith('abc', +Infinity), false); +assertEq('abc'.startsWith('bcd', +Infinity), false); +assertEq('abc'.startsWith('abcd', +Infinity), false); +assertEq('abc'.startsWith('bcde', +Infinity), false); + +assertEq('abc'.startsWith('', true), true); +assertEq('abc'.startsWith('\0', true), false); +assertEq('abc'.startsWith('a', true), false); +assertEq('abc'.startsWith('b', true), true); +assertEq('abc'.startsWith('ab', true), false); +assertEq('abc'.startsWith('bc', true), true); +assertEq('abc'.startsWith('abc', true), false); +assertEq('abc'.startsWith('bcd', true), false); +assertEq('abc'.startsWith('abcd', true), false); +assertEq('abc'.startsWith('bcde', true), false); + +assertEq('abc'.startsWith('', 'x'), true); +assertEq('abc'.startsWith('\0', 'x'), false); +assertEq('abc'.startsWith('a', 'x'), true); +assertEq('abc'.startsWith('b', 'x'), false); +assertEq('abc'.startsWith('ab', 'x'), true); +assertEq('abc'.startsWith('bc', 'x'), false); +assertEq('abc'.startsWith('abc', 'x'), true); +assertEq('abc'.startsWith('bcd', 'x'), false); +assertEq('abc'.startsWith('abcd', 'x'), false); +assertEq('abc'.startsWith('bcde', 'x'), false); + +assertEq('[a-z]+(bar)?'.startsWith('[a-z]+'), true); +assertThrows(function() { '[a-z]+(bar)?'.startsWith(/[a-z]+/); }, TypeError); +assertEq('[a-z]+(bar)?'.startsWith('(bar)?', 6), true); +assertThrows(function() { '[a-z]+(bar)?'.startsWith(/(bar)?/); }, TypeError); +assertThrows(function() { '[a-z]+/(bar)?/'.startsWith(/(bar)?/); }, TypeError); +var global = newGlobal(); +global.eval('this.re = /(bar)?/'); +assertThrows(function() { '[a-z]+/(bar)?/'.startsWith(global.re); }, TypeError); + +// http://mathiasbynens.be/notes/javascript-unicode#poo-test +var string = 'I\xF1t\xEBrn\xE2ti\xF4n\xE0liz\xE6ti\xF8n\u2603\uD83D\uDCA9'; +assertEq(string.startsWith(''), true); +assertEq(string.startsWith('\xF1t\xEBr'), false); +assertEq(string.startsWith('\xF1t\xEBr', 1), true); +assertEq(string.startsWith('\xE0liz\xE6'), false); +assertEq(string.startsWith('\xE0liz\xE6', 11), true); +assertEq(string.startsWith('\xF8n\u2603\uD83D\uDCA9'), false); +assertEq(string.startsWith('\xF8n\u2603\uD83D\uDCA9', 18), true); +assertEq(string.startsWith('\u2603'), false); +assertEq(string.startsWith('\u2603', 20), true); +assertEq(string.startsWith('\uD83D\uDCA9'), false); +assertEq(string.startsWith('\uD83D\uDCA9', 21), true); + +assertThrows(function() { String.prototype.startsWith.call(undefined); }, TypeError); +assertThrows(function() { String.prototype.startsWith.call(undefined, 'b'); }, TypeError); +assertThrows(function() { String.prototype.startsWith.call(undefined, 'b', 4); }, TypeError); +assertThrows(function() { String.prototype.startsWith.call(null); }, TypeError); +assertThrows(function() { String.prototype.startsWith.call(null, 'b'); }, TypeError); +assertThrows(function() { String.prototype.startsWith.call(null, 'b', 4); }, TypeError); +assertEq(String.prototype.startsWith.call(42, '2'), false); +assertEq(String.prototype.startsWith.call(42, '4'), true); +assertEq(String.prototype.startsWith.call(42, 'b', 4), false); +assertEq(String.prototype.startsWith.call(42, '2', 1), true); +assertEq(String.prototype.startsWith.call(42, '2', 4), false); +assertEq(String.prototype.startsWith.call({ 'toString': function() { return 'abc'; } }, 'b', 0), false); +assertEq(String.prototype.startsWith.call({ 'toString': function() { return 'abc'; } }, 'b', 1), true); +assertEq(String.prototype.startsWith.call({ 'toString': function() { return 'abc'; } }, 'b', 2), false); +assertThrows(function() { String.prototype.startsWith.call({ 'toString': function() { throw RangeError(); } }, /./); }, RangeError); +assertThrows(function() { String.prototype.startsWith.call({ 'toString': function() { return 'abc'; } }, /./); }, TypeError); + +assertThrows(function() { String.prototype.startsWith.apply(undefined); }, TypeError); +assertThrows(function() { String.prototype.startsWith.apply(undefined, ['b']); }, TypeError); +assertThrows(function() { String.prototype.startsWith.apply(undefined, ['b', 4]); }, TypeError); +assertThrows(function() { String.prototype.startsWith.apply(null); }, TypeError); +assertThrows(function() { String.prototype.startsWith.apply(null, ['b']); }, TypeError); +assertThrows(function() { String.prototype.startsWith.apply(null, ['b', 4]); }, TypeError); +assertEq(String.prototype.startsWith.apply(42, ['2']), false); +assertEq(String.prototype.startsWith.apply(42, ['4']), true); +assertEq(String.prototype.startsWith.apply(42, ['b', 4]), false); +assertEq(String.prototype.startsWith.apply(42, ['2', 1]), true); +assertEq(String.prototype.startsWith.apply(42, ['2', 4]), false); +assertEq(String.prototype.startsWith.apply({ 'toString': function() { return 'abc'; } }, ['b', 0]), false); +assertEq(String.prototype.startsWith.apply({ 'toString': function() { return 'abc'; } }, ['b', 1]), true); +assertEq(String.prototype.startsWith.apply({ 'toString': function() { return 'abc'; } }, ['b', 2]), false); +assertThrows(function() { String.prototype.startsWith.apply({ 'toString': function() { throw RangeError(); } }, [/./]); }, RangeError); +assertThrows(function() { String.prototype.startsWith.apply({ 'toString': function() { return 'abc'; } }, [/./]); }, TypeError); diff --git a/js/src/jit-test/tests/basic/stringConvert.js b/js/src/jit-test/tests/basic/stringConvert.js new file mode 100644 index 0000000000..53181891d5 --- /dev/null +++ b/js/src/jit-test/tests/basic/stringConvert.js @@ -0,0 +1,18 @@ +function stringConvert() +{ + var a = []; + var s1 = "F", s2 = "1.3", s3 = "5"; + for (var i = 0; i < 10; i++) { + a[0] = 1 >> s1; + a[1] = 10 - s2; + a[2] = 15 * s3; + a[3] = s3 | 32; + a[4] = s2 + 60; + // a[5] = 9 + s3; + // a[6] = -s3; + a[7] = s3 & "7"; + // a[8] = ~s3; + } + return a.toString(); +} +assertEq(stringConvert(), "1,8.7,75,37,1.360,,,5"); diff --git a/js/src/jit-test/tests/basic/stringSplitIntoArrayTest.js b/js/src/jit-test/tests/basic/stringSplitIntoArrayTest.js new file mode 100644 index 0000000000..e7fdb097be --- /dev/null +++ b/js/src/jit-test/tests/basic/stringSplitIntoArrayTest.js @@ -0,0 +1,9 @@ +function stringSplitIntoArrayTest() +{ + var s = "a,b" + var a = []; + for (var i = 0; i < 10; ++i) + a[i] = s.split(","); + return a.join(); +} +assertEq(stringSplitIntoArrayTest(), "a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b"); diff --git a/js/src/jit-test/tests/basic/stringSplitTest.js b/js/src/jit-test/tests/basic/stringSplitTest.js new file mode 100644 index 0000000000..942c7e79bc --- /dev/null +++ b/js/src/jit-test/tests/basic/stringSplitTest.js @@ -0,0 +1,9 @@ +function stringSplitTest() +{ + var s = "a,b" + var a = null; + for (var i = 0; i < 10; ++i) + a = s.split(","); + return a.join(); +} +assertEq(stringSplitTest(), "a,b"); diff --git a/js/src/jit-test/tests/basic/strings.js b/js/src/jit-test/tests/basic/strings.js new file mode 100644 index 0000000000..19139b9927 --- /dev/null +++ b/js/src/jit-test/tests/basic/strings.js @@ -0,0 +1,21 @@ +function strings() +{ + var a = [], b = -1; + var s = "abcdefghij", s2 = "a"; + var f = "f"; + var c = 0, d = 0, e = 0, g = 0; + for (var i = 0; i < 10; i++) { + a[i] = (s.substring(i, i+1) + s[i] + String.fromCharCode(s2.charCodeAt(0) + i)).concat(i) + i; + if (s[i] == f) + c++; + if (s[i] != 'b') + d++; + if ("B" > s2) + g++; // f already used + if (s2 < "b") + e++; + b = s.length; + } + return a.toString() + b + c + d + e + g; +} +assertEq(strings(), "aaa00,bbb11,ccc22,ddd33,eee44,fff55,ggg66,hhh77,iii88,jjj991019100"); diff --git a/js/src/jit-test/tests/basic/substring-inline-strings.js b/js/src/jit-test/tests/basic/substring-inline-strings.js new file mode 100644 index 0000000000..3f9381bb50 --- /dev/null +++ b/js/src/jit-test/tests/basic/substring-inline-strings.js @@ -0,0 +1,49 @@ +let hasStringRepresentation = typeof stringRepresentation === "function"; + +function testLatin1() { + var s = "abcdefghijklmnopqrstuvwxyz"; + for (var i = 0; i < 100; i++) { + var sub8 = s.substring(0, 8); + assertEq(sub8, "abcdefgh"); + if (hasStringRepresentation) { + assertEq(stringRepresentation(sub8).includes("(JSThinInlineString*)"), true); + } + + var sub24 = s.substring(0, 24); + assertEq(sub24, "abcdefghijklmnopqrstuvwx"); + if (hasStringRepresentation) { + assertEq(stringRepresentation(sub24).includes("(JSFatInlineString*)"), true); + } + + var sub25 = s.substring(0, 25); + assertEq(sub25, "abcdefghijklmnopqrstuvwxy"); + if (hasStringRepresentation) { + assertEq(stringRepresentation(sub25).includes("(JSDependentString*)"), true); + } + } +} +testLatin1(); + +function testTwoByte() { + var s = "\u1000bcdefghijklmnopqrstuvwxyz"; + for (var i = 0; i < 100; i++) { + var sub4 = s.substring(0, 4); + assertEq(sub4, "\u1000bcd"); + if (hasStringRepresentation) { + assertEq(stringRepresentation(sub4).includes("(JSThinInlineString*)"), true); + } + + var sub12 = s.substring(0, 12); + assertEq(sub12, "\u1000bcdefghijkl"); + if (hasStringRepresentation) { + assertEq(stringRepresentation(sub12).includes("(JSFatInlineString*)"), true); + } + + var sub13 = s.substring(0, 13); + assertEq(sub13, "\u1000bcdefghijklm"); + if (hasStringRepresentation) { + assertEq(stringRepresentation(sub13).includes("(JSDependentString*)"), true); + } + } +} +testTwoByte(); diff --git a/js/src/jit-test/tests/basic/symbol-in-loop.js b/js/src/jit-test/tests/basic/symbol-in-loop.js new file mode 100644 index 0000000000..cddef52655 --- /dev/null +++ b/js/src/jit-test/tests/basic/symbol-in-loop.js @@ -0,0 +1,8 @@ +function f() { + return Object(Symbol()); +} + +for (var i = 0; i < 4; i++) { + f(); + gc(); +} diff --git a/js/src/jit-test/tests/basic/syntax-error-function-body-eof.js b/js/src/jit-test/tests/basic/syntax-error-function-body-eof.js new file mode 100644 index 0000000000..7015f83b10 --- /dev/null +++ b/js/src/jit-test/tests/basic/syntax-error-function-body-eof.js @@ -0,0 +1,9 @@ +var caught = false; +try { + new Function("switch (x) {} }"); +} catch (e) { + assertEq(e instanceof SyntaxError, true); + assertEq(e.message.startsWith("unexpected garbage after function body, starting with '}'") == -1, false); + caught = true; +} +assertEq(caught, true); diff --git a/js/src/jit-test/tests/basic/syntax-error-primary.js b/js/src/jit-test/tests/basic/syntax-error-primary.js new file mode 100644 index 0000000000..6be66ee0c1 --- /dev/null +++ b/js/src/jit-test/tests/basic/syntax-error-primary.js @@ -0,0 +1,69 @@ +var caught = false; +try { + new Function(")"); +} catch (e) { + assertEq(e instanceof SyntaxError, true); + assertEq(e.message.startsWith("expected expression, got ')'") == -1, false); + caught = true; +} +assertEq(caught, true); + +caught = false; +try { + new Function("...;"); +} catch (e) { + assertEq(e instanceof SyntaxError, true); + assertEq(e.message.startsWith("expected rest argument name, got ';'") == -1, false); + caught = true; +} +assertEq(caught, true); + +caught = false; +try { + new Function("...a;"); +} catch (e) { + assertEq(e instanceof SyntaxError, true); + assertEq(e.message.startsWith("expected closing parenthesis, got ';'") == -1, false); + caught = true; +} +assertEq(caught, true); + +caught = false; +try { + new Function("...a);"); +} catch (e) { + assertEq(e instanceof SyntaxError, true); + assertEq(e.message.startsWith("expected '=>' after argument list, got ';'") == -1, false); + caught = true; +} +assertEq(caught, true); + +caught = false; +try { + new Function("...a) @"); +} catch (e) { + assertEq(e instanceof SyntaxError, true); + assertEq(e.message.startsWith("expected '=>' after argument list, got '@'") == -1, false); + caught = true; +} +assertEq(caught, true); + +caught = false; +try { + new Function("(if)"); +} catch (e) { + assertEq(e instanceof SyntaxError, true); + assertEq(e.message.startsWith("expected expression, got keyword 'if'") == -1, false); + caught = true; +} +assertEq(caught, true); + +caught = false; +try { + new Function("("); +} catch (e) { + assertEq(e instanceof SyntaxError, true); + assertEq(e.message.startsWith("expected expression, got end of script") == -1, false); + caught = true; +} +assertEq(caught, true); diff --git a/js/src/jit-test/tests/basic/syntax-error-throw.js b/js/src/jit-test/tests/basic/syntax-error-throw.js new file mode 100644 index 0000000000..c82c56cf8b --- /dev/null +++ b/js/src/jit-test/tests/basic/syntax-error-throw.js @@ -0,0 +1,39 @@ +var caught = false; +try { + new Function("throw;"); +} catch (e) { + assertEq(e instanceof SyntaxError, true); + assertEq(e.message.startsWith("throw statement is missing an expression") == -1, false); + caught = true; +} +assertEq(caught, true); + +caught = false; +try { + new Function("throw\n1;"); +} catch (e) { + assertEq(e instanceof SyntaxError, true); + assertEq(e.message.startsWith("no line break is allowed between 'throw' and its expression") == -1, false); + caught = true; +} +assertEq(caught, true); + +caught = false; +try { + new Function("throw}"); +} catch (e) { + assertEq(e instanceof SyntaxError, true); + assertEq(e.message.startsWith("throw statement is missing an expression") == -1, false); + caught = true; +} +assertEq(caught, true); + +caught = false; +try { + new Function("throw"); +} catch (e) { + assertEq(e instanceof SyntaxError, true); + assertEq(e.message.startsWith("throw statement is missing an expression") == -1, false); + caught = true; +} +assertEq(caught, true); diff --git a/js/src/jit-test/tests/basic/syntax-error-toplevel-eof.js b/js/src/jit-test/tests/basic/syntax-error-toplevel-eof.js new file mode 100644 index 0000000000..15aaaf7801 --- /dev/null +++ b/js/src/jit-test/tests/basic/syntax-error-toplevel-eof.js @@ -0,0 +1,9 @@ +var caught = false; +try { + Reflect.parse("}"); +} catch (e) { + assertEq(e instanceof SyntaxError, true); + assertEq(e.message.startsWith("unexpected garbage after script, starting with '}'") == -1, false); + caught = true; +} +assertEq(caught, true); diff --git a/js/src/jit-test/tests/basic/tagTempl.js b/js/src/jit-test/tests/basic/tagTempl.js new file mode 100644 index 0000000000..f4007a8c9a --- /dev/null +++ b/js/src/jit-test/tests/basic/tagTempl.js @@ -0,0 +1,35 @@ +/* + * Tests tagged template string functionality. + */ + +function check(actual, expected) { + assertEq(actual.length, expected.length); + for (var i = 0; i < expected.length; i++) + assertEq(actual[i], expected[i]); +} + +function func(a) { return a; } + +function csoLoop() { + var cso = []; + for (var index = 0; index < 2000; index++) { + cso[index] = func`hey${4}there`; + if (index > 0) + assertEq(cso[index - 1], cso[index]); + } +} + +// Tests baseline and ion functionality. +csoLoop(); + +// Tests off thread compilation +if (helperThreadCount() !== 0) { + offThreadCompileToStencil("(x=>x)`abc`"); + var stencil = finishOffThreadStencil(); + a = evalStencil(stencil); + check(a, ["abc"]); + check(a.raw, ["abc"]); + assertEq(a === a.raw, false); + assertEq(Object.isFrozen(a), true); + assertEq(Object.isFrozen(a.raw), true); +} diff --git a/js/src/jit-test/tests/basic/teleporting-mutable-proto.js b/js/src/jit-test/tests/basic/teleporting-mutable-proto.js new file mode 100644 index 0000000000..c9bfd7f287 --- /dev/null +++ b/js/src/jit-test/tests/basic/teleporting-mutable-proto.js @@ -0,0 +1,14 @@ +var A = {x: 3}; +var B = Object.create(A); +var C = Object.create(B); +var D = Object.create(C); + +function f() { + for (var i=0; i<30; i++) { + assertEq(D.x, (i <= 20) ? 3 : 10); + if (i === 20) { + C.__proto__ = {x: 10}; + } + } +} +f(); diff --git a/js/src/jit-test/tests/basic/terminate.js b/js/src/jit-test/tests/basic/terminate.js new file mode 100644 index 0000000000..f2966d783a --- /dev/null +++ b/js/src/jit-test/tests/basic/terminate.js @@ -0,0 +1,10 @@ +// |jit-test| exitstatus: 3 +try { + terminate(); + assertEq("execution continued", "execution should not continue"); +} catch (x) { + assertEq("caught exception", "uncatchable"); +} finally { + assertEq("'finally' clause ran", "'finally' clause should not run"); +} +assertEq("top-level execution continued", "top-level execution should not continue"); diff --git a/js/src/jit-test/tests/basic/test-apply-many-args.js b/js/src/jit-test/tests/basic/test-apply-many-args.js new file mode 100644 index 0000000000..ea02f4df35 --- /dev/null +++ b/js/src/jit-test/tests/basic/test-apply-many-args.js @@ -0,0 +1,14 @@ +function f(x) { + if (x == 0) + return; + arguments[0]--; + f.apply(null, arguments); +} + +// When the apply-optimization isn't on, each recursive call chews up the C +// stack, so don't push it. +a = [20]; + +for (var i = 0; i < 2000; ++i) + a.push(i); +f.apply(null, a); diff --git a/js/src/jit-test/tests/basic/test-error-accessors-with-wrappers.js b/js/src/jit-test/tests/basic/test-error-accessors-with-wrappers.js new file mode 100644 index 0000000000..2afa881f3a --- /dev/null +++ b/js/src/jit-test/tests/basic/test-error-accessors-with-wrappers.js @@ -0,0 +1,11 @@ +let g = newGlobal(); + +let error = g.eval("Error()"); + +// This should not throw. +assertEq(typeof error.stack, "string"); + +g.error = Error(); + +// Nor should this. +assertEq(g.eval("typeof error.stack"), "string"); diff --git a/js/src/jit-test/tests/basic/test-jitinfo.js b/js/src/jit-test/tests/basic/test-jitinfo.js new file mode 100644 index 0000000000..606f277794 --- /dev/null +++ b/js/src/jit-test/tests/basic/test-jitinfo.js @@ -0,0 +1,26 @@ +// Test for the shell's FakeDOMObject constructor. This test +// ensures the fuzzers know about this object. +function f() { + var res = 0; + var d = new FakeDOMObject(); + assertEq(d !== new FakeDOMObject(), true); + + for (var i = 0; i < 100; i++) { + assertEq(d.slot, 42); + + var x = d.x; + assertEq(typeof x, "number"); + + d.x = 10; + d.x = undefined; + + d.x = FakeDOMObject.prototype.x; + FakeDOMObject.prototype.x = d.x; + FakeDOMObject.prototype.doFoo(); + + assertEq(d.doFoo(), 0); + assertEq(d.doFoo(1), 1); + assertEq(d.doFoo(1, 2), 2); + } +} +f(); diff --git a/js/src/jit-test/tests/basic/test586387.js b/js/src/jit-test/tests/basic/test586387.js new file mode 100644 index 0000000000..5ddc2d7266 --- /dev/null +++ b/js/src/jit-test/tests/basic/test586387.js @@ -0,0 +1,14 @@ +function testFloatArray() { + var v = new Float32Array(32); + + for (var i = 0; i < v.length; ++i) + v[i] = i; + + var t = 0; + for (var i = 0; i < v.length; ++i) + t += v[i]; + + return t; +} + +assertEq(testFloatArray(), 496); diff --git a/js/src/jit-test/tests/basic/testAbortedImacroDecompilation.js b/js/src/jit-test/tests/basic/testAbortedImacroDecompilation.js new file mode 100644 index 0000000000..b1cfdb92d1 --- /dev/null +++ b/js/src/jit-test/tests/basic/testAbortedImacroDecompilation.js @@ -0,0 +1,7 @@ +function f() { + for (var i=0; i<9; i++) + assertEq("" + f, expected); +} + +var expected = "" + f; +f(); diff --git a/js/src/jit-test/tests/basic/testAccessCanonicalArgInGetElem.js b/js/src/jit-test/tests/basic/testAccessCanonicalArgInGetElem.js new file mode 100644 index 0000000000..6440724615 --- /dev/null +++ b/js/src/jit-test/tests/basic/testAccessCanonicalArgInGetElem.js @@ -0,0 +1,12 @@ +var o = {x:42}; + +function f(index,param) { + arguments[1] = 0; + var ret = 0; + for (var i = 0; i < 5; ++i) + ret = arguments[index].x; + return ret; +} + +assertEq(f(2,o,o), 42); +assertEq(f(1,o,o), undefined); diff --git a/js/src/jit-test/tests/basic/testAddAnyInconvertibleObject.js b/js/src/jit-test/tests/basic/testAddAnyInconvertibleObject.js new file mode 100644 index 0000000000..4a4b1d8575 --- /dev/null +++ b/js/src/jit-test/tests/basic/testAddAnyInconvertibleObject.js @@ -0,0 +1,28 @@ +function testAddAnyInconvertibleObject() +{ + var count = 0; + function toString() { ++count; if (count == 95) return {}; return "" + count; } + var o = {valueOf: undefined, toString: toString}; + + var threw = false; + try + { + for (var i = 0; i < 100; i++) + var q = 5 + o; + } + catch (e) + { + threw = true; + if (i !== 94) + return "expected i === 94, got " + i; + if (q !== "594") + return "expected q === '594', got " + q + " (type " + typeof q + ")"; + if (count !== 95) + return "expected count === 95, got " + count; + } + if (!threw) + return "expected throw with 5 + o"; // hey, a rhyme! + + return "pass"; +} +assertEq(testAddAnyInconvertibleObject(), "pass"); diff --git a/js/src/jit-test/tests/basic/testAddInconvertibleObjectAny.js b/js/src/jit-test/tests/basic/testAddInconvertibleObjectAny.js new file mode 100644 index 0000000000..aabf8ec573 --- /dev/null +++ b/js/src/jit-test/tests/basic/testAddInconvertibleObjectAny.js @@ -0,0 +1,34 @@ +function testAddInconvertibleObjectAny() +{ + var count = 0; + function toString() + { + ++count; + if (count == 95) + return {}; + return "" + count; + } + var o = {valueOf: undefined, toString: toString}; + + var threw = false; + try + { + for (var i = 0; i < 100; i++) + var q = o + 5; + } + catch (e) + { + threw = true; + if (i !== 94) + return "expected i === 94, got " + i; + if (q !== "945") + return "expected q === '945', got " + q + " (type " + typeof q + ")"; + if (count !== 95) + return "expected count === 95, got " + count; + } + if (!threw) + return "expected throw with o + 5"; + + return "pass"; +} +assertEq(testAddInconvertibleObjectAny(), "pass"); diff --git a/js/src/jit-test/tests/basic/testAddInconvertibleObjectInconvertibleObject.js b/js/src/jit-test/tests/basic/testAddInconvertibleObjectInconvertibleObject.js new file mode 100644 index 0000000000..5004dbbe5c --- /dev/null +++ b/js/src/jit-test/tests/basic/testAddInconvertibleObjectInconvertibleObject.js @@ -0,0 +1,33 @@ +function testAddInconvertibleObjectInconvertibleObject() +{ + var count1 = 0; + function toString1() { ++count1; if (count1 == 95) return {}; return "" + count1; } + var o1 = {valueOf: undefined, toString: toString1}; + var count2 = 0; + function toString2() { ++count2; if (count2 == 95) return {}; return "" + count2; } + var o2 = {valueOf: undefined, toString: toString2}; + + var threw = false; + try + { + for (var i = 0; i < 100; i++) + var q = o1 + o2; + } + catch (e) + { + threw = true; + if (i !== 94) + return "expected i === 94, got " + i; + if (q !== "9494") + return "expected q === '9494', got " + q + " (type " + typeof q + ")"; + if (count1 !== 95) + return "expected count1 === 95, got " + count1; + if (count2 !== 94) + return "expected count2 === 94, got " + count2; + } + if (!threw) + return "expected throw with o1 + o2"; + + return "pass"; +} +assertEq(testAddInconvertibleObjectInconvertibleObject(), "pass"); diff --git a/js/src/jit-test/tests/basic/testAddNull.js b/js/src/jit-test/tests/basic/testAddNull.js new file mode 100644 index 0000000000..78b40a519a --- /dev/null +++ b/js/src/jit-test/tests/basic/testAddNull.js @@ -0,0 +1,8 @@ +function testAddNull() +{ + var rv; + for (var x = 0; x < 9; ++x) + rv = null + [,,]; + return rv; +} +assertEq(testAddNull(), "null,"); diff --git a/js/src/jit-test/tests/basic/testAddUndefined.js b/js/src/jit-test/tests/basic/testAddUndefined.js new file mode 100644 index 0000000000..9a21e2f93b --- /dev/null +++ b/js/src/jit-test/tests/basic/testAddUndefined.js @@ -0,0 +1,5 @@ +function testAddUndefined() { + for (var j = 0; j < 3; ++j) + (0 + void 0) && 0; +} +testAddUndefined(); diff --git a/js/src/jit-test/tests/basic/testAliasedLet.js b/js/src/jit-test/tests/basic/testAliasedLet.js new file mode 100644 index 0000000000..3ab016999b --- /dev/null +++ b/js/src/jit-test/tests/basic/testAliasedLet.js @@ -0,0 +1,12 @@ +function f() { + { + let x, y, z; + eval('x = 1; y = 2; z = 3'); + for (var i = 0; i < 10000; ++i) { + assertEq(x, 1); + assertEq(y, 2); + assertEq(z, 3); + } + } +} +f(); diff --git a/js/src/jit-test/tests/basic/testApply.js b/js/src/jit-test/tests/basic/testApply.js new file mode 100644 index 0000000000..73e3592284 --- /dev/null +++ b/js/src/jit-test/tests/basic/testApply.js @@ -0,0 +1,7 @@ +function testApply() { + var q = []; + for (var i = 0; i < 10; ++i) + Array.prototype.push.apply(q, [5]); + return q.join(","); +} +assertEq(testApply(), "5,5,5,5,5,5,5,5,5,5"); diff --git a/js/src/jit-test/tests/basic/testApplyArrayInline.js b/js/src/jit-test/tests/basic/testApplyArrayInline.js new file mode 100644 index 0000000000..75b5d9239c --- /dev/null +++ b/js/src/jit-test/tests/basic/testApplyArrayInline.js @@ -0,0 +1,74 @@ +// |jit-test| skip-if: !this.getJitCompilerOptions() || !getJitCompilerOptions()['ion.enable']; --ion-warmup-threshold=50 + +// Test inlining in Ion of fun.apply(..., array). + +setJitCompilerOption("offthread-compilation.enable", 0); +gcPreserveCode(); + +var itercount = 1000; +var warmup = 100; + +// Force Ion to do something predictable without having to wait +// forever for it. + +if (getJitCompilerOptions()["ion.warmup.trigger"] > warmup) + setJitCompilerOption("ion.warmup.trigger", warmup); + +setJitCompilerOption("offthread-compilation.enable", 0); + +function g(a, b, c, d) { + return a + b + c + (d === undefined); +} + +var g_inIonInLoop = false; +var g_inIonAtEnd = false; + +function f(xs) { + var sum = 0; + var inIonInLoop = 0; + for ( var i=0 ; i < itercount ; i++ ) { + inIonInLoop |= inIon(); + sum += g.apply(null, xs); + } + g_ionAtEnd = inIon(); + g_inIonInLoop = !!inIonInLoop; + return sum; +} + +// Basic test + +assertEq(f([1,2,3,4]), 6*itercount); + +// Attempt to detect a botched optimization: either we ion-compiled +// the loop, or we did not ion-compile the function (ion not actually +// effective at all, this can happen). + +assertEq(g_inIonInLoop || !g_inIonAtEnd, true); + +// If Ion is inert just leave. + +if (!g_inIonInLoop) { + print("Leaving early - ion not kicking in at all"); + quit(0); +} + +// Test that we get the correct argument value even if the array has +// fewer initialized members than its length. + +var headroom = [1,2,3]; +headroom.length = 13; +assertEq(f(headroom), 7*itercount); + +// Test that we throw when the array is too long. + +var thrown = false; +try { + var long = []; + long.length = getMaxArgs() + 1; + f(long); +} +catch (e) { + thrown = true; + assertEq(e instanceof RangeError, true); +} +assertEq(thrown, true); diff --git a/js/src/jit-test/tests/basic/testApplyAtJoinPoint.js b/js/src/jit-test/tests/basic/testApplyAtJoinPoint.js new file mode 100644 index 0000000000..bb7f219abf --- /dev/null +++ b/js/src/jit-test/tests/basic/testApplyAtJoinPoint.js @@ -0,0 +1,12 @@ +var isTrue = true; + +function g(x) { + return x; +} + +function f() { + return g.apply(null, isTrue ? ["happy"] : arguments); +} + +for (var i = 0; i < 18; ++i) + assertEq(f("sad"), "happy"); diff --git a/js/src/jit-test/tests/basic/testApplyCall.js b/js/src/jit-test/tests/basic/testApplyCall.js new file mode 100644 index 0000000000..0afe2ff7c9 --- /dev/null +++ b/js/src/jit-test/tests/basic/testApplyCall.js @@ -0,0 +1,42 @@ +function testApplyCallHelper(f) { + var r = []; + for (var i = 0; i < 10; ++i) f.call(); + r.push(x); + for (var i = 0; i < 10; ++i) f.call(this); + r.push(x); + for (var i = 0; i < 10; ++i) f.apply(this); + r.push(x); + for (var i = 0; i < 10; ++i) f.call(this,0); + r.push(x); + for (var i = 0; i < 10; ++i) f.apply(this,[0]); + r.push(x); + for (var i = 0; i < 10; ++i) f.call(this,0,1); + r.push(x); + for (var i = 0; i < 10; ++i) f.apply(this,[0,1]); + r.push(x); + for (var i = 0; i < 10; ++i) f.call(this,0,1,2); + r.push(x); + for (var i = 0; i < 10; ++i) f.apply(this,[0,1,2]); + r.push(x); + for (var i = 0; i < 10; ++i) f.call(this,0,1,2,3); + r.push(x); + for (var i = 0; i < 10; ++i) f.apply(this,[0,1,2,3]); + r.push(x); + for (var i = 0; i < 10; ++i) f.call(this,0,1,2,3,4); + r.push(x); + for (var i = 0; i < 10; ++i) f.apply(this,[0,1,2,3,4]); + r.push(x); + for (var i = 0; i < 10; ++i) f.call(this,0,1,2,3,4,5); + r.push(x); + for (var i = 0; i < 10; ++i) f.apply(this,[0,1,2,3,4,5]) + r.push(x); + return(r.join(",")); +} +function testApplyCall() { + var r = testApplyCallHelper(function (a0,a1,a2,a3,a4,a5,a6,a7) { x = [a0,a1,a2,a3,a4,a5,a6,a7]; }); + r += testApplyCallHelper(function (a0,a1,a2,a3,a4,a5,a6,a7) { x = [a0,a1,a2,a3,a4,a5,a6,a7]; }); + return r; +} + +assertEq(testApplyCall(), ",,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,,0,,,,,,,,0,1,,,,,,,0,1,,,,,,,0,1,2,,,,,,0,1,2,,,,,,0,1,2,3,,,,,0,1,2,3,,,,,0,1,2,3,4,,,,0,1,2,3,4,,,,0,1,2,3,4,5,,,0,1,2,3,4,5,," + +",,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,,0,,,,,,,,0,1,,,,,,,0,1,,,,,,,0,1,2,,,,,,0,1,2,,,,,,0,1,2,3,,,,,0,1,2,3,,,,,0,1,2,3,4,,,,0,1,2,3,4,,,,0,1,2,3,4,5,,,0,1,2,3,4,5,,"); diff --git a/js/src/jit-test/tests/basic/testApplyInterpretLowered.js b/js/src/jit-test/tests/basic/testApplyInterpretLowered.js new file mode 100644 index 0000000000..e35659f9e8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testApplyInterpretLowered.js @@ -0,0 +1,15 @@ + +/* Read correct return value when the interpreter pops a lowered call/apply. */ + +function recompile() {} + +function foo() { + if (arguments[0] == 9) + recompile(); + return arguments[0]; +} +function bar() { + for (var i = 0; i < 10; i++) + assertEq(foo.apply(null, [i]), i); +} +bar(); diff --git a/js/src/jit-test/tests/basic/testApplyInterpretLowered2.js b/js/src/jit-test/tests/basic/testApplyInterpretLowered2.js new file mode 100644 index 0000000000..0564ead0b6 --- /dev/null +++ b/js/src/jit-test/tests/basic/testApplyInterpretLowered2.js @@ -0,0 +1,12 @@ + +/* Make sure the interpreter can pop lowered frames pushed by CompileFunction. */ + +function recompile() {} + +function bar() { + for (var i = 0; i < 50; i++) { + var foo = new Function("recompile(arguments[0] + " + i + "); return arguments[0]"); + assertEq(foo.apply(null, [i]), i); + } +} +bar(); diff --git a/js/src/jit-test/tests/basic/testApplySpeculationFailInCompiler.js b/js/src/jit-test/tests/basic/testApplySpeculationFailInCompiler.js new file mode 100644 index 0000000000..8a79a5cf5e --- /dev/null +++ b/js/src/jit-test/tests/basic/testApplySpeculationFailInCompiler.js @@ -0,0 +1,6 @@ +function baz(i) { return i } +function bar(x, y) { return baz.apply(null, x ? y : arguments) } +var s; +for (var i = 0; i < 1000; ++i) + s = bar(true, [42]); +assertEq(s, 42); diff --git a/js/src/jit-test/tests/basic/testApplyUnbox.js b/js/src/jit-test/tests/basic/testApplyUnbox.js new file mode 100644 index 0000000000..5336ace075 --- /dev/null +++ b/js/src/jit-test/tests/basic/testApplyUnbox.js @@ -0,0 +1,11 @@ +function testApplyUnboxHelper(f,a) { + var q; + for (var i = 0; i < 10; ++i) + q = f.apply(f,a); + return q; +} +function testApplyUnbox() { + var f = function(x) { return x; } + return [testApplyUnboxHelper(f,[1]), testApplyUnboxHelper(f,[true])].join(","); +} +assertEq(testApplyUnbox(), "1,true"); diff --git a/js/src/jit-test/tests/basic/testArgumentsOptimizationFailCornerCase.js b/js/src/jit-test/tests/basic/testArgumentsOptimizationFailCornerCase.js new file mode 100644 index 0000000000..90f4f11c94 --- /dev/null +++ b/js/src/jit-test/tests/basic/testArgumentsOptimizationFailCornerCase.js @@ -0,0 +1,23 @@ +Object.prototype.blah = 42; + +function g(a,b,c) { + assertEq(a, 1); + assertEq(b, 2); + assertEq(c, 3); + return 43; +} + +function f() { + var a = arguments; + var b = a; + var s = "blah"; + assertEq(a[s], 42); + assertEq(b[s], 42); + assertEq(a[s], 42); + assertEq(b.length, 3); + assertEq(a.length, 3); + assertEq(g.apply(null, b), 43); +} + +for (var i = 0; i < 10; ++i) + f(1,2,3); diff --git a/js/src/jit-test/tests/basic/testArgumentsPropLookup.js b/js/src/jit-test/tests/basic/testArgumentsPropLookup.js new file mode 100644 index 0000000000..6e8a4cda75 --- /dev/null +++ b/js/src/jit-test/tests/basic/testArgumentsPropLookup.js @@ -0,0 +1,19 @@ +(function() { + var s = "__proto__"; + assertEq(arguments[s], Object.prototype); +})(); + +Object.defineProperty(Object.prototype, "foo", { + get:function() { + this.bar = 42; + return 41 + } +}); + +(function() { + var s = "foo"; + assertEq(arguments[s], 41); + s = "bar"; + assertEq(arguments[s], 42); + assertEq("bar" in Object.prototype, false); +})(); diff --git a/js/src/jit-test/tests/basic/testArrayBufferSlice.js b/js/src/jit-test/tests/basic/testArrayBufferSlice.js new file mode 100644 index 0000000000..3b1f353def --- /dev/null +++ b/js/src/jit-test/tests/basic/testArrayBufferSlice.js @@ -0,0 +1,57 @@ +function testSlice() { + function test(subBuf, starts, size) { + var byteLength = size; + var subBuffer = eval(subBuf); + var subArray = new Int8Array(subBuffer); + assertEq(subBuffer.byteLength, byteLength); + for (var i = 0; i < size; ++i) + assertEq(starts + i, subArray[i]); + } + + var buffer = new ArrayBuffer(32); + var array = new Int8Array(buffer); + for (var i = 0; i < 32; ++i) + array[i] = i; + + test("buffer.slice(0)", 0, 32); + test("buffer.slice(16)", 16, 16); + test("buffer.slice(24)", 24, 8); + test("buffer.slice(32)", 32, 0); + test("buffer.slice(40)", 32, 0); + test("buffer.slice(80)", 32, 0); + + test("buffer.slice(-8)", 24, 8); + test("buffer.slice(-16)", 16, 16); + test("buffer.slice(-24)", 8, 24); + test("buffer.slice(-32)", 0, 32); + test("buffer.slice(-40)", 0, 32); + test("buffer.slice(-80)", 0, 32); + + test("buffer.slice(0, 32)", 0, 32); + test("buffer.slice(0, 16)", 0, 16); + test("buffer.slice(8, 24)", 8, 16); + test("buffer.slice(16, 32)", 16, 16); + test("buffer.slice(24, 16)", 24, 0); + + test("buffer.slice(16, -8)", 16, 8); + test("buffer.slice(-20, 30)", 12, 18); + + test("buffer.slice(-8, -20)", 24, 0); + test("buffer.slice(-20, -8)", 12, 12); + test("buffer.slice(-40, 16)", 0, 16); + test("buffer.slice(-40, 40)", 0, 32); + + gczeal(7, 100000); + var nurseryBuf = new ArrayBuffer(32); + var arr = new Int8Array(nurseryBuf); + arr[0] = 77; + + // tenure nurseryBuf during the slice operation + nurseryBuf.slice; // Creates an object + schedulegc(1); + var newbuf = nurseryBuf.slice(0); + var arr2 = new Int8Array(newbuf); + assertEq(arr2[0], 77); +} + +testSlice(); diff --git a/js/src/jit-test/tests/basic/testArrayBufferSpeciesDelete.js b/js/src/jit-test/tests/basic/testArrayBufferSpeciesDelete.js new file mode 100644 index 0000000000..02e515d325 --- /dev/null +++ b/js/src/jit-test/tests/basic/testArrayBufferSpeciesDelete.js @@ -0,0 +1,5 @@ +delete ArrayBuffer[Symbol.species]; +var a = new Uint8Array(new Uint8Array([1, 2])); +assertEq(a.length, 2); +assertEq(a[0], 1); +assertEq(a[1], 2); diff --git a/js/src/jit-test/tests/basic/testArrayConcat.js b/js/src/jit-test/tests/basic/testArrayConcat.js new file mode 100644 index 0000000000..ec29e43536 --- /dev/null +++ b/js/src/jit-test/tests/basic/testArrayConcat.js @@ -0,0 +1,10 @@ + +var x = Array(4); +x[0] = 1; +x[1] = 2; +x[2] = 3; +var y = x.concat(); +assertEq(y[3], undefined); + +var z = x.concat(/abc/).pop(); +assertEq(z.source, "abc"); diff --git a/js/src/jit-test/tests/basic/testArrayDensityChange.js b/js/src/jit-test/tests/basic/testArrayDensityChange.js new file mode 100644 index 0000000000..b9dfabad1e --- /dev/null +++ b/js/src/jit-test/tests/basic/testArrayDensityChange.js @@ -0,0 +1,17 @@ +function testArrayDensityChange() { + var x = []; + var count = 0; + for (var i=0; i < 100; ++i) { + x[i] = "asdf"; + } + for (var i=0; i < x.length; ++i) { + if (i == 51) + { + x[199] = "asdf"; + } + if (x[i]) + count += x[i].length; + } + return count; +} +assertEq(testArrayDensityChange(), 404); diff --git a/js/src/jit-test/tests/basic/testArrayInWithIndexedProto.js b/js/src/jit-test/tests/basic/testArrayInWithIndexedProto.js new file mode 100644 index 0000000000..97da0ee07a --- /dev/null +++ b/js/src/jit-test/tests/basic/testArrayInWithIndexedProto.js @@ -0,0 +1,24 @@ +function testArrayInWithIndexedProto() +{ + Array.prototype[0] = "Got me"; + var zeroPresent, zeroPresent2; + // Need to go to 18 because in the failure mode this is + // testing we have various side-exits in there due to interp and + // tracer not agreeing that confuse the issue and cause us to not + // hit the bad case within 9 iterations. + for (var j = 0; j < 18; ++j) { + zeroPresent = 0 in []; + } + + var arr = [1, 2]; + delete arr[0]; + for (var j = 0; j < 18; ++j) { + zeroPresent2 = 0 in arr; + } + return [zeroPresent, zeroPresent2]; +} + +var [ret, ret2] = testArrayInWithIndexedProto(); +assertEq(ret, true); +assertEq(ret2, true); + diff --git a/js/src/jit-test/tests/basic/testArrayNaNIndex.js b/js/src/jit-test/tests/basic/testArrayNaNIndex.js new file mode 100644 index 0000000000..671f6ff8f6 --- /dev/null +++ b/js/src/jit-test/tests/basic/testArrayNaNIndex.js @@ -0,0 +1,7 @@ +function testArrayNaNIndex() +{ + for (var j = 0; j < 4; ++j) { [this[NaN]]; } + for (var j = 0; j < 5; ++j) { if([1][-0]) { } } + return "ok"; +} +assertEq(testArrayNaNIndex(), "ok"); diff --git a/js/src/jit-test/tests/basic/testArrayNamedProp.js b/js/src/jit-test/tests/basic/testArrayNamedProp.js new file mode 100644 index 0000000000..7357412dd4 --- /dev/null +++ b/js/src/jit-test/tests/basic/testArrayNamedProp.js @@ -0,0 +1,5 @@ +function testArrayNamedProp() { + for (var x = 0; x < 10; ++x) { [4].sort-- } + return "ok"; +} +assertEq(testArrayNamedProp(), "ok"); diff --git a/js/src/jit-test/tests/basic/testArrayPushPop.js b/js/src/jit-test/tests/basic/testArrayPushPop.js new file mode 100644 index 0000000000..8e00dad231 --- /dev/null +++ b/js/src/jit-test/tests/basic/testArrayPushPop.js @@ -0,0 +1,11 @@ +function testArrayPushPop() { + var a = [], sum1 = 0, sum2 = 0; + for (var i = 0; i < 10; ++i) + sum1 += a.push(i); + for (var i = 0; i < 10; ++i) + sum2 += a.pop(); + a.push(sum1); + a.push(sum2); + return a.join(","); +} +assertEq(testArrayPushPop(), "55,45"); diff --git a/js/src/jit-test/tests/basic/testArraySpeciesDelete.js b/js/src/jit-test/tests/basic/testArraySpeciesDelete.js new file mode 100644 index 0000000000..8677d22547 --- /dev/null +++ b/js/src/jit-test/tests/basic/testArraySpeciesDelete.js @@ -0,0 +1,5 @@ +delete Array[Symbol.species]; +var a = [1, 2, 3].slice(1); +assertEq(a.length, 2); +assertEq(a[0], 2); +assertEq(a[1], 3); diff --git a/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js b/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js new file mode 100644 index 0000000000..1c59113482 --- /dev/null +++ b/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js @@ -0,0 +1,10 @@ +var o = { + set x(v) { + return 42; + } +}; + +for (var i = 0; i < 10; ++i) { + var z = o.x = "choose me"; + assertEq(z, "choose me"); +} diff --git a/js/src/jit-test/tests/basic/testAtomize.js b/js/src/jit-test/tests/basic/testAtomize.js new file mode 100644 index 0000000000..16076eb6be --- /dev/null +++ b/js/src/jit-test/tests/basic/testAtomize.js @@ -0,0 +1,10 @@ +function testAtomize() { + x = {}; + for (var i = 0; i < 65536; ++i) + x[String.fromCharCode(i)] = 1; + var z = 0; + for (var p in x) + ++z; + return z; +} +assertEq(testAtomize(), 65536) diff --git a/js/src/jit-test/tests/basic/testBitOrAnyInconvertibleObject.js b/js/src/jit-test/tests/basic/testBitOrAnyInconvertibleObject.js new file mode 100644 index 0000000000..d3daadbea4 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBitOrAnyInconvertibleObject.js @@ -0,0 +1,28 @@ +function testBitOrAnyInconvertibleObject() +{ + var count = 0; + function toString() { ++count; if (count == 95) return {}; return count; } + var o = {valueOf: undefined, toString: toString}; + + var threw = false; + try + { + for (var i = 0; i < 100; i++) + var q = 1 | o; + } + catch (e) + { + threw = true; + if (i !== 94) + return "expected i === 94, got " + i; + if (q !== 95) + return "expected q === 95, got " + q; + if (count !== 95) + return "expected count === 95, got " + count; + } + if (!threw) + return "expected throw with 2 | o"; // hey, a rhyme! + + return "pass"; +} +assertEq(testBitOrAnyInconvertibleObject(), "pass"); diff --git a/js/src/jit-test/tests/basic/testBitOrInconvertibleObjectAny.js b/js/src/jit-test/tests/basic/testBitOrInconvertibleObjectAny.js new file mode 100644 index 0000000000..29d983ab09 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBitOrInconvertibleObjectAny.js @@ -0,0 +1,28 @@ +function testBitOrInconvertibleObjectAny() +{ + var count = 0; + function toString() { ++count; if (count == 95) return {}; return count; } + var o = {valueOf: undefined, toString: toString}; + + var threw = false; + try + { + for (var i = 0; i < 100; i++) + var q = o | 1; + } + catch (e) + { + threw = true; + if (i !== 94) + return "expected i === 94, got " + i; + if (q !== 95) + return "expected q === 95, got " + q; + if (count !== 95) + return "expected count === 95, got " + count; + } + if (!threw) + return "expected throw with o | 2"; + + return "pass"; +} +assertEq(testBitOrInconvertibleObjectAny(), "pass"); diff --git a/js/src/jit-test/tests/basic/testBitOrInconvertibleObjectInconvertibleObject.js b/js/src/jit-test/tests/basic/testBitOrInconvertibleObjectInconvertibleObject.js new file mode 100644 index 0000000000..420b431ea0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBitOrInconvertibleObjectInconvertibleObject.js @@ -0,0 +1,33 @@ +function testBitOrInconvertibleObjectInconvertibleObject() +{ + var count1 = 0; + function toString1() { ++count1; if (count1 == 95) return {}; return count1; } + var o1 = {valueOf: undefined, toString: toString1}; + var count2 = 0; + function toString2() { ++count2; if (count2 == 95) return {}; return count2; } + var o2 = {valueOf: undefined, toString: toString2}; + + var threw = false; + try + { + for (var i = 0; i < 100; i++) + var q = o1 | o2; + } + catch (e) + { + threw = true; + if (i !== 94) + return "expected i === 94, got " + i; + if (q !== 94) + return "expected q === 94, got " + q; + if (count1 !== 95) + return "expected count1 === 95, got " + count1; + if (count2 !== 94) + return "expected count2 === 94, got " + count2; + } + if (!threw) + return "expected throw with o1 | o2"; + + return "pass"; +} +assertEq(testBitOrInconvertibleObjectInconvertibleObject(), "pass"); diff --git a/js/src/jit-test/tests/basic/testBitopWithConstan.js b/js/src/jit-test/tests/basic/testBitopWithConstan.js new file mode 100644 index 0000000000..494994d7f5 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBitopWithConstan.js @@ -0,0 +1,741 @@ +function test1 (x) {
+ assertEq(x | -1, -1);
+ assertEq(-1 | x, -1);
+ assertEq(x & -1, 1);
+ assertEq(-1 & x, 1);
+ assertEq(x ^ -1, -2);
+ assertEq(-1 ^ x, -2);
+ assertEq(x >> -1, 0);
+ assertEq(-1 >> x, -1);
+ assertEq(x >>> -1, 0);
+ assertEq(-1 >>> x, 2147483647);
+ assertEq(x << -1, -2147483648);
+ assertEq(-1 << x, -2);
+ assertEq(x | 1, 1);
+ assertEq(1 | x, 1);
+ assertEq(x & 1, 1);
+ assertEq(1 & x, 1);
+ assertEq(x ^ 1, 0);
+ assertEq(1 ^ x, 0);
+ assertEq(x >> 1, 0);
+ assertEq(1 >> x, 0);
+ assertEq(x >>> 1, 0);
+ assertEq(1 >>> x, 0);
+ assertEq(x << 1, 2);
+ assertEq(1 << x, 2);
+ assertEq(x | 0, 1);
+ assertEq(0 | x, 1);
+ assertEq(x & 0, 0);
+ assertEq(0 & x, 0);
+ assertEq(x ^ 0, 1);
+ assertEq(0 ^ x, 1);
+ assertEq(x >> 0, 1);
+ assertEq(0 >> x, 0);
+ assertEq(x >>> 0, 1);
+ assertEq(0 >>> x, 0);
+ assertEq(x << 0, 1);
+ assertEq(0 << x, 0);
+ assertEq(x | 0xffffffff, -1);
+ assertEq(0xffffffff | x, -1);
+ assertEq(x & 0xffffffff, 1);
+ assertEq(0xffffffff & x, 1);
+ assertEq(x ^ 0xffffffff, -2);
+ assertEq(0xffffffff ^ x, -2);
+ assertEq(x >> 0xffffffff, 0);
+ assertEq(0xffffffff >> x, -1);
+ assertEq(x >>> 0xffffffff, 0);
+ assertEq(0xffffffff >>> x, 2147483647);
+ assertEq(x << 0xffffffff, -2147483648);
+ assertEq(0xffffffff << x, -2);
+ assertEq(x | "10.6", 11);
+ assertEq("10.6" | x, 11);
+ assertEq(x & "10.6", 0);
+ assertEq("10.6" & x, 0);
+ assertEq(x ^ "10.6", 11);
+ assertEq("10.6" ^ x, 11);
+ assertEq(x >> "10.6", 0);
+ assertEq("10.6" >> x, 5);
+ assertEq(x >>> "10.6", 0);
+ assertEq("10.6" >>> x, 5);
+ assertEq(x << "10.6", 1024);
+ assertEq("10.6" << x, 20);
+ assertEq(x | 2147483648, -2147483647);
+ assertEq(2147483648 | x, -2147483647);
+ assertEq(x & 2147483648, 0);
+ assertEq(2147483648 & x, 0);
+ assertEq(x ^ 2147483648, -2147483647);
+ assertEq(2147483648 ^ x, -2147483647);
+ assertEq(x >> 2147483648, 1);
+ assertEq(2147483648 >> x, -1073741824);
+ assertEq(x >>> 2147483648, 1);
+ assertEq(2147483648 >>> x, 1073741824);
+ assertEq(x << 2147483648, 1);
+ assertEq(2147483648 << x, 0);
+ assertEq(x | 4294967296, 1);
+ assertEq(4294967296 | x, 1);
+ assertEq(x & 4294967296, 0);
+ assertEq(4294967296 & x, 0);
+ assertEq(x ^ 4294967296, 1);
+ assertEq(4294967296 ^ x, 1);
+ assertEq(x >> 4294967296, 1);
+ assertEq(4294967296 >> x, 0);
+ assertEq(x >>> 4294967296, 1);
+ assertEq(4294967296 >>> x, 0);
+ assertEq(x << 4294967296, 1);
+ assertEq(4294967296 << x, 0);
+ assertEq(x | undefined, 1);
+ assertEq(undefined | x, 1);
+ assertEq(x & undefined, 0);
+ assertEq(undefined & x, 0);
+ assertEq(x ^ undefined, 1);
+ assertEq(undefined ^ x, 1);
+ assertEq(x >> undefined, 1);
+ assertEq(undefined >> x, 0);
+ assertEq(x >>> undefined, 1);
+ assertEq(undefined >>> x, 0);
+ assertEq(x << undefined, 1);
+ assertEq(undefined << x, 0);
+ assertEq(x | null, 1);
+ assertEq(null | x, 1);
+ assertEq(x & null, 0);
+ assertEq(null & x, 0);
+ assertEq(x ^ null, 1);
+ assertEq(null ^ x, 1);
+ assertEq(x >> null, 1);
+ assertEq(null >> x, 0);
+ assertEq(x >>> null, 1);
+ assertEq(null >>> x, 0);
+ assertEq(x << null, 1);
+ assertEq(null << x, 0);
+ assertEq(x | false, 1);
+ assertEq(false | x, 1);
+ assertEq(x & false, 0);
+ assertEq(false & x, 0);
+ assertEq(x ^ false, 1);
+ assertEq(false ^ x, 1);
+ assertEq(x >> false, 1);
+ assertEq(false >> x, 0);
+ assertEq(x >>> false, 1);
+ assertEq(false >>> x, 0);
+ assertEq(x << false, 1);
+ assertEq(false << x, 0);
+ assertEq(x | true, 1);
+ assertEq(true | x, 1);
+ assertEq(x & true, 1);
+ assertEq(true & x, 1);
+ assertEq(x ^ true, 0);
+ assertEq(true ^ x, 0);
+ assertEq(x >> true, 0);
+ assertEq(true >> x, 0);
+ assertEq(x >>> true, 0);
+ assertEq(true >>> x, 0);
+ assertEq(x << true, 2);
+ assertEq(true << x, 2);
+ assertEq(x | -1.5, -1);
+ assertEq(-1.5 | x, -1);
+ assertEq(x & -1.5, 1);
+ assertEq(-1.5 & x, 1);
+ assertEq(x ^ -1.5, -2);
+ assertEq(-1.5 ^ x, -2);
+ assertEq(x >> -1.5, 0);
+ assertEq(-1.5 >> x, -1);
+ assertEq(x >>> -1.5, 0);
+ assertEq(-1.5 >>> x, 2147483647);
+ assertEq(x << -1.5, -2147483648);
+ assertEq(-1.5 << x, -2);
+}
+test1(1)
+
+function test2 (x) {
+ assertEq(x | -1, -1);
+ assertEq(-1 | x, -1);
+ assertEq(x & -1, 0);
+ assertEq(-1 & x, 0);
+ assertEq(x ^ -1, -1);
+ assertEq(-1 ^ x, -1);
+ assertEq(x >> -1, 0);
+ assertEq(-1 >> x, -1);
+ assertEq(x >>> -1, 0);
+ assertEq(-1 >>> x, 4294967295);
+ assertEq(x << -1, 0);
+ assertEq(-1 << x, -1);
+ assertEq(x | 1, 1);
+ assertEq(1 | x, 1);
+ assertEq(x & 1, 0);
+ assertEq(1 & x, 0);
+ assertEq(x ^ 1, 1);
+ assertEq(1 ^ x, 1);
+ assertEq(x >> 1, 0);
+ assertEq(1 >> x, 1);
+ assertEq(x >>> 1, 0);
+ assertEq(1 >>> x, 1);
+ assertEq(x << 1, 0);
+ assertEq(1 << x, 1);
+ assertEq(x | 0, 0);
+ assertEq(0 | x, 0);
+ assertEq(x & 0, 0);
+ assertEq(0 & x, 0);
+ assertEq(x ^ 0, 0);
+ assertEq(0 ^ x, 0);
+ assertEq(x >> 0, 0);
+ assertEq(0 >> x, 0);
+ assertEq(x >>> 0, 0);
+ assertEq(0 >>> x, 0);
+ assertEq(x << 0, 0);
+ assertEq(0 << x, 0);
+ assertEq(x | 0xffffffff, -1);
+ assertEq(0xffffffff | x, -1);
+ assertEq(x & 0xffffffff, 0);
+ assertEq(0xffffffff & x, 0);
+ assertEq(x ^ 0xffffffff, -1);
+ assertEq(0xffffffff ^ x, -1);
+ assertEq(x >> 0xffffffff, 0);
+ assertEq(0xffffffff >> x, -1);
+ assertEq(x >>> 0xffffffff, 0);
+ assertEq(0xffffffff >>> x, 4294967295);
+ assertEq(x << 0xffffffff, 0);
+ assertEq(0xffffffff << x, -1);
+ assertEq(x | "10.6", 10);
+ assertEq("10.6" | x, 10);
+ assertEq(x & "10.6", 0);
+ assertEq("10.6" & x, 0);
+ assertEq(x ^ "10.6", 10);
+ assertEq("10.6" ^ x, 10);
+ assertEq(x >> "10.6", 0);
+ assertEq("10.6" >> x, 10);
+ assertEq(x >>> "10.6", 0);
+ assertEq("10.6" >>> x, 10);
+ assertEq(x << "10.6", 0);
+ assertEq("10.6" << x, 10);
+ assertEq(x | 2147483648, -2147483648);
+ assertEq(2147483648 | x, -2147483648);
+ assertEq(x & 2147483648, 0);
+ assertEq(2147483648 & x, 0);
+ assertEq(x ^ 2147483648, -2147483648);
+ assertEq(2147483648 ^ x, -2147483648);
+ assertEq(x >> 2147483648, 0);
+ assertEq(2147483648 >> x, -2147483648);
+ assertEq(x >>> 2147483648, 0);
+ assertEq(2147483648 >>> x, 2147483648);
+ assertEq(x << 2147483648, 0);
+ assertEq(2147483648 << x, -2147483648);
+ assertEq(x | 4294967296, 0);
+ assertEq(4294967296 | x, 0);
+ assertEq(x & 4294967296, 0);
+ assertEq(4294967296 & x, 0);
+ assertEq(x ^ 4294967296, 0);
+ assertEq(4294967296 ^ x, 0);
+ assertEq(x >> 4294967296, 0);
+ assertEq(4294967296 >> x, 0);
+ assertEq(x >>> 4294967296, 0);
+ assertEq(4294967296 >>> x, 0);
+ assertEq(x << 4294967296, 0);
+ assertEq(4294967296 << x, 0);
+ assertEq(x | undefined, 0);
+ assertEq(undefined | x, 0);
+ assertEq(x & undefined, 0);
+ assertEq(undefined & x, 0);
+ assertEq(x ^ undefined, 0);
+ assertEq(undefined ^ x, 0);
+ assertEq(x >> undefined, 0);
+ assertEq(undefined >> x, 0);
+ assertEq(x >>> undefined, 0);
+ assertEq(undefined >>> x, 0);
+ assertEq(x << undefined, 0);
+ assertEq(undefined << x, 0);
+ assertEq(x | null, 0);
+ assertEq(null | x, 0);
+ assertEq(x & null, 0);
+ assertEq(null & x, 0);
+ assertEq(x ^ null, 0);
+ assertEq(null ^ x, 0);
+ assertEq(x >> null, 0);
+ assertEq(null >> x, 0);
+ assertEq(x >>> null, 0);
+ assertEq(null >>> x, 0);
+ assertEq(x << null, 0);
+ assertEq(null << x, 0);
+ assertEq(x | false, 0);
+ assertEq(false | x, 0);
+ assertEq(x & false, 0);
+ assertEq(false & x, 0);
+ assertEq(x ^ false, 0);
+ assertEq(false ^ x, 0);
+ assertEq(x >> false, 0);
+ assertEq(false >> x, 0);
+ assertEq(x >>> false, 0);
+ assertEq(false >>> x, 0);
+ assertEq(x << false, 0);
+ assertEq(false << x, 0);
+ assertEq(x | true, 1);
+ assertEq(true | x, 1);
+ assertEq(x & true, 0);
+ assertEq(true & x, 0);
+ assertEq(x ^ true, 1);
+ assertEq(true ^ x, 1);
+ assertEq(x >> true, 0);
+ assertEq(true >> x, 1);
+ assertEq(x >>> true, 0);
+ assertEq(true >>> x, 1);
+ assertEq(x << true, 0);
+ assertEq(true << x, 1);
+ assertEq(x | -1.5, -1);
+ assertEq(-1.5 | x, -1);
+ assertEq(x & -1.5, 0);
+ assertEq(-1.5 & x, 0);
+ assertEq(x ^ -1.5, -1);
+ assertEq(-1.5 ^ x, -1);
+ assertEq(x >> -1.5, 0);
+ assertEq(-1.5 >> x, -1);
+ assertEq(x >>> -1.5, 0);
+ assertEq(-1.5 >>> x, 4294967295);
+ assertEq(x << -1.5, 0);
+ assertEq(-1.5 << x, -1);
+}
+test2(0)
+
+function test3 (x) {
+ assertEq(x | -1, -1);
+ assertEq(-1 | x, -1);
+ assertEq(x & -1, -1);
+ assertEq(-1 & x, -1);
+ assertEq(x ^ -1, 0);
+ assertEq(-1 ^ x, 0);
+ assertEq(x >> -1, -1);
+ assertEq(-1 >> x, -1);
+ assertEq(x >>> -1, 1);
+ assertEq(-1 >>> x, 1);
+ assertEq(x << -1, -2147483648);
+ assertEq(-1 << x, -2147483648);
+ assertEq(x | 1, -1);
+ assertEq(1 | x, -1);
+ assertEq(x & 1, 1);
+ assertEq(1 & x, 1);
+ assertEq(x ^ 1, -2);
+ assertEq(1 ^ x, -2);
+ assertEq(x >> 1, -1);
+ assertEq(1 >> x, 0);
+ assertEq(x >>> 1, 2147483647);
+ assertEq(1 >>> x, 0);
+ assertEq(x << 1, -2);
+ assertEq(1 << x, -2147483648);
+ assertEq(x | 0, -1);
+ assertEq(0 | x, -1);
+ assertEq(x & 0, 0);
+ assertEq(0 & x, 0);
+ assertEq(x ^ 0, -1);
+ assertEq(0 ^ x, -1);
+ assertEq(x >> 0, -1);
+ assertEq(0 >> x, 0);
+ assertEq(x >>> 0, 4294967295);
+ assertEq(0 >>> x, 0);
+ assertEq(x << 0, -1);
+ assertEq(0 << x, 0);
+ assertEq(x | 0xffffffff, -1);
+ assertEq(0xffffffff | x, -1);
+ assertEq(x & 0xffffffff, -1);
+ assertEq(0xffffffff & x, -1);
+ assertEq(x ^ 0xffffffff, 0);
+ assertEq(0xffffffff ^ x, 0);
+ assertEq(x >> 0xffffffff, -1);
+ assertEq(0xffffffff >> x, -1);
+ assertEq(x >>> 0xffffffff, 1);
+ assertEq(0xffffffff >>> x, 1);
+ assertEq(x << 0xffffffff, -2147483648);
+ assertEq(0xffffffff << x, -2147483648);
+ assertEq(x | "10.6", -1);
+ assertEq("10.6" | x, -1);
+ assertEq(x & "10.6", 10);
+ assertEq("10.6" & x, 10);
+ assertEq(x ^ "10.6", -11);
+ assertEq("10.6" ^ x, -11);
+ assertEq(x >> "10.6", -1);
+ assertEq("10.6" >> x, 0);
+ assertEq(x >>> "10.6", 4194303);
+ assertEq("10.6" >>> x, 0);
+ assertEq(x << "10.6", -1024);
+ assertEq("10.6" << x, 0);
+ assertEq(x | 2147483648, -1);
+ assertEq(2147483648 | x, -1);
+ assertEq(x & 2147483648, -2147483648);
+ assertEq(2147483648 & x, -2147483648);
+ assertEq(x ^ 2147483648, 2147483647);
+ assertEq(2147483648 ^ x, 2147483647);
+ assertEq(x >> 2147483648, -1);
+ assertEq(2147483648 >> x, -1);
+ assertEq(x >>> 2147483648, 4294967295);
+ assertEq(2147483648 >>> x, 1);
+ assertEq(x << 2147483648, -1);
+ assertEq(2147483648 << x, 0);
+ assertEq(x | 4294967296, -1);
+ assertEq(4294967296 | x, -1);
+ assertEq(x & 4294967296, 0);
+ assertEq(4294967296 & x, 0);
+ assertEq(x ^ 4294967296, -1);
+ assertEq(4294967296 ^ x, -1);
+ assertEq(x >> 4294967296, -1);
+ assertEq(4294967296 >> x, 0);
+ assertEq(x >>> 4294967296, 4294967295);
+ assertEq(4294967296 >>> x, 0);
+ assertEq(x << 4294967296, -1);
+ assertEq(4294967296 << x, 0);
+ assertEq(x | undefined, -1);
+ assertEq(undefined | x, -1);
+ assertEq(x & undefined, 0);
+ assertEq(undefined & x, 0);
+ assertEq(x ^ undefined, -1);
+ assertEq(undefined ^ x, -1);
+ assertEq(x >> undefined, -1);
+ assertEq(undefined >> x, 0);
+ assertEq(x >>> undefined, 4294967295);
+ assertEq(undefined >>> x, 0);
+ assertEq(x << undefined, -1);
+ assertEq(undefined << x, 0);
+ assertEq(x | null, -1);
+ assertEq(null | x, -1);
+ assertEq(x & null, 0);
+ assertEq(null & x, 0);
+ assertEq(x ^ null, -1);
+ assertEq(null ^ x, -1);
+ assertEq(x >> null, -1);
+ assertEq(null >> x, 0);
+ assertEq(x >>> null, 4294967295);
+ assertEq(null >>> x, 0);
+ assertEq(x << null, -1);
+ assertEq(null << x, 0);
+ assertEq(x | false, -1);
+ assertEq(false | x, -1);
+ assertEq(x & false, 0);
+ assertEq(false & x, 0);
+ assertEq(x ^ false, -1);
+ assertEq(false ^ x, -1);
+ assertEq(x >> false, -1);
+ assertEq(false >> x, 0);
+ assertEq(x >>> false, 4294967295);
+ assertEq(false >>> x, 0);
+ assertEq(x << false, -1);
+ assertEq(false << x, 0);
+ assertEq(x | true, -1);
+ assertEq(true | x, -1);
+ assertEq(x & true, 1);
+ assertEq(true & x, 1);
+ assertEq(x ^ true, -2);
+ assertEq(true ^ x, -2);
+ assertEq(x >> true, -1);
+ assertEq(true >> x, 0);
+ assertEq(x >>> true, 2147483647);
+ assertEq(true >>> x, 0);
+ assertEq(x << true, -2);
+ assertEq(true << x, -2147483648);
+ assertEq(x | -1.5, -1);
+ assertEq(-1.5 | x, -1);
+ assertEq(x & -1.5, -1);
+ assertEq(-1.5 & x, -1);
+ assertEq(x ^ -1.5, 0);
+ assertEq(-1.5 ^ x, 0);
+ assertEq(x >> -1.5, -1);
+ assertEq(-1.5 >> x, -1);
+ assertEq(x >>> -1.5, 1);
+ assertEq(-1.5 >>> x, 1);
+ assertEq(x << -1.5, -2147483648);
+ assertEq(-1.5 << x, -2147483648);
+}
+test3(-1)
+
+function test4 (x) {
+ assertEq(x | -1, -1);
+ assertEq(-1 | x, -1);
+ assertEq(x & -1, -2147483648);
+ assertEq(-1 & x, -2147483648);
+ assertEq(x ^ -1, 2147483647);
+ assertEq(-1 ^ x, 2147483647);
+ assertEq(x >> -1, -1);
+ assertEq(-1 >> x, -1);
+ assertEq(x >>> -1, 1);
+ assertEq(-1 >>> x, 4294967295);
+ assertEq(x << -1, 0);
+ assertEq(-1 << x, -1);
+ assertEq(x | 1, -2147483647);
+ assertEq(1 | x, -2147483647);
+ assertEq(x & 1, 0);
+ assertEq(1 & x, 0);
+ assertEq(x ^ 1, -2147483647);
+ assertEq(1 ^ x, -2147483647);
+ assertEq(x >> 1, -1073741824);
+ assertEq(1 >> x, 1);
+ assertEq(x >>> 1, 1073741824);
+ assertEq(1 >>> x, 1);
+ assertEq(x << 1, 0);
+ assertEq(1 << x, 1);
+ assertEq(x | 0, -2147483648);
+ assertEq(0 | x, -2147483648);
+ assertEq(x & 0, 0);
+ assertEq(0 & x, 0);
+ assertEq(x ^ 0, -2147483648);
+ assertEq(0 ^ x, -2147483648);
+ assertEq(x >> 0, -2147483648);
+ assertEq(0 >> x, 0);
+ assertEq(x >>> 0, 2147483648);
+ assertEq(0 >>> x, 0);
+ assertEq(x << 0, -2147483648);
+ assertEq(0 << x, 0);
+ assertEq(x | 0xffffffff, -1);
+ assertEq(0xffffffff | x, -1);
+ assertEq(x & 0xffffffff, -2147483648);
+ assertEq(0xffffffff & x, -2147483648);
+ assertEq(x ^ 0xffffffff, 2147483647);
+ assertEq(0xffffffff ^ x, 2147483647);
+ assertEq(x >> 0xffffffff, -1);
+ assertEq(0xffffffff >> x, -1);
+ assertEq(x >>> 0xffffffff, 1);
+ assertEq(0xffffffff >>> x, 4294967295);
+ assertEq(x << 0xffffffff, 0);
+ assertEq(0xffffffff << x, -1);
+ assertEq(x | "10.6", -2147483638);
+ assertEq("10.6" | x, -2147483638);
+ assertEq(x & "10.6", 0);
+ assertEq("10.6" & x, 0);
+ assertEq(x ^ "10.6", -2147483638);
+ assertEq("10.6" ^ x, -2147483638);
+ assertEq(x >> "10.6", -2097152);
+ assertEq("10.6" >> x, 10);
+ assertEq(x >>> "10.6", 2097152);
+ assertEq("10.6" >>> x, 10);
+ assertEq(x << "10.6", 0);
+ assertEq("10.6" << x, 10);
+ assertEq(x | 2147483648, -2147483648);
+ assertEq(2147483648 | x, -2147483648);
+ assertEq(x & 2147483648, -2147483648);
+ assertEq(2147483648 & x, -2147483648);
+ assertEq(x ^ 2147483648, 0);
+ assertEq(2147483648 ^ x, 0);
+ assertEq(x >> 2147483648, -2147483648);
+ assertEq(2147483648 >> x, -2147483648);
+ assertEq(x >>> 2147483648, 2147483648);
+ assertEq(2147483648 >>> x, 2147483648);
+ assertEq(x << 2147483648, -2147483648);
+ assertEq(2147483648 << x, -2147483648);
+ assertEq(x | 4294967296, -2147483648);
+ assertEq(4294967296 | x, -2147483648);
+ assertEq(x & 4294967296, 0);
+ assertEq(4294967296 & x, 0);
+ assertEq(x ^ 4294967296, -2147483648);
+ assertEq(4294967296 ^ x, -2147483648);
+ assertEq(x >> 4294967296, -2147483648);
+ assertEq(4294967296 >> x, 0);
+ assertEq(x >>> 4294967296, 2147483648);
+ assertEq(4294967296 >>> x, 0);
+ assertEq(x << 4294967296, -2147483648);
+ assertEq(4294967296 << x, 0);
+ assertEq(x | undefined, -2147483648);
+ assertEq(undefined | x, -2147483648);
+ assertEq(x & undefined, 0);
+ assertEq(undefined & x, 0);
+ assertEq(x ^ undefined, -2147483648);
+ assertEq(undefined ^ x, -2147483648);
+ assertEq(x >> undefined, -2147483648);
+ assertEq(undefined >> x, 0);
+ assertEq(x >>> undefined, 2147483648);
+ assertEq(undefined >>> x, 0);
+ assertEq(x << undefined, -2147483648);
+ assertEq(undefined << x, 0);
+ assertEq(x | null, -2147483648);
+ assertEq(null | x, -2147483648);
+ assertEq(x & null, 0);
+ assertEq(null & x, 0);
+ assertEq(x ^ null, -2147483648);
+ assertEq(null ^ x, -2147483648);
+ assertEq(x >> null, -2147483648);
+ assertEq(null >> x, 0);
+ assertEq(x >>> null, 2147483648);
+ assertEq(null >>> x, 0);
+ assertEq(x << null, -2147483648);
+ assertEq(null << x, 0);
+ assertEq(x | false, -2147483648);
+ assertEq(false | x, -2147483648);
+ assertEq(x & false, 0);
+ assertEq(false & x, 0);
+ assertEq(x ^ false, -2147483648);
+ assertEq(false ^ x, -2147483648);
+ assertEq(x >> false, -2147483648);
+ assertEq(false >> x, 0);
+ assertEq(x >>> false, 2147483648);
+ assertEq(false >>> x, 0);
+ assertEq(x << false, -2147483648);
+ assertEq(false << x, 0);
+ assertEq(x | true, -2147483647);
+ assertEq(true | x, -2147483647);
+ assertEq(x & true, 0);
+ assertEq(true & x, 0);
+ assertEq(x ^ true, -2147483647);
+ assertEq(true ^ x, -2147483647);
+ assertEq(x >> true, -1073741824);
+ assertEq(true >> x, 1);
+ assertEq(x >>> true, 1073741824);
+ assertEq(true >>> x, 1);
+ assertEq(x << true, 0);
+ assertEq(true << x, 1);
+ assertEq(x | -1.5, -1);
+ assertEq(-1.5 | x, -1);
+ assertEq(x & -1.5, -2147483648);
+ assertEq(-1.5 & x, -2147483648);
+ assertEq(x ^ -1.5, 2147483647);
+ assertEq(-1.5 ^ x, 2147483647);
+ assertEq(x >> -1.5, -1);
+ assertEq(-1.5 >> x, -1);
+ assertEq(x >>> -1.5, 1);
+ assertEq(-1.5 >>> x, 4294967295);
+ assertEq(x << -1.5, 0);
+ assertEq(-1.5 << x, -1);
+}
+test4(2147483648)
+
+function test5 (x) {
+ assertEq(x | -1, -1);
+ assertEq(-1 | x, -1);
+ assertEq(x & -1, -2147483648);
+ assertEq(-1 & x, -2147483648);
+ assertEq(x ^ -1, 2147483647);
+ assertEq(-1 ^ x, 2147483647);
+ assertEq(x >> -1, -1);
+ assertEq(-1 >> x, -1);
+ assertEq(x >>> -1, 1);
+ assertEq(-1 >>> x, 4294967295);
+ assertEq(x << -1, 0);
+ assertEq(-1 << x, -1);
+ assertEq(x | 1, -2147483647);
+ assertEq(1 | x, -2147483647);
+ assertEq(x & 1, 0);
+ assertEq(1 & x, 0);
+ assertEq(x ^ 1, -2147483647);
+ assertEq(1 ^ x, -2147483647);
+ assertEq(x >> 1, -1073741824);
+ assertEq(1 >> x, 1);
+ assertEq(x >>> 1, 1073741824);
+ assertEq(1 >>> x, 1);
+ assertEq(x << 1, 0);
+ assertEq(1 << x, 1);
+ assertEq(x | 0, -2147483648);
+ assertEq(0 | x, -2147483648);
+ assertEq(x & 0, 0);
+ assertEq(0 & x, 0);
+ assertEq(x ^ 0, -2147483648);
+ assertEq(0 ^ x, -2147483648);
+ assertEq(x >> 0, -2147483648);
+ assertEq(0 >> x, 0);
+ assertEq(x >>> 0, 2147483648);
+ assertEq(0 >>> x, 0);
+ assertEq(x << 0, -2147483648);
+ assertEq(0 << x, 0);
+ assertEq(x | 0xffffffff, -1);
+ assertEq(0xffffffff | x, -1);
+ assertEq(x & 0xffffffff, -2147483648);
+ assertEq(0xffffffff & x, -2147483648);
+ assertEq(x ^ 0xffffffff, 2147483647);
+ assertEq(0xffffffff ^ x, 2147483647);
+ assertEq(x >> 0xffffffff, -1);
+ assertEq(0xffffffff >> x, -1);
+ assertEq(x >>> 0xffffffff, 1);
+ assertEq(0xffffffff >>> x, 4294967295);
+ assertEq(x << 0xffffffff, 0);
+ assertEq(0xffffffff << x, -1);
+ assertEq(x | "10.6", -2147483638);
+ assertEq("10.6" | x, -2147483638);
+ assertEq(x & "10.6", 0);
+ assertEq("10.6" & x, 0);
+ assertEq(x ^ "10.6", -2147483638);
+ assertEq("10.6" ^ x, -2147483638);
+ assertEq(x >> "10.6", -2097152);
+ assertEq("10.6" >> x, 10);
+ assertEq(x >>> "10.6", 2097152);
+ assertEq("10.6" >>> x, 10);
+ assertEq(x << "10.6", 0);
+ assertEq("10.6" << x, 10);
+ assertEq(x | 2147483648, -2147483648);
+ assertEq(2147483648 | x, -2147483648);
+ assertEq(x & 2147483648, -2147483648);
+ assertEq(2147483648 & x, -2147483648);
+ assertEq(x ^ 2147483648, 0);
+ assertEq(2147483648 ^ x, 0);
+ assertEq(x >> 2147483648, -2147483648);
+ assertEq(2147483648 >> x, -2147483648);
+ assertEq(x >>> 2147483648, 2147483648);
+ assertEq(2147483648 >>> x, 2147483648);
+ assertEq(x << 2147483648, -2147483648);
+ assertEq(2147483648 << x, -2147483648);
+ assertEq(x | 4294967296, -2147483648);
+ assertEq(4294967296 | x, -2147483648);
+ assertEq(x & 4294967296, 0);
+ assertEq(4294967296 & x, 0);
+ assertEq(x ^ 4294967296, -2147483648);
+ assertEq(4294967296 ^ x, -2147483648);
+ assertEq(x >> 4294967296, -2147483648);
+ assertEq(4294967296 >> x, 0);
+ assertEq(x >>> 4294967296, 2147483648);
+ assertEq(4294967296 >>> x, 0);
+ assertEq(x << 4294967296, -2147483648);
+ assertEq(4294967296 << x, 0);
+ assertEq(x | undefined, -2147483648);
+ assertEq(undefined | x, -2147483648);
+ assertEq(x & undefined, 0);
+ assertEq(undefined & x, 0);
+ assertEq(x ^ undefined, -2147483648);
+ assertEq(undefined ^ x, -2147483648);
+ assertEq(x >> undefined, -2147483648);
+ assertEq(undefined >> x, 0);
+ assertEq(x >>> undefined, 2147483648);
+ assertEq(undefined >>> x, 0);
+ assertEq(x << undefined, -2147483648);
+ assertEq(undefined << x, 0);
+ assertEq(x | null, -2147483648);
+ assertEq(null | x, -2147483648);
+ assertEq(x & null, 0);
+ assertEq(null & x, 0);
+ assertEq(x ^ null, -2147483648);
+ assertEq(null ^ x, -2147483648);
+ assertEq(x >> null, -2147483648);
+ assertEq(null >> x, 0);
+ assertEq(x >>> null, 2147483648);
+ assertEq(null >>> x, 0);
+ assertEq(x << null, -2147483648);
+ assertEq(null << x, 0);
+ assertEq(x | false, -2147483648);
+ assertEq(false | x, -2147483648);
+ assertEq(x & false, 0);
+ assertEq(false & x, 0);
+ assertEq(x ^ false, -2147483648);
+ assertEq(false ^ x, -2147483648);
+ assertEq(x >> false, -2147483648);
+ assertEq(false >> x, 0);
+ assertEq(x >>> false, 2147483648);
+ assertEq(false >>> x, 0);
+ assertEq(x << false, -2147483648);
+ assertEq(false << x, 0);
+ assertEq(x | true, -2147483647);
+ assertEq(true | x, -2147483647);
+ assertEq(x & true, 0);
+ assertEq(true & x, 0);
+ assertEq(x ^ true, -2147483647);
+ assertEq(true ^ x, -2147483647);
+ assertEq(x >> true, -1073741824);
+ assertEq(true >> x, 1);
+ assertEq(x >>> true, 1073741824);
+ assertEq(true >>> x, 1);
+ assertEq(x << true, 0);
+ assertEq(true << x, 1);
+ assertEq(x | -1.5, -1);
+ assertEq(-1.5 | x, -1);
+ assertEq(x & -1.5, -2147483648);
+ assertEq(-1.5 & x, -2147483648);
+ assertEq(x ^ -1.5, 2147483647);
+ assertEq(-1.5 ^ x, 2147483647);
+ assertEq(x >> -1.5, -1);
+ assertEq(-1.5 >> x, -1);
+ assertEq(x >>> -1.5, 1);
+ assertEq(-1.5 >>> x, 4294967295);
+ assertEq(x << -1.5, 0);
+ assertEq(-1.5 << x, -1);
+}
+test5(-2147483648)
+
+
diff --git a/js/src/jit-test/tests/basic/testBitwise.js b/js/src/jit-test/tests/basic/testBitwise.js new file mode 100644 index 0000000000..5d940a556b --- /dev/null +++ b/js/src/jit-test/tests/basic/testBitwise.js @@ -0,0 +1,12 @@ +function testBitwise() { + var x = 10000; + var y = 123456; + var z = 987234; + for (var i = 0; i < 50; i++) { + x = x ^ y; + y = y | z; + z = ~x; + } + return x + y + z; +} +assertEq(testBitwise(), -1298); diff --git a/js/src/jit-test/tests/basic/testBoolToString.js b/js/src/jit-test/tests/basic/testBoolToString.js new file mode 100644 index 0000000000..9eeb40c5d5 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBoolToString.js @@ -0,0 +1,3 @@ +// |jit-test| error: TypeError; +var bts = true.toString; +bts(); diff --git a/js/src/jit-test/tests/basic/testBoxDoubleWithDoubleSizedInt.js b/js/src/jit-test/tests/basic/testBoxDoubleWithDoubleSizedInt.js new file mode 100644 index 0000000000..5327e56e5f --- /dev/null +++ b/js/src/jit-test/tests/basic/testBoxDoubleWithDoubleSizedInt.js @@ -0,0 +1,10 @@ +function testBoxDoubleWithDoubleSizedInt() +{ + var i = 0; + var a = new Array(3); + + while (i < a.length) + a[i++] = 0x5a827999; + return a.join(","); +} +assertEq(testBoxDoubleWithDoubleSizedInt(), "1518500249,1518500249,1518500249"); diff --git a/js/src/jit-test/tests/basic/testBranchCse.js b/js/src/jit-test/tests/basic/testBranchCse.js new file mode 100644 index 0000000000..1c99658171 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBranchCse.js @@ -0,0 +1,7 @@ +function testBranchCse() { + empty = []; + out = []; + for (var j=0;j<10;++j) { empty[42]; out.push((1 * (1)) | ""); } + return out.join(","); +} +assertEq(testBranchCse(), "1,1,1,1,1,1,1,1,1,1"); diff --git a/js/src/jit-test/tests/basic/testBranchingLoop.js b/js/src/jit-test/tests/basic/testBranchingLoop.js new file mode 100644 index 0000000000..5c302425fe --- /dev/null +++ b/js/src/jit-test/tests/basic/testBranchingLoop.js @@ -0,0 +1,11 @@ +function testBranchingLoop() { + var x = 0; + for (var i=0; i < 100; ++i) { + if (i == 51) { + x += 10; + } + x++; + } + return x; +} +assertEq(testBranchingLoop(), 110); diff --git a/js/src/jit-test/tests/basic/testBranchingUnstableLoop.js b/js/src/jit-test/tests/basic/testBranchingUnstableLoop.js new file mode 100644 index 0000000000..f8333ecff8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBranchingUnstableLoop.js @@ -0,0 +1,11 @@ +function testBranchingUnstableLoop() { + var x = 0; + for (var i=0; i < 100; ++i) { + if (i == 51) { + x += 10.1; + } + x++; + } + return x; +} +assertEq(testBranchingUnstableLoop(), 110.1); diff --git a/js/src/jit-test/tests/basic/testBranchingUnstableLoopCounter.js b/js/src/jit-test/tests/basic/testBranchingUnstableLoopCounter.js new file mode 100644 index 0000000000..53fff9e087 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBranchingUnstableLoopCounter.js @@ -0,0 +1,11 @@ +function testBranchingUnstableLoopCounter() { + var x = 0; + for (var i=0; i < 100; ++i) { + if (i == 51) { + i += 1.1; + } + x++; + } + return x; +} +assertEq(testBranchingUnstableLoopCounter(), 99); diff --git a/js/src/jit-test/tests/basic/testBranchingUnstableObject.js b/js/src/jit-test/tests/basic/testBranchingUnstableObject.js new file mode 100644 index 0000000000..338ae73c0b --- /dev/null +++ b/js/src/jit-test/tests/basic/testBranchingUnstableObject.js @@ -0,0 +1,13 @@ +function testBranchingUnstableObject() { + var x = {s: "a"}; + var t = ""; + for (var i=0; i < 100; ++i) { + if (i == 51) + { + x.s = 5; + } + t += x.s; + } + return t.length; +} +assertEq(testBranchingUnstableObject(), 100); diff --git a/js/src/jit-test/tests/basic/testBug1126754.js b/js/src/jit-test/tests/basic/testBug1126754.js new file mode 100644 index 0000000000..70f27c29ef --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug1126754.js @@ -0,0 +1,9 @@ +// |jit-test| error:SyntaxError + +(function() { + with ({}) {} + function f() { + ({ *h(){} }) + } + function f +})() diff --git a/js/src/jit-test/tests/basic/testBug1235874.js b/js/src/jit-test/tests/basic/testBug1235874.js new file mode 100644 index 0000000000..8e78410814 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug1235874.js @@ -0,0 +1 @@ +evaluate('evalcx("1")', { fileName: null }); diff --git a/js/src/jit-test/tests/basic/testBug1827733.js b/js/src/jit-test/tests/basic/testBug1827733.js new file mode 100644 index 0000000000..3e35bfe597 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug1827733.js @@ -0,0 +1,9 @@ +function test(a, b) { + return a + b; +} + +try { + disnative(test); +} catch (err) { + assertEq(err.message, "The function hasn't been warmed up, hence no JIT code to disassemble."); +}
\ No newline at end of file diff --git a/js/src/jit-test/tests/basic/testBug458838.js b/js/src/jit-test/tests/basic/testBug458838.js new file mode 100644 index 0000000000..59b55a50c9 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug458838.js @@ -0,0 +1,14 @@ +var escape; +function testBug458838() { + var a = 1; + function g() { + var b = 0 + for (var i = 0; i < 10; ++i) { + b += a; + } + return b; + } + + return g(); +} +assertEq(testBug458838(), 10); diff --git a/js/src/jit-test/tests/basic/testBug463490.js b/js/src/jit-test/tests/basic/testBug463490.js new file mode 100644 index 0000000000..730879ead7 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug463490.js @@ -0,0 +1,18 @@ +//test no multitrees assert +function testBug463490() { + function f(a, b, d) { + for (var i = 0; i < 10; i++) { + if (d) + b /= 2; + } + return a + b; + } + //integer stable loop + f(2, 2, false); + //double stable loop + f(3, 4.5, false); + //integer unstable branch + f(2, 2, true); + return true; +}; +assertEq(testBug463490(), true); diff --git a/js/src/jit-test/tests/basic/testBug465272.js b/js/src/jit-test/tests/basic/testBug465272.js new file mode 100644 index 0000000000..88a8f064f7 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug465272.js @@ -0,0 +1,6 @@ +function testBug465272() { + var a = new Array(5); + for (j=0;j<5;++j) a[j] = "" + ((5) - 2); + return a.join(","); +} +assertEq(testBug465272(), "3,3,3,3,3"); diff --git a/js/src/jit-test/tests/basic/testBug465688.js b/js/src/jit-test/tests/basic/testBug465688.js new file mode 100644 index 0000000000..40cdde52b9 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug465688.js @@ -0,0 +1,6 @@ +//test no assert +function testBug465688() { + for (let d of [-0x80000000, -0x80000000]) - -d; + return true; +} +assertEq(testBug465688(), true); diff --git a/js/src/jit-test/tests/basic/testBug466262.js b/js/src/jit-test/tests/basic/testBug466262.js new file mode 100644 index 0000000000..450d095030 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug466262.js @@ -0,0 +1,11 @@ +//test no assert +function testBug466262() { + var e = 1; + for (var d = 0; d < 3; ++d) { + if (d == 2) { + e = ""; + } + } + return true; +} +assertEq(testBug466262(), true); diff --git a/js/src/jit-test/tests/basic/testBug501690.js b/js/src/jit-test/tests/basic/testBug501690.js new file mode 100644 index 0000000000..9fa65b6c24 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug501690.js @@ -0,0 +1,14 @@ +function testBug501690() { + // Property cache assertion when 3 objects along a prototype chain have the same shape. + function B(){} + B.prototype = {x: 123}; + + function D(){} + D.prototype = new B; + D.prototype.x = 1; // [1] shapeOf(B.prototype) == shapeOf(D.prototype) + + arr = [new D, new D, new D, D.prototype]; // [2] all the same shape + for (var i = 0; i < 4; i++) + assertEq(arr[i].x, 1); // same kshape [2], same vshape [1] +} +testBug501690(); diff --git a/js/src/jit-test/tests/basic/testBug502914.js b/js/src/jit-test/tests/basic/testBug502914.js new file mode 100644 index 0000000000..d01ee9786e --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug502914.js @@ -0,0 +1,19 @@ +function testBug502914() { + // Assigning a non-function to a function-valued property on trace should + // bump the shape. + function f1() {} + function C() {} + var x = C.prototype = {m: f1}; + x.m(); // brand scope + var arr = [new C, new C, new C, x]; + try { + for (var i = 0; i < 4; i++) { + arr[i].m = 12; + x.m(); // should throw last time through + } + } catch (exc) { + return exc.constructor.name; + } + return "no exception"; +} +assertEq(testBug502914(), "TypeError"); diff --git a/js/src/jit-test/tests/basic/testBug504520.js b/js/src/jit-test/tests/basic/testBug504520.js new file mode 100644 index 0000000000..ba5f767640 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug504520.js @@ -0,0 +1,11 @@ +function testBug504520() { + // A bug involving comparisons. + var arr = [1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 0]; + assertEq(arr.length > 9, true); + + var s = ''; + for (var i = 0; i < arr.length; i++) + arr[i] >= 1/0 ? null : (s += i); + assertEq(s, '9'); +} +testBug504520(); diff --git a/js/src/jit-test/tests/basic/testBug504520Harder.js b/js/src/jit-test/tests/basic/testBug504520Harder.js new file mode 100644 index 0000000000..9a08193195 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug504520Harder.js @@ -0,0 +1,33 @@ +function testBug504520Harder() { + // test 1024 similar cases + var vals = [1/0, -1/0, 0, 0/0]; + var ops = ["===", "!==", "==", "!=", "<", ">", "<=", ">="]; + for (var x of vals) { + for (var y of vals) { + for (var op of ops) { + for (var z of vals) { + // Assume eval is correct. This depends on the global + // Infinity property not having been reassigned. + var xz = eval(x + op + z); + var yz = eval(y + op + z); + + var arr = [x, x, x, x, x, x, x, x, x, y]; + assertEq(arr.length > 9, true); + var expected = [xz, xz, xz, xz, xz, xz, xz, xz, xz, yz]; + + // ?: looks superfluous but that's what we're testing here + var fun = eval( + '(function (arr, results) {\n' + + ' for (let i = 0; i < arr.length; i++)\n' + + ' results.push(arr[i]' + op + z + ' ? "true" : "false");\n' + + '});\n'); + var actual = []; + fun(arr, actual); + print(x, y, op, z); + assertEq("" + actual, "" + expected); + } + } + } + } +} +testBug504520Harder(); diff --git a/js/src/jit-test/tests/basic/testBug507425.js b/js/src/jit-test/tests/basic/testBug507425.js new file mode 100644 index 0000000000..616bababde --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug507425.js @@ -0,0 +1,14 @@ +// |jit-test| allow-oom; +function testBug507425() { + var r = /x/; + for (var i = 0; i < 3; i++) + r.lastIndex = 0; // call a setter + var s = ';'; + try { + for (i = 0; i < 80; i++) + s += s; // call js_CanLeaveTrace + } catch (exc) { + return "ok"; + } +} +assertEq(testBug507425(), "ok"); diff --git a/js/src/jit-test/tests/basic/testBug520503-1.js b/js/src/jit-test/tests/basic/testBug520503-1.js new file mode 100644 index 0000000000..a3730e5a34 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug520503-1.js @@ -0,0 +1,3 @@ +(new Function("for (var j=0; j<9; ++j) { (function sum_indexing(array,start){return array.length==start ? 0 : array[start]+ sum_indexing(array,start+1)})([true,true,undefined],0)}"))() + +/* Should not have crashed. */ diff --git a/js/src/jit-test/tests/basic/testBug520503-3.js b/js/src/jit-test/tests/basic/testBug520503-3.js new file mode 100644 index 0000000000..1385af09a9 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug520503-3.js @@ -0,0 +1,6 @@ +(Function("for (var a = 0; a < 6; a++) {\ + (function sum_indexing(b, c) {\ + return b.length == c ? 0 : b[c] + sum_indexing(b, c + 1)\ + })([(void 0), Infinity, Infinity], 0)\ +}"))() + diff --git a/js/src/jit-test/tests/basic/testBug529147.js b/js/src/jit-test/tests/basic/testBug529147.js new file mode 100644 index 0000000000..8b700879d8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug529147.js @@ -0,0 +1,22 @@ +var magicNumbers = [1, -1, 0, 0]; +var magicIndex = 0; + +var sum = 0; + +function foo(n) { + for (var i = 0; i < n; ++i) { + sum += 10; + bar(); + } +} + +function bar() { + var q = magicNumbers[magicIndex++]; + if (q != -1) { + sum += 1; + foo(q); + } +} + +foo(3); +assertEq(sum, 43); diff --git a/js/src/jit-test/tests/basic/testBug547791.js b/js/src/jit-test/tests/basic/testBug547791.js new file mode 100644 index 0000000000..2d4482eb51 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug547791.js @@ -0,0 +1,21 @@ + +function Bext(k) { + if (k > 0) { + let i = k + 1; + if (k == 10) { + function x () { i = 2; } + } + Bext(i - 2); + Bext(i - 2); + } + return 0; +} + +function f() { + Bext(12); +} + +f(); + +/* Don't assert. */ + diff --git a/js/src/jit-test/tests/basic/testBug550210.js b/js/src/jit-test/tests/basic/testBug550210.js new file mode 100644 index 0000000000..1e722bd14f --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug550210.js @@ -0,0 +1,16 @@ +function g(e) { + return ("" + e); +} + +function* blah() { + do { + yield; + } while ({}(p = arguments)); +} +rv = blah(); +try { + for (a of rv) ; +} catch (e) { + print("" + g(e)); +} +gc(); diff --git a/js/src/jit-test/tests/basic/testBug552248.js b/js/src/jit-test/tests/basic/testBug552248.js new file mode 100644 index 0000000000..ec310d158b --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug552248.js @@ -0,0 +1,37 @@ +load(libdir + "evalInFrame.js"); + +var a = new Array(); + +function i(save) { + var x = 9; + evalInFrame(0, "a.push(x)", save); + evalInFrame(1, "a.push(z)", save); + evalInFrame(2, "a.push(z)", save); + evalInFrame(3, "a.push(y)", save); + evalInFrame(4, "a.push(x)", save); +} + +function h() { + var z = 5; + evalInFrame(0, "a.push(z)"); + evalInFrame(1, "a.push(y)"); + evalInFrame(2, "a.push(x)"); + evalInFrame(0, "i(false)"); + evalInFrame(0, "a.push(z)", true); + evalInFrame(1, "a.push(y)", true); + evalInFrame(2, "a.push(x)", true); + evalInFrame(0, "i(true)", true); +} + +function g() { + var y = 4; + h(); +} + +function f() { + var x = 3; + g(); +} + +f(); +assertEq(a+'', [5, 4, 3, 9, 5, 5, 4, 3, 5, 4, 3, 9, 5, 5, 4, 3]+''); diff --git a/js/src/jit-test/tests/basic/testBug554043.js b/js/src/jit-test/tests/basic/testBug554043.js new file mode 100644 index 0000000000..a0071aeb80 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug554043.js @@ -0,0 +1,6 @@ +(function () { + for (var a = 0; a < 5; a++) { + print(-false) + assertEq(-false, -0.0); + } +})() diff --git a/js/src/jit-test/tests/basic/testBug555484.js b/js/src/jit-test/tests/basic/testBug555484.js new file mode 100644 index 0000000000..f15f2b268a --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug555484.js @@ -0,0 +1,8 @@ +var result = ""; +o = { valueOf:function(){ throw "cow" } }; +try { + String.fromCharCode(o); +} catch (e) { + result = e.toString(); +} +assertEq(result, "cow"); diff --git a/js/src/jit-test/tests/basic/testBug558446.js b/js/src/jit-test/tests/basic/testBug558446.js new file mode 100644 index 0000000000..8560de0947 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug558446.js @@ -0,0 +1,10 @@ +function f(a, b) { return a + " " + b; } + +for (var i = 0; i < 10; ++i) { + var s = ''; + var a = {toString: function () { s += 'a'; return 'a'; }}; + var b = {toString: function () { s += 'b'; return 'b'; }}; + f(a, b); + assertEq(s, 'ab'); +} + diff --git a/js/src/jit-test/tests/basic/testBug579602.js b/js/src/jit-test/tests/basic/testBug579602.js new file mode 100644 index 0000000000..3ad40a64ad --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug579602.js @@ -0,0 +1,21 @@ +// don't panic + +f = function*() { + x = yield +} +rv = f() +for (a of rv) (function() {}) +x = new Proxy({}, (function() { + return { + defineProperty: gc + } +})()); +with({ + d: (({ + x: Object.defineProperty(x, "", ({ + set: Array.e + })) + })) +}) {} + +// don't crash diff --git a/js/src/jit-test/tests/basic/testBug582766.js b/js/src/jit-test/tests/basic/testBug582766.js new file mode 100644 index 0000000000..cfcafbed08 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug582766.js @@ -0,0 +1,18 @@ +expected = 4; + +var fourth = { nextSibling: null }; +var third = { nextSibling: fourth }; +var second = { nextSibling: third }; +var first = { nextSibling: second }; + +function f() { + let loopcount = 0; + for (let node = first; node; node = node.nextSibling) { + loopcount++; + } + return loopcount; +} + +actual = f(); + +assertEq(actual, expected); diff --git a/js/src/jit-test/tests/basic/testBug586866.js b/js/src/jit-test/tests/basic/testBug586866.js new file mode 100644 index 0000000000..425bf2b782 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug586866.js @@ -0,0 +1,16 @@ +var magic = 8; + +var obj = {}; +for (var i = 1; i <= magic; ++i) + obj[i] = "a"; + +function func() { + var i = 1; + while (i in obj) { + ++i; + } + return i - 1; +} +assertEq(func(), magic); +assertEq(func(), magic); +assertEq(func(), magic); diff --git a/js/src/jit-test/tests/basic/testBug593559.js b/js/src/jit-test/tests/basic/testBug593559.js new file mode 100644 index 0000000000..d9445c8b2f --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug593559.js @@ -0,0 +1,9 @@ +var gen = (function* () {yield})(); +var t = gen.throw; +try { + new t; +} catch (e) { + actual = e; +} +assertEq(actual.name, "TypeError"); +assertEq(/is not a constructor/.test(actual.message), true); diff --git a/js/src/jit-test/tests/basic/testBug602413.js b/js/src/jit-test/tests/basic/testBug602413.js new file mode 100644 index 0000000000..eeef15cbee --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug602413.js @@ -0,0 +1,45 @@ +var so = []; + +function U(unusedV) +{ + for (var i = 0; i < so.length; ++i) + return false; + so.push(0); +} + +function C(v) +{ + if (typeof v == "object" || typeof v == "function") { + for (var i = 0; i < 10; ++i) {} + U(v); + } +} + +function exploreProperties(obj) +{ + var props = []; + for (var o = obj; o; o = Object.getPrototypeOf(o)) { + props = props.concat(Object.getOwnPropertyNames(o)); + } + for (var i = 0; i < props.length; ++i) { + var p = props[i]; + try { + var v = obj[p]; + C(v); + } catch(e) { } + } +} + +function boom() +{ + var a = []; + var b = function(){}; + var c = [{}]; + exploreProperties(a); + exploreProperties(b); + exploreProperties(c); + exploreProperties(c); +} + +boom(); + diff --git a/js/src/jit-test/tests/basic/testBug604210.js b/js/src/jit-test/tests/basic/testBug604210.js new file mode 100644 index 0000000000..146eaf1801 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug604210.js @@ -0,0 +1,11 @@ +function f() { + var ex; + try { + var x = undefined; + print(x.foo); + } catch (e) { + ex = e; + } + assertEq(/(x is|"foo" of) undefined/.test(ex.message), true); +} +f(); diff --git a/js/src/jit-test/tests/basic/testBug606138.js b/js/src/jit-test/tests/basic/testBug606138.js new file mode 100644 index 0000000000..141bf25345 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug606138.js @@ -0,0 +1,3 @@ +// The proxy is going to mutate thisv in place. InvokeSessionGuard should be +// cool with that +with(evalcx(''))[7, 8].map((n) => new Int16Array(n), []) diff --git a/js/src/jit-test/tests/basic/testBug607659.js b/js/src/jit-test/tests/basic/testBug607659.js new file mode 100644 index 0000000000..edfda935c3 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug607659.js @@ -0,0 +1,8 @@ +var g = 0; +Object.defineProperty(RegExp.prototype, 'test', { get:function() { ++g } }); +function f() { + for (var i = 0; i < 100; ++i) + /a/.exec('a'); +} +f(); +assertEq(g, 0); diff --git a/js/src/jit-test/tests/basic/testBug614653.js b/js/src/jit-test/tests/basic/testBug614653.js new file mode 100644 index 0000000000..e09759ae58 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug614653.js @@ -0,0 +1,10 @@ +/* Bug 614653 - This test .2 seconds with the fix, 20 minutes without. */ +for (var i = 0; i < 10; ++i) { + var arr = []; + var s = "abcdefghijklmnop"; + for (var j = 0; j < 50000; ++j) { + s = "<" + s + ">"; + arr.push(s); + } + gc(); +} diff --git a/js/src/jit-test/tests/basic/testBug614752.js b/js/src/jit-test/tests/basic/testBug614752.js new file mode 100644 index 0000000000..d34392da10 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug614752.js @@ -0,0 +1,3 @@ +// |jit-test| error: TypeError +Object.prototype.apply = Function.prototype.apply; +({}).apply(null, null); // don't assert diff --git a/js/src/jit-test/tests/basic/testBug616454.js b/js/src/jit-test/tests/basic/testBug616454.js new file mode 100644 index 0000000000..34ca440a7a --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug616454.js @@ -0,0 +1,2 @@ +function isnan(x) { return x !== x } +assertEq(isnan(deserialize(serialize(-'test'))), true); diff --git a/js/src/jit-test/tests/basic/testBug621202.js b/js/src/jit-test/tests/basic/testBug621202.js new file mode 100644 index 0000000000..5bf8269103 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug621202.js @@ -0,0 +1,16 @@ +const MAX = 10000; + +var arr = []; +var str = ""; +for (var i = 0; i < MAX; ++i) { + /x/.test(str); + str = str + 'xxxxxxxxxxxxxx'; + arr.push(str); +} + +arr.length = Math.floor(MAX/3); +gc(); + +for (var i = 0; i < MAX; ++i) { + /x/.test(arr[i]); +} diff --git a/js/src/jit-test/tests/basic/testBug628564.js b/js/src/jit-test/tests/basic/testBug628564.js new file mode 100644 index 0000000000..8e9455064f --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug628564.js @@ -0,0 +1,8 @@ +x = 0 +for (a = 0; a < 13; ++a) { + if (a == 7) { + if (!x) { + this.__defineSetter__("x", Object.defineProperties) + } + } +} diff --git a/js/src/jit-test/tests/basic/testBug629974.js b/js/src/jit-test/tests/basic/testBug629974.js new file mode 100644 index 0000000000..50e7247f4f --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug629974.js @@ -0,0 +1,7 @@ +foo = {} +foo.y = 3; +foo.y = function () {} +Object.defineProperty(foo, "y", { set:function(){} }) +gc() +delete foo.y +gc(); diff --git a/js/src/jit-test/tests/basic/testBug630064.js b/js/src/jit-test/tests/basic/testBug630064.js new file mode 100644 index 0000000000..aab4885cc5 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug630064.js @@ -0,0 +1,48 @@ +var BUGNUMBER = ''; +function printBugNumber (num) +{ + return "foo"; +} +function optionsClear() { + var x = printBugNumber().split(','); +} +function optionsReset() { + optionsClear(); +} +var code = new Array(); +code.push("evaluate"); +var x0 = "\ + printBugNumber(BUGNUMBER);\n\ + function gen()\n\ + {\n\ + try {\n\ + yield 0;\n\ + } finally {\n\ + }\n\ + }\n\ + var iter1 = gen( iter1=\"NaN\", new gen(gen)) ;\n\ + gc();\n\ +"; +code.push(x0); +code.push("evaluate"); +var files = new Array(); +while (true) { + var file = code.shift(); + if (file == "evaluate") { + loadFiles(files); + } else if (file == undefined) { + break; + } else { + files.push(file); + } +} +function loadFiles(x) { + for (i in x) { + try { + eval(x[i]); + } catch (e) { + } + } + optionsReset(); +} + diff --git a/js/src/jit-test/tests/basic/testBug634590.js b/js/src/jit-test/tests/basic/testBug634590.js new file mode 100644 index 0000000000..32df4f3bd8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug634590.js @@ -0,0 +1,12 @@ +this.name = "outer"; +var sb = evalcx(''); +sb.name = "inner"; +sb.parent = this; +function f() { return this.name; } +assertEq(evalcx('this.f = parent.f;\n' + + 'var s = "";\n' + + 'for (i = 0; i < 10; ++i)\n' + + ' s += f();\n' + + 's', + sb), + "outerouterouterouterouterouterouterouterouterouter"); diff --git a/js/src/jit-test/tests/basic/testBug634590b.js b/js/src/jit-test/tests/basic/testBug634590b.js new file mode 100644 index 0000000000..42531a8295 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug634590b.js @@ -0,0 +1,19 @@ +this.name = "outer"; +var sb = evalcx(''); +sb.name = "inner"; +sb.parent = this; +function f() { return this.name; } +f.notMuchTodo = '42'; +assertEq(evalcx('{\n' + + ' let f = parent.f;\n' + + ' let name = "block";\n' + + ' (function () {\n' + + ' eval(f.notMuchTodo);\n' + // reify Block + ' var s = "";\n' + + ' for (i = 0; i < 10; ++i)\n' + + ' s += f();\n' + + ' return s;\n' + + ' })();\n' + + '}', + sb), + "outerouterouterouterouterouterouterouterouterouter"); diff --git a/js/src/jit-test/tests/basic/testBug634590c.js b/js/src/jit-test/tests/basic/testBug634590c.js new file mode 100644 index 0000000000..1ae2542def --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug634590c.js @@ -0,0 +1,20 @@ +this.name = "outer"; +var sb = evalcx(''); +sb.name = "inner"; +sb.parent = this; +function f() { return this.name; } +f.notMuchTodo = '42'; +assertEq(evalcx('(function () {\n' + + ' arguments = null;\n' + // force heavyweight + ' var f = parent.f;\n' + + ' var name = "call";\n' + + ' return (function () {\n' + + ' eval(f.notMuchTodo);\n' + // reify Call, make f() compile to JSOP_CALLNAME + ' var s = "";\n' + + ' for (i = 0; i < 10; ++i)\n' + + ' s += f();\n' + + ' return s;\n' + + ' })();\n' + + '})()', + sb), + "outerouterouterouterouterouterouterouterouterouter"); diff --git a/js/src/jit-test/tests/basic/testBug634590d.js b/js/src/jit-test/tests/basic/testBug634590d.js new file mode 100644 index 0000000000..d2e47b51fa --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug634590d.js @@ -0,0 +1,19 @@ +this.name = "outer"; +var sb = evalcx(''); +sb.name = "inner"; +sb.parent = this; +this.f = function name(outer) { + if (outer) { + return function () { + return name(false); + }(); + } + return this.name; +} +assertEq(evalcx('this.f = parent.f;\n' + + 'var s = "";\n' + + 'for (i = 0; i < 10; ++i)\n' + + ' s += f(true);\n' + + 's', + sb), + "outerouterouterouterouterouterouterouterouterouter"); diff --git a/js/src/jit-test/tests/basic/testBug634590ma.js b/js/src/jit-test/tests/basic/testBug634590ma.js new file mode 100644 index 0000000000..3914cba47a --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug634590ma.js @@ -0,0 +1,14 @@ +// |jit-test| + +this.name = "outer"; +var sb = evalcx(''); +sb.name = "inner"; +sb.parent = this; +function f() { return this.name; } +assertEq(evalcx('this.f = parent.f;\n' + + 'var s = "";\n' + + 'for (i = 0; i < 10; ++i)\n' + + ' s += f();\n' + + 's', + sb), + "outerouterouterouterouterouterouterouterouterouter"); diff --git a/js/src/jit-test/tests/basic/testBug637014.js b/js/src/jit-test/tests/basic/testBug637014.js new file mode 100644 index 0000000000..53e22f8bde --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug637014.js @@ -0,0 +1,2 @@ +var o = newGlobal(); +o.makeFinalizeObserver(); diff --git a/js/src/jit-test/tests/basic/testBug648438.js b/js/src/jit-test/tests/basic/testBug648438.js new file mode 100644 index 0000000000..9bdfc0fbd8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug648438.js @@ -0,0 +1,7 @@ +for (var i = 0; i < 20; i++) { + (function () { + try { + JSON.parse(); + } catch (e) {} + }).call(); +} diff --git a/js/src/jit-test/tests/basic/testBug653396.js b/js/src/jit-test/tests/basic/testBug653396.js new file mode 100644 index 0000000000..6eefdf2289 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug653396.js @@ -0,0 +1,6 @@ +// |jit-test| error: RangeError +function g(a, b, c, d) {} +function f(a, b, c) { + arguments.length = getMaxArgs() + 1; + g.apply(this, arguments); +}f(); diff --git a/js/src/jit-test/tests/basic/testBug659577-1.js b/js/src/jit-test/tests/basic/testBug659577-1.js new file mode 100644 index 0000000000..3ae1a605a3 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug659577-1.js @@ -0,0 +1 @@ +Function("for(;(function(){([x],0)});x){}var x") diff --git a/js/src/jit-test/tests/basic/testBug659577-2.js b/js/src/jit-test/tests/basic/testBug659577-2.js new file mode 100644 index 0000000000..dbd4ec2407 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug659577-2.js @@ -0,0 +1,15 @@ +gczeal(4); +evaluate("\ +Date.formatFunctions = {count:0};\ +Date.prototype.dateFormat = function(format) {\ + var funcName = 'format' + Date.formatFunctions.count++;\ + var code = 'Date.prototype.' + funcName + ' = function(){return ';\ + var ch = '';\ + for (var i = 0; i < format.length; ++i) {\ + ch = format.charAt(i);\ + eval(code.substring(0, code.length - 3) + ';}');\ + }\ +};\ +var date = new Date('1/1/2007 1:11:11');\ + var shortFormat = date.dateFormat('Y-m-d');\ +"); diff --git a/js/src/jit-test/tests/basic/testBug663789-1.js b/js/src/jit-test/tests/basic/testBug663789-1.js new file mode 100644 index 0000000000..4fdc262b51 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug663789-1.js @@ -0,0 +1,6 @@ +function f() { + a = arguments; + return a[0] - a[1]; +} + +[1,2,3,4].sort(f); diff --git a/js/src/jit-test/tests/basic/testBug663789-2.js b/js/src/jit-test/tests/basic/testBug663789-2.js new file mode 100644 index 0000000000..3e1a608bda --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug663789-2.js @@ -0,0 +1,6 @@ +load(libdir + "evalInFrame.js"); + +o = { toString:function() { return evalInFrame(1, "x") } } +var x = 'C'; +var s = "aaaaaaaaaa".replace(/a/g, function() { var x = 'B'; return o }); +assertEq(s, "CCCCCCCCCC"); diff --git a/js/src/jit-test/tests/basic/testBug666003.js b/js/src/jit-test/tests/basic/testBug666003.js new file mode 100644 index 0000000000..b508e7aa55 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug666003.js @@ -0,0 +1,13 @@ +function f() { + f = function() { g(); }; + f(); +} +g = f; + +var caught = false; +try { + f(); +} catch(e) { + caught = true; +} +assertEq(caught, true); diff --git a/js/src/jit-test/tests/basic/testBug668479.js b/js/src/jit-test/tests/basic/testBug668479.js new file mode 100644 index 0000000000..30eaca5c40 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug668479.js @@ -0,0 +1,3 @@ +function a() { + with(a) eval("arguments[0]"); +} a(); diff --git a/js/src/jit-test/tests/basic/testBug672436.js b/js/src/jit-test/tests/basic/testBug672436.js new file mode 100644 index 0000000000..95a6d07a1d --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug672436.js @@ -0,0 +1,25 @@ +try { new Error() } catch (e) {} + +const N = 18; + +var arr = []; +for (var i = 0; i < N; ++i) + arr[i] = 'a'; +arr[N] = '%'; + +function inner(i) { + decodeURI(arr[i]); +} +function outer() { + for (var i = 0; i <= N; ++i) + inner(i); +} + +var caught = false; +try { + outer(); +} catch (e) { + caught = true; +} +assertEq(caught, true); + diff --git a/js/src/jit-test/tests/basic/testBug673066.js b/js/src/jit-test/tests/basic/testBug673066.js new file mode 100644 index 0000000000..28aa518028 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug673066.js @@ -0,0 +1,23 @@ +function f(code) { + a = code.replace(/s/, ""); + wtt = a + code = code.replace(/\/\*DUPTRY\d+\*\//, function(k) { + n = parseInt(k.substr(8), 0); + return g("try{}catch(e){}", n) + }); + f = eval("(function(){" + code + "})") + if (typeof disassemble == 'function') { + disassemble("-r", f) + } +} +function g(s, n) { + if (n == 0) { + return s + } + s2 = s + s + r = n % 2 + d = (n - r) / 2 + m = g(s2, d) + return r ? m + s : m +} +f("switch(''){default:break;/*DUPTRY525*/}") diff --git a/js/src/jit-test/tests/basic/testBug673068.js b/js/src/jit-test/tests/basic/testBug673068.js new file mode 100644 index 0000000000..5f2618b1aa --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug673068.js @@ -0,0 +1,12 @@ +// |jit-test| + +function f(x) { + var x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10; + var y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10; + var z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10; + if (x == 0) + return; + f(x - 1); +} + +f(100); diff --git a/js/src/jit-test/tests/basic/testBug676486.js b/js/src/jit-test/tests/basic/testBug676486.js new file mode 100644 index 0000000000..5f5de23c6a --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug676486.js @@ -0,0 +1,8 @@ +var proxy = new Proxy(function() { + return (function () { eval("foo") })(); + }, {}); + +try { + new proxy(); +} catch (e) { +} diff --git a/js/src/jit-test/tests/basic/testBug686274.js b/js/src/jit-test/tests/basic/testBug686274.js new file mode 100644 index 0000000000..e03fd43542 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug686274.js @@ -0,0 +1,15 @@ +// Don't Baseline-compile the huge array literal with --baseline-eager +// as it's slow, especially in debug builds. +setJitCompilerOption("baseline.warmup.trigger", 2); + +function f(N) { + var body = "return ["; + for (var i = 0; i < N-1; i++) + body += "1,"; + body += "2]"; + var f = new Function(body); + var arr = f(); + assertEq(arr.length, N); + assertEq(arr[N-1], 2); +} +f(1000000); diff --git a/js/src/jit-test/tests/basic/testBug690959.js b/js/src/jit-test/tests/basic/testBug690959.js new file mode 100644 index 0000000000..6f4b800c1e --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug690959.js @@ -0,0 +1,4 @@ +var s = 'abcdFF0123456789012345fail'; +s = s.replace("abcd", "0123456789012345678901234567890123456789012FF"); +s = s.replace("FF0123456789012345fail", "ok"); +assertEq(s, '0123456789012345678901234567890123456789012FFok'); diff --git a/js/src/jit-test/tests/basic/testBug692274-2.js b/js/src/jit-test/tests/basic/testBug692274-2.js new file mode 100644 index 0000000000..dff5c90523 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug692274-2.js @@ -0,0 +1,7 @@ +function f() { + var ss = [new f("abc"), new String("foobar"), new String("quux")]; + for (let a6 = this ;; ) {} +} +try { + f(); +} catch (e) {} diff --git a/js/src/jit-test/tests/basic/testBug692274-3.js b/js/src/jit-test/tests/basic/testBug692274-3.js new file mode 100644 index 0000000000..a8c0afe65f --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug692274-3.js @@ -0,0 +1,16 @@ +var x = -false; +switch(x) { + case 11: + let y = 42; +} +switch(x) { + case 11: + let y = 42; + let z = 'ponies'; +} +switch(x) { + case 11: + let y = 42; + let z = 'ponies'; + let a = false; +} diff --git a/js/src/jit-test/tests/basic/testBug701227.js b/js/src/jit-test/tests/basic/testBug701227.js new file mode 100644 index 0000000000..cf12409fea --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug701227.js @@ -0,0 +1 @@ +(function f() { try {} catch(e) { let x } }).toString() diff --git a/js/src/jit-test/tests/basic/testBug701239.js b/js/src/jit-test/tests/basic/testBug701239.js new file mode 100644 index 0000000000..665134c1d1 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug701239.js @@ -0,0 +1 @@ +(function f(w) { for([w] in 1) {} }).toString(); diff --git a/js/src/jit-test/tests/basic/testBug701244.js b/js/src/jit-test/tests/basic/testBug701244.js new file mode 100644 index 0000000000..4a9931f804 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug701244.js @@ -0,0 +1 @@ +(function f({length}) {}).toString(); diff --git a/js/src/jit-test/tests/basic/testBug703857.js b/js/src/jit-test/tests/basic/testBug703857.js new file mode 100644 index 0000000000..dcdcc1e1f1 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug703857.js @@ -0,0 +1,13 @@ +Function.prototype.X = 42; +function ownProperties() { + var props = {}; + var r = function () {}; + for (var a in r) { + { + let a = function() { for (var r=0;r<6;++r) ++a; }; + a(); + } + props[a] = true; + } +} +ownProperties(); diff --git a/js/src/jit-test/tests/basic/testBug705423.js b/js/src/jit-test/tests/basic/testBug705423.js new file mode 100644 index 0000000000..4ce993c203 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug705423.js @@ -0,0 +1,19 @@ +gczeal(1); + +var g = newGlobal(); + +g.eval("\ +var f = function(x) { \ + arg = arguments; \ + fun = function() { return x }; \ +} \ +"); + +g.f(3); +g.f = null; +assertEq(g.fun(), 3); +assertEq(g.arg[0], 3); +gc(); +g.arg[0] = 9; +assertEq(g.fun(), 9); +assertEq(g.arg[0], 9); diff --git a/js/src/jit-test/tests/basic/testBug714650.js b/js/src/jit-test/tests/basic/testBug714650.js new file mode 100644 index 0000000000..2284faa197 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug714650.js @@ -0,0 +1,36 @@ +{ + let [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], + [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = [], [] = []; + print("ok"); +} diff --git a/js/src/jit-test/tests/basic/testBug720695.js b/js/src/jit-test/tests/basic/testBug720695.js new file mode 100644 index 0000000000..4e3dc764ff --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug720695.js @@ -0,0 +1,16 @@ +var v = [ -0x80000003, -0x80000002, -0x80000001, -0x80000000, -0x7fffffff, -0x7ffffffe, -0x7ffffffd, + -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 20, 21, 100, 101, 110, 111, 500, + 0x7ffffffd, 0x7ffffffe, 0x7fffffff, 0x80000000, 0x80000001, 0x80000002, 0x80000003]; + +function strcmp(x, y) { + return Number(String(x) > String(y)) +} + +for (var i = 0; i < v.length; ++i) { + for (var j = 0; j < v.length; ++j) { + var builtin = String([v[i], v[j]].sort()); + var manual = String([v[i], v[j]].sort(strcmp)); + assertEq(builtin, manual); + } +} diff --git a/js/src/jit-test/tests/basic/testBug723445.js b/js/src/jit-test/tests/basic/testBug723445.js new file mode 100644 index 0000000000..7cbe0a0172 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug723445.js @@ -0,0 +1,10 @@ +var global = newGlobal(); +global.eval("function f(b) { if (b) { new Error }; }"); + +function f(b) { global.f(b) } +function g(b) { f(b) } +function h() { + for (var i = 0; i < 1000; ++i) + g(i > 900); +} +h(); diff --git a/js/src/jit-test/tests/basic/testBug726380.js b/js/src/jit-test/tests/basic/testBug726380.js new file mode 100644 index 0000000000..2f4475674a --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug726380.js @@ -0,0 +1,2 @@ +var r = /a/; +r.compile(r); diff --git a/js/src/jit-test/tests/basic/testBug731181.js b/js/src/jit-test/tests/basic/testBug731181.js new file mode 100644 index 0000000000..9ece975354 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug731181.js @@ -0,0 +1,2 @@ +gczeal(2,1); +/a/y.exec('a'); diff --git a/js/src/jit-test/tests/basic/testBug736012.js b/js/src/jit-test/tests/basic/testBug736012.js new file mode 100644 index 0000000000..fdcb4fc1d5 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug736012.js @@ -0,0 +1,8 @@ +evaluate("\ +function fatty() {\ + try { fatty(); } catch (e) {\ + for (foo of [1]) {}\ + }\ +}\ +fatty();\ +"); diff --git a/js/src/jit-test/tests/basic/testBug736807.js b/js/src/jit-test/tests/basic/testBug736807.js new file mode 100644 index 0000000000..b279b02eb9 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug736807.js @@ -0,0 +1,13 @@ +function f() { + newGlobal().eval('\ + try {\ + if (typeof gczeal === "function") \ + gczeal(2,1); \ + throw new Error();\ + } catch (e) { \ + gc(); \ + assertEq("" + e, "Error"); \ + } \ + '); +} +f({}, [1,2,4,5,6,7,8,1], new RegExp(), function() {}); diff --git a/js/src/jit-test/tests/basic/testBug737388.js b/js/src/jit-test/tests/basic/testBug737388.js new file mode 100644 index 0000000000..1a97ab57fe --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug737388.js @@ -0,0 +1,8 @@ +function one() {}; +function two() { assertEq(arguments[0], undefined); } +function three() { + one("","","","","",""); + two(); +} +for (var i = 0; i < 10; ++i) + three(); diff --git a/js/src/jit-test/tests/basic/testBug737575.js b/js/src/jit-test/tests/basic/testBug737575.js new file mode 100644 index 0000000000..5c0c9705f1 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug737575.js @@ -0,0 +1,6 @@ +function f(s) { + return arguments[s]; +} + +for (var i = 0; i < 10; ++i) + assertEq(f(String(i+1), 0,1,2,3,4,5,6,7,8,9), i); diff --git a/js/src/jit-test/tests/basic/testBug740442.js b/js/src/jit-test/tests/basic/testBug740442.js new file mode 100644 index 0000000000..143ce2da96 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug740442.js @@ -0,0 +1,11 @@ +function g1() {} +function g2() { + return function Int8Array () {}; +} +function f1(other) { + eval("gc(); h = g1"); + for(var i=0; i<20; i++) { + i = i.name; + } +} +f1(g2); diff --git a/js/src/jit-test/tests/basic/testBug740445.js b/js/src/jit-test/tests/basic/testBug740445.js new file mode 100644 index 0000000000..227ddfc236 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug740445.js @@ -0,0 +1,9 @@ +function testMethodInit() { + function o() {} + function k() { + for (i = 0; i < this.depth; ++i) {} + } + for (var i = 0; i < 10; i++) + (i) = {o: o, k: k}; +} +testMethodInit(); diff --git a/js/src/jit-test/tests/basic/testBug741497.js b/js/src/jit-test/tests/basic/testBug741497.js new file mode 100644 index 0000000000..f61138aa44 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug741497.js @@ -0,0 +1,3 @@ +// |jit-test| error: SyntaxError +"use strict"; +function inner() (([arguments, b] = this, c)()); diff --git a/js/src/jit-test/tests/basic/testBug743408.js b/js/src/jit-test/tests/basic/testBug743408.js new file mode 100644 index 0000000000..2c55106584 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug743408.js @@ -0,0 +1,6 @@ +// |jit-test| error:ReferenceError +test(); +function test() { + (arguments); + F.prototype = new F(); +} diff --git a/js/src/jit-test/tests/basic/testBug747554.js b/js/src/jit-test/tests/basic/testBug747554.js new file mode 100644 index 0000000000..8b77ef8a13 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug747554.js @@ -0,0 +1,6 @@ +assertEq((function(x) { + (function () { x++ })(); + var z; + ({ z } = { z:'ponies' }) + return z; +})(), 'ponies'); diff --git a/js/src/jit-test/tests/basic/testBug752205.js b/js/src/jit-test/tests/basic/testBug752205.js new file mode 100644 index 0000000000..edf7348551 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug752205.js @@ -0,0 +1,6 @@ +var x = "one"; +var y = "two"; +const a = x + y; +var hit = false; +eval('switch("onetwo") { case a: hit = true; };'); +assertEq(hit, true); diff --git a/js/src/jit-test/tests/basic/testBug752379.js b/js/src/jit-test/tests/basic/testBug752379.js new file mode 100644 index 0000000000..376657defa --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug752379.js @@ -0,0 +1,10 @@ +var lfcode = new Array(); +lfcode.push(""); +lfcode.push("print('hi');"); +while (true) { + var file = lfcode.shift(); if (file == undefined) { break; } + loadFile(file); +} +function loadFile(lfVarx) { + evaluate(lfVarx); +} diff --git a/js/src/jit-test/tests/basic/testBug753158.js b/js/src/jit-test/tests/basic/testBug753158.js new file mode 100644 index 0000000000..50ba14b232 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug753158.js @@ -0,0 +1,67 @@ +function testFuncStmt1() { + var g = 3; + function f(b) { + if (b) { + function g() { return 42 } + assertEq(g(), 42); + } + } + f(true); +} +testFuncStmt1(); + +function testFuncStmt2() { + var g = 3; + (function(b) { + if (b) { + function g() { return 42 } + function f() { assertEq(g(), 42); } + f(); + } + })(true); +} +testFuncStmt2(); + +function testEval1() { + var g = 3; + function f() { + eval("var g = 42"); + assertEq(g, 42); + } + f(); +} +testEval1(); + +function testEval2() { + var g = 3; + (function() { + eval("var g = 42"); + function f() { + assertEq(g, 42); + } + f(); + })(); +} +testEval2(); + +function testWith1() { + var g = 3; + function f() { + with ({g:42}) { + assertEq(g, 42); + } + } + f(); +} +testWith1(); + +function testWith2() { + var g = 3; + with ({g:42}) { + function f() { + assertEq(g, 42); + } + } + f(); +} +testWith2(); diff --git a/js/src/jit-test/tests/basic/testBug755916.js b/js/src/jit-test/tests/basic/testBug755916.js new file mode 100644 index 0000000000..157d3073ac --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug755916.js @@ -0,0 +1,12 @@ +// |jit-test| error:InternalError + +Object.defineProperty(this, "t2", { + get: function() { + for (p in h2) { + t2 + } + } +}) +h2 = {} +h2.a = function() {} +Object(t2) diff --git a/js/src/jit-test/tests/basic/testBug756918.js b/js/src/jit-test/tests/basic/testBug756918.js new file mode 100644 index 0000000000..2787b38813 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug756918.js @@ -0,0 +1,6 @@ +// |jit-test| error:Error + +with({}) + let([] = []) { + eval("throw new Error()"); + } diff --git a/js/src/jit-test/tests/basic/testBug756919.js b/js/src/jit-test/tests/basic/testBug756919.js new file mode 100644 index 0000000000..a72f46bece --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug756919.js @@ -0,0 +1,10 @@ +// |jit-test| skip-if: !('oomTest' in this) +function test(x) { + var upvar = ""; + function f() { upvar += ""; } + if (x > 0) + test(x - 1); + eval(''); +} + +oomTest(() => test(10)); diff --git a/js/src/jit-test/tests/basic/testBug761863.js b/js/src/jit-test/tests/basic/testBug761863.js new file mode 100644 index 0000000000..fc5c12d20b --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug761863.js @@ -0,0 +1,12 @@ +gczeal(4); +function blah() { + var i = 1; + function o() {} + function k() { i++; } + o.x = 0; + for (var j = 0; j < 100; ++j) { + i = {a: o, b: k}; + i++; + } +} +blah(); diff --git a/js/src/jit-test/tests/basic/testBug7618864.js b/js/src/jit-test/tests/basic/testBug7618864.js new file mode 100644 index 0000000000..9b9ba0ec41 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug7618864.js @@ -0,0 +1,55 @@ +function printStatus (msg) { + var lines = msg.split (""); +} +function printBugNumber (num) { + var digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"]; +} +var lfcode = new Array(); +lfcode.push("gczeal(4);"); +lfcode.push("jsTestDriverEnd();"); +lfcode.push(""); +lfcode.push("var BUGNUMBER = \"(none)\";\ +var summary = \"gen.close(); gen.throw(ex) throws ex forever\";\ +var actual, expect;\ +printBugNumber(BUGNUMBER);\ +printStatus(summary);\ +function gen() {\ + var x = 5, y = 7;\ + yield z;\ +}\ +var failed = false;\ +var it = gen();\ +try {\ + it.close();\ + var doThrow = true;\ + var thrown = \"foobar\";\ + try { } catch (e) { }\ + try { } catch (e) { }\ + throw \"it.throw(\\\"\" + thrown + \"\\\") failed\";\ + var stopPassed = false;\ + try { } catch (e) {\ + if (\"1234\")\ + stopPassed = true;\ + }\ +} catch (e) {}\ +"); +var lfRunTypeId = -1; +while (true) { + var file = lfcode.shift(); if (file == undefined) { break; } + if (file == "evaluate") { + } else { + loadFile(file); + } +} +function loadFile(lfVarx) { + try { + if (lfVarx.substr(-3) == ".js") { + } else { + switch (lfRunTypeId) { + default: evaluate(lfVarx); + } + } + } catch (lfVare) { + print(lfVare); + } +} diff --git a/js/src/jit-test/tests/basic/testBug762105.js b/js/src/jit-test/tests/basic/testBug762105.js new file mode 100644 index 0000000000..147a87eac0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug762105.js @@ -0,0 +1,33 @@ +function escapeme() {} + +function f1(x) { + escapeme(arguments); + var y = ++x; + return x + y; +} +for (var i = 0; i < 100; ++i) + assertEq(f1(2), 6); + +function f2(x) { + escapeme(arguments); + var y = --x; + return x + y; +} +for (var i = 0; i < 100; ++i) + assertEq(f2(2), 2); + +function f3(x) { + escapeme(arguments); + var y = x++; + return x + y; +} +for (var i = 0; i < 100; ++i) + assertEq(f3(2), 5); + +function f4(x) { + escapeme(arguments); + var y = x--; + return x + y; +} +for (var i = 0; i < 100; ++i) + assertEq(f4(2), 3); diff --git a/js/src/jit-test/tests/basic/testBug762432.js b/js/src/jit-test/tests/basic/testBug762432.js new file mode 100644 index 0000000000..c010aefc1e --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug762432.js @@ -0,0 +1,15 @@ +function getter() { return 1; } +function setter() { } +function getDescriptor(target, name) { + if (name != 'prop') + throw "Unknown property: " + name; + return { configurable: true, enumerable: true, get: getter, set: setter }; +} +var handler = { + getOwnPropertyDescriptor: getDescriptor, +}; + +// Make sure that __lookup{Getter,Setter}__ works on proxies. +var proxy = new Proxy({}, handler); +assertEq(Object.prototype.__lookupGetter__.call(proxy, 'prop'), getter); +assertEq(Object.prototype.__lookupSetter__.call(proxy, 'prop'), setter); diff --git a/js/src/jit-test/tests/basic/testBug762450.js b/js/src/jit-test/tests/basic/testBug762450.js new file mode 100644 index 0000000000..2813015a60 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug762450.js @@ -0,0 +1,7 @@ +function f(a, b, c) { + arguments[0] = 3; + return (c--) + 1; +} +var r = f(); +print(r); +assertEq(r !== r, true); diff --git a/js/src/jit-test/tests/basic/testBug762473.js b/js/src/jit-test/tests/basic/testBug762473.js new file mode 100644 index 0000000000..d79bc2e2e4 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug762473.js @@ -0,0 +1,49 @@ +function f(i) { + var a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a16,a17; + var b = true; + if (b) + function f1() {} + if (b) + function f2() {} + if (b) + function f3() {} + if (b) + function f4() {} + if (b) + function f5() {} + if (b) + function f6() {} + if (b) + function f7() {} + if (b) + function f8() {} + if (b) + function f9() {} + if (b) + function f10() {} + if (b) + function f11() {} + if (b) + function f12() {} + if (b) + function f13() {} + if (b) + function f14() {} + if (b) + function f15() {} + if (b) + function f16() {} + if (b) + function f17() {} + + a1 = i; + + function f() { + return a1; + } + + return f(); +} + +for (var i = 0; i < 100; ++i) + assertEq(f(i), i); diff --git a/js/src/jit-test/tests/basic/testBug763384.js b/js/src/jit-test/tests/basic/testBug763384.js new file mode 100644 index 0000000000..572941366d --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug763384.js @@ -0,0 +1,9 @@ +var caught = false; +try { + ''.match('('); +} catch (e) { + caught = true; + assertEq(e instanceof Error, true); + assertEq(('' + e).indexOf('SyntaxError') === -1, false); +} +assertEq(caught, true); diff --git a/js/src/jit-test/tests/basic/testBug763950.js b/js/src/jit-test/tests/basic/testBug763950.js new file mode 100644 index 0000000000..6f685217fd --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug763950.js @@ -0,0 +1,6 @@ +(function() { + var x; + for (let j = 0; j < 1; j = j + 1) + x = function() { return j; }; + assertEq(x(), 0); +})(); diff --git a/js/src/jit-test/tests/basic/testBug766064.js b/js/src/jit-test/tests/basic/testBug766064.js new file mode 100644 index 0000000000..cd13f1f674 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug766064.js @@ -0,0 +1,7 @@ +function loop(actual = 0) { + if (function() { actual++ }) + {} + return actual; +} + +assertEq(loop(), 0); diff --git a/js/src/jit-test/tests/basic/testBug769987.js b/js/src/jit-test/tests/basic/testBug769987.js new file mode 100644 index 0000000000..52bcdc1118 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug769987.js @@ -0,0 +1,13 @@ +function h(code) { + f = Function(code); + g() +} +function g() { + f() +} +h() +h() +h("\ + arguments[\"0\"];\ + gc();\ +") diff --git a/js/src/jit-test/tests/basic/testBug770407.js b/js/src/jit-test/tests/basic/testBug770407.js new file mode 100644 index 0000000000..54184fab41 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug770407.js @@ -0,0 +1,4 @@ +// |jit-test| error:TypeError +var otherGlobal = newGlobal(); +var proxy = new (otherGlobal.Proxy)({}, {}); +Int8Array.set(proxy); diff --git a/js/src/jit-test/tests/basic/testBug772328.js b/js/src/jit-test/tests/basic/testBug772328.js new file mode 100644 index 0000000000..4b465b0a22 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug772328.js @@ -0,0 +1,20 @@ +function f(x) { + function x() {} + arguments[0] = 42; + return x; +} +assertEq(f(0), 42); + +function g(x) { + function x() {} + assertEq(arguments[0], x); +} +g(0); + +var caught = false; +try { + (function h(x) { function x() {} }).blah.baz; +} catch (e) { + caught = true; +} +assertEq(caught, true); diff --git a/js/src/jit-test/tests/basic/testBug775801.js b/js/src/jit-test/tests/basic/testBug775801.js new file mode 100644 index 0000000000..35ced600ec --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug775801.js @@ -0,0 +1,8 @@ +function f() { + var x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20; + var b = {a:'ponies'}; + eval(''); + return function(e) { return b[e] } +} + +assertEq("aaa".replace(/a/g, f()), "poniesponiesponies"); diff --git a/js/src/jit-test/tests/basic/testBug775807.js b/js/src/jit-test/tests/basic/testBug775807.js new file mode 100644 index 0000000000..b136b0a81b --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug775807.js @@ -0,0 +1,19 @@ +// |jit-test| --dump-bytecode + +(function() { + const x = ((function() { + return { + e: function() { + (function() { + for (e in x) {} + })() + } + } + }(function() { + return { + t: { + c + } + } + }))) +})() diff --git a/js/src/jit-test/tests/basic/testBug776191.js b/js/src/jit-test/tests/basic/testBug776191.js new file mode 100644 index 0000000000..043e50111d --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug776191.js @@ -0,0 +1,8 @@ +(function() { + { + let a, b, c; + ((function() { + with({}) { { let b; { ((function() { c = 0 })()) } } } + })()) + } +})() diff --git a/js/src/jit-test/tests/basic/testBug778603.js b/js/src/jit-test/tests/basic/testBug778603.js new file mode 100644 index 0000000000..9df17d04ea --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug778603.js @@ -0,0 +1 @@ +assertEq(unescape("0%u0000".substr(0,2)), "0%"); diff --git a/js/src/jit-test/tests/basic/testBug780712.js b/js/src/jit-test/tests/basic/testBug780712.js new file mode 100644 index 0000000000..f82ad8db0f --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug780712.js @@ -0,0 +1,9 @@ +r = evalcx("/x/", undefined); +s = ""; +gc() +Function("\ + s.match(r);\ + schedulezone(__proto__);\ + ({c:schedulegc(2)});\ + s.match(r);\ +")() diff --git a/js/src/jit-test/tests/basic/testBug783441.js b/js/src/jit-test/tests/basic/testBug783441.js new file mode 100644 index 0000000000..b1d6af68ab --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug783441.js @@ -0,0 +1 @@ +assertEq((function(x, y, x) { return (function() { return x+y; })(); })(1,2,5), 7); diff --git a/js/src/jit-test/tests/basic/testBug783540.js b/js/src/jit-test/tests/basic/testBug783540.js new file mode 100644 index 0000000000..618570707d --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug783540.js @@ -0,0 +1,5 @@ +gczeal(2, 2) +var stringA = "abcdef"; +var stringB = "ghijk"; +var stringC = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"; +(stringA + stringB + stringC).replace('abc', 'AA') diff --git a/js/src/jit-test/tests/basic/testBug783543.js b/js/src/jit-test/tests/basic/testBug783543.js new file mode 100644 index 0000000000..80e3495fc7 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug783543.js @@ -0,0 +1,11 @@ +// |jit-test| error:ReferenceError + +try { + evaluate(" (function(c) { const x = 1; for (x in null); })();"); + var expect = "Passed"; +} catch ( e ) { + result = expect; +} +schedulegc(10); +eval("var o = new MyObject(); var result = 0; for (var o in foo) { result += this[o]; } ") +function MyObject() {} diff --git a/js/src/jit-test/tests/basic/testBug784639.js b/js/src/jit-test/tests/basic/testBug784639.js new file mode 100644 index 0000000000..1380ae6ed2 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug784639.js @@ -0,0 +1,17 @@ +evalcx("\ + Object.defineProperty(this, \"a\", {});\ + f = (function(j) {\ + a = Proxy\ + });\ + Object.defineProperty(this, \"g\", {\ + get: function() {\ + return ({\ + r: function() {},\ + t: function() {}\ + })\ + }\ + });\ + for (p in g) {\ + f(1)\ + }\ +", newGlobal()) diff --git a/js/src/jit-test/tests/basic/testBug840012.js b/js/src/jit-test/tests/basic/testBug840012.js new file mode 100644 index 0000000000..20793f7efe --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug840012.js @@ -0,0 +1,18 @@ +// |jit-test| allow-oom; allow-unhandlable-oom; allow-overrecursed + +gcPreserveCode(); +evaluate("gcparam(\"maxBytes\", gcparam(\"gcBytes\") + 4*1024);"); +evaluate("\ +function testDontEnum(F) { \ + function test() {\ + var upvar = \"\";\ + function f() { upvar += \"\"; }\ + typeof (new test(\"1\")) != 'function'\ + }\ + test();\ +} \ +var list = [];\ +for (i in list)\ + var F = this[list[i]];\ +actual = testDontEnum(F);\ +"); diff --git a/js/src/jit-test/tests/basic/testBug878429.js b/js/src/jit-test/tests/basic/testBug878429.js new file mode 100644 index 0000000000..edbb0523bf --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug878429.js @@ -0,0 +1,9 @@ +function negZeroMinusNegZero() +{ + var x = -0.0; + var y = -0.0; + return +(x - y); +} + +assertEq(1 / negZeroMinusNegZero(), Infinity); +assertEq(1 / negZeroMinusNegZero(), Infinity); diff --git a/js/src/jit-test/tests/basic/testBug895774.js b/js/src/jit-test/tests/basic/testBug895774.js new file mode 100644 index 0000000000..ad83832efb --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug895774.js @@ -0,0 +1,14 @@ +var g1 = newGlobal({newCompartment: true}); +var g2 = newGlobal({newCompartment: true}); +g1.eval("function f1() { debugger; evaluate('debugger') }"); +g2.eval("function f2() { f1(); assertEq(Number(this), 42) }"); +g2.f1 = g1.f1; + +var dbg = new Debugger(g1,g2); +dbg.onDebuggerStatement = function(frame) { + var target = frame.older; + dbg.onDebuggerStatement = function(frame) { + assertEq(Number(target.this.unsafeDereference()), 42); + } +} +g2.f2.call(42); diff --git a/js/src/jit-test/tests/basic/testBug961969.js b/js/src/jit-test/tests/basic/testBug961969.js new file mode 100644 index 0000000000..999e15e1d0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug961969.js @@ -0,0 +1,2 @@ +(()=>{ var x,y,z; ()=>{x++;y++;z++} })(); +(()=>{ var x,y; if (true) { function z() { x++;y++ } } })(); diff --git a/js/src/jit-test/tests/basic/testCallApply.js b/js/src/jit-test/tests/basic/testCallApply.js new file mode 100644 index 0000000000..9141f80bcb --- /dev/null +++ b/js/src/jit-test/tests/basic/testCallApply.js @@ -0,0 +1,168 @@ +function script1() { return arguments.length; } +function script2(x) { return x; } +function script3(x) { var o = arguments; return o[0]; } +function genClosure() { var x = 3; eval("x = 4"); return function(y) { return x + y } }; +var closed1 = genClosure(); +var closed2 = genClosure(); +var closed3 = genClosure(); +var native1 = String.prototype.search; +var native2 = String.prototype.match; +var tricky1 = { call:function(x,y) { return y }, apply:function(x,y) { return y } }; + +test0(); +test1(); +test2(); +test3(); + +function test0() { + assertEq(script1.call(null), 0); + assertEq(script1.call(null, 1), 1); + assertEq(script1.call(null, 1,2), 2); + assertEq(native1.call("aabc", /b/), 2); + assertEq(native1.call("abc"), 0); + assertEq(tricky1.call(null, 9), 9); + assertEq(script1.apply(null), 0); + assertEq(script1.apply(null, [1]), 1); + assertEq(script1.apply(null, [1,2]), 2); + assertEq(native1.apply("aabc", [/b/]), 2); + assertEq(native1.apply("abc"), 0); + assertEq(tricky1.apply(null, 1), 1); +} +test0(); + +function test1() { + function f(arr) { + for (var i = 0; i < 10; ++i) { + for (var j = 0; j < arr.length; ++j) { + arr[j].call('a'); + arr[j].apply('a', []); + var arg0 = []; + arr[j].apply('a', arg0); + (function() { arr[j].apply('a', arguments); })(); + + arr[j].call('a', 1); + arr[j].apply('a', [1]); + var arg0 = [1]; + arr[j].apply('a', arg0); + (function() { arr[j].apply('a', arguments); })(1); + + arr[j].call('a', 1,'g'); + arr[j].apply('a', [1,'g']); + var arg0 = [1,'g']; + arr[j].apply('a', arg0); + (function() { arr[j].apply('a', arguments); })(1,'g'); + + arr[j].call('a', 1,'g',3,4,5,6,7,8,9); + arr[j].apply('a', [1,'g',3,4,5,6,7,8,9]); + var arg0 = [1,'g',3,4,5,6,7,8,9]; + arr[j].apply('a', arg0); + (function() { arr[j].apply('a', arguments); })(1,'g',3,4,5,6,7,8,9); + } + } + } + + f([script1, script1, script1, script1, script2, script2, script1, script2]); + f([script1, script2, script3, script1, script2, script3, script3, script3]); + f([script1, script2, script2, script2, script2, script3, script1, script2]); + f([script1, script1, script1, native1, native1, native1, native1, script1]); + f([native1, native1, native1, native2, native2, native2, native2, native1]); + f([native1, native2, native1, native2, native1, native2, native1, native2]); + f([native1, native1, native1, script1, script2, script2, native1, script3]); + f([closed1, closed1, closed1, closed2, closed2, closed2, script3, script3]); + f([closed1, closed2, closed1, closed2, closed1, closed2, closed1, closed2]); + f([closed1, closed2, closed3, closed1, closed2, closed3, script1, script2]); + f([closed1, closed1, closed1, closed2, closed2, closed2, native1, native2]); + f([closed1, closed1, closed1, closed2, closed2, closed2, native1, native2]); + f([native1, native1, native1, closed1, closed2, script1, script2, native2]); +} + +// test things that break our speculation +function test2() { + var threw = false; + try { + (3).call(null, 1,2); + } catch (e) { + threw = true; + } + assertEq(threw, true); + + var threw = false; + try { + (3).apply(null, [1,2]); + } catch (e) { + threw = true; + } + assertEq(threw, true); + + var threw = false; + try { + var arr = [1,2]; + (3).apply(null, arr); + } catch (e) { + threw = true; + } + assertEq(threw, true); + + function tryAndFail(o) { + var threw = false; + try { + o.call(null, 1,2); + } catch(e) { + threw = true; + } + assertEq(threw, true); + threw = false; + try { + o.apply(null, [1,2]); + } catch(e) { + threw = true; + } + assertEq(threw, true); + } + + tryAndFail(1); + tryAndFail({}); + tryAndFail({call:{}, apply:{}}); + tryAndFail({call:function() { throw "not js_fun_call"}, apply:function(){ throw "not js_fun_apply" }}); +} + +// hit the stubs::CompileFunction path +function test3() { + function genFreshFunction(s) { return new Function(s, "return " + s); } + + function callIt(f) { + assertEq(f.call(null, 1,2), 1); + } + callIt(script2); callIt(script2); callIt(script2); callIt(script2); + callIt(genFreshFunction("x")); + callIt(genFreshFunction("y")); + callIt(genFreshFunction("z")); + + function applyIt(f) { + var arr = [1,2]; + assertEq(f.apply(null, arr), 1); + } + applyIt(script2); applyIt(script2); applyIt(script2); applyIt(script2); + applyIt(genFreshFunction("x")); + applyIt(genFreshFunction("y")); + applyIt(genFreshFunction("z")); + + function applyIt1(f) { + function g() { + assertEq(f.apply(null, arguments), 1); + } + g(1,2); + } + applyIt1(script2); applyIt1(script2); applyIt1(script2); applyIt1(script2); + applyIt1(genFreshFunction("x")); + applyIt1(genFreshFunction("y")); + applyIt1(genFreshFunction("z")); + + function applyIt2(f) { + assertEq(f.apply(null, [1,2]), 1); + } + applyIt2(script2); applyIt2(script2); applyIt2(script2); applyIt2(script2); + applyIt2(genFreshFunction("x")); + applyIt2(genFreshFunction("y")); + applyIt2(genFreshFunction("z")); +} diff --git a/js/src/jit-test/tests/basic/testCallApplySpeculationFailed.js b/js/src/jit-test/tests/basic/testCallApplySpeculationFailed.js new file mode 100644 index 0000000000..f1b127839f --- /dev/null +++ b/js/src/jit-test/tests/basic/testCallApplySpeculationFailed.js @@ -0,0 +1,5 @@ +function foo(n) { return n; } +foo.apply = function(a, b) { return b[0]; } +function bar(value) { return foo.apply(null, arguments); } +for (var i = 1 ; i < 4; i++) + assertEq(bar(i), i); diff --git a/js/src/jit-test/tests/basic/testCallElem.js b/js/src/jit-test/tests/basic/testCallElem.js new file mode 100644 index 0000000000..b40553edc1 --- /dev/null +++ b/js/src/jit-test/tests/basic/testCallElem.js @@ -0,0 +1,17 @@ +function testCALLELEM() +{ + function f() { + return 5; + } + + function g() { + return 7; + } + + var x = [f,f,f,f,g]; + var y = 0; + for (var i = 0; i < 5; ++i) + y = x[i](); + return y; +} +assertEq(testCALLELEM(), 7); diff --git a/js/src/jit-test/tests/basic/testCallFunctionPrototypeInALoop.js b/js/src/jit-test/tests/basic/testCallFunctionPrototypeInALoop.js new file mode 100644 index 0000000000..5930cdc90b --- /dev/null +++ b/js/src/jit-test/tests/basic/testCallFunctionPrototypeInALoop.js @@ -0,0 +1,4 @@ +var x; +for (var a = 0; a < 8; a++) { + Function.prototype() +} diff --git a/js/src/jit-test/tests/basic/testCallPick.js b/js/src/jit-test/tests/basic/testCallPick.js new file mode 100644 index 0000000000..7f1d9ade00 --- /dev/null +++ b/js/src/jit-test/tests/basic/testCallPick.js @@ -0,0 +1,18 @@ +function testCallPick() { + function g(x,a) { + x.f(); + } + + var x = []; + x.f = function() { } + + var y = []; + y.f = function() { } + + var z = [x,x,x,x,x,y,y,y,y,y]; + + for (var i = 0; i < 10; ++i) + g.call(this, z[i], ""); + return true; +} +assertEq(testCallPick(), true); diff --git a/js/src/jit-test/tests/basic/testCallProtoMethod.js b/js/src/jit-test/tests/basic/testCallProtoMethod.js new file mode 100644 index 0000000000..8907871ba0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testCallProtoMethod.js @@ -0,0 +1,14 @@ +function testCallProtoMethod() { + function X() { this.x = 1; } + X.prototype.getName = function () { return "X"; } + + function Y() { this.x = 2; } + Y.prototype.getName = function() { return "Y"; }; + + var a = [new X, new X, new X, new X, new Y]; + var s = ''; + for (var i = 0; i < a.length; i++) + s += a[i].getName(); + return s; +} +assertEq(testCallProtoMethod(), 'XXXXY'); diff --git a/js/src/jit-test/tests/basic/testCaseAbort.js b/js/src/jit-test/tests/basic/testCaseAbort.js new file mode 100644 index 0000000000..4e594bb86e --- /dev/null +++ b/js/src/jit-test/tests/basic/testCaseAbort.js @@ -0,0 +1,16 @@ +function testCaseAbort() +{ + var four = "4"; + var r = 0; + for (var i = 0; i < 5; i++) + { + switch (i) + { + case four: r += 1; break; + default: r += 2; break; + } + } + + return "" + r; +} +assertEq(testCaseAbort(), "10"); diff --git a/js/src/jit-test/tests/basic/testCaseTypeMismatchBadness.js b/js/src/jit-test/tests/basic/testCaseTypeMismatchBadness.js new file mode 100644 index 0000000000..4bacba9aae --- /dev/null +++ b/js/src/jit-test/tests/basic/testCaseTypeMismatchBadness.js @@ -0,0 +1,19 @@ +function testCaseTypeMismatchBadness() +{ + for (var z = 0; z < 3; ++z) + { + switch ("") + { + default: + case 9: + break; + + case "": + case {}: + break; + } + } + + return "no crash"; +} +assertEq(testCaseTypeMismatchBadness(), "no crash"); diff --git a/js/src/jit-test/tests/basic/testChangingObjectWithLength.js b/js/src/jit-test/tests/basic/testChangingObjectWithLength.js new file mode 100644 index 0000000000..9269d0de57 --- /dev/null +++ b/js/src/jit-test/tests/basic/testChangingObjectWithLength.js @@ -0,0 +1,33 @@ +function testChangingObjectWithLength() +{ + var obj = { length: 10 }; + var dense = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + var slow = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; slow.slow = 5; + + /* + * The elements of objs constitute a De Bruijn sequence repeated 4x to trace + * and run native code for every object and transition. + */ + var objs = [obj, obj, obj, obj, + obj, obj, obj, obj, + dense, dense, dense, dense, + obj, obj, obj, obj, + slow, slow, slow, slow, + dense, dense, dense, dense, + dense, dense, dense, dense, + slow, slow, slow, slow, + slow, slow, slow, slow, + obj, obj, obj, obj]; + + var counter = 0; + + for (var i = 0, sz = objs.length; i < sz; i++) + { + var o = objs[i]; + for (var j = 0; j < o.length; j++) + counter++; + } + + return counter; +} +assertEq(testChangingObjectWithLength(), 400); diff --git a/js/src/jit-test/tests/basic/testChangingTypeDuringRecording.js b/js/src/jit-test/tests/basic/testChangingTypeDuringRecording.js new file mode 100644 index 0000000000..5c6a576ca4 --- /dev/null +++ b/js/src/jit-test/tests/basic/testChangingTypeDuringRecording.js @@ -0,0 +1,6 @@ +X = { value: "" } +z = 0; +for (var i = 0; i < 20; i++) { + Object.defineProperty(this, "z", X); + z = 1; +} diff --git a/js/src/jit-test/tests/basic/testClosedVarInExtensibleScope.js b/js/src/jit-test/tests/basic/testClosedVarInExtensibleScope.js new file mode 100644 index 0000000000..f06efa6bda --- /dev/null +++ b/js/src/jit-test/tests/basic/testClosedVarInExtensibleScope.js @@ -0,0 +1,13 @@ +function runTest() {
+ if (Math) {
+ function createTester(options) {
+ return function() {
+ return options.blah;
+ };
+ }
+
+ return createTester({blah:"bar"});
+ }
+}
+
+assertEq(runTest()(), "bar");
diff --git a/js/src/jit-test/tests/basic/testClosingRecursion.js b/js/src/jit-test/tests/basic/testClosingRecursion.js new file mode 100644 index 0000000000..5b76d2ab13 --- /dev/null +++ b/js/src/jit-test/tests/basic/testClosingRecursion.js @@ -0,0 +1,13 @@ +// Test no assert (bug 464089) +function shortRecursiveLoop(b, c) { + for (var i = 0; i < c; i++) { + if (b) + shortRecursiveLoop(c - 1); + } +} +function testClosingRecursion() { + shortRecursiveLoop(false, 1); + shortRecursiveLoop(true, 3); + return true; +} +assertEq(testClosingRecursion(), true); diff --git a/js/src/jit-test/tests/basic/testClosures.js b/js/src/jit-test/tests/basic/testClosures.js new file mode 100644 index 0000000000..a8152c209c --- /dev/null +++ b/js/src/jit-test/tests/basic/testClosures.js @@ -0,0 +1,18 @@ +function testClosures() +{ + function MyObject(id) { + var thisObject = this; + this.id = id; + this.toString = str; + + function str() { + return "" + this.id + thisObject.id; + } + } + + var a = []; + for (var i = 0; i < 5; i++) + a.push(new MyObject(i)); + return a.toString(); +} +assertEq(testClosures(), "00,11,22,33,44"); diff --git a/js/src/jit-test/tests/basic/testComparisons.js b/js/src/jit-test/tests/basic/testComparisons.js new file mode 100644 index 0000000000..b4ae997d54 --- /dev/null +++ b/js/src/jit-test/tests/basic/testComparisons.js @@ -0,0 +1,988 @@ +function testComparisons() +{ + // All the special values from each of the types in + // ECMA-262, 3rd ed. section 8 + var undefinedType, nullType, booleanType, stringType, numberType, objectType; + + var types = []; + types[undefinedType = 0] = "Undefined"; + types[nullType = 1] = "Null"; + types[booleanType = 2] = "Boolean"; + types[stringType = 3] = "String"; + types[numberType = 4] = "Number"; + types[objectType = 5] = "Object"; + + var JSVAL_INT_MIN = -Math.pow(2, 30); + var JSVAL_INT_MAX = Math.pow(2, 30) - 1; + + // Values from every ES3 type, hitting all the edge-case and special values + // that can be dreamed up + var values = + { + "undefined": + { + value: function() { return undefined; }, + type: undefinedType + }, + "null": + { + value: function() { return null; }, + type: nullType + }, + "true": + { + value: function() { return true; }, + type: booleanType + }, + "false": + { + value: function() { return false; }, + type: booleanType + }, + '""': + { + value: function() { return ""; }, + type: stringType + }, + '"a"': + { + // a > [, for string-object comparisons + value: function() { return "a"; }, + type: stringType + }, + '"Z"': + { + // Z < [, for string-object comparisons + value: function() { return "Z"; }, + type: stringType + }, + "0": + { + value: function() { return 0; }, + type: numberType + }, + "-0": + { + value: function() { return -0; }, + type: numberType + }, + "1": + { + value: function() { return 1; }, + type: numberType + }, + "Math.E": + { + value: function() { return Math.E; }, + type: numberType + }, + "JSVAL_INT_MIN - 1": + { + value: function() { return JSVAL_INT_MIN - 1; }, + type: numberType + }, + "JSVAL_INT_MIN": + { + value: function() { return JSVAL_INT_MIN; }, + type: numberType + }, + "JSVAL_INT_MIN + 1": + { + value: function() { return JSVAL_INT_MIN + 1; }, + type: numberType + }, + "JSVAL_INT_MAX - 1": + { + value: function() { return JSVAL_INT_MAX - 1; }, + type: numberType + }, + "JSVAL_INT_MAX": + { + value: function() { return JSVAL_INT_MAX; }, + type: numberType + }, + "JSVAL_INT_MAX + 1": + { + value: function() { return JSVAL_INT_MAX + 1; }, + type: numberType + }, + "Infinity": + { + value: function() { return Infinity; }, + type: numberType + }, + "-Infinity": + { + value: function() { return -Infinity; }, + type: numberType + }, + "NaN": + { + value: function() { return NaN; }, + type: numberType + }, + "{}": + { + value: function() { return {}; }, + type: objectType + }, + "{ valueOf: undefined }": + { + value: function() { return { valueOf: undefined }; }, + type: objectType + }, + "[]": + { + value: function() { return []; }, + type: objectType + }, + '[""]': + { + value: function() { return [""]; }, + type: objectType + }, + '["a"]': + { + value: function() { return ["a"]; }, + type: objectType + }, + "[0]": + { + value: function() { return [0]; }, + type: objectType + } + }; + + var orderOps = + { + "<": function(a, b) { return a < b; }, + ">": function(a, b) { return a > b; }, + "<=": function(a, b) { return a <= b; }, + ">=": function(a, b) { return a >= b; } + }; + var eqOps = + { + "==": function(a, b) { return a == b; }, + "!=": function(a, b) { return a != b; }, + "===": function(a, b) { return a === b; }, + "!==": function(a, b) { return a !== b; } + }; + + + var notEqualIncomparable = + { + eq: { "==": false, "!=": true, "===": false, "!==": true }, + order: { "<": false, ">": false, "<=": false, ">=": false } + }; + var notEqualLessThan = + { + eq: { "==": false, "!=": true, "===": false, "!==": true }, + order: { "<": true, ">": false, "<=": true, ">=": false } + }; + var notEqualGreaterThan = + { + eq: { "==": false, "!=": true, "===": false, "!==": true }, + order: { "<": false, ">": true, "<=": false, ">=": true } + }; + var notEqualNorDifferent = + { + eq: { "==": false, "!=": true, "===": false, "!==": true }, + order: { "<": false, ">": false, "<=": true, ">=": true } + }; + var strictlyEqual = + { + eq: { "==": true, "!=": false, "===": true, "!==": false }, + order: { "<": false, ">": false, "<=": true, ">=": true } + }; + var looselyEqual = + { + eq: { "==": true, "!=": false, "===": false, "!==": true }, + order: { "<": false, ">": false, "<=": true, ">=": true } + }; + var looselyEqualNotDifferent = + { + eq: { "==": true, "!=": false, "===": false, "!==": true }, + order: { "<": false, ">": false, "<=": true, ">=": true } + }; + var looselyEqualIncomparable = + { + eq: { "==": true, "!=": false, "===": false, "!==": true }, + order: { "<": false, ">": false, "<=": false, ">=": false } + }; + var strictlyEqualNotDifferent = + { + eq: { "==": true, "!=": false, "===": true, "!==": false }, + order: { "<": false, ">": false, "<=": true, ">=": true } + }; + var strictlyEqualIncomparable = + { + eq: { "==": true, "!=": false, "===": true, "!==": false }, + order: { "<": false, ">": false, "<=": false, ">=": false } + }; + + var comparingZeroToSomething = + { + "undefined": notEqualIncomparable, + "null": notEqualNorDifferent, + "true": notEqualLessThan, + "false": looselyEqual, + '""': looselyEqualNotDifferent, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": strictlyEqual, + "-0": strictlyEqual, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": looselyEqual, + '[""]': looselyEqual, + '["a"]': notEqualIncomparable, + "[0]": looselyEqual + }; + + var comparingObjectOrObjectWithValueUndefined = + { + "undefined": notEqualIncomparable, + "null": notEqualIncomparable, + "true": notEqualIncomparable, + "false": notEqualIncomparable, + '""': notEqualGreaterThan, + '"a"': notEqualLessThan, + '"Z"': notEqualGreaterThan, + "0": notEqualIncomparable, + "-0": notEqualIncomparable, + "1": notEqualIncomparable, + "Math.E": notEqualIncomparable, + "JSVAL_INT_MIN - 1": notEqualIncomparable, + "JSVAL_INT_MIN": notEqualIncomparable, + "JSVAL_INT_MIN + 1": notEqualIncomparable, + "JSVAL_INT_MAX - 1": notEqualIncomparable, + "JSVAL_INT_MAX": notEqualIncomparable, + "JSVAL_INT_MAX + 1": notEqualIncomparable, + "Infinity": notEqualIncomparable, + "-Infinity": notEqualIncomparable, + "NaN": notEqualIncomparable, + "{}": notEqualNorDifferent, + "{ valueOf: undefined }": notEqualNorDifferent, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualLessThan, + "[0]": notEqualGreaterThan + }; + + // Constructed expected-value matrix + var expected = + { + "undefined": + { + "undefined": strictlyEqualIncomparable, + "null": looselyEqualIncomparable, + "true": notEqualIncomparable, + "false": notEqualIncomparable, + '""': notEqualIncomparable, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualIncomparable, + "-0": notEqualIncomparable, + "1": notEqualIncomparable, + "Math.E": notEqualIncomparable, + "JSVAL_INT_MIN - 1": notEqualIncomparable, + "JSVAL_INT_MIN": notEqualIncomparable, + "JSVAL_INT_MIN + 1": notEqualIncomparable, + "JSVAL_INT_MAX - 1": notEqualIncomparable, + "JSVAL_INT_MAX": notEqualIncomparable, + "JSVAL_INT_MAX + 1": notEqualIncomparable, + "Infinity": notEqualIncomparable, + "-Infinity": notEqualIncomparable, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualIncomparable, + '[""]': notEqualIncomparable, + '["a"]': notEqualIncomparable, + "[0]": notEqualIncomparable + }, + "null": + { + "undefined": looselyEqualIncomparable, + "null": strictlyEqualNotDifferent, + "true": notEqualLessThan, + "false": notEqualNorDifferent, + '""': notEqualNorDifferent, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualNorDifferent, + "-0": notEqualNorDifferent, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualNorDifferent, + '[""]': notEqualNorDifferent, + '["a"]': notEqualIncomparable, + "[0]": notEqualNorDifferent + }, + "true": + { + "undefined": notEqualIncomparable, + "null": notEqualGreaterThan, + "true": strictlyEqual, + "false": notEqualGreaterThan, + '""': notEqualGreaterThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualGreaterThan, + "-0": notEqualGreaterThan, + "1": looselyEqual, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualGreaterThan + }, + "false": + { + "undefined": notEqualIncomparable, + "null": notEqualNorDifferent, + "true": notEqualLessThan, + "false": strictlyEqual, + '""': looselyEqualNotDifferent, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": looselyEqual, + "-0": looselyEqual, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": looselyEqual, + '[""]': looselyEqual, + '["a"]': notEqualIncomparable, + "[0]": looselyEqual + }, + '""': + { + "undefined": notEqualIncomparable, + "null": notEqualNorDifferent, + "true": notEqualLessThan, + "false": looselyEqual, + '""': strictlyEqual, + '"a"': notEqualLessThan, + '"Z"': notEqualLessThan, + "0": looselyEqual, + "-0": looselyEqual, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualLessThan, + "{ valueOf: undefined }": notEqualLessThan, + "[]": looselyEqual, + '[""]': looselyEqual, + '["a"]': notEqualLessThan, + "[0]": notEqualLessThan + }, + '"a"': + { + "undefined": notEqualIncomparable, + "null": notEqualIncomparable, + "true": notEqualIncomparable, + "false": notEqualIncomparable, + '""': notEqualGreaterThan, + '"a"': strictlyEqual, + '"Z"': notEqualGreaterThan, + "0": notEqualIncomparable, + "-0": notEqualIncomparable, + "1": notEqualIncomparable, + "Math.E": notEqualIncomparable, + "JSVAL_INT_MIN - 1": notEqualIncomparable, + "JSVAL_INT_MIN": notEqualIncomparable, + "JSVAL_INT_MIN + 1": notEqualIncomparable, + "JSVAL_INT_MAX - 1": notEqualIncomparable, + "JSVAL_INT_MAX": notEqualIncomparable, + "JSVAL_INT_MAX + 1": notEqualIncomparable, + "Infinity": notEqualIncomparable, + "-Infinity": notEqualIncomparable, + "NaN": notEqualIncomparable, + "{}": notEqualGreaterThan, + "{ valueOf: undefined }": notEqualGreaterThan, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': looselyEqualNotDifferent, + "[0]": notEqualGreaterThan + }, + '"Z"': + { + "undefined": notEqualIncomparable, + "null": notEqualIncomparable, + "true": notEqualIncomparable, + "false": notEqualIncomparable, + '""': notEqualGreaterThan, + '"a"': notEqualLessThan, + '"Z"': strictlyEqual, + "0": notEqualIncomparable, + "-0": notEqualIncomparable, + "1": notEqualIncomparable, + "Math.E": notEqualIncomparable, + "JSVAL_INT_MIN - 1": notEqualIncomparable, + "JSVAL_INT_MIN": notEqualIncomparable, + "JSVAL_INT_MIN + 1": notEqualIncomparable, + "JSVAL_INT_MAX - 1": notEqualIncomparable, + "JSVAL_INT_MAX": notEqualIncomparable, + "JSVAL_INT_MAX + 1": notEqualIncomparable, + "Infinity": notEqualIncomparable, + "-Infinity": notEqualIncomparable, + "NaN": notEqualIncomparable, + "{}": notEqualLessThan, + "{ valueOf: undefined }": notEqualLessThan, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualLessThan, + "[0]": notEqualGreaterThan + }, + "0": comparingZeroToSomething, + "-0": comparingZeroToSomething, + "1": + { + "undefined": notEqualIncomparable, + "null": notEqualGreaterThan, + "true": looselyEqual, + "false": notEqualGreaterThan, + '""': notEqualGreaterThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualGreaterThan, + "-0": notEqualGreaterThan, + "1": strictlyEqual, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualGreaterThan + }, + "Math.E": + { + "undefined": notEqualIncomparable, + "null": notEqualGreaterThan, + "true": notEqualGreaterThan, + "false": notEqualGreaterThan, + '""': notEqualGreaterThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualGreaterThan, + "-0": notEqualGreaterThan, + "1": notEqualGreaterThan, + "Math.E": strictlyEqual, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualGreaterThan + }, + "JSVAL_INT_MIN - 1": + { + "undefined": notEqualIncomparable, + "null": notEqualLessThan, + "true": notEqualLessThan, + "false": notEqualLessThan, + '""': notEqualLessThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualLessThan, + "-0": notEqualLessThan, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": strictlyEqual, + "JSVAL_INT_MIN": notEqualLessThan, + "JSVAL_INT_MIN + 1": notEqualLessThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualLessThan, + '[""]': notEqualLessThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualLessThan + }, + "JSVAL_INT_MIN": + { + "undefined": notEqualIncomparable, + "null": notEqualLessThan, + "true": notEqualLessThan, + "false": notEqualLessThan, + '""': notEqualLessThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualLessThan, + "-0": notEqualLessThan, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": strictlyEqual, + "JSVAL_INT_MIN + 1": notEqualLessThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualLessThan, + '[""]': notEqualLessThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualLessThan + }, + "JSVAL_INT_MIN + 1": + { + "undefined": notEqualIncomparable, + "null": notEqualLessThan, + "true": notEqualLessThan, + "false": notEqualLessThan, + '""': notEqualLessThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualLessThan, + "-0": notEqualLessThan, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": strictlyEqual, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualLessThan, + '[""]': notEqualLessThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualLessThan + }, + "JSVAL_INT_MAX - 1": + { + "undefined": notEqualIncomparable, + "null": notEqualGreaterThan, + "true": notEqualGreaterThan, + "false": notEqualGreaterThan, + '""': notEqualGreaterThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualGreaterThan, + "-0": notEqualGreaterThan, + "1": notEqualGreaterThan, + "Math.E": notEqualGreaterThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": strictlyEqual, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualGreaterThan + }, + "JSVAL_INT_MAX": + { + "undefined": notEqualIncomparable, + "null": notEqualGreaterThan, + "true": notEqualGreaterThan, + "false": notEqualGreaterThan, + '""': notEqualGreaterThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualGreaterThan, + "-0": notEqualGreaterThan, + "1": notEqualGreaterThan, + "Math.E": notEqualGreaterThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualGreaterThan, + "JSVAL_INT_MAX": strictlyEqual, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualGreaterThan + }, + "JSVAL_INT_MAX + 1": + { + "undefined": notEqualIncomparable, + "null": notEqualGreaterThan, + "true": notEqualGreaterThan, + "false": notEqualGreaterThan, + '""': notEqualGreaterThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualGreaterThan, + "-0": notEqualGreaterThan, + "1": notEqualGreaterThan, + "Math.E": notEqualGreaterThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualGreaterThan, + "JSVAL_INT_MAX": notEqualGreaterThan, + "JSVAL_INT_MAX + 1": strictlyEqual, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualGreaterThan + }, + "Infinity": + { + "undefined": notEqualIncomparable, + "null": notEqualGreaterThan, + "true": notEqualGreaterThan, + "false": notEqualGreaterThan, + '""': notEqualGreaterThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualGreaterThan, + "-0": notEqualGreaterThan, + "1": notEqualGreaterThan, + "Math.E": notEqualGreaterThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualGreaterThan, + "JSVAL_INT_MAX": notEqualGreaterThan, + "JSVAL_INT_MAX + 1": notEqualGreaterThan, + "Infinity": strictlyEqual, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualGreaterThan + }, + "-Infinity": + { + "undefined": notEqualIncomparable, + "null": notEqualLessThan, + "true": notEqualLessThan, + "false": notEqualLessThan, + '""': notEqualLessThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualLessThan, + "-0": notEqualLessThan, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualLessThan, + "JSVAL_INT_MIN": notEqualLessThan, + "JSVAL_INT_MIN + 1": notEqualLessThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": strictlyEqual, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualLessThan, + '[""]': notEqualLessThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualLessThan + }, + "NaN": + { + "undefined": notEqualIncomparable, + "null": notEqualIncomparable, + "true": notEqualIncomparable, + "false": notEqualIncomparable, + '""': notEqualIncomparable, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualIncomparable, + "-0": notEqualIncomparable, + "1": notEqualIncomparable, + "Math.E": notEqualIncomparable, + "JSVAL_INT_MIN - 1": notEqualIncomparable, + "JSVAL_INT_MIN": notEqualIncomparable, + "JSVAL_INT_MIN + 1": notEqualIncomparable, + "JSVAL_INT_MAX - 1": notEqualIncomparable, + "JSVAL_INT_MAX": notEqualIncomparable, + "JSVAL_INT_MAX + 1": notEqualIncomparable, + "Infinity": notEqualIncomparable, + "-Infinity": notEqualIncomparable, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualIncomparable, + '[""]': notEqualIncomparable, + '["a"]': notEqualIncomparable, + "[0]": notEqualIncomparable + }, + "{}": comparingObjectOrObjectWithValueUndefined, + "{ valueOf: undefined }": comparingObjectOrObjectWithValueUndefined, + "[]": + { + "undefined": notEqualIncomparable, + "null": notEqualNorDifferent, + "true": notEqualLessThan, + "false": looselyEqual, + '""': looselyEqual, + '"a"': notEqualLessThan, + '"Z"': notEqualLessThan, + "0": looselyEqual, + "-0": looselyEqual, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualLessThan, + "{ valueOf: undefined }": notEqualLessThan, + "[]": notEqualNorDifferent, + '[""]': notEqualNorDifferent, + '["a"]': notEqualLessThan, + "[0]": notEqualLessThan + }, + '[""]': + { + "undefined": notEqualIncomparable, + "null": notEqualNorDifferent, + "true": notEqualLessThan, + "false": looselyEqual, + '""': looselyEqual, + '"a"': notEqualLessThan, + '"Z"': notEqualLessThan, + "0": looselyEqual, + "-0": looselyEqual, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualLessThan, + "{ valueOf: undefined }": notEqualLessThan, + "[]": notEqualNorDifferent, + '[""]': notEqualNorDifferent, + '["a"]': notEqualLessThan, + "[0]": notEqualLessThan + }, + '["a"]': + { + "undefined": notEqualIncomparable, + "null": notEqualIncomparable, + "true": notEqualIncomparable, + "false": notEqualIncomparable, + '""': notEqualGreaterThan, + '"a"': looselyEqual, + '"Z"': notEqualGreaterThan, + "0": notEqualIncomparable, + "-0": notEqualIncomparable, + "1": notEqualIncomparable, + "Math.E": notEqualIncomparable, + "JSVAL_INT_MIN - 1": notEqualIncomparable, + "JSVAL_INT_MIN": notEqualIncomparable, + "JSVAL_INT_MIN + 1": notEqualIncomparable, + "JSVAL_INT_MAX - 1": notEqualIncomparable, + "JSVAL_INT_MAX": notEqualIncomparable, + "JSVAL_INT_MAX + 1": notEqualIncomparable, + "Infinity": notEqualIncomparable, + "-Infinity": notEqualIncomparable, + "NaN": notEqualIncomparable, + "{}": notEqualGreaterThan, + "{ valueOf: undefined }": notEqualGreaterThan, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualNorDifferent, + "[0]": notEqualGreaterThan + }, + "[0]": + { + "undefined": notEqualIncomparable, + "null": notEqualNorDifferent, + "true": notEqualLessThan, + "false": looselyEqual, + '""': notEqualGreaterThan, + '"a"': notEqualLessThan, + '"Z"': notEqualLessThan, + "0": looselyEqual, + "-0": looselyEqual, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualLessThan, + "{ valueOf: undefined }": notEqualLessThan, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualLessThan, + "[0]": notEqualNorDifferent + } + }; + + + + var failures = []; + function fail(a, ta, b, tb, ex, ac, op) + { + failures.push("(" + a + " " + op + " " + b + ") wrong: " + + "expected " + ex + ", got " + ac + + " (types " + types[ta] + ", " + types[tb] + ")"); + } + + var result = false; + for (var i in values) + { + for (var j in values) + { + // Constants, so hoist to help JIT know that + var vala = values[i], valb = values[j]; + var a = vala.value(), b = valb.value(); + + for (var opname in orderOps) + { + var op = orderOps[opname]; + var expect = expected[i][j].order[opname]; + var failed = false; + + for (var iter = 0; iter < 5; iter++) + { + result = op(a, b); + failed = failed || result !== expect; + } + + if (failed) + fail(i, vala.type, j, valb.type, expect, result, opname); + } + + for (var opname in eqOps) + { + var op = eqOps[opname]; + var expect = expected[i][j].eq[opname]; + var failed = false; + + for (var iter = 0; iter < 5; iter++) + { + result = op(a, b); + failed = failed || result !== expect; + } + + if (failed) + fail(i, vala.type, j, valb.type, expect, result, opname); + } + } + } + + if (failures.length == 0) + return "no failures reported!"; + + return "\n" + failures.join(",\n"); +} +assertEq(testComparisons(), "no failures reported!"); diff --git a/js/src/jit-test/tests/basic/testConcatNWithSideEffects.js b/js/src/jit-test/tests/basic/testConcatNWithSideEffects.js new file mode 100644 index 0000000000..b7b636e5d8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testConcatNWithSideEffects.js @@ -0,0 +1,12 @@ +var log; +function b(x) { log += 'b'; return 'B'; } +function g() { + log = ''; + var a = {toString: function () { log += 'a'; return 'A'; }}; + assertEq("[" + a + b() + "]", "[AB]"); + assertEq(log, "ab"); +} + +for (var i = 0; i < 1000; ++i) + g(); + diff --git a/js/src/jit-test/tests/basic/testCondSwitch1.js b/js/src/jit-test/tests/basic/testCondSwitch1.js new file mode 100644 index 0000000000..a1318fb574 --- /dev/null +++ b/js/src/jit-test/tests/basic/testCondSwitch1.js @@ -0,0 +1,46 @@ +function get(x) { + return x; +} + +function f(x) { + switch(x) { + case get(0): + return 0; + case get(1): + return 1; + case get("foo"): + return "foo"; + case get(true): + return true; + case get(false): + return false; + case get({}): + return {}; + case get(null): + return null; + case Number.MIN_VALUE: + return Number.MIN_VALUE; + case Math: + return Math; + default: + return -123; + } +} + +assertEq(f(0), 0); +assertEq(f(-0), 0); +assertEq(f(1), 1); +assertEq(f("foo"), "foo"); +assertEq(f(true), true); +assertEq(f(false), false); +assertEq(f({}), -123); +assertEq(f([]), -123); +assertEq(f(Math), Math); + +assertEq(f({x:1}), -123); +assertEq(f(333), -123); +assertEq(f(null), null); +assertEq(f(undefined), -123); + +assertEq(f(Number.MIN_VALUE), Number.MIN_VALUE); + diff --git a/js/src/jit-test/tests/basic/testCondSwitch2.js b/js/src/jit-test/tests/basic/testCondSwitch2.js new file mode 100644 index 0000000000..39bb5347a1 --- /dev/null +++ b/js/src/jit-test/tests/basic/testCondSwitch2.js @@ -0,0 +1,33 @@ + +var C1 = 1; +var C2 = 2; +const C3 = 3; + +function f(x) { + var s = ""; + + switch(x) { + case C1: + s += "1"; + case C2: + s += "2"; + break; + case C3: + s += "3"; + default: + s += "d"; + case 4: + s += "4"; + } + return s; +} +assertEq(f(1), "12"); +assertEq(f(2), "2"); +assertEq(f(3), "3d4"); +assertEq(f(4), "4"); + +assertEq(f(0), "d4"); +assertEq(f(-0), "d4"); + +assertEq(f(true), "d4"); + diff --git a/js/src/jit-test/tests/basic/testCondSwitch3.js b/js/src/jit-test/tests/basic/testCondSwitch3.js new file mode 100644 index 0000000000..43ea73b7ef --- /dev/null +++ b/js/src/jit-test/tests/basic/testCondSwitch3.js @@ -0,0 +1,22 @@ + +var C1 = 1; + +function f(x) { + var s = ""; + + switch(x) { + case 0: + s += "0"; + case C1: + s += "1"; + } + return s; +} + +assertEq(f(0), "01"); +assertEq(f(1), "1"); +assertEq(f(2), ""); + +assertEq(f(true), ""); +assertEq(f(Math), ""); + diff --git a/js/src/jit-test/tests/basic/testConstDestructringArguments.js b/js/src/jit-test/tests/basic/testConstDestructringArguments.js new file mode 100644 index 0000000000..e07d93a55f --- /dev/null +++ b/js/src/jit-test/tests/basic/testConstDestructringArguments.js @@ -0,0 +1,3 @@ +// |jit-test| error: TypeError + +(function () { const [arguments] = 0; })(); diff --git a/js/src/jit-test/tests/basic/testConstIf.js b/js/src/jit-test/tests/basic/testConstIf.js new file mode 100644 index 0000000000..2fcde1caf0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testConstIf.js @@ -0,0 +1,6 @@ +function testConstIf() { + var x; + for (var j=0;j<5;++j) { if (1.1 || 5) { } x = 2;} + return x; +} +assertEq(testConstIf(), 2); diff --git a/js/src/jit-test/tests/basic/testConstSwitch.js b/js/src/jit-test/tests/basic/testConstSwitch.js new file mode 100644 index 0000000000..f98959adf8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testConstSwitch.js @@ -0,0 +1,13 @@ +// No test case, just make sure this doesn't assert. +function testNegZero2() { + var z = 0; + for (let j = 0; j < 5; ++j) { ({p: (-z)}); } +} +testNegZero2(); + +function testConstSwitch() { + var x; + for (var j=0;j<5;++j) { switch(1.1) { case NaN: case 2: } x = 2; } + return x; +} +assertEq(testConstSwitch(), 2); diff --git a/js/src/jit-test/tests/basic/testConstSwitch2.js b/js/src/jit-test/tests/basic/testConstSwitch2.js new file mode 100644 index 0000000000..48d5f2c9df --- /dev/null +++ b/js/src/jit-test/tests/basic/testConstSwitch2.js @@ -0,0 +1,6 @@ +function testConstSwitch2() { + var x; + for (var j = 0; j < 4; ++j) { switch(0/0) { } } + return "ok"; +} +assertEq(testConstSwitch2(), "ok"); diff --git a/js/src/jit-test/tests/basic/testConstantBooleanExpr.js b/js/src/jit-test/tests/basic/testConstantBooleanExpr.js new file mode 100644 index 0000000000..8cc5f34822 --- /dev/null +++ b/js/src/jit-test/tests/basic/testConstantBooleanExpr.js @@ -0,0 +1,6 @@ +function testConstantBooleanExpr() +{ + for (var j = 0; j < 3; ++j) { if(true <= true) { } } + return "ok"; +} +assertEq(testConstantBooleanExpr(), "ok"); diff --git a/js/src/jit-test/tests/basic/testConstructorArgs-1.js b/js/src/jit-test/tests/basic/testConstructorArgs-1.js new file mode 100644 index 0000000000..46b6c4e08a --- /dev/null +++ b/js/src/jit-test/tests/basic/testConstructorArgs-1.js @@ -0,0 +1,11 @@ +function f(a, b) { + this.a = a; + assertEq(b, 'x'); +} + +for (var x = 0; x < 9; ++x) { + f.prototype = {}; + var obj = new f(x, 'x'); + assertEq(obj.a, x); + assertEq(Object.getPrototypeOf(obj), f.prototype); +} diff --git a/js/src/jit-test/tests/basic/testConstructorArgs-2.js b/js/src/jit-test/tests/basic/testConstructorArgs-2.js new file mode 100644 index 0000000000..0a8292dd8c --- /dev/null +++ b/js/src/jit-test/tests/basic/testConstructorArgs-2.js @@ -0,0 +1,12 @@ +function f(a, b, c) { + this.a = a; + assertEq(b, 'x'); + assertEq(c, void 0); +} + +for (var x = 0; x < 9; ++x) { + f.prototype = {}; + var obj = new f(x, 'x'); // fewer than f.length arguments + assertEq(obj.a, x); + assertEq(Object.getPrototypeOf(obj), f.prototype); +} diff --git a/js/src/jit-test/tests/basic/testConstructorArgs-3.js b/js/src/jit-test/tests/basic/testConstructorArgs-3.js new file mode 100644 index 0000000000..eb594b3dd8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testConstructorArgs-3.js @@ -0,0 +1,11 @@ +function f(a) { + this.a = a; + assertEq(arguments[1], 'x'); +} + +for (var x = 0; x < 9; ++x) { + f.prototype = {}; + var obj = new f(x, 'x'); // more than f.length arguments + assertEq(obj.a, x); + assertEq(Object.getPrototypeOf(obj), f.prototype); +} diff --git a/js/src/jit-test/tests/basic/testConstructorBail.js b/js/src/jit-test/tests/basic/testConstructorBail.js new file mode 100644 index 0000000000..0cd3397f73 --- /dev/null +++ b/js/src/jit-test/tests/basic/testConstructorBail.js @@ -0,0 +1,4 @@ +function testConstructorBail() { + for (let i = 0; i < 5; ++i) new Number(/x/); +} +testConstructorBail(); diff --git a/js/src/jit-test/tests/basic/testContinue.js b/js/src/jit-test/tests/basic/testContinue.js new file mode 100644 index 0000000000..a878bbb930 --- /dev/null +++ b/js/src/jit-test/tests/basic/testContinue.js @@ -0,0 +1,11 @@ +function testContinue() { + var i; + var total = 0; + for (i = 0; i < 20; ++i) { + if (i == 11) + continue; + total++; + } + return total; +} +assertEq(testContinue(), 19); diff --git a/js/src/jit-test/tests/basic/testContinueWithLabel.js b/js/src/jit-test/tests/basic/testContinueWithLabel.js new file mode 100644 index 0000000000..b851b41de8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testContinueWithLabel.js @@ -0,0 +1,16 @@ +function testContinueWithLabel() { + var i = 0; + var j = 20; + checkiandj : + while (i < 10) { + i += 1; + checkj : + while (j > 10) { + j -= 1; + if ((j % 2) == 0) + continue checkj; + } + } + return i + j; +} +assertEq(testContinueWithLabel(), 20); diff --git a/js/src/jit-test/tests/basic/testContinueWithLabel3.js b/js/src/jit-test/tests/basic/testContinueWithLabel3.js new file mode 100644 index 0000000000..14ef74bc66 --- /dev/null +++ b/js/src/jit-test/tests/basic/testContinueWithLabel3.js @@ -0,0 +1,6 @@ +// bug 511575 comment 3 +outer: +for (var j = 0; j < 10; j++) + for (var p in {x:1}) + if (p > "q") + continue outer; diff --git a/js/src/jit-test/tests/basic/testContinueWithLabel4.js b/js/src/jit-test/tests/basic/testContinueWithLabel4.js new file mode 100644 index 0000000000..739726c7a2 --- /dev/null +++ b/js/src/jit-test/tests/basic/testContinueWithLabel4.js @@ -0,0 +1,25 @@ +// bug 511575 + +Function.prototype.X = 42; + +function ownProperties() { + var props = {}; + var r = function () {}; + + outer: + for (var a in r) { + for (var b in r) { + if (a == b) { + continue outer; + } + } + print("SHOULD NOT BE REACHED"); + props[a] = true; + } + return props; +} + +for (var i = 0; i < 12; ++i) { + print(i); + ownProperties(); +} diff --git a/js/src/jit-test/tests/basic/testConvertibleObjectEqUndefined.js b/js/src/jit-test/tests/basic/testConvertibleObjectEqUndefined.js new file mode 100644 index 0000000000..89431affe8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testConvertibleObjectEqUndefined.js @@ -0,0 +1,30 @@ +function x4(v) { return "" + v + v + v + v; } +function testConvertibleObjectEqUndefined() +{ + var compares = + [ + false, false, false, false, + undefined, undefined, undefined, undefined, + false, false, false, false, + undefined, undefined, undefined, undefined, + false, false, false, false, + undefined, undefined, undefined, undefined, + false, false, false, false, + undefined, undefined, undefined, undefined, + false, false, false, false, + undefined, undefined, undefined, undefined, + ]; + var count = 0; + var obj = { valueOf: function() { count++; return 1; } }; + var results = compares.map(function(v) { return "unwritten"; }); + + for (var i = 0, sz = compares.length; i < sz; i++) + results[i] = compares[i] == obj; + + return results.join("") + count; +} + +assertEq(testConvertibleObjectEqUndefined(), + x4(false) + x4(false) + x4(false) + x4(false) + x4(false) + x4(false) + + x4(false) + x4(false) + x4(false) + x4(false) + "20"); + diff --git a/js/src/jit-test/tests/basic/testCrossCompartmentTransparency.js b/js/src/jit-test/tests/basic/testCrossCompartmentTransparency.js new file mode 100644 index 0000000000..9745432352 --- /dev/null +++ b/js/src/jit-test/tests/basic/testCrossCompartmentTransparency.js @@ -0,0 +1,165 @@ +// |jit-test| error: done + +var g1 = newGlobal('same-compartment'); +var g2 = newGlobal(); +var proxyStr = "new Proxy({}, "+ +" { getOwnPropertyDescriptor: () =>assertEq(true,false), "+ +" ownKeys: () =>assertEq(true,false), "+ +" defineProperty: () =>assertEq(true,false), "+ +" deleteProperty: () =>assertEq(true,false), "+ +" get: () =>assertEq(true,false), "+ +" set: () =>assertEq(true,false), "+ +"}); "; +var proxy1 = g1.eval(proxyStr); +var proxy2 = g2.eval(proxyStr); + +var test = (function() { +"use strict"; +return function test(str, f, isGeneric = false) { + + var x = f(eval(str)); + assertEq(x, f(g1.eval(str))); + assertEq(x, f(g2.eval(str))); + + var threw = false; + try { + f(g1.eval("new Object()")); + } catch (e) { + assertEq(Object.prototype.toString.call(e), "[object Error]"); + threw = true; + } + assertEq(threw, !isGeneric); + threw = false; + try { + f(g2.eval("new Object()")); + } catch (e) { + assertEq(Object.prototype.toString.call(e), "[object Error]"); + threw = true; + } + assertEq(threw, !isGeneric); + threw = false; + try { + f(proxy1); + } catch (e) { + assertEq(Object.prototype.toString.call(e), "[object Error]"); + threw = true; + } + assertEq(threw, !isGeneric); + threw = false; + try { + f(proxy2); + } catch (e) { + assertEq(Object.prototype.toString.call(e), "[object Error]"); + threw = true; + } + assertEq(threw, !isGeneric); +} +})(); + +if (Boolean.prototype.toSource) { + test("new Boolean(true)", b => Boolean.prototype.toSource.call(b)); +} +test("new Boolean(true)", b => Boolean.prototype.toString.call(b)); +test("new Boolean(true)", b => Boolean.prototype.valueOf.call(b)); +if (Number.prototype.toSource) { + test("new Number(1)", n => Number.prototype.toSource.call(n)); +} +test("new Number(1)", n => Number.prototype.toString.call(n)); +test("new Number(1)", n => Number.prototype.valueOf.call(n)); +test("new Number(1)", n => Number.prototype.toFixed.call(n)); +test("new Number(1)", n => Number.prototype.toExponential.call(n)); +test("new Number(1)", n => Number.prototype.toPrecision.call(n)); +test("(function*(){yield 1})()", i => (function*(){yield})().next.call(i).toString()); +if (String.prototype.toSource) { + test("new String('one')", s => String.prototype.toSource.call(s)); +} +test("new String('one')", s => String.prototype.toString.call(s)); +test("new RegExp('1')", r => RegExp.prototype.exec.call(r, '1').toString()); +test("new RegExp('1')", r => RegExp.prototype.test.call(r, '1')); +test("new RegExp('1')", r => RegExp.prototype.compile.call(r, '1').toString()); +test("new RegExp('1')", r => assertEq("a1".search(r), 1)); +test("new RegExp('1')", r => assertEq("a1".match(r)[0], '1')); +test("new RegExp('1')", r => assertEq("a1".replace(r, 'A'), 'aA')); +test("new RegExp('1')", r => assertEq(String("a1b".split(r)), "a,b")); +test("new RegExp('1')", r => assertEq(String(new RegExp(r)), String(r))); +test("new RegExp('1')", r => assertEq(String(/x/.compile(r)), String(r))); +test("new WeakMap()", w => WeakMap.prototype.has.call(w, {})); +test("new WeakMap()", w => WeakMap.prototype.get.call(w, {})); +test("new WeakMap()", w => WeakMap.prototype.delete.call(w, {})); +test("new WeakMap()", w => WeakMap.prototype.set.call(w, {}).toString()); +test("new Map()", w => Map.prototype.has.call(w, {})); +test("new Map()", w => Map.prototype.get.call(w, {})); +test("new Map()", w => Map.prototype.delete.call(w, {})); +test("new Map()", w => Map.prototype.set.call(w, {}).toString()); +test("new Set()", w => Set.prototype.has.call(w, {})); +test("new Set()", w => Set.prototype.add.call(w, {}).toString()); +test("new Set()", w => Set.prototype.delete.call(w, {})); + +test("new Int8Array(1)", a => Int8Array.prototype.subarray.call(a).toString()); +test("new Uint8Array(1)", a => Uint8Array.prototype.subarray.call(a).toString()); +test("new Int16Array(1)", a => Int16Array.prototype.subarray.call(a).toString()); +test("new Uint16Array(1)", a => Uint16Array.prototype.subarray.call(a).toString()); +test("new Int32Array(1)", a => Int32Array.prototype.subarray.call(a).toString()); +test("new Uint32Array(1)", a => Uint32Array.prototype.subarray.call(a).toString()); +test("new Float32Array(1)", a => Float32Array.prototype.subarray.call(a).toString()); +test("new Float64Array(1)", a => Float64Array.prototype.subarray.call(a).toString()); +test("new Uint8ClampedArray(1)", a => Uint8ClampedArray.prototype.subarray.call(a).toString()); + +test("new Int8Array(1)", a => Int8Array.prototype.set.call(a, [])); +test("new Uint8Array(1)", a => Uint8Array.prototype.set.call(a, [])); +test("new Int16Array(1)", a => Int16Array.prototype.set.call(a, [])); +test("new Uint16Array(1)", a => Uint16Array.prototype.set.call(a, [])); +test("new Int32Array(1)", a => Int32Array.prototype.set.call(a, [])); +test("new Uint32Array(1)", a => Uint32Array.prototype.set.call(a, [])); +test("new Float32Array(1)", a => Float32Array.prototype.set.call(a, [])); +test("new Float64Array(1)", a => Float64Array.prototype.set.call(a, [])); +test("new Uint8ClampedArray(1)", a => Uint8ClampedArray.prototype.set.call(a, [])); + +function justDontThrow() {} +test("new Date()", d => justDontThrow(Date.prototype.getTime.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getYear.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getFullYear.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getUTCFullYear.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getMonth.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getUTCMonth.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getDate.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getUTCDate.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getDay.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getUTCDay.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getHours.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getUTCHours.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getMinutes.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getUTCMinutes.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getSeconds.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getUTCSeconds.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.getTimezoneOffset.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setTime.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setMilliseconds.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setUTCMilliseconds.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setSeconds.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setUTCSeconds.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setMinutes.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setUTCMinutes.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setHours.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setUTCHours.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setDate.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setUTCDate.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setMonth.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setUTCMonth.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setFullYear.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setUTCFullYear.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.setYear.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.toGMTString.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.toISOString.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.toLocaleString.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.toLocaleDateString.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.toLocaleTimeString.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.toTimeString.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.toDateString.call(d))); +if (Date.prototype.toSource) { + test("new Date()", d => justDontThrow(Date.prototype.toSource.call(d))); +} +test("new Date()", d => justDontThrow(Date.prototype.toString.call(d))); +test("new Date()", d => justDontThrow(Date.prototype.valueOf.call(d))); + +throw "done"; diff --git a/js/src/jit-test/tests/basic/testCrossCompartmentTransparency2.js b/js/src/jit-test/tests/basic/testCrossCompartmentTransparency2.js new file mode 100644 index 0000000000..39319bc96a --- /dev/null +++ b/js/src/jit-test/tests/basic/testCrossCompartmentTransparency2.js @@ -0,0 +1,15 @@ +var g = newGlobal(); + +var array = g.eval("new Array(1,2,3)"); +assertEq([array,array].concat().toString(), "1,2,3,1,2,3"); +assertEq(Array.isArray(array), true); + +var number = g.eval("new Number(42)"); +var bool = g.eval("new Boolean(false)"); +var string = g.eval("new String('ponies')"); +assertEq(JSON.stringify({n:number, b:bool, s:string}), "{\"n\":42,\"b\":false,\"s\":\"ponies\"}"); +assertEq(JSON.stringify({arr:array}), "{\"arr\":[1,2,3]}"); +assertEq(JSON.stringify({2:'ponies', unicorns:'not real'}, array), "{\"2\":\"ponies\"}"); +assertEq(JSON.stringify({42:true, ponies:true, unicorns:'sad'}, [number, string]), "{\"42\":true,\"ponies\":true}"); +assertEq(JSON.stringify({a:true,b:false}, undefined, number), "{\n \"a\": true,\n \"b\": false\n}"); +assertEq(JSON.stringify({a:true,b:false}, undefined, string), "{\nponies\"a\": true,\nponies\"b\": false\n}"); diff --git a/js/src/jit-test/tests/basic/testDateNow.js b/js/src/jit-test/tests/basic/testDateNow.js new file mode 100644 index 0000000000..0a186caa28 --- /dev/null +++ b/js/src/jit-test/tests/basic/testDateNow.js @@ -0,0 +1,10 @@ +function testDateNow() { + // Accessing global.Date for the first time will change the global shape, + // so do it before the loop starts; otherwise we have to loop an extra time + // to pick things up. + var time = Date.now(); + for (var j = 0; j < 9; ++j) + time = Date.now(); + return "ok"; +} +assertEq(testDateNow(), "ok"); diff --git a/js/src/jit-test/tests/basic/testDecElem1.js b/js/src/jit-test/tests/basic/testDecElem1.js new file mode 100644 index 0000000000..6739cab40e --- /dev/null +++ b/js/src/jit-test/tests/basic/testDecElem1.js @@ -0,0 +1,7 @@ +var obj = {p: 100}; +var name = "p"; +var a = []; +for (var i = 0; i < 10; i++) + a[i] = --obj[name]; +assertEq(a.join(','), '99,98,97,96,95,94,93,92,91,90'); +assertEq(obj.p, 90); diff --git a/js/src/jit-test/tests/basic/testDecElem2.js b/js/src/jit-test/tests/basic/testDecElem2.js new file mode 100644 index 0000000000..8fe74ff50f --- /dev/null +++ b/js/src/jit-test/tests/basic/testDecElem2.js @@ -0,0 +1,11 @@ +var obj = {s: ""}; +var name = "s"; +var a = []; +for (var i = 0; i <= 13; i++) { + a[i] = 'x'; + if (i > 8) + a[i] = --obj[name]; // first recording changes obj.s from string to number +} +assertEq(a.join(','), Array(10).join('x,') + '-1,-2,-3,-4,-5'); +assertEq(obj.s, -5); + diff --git a/js/src/jit-test/tests/basic/testDecayingInnerLoop.js b/js/src/jit-test/tests/basic/testDecayingInnerLoop.js new file mode 100644 index 0000000000..92e985cd6c --- /dev/null +++ b/js/src/jit-test/tests/basic/testDecayingInnerLoop.js @@ -0,0 +1,9 @@ +function testDecayingInnerLoop() { + var i, j, k = 10; + for (i = 0; i < 5000; ++i) { + for (j = 0; j < k; ++j); + --k; + } + return i; +} +assertEq(testDecayingInnerLoop(), 5000); diff --git a/js/src/jit-test/tests/basic/testDeepBail1.js b/js/src/jit-test/tests/basic/testDeepBail1.js new file mode 100644 index 0000000000..779f96597e --- /dev/null +++ b/js/src/jit-test/tests/basic/testDeepBail1.js @@ -0,0 +1,6 @@ +function testDeepBail1() { + var y = [1,2,3]; + for (var i = 0; i < 9; i++) + "" in y; +} +testDeepBail1(); diff --git a/js/src/jit-test/tests/basic/testDeepBailFromHasInstance.js b/js/src/jit-test/tests/basic/testDeepBailFromHasInstance.js new file mode 100644 index 0000000000..6be2576838 --- /dev/null +++ b/js/src/jit-test/tests/basic/testDeepBailFromHasInstance.js @@ -0,0 +1,12 @@ +var arr = [Math, Math, Math, Math, {}]; +var obj = {}; +var x; +var result = 'no error'; +try { + for (var i = 0; i < arr.length; i++) + x = (obj instanceof arr[i]); // last iteration throws, triggering deep bail +} catch (exc) { + result = exc.constructor.name; +} +assertEq(result, 'TypeError'); + diff --git a/js/src/jit-test/tests/basic/testDeepBailInMoreIter.js b/js/src/jit-test/tests/basic/testDeepBailInMoreIter.js new file mode 100644 index 0000000000..85c9f470f7 --- /dev/null +++ b/js/src/jit-test/tests/basic/testDeepBailInMoreIter.js @@ -0,0 +1,5 @@ +w = (function*() { yield })(); +w.next(); +for (var i = 0; i < 100; ++i) { + for (v of w) {} +} diff --git a/js/src/jit-test/tests/basic/testDeepBailWhileRecording.js b/js/src/jit-test/tests/basic/testDeepBailWhileRecording.js new file mode 100644 index 0000000000..17c1086aa1 --- /dev/null +++ b/js/src/jit-test/tests/basic/testDeepBailWhileRecording.js @@ -0,0 +1,15 @@ +var o = {}; +var arr = [o,o,o,o,o,o,o,o,o,o,o,o,o]; +var out = []; + +const OUTER = 10; + +for (var i = 0; i < 10; ++i) { + for (var j = 0; j < arr.length; ++j) { + out.push(String.prototype.indexOf.call(arr[i], 'object')); + } +} + +assertEq(out.length, 10 * arr.length); +for (var i = 0; i < out.length; ++i) + assertEq(out[i], 1); diff --git a/js/src/jit-test/tests/basic/testDeepPropertyShadowing.js b/js/src/jit-test/tests/basic/testDeepPropertyShadowing.js new file mode 100644 index 0000000000..65dbf8d5eb --- /dev/null +++ b/js/src/jit-test/tests/basic/testDeepPropertyShadowing.js @@ -0,0 +1,17 @@ +function testDeepPropertyShadowing() +{ + function h(node) { + var x = 0; + while (node) { + x++; + node = node.parent; + } + return x; + } + var tree = {__proto__: {__proto__: {parent: null}}}; + h(tree); + h(tree); + tree.parent = {}; + assertEq(h(tree), 2); +} +testDeepPropertyShadowing(); diff --git a/js/src/jit-test/tests/basic/testDefinePropertyAcrossCompartment.js b/js/src/jit-test/tests/basic/testDefinePropertyAcrossCompartment.js new file mode 100644 index 0000000000..b997089e71 --- /dev/null +++ b/js/src/jit-test/tests/basic/testDefinePropertyAcrossCompartment.js @@ -0,0 +1,7 @@ +var a = evalcx(''); +Object.defineProperty(a, "", ({ + get: function() {}, +})) +gc() + +// don't crash diff --git a/js/src/jit-test/tests/basic/testDenseArrayProp.js b/js/src/jit-test/tests/basic/testDenseArrayProp.js new file mode 100644 index 0000000000..6d7bdc4dc9 --- /dev/null +++ b/js/src/jit-test/tests/basic/testDenseArrayProp.js @@ -0,0 +1,12 @@ +function testDenseArrayProp() +{ + [].__proto__.x = 1; + ({}).__proto__.x = 2; + var a = [[],[],[],({}).__proto__]; + for (var i = 0; i < a.length; ++i) + JSON.stringify(a[i].x); + delete [].__proto__.x; + delete ({}).__proto__.x; + return "ok"; +} +assertEq(testDenseArrayProp(), "ok"); diff --git a/js/src/jit-test/tests/basic/testDenseToSlowArray.js b/js/src/jit-test/tests/basic/testDenseToSlowArray.js new file mode 100644 index 0000000000..e4b6b5d2dd --- /dev/null +++ b/js/src/jit-test/tests/basic/testDenseToSlowArray.js @@ -0,0 +1,185 @@ +// test dense -> slow array transitions during the recording and on trace +// for various array functions and property accessors + +function test_set_elem() { + + function f() { + var bag = []; + for (var i = 0; i != 100; ++i) { + var a = [0]; + a[100*100] = i; + bag.push(a); + } + + for (var i = 0; i != 100; ++i) { + var a = [0]; + a[200 + i] = i; + bag.push(a); + } + return bag; + } + + var bag = f(); + + for (var i = 0; i != 100; ++i) { + var a = bag[i]; + assertEq(a.length, 100 * 100 + 1); + assertEq(a[100*100], i); + assertEq(a[0], 0); + assertEq(1 + i in a, false); + } + + for (var i = 0; i != 100; ++i) { + var a = bag[100 + i]; + assertEq(a.length, 200 + i + 1); + assertEq(a[200 + i], i); + assertEq(a[0], 0); + assertEq(1 + i in a, false); + } +} + +function test_reverse() { + + function prepare_arays() { + var bag = []; + var base_index = 245; + for (var i = 0; i != 50; ++i) { + var a = [1, 2, 3, 4, 5]; + a.length = i + base_index; + bag.push(a); + } + return bag; + } + + function test(bag) { + for (var i = 0; i != bag.length; ++i) { + var a = bag[i]; + a.reverse(); + a[0] = 1; + } + } + + var bag = prepare_arays(); + test(bag); + for (var i = 0; i != bag.length; ++i) { + var a = bag[i]; + assertEq(a[0], 1); + for (var j = 1; j <= 5; ++j) { + assertEq(a[a.length - j], j); + } + for (var j = 1; j < a.length - 5; ++j) { + assertEq(j in a, false); + } + } + +} + +function test_push() { + + function prepare_arays() { + var bag = []; + var base_index = 245; + for (var i = 0; i != 50; ++i) { + var a = [0]; + a.length = i + base_index; + bag.push(a); + } + return bag; + } + + function test(bag) { + for (var i = 0; i != bag.length; ++i) { + var a = bag[i]; + a.push(2); + a[0] = 1; + } + } + + var bag = prepare_arays(); + test(bag); + for (var i = 0; i != bag.length; ++i) { + var a = bag[i]; + assertEq(a[0], 1); + assertEq(a[a.length - 1], 2); + for (var j = 1; j < a.length - 1; ++j) { + assertEq(j in a, false); + } + } +} + +function test_unshift() { + + function prepare_arays() { + var bag = []; + var base_index = 245; + for (var i = 0; i != 50; ++i) { + var a = [0]; + a.length = i + base_index; + bag.push(a); + } + return bag; + } + + function test(bag) { + for (var i = 0; i != bag.length; ++i) { + var a = bag[i]; + a.unshift(1); + a[2] = 2; + } + } + + var bag = prepare_arays(); + test(bag); + for (var i = 0; i != bag.length; ++i) { + var a = bag[i]; + assertEq(a[0], 1); + assertEq(a[1], 0); + assertEq(a[2], 2); + for (var j = 3; j < a.length; ++j) { + assertEq(j in a, false); + } + } +} + +function test_splice() { + + function prepare_arays() { + var bag = []; + var base_index = 245; + for (var i = 0; i != 50; ++i) { + var a = [1, 2]; + a.length = i + base_index; + bag.push(a); + } + return bag; + } + + function test(bag) { + for (var i = 0; i != bag.length; ++i) { + var a = bag[i]; + a.splice(1, 0, "a", "b", "c"); + a[2] = 100; + } + } + + var bag = prepare_arays(); + test(bag); + for (var i = 0; i != bag.length; ++i) { + var a = bag[i]; + assertEq(a[0], 1); + assertEq(a[1], "a"); + assertEq(a[2], 100); + assertEq(a[3], "c"); + assertEq(a[4], 2); + for (var j = 5; j < a.length; ++j) { + assertEq(j in a, false); + } + } +} + +test_set_elem(); +test_reverse(); +test_push(); +test_unshift(); +test_splice(); + diff --git a/js/src/jit-test/tests/basic/testDestructuring.js b/js/src/jit-test/tests/basic/testDestructuring.js new file mode 100644 index 0000000000..05a267802b --- /dev/null +++ b/js/src/jit-test/tests/basic/testDestructuring.js @@ -0,0 +1,9 @@ +function testDestructuring() { + var t = 0; + for (var i = 0; i < 9; ++i) { + var [r, g, b] = [1, 1, 1]; + t += r + g + b; + } + return t +} +assertEq(testDestructuring(), (9) * 3); diff --git a/js/src/jit-test/tests/basic/testDestructuringFormalError.js b/js/src/jit-test/tests/basic/testDestructuringFormalError.js new file mode 100644 index 0000000000..1d1a8c2c03 --- /dev/null +++ b/js/src/jit-test/tests/basic/testDestructuringFormalError.js @@ -0,0 +1,6 @@ +// |jit-test| error:TypeError +(function({ + l +}) { + eval(); +})() diff --git a/js/src/jit-test/tests/basic/testDestructuringVarInsideWith.js b/js/src/jit-test/tests/basic/testDestructuringVarInsideWith.js new file mode 100644 index 0000000000..b233c9ceb2 --- /dev/null +++ b/js/src/jit-test/tests/basic/testDestructuringVarInsideWith.js @@ -0,0 +1,4 @@ +with ({b:1}) {
+ const [ b ] = [];
+ assertEq(b, undefined);
+}
diff --git a/js/src/jit-test/tests/basic/testDifferingArgc.js b/js/src/jit-test/tests/basic/testDifferingArgc.js new file mode 100644 index 0000000000..0cac5696fc --- /dev/null +++ b/js/src/jit-test/tests/basic/testDifferingArgc.js @@ -0,0 +1,18 @@ +function doTestDifferingArgc(a, b) +{ + var k = 0; + for (var i = 0; i < 10; i++) + { + k += i; + } + return k; +} +function testDifferingArgc() +{ + var x = 0; + x += doTestDifferingArgc(1, 2); + x += doTestDifferingArgc(1); + x += doTestDifferingArgc(1, 2, 3); + return x; +} +assertEq(testDifferingArgc(), 45*3); diff --git a/js/src/jit-test/tests/basic/testDivModWithIntMin.js b/js/src/jit-test/tests/basic/testDivModWithIntMin.js new file mode 100644 index 0000000000..a8ea2d2c41 --- /dev/null +++ b/js/src/jit-test/tests/basic/testDivModWithIntMin.js @@ -0,0 +1,62 @@ +var intMin = -2147483648; +var intMax = 2147483647; +var negativeZero = -0; +var zero = 0; + +function testModNegativeZero() { + assertEq(intMin % -2147483648, -0); + assertEq(intMin % -1, -0); + assertEq(intMin % 1, -0); + assertEq(intMin % -2147483648, -0); + + assertEq(((intMin|0) % -2147483648)|0, 0); + assertEq(((intMin|0) % -1)|0, 0); + assertEq(((intMin|0) % 1)|0, 0); + assertEq(((intMin|0) % -2147483648)|0, 0); +} + +testModNegativeZero(); +testModNegativeZero(); + +function testMinModulus1() { + assertEq(intMin % -3, -2); + assertEq(intMin % 3, -2); + assertEq(intMin % 10, -8); + assertEq(intMin % 2147483647, -1); + + assertEq(((intMin|0) % -3)|0, -2); + assertEq(((intMin|0) % 3)|0, -2); + assertEq(((intMin|0) % 10)|0, -8); + assertEq(((intMin|0) % 2147483647)|0, -1); +} + +testMinModulus1(); +testMinModulus1(); + +function testMinModulus2() { + for (var i = -10; i <= 10; ++i) + assertEq(i % -2147483648, i); + assertEq(intMax % -2147483648, intMax); + + for (var i = -10; i <= 10; ++i) + assertEq(((i|0) % -2147483648)|0, i); + assertEq(((intMax|0) % -2147483648)|0, intMax); +} + +testMinModulus2(); +testMinModulus2(); + +function testDivEdgeCases() { + assertEq(intMin / -2147483648, 1); + assertEq(intMin / -1, -intMin); + assertEq(negativeZero / -2147483648, 0); + assertEq(zero / -2147483648, -0); + + assertEq(((intMin|0) / -2147483648)|0, 1); + assertEq(((intMin|0) / -1)|0, intMin); + assertEq(((negativeZero|0) / -2147483648)|0, 0); + assertEq(((zero|0) / -2147483648)|0, 0); +} + +testDivEdgeCases(); +testDivEdgeCases(); diff --git a/js/src/jit-test/tests/basic/testDivision.js b/js/src/jit-test/tests/basic/testDivision.js new file mode 100644 index 0000000000..52f3d9557a --- /dev/null +++ b/js/src/jit-test/tests/basic/testDivision.js @@ -0,0 +1,10 @@ +function testDivision() { + var a = 32768; + var b; + while (b !== 1) { + b = a / 2; + a = b; + } + return a; +} +assertEq(testDivision(), 1); diff --git a/js/src/jit-test/tests/basic/testDivisionFloat.js b/js/src/jit-test/tests/basic/testDivisionFloat.js new file mode 100644 index 0000000000..44f67659a8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testDivisionFloat.js @@ -0,0 +1,10 @@ +function testDivisionFloat() { + var a = 32768.0; + var b; + while (b !== 1) { + b = a / 2.0; + a = b; + } + return a === 1.0; +} +assertEq(testDivisionFloat(), true); diff --git a/js/src/jit-test/tests/basic/testDivisionWithNegative1.js b/js/src/jit-test/tests/basic/testDivisionWithNegative1.js new file mode 100644 index 0000000000..18a3b266fa --- /dev/null +++ b/js/src/jit-test/tests/basic/testDivisionWithNegative1.js @@ -0,0 +1,6 @@ +function testDivisionWithNegative1() { + for (var i = 3; i >= 0; --i) + c = i / -1; + return 1/c; +} +assertEq(testDivisionWithNegative1(), -Infinity); diff --git a/js/src/jit-test/tests/basic/testDontClobberScannerError.js b/js/src/jit-test/tests/basic/testDontClobberScannerError.js new file mode 100644 index 0000000000..cdde939306 --- /dev/null +++ b/js/src/jit-test/tests/basic/testDontClobberScannerError.js @@ -0,0 +1,9 @@ +var caught = false; +try { + Function("a, …", ""); +} catch(e) { + assertEq(e.toString().search("SyntaxError: malformed formal parameter") == -1, true); + assertEq(e.toString().search("SyntaxError: illegal character") == -1, false); + caught = true; +} +assertEq(caught, true); diff --git a/js/src/jit-test/tests/basic/testDoubleComparison.js b/js/src/jit-test/tests/basic/testDoubleComparison.js new file mode 100644 index 0000000000..1d4b3e33a5 --- /dev/null +++ b/js/src/jit-test/tests/basic/testDoubleComparison.js @@ -0,0 +1,13 @@ +function testDoubleComparison() +{ + for (var i = 0; i < 500000; ++i) + { + switch (1 / 0) + { + case Infinity: + } + } + + return "finished"; +} +assertEq(testDoubleComparison(), "finished"); diff --git a/js/src/jit-test/tests/basic/testDoubleToStr.js b/js/src/jit-test/tests/basic/testDoubleToStr.js new file mode 100644 index 0000000000..9eea240bb6 --- /dev/null +++ b/js/src/jit-test/tests/basic/testDoubleToStr.js @@ -0,0 +1,9 @@ +function testDoubleToStr() { + var x = 0.0; + var y = 5.5; + for (var i = 0; i < 200; i++) { + x += parseFloat(y.toString()); + } + return x; +} +assertEq(testDoubleToStr(), 5.5*200); diff --git a/js/src/jit-test/tests/basic/testDoubleZeroInSwitch1.js b/js/src/jit-test/tests/basic/testDoubleZeroInSwitch1.js new file mode 100644 index 0000000000..2b147aaf27 --- /dev/null +++ b/js/src/jit-test/tests/basic/testDoubleZeroInSwitch1.js @@ -0,0 +1,7 @@ +var a = Math.sin(Math.PI/2); // spec does not specify precise answer here... +if (a === 1) { // ...but if a === 1 here... + switch (a) { + case 1: break; // ...then it must also match here + default: throw "FAIL"; + } +} diff --git a/js/src/jit-test/tests/basic/testDoubleZeroInSwitch2.js b/js/src/jit-test/tests/basic/testDoubleZeroInSwitch2.js new file mode 100644 index 0000000000..504d1b76db --- /dev/null +++ b/js/src/jit-test/tests/basic/testDoubleZeroInSwitch2.js @@ -0,0 +1,9 @@ +var arr = new Float32Array(1); +arr[0] = 15; +var a = arr[0]; +assertEq(a, 15); +switch (a) { + case 15: break; + default: throw "FAIL"; +} + diff --git a/js/src/jit-test/tests/basic/testDynamicLookup.js b/js/src/jit-test/tests/basic/testDynamicLookup.js new file mode 100644 index 0000000000..781c9f8a7a --- /dev/null +++ b/js/src/jit-test/tests/basic/testDynamicLookup.js @@ -0,0 +1,67 @@ +(function() { var x = 2; eval("assertEq(x, 2)"); })(); +(function() { var x = 2; (function() { assertEq(x, 2) })() })(); +(function() { var x = 2; (function() { eval("assertEq(x, 2)") })() })(); +(function() { var x = 2; (function() { (function() { assertEq(x, 2) })()})() })(); +(function() { var x = 2; (function() { (function() { eval("assertEq(x, 2)") })()})() })(); + +(function() { var x = 2; with({}) { assertEq(x, 2) } })(); +(function() { var x = 2; with({}) { (function() { assertEq(x, 2) })() } })(); +(function() { var x = 3; with({x:2}) { assertEq(x, 2) } })(); +(function() { var x = 3; with({x:2}) { (function() { assertEq(x, 2) })() } })(); +(function() { var x = 2; (function() { with({}) { assertEq(x, 2) } })() })(); +(function() { var x = 2; (function() { with({}) { (function() { assertEq(x, 2) })() } })() })(); +(function() { var x = 3; (function() { with({x:2}) { assertEq(x, 2) } })() })(); +(function() { var x = 3; (function() { with({x:2}) { (function() { assertEq(x, 2) })() } })() })(); + +(function() { if (Math) function x() {}; assertEq(typeof x, "function") })(); +(function() { if (Math) function x() {}; eval('assertEq(typeof x, "function")') })(); +(function() { if (Math) function x() {}; (function() { assertEq(typeof x, "function") })() })(); +(function() { if (Math) function x() {}; (function() { eval('assertEq(typeof x, "function")') })() })(); + +(function() { eval("var x = 2"); assertEq(x, 2) })(); +(function() { eval("var x = 2"); (function() { assertEq(x, 2) })() })(); +(function() { eval("var x = 2"); (function() { (function() { assertEq(x, 2) })() })() })(); + +(function() { var x = 2; (function() { eval('var y = 3'); assertEq(x, 2) })() })(); +(function() { var x = 2; (function() { eval('var y = 3'); (function() { assertEq(x, 2) })() })() })(); + +(function() { var x = 3; (function() { eval('var x = 2'); assertEq(x, 2) })() })(); +(function() { var x = 3; (function() { eval('var x = 2'); (function() { assertEq(x, 2) })() })() })(); + +(function() { var x = 2; eval("eval('assertEq(x, 2)')") })(); +(function() { var x = 2; (function() { eval("eval('assertEq(x, 2)')") })() })(); +(function() { var x = 2; eval("(function() { eval('assertEq(x, 2)') })()") })(); +(function() { var x = 2; (function() { eval("(function() { eval('assertEq(x, 2)') })()") })() })(); +(function() { var x = 2; (function() { eval("(function() { eval('(function() { assertEq(x, 2) })()') })()") })() })(); + +(function() { var [x] = [2]; eval('assertEq(x, 2)') })(); +(function() { var [x] = [2]; (function() { assertEq(x, 2) })() })(); +(function() { var [x] = [2]; (function() { eval('assertEq(x, 2)') })() })(); +(function() { for (var [x] = [2];;) { return (function() { return assertEq(x, 2); })() } })(); +(function() { for (var [x] = [2];;) { return (function() { return eval('assertEq(x, 2)'); })() } })(); + +(function() { var {y:x} = {y:2}; eval('assertEq(x, 2)') })(); +(function() { var {y:x} = {y:2}; (function() { assertEq(x, 2) })() })(); +(function() { var {y:x} = {y:2}; (function() { eval('assertEq(x, 2)') })() })(); +(function() { for (var {y:x} = {y:2};;) { return (function() { return assertEq(x, 2); })() } })(); +(function() { for (var {y:x} = {y:2};;) { return (function() { return eval('assertEq(x, 2)'); })() } })(); + +(function([x]) { eval('assertEq(x, 2)') })([2]); +(function([x]) { (function() { assertEq(x, 2) })() })([2]); +(function([x]) { (function() { eval('assertEq(x, 2)') })() })([2]); + +(function f() { assertEq(f.length, 0) })(); +(function f() { eval('assertEq(f.length, 0)') })(); +(function f() { (function f(x) { eval('assertEq(f.length, 1)') })() })(); +(function f() { eval("(function f(x) { eval('assertEq(f.length, 1)') })()") })(); + +(function f() { arguments = 3; function arguments() {}; assertEq(arguments, 3) })(); +(function f() { function arguments() {}; arguments = 3; assertEq(arguments, 3) })(); +(function f() { var arguments = 3; function arguments() {}; assertEq(arguments, 3) })(); +(function f() { function arguments() {}; var arguments = 3; assertEq(arguments, 3) })(); + +function f1() { assertEq(typeof f1, "function") }; f1(); +with({}) { (function() { assertEq(typeof f1, "function") })() } +if (Math) + function f2(x) {} +assertEq(f2.length, 1); diff --git a/js/src/jit-test/tests/basic/testDynamicUsage.js b/js/src/jit-test/tests/basic/testDynamicUsage.js new file mode 100644 index 0000000000..49ee874c1f --- /dev/null +++ b/js/src/jit-test/tests/basic/testDynamicUsage.js @@ -0,0 +1,82 @@ +assertEq((function() { var x = 3; return (function() { return x } )() })(), 3); +assertEq((function() { var g = function() { return x }; var x = 3; return g()})(), 3); +assertEq((function() { var x; x = 3; return (function() { return x } )() })(), 3); +assertEq((function() { x = 3; var x; return (function() { return x } )() })(), 3); +assertEq((function() { var x; var g = function() { return x }; x = 3; return g() })(), 3); + +assertEq((function() { function f() { return 3 }; assertEq(f(), 3); return (function() { return f(); })(); })(), 3); +assertEq((function() { function f() { return 3 }; assertEq(f(), 3); return eval('f()') })(), 3); +assertEq((function() { function f() { return 3 }; (function() { return f(); })(); return f() })(), 3); + +assertEq((function() { var x = 3; return eval("x") })(), 3); +assertEq((function() { var x; x = 3; return eval("x") })(), 3); +assertEq((function() { x = 3; var x; return eval("x") })(), 3); + +assertEq((function() { var x; (function() {x = 2})(); return ++x })(), 3); +assertEq((function() { var x; (function() {x = 2})(); x++; return x })(), 3); +assertEq((function() { var x; (function() {x = 4})(); return --x })(), 3); +assertEq((function() { var x; (function() {x = 4})(); x--; return x })(), 3); + +assertEq((function(x) { return (function() { return x } )() })(3), 3); +assertEq((function(x) { var x = 3; return (function() { return x } )() })(4), 3); +assertEq((function(x) { x = 3; return (function() { return x } )() })(4), 3); +assertEq((function(x) { var g = function() { return x }; x = 3; return g()})(3), 3); + +assertEq((function(x) { return eval("x") })(3), 3); +assertEq((function(x) { x = 3; return eval("x") })(4), 3); + +assertEq((function(a) { var [x,y] = a; (function() { x += y })(); return x })([1,2]), 3); +assertEq((function(a) { var [x,y] = a; x += y; return (function() { return x; })() })([1,2]), 3); +assertEq((function(a) { var [[l, x],[m, y]] = a; x += y; return (function() { return x; })() })([[0,1],[0,2]]), 3); +assertEq((function(a) { var [x,y] = a; eval('x += y'); return x })([1,2]), 3); +assertEq((function(a) { var [x,y] = a; x += y; return eval('x') })([1,2]), 3); +assertEq((function(a) { var [x,y] = a; (function() { x += y })(); return x })([1,2]), 3); +assertEq((function(a) { var [x,y] = a; x += y; return (function() { return x; })() })([1,2]), 3); +assertEq((function(a,x,y) { [x,y] = a; (function() { eval('x += y') })(); return x })([1,2]), 3); +assertEq((function(a,x,y) { [x,y] = a; x += y; return (function() { return eval('x'); })() })([1,2]), 3); + +assertEq((function() { var [x,y] = [1,2]; x += y; return (function() { return x; })() })(), 3); +assertEq((function() { var [x,y] = [1,2]; (function() { return x += y; })(); return x })(), 3); +assertEq((function() { { let [x,y] = [1,2]; x += y; return (function() { return x; })() } })(), 3); +assertEq((function() { { let [x,y] = [1,2]; (function() { return x += y; })(); return x } })(), 3); + +assertEq((function([x,y]) { (function() { x += y })(); return x })([1,2]), 3); +assertEq((function([x,y]) { x += y; return (function() { return x; })() })([1,2]), 3); +assertEq((function([[l,x],[m,y]]) { (function() { x += y })(); return x })([[0,1],[0,2]]), 3); +assertEq((function([[l,x],[m,y]]) { x += y; return (function() { return x; })() })([[0,1],[0,2]]), 3); +assertEq((function([x,y]) { (function() { eval('x += y') })(); return x })([1,2]), 3); +assertEq((function([x,y]) { x += y; return (function() { return eval('x'); })() })([1,2]), 3); +assertEq((function() { try { throw [1,2] } catch([x,y]) { eval('x += y'); return x }})(), 3); +assertEq((function() { try { throw [1,2] } catch([x,y]) { x += y; return eval('x') }})(), 3); +assertEq((function() { try { throw [1,2] } catch([x,y]) { (function() { x += y })(); return x }})(), 3); +assertEq((function() { try { throw [1,2] } catch([x,y]) { x += y; return (function() { return x; })() }})(), 3); +assertEq((function() { try { throw [1,2] } catch([x,y]) { (function() { eval('x += y') })(); return x }})(), 3); +assertEq((function() { try { throw [1,2] } catch([x,y]) { x += y; return (function() { return eval('x'); })() }})(), 3); + +assertEq((function(a) { let [x,y] = a; (function() { x += y })(); return x })([1,2]), 3); +assertEq((function(a) { let [x,y] = a; x += y; return (function() { return x; })() })([1,2]), 3); +assertEq((function(a) { { let [x,y] = a; (function() { x += y })(); return x } })([1,2]), 3); +assertEq((function(a) { { let [x,y] = a; x += y; return (function() { return x; })() } })([1,2]), 3); +assertEq((function(a) { { let [[l, x],[m, y]] = a; (function() { x += y })(); return x } })([[0,1],[0,2]]), 3); +assertEq((function(a) { { let [[l, x],[m, y]] = a; x += y; return (function() { return x; })() } })([[0,1],[0,2]]), 3); + +assertEq((function() { let x = 3; return (function() { return x })() })(), 3); +assertEq((function() { let g = function() { return x }; let x = 3; return g() })(), 3); + +assertEq((function() { { let x = 3; return (function() { return x })() } })(), 3); +assertEq((function() { { let x = 3; (function() { assertEq(x, 3) })(); return x } })(), 3); +assertEq((function() { { let x = 2; x = 3; return (function() { return x })() } })(), 3); +assertEq((function() { { let x = 1; { let x = 3; (function() { assertEq(x,3) })() } return x } })(), 1); + +assertEq((function() { try { throw 3 } catch (e) { (function(){assertEq(e,3)})(); return e } })(), 3); +assertEq((function() { try { throw 3 } catch (e) { assertEq(e, 3); return (function() { return e; })() } })(), 3); +assertEq((function() { try { throw 3 } catch (e) { (function(){eval('assertEq(e,3)')})(); return e } })(), 3); + +assertEq((function() { var x; function f() { return x } function f() { return 3 }; return f() })(), 3); +assertEq((function() { var x = 3; function f() { return 3 } function f() { return x }; return f() })(), 3); + +assertEq((function() { function f(x,y) { (function() { assertEq(f.length, 2) })(); }; return f.length })(), 2); +assertEq((function f(x,y) { (function() { assertEq(f.length, 2) })(); return f.length})(), 2); +function f1(x,y) { (function() { assertEq(f1.length, 2) })(); assertEq(f1.length, 2) }; f1(); + +String(function([]) { eval('') }); diff --git a/js/src/jit-test/tests/basic/testElemDec1.js b/js/src/jit-test/tests/basic/testElemDec1.js new file mode 100644 index 0000000000..c03ea2ae05 --- /dev/null +++ b/js/src/jit-test/tests/basic/testElemDec1.js @@ -0,0 +1,7 @@ +var obj = {p: 100}; +var name = "p"; +var a = []; +for (var i = 0; i < 10; i++) + a[i] = obj[name]--; +assertEq(a.join(','), '100,99,98,97,96,95,94,93,92,91'); +assertEq(obj.p, 90); diff --git a/js/src/jit-test/tests/basic/testElemDec2.js b/js/src/jit-test/tests/basic/testElemDec2.js new file mode 100644 index 0000000000..7dc674645f --- /dev/null +++ b/js/src/jit-test/tests/basic/testElemDec2.js @@ -0,0 +1,7 @@ +var obj = {s: ""}; +var name = "s"; +for (var i = 0; i <= 13; i++) + if (i > 8) + obj[name]--; // first recording changes obj.s from string to number +assertEq(obj.s, -5); + diff --git a/js/src/jit-test/tests/basic/testElemInc1.js b/js/src/jit-test/tests/basic/testElemInc1.js new file mode 100644 index 0000000000..c0d4f8c113 --- /dev/null +++ b/js/src/jit-test/tests/basic/testElemInc1.js @@ -0,0 +1,7 @@ +var obj = {p: 100}; +var name = "p"; +var a = []; +for (var i = 0; i < 10; i++) + a[i] = obj[name]++; +assertEq(a.join(','), '100,101,102,103,104,105,106,107,108,109'); +assertEq(obj.p, 110); diff --git a/js/src/jit-test/tests/basic/testElemInc2.js b/js/src/jit-test/tests/basic/testElemInc2.js new file mode 100644 index 0000000000..56a926b2e2 --- /dev/null +++ b/js/src/jit-test/tests/basic/testElemInc2.js @@ -0,0 +1,7 @@ +var obj = {s: ""}; +var name = "s"; +for (var i = 0; i <= 13; i++) + if (i > 8) + obj[name]++; // first recording changes obj.s from string to number +assertEq(obj.s, 5); + diff --git a/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js b/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js new file mode 100644 index 0000000000..25d0be96ca --- /dev/null +++ b/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js @@ -0,0 +1,6 @@ +function testEliminatedGuardWithinAnchor() { + for (let i = 0; i < 5; ++i) { i / (i * i); } + return "ok"; +} + +assertEq(testEliminatedGuardWithinAnchor(), "ok"); diff --git a/js/src/jit-test/tests/basic/testEqFalseEmptyString.js b/js/src/jit-test/tests/basic/testEqFalseEmptyString.js new file mode 100644 index 0000000000..6fd70f1076 --- /dev/null +++ b/js/src/jit-test/tests/basic/testEqFalseEmptyString.js @@ -0,0 +1,6 @@ +function testEqFalseEmptyString() { + var x = []; + for (var i=0;i<5;++i) x.push(false == ""); + return x.join(","); +} +assertEq(testEqFalseEmptyString(), "true,true,true,true,true"); diff --git a/js/src/jit-test/tests/basic/testErrorInFinalizerCalledWhileUnwinding.js b/js/src/jit-test/tests/basic/testErrorInFinalizerCalledWhileUnwinding.js new file mode 100644 index 0000000000..140b75175a --- /dev/null +++ b/js/src/jit-test/tests/basic/testErrorInFinalizerCalledWhileUnwinding.js @@ -0,0 +1,31 @@ +var finalizerRun = false; +var caught = false; + +function foo(arr) { + finalizerRun = true; + return not_defined; +} + +function* gen() { + try { + yield 1; + } finally { + foo(); + } +} + +function test() { + var i_have_locals; + for (i of gen()) { + } +} + +try { + test(); +} catch(e) { + caught = true; + assertEq(''+e, "ReferenceError: not_defined is not defined"); +} + +assertEq(finalizerRun, true); +assertEq(caught, true); diff --git a/js/src/jit-test/tests/basic/testEvalInFrameEdgeCase.js b/js/src/jit-test/tests/basic/testEvalInFrameEdgeCase.js new file mode 100644 index 0000000000..d22a357572 --- /dev/null +++ b/js/src/jit-test/tests/basic/testEvalInFrameEdgeCase.js @@ -0,0 +1,11 @@ +load(libdir + "evalInFrame.js"); + +function g() { + var x = 100; + return evalInFrame(2, "x"); +} +function f() { + var x = 42; + return evalInFrame.call(null, 0, "g()"); +} +assertEq(f.call(), 42); diff --git a/js/src/jit-test/tests/basic/testEvalInFunctionCallee.js b/js/src/jit-test/tests/basic/testEvalInFunctionCallee.js new file mode 100644 index 0000000000..81f757fa62 --- /dev/null +++ b/js/src/jit-test/tests/basic/testEvalInFunctionCallee.js @@ -0,0 +1,4 @@ +function f(x,y) { + eval("assertEq(arguments.callee, f)"); +} +f(1,2); diff --git a/js/src/jit-test/tests/basic/testExistingPropToJoinedMethodAttempt-2.js b/js/src/jit-test/tests/basic/testExistingPropToJoinedMethodAttempt-2.js new file mode 100644 index 0000000000..002da3f61b --- /dev/null +++ b/js/src/jit-test/tests/basic/testExistingPropToJoinedMethodAttempt-2.js @@ -0,0 +1,8 @@ +function f() { + var a = [], i, N = 10; + for (i = 0; i < N; i++) + a[i] = {m: i, m: function() { return 0; }}; + assertEq(a[N - 2].m === a[N - 1].m, false); +} +f(); +f(); diff --git a/js/src/jit-test/tests/basic/testExistingPropToJoinedMethodAttempt-3.js b/js/src/jit-test/tests/basic/testExistingPropToJoinedMethodAttempt-3.js new file mode 100644 index 0000000000..573c33ef11 --- /dev/null +++ b/js/src/jit-test/tests/basic/testExistingPropToJoinedMethodAttempt-3.js @@ -0,0 +1,15 @@ +function f() { + var a = [], i, N = 10; + for (i = 0; i < N; i++) { + a[i] = {}; + a[i].m = function() { return 0; }; + a[i].m = function() { return 1; }; + } + assertEq(a[N - 2].m === a[N - 1].m, false); + for (i = 0; i < N; i++) { + var f = a[i].m; + assertEq(f(), 1); + } +} +f(); +f(); diff --git a/js/src/jit-test/tests/basic/testExistingPropToJoinedMethodAttempt-4.js b/js/src/jit-test/tests/basic/testExistingPropToJoinedMethodAttempt-4.js new file mode 100644 index 0000000000..8d0bc1b157 --- /dev/null +++ b/js/src/jit-test/tests/basic/testExistingPropToJoinedMethodAttempt-4.js @@ -0,0 +1,12 @@ +function f() { + var a = [], i, N = 10; + for (i = 0; i < N; i++) + a[i] = {m: function() { return 0; }, m: function() { return 1; }}; + assertEq(a[N - 2].m === a[N - 1].m, false); + for (i = 0; i < N; i++) { + var f = a[i].m; + assertEq(f(), 1); + } +} +f(); +f(); diff --git a/js/src/jit-test/tests/basic/testExistingPropToJoinedMethodAttempt.js b/js/src/jit-test/tests/basic/testExistingPropToJoinedMethodAttempt.js new file mode 100644 index 0000000000..0faafe2f4b --- /dev/null +++ b/js/src/jit-test/tests/basic/testExistingPropToJoinedMethodAttempt.js @@ -0,0 +1,10 @@ +function f() { + var a = [], i, N = 10; + for (i = 0; i < N; i++) + a[i] = {m: i}; + for (i = 0; i < N; i++) + a[i].m = function() { return 0; }; + assertEq(a[N - 2].m === a[N - 1].m, false); +} +f(); +f(); diff --git a/js/src/jit-test/tests/basic/testFakeDOMWeakmapKey.js b/js/src/jit-test/tests/basic/testFakeDOMWeakmapKey.js new file mode 100644 index 0000000000..80d116960d --- /dev/null +++ b/js/src/jit-test/tests/basic/testFakeDOMWeakmapKey.js @@ -0,0 +1 @@ +(new WeakMap).set(FakeDOMObject.prototype, this) diff --git a/js/src/jit-test/tests/basic/testFloatArrayIndex.js b/js/src/jit-test/tests/basic/testFloatArrayIndex.js new file mode 100644 index 0000000000..564824778d --- /dev/null +++ b/js/src/jit-test/tests/basic/testFloatArrayIndex.js @@ -0,0 +1,9 @@ +function testFloatArrayIndex() { + var a = []; + for (var i = 0; i < 10; ++i) { + a[3] = 5; + a[3.5] = 7; + } + return a[3] + "," + a[3.5]; +} +assertEq(testFloatArrayIndex(), "5,7"); diff --git a/js/src/jit-test/tests/basic/testFoldPropertyAccess.js b/js/src/jit-test/tests/basic/testFoldPropertyAccess.js new file mode 100644 index 0000000000..2ccb5e21f7 --- /dev/null +++ b/js/src/jit-test/tests/basic/testFoldPropertyAccess.js @@ -0,0 +1,23 @@ + +var cases = [ + function (obj) { + return obj["ab"]; + }, + function (obj) { + return obj["a" + "b"]; + }, + function (obj) { + return obj[0 ? "cd" : "ab"]; + }, + function (obj) { + return obj[true ? "ab" : "cd"]; + }, + function (obj) { + return obj[(1 + 0) ? "ab" : "cd"]; + } +] + +for (var i = 0; i < cases.length; i++) { + assertEq(cases[i]({ab: 42}), 42); + assertEq(cases[i]({cd: 120}), undefined); +} diff --git a/js/src/jit-test/tests/basic/testForInLoopChangeIteratorType.js b/js/src/jit-test/tests/basic/testForInLoopChangeIteratorType.js new file mode 100644 index 0000000000..0efce83648 --- /dev/null +++ b/js/src/jit-test/tests/basic/testForInLoopChangeIteratorType.js @@ -0,0 +1,11 @@ +function testForInLoopChangeIteratorType() { + for(y in [0,1,2]) y = NaN; + (function(){ + [].__proto__.u = void 0; + for (let y in [5,6,7,8]) + y = NaN; + delete [].__proto__.u; + })() + return "ok"; +} +assertEq(testForInLoopChangeIteratorType(), "ok"); diff --git a/js/src/jit-test/tests/basic/testFunApplyMadness1.js b/js/src/jit-test/tests/basic/testFunApplyMadness1.js new file mode 100644 index 0000000000..dabc41be44 --- /dev/null +++ b/js/src/jit-test/tests/basic/testFunApplyMadness1.js @@ -0,0 +1,19 @@ +function g() { assertEq(false, true) } +var ct = 0; + +function f(b) { + var a = arguments; + if (b) + f(false); + else + g = { + apply:function(x,y) { + ++ct; + assertEq(x, null); + assertEq(typeof y[0], "boolean"); + } + }; + g.apply(null, a); +} +f(true); +assertEq(ct, 2); diff --git a/js/src/jit-test/tests/basic/testFunApplyMadness2.js b/js/src/jit-test/tests/basic/testFunApplyMadness2.js new file mode 100644 index 0000000000..22684fdd31 --- /dev/null +++ b/js/src/jit-test/tests/basic/testFunApplyMadness2.js @@ -0,0 +1,20 @@ +function g() { assertEq(false, true) } +var ct = 0; + +function f(b) { + if (b) { + arguments = [false]; + f(false); + } else { + g = { + apply:function(x,y) { + ++ct; + assertEq(x, null); + assertEq(y[0], false); + } + }; + } + g.apply(null, arguments); +} +f(true); +assertEq(ct, 2); diff --git a/js/src/jit-test/tests/basic/testFunApplyMadness400.js b/js/src/jit-test/tests/basic/testFunApplyMadness400.js new file mode 100644 index 0000000000..886d559347 --- /dev/null +++ b/js/src/jit-test/tests/basic/testFunApplyMadness400.js @@ -0,0 +1,19 @@ +function g() { assertEq(false, true) } +var max = 400; ct = 0; + +function f(b) { + if (b) { + f(b - 1); + } else { + g = { + apply:function(x,y) { + assertEq(x, null); + assertEq(y[0], ct); + ++ct; + } + }; + } + g.apply(null, arguments); +} +f(max - 1); +assertEq(ct, max); diff --git a/js/src/jit-test/tests/basic/testFunApplyMisspeculation.js b/js/src/jit-test/tests/basic/testFunApplyMisspeculation.js new file mode 100644 index 0000000000..d572d4ff20 --- /dev/null +++ b/js/src/jit-test/tests/basic/testFunApplyMisspeculation.js @@ -0,0 +1,3 @@ +var h = { apply:function() { return "ponies"; } }; +function f() { var x = 3; g = function() { return ++x }; return h.apply(null, arguments) } +assertEq(f(), "ponies"); diff --git a/js/src/jit-test/tests/basic/testFunApplyOverflow.js b/js/src/jit-test/tests/basic/testFunApplyOverflow.js new file mode 100644 index 0000000000..45be944e99 --- /dev/null +++ b/js/src/jit-test/tests/basic/testFunApplyOverflow.js @@ -0,0 +1,10 @@ +function g(x,y) { + return x + y; +} + +function f(x) { + return g.apply(null, arguments); +} + +for (var i = 0; i < 100; ++i) + assertEq(f(i, 1), i+1); diff --git a/js/src/jit-test/tests/basic/testFunctionIdentityChange.js b/js/src/jit-test/tests/basic/testFunctionIdentityChange.js new file mode 100644 index 0000000000..9f4b7dddf9 --- /dev/null +++ b/js/src/jit-test/tests/basic/testFunctionIdentityChange.js @@ -0,0 +1,16 @@ +function testFunctionIdentityChange() +{ + function a() {} + function b() {} + + var o = { a: a, b: b }; + + for (var prop in o) + { + for (var i = 0; i < 1000; i++) + o[prop](); + } + + return true; +} +assertEq(testFunctionIdentityChange(), true); diff --git a/js/src/jit-test/tests/basic/testFunctionStatementAliasLocals.js b/js/src/jit-test/tests/basic/testFunctionStatementAliasLocals.js new file mode 100644 index 0000000000..be7f528b95 --- /dev/null +++ b/js/src/jit-test/tests/basic/testFunctionStatementAliasLocals.js @@ -0,0 +1,18 @@ +function f1(b) { + var w = 3; + if (b) + function w() {} + return w; +} +assertEq(typeof f1(true), "function"); +assertEq(f1(false), 3); + +function f2(b, w) { + // Annex B doesn't apply to functions in blocks with the same name as a + // parameter. + if (b) + function w() {} + return w; +} +assertEq(typeof f2(true, 3), "number"); +assertEq(f2(false, 3), 3); diff --git a/js/src/jit-test/tests/basic/testFunctionStatementNamedArguments.js b/js/src/jit-test/tests/basic/testFunctionStatementNamedArguments.js new file mode 100644 index 0000000000..967ab3e938 --- /dev/null +++ b/js/src/jit-test/tests/basic/testFunctionStatementNamedArguments.js @@ -0,0 +1,10 @@ +var g; +function foo(b) { + if (b) + function arguments() {}; + return arguments; +} + +var a = foo(true); +assertEq(typeof a, "function"); +assertEq(a.name, "arguments"); diff --git a/js/src/jit-test/tests/basic/testGCWhileRecording.js b/js/src/jit-test/tests/basic/testGCWhileRecording.js new file mode 100644 index 0000000000..2c80203318 --- /dev/null +++ b/js/src/jit-test/tests/basic/testGCWhileRecording.js @@ -0,0 +1,8 @@ +function test() { + for (let z = 0; z < 4; ++z) { + JSON.stringify({ x: 9 }); + gc() + } + return "pass"; +} +assertEq(test(), "pass"); diff --git a/js/src/jit-test/tests/basic/testGeneratorDeepBail.js b/js/src/jit-test/tests/basic/testGeneratorDeepBail.js new file mode 100644 index 0000000000..29abc8b1e1 --- /dev/null +++ b/js/src/jit-test/tests/basic/testGeneratorDeepBail.js @@ -0,0 +1,11 @@ +function testGeneratorDeepBail() { + function* g() { yield 2; } + var iterables = [[1], [], [], [], g()]; + + var total = 0; + for (let i = 0; i < iterables.length; i++) + for (let j of iterables[i]) + total += j; + return total; +} +assertEq(testGeneratorDeepBail(), 3); diff --git a/js/src/jit-test/tests/basic/testGeneratorDieButScopeAlive.js b/js/src/jit-test/tests/basic/testGeneratorDieButScopeAlive.js new file mode 100644 index 0000000000..42799776f2 --- /dev/null +++ b/js/src/jit-test/tests/basic/testGeneratorDieButScopeAlive.js @@ -0,0 +1,24 @@ +var g = newGlobal({newCompartment: true}); +var dbg = new Debugger(g); + +var hits = 0; +dbg.onDebuggerStatement = function(frame) { + ++hits; + frame.older.eval("escaped = function() { return y }"); +} + +var arr = []; +const N = 10; + +for (var i = 0; i < N; ++i) { + g.escaped = undefined; + g.eval("function h() { debugger }"); + g.eval("(function* () { var y = {p:42}; h(); yield })().next();"); + assertEq(g.eval("escaped().p"), 42); + arr.push(g.escaped); +} + +gc(); + +for (var i = 0; i < N; ++i) + arr[i](); diff --git a/js/src/jit-test/tests/basic/testGetCallObj.js b/js/src/jit-test/tests/basic/testGetCallObj.js new file mode 100644 index 0000000000..6c0902a0ae --- /dev/null +++ b/js/src/jit-test/tests/basic/testGetCallObj.js @@ -0,0 +1,11 @@ +function testGetCallObjInlined(i) { + if (i > 7) eval("1"); + return 1; +} + +function testGetCallObj() { + for (var i = 0; i < 10; ++i) + testGetCallObjInlined(i); + return "ok"; +} +assertEq(testGetCallObj(), "ok"); diff --git a/js/src/jit-test/tests/basic/testGetThis.js b/js/src/jit-test/tests/basic/testGetThis.js new file mode 100644 index 0000000000..3c2546a6b0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testGetThis.js @@ -0,0 +1,7 @@ +function testGetThis() { + for (var i = 0; i < 3; ++i) { + (function() { return this; })(); + } + return "ok"; +} +assertEq(testGetThis(), "ok"); diff --git a/js/src/jit-test/tests/basic/testGlobalAsProto.js b/js/src/jit-test/tests/basic/testGlobalAsProto.js new file mode 100644 index 0000000000..1ba24550a4 --- /dev/null +++ b/js/src/jit-test/tests/basic/testGlobalAsProto.js @@ -0,0 +1,3 @@ +var b = Object.create(this); +for (var i = 0; i < 9; i++) + assertEq(b.i, i); diff --git a/js/src/jit-test/tests/basic/testGlobalOptimize-2.js b/js/src/jit-test/tests/basic/testGlobalOptimize-2.js new file mode 100644 index 0000000000..3aa1db6104 --- /dev/null +++ b/js/src/jit-test/tests/basic/testGlobalOptimize-2.js @@ -0,0 +1,8 @@ +var test; +{ + let a = 5; + with ({a: 2}) { + test = (function () { return a; })(); + } +} +assertEq(test, 2); diff --git a/js/src/jit-test/tests/basic/testGlobalOptimize-3.js b/js/src/jit-test/tests/basic/testGlobalOptimize-3.js new file mode 100644 index 0000000000..ef62a70890 --- /dev/null +++ b/js/src/jit-test/tests/basic/testGlobalOptimize-3.js @@ -0,0 +1,10 @@ +var test; +{ + with ({a: 2}) { + { + let a = 5; + test = (function () { return a; })(); + } + } +} +assertEq(test, 5); diff --git a/js/src/jit-test/tests/basic/testGlobalOptimize-4.js b/js/src/jit-test/tests/basic/testGlobalOptimize-4.js new file mode 100644 index 0000000000..30754214a4 --- /dev/null +++ b/js/src/jit-test/tests/basic/testGlobalOptimize-4.js @@ -0,0 +1,8 @@ +var test; +{ + with ({a: 2}) { + test = (function () { return a; })(); + } + let a = 5; +} +assertEq(test, 2); diff --git a/js/src/jit-test/tests/basic/testGlobalOptimize-5.js b/js/src/jit-test/tests/basic/testGlobalOptimize-5.js new file mode 100644 index 0000000000..e0a3aecc2e --- /dev/null +++ b/js/src/jit-test/tests/basic/testGlobalOptimize-5.js @@ -0,0 +1,11 @@ +var test; +function f() { + { + let a = 5; + with ({a: 2}) { + test = (function () { return a;} )(); + } + } +} +f(); +assertEq(test, 2); diff --git a/js/src/jit-test/tests/basic/testGlobalOptimize-6.js b/js/src/jit-test/tests/basic/testGlobalOptimize-6.js new file mode 100644 index 0000000000..4bc14058e8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testGlobalOptimize-6.js @@ -0,0 +1,11 @@ +var test; +function f() { + with ({a: 2}) { + { + let a = 5; + test = (function () { return a; })(); + } + } +} +f(); +assertEq(test, 5); diff --git a/js/src/jit-test/tests/basic/testGlobalProtoAccess.js b/js/src/jit-test/tests/basic/testGlobalProtoAccess.js new file mode 100644 index 0000000000..97f161289a --- /dev/null +++ b/js/src/jit-test/tests/basic/testGlobalProtoAccess.js @@ -0,0 +1,5 @@ +function testGlobalProtoAccess() { + return "ok"; +} +this.__proto__.a = 3; for (var j = 0; j < 4; ++j) { [a]; } +assertEq(testGlobalProtoAccess(), "ok"); diff --git a/js/src/jit-test/tests/basic/testGlobalShapeChangeAfterDeepBail.js b/js/src/jit-test/tests/basic/testGlobalShapeChangeAfterDeepBail.js new file mode 100644 index 0000000000..0839b370c3 --- /dev/null +++ b/js/src/jit-test/tests/basic/testGlobalShapeChangeAfterDeepBail.js @@ -0,0 +1,15 @@ +// Complicated whitebox test for bug 487845. +function testGlobalShapeChangeAfterDeepBail() { + function f(name) { + this[name] = 1; // may change global shape + for (var i = 0; i < 4; i++) + ; // MonitorLoopEdge eventually triggers assertion + } + + // When i==3, deep-bail, then change global shape enough times to exhaust + // the array of GlobalStates. + var arr = [[], [], [], ["bug0", "bug1", "bug2", "bug3", "bug4"]]; + for (var i = 0; i < arr.length; i++) + arr[i].forEach(f); +} +testGlobalShapeChangeAfterDeepBail(); diff --git a/js/src/jit-test/tests/basic/testGroupAssignment.js b/js/src/jit-test/tests/basic/testGroupAssignment.js new file mode 100644 index 0000000000..caf72a185e --- /dev/null +++ b/js/src/jit-test/tests/basic/testGroupAssignment.js @@ -0,0 +1,17 @@ +load(libdir + "asserts.js"); + +assertDeepEq( + (function () { + var arr = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 ]; + + for (var i = 0; i < 4; ++i) { + var src = i * 8; + var dst = i * 8 + 7; + for (var j = 0; j < 4; ++j) { + [arr[dst--], arr[src++]] = [arr[src], arr[dst]]; + } + } + return arr; + })(), + [7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 32]); diff --git a/js/src/jit-test/tests/basic/testGrowDenseArray.js b/js/src/jit-test/tests/basic/testGrowDenseArray.js new file mode 100644 index 0000000000..810c12ff63 --- /dev/null +++ b/js/src/jit-test/tests/basic/testGrowDenseArray.js @@ -0,0 +1,7 @@ +function testGrowDenseArray() { + var a = new Array(); + for (var i = 0; i < 10; ++i) + a[i] |= 5; + return a.join(","); +} +assertEq(testGrowDenseArray(), "5,5,5,5,5,5,5,5,5,5"); diff --git a/js/src/jit-test/tests/basic/testGuardCalleeSneakAttack.js b/js/src/jit-test/tests/basic/testGuardCalleeSneakAttack.js new file mode 100644 index 0000000000..87939ef992 --- /dev/null +++ b/js/src/jit-test/tests/basic/testGuardCalleeSneakAttack.js @@ -0,0 +1,31 @@ +function loop(f, expected) { + // This is the loop that breaks us. + // At record time, f's parent is a Call object with no fp. + // At second execute time, it is a Call object with fp, + // and all the Call object's dslots are still JSVAL_VOID. + for (var i = 0; i < 9; i++) + assertEq(f(), expected); +} + +function C(bad) { + var x = bad; + function f() { + return x; // We trick TR::callProp() into emitting code that gets + // JSVAL_VOID (from the Call object's dslots) + // rather than the actual value (true or false). + } + this.m = f; + return f; +} + +var obj = { + set m(f) { + if (f()) // Call once to resolve x on the Call object, + // for shape consistency. Otherwise loop gets + // recorded twice. + loop(f, true); + } +}; + +loop(C.call(obj, false), false); +C.call(obj, true); diff --git a/js/src/jit-test/tests/basic/testGuardCalleeSneakAttack2.js b/js/src/jit-test/tests/basic/testGuardCalleeSneakAttack2.js new file mode 100644 index 0000000000..9bf3c0c383 --- /dev/null +++ b/js/src/jit-test/tests/basic/testGuardCalleeSneakAttack2.js @@ -0,0 +1,32 @@ +function loop(f, expected) { + // This is the loop that breaks us. + // At record time, f's parent is a Call object with no fp. + // At second execute time, it is a Call object with fp, + // and all the Call object's dslots are still JSVAL_VOID. + for (var i = 0; i < 9; i++) + assertEq(f(), expected); +} + +function C(bad) { + var x = bad; + function f() { + return x; // We trick TR::callProp() into emitting code that gets + // JSVAL_VOID (from the Call object's dslots) + // rather than the actual value (true or false). + } + if (bad) + void (f + "a!"); + return f; +} + +var obj = { +}; + +// Warm up and trace with C's Call object entrained but its stack frame gone. +loop(C.call(obj, false), false); + +// Sneaky access to f via a prototype method called implicitly by operator +. +Function.prototype.toString = function () { loop(this, true); return "hah"; }; + +// Fail hard if we don't handle the implicit call out of C to F.p.toString. +C.call(obj, true); diff --git a/js/src/jit-test/tests/basic/testHOTLOOPSize.js b/js/src/jit-test/tests/basic/testHOTLOOPSize.js new file mode 100644 index 0000000000..9245a7f2f5 --- /dev/null +++ b/js/src/jit-test/tests/basic/testHOTLOOPSize.js @@ -0,0 +1,4 @@ +function test8Size() { + return 8 > 1; +} +assertEq(test8Size(), true); diff --git a/js/src/jit-test/tests/basic/testHeavy.js b/js/src/jit-test/tests/basic/testHeavy.js new file mode 100644 index 0000000000..1d539fb2d4 --- /dev/null +++ b/js/src/jit-test/tests/basic/testHeavy.js @@ -0,0 +1,14 @@ +function heavyFn1(i) { + if (i == 3) { + var x = 3; + return [0, i].map(function (i) { return i + x; }); + } + return []; +} + +function testHeavy() { + for (var i = 0; i <= 3; i++) + heavyFn1(i); +} + +testHeavy(); diff --git a/js/src/jit-test/tests/basic/testHeavy2.js b/js/src/jit-test/tests/basic/testHeavy2.js new file mode 100644 index 0000000000..12da3eee5d --- /dev/null +++ b/js/src/jit-test/tests/basic/testHeavy2.js @@ -0,0 +1,20 @@ +function heavyFn1(i) { + if (i == 3) { + var x = 3; + return [0, i].map(function (i) { return i + x; }); + } + return []; +} + +function heavyFn2(i) { + if (i < 1000) + return heavyFn1(i); + return function () { return i; }; +} + +function testHeavy2() { + for (var i = 0; i <= 3; i++) + heavyFn2(i); +} + +testHeavy2(); diff --git a/js/src/jit-test/tests/basic/testHoleInDenseArray.js b/js/src/jit-test/tests/basic/testHoleInDenseArray.js new file mode 100644 index 0000000000..29523262c2 --- /dev/null +++ b/js/src/jit-test/tests/basic/testHoleInDenseArray.js @@ -0,0 +1,16 @@ +var s; + +function f(i) { + if (i > 4) /* side exit when arr[i] changes from bool to undefined (via a hole) */ + assertEq(s, undefined); + else + assertEq(s, false); + return 1; +} + +/* trailing 'true' ensures array has capacity >= 10 */ +var arr = [ false, false, false, false, false, , , , , , true ]; + +for (var i = 0; i < 10; ++i) { + (s = arr[i]) + f(i); +} diff --git a/js/src/jit-test/tests/basic/testHolePushing.js b/js/src/jit-test/tests/basic/testHolePushing.js new file mode 100644 index 0000000000..a2316130ea --- /dev/null +++ b/js/src/jit-test/tests/basic/testHolePushing.js @@ -0,0 +1,13 @@ +function testHolePushing() { + var a = ["foobar", "baz"]; + for (var i = 0; i < 5; i++) + a = [, "overwritten", "new"]; + var s = "["; + for (i = 0; i < a.length; i++) { + s += (i in a) ? a[i] : "<hole>"; + if (i != a.length - 1) + s += ","; + } + return s + "], " + (0 in a); +} +assertEq(testHolePushing(), "[<hole>,overwritten,new], false"); diff --git a/js/src/jit-test/tests/basic/testHolesAndIndexPropertiesOnThePrototype.js b/js/src/jit-test/tests/basic/testHolesAndIndexPropertiesOnThePrototype.js new file mode 100644 index 0000000000..1af2506bfa --- /dev/null +++ b/js/src/jit-test/tests/basic/testHolesAndIndexPropertiesOnThePrototype.js @@ -0,0 +1,29 @@ +function f(x,y,z) { + return x + y + z; +} + +Array.prototype[1] = 10; + +function g() { + var arr = [1, ,3,4,5,6]; + + for (var i = 0; i < 10; ++i) { + assertEq(f.apply(null, arr), 14); + } +} +g(); + +Object.prototype[1] = 20; + +function h() { + delete arguments[1]; + return f.apply(null, arguments); +} +assertEq(h(1,2,3), 24); + +function i() { + o = arguments; + delete o[1]; + return f.apply(null, o); +} +assertEq(i(1,2,3), 24); diff --git a/js/src/jit-test/tests/basic/testINITELEM.js b/js/src/jit-test/tests/basic/testINITELEM.js new file mode 100644 index 0000000000..2d7567a24d --- /dev/null +++ b/js/src/jit-test/tests/basic/testINITELEM.js @@ -0,0 +1,8 @@ +function testINITELEM() +{ + var x; + for (var i = 0; i < 10; ++i) + x = { 0: 5, 1: 5 }; + return x[0] + x[1]; +} +assertEq(testINITELEM(), 10); diff --git a/js/src/jit-test/tests/basic/testImplicitThisMiss.js b/js/src/jit-test/tests/basic/testImplicitThisMiss.js new file mode 100644 index 0000000000..8539001ef5 --- /dev/null +++ b/js/src/jit-test/tests/basic/testImplicitThisMiss.js @@ -0,0 +1,2 @@ +// |jit-test| error:TypeError +Function("Object.defineProperty(this, 'x', { configurable:true, get:function() { delete this['x'] } }); x()")(); diff --git a/js/src/jit-test/tests/basic/testIn.js b/js/src/jit-test/tests/basic/testIn.js new file mode 100644 index 0000000000..aeadab3088 --- /dev/null +++ b/js/src/jit-test/tests/basic/testIn.js @@ -0,0 +1,19 @@ +function testIn() { + var array = [3]; + var obj = { "-1": 5, "1.7": 3, "foo": 5, "1": 7 }; + var a = []; + for (let j = 0; j < 5; ++j) { + a.push("0" in array); + a.push(-1 in obj); + a.push(1.7 in obj); + a.push("foo" in obj); + a.push(1 in obj); + a.push("1" in array); + a.push(-2 in obj); + a.push(2.7 in obj); + a.push("bar" in obj); + a.push(2 in obj); + } + return a.join(","); +} +assertEq(testIn(), "true,true,true,true,true,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false"); diff --git a/js/src/jit-test/tests/basic/testIncDec.js b/js/src/jit-test/tests/basic/testIncDec.js new file mode 100644 index 0000000000..89b533517f --- /dev/null +++ b/js/src/jit-test/tests/basic/testIncDec.js @@ -0,0 +1,19 @@ +function testIncDec2(ii) { + var x = []; + for (let j=0;j<5;++j) { + ii=j; + jj=j; + var kk=j; + x.push(ii--); + x.push(jj--); + x.push(kk--); + x.push(++ii); + x.push(++jj); + x.push(++kk); + } + return x.join(","); +} +function testIncDec() { + return testIncDec2(0); +} +assertEq(testIncDec(), "0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4"); diff --git a/js/src/jit-test/tests/basic/testIncDecReadOnly.js b/js/src/jit-test/tests/basic/testIncDecReadOnly.js new file mode 100644 index 0000000000..5ff23b2495 --- /dev/null +++ b/js/src/jit-test/tests/basic/testIncDecReadOnly.js @@ -0,0 +1,22 @@ +var r; +Object.defineProperty(this, "x", {value: 0, writable: false}); + +for (var a = 0; a < 10; ++a) + r = ++x; +assertEq(x, 0); +assertEq(r, 1); + +for (var a = 0; a < 10; ++a) + r = --x; +assertEq(x, 0); +assertEq(r, -1); + +for (var a = 0; a < 10; ++a) + r = x++; +assertEq(x, 0); +assertEq(r, 0); + +for (var a = 0; a < 10; ++a) + r = x--; +assertEq(x, 0); +assertEq(r, 0); diff --git a/js/src/jit-test/tests/basic/testIncElem1.js b/js/src/jit-test/tests/basic/testIncElem1.js new file mode 100644 index 0000000000..633c327cf0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testIncElem1.js @@ -0,0 +1,7 @@ +var obj = {p: 100}; +var name = "p"; +var a = []; +for (var i = 0; i < 10; i++) + a[i] = ++obj[name]; +assertEq(a.join(','), '101,102,103,104,105,106,107,108,109,110'); +assertEq(obj.p, 110); diff --git a/js/src/jit-test/tests/basic/testIncElem2.js b/js/src/jit-test/tests/basic/testIncElem2.js new file mode 100644 index 0000000000..cc2d7d08e3 --- /dev/null +++ b/js/src/jit-test/tests/basic/testIncElem2.js @@ -0,0 +1,11 @@ +var obj = {s: ""}; +var name = "s"; +var a = []; +for (var i = 0; i <= 13; i++) { + a[i] = 'x'; + if (i > 8) + a[i] = ++obj[name]; // first recording changes obj.s from string to number +} +assertEq(a.join(','), Array(10).join('x,') + '1,2,3,4,5'); +assertEq(obj.s, 5); + diff --git a/js/src/jit-test/tests/basic/testIncElem3.js b/js/src/jit-test/tests/basic/testIncElem3.js new file mode 100644 index 0000000000..922aeb9b8f --- /dev/null +++ b/js/src/jit-test/tests/basic/testIncElem3.js @@ -0,0 +1,6 @@ +var arr; +for (var j = 0; j < 18; ++j ) { + arr = [,]; + ++arr[0]; +} +assertEq(isNaN(arr[0]), true); diff --git a/js/src/jit-test/tests/basic/testIncElem4.js b/js/src/jit-test/tests/basic/testIncElem4.js new file mode 100644 index 0000000000..a3cec16611 --- /dev/null +++ b/js/src/jit-test/tests/basic/testIncElem4.js @@ -0,0 +1,10 @@ + +var counter = 0; +var x = { toString: function() { counter++; } }; +var y = {}; + +for (var i = 0; i < 50; i++) + ++y[x]; + +// :FIXME: bug 672076 +//assertEq(counter, 50); diff --git a/js/src/jit-test/tests/basic/testInitPropOverMethod.js b/js/src/jit-test/tests/basic/testInitPropOverMethod.js new file mode 100644 index 0000000000..5f70d3cd6f --- /dev/null +++ b/js/src/jit-test/tests/basic/testInitPropOverMethod.js @@ -0,0 +1,9 @@ +for (var i = 0; i < 10; i++) + x = {a: function () { return 33; }, a: 4}; + +try { + result = x.a(); +} catch (exc) { + result = "threw " + exc.name; +} +assertEq(result, "threw TypeError"); diff --git a/js/src/jit-test/tests/basic/testInitPropWithIntName.js b/js/src/jit-test/tests/basic/testInitPropWithIntName.js new file mode 100644 index 0000000000..755cd726b5 --- /dev/null +++ b/js/src/jit-test/tests/basic/testInitPropWithIntName.js @@ -0,0 +1,2 @@ +for (var j=0; j<8; ++j) + ({'0': 0}); diff --git a/js/src/jit-test/tests/basic/testInitProtoPrimitive.js b/js/src/jit-test/tests/basic/testInitProtoPrimitive.js new file mode 100644 index 0000000000..d84dd8ac22 --- /dev/null +++ b/js/src/jit-test/tests/basic/testInitProtoPrimitive.js @@ -0,0 +1,2 @@ +for (var i = 0; i < 10; i++) + "" + {__proto__: 'aaa'}; diff --git a/js/src/jit-test/tests/basic/testInitSingletons.js b/js/src/jit-test/tests/basic/testInitSingletons.js new file mode 100644 index 0000000000..82ca54c81c --- /dev/null +++ b/js/src/jit-test/tests/basic/testInitSingletons.js @@ -0,0 +1,61 @@ + +var x = [1,2.5,"three",true,false,null,[1,2,3],{a:0,b:1}]; +assertEq(String(x), "1,2.5,three,true,false,,1,2,3,[object Object]"); +assertEq(x.length, 8); +assertEq(x[7].a, 0); +assertEq(x[7].b, 1); + +var y = {a:0,a:1,a:2}; +assertEq(y.a,2); + +var z = {a:0,b:1,__proto__:{c:2,d:3}}; +assertEq(z.a,0); +assertEq(z.b,1); +assertEq(z.c,2); +assertEq(z.d,3); + +function foo() { + var q = eval("[1,2,3]"); + var r = eval("[1,2,3]"); + assertEq(q === r, false); +} +foo(); + +var q = {0x4fffffff: 0, 0x7fffffff: 1, 0xffffffff: 2}; +assertEq(q[1342177279], 0); +assertEq(q[2147483647], 1); +assertEq(q[4294967295], 2); + +try { + [1,2,3,{a:0,b:1}].foo.bar; +} catch (e) { + assertEq(/(.foo is|"bar" of) undefined/.test(e.message), true); +} + +var a = [1 + 1, 3 * 2, 6 - 5, 14 % 6, 15 / 5, 1 << 3, + 8 >> 2, 5 | 2, 5 ^ 3, ~3, -3,"a" + "b", !true, !false]; +assertEq(String(a), "2,6,1,2,3,8,2,7,6,-4,-3,ab,false,true"); +assertEq(a.length, 14); + +var b = { + a: 1 + 1, + b: 3 * 2, + c: 6 - 5, + d: 14 % 6, + e: 15 / 5, + f: 1 << 3, + g: 8 >> 2, + h: 5 | 2, + i: 5 ^ 3, + j: ~3, + k: -3, + l: "a" + "b", + m: !true, + n: !false, +} + +var char = "a".charCodeAt(0); +for (var i = 0; i < a.length; i++) { + assertEq(b[String.fromCharCode(char)], a[i]); + char++; +} diff --git a/js/src/jit-test/tests/basic/testInitSlowify.js b/js/src/jit-test/tests/basic/testInitSlowify.js new file mode 100644 index 0000000000..fb6868c25f --- /dev/null +++ b/js/src/jit-test/tests/basic/testInitSlowify.js @@ -0,0 +1,41 @@ + +var x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,gc(), + ]; +assertEq(x.length, 500); +assertEq(x[10], 11); +assertEq(x[90], 11); + +function stringify(a) { + var b = ""; + for (var c in a) { b += c + ","; } + return b; +} + +var y = {a:1,b:2,c:3,d:4,e:gc(),f:6,g:7,h:8,i:9,j:gc(), + k:11,l:12,m:13,n:14,o:gc(),p:16,q:17,r:18,s:19,t:gc()}; + +assertEq(stringify(y), "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,"); diff --git a/js/src/jit-test/tests/basic/testInitelemCond.js b/js/src/jit-test/tests/basic/testInitelemCond.js new file mode 100644 index 0000000000..2f83c12102 --- /dev/null +++ b/js/src/jit-test/tests/basic/testInitelemCond.js @@ -0,0 +1,13 @@ + +/* Element initializers with unknown index. */ + +function foo(i) { + var x = [1,2,i == 1 ? 3 : 4,5,6]; + var y = "" + x; + if (i == 1) + assertEq(y, "1,2,3,5,6"); + else + assertEq(y, "1,2,4,5,6"); +} +for (var i = 0; i < 10; i++) + foo(i); diff --git a/js/src/jit-test/tests/basic/testInitelemWithFloatIndex.js b/js/src/jit-test/tests/basic/testInitelemWithFloatIndex.js new file mode 100644 index 0000000000..93477e7cbe --- /dev/null +++ b/js/src/jit-test/tests/basic/testInitelemWithFloatIndex.js @@ -0,0 +1,3 @@ +for (i = 0; i < 9; i++) + x = {1.5: 0}; +assertEq(x["1.5"], 0); diff --git a/js/src/jit-test/tests/basic/testInitelemWithSetter.js b/js/src/jit-test/tests/basic/testInitelemWithSetter.js new file mode 100644 index 0000000000..6753b37870 --- /dev/null +++ b/js/src/jit-test/tests/basic/testInitelemWithSetter.js @@ -0,0 +1,3 @@ +Object.prototype.__defineSetter__(1, function () { throw "fit"; }); +for (var i =0; i<9; i++) + ({1:'a'}); diff --git a/js/src/jit-test/tests/basic/testInnerMissingArgs.js b/js/src/jit-test/tests/basic/testInnerMissingArgs.js new file mode 100644 index 0000000000..d70b5d1aaa --- /dev/null +++ b/js/src/jit-test/tests/basic/testInnerMissingArgs.js @@ -0,0 +1,21 @@ +function innerTestInnerMissingArgs(a,b,c,d) +{ + if (a) { + } else { + } +} + +function doTestInnerMissingArgs(k) +{ + for (i = 0; i < 10; i++) { + innerTestInnerMissingArgs(k); + } +} + +function testInnerMissingArgs() +{ + doTestInnerMissingArgs(1); + doTestInnerMissingArgs(0); +} + +testInnerMissingArgs(); diff --git a/js/src/jit-test/tests/basic/testInnerSwitchBreak.js b/js/src/jit-test/tests/basic/testInnerSwitchBreak.js new file mode 100644 index 0000000000..4e9eafdbc3 --- /dev/null +++ b/js/src/jit-test/tests/basic/testInnerSwitchBreak.js @@ -0,0 +1,24 @@ +function innerSwitch(k) +{ + var m = 0; + + switch (k) + { + case 0: + m = 1; + break; + } + + return m; +} +function testInnerSwitchBreak() +{ + var r = new Array(5); + for (var i = 0; i < 5; i++) + { + r[i] = innerSwitch(0); + } + + return r.join(","); +} +assertEq(testInnerSwitchBreak(), "1,1,1,1,1"); diff --git a/js/src/jit-test/tests/basic/testInnerTreeMutatingUpvars.js b/js/src/jit-test/tests/basic/testInnerTreeMutatingUpvars.js new file mode 100644 index 0000000000..97502f8364 --- /dev/null +++ b/js/src/jit-test/tests/basic/testInnerTreeMutatingUpvars.js @@ -0,0 +1,17 @@ +function f() { + for (var a = 0; a < 8; ++a) { + (function () { + var x; + for (var b = 0; b < 8; ++b) { + x = 0; + (function () { + for (var i = 0; i < 1; ++i) { + x = 1; + } + })(); + x++; + } + })(); + } +} +f(); diff --git a/js/src/jit-test/tests/basic/testInt32ToId.js b/js/src/jit-test/tests/basic/testInt32ToId.js new file mode 100644 index 0000000000..3164ac5de3 --- /dev/null +++ b/js/src/jit-test/tests/basic/testInt32ToId.js @@ -0,0 +1,35 @@ +function testInt32ToId() +{ + // Ensure that a property which is a negative integer that does not fit in a + // jsval is properly detected by the 'in' operator. + var obj = { "-1073741828": 17 }; + var index = -1073741819; + var a = []; + for (var i = 0; i < 10; i++) + { + a.push(index in obj); + index--; + } + + // Ensure that a property which is a negative integer that does not fit in a + // jsval is properly *not* detected by the 'in' operator. In this case + // wrongly applying INT_TO_JSID to -2147483648 will shift off the sign bit + // (the only bit set in that number) and bitwise-or that value with 1, + // producing jsid(1) -- which actually represents "0", not "-2147483648". + // Thus 'in' will report a "-2147483648" property when none exists, because + // it thinks the request was really whether the object had property "0". + var obj2 = { 0: 17 }; + var b = []; + var index = -(1 << 28); + for (var i = 0; i < 10; i++) + { + b.push(index in obj2); + index = index - (1 << 28); + } + + return a.join(",") + b.join(","); +} + +assertEq(testInt32ToId(), + "false,false,false,false,false,false,false,false,false,true" + + "false,false,false,false,false,false,false,false,false,false"); diff --git a/js/src/jit-test/tests/basic/testIntFloor.js b/js/src/jit-test/tests/basic/testIntFloor.js new file mode 100644 index 0000000000..80b4ea741f --- /dev/null +++ b/js/src/jit-test/tests/basic/testIntFloor.js @@ -0,0 +1,8 @@ +function testIntFloor() { + var a; + for (var x = 0; x < 3; ++x) { + a = Math.floor('') + } + return a; +} +assertEq(testIntFloor(), 0) diff --git a/js/src/jit-test/tests/basic/testIntOverflow.js b/js/src/jit-test/tests/basic/testIntOverflow.js new file mode 100644 index 0000000000..cfe68983ce --- /dev/null +++ b/js/src/jit-test/tests/basic/testIntOverflow.js @@ -0,0 +1,9 @@ +function testIntOverflow() { + // int32_max - 7 + var ival = 2147483647 - 7; + for (var i = 0; i < 30; i++) { + ival += 30; + } + return (ival < 2147483647); +} +assertEq(testIntOverflow(), false); diff --git a/js/src/jit-test/tests/basic/testIntUnderflow.js b/js/src/jit-test/tests/basic/testIntUnderflow.js new file mode 100644 index 0000000000..65db00a0a7 --- /dev/null +++ b/js/src/jit-test/tests/basic/testIntUnderflow.js @@ -0,0 +1,9 @@ +function testIntUnderflow() { + // int32_min + 8 + var ival = -2147483648 + 8; + for (var i = 0; i < 30; i++) { + ival -= 2; + } + return (ival > -2147483648); +} +assertEq(testIntUnderflow(), false); diff --git a/js/src/jit-test/tests/basic/testInterpreterReentry.js b/js/src/jit-test/tests/basic/testInterpreterReentry.js new file mode 100644 index 0000000000..d820b23336 --- /dev/null +++ b/js/src/jit-test/tests/basic/testInterpreterReentry.js @@ -0,0 +1,6 @@ +function testInterpreterReentry() { + this.__defineSetter__('x', function(){}) + for (var j = 0; j < 5; ++j) { x = 3; } + return 1; +} +assertEq(testInterpreterReentry(), 1); diff --git a/js/src/jit-test/tests/basic/testInterpreterReentry2.js b/js/src/jit-test/tests/basic/testInterpreterReentry2.js new file mode 100644 index 0000000000..030f088e1f --- /dev/null +++ b/js/src/jit-test/tests/basic/testInterpreterReentry2.js @@ -0,0 +1,10 @@ +function testInterpreterReentry2() { + var a = false; + var b = {}; + var c = false; + var d = {}; + this.__defineGetter__('e', function(){}); + for (let f in this) print(f); + return 1; +} +assertEq(testInterpreterReentry2(), 1); diff --git a/js/src/jit-test/tests/basic/testInterpreterReentry3.js b/js/src/jit-test/tests/basic/testInterpreterReentry3.js new file mode 100644 index 0000000000..5c3e7a3d0b --- /dev/null +++ b/js/src/jit-test/tests/basic/testInterpreterReentry3.js @@ -0,0 +1,6 @@ +function testInterpreterReentry3() { + for (let i=0;i<5;++i) this["y" + i] = function(){}; + this.__defineGetter__('e', function* (x2) { yield; }); + return 1; +} +assertEq(testInterpreterReentry3(), 1); diff --git a/js/src/jit-test/tests/basic/testInterpreterReentry4.js b/js/src/jit-test/tests/basic/testInterpreterReentry4.js new file mode 100644 index 0000000000..b09e5cb9a7 --- /dev/null +++ b/js/src/jit-test/tests/basic/testInterpreterReentry4.js @@ -0,0 +1,6 @@ +function testInterpreterReentry4() { + var obj = {a:1, b:1, c:1, d:1, get e() { return 1000; } }; + for (var p in obj) + obj[p]; +} +testInterpreterReentry4(); diff --git a/js/src/jit-test/tests/basic/testInterpreterReentry5.js b/js/src/jit-test/tests/basic/testInterpreterReentry5.js new file mode 100644 index 0000000000..1c9b698ebf --- /dev/null +++ b/js/src/jit-test/tests/basic/testInterpreterReentry5.js @@ -0,0 +1,9 @@ +function testInterpreterReentry5() { + var arr = [0, 1, 2, 3, 4]; + arr.__defineGetter__("4", function() { return 1000; }); + for (var i = 0; i < 5; i++) + arr[i]; + for (var p in arr) + arr[p]; +} +testInterpreterReentry5(); diff --git a/js/src/jit-test/tests/basic/testInterpreterReentry6.js b/js/src/jit-test/tests/basic/testInterpreterReentry6.js new file mode 100644 index 0000000000..c5a6b28630 --- /dev/null +++ b/js/src/jit-test/tests/basic/testInterpreterReentry6.js @@ -0,0 +1,7 @@ +function testInterpreterReentry6() { + var obj = {a:1, b:1, c:1, d:1, set e(x) { this._e = x; }}; + for (var p in obj) + obj[p] = "grue"; + return obj._e; +} +assertEq(testInterpreterReentry6(), "grue"); diff --git a/js/src/jit-test/tests/basic/testInterpreterReentry7.js b/js/src/jit-test/tests/basic/testInterpreterReentry7.js new file mode 100644 index 0000000000..36b34c6f0c --- /dev/null +++ b/js/src/jit-test/tests/basic/testInterpreterReentry7.js @@ -0,0 +1,11 @@ +function testInterpreterReentry7() { + var arr = [0, 1, 2, 3, 4]; + arr.__defineSetter__("4", function(x) { this._4 = x; }); + for (var i = 0; i < 5; i++) + arr[i] = "grue"; + var tmp = arr._4; + for (var p in arr) + arr[p] = "bleen"; + return tmp + " " + arr._4; +} +assertEq(testInterpreterReentry7(), "grue bleen"); diff --git a/js/src/jit-test/tests/basic/testInvalidCharCodeAt.js b/js/src/jit-test/tests/basic/testInvalidCharCodeAt.js new file mode 100644 index 0000000000..748220fcd0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testInvalidCharCodeAt.js @@ -0,0 +1,12 @@ +function doTestInvalidCharCodeAt(input) +{ + var q = ""; + for (var i = 0; i < 10; i++) + q += input.charCodeAt(i); + return q; +} +function testInvalidCharCodeAt() +{ + return doTestInvalidCharCodeAt(""); +} +assertEq(testInvalidCharCodeAt(), "NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN"); diff --git a/js/src/jit-test/tests/basic/testInvertNullAfterNegateNull.js b/js/src/jit-test/tests/basic/testInvertNullAfterNegateNull.js new file mode 100644 index 0000000000..7e6a12b05f --- /dev/null +++ b/js/src/jit-test/tests/basic/testInvertNullAfterNegateNull.js @@ -0,0 +1,7 @@ +function testInvertNullAfterNegateNull() +{ + for (var i = 0; i < 5; i++) !null; + for (var i = 0; i < 5; i++) -null; + return "no assertion"; +} +assertEq(testInvertNullAfterNegateNull(), "no assertion"); diff --git a/js/src/jit-test/tests/basic/testIteratorReification.js b/js/src/jit-test/tests/basic/testIteratorReification.js new file mode 100644 index 0000000000..8f89672bb2 --- /dev/null +++ b/js/src/jit-test/tests/basic/testIteratorReification.js @@ -0,0 +1 @@ +for (b in evalcx('')) {} diff --git a/js/src/jit-test/tests/basic/testLambdaCtor.js b/js/src/jit-test/tests/basic/testLambdaCtor.js new file mode 100644 index 0000000000..ea91cd9a48 --- /dev/null +++ b/js/src/jit-test/tests/basic/testLambdaCtor.js @@ -0,0 +1,13 @@ +function testLambdaCtor() { + var a = []; + for (var x = 0; x < 9; ++x) { + var f = function(){}; + a[a.length] = new f; + } + + assertEq([8].__proto__ !== a[7].__proto__, true); + + // Assert that the last f was properly constructed. + return a[8].__proto__ === f.prototype; +} +assertEq(testLambdaCtor(), true); diff --git a/js/src/jit-test/tests/basic/testLambdaInitedVar.js b/js/src/jit-test/tests/basic/testLambdaInitedVar.js new file mode 100644 index 0000000000..e37b4f9c7b --- /dev/null +++ b/js/src/jit-test/tests/basic/testLambdaInitedVar.js @@ -0,0 +1,8 @@ +function testLambdaInitedVar() { + var jQuery = function (a, b) { + return jQuery && jQuery.length; + } + return jQuery(); +} + +assertEq(testLambdaInitedVar(), 2); diff --git a/js/src/jit-test/tests/basic/testLengthInString.js b/js/src/jit-test/tests/basic/testLengthInString.js new file mode 100644 index 0000000000..5950b509f9 --- /dev/null +++ b/js/src/jit-test/tests/basic/testLengthInString.js @@ -0,0 +1,12 @@ +function testLengthInString() +{ + var s = new String(); + var res = "length" in s; + for (var i = 0; i < 5; i++) + res = res && ("length" in s); + res = res && s.hasOwnProperty("length"); + for (var i = 0; i < 5; i++) + res = res && s.hasOwnProperty("length"); + return res; +} +assertEq(testLengthInString(), true); diff --git a/js/src/jit-test/tests/basic/testLengthOnNonNativeProto.js b/js/src/jit-test/tests/basic/testLengthOnNonNativeProto.js new file mode 100644 index 0000000000..80d388f8dd --- /dev/null +++ b/js/src/jit-test/tests/basic/testLengthOnNonNativeProto.js @@ -0,0 +1,20 @@ +function testLengthOnNonNativeProto() +{ + var o = {}; + o.__proto__ = [3]; + for (var j = 0; j < 5; j++) + o[0]; + + var o2 = {}; + o2.__proto__ = []; + for (var j = 0; j < 5; j++) + o2.length; + + function foo() { } + foo.__proto__ = []; + for (var j = 0; j < 5; j++) + foo.length; + + return "no assertion"; +} +assertEq(testLengthOnNonNativeProto(), "no assertion"); diff --git a/js/src/jit-test/tests/basic/testLet.js b/js/src/jit-test/tests/basic/testLet.js new file mode 100644 index 0000000000..940dcff3dc --- /dev/null +++ b/js/src/jit-test/tests/basic/testLet.js @@ -0,0 +1,210 @@ +var otherGlobal = newGlobal(); + +function test(str, arg, result) +{ + arg = arg || 'ponies'; + if (arguments.length < 3) + result = 'ponies'; + + var fun = new Function('x', str); + + var got = `(${fun.toString()})`; + var expect = '(function anonymous(x\n) {\n' + str + '\n})'; + if (got !== expect) { + print("GOT: " + got); + print("EXPECT: " + expect); + assertEq(got, expect); + } + + // test reflection logic + Reflect.parse(got); + + var got = fun(arg); + var expect = result; + if (got !== expect) { + print("GOT:" + got); + print("EXPECT: " + expect); + assertEq(got, expect); + } +} + +function isParseError(str) +{ + var caught = false; + try { + new Function(str); + } catch(e) { + assertEq(e instanceof TypeError || e instanceof SyntaxError, true); + caught = true; + } + assertEq(caught, true); +} + +function isRuntimeParseError(str, arg) +{ + var caught = false; + try { + (new Function("x", str))(arg); + } catch(e) { + assertEq(e instanceof TypeError || e instanceof SyntaxError, true); + caught = true; + } + assertEq(caught, true); +} + +function isReferenceError(str) +{ + var caught = false; + try { + (new Function(str))(); + } catch(e) { + assertEq(e instanceof ReferenceError, true); + caught = true; + } + assertEq(caught, true); +} + +// var declarations +test('var y;return x;'); +test('var y = x;return x;'); +test('var [] = x;return x;'); +test('var [, ] = x;return x;'); +test('var [, , , , ] = x;return x;'); +test('var x = x;return x;'); +test('var y = y;return "" + y;', 'unicorns', 'undefined'); +test('var x = eval("x");return x;'); +test('var X = x + 1, y = x;return y;'); +test('var X = x + 1, [] = X, [[, , ]] = X, y = x;return y;'); +test('var [{a: X}] = x, [, {b: y}] = x;var X = X + 1, y = y + 2;return X + y;', [{a:"p"},{b:"p"}], "p1p2"); +test('var [x] = [x];return x;'); +test('var [[a, [b, c]]] = [[x, []]];return a;'); +test('var [y] = [x];return y;'); +test('var [a] = (1, [x]);return a;'); +test('var [a] = (1, x, 1, x);return a;', ['ponies']); +test('var [x, y] = [x, x + 1];return x + y;', 1, 3); +test('var [x, y, z] = [x, x + 1, x + 2];return x + y + z;', 1, 6); +test('var [[x]] = [[x]];return x;'); +test('var [x, y] = [x, x + 1];return x;'); +test('var [x, [y, z]] = [x, x + 1];return x;'); +test('var [{x: [x]}, {y1: y, z1: z}] = [x, x + 1];return x;',{x:['ponies']}); +test('if (x) {var y = x;return x;}'); +test('if (x) {y = x;var y = y;return y;}'); +test('if (x) {var z = y;var [y] = x;z += y;}return z;', ['-'], 'undefined-'); + +// let declaration in context +test('if (x) {let y;return x;}'); +test('if (x) {let x;return "" + x;}', 'unicorns', 'undefined'); +test('if (x) {let y = x;return x;}'); +test('if (x) {let y = x;return x;}'); +test('if (x) {let [] = x;return x;}'); +test('if (x) {let [, ] = x;return x;}'); +test('if (x) {let [, , , , ] = x;return x;}'); +test('if (x) {let X = x + 1, y = x;return y;}'); +test('if (x) {let X = x + 1, [] = X, [[, , ]] = X, y = x;return y;}'); +test('if (x) {let [{a: X}] = x, [, {b: Y}] = x;var XX = X + 1, YY = Y + 2;return XX + YY;}', [{a:"p"},{b:"p"}], "p1p2"); +test('if (x) {let [[a, [b, c]]] = [[x, []]];return a;}'); +test('if (x) {let [X] = [x];return X;}'); +test('if (x) {let [y] = [x];return y;}'); +test('if (x) {let [a] = (1, [x]);return a;}'); +test('if (x) {let [a] = (1, x, 1, x);return a;}', ['ponies']); +test('if (x) {let [X, y] = [x, x + 1];return X + y;}', 1, 3); +test('if (x) {let [X, y, z] = [x, x + 1, x + 2];return X + y + z;}', 1, 6); +test('if (x) {let [[X]] = [[x]];return X;}'); +test('if (x) {let [X, y] = [x, x + 1];return X;}'); +test('if (x) {let [X, [y, z]] = [x, x + 1];return X;}'); +test('if (x) {let [{x: [X]}, {y1: y, z1: z}] = [x, x + 1];return X;}',{x:['ponies']}); +test('if (x) {let y = x;try {let x = 1;throw 2;} catch (e) {return y;}}'); +test('try {let x = 1;throw 2;} catch (e) {return x;}'); +test('x.foo;{let y = x;return y;}'); +test('x.foo;if (x) {x.bar;let y = x;return y;}'); +test('if (x) {let y = x;return function () {return eval("y");}();}'); +test('return eval("let y = x; y");'); +isRuntimeParseError('if (x) {let y = x;eval("var y = 2");return y;}', 'ponies'); +test('"use strict";if (x) {let y = x;eval("var y = 2");return y;}'); +test('"use strict";if (x) {let y = x;eval("let y = 2");return y;}'); +test('"use strict";if (x) {let y = 1;return eval("let y = x;y;");}'); +test('this.y = x;if (x) {let y = 1;return this.eval("y");}'); + +// for(;;) +test('for (;;) {return x;}'); +test('for (let y = 1;;) {return x;}'); +test('for (let y = 1;; ++y) {return x;}'); +test('for (let y = 1; ++y;) {return x;}'); +test('for (let [[a, [b, c]]] = [[x, []]];;) {return a;}'); +test('var sum = 0;for (let y = x; y < 4; ++y) {sum += y;}return sum;', 1, 6); +test('var sum = 0;for (let x = 1; eval("x") < 4; ++x) {sum += eval("x");}return sum;', 1, 6); +test('for (var y = 1;;) {return x;}'); +test('for (var y = 1;; ++y) {return x;}'); +test('for (var y = 1; ++y;) {return x;}'); +test('for (var X = 1, [y, z] = x, a = x; z < 4; ++z) {return X + y;}', [2,3], 3); +test('var sum = 0;for (var y = x; y < 4; ++y) {sum += y;}return sum;', 1, 6); +test('var sum = 0;for (var X = x, y = 10; X < 4; ++X) {sum += X;}return sum;', 1, 6); +test('var sum = 0;for (var X = x; X < 4; ++X) {sum += X;}return x;', 1, 1); +test('var sum = 0;for (var X = eval("x"); X < 4; ++X) {sum += X;}return sum;', 1, 6); +test('var sum = 0;for (var X = x; eval("X") < 4; ++X) {sum += eval("X");}return sum;', 1, 6); +test('var sum = 0;for (var X = eval("x"); eval("X") < 4; ++X) {sum += eval("X");}return sum;', 1, 6); +test('for (let y = x;;) {let x;return y;}'); +test('for (let y = x;;) {let y;return x;}'); +test('for (let y;;) {let y;return x;}'); +test('for (let a = x;;) {let c = x, d = x;return c;}'); +test('for (let [a, b] = x;;) {let c = x, d = x;return c;}'); +test('for (let [a] = (1, [x]);;) {return a;}'); +test('for (let [a] = (1, x, 1, x);;) {return a;}', ['ponies']); +isParseError('for (let x = 1, x = 2;;) {}'); +isParseError('for (let [x, y] = a, {a:x} = b;;) {}'); +isParseError('for (let [x, y, x] = a;;) {}'); +isParseError('for (let [x, [y, [x]]] = a;;) {}'); + +// for(in) +test('for (let i in x) {return x;}'); +test('for (let i in x) {let y;return x;}'); +test('for (let i in x) {let i = x;return i;}'); +test('var s = "";for (let a in x) {for (let b in x) {s += a + b;}}return s;', [1,2], '00011011'); +test('var res = "";for (let i in x) {res += x[i];}return res;'); +test('var res = "";for (var i in x) {res += x[i];}return res;'); +isParseError('for ((let (x = {y: true}) x).y in eval("x")) {return eval("x");}'); +test('for (let i in x) {break;}return x;'); +test('for (let i in x) {break;}return eval("x");'); +test('a:for (let i in x) {for (let j in x) {break a;}}return x;'); +test('a:for (let i in x) {for (let j in x) {break a;}}return eval("x");'); +test('var j;for (let i in x) {j = i;break;}return j;', {ponies:true}); +isParseError('for (let [x, x] in o) {}'); +isParseError('for (let [x, y, x] in o) {}'); +isParseError('for (let [x, [y, [x]]] in o) {}'); + +// for(let ... in ...) scoping bugs (bug 1069480) +isReferenceError('for (let x in eval("x")) {return x;}', {ponies:true}, undefined); +isReferenceError('for (let x in x) {return eval("x");}', {ponies:true}, undefined); +isReferenceError('for (let x in eval("x")) {return eval("x");}', {ponies:true}, undefined); +isReferenceError('for (let x in x) {break;}return x;'); +isReferenceError('for (let x in x) {break;}return eval("x");'); +isReferenceError('for (let x in eval("throw x")) {}', undefined, undefined); + +// don't forget about switch craziness +test('var y = 3;switch (function () {return eval("y");}()) {case 3:let y;return x;default:;}'); +test('switch (x) {case 3:let y;return 3;case 4:let z;return 4;default:return x;}'); +isParseError('switch (x) {case 3:let y;return 3;case 4:let y;return 4;default:;}'); + +// TDZ checks +isReferenceError('x + 1; let x = 42;'); +isReferenceError('x = 42; let x;'); +isReferenceError('inner(); function inner() { x++; } let x;'); +isReferenceError('inner(); let x; function inner() { x++; }'); +isReferenceError('inner(); let x; function inner() { function innerer() { x++; } innerer(); }'); +isReferenceError('let x; var inner = function () { y++; }; inner(); let y;'); +isReferenceError('let x = x;'); +isReferenceError('let [x] = [x];'); +isReferenceError('let {x} = {x:x};'); +isReferenceError('switch (x) {case 3:let x;break;default:if (x === undefined) {return "ponies";}}'); +isReferenceError('let x = function() {} ? x() : function() {}'); +isReferenceError('(function() { let x = (function() { return x }()); }())'); +isReferenceError('var sum = 0;for (let x = x, y = 10; x < 4; ++x) {sum += x;}return sum;'); +isReferenceError('var sum = 0;for (let x = x; x < 4; ++x) {sum += x;}return x;'); +isReferenceError('var sum = 0;for (let x = eval("x"); x < 4; ++x) {sum += x;}return sum;'); +isReferenceError('var sum = 0;for (let x = x; eval("x") < 4; ++x) {sum += eval("x");}return sum;'); +isReferenceError('var sum = 0;for (let x = eval("x"); eval("x") < 4; ++x) {sum += eval("x");}return sum;'); +isReferenceError('for (let x = eval("throw x");;) {}'); +isReferenceError('for (let x = x + "s"; eval("throw x");) {}'); + +// redecl with function statements +isParseError('let a; function a() {}'); diff --git a/js/src/jit-test/tests/basic/testLetOverridingArgs.js b/js/src/jit-test/tests/basic/testLetOverridingArgs.js new file mode 100644 index 0000000000..fbebe7a2fc --- /dev/null +++ b/js/src/jit-test/tests/basic/testLetOverridingArgs.js @@ -0,0 +1,5 @@ +function f1() { { let arguments = 42; return arguments } } +assertEq(f1(), 42); + +function f2() { { let arguments; return arguments } } +assertEq(f2(), undefined); diff --git a/js/src/jit-test/tests/basic/testLirBufOOM.js b/js/src/jit-test/tests/basic/testLirBufOOM.js new file mode 100644 index 0000000000..f9d4e1dc92 --- /dev/null +++ b/js/src/jit-test/tests/basic/testLirBufOOM.js @@ -0,0 +1,34 @@ +function testLirBufOOM() +{ + var a = [ + "12345678901234", + "123456789012", + "1234567890123456789012345678", + "12345678901234567890123456789012345678901234567890123456", + "f", + "$", + "", + "f()", + "(\\*)", + "b()", + "()", + "(#)", + "ABCDEFGHIJK", + "ABCDEFGHIJKLM", + "ABCDEFGHIJKLMNOPQ", + "ABCDEFGH", + "(.)", + "(|)", + "()$", + "/()", + "(.)$" + ]; + + for (var j = 0; j < 200; ++j) { + var js = "" + j; + for (var i = 0; i < a.length; i++) + "".match(a[i] + js) + } + return "ok"; +} +assertEq(testLirBufOOM(), "ok"); diff --git a/js/src/jit-test/tests/basic/testLocaleCompare.js b/js/src/jit-test/tests/basic/testLocaleCompare.js new file mode 100644 index 0000000000..e9428b2c6f --- /dev/null +++ b/js/src/jit-test/tests/basic/testLocaleCompare.js @@ -0,0 +1,8 @@ +assertEq("undefined".localeCompare(), 0); +assertEq("a".localeCompare(), "a".localeCompare("undefined")); +assertEq("a".localeCompare("b"), -1); +assertEq("a".localeCompare("b", "en"), -1); +assertEq("b".localeCompare("a"), 1); +assertEq("b".localeCompare("a", "en"), 1); +assertEq("a".localeCompare("a"), 0); +assertEq("a".localeCompare("a", "en"), 0); diff --git a/js/src/jit-test/tests/basic/testLogicalNotNaN.js b/js/src/jit-test/tests/basic/testLogicalNotNaN.js new file mode 100644 index 0000000000..6bb0251e28 --- /dev/null +++ b/js/src/jit-test/tests/basic/testLogicalNotNaN.js @@ -0,0 +1,8 @@ +function testLogicalNotNaN() { + var i = 0; + var a = new Array(5); + while (i < a.length) + a[i++] = !NaN; + return a.join(); +} +assertEq(testLogicalNotNaN(), "true,true,true,true,true"); diff --git a/js/src/jit-test/tests/basic/testLongNumToString.js b/js/src/jit-test/tests/basic/testLongNumToString.js new file mode 100644 index 0000000000..def2b47a9b --- /dev/null +++ b/js/src/jit-test/tests/basic/testLongNumToString.js @@ -0,0 +1,7 @@ +function testLongNumToString() { + var s; + for (var i = 0; i < 5; i++) + s = (0x08000000).toString(2); + return s; +} +assertEq(testLongNumToString(), '1000000000000000000000000000'); diff --git a/js/src/jit-test/tests/basic/testLoopWithUndefined1.js b/js/src/jit-test/tests/basic/testLoopWithUndefined1.js new file mode 100644 index 0000000000..63c4b97a8f --- /dev/null +++ b/js/src/jit-test/tests/basic/testLoopWithUndefined1.js @@ -0,0 +1,12 @@ +function loopWithUndefined1(t, val) { + var a = new Array(6); + for (var i = 0; i < 6; i++) + a[i] = (t > val); + return a; +} +loopWithUndefined1(5.0, 2); //compile version with val=int + +function testLoopWithUndefined1() { + return loopWithUndefined1(5.0).join(","); //val=undefined +}; +assertEq(testLoopWithUndefined1(), "false,false,false,false,false,false"); diff --git a/js/src/jit-test/tests/basic/testLoopWithUndefined2.js b/js/src/jit-test/tests/basic/testLoopWithUndefined2.js new file mode 100644 index 0000000000..a6ba9dbe53 --- /dev/null +++ b/js/src/jit-test/tests/basic/testLoopWithUndefined2.js @@ -0,0 +1,20 @@ +function loopWithUndefined2(t, dostuff, val) { + var a = new Array(6); + for (var i = 0; i < 6; i++) { + if (dostuff) { + val = 1; + a[i] = (t > val); + } else { + a[i] = (val == undefined); + } + } + return a; +} +function testLoopWithUndefined2() { + var a = loopWithUndefined2(5.0, true, 2); + var b = loopWithUndefined2(5.0, true); + var c = loopWithUndefined2(5.0, false, 8); + var d = loopWithUndefined2(5.0, false); + return [a[0], b[0], c[0], d[0]].join(","); +} +assertEq(testLoopWithUndefined2(), "true,true,false,true"); diff --git a/js/src/jit-test/tests/basic/testLoopingAccumulator.js b/js/src/jit-test/tests/basic/testLoopingAccumulator.js new file mode 100644 index 0000000000..bacb29bea5 --- /dev/null +++ b/js/src/jit-test/tests/basic/testLoopingAccumulator.js @@ -0,0 +1,21 @@ +function addAccumulations(f) { + var a = f(); + var b = f(); + return a() + b(); +} + +function loopingAccumulator() { + var x = 0; + return function () { + for (var i = 0; i < 10; ++i) { + ++x; + } + return x; + } +} + +function testLoopingAccumulator() { + var x = addAccumulations(loopingAccumulator); + return x; +} +assertEq(testLoopingAccumulator(), 20); diff --git a/js/src/jit-test/tests/basic/testManyVars.js b/js/src/jit-test/tests/basic/testManyVars.js new file mode 100644 index 0000000000..a89d4539cf --- /dev/null +++ b/js/src/jit-test/tests/basic/testManyVars.js @@ -0,0 +1,13 @@ +const MANY_VARS = Math.pow(2,17); + +var code = "function f1() {\n"; +code += " var x0 = 0"; +for (var i = 1; i < MANY_VARS; i++) + code += ", x" + i + " = " + i; +code += ";\n"; +for (var i = 0; i < MANY_VARS; i += 100) + code += " assertEq(x" + i + ", " + i + ");\n"; +code += " return x80000;\n"; +code += "}\n"; +eval(code); +assertEq(f1(), 80000); diff --git a/js/src/jit-test/tests/basic/testMatchAsCondition.js b/js/src/jit-test/tests/basic/testMatchAsCondition.js new file mode 100644 index 0000000000..8cb429f0c5 --- /dev/null +++ b/js/src/jit-test/tests/basic/testMatchAsCondition.js @@ -0,0 +1,8 @@ +function testMatchAsCondition() { + var a = ['0', '0', '0', '0']; + var r = /0/; + "x".q; + for (var z = 0; z < 4; z++) + a[z].match(r) ? 1 : 2; +} +testMatchAsCondition(); diff --git a/js/src/jit-test/tests/basic/testMatchStringObject.js b/js/src/jit-test/tests/basic/testMatchStringObject.js new file mode 100644 index 0000000000..cde2da1aed --- /dev/null +++ b/js/src/jit-test/tests/basic/testMatchStringObject.js @@ -0,0 +1,8 @@ +function testMatchStringObject() { + var a = new String("foo"); + var b; + for (i = 0; i < 300; i++) + b = a.match(/bar/); + return b; +} +assertEq(testMatchStringObject(), null); diff --git a/js/src/jit-test/tests/basic/testMathClz32.js b/js/src/jit-test/tests/basic/testMathClz32.js new file mode 100644 index 0000000000..61cd1f91a2 --- /dev/null +++ b/js/src/jit-test/tests/basic/testMathClz32.js @@ -0,0 +1,38 @@ +function f() { + var x = 0; + for (var i = 1; i < 1e6; i++) { + if (i > 0) + x += Math.clz32(i); + } + return x; +} + +function g() { + var x = 0; + for (var i = 1; i < 1e6; i++) { + x += Math.clz32(i); + } + return x; +} + +function h() { + var x = 0; + for (var i = 0; i < 1e6; i++) { + x += Math.clz32(i); + } + return x; +} + +function k() { + var x = 0; + for (var i = -1000; i < 1000; i++) { + x += Math.clz32(i); + x += Math.clz32(i + 0.5); + } + return x; +} + +assertEq(f(), 13048543); +assertEq(g(), 13048543); +assertEq(h(), 13048575); +assertEq(k(), 46078); diff --git a/js/src/jit-test/tests/basic/testMathMinMax.js b/js/src/jit-test/tests/basic/testMathMinMax.js new file mode 100644 index 0000000000..4c057fa6da --- /dev/null +++ b/js/src/jit-test/tests/basic/testMathMinMax.js @@ -0,0 +1,74 @@ +for (var i = 2; i < 10; i++) { + assertEq(Math.min(i, 1), 1); + assertEq(Math.min(i, -1), -1); + assertEq(Math.min(1, i), 1); + assertEq(Math.min(-1, i), -1); + assertEq(Math.min(5, 2), 2); + assertEq(Math.min(2, 5), 2); + assertEq(Math.min(5, -2), -2); + assertEq(Math.min(-2, 5), -2); +} + +for (i = 2; i < 10; i++) { + assertEq(Math.max(i, 1), i); + assertEq(Math.max(i, -1), i); + assertEq(Math.max(1, i), i); + assertEq(Math.max(-1, i), i); + assertEq(Math.max(5, -2), 5); + assertEq(Math.max(-2, 5), 5); + assertEq(Math.max(5, 2), 5); + assertEq(Math.max(2, 5), 5); +} + +for (i = 2.1; i < 13; i += 3.17584) { + assertEq(Math.max(i, 1), i); + assertEq(Math.max(i, 1.5), i); + assertEq(Math.max(1, i), i); + assertEq(Math.max(1.5, i), i); + + assertEq(Math.max(NaN, NaN), NaN); + assertEq(Math.max(NaN, Infinity), NaN); + assertEq(Math.max(Infinity, NaN), NaN); + + assertEq(Math.max(NaN, i), NaN); + assertEq(Math.max(i, NaN), NaN); + + assertEq(Math.max(i, Infinity), Infinity); + assertEq(Math.max(Infinity, i), Infinity); + + assertEq(Math.max(i, -Infinity), i); + assertEq(Math.max(-Infinity, i), i); +} + +for (i = 2.1; i < 13; i += 3.17584) { + assertEq(Math.min(i, 1), 1); + assertEq(Math.min(i, 1.5), 1.5); + assertEq(Math.min(1, i), 1); + assertEq(Math.min(1.5, i), 1.5); + + assertEq(Math.min(NaN, NaN), NaN); + assertEq(Math.min(NaN, Infinity), NaN); + assertEq(Math.min(Infinity, NaN), NaN); + + assertEq(Math.min(NaN, i), NaN); + assertEq(Math.min(i, NaN), NaN); + + assertEq(Math.min(i, Infinity), i); + assertEq(Math.min(Infinity, i), i); + + assertEq(Math.min(i, -Infinity), -Infinity); + assertEq(Math.min(-Infinity, i), -Infinity); +} + +function isNegZero(n) { + return n === 0 && 1/n === -Infinity; +} + +for (i = 0; i < 5; i++) { + assertEq(isNegZero(Math.min(0, -0)), true); + assertEq(isNegZero(Math.min(-0, 0)), true); + assertEq(isNegZero(Math.min(-0, -0)), true); + assertEq(isNegZero(Math.max(0, -0)), false); + assertEq(isNegZero(Math.max(-0, 0)), false); + assertEq(isNegZero(Math.max(-0, -0)), true); +} diff --git a/js/src/jit-test/tests/basic/testMethodInc.js b/js/src/jit-test/tests/basic/testMethodInc.js new file mode 100644 index 0000000000..f283f84066 --- /dev/null +++ b/js/src/jit-test/tests/basic/testMethodInc.js @@ -0,0 +1,5 @@ +for (var i = 0; i < 9; i++) { + var x = {f: function() {}}; + x.f++; + assertEq(""+x.f, "NaN"); +} diff --git a/js/src/jit-test/tests/basic/testMethodInit.js b/js/src/jit-test/tests/basic/testMethodInit.js new file mode 100644 index 0000000000..64cfa4c37c --- /dev/null +++ b/js/src/jit-test/tests/basic/testMethodInit.js @@ -0,0 +1,10 @@ +function testMethodInit() { // bug 503198 + function o() { return 'o'; } + function k() { return 'k'; } + + var x; + for (var i = 0; i < 10; i++) + x = {o: o, k: k}; + return x.o() + x.k(); +} +assertEq(testMethodInit(), "ok"); diff --git a/js/src/jit-test/tests/basic/testMethodInitSafety.js b/js/src/jit-test/tests/basic/testMethodInitSafety.js new file mode 100644 index 0000000000..34177ab8f7 --- /dev/null +++ b/js/src/jit-test/tests/basic/testMethodInitSafety.js @@ -0,0 +1,14 @@ +function testMethodInitSafety() { + function f() { return 'fail'; } + function g() { return 'ok'; } + + var s; + var arr = [f, f, f, f, g]; + //assertEq(arr.length > 9, true); + for (var i = 0; i < arr.length; i++) { + var x = {m: arr[i]}; + s = x.m(); + } + return s; +} +assertEq(testMethodInitSafety(), "ok"); diff --git a/js/src/jit-test/tests/basic/testMethodSet.js b/js/src/jit-test/tests/basic/testMethodSet.js new file mode 100644 index 0000000000..d7fcd7fc08 --- /dev/null +++ b/js/src/jit-test/tests/basic/testMethodSet.js @@ -0,0 +1,13 @@ +function testMethodSet() { // bug 503198 + function o() { return 'o'; } + function k() { return 'k'; } + + var x; + for (var i = 0; i < 10; i++) { + x = {}; + x.o = o; + x.k = k; + } + return x.o() + x.k(); +} +assertEq(testMethodSet(), "ok"); diff --git a/js/src/jit-test/tests/basic/testMethodWriteBarrier.js b/js/src/jit-test/tests/basic/testMethodWriteBarrier.js new file mode 100644 index 0000000000..86f2b17226 --- /dev/null +++ b/js/src/jit-test/tests/basic/testMethodWriteBarrier.js @@ -0,0 +1,4 @@ +var x = {p: 0.1, m: function(){}}; +x.m(); // the interpreter brands x +for (var i = 0; i < 9; i++) + x.p = 0.1; diff --git a/js/src/jit-test/tests/basic/testMethodWriteBarrier2.js b/js/src/jit-test/tests/basic/testMethodWriteBarrier2.js new file mode 100644 index 0000000000..19b387198a --- /dev/null +++ b/js/src/jit-test/tests/basic/testMethodWriteBarrier2.js @@ -0,0 +1,17 @@ +function C() { + this.m = function () {}; // JSOP_SETMETHOD +} + +var a = [new C, new C, new C, new C, new C, new C, new C, new C, new C]; +var b = [new C, new C, new C, new C, new C, new C, a[8], new C, new C]; + +var thrown = 'none'; +try { + for (var i = 0; i < 9; i++) { + a[i].m(); + b[i].m = 0.7; // MethodWriteBarrier required here + } +} catch (exc) { + thrown = exc.name; +} +assertEq(thrown, 'TypeError'); diff --git a/js/src/jit-test/tests/basic/testMethodWriteBarrier3.js b/js/src/jit-test/tests/basic/testMethodWriteBarrier3.js new file mode 100644 index 0000000000..9ae20fed9c --- /dev/null +++ b/js/src/jit-test/tests/basic/testMethodWriteBarrier3.js @@ -0,0 +1,27 @@ +function g() {} + +function h() { + for (var i = 0; i < 9; i++) + x.f = i; +} + +function j() { + x.f(); +} + +var x = {f: 0.7, g: g}; +x.g(); // interpreter brands x +h(); +print(shapeOf(x)); +x.f = function (){}; // does not change x's shape +j(); +print(shapeOf(x)); +h(); // should change x's shape + +var thrown = 'none'; +try { + j(); // should throw since x.f === 8 +} catch (exc) { + thrown = exc.name; +} +assertEq(thrown, 'TypeError');
\ No newline at end of file diff --git a/js/src/jit-test/tests/basic/testMethodWriteBarrier4.js b/js/src/jit-test/tests/basic/testMethodWriteBarrier4.js new file mode 100644 index 0000000000..f120c9450d --- /dev/null +++ b/js/src/jit-test/tests/basic/testMethodWriteBarrier4.js @@ -0,0 +1,12 @@ +var z = 0; +function f() { + this.b = function() {}; + this.b = undefined; + if (z++ > 8) + this.b(); +} + +try { + for (var i = 0; i < 10; i++) + new f(); +} catch (exc) {} diff --git a/js/src/jit-test/tests/basic/testMissingMethod.js b/js/src/jit-test/tests/basic/testMissingMethod.js new file mode 100644 index 0000000000..50ebb4bea3 --- /dev/null +++ b/js/src/jit-test/tests/basic/testMissingMethod.js @@ -0,0 +1,9 @@ +var o = {y: function () {}}; +var a = [o, o, o, o, o, o, o, o, o]; +a[7] = {}; +try { + for (var i = 0; i < 9; i++) + a[i].y(); +} catch (exc) { + assertEq(exc.name, "TypeError"); // should happen when i == 7 +} diff --git a/js/src/jit-test/tests/basic/testMissingMethod2.js b/js/src/jit-test/tests/basic/testMissingMethod2.js new file mode 100644 index 0000000000..fabfa08a60 --- /dev/null +++ b/js/src/jit-test/tests/basic/testMissingMethod2.js @@ -0,0 +1,10 @@ +var o = {y: function() {}}; +var a = [o, o, o, o, o, o, o, o, o]; +Number.prototype.y = 0; +a[7] = 0; +try { + for (var i = 0; i < 9; i++) + a[i].y(); +} catch (exc) { + assertEq(exc.name, "TypeError"); // should happen when i == 7 +} diff --git a/js/src/jit-test/tests/basic/testMissingProperties.js b/js/src/jit-test/tests/basic/testMissingProperties.js new file mode 100644 index 0000000000..71512c6f5c --- /dev/null +++ b/js/src/jit-test/tests/basic/testMissingProperties.js @@ -0,0 +1,49 @@ +function isnan(n) { return n !== n } + +function f(x) { + var sum = 0; + for (var i = 0; i < 100; ++i) + sum += x.x; + return sum; +} +var o = {}; +assertEq(isnan(f(o)), true); +o.x = 1; +assertEq(f(o), 100); +var o = {a:1, b:2}; +assertEq(isnan(f(o)), true); +o.x = 2; +assertEq(f(o), 200); + +function g(x) { + var sum = 0; + for (var i = 0; i < 100; ++i) + sum += x.x; + return sum; +} +var o = {c:1, x:1}; +assertEq(g(o), 100); +var o = {}; +assertEq(isnan(g(o)), true); + +function h(x) { + var sum = 0; + for (var i = 0; i < 100; ++i) + sum += x.x; + return sum; +} + +var proto1 = {}; +var proto2 = Object.create(proto1); +var o = Object.create(proto2); +assertEq(isnan(f(o)), true); +assertEq(isnan(g(o)), true); +assertEq(isnan(h(o)), true); +proto2.x = 2; +assertEq(f(o), 200); +assertEq(g(o), 200); +assertEq(h(o), 200); +var o = {} +assertEq(isnan(f(o)), true); +assertEq(isnan(g(o)), true); +assertEq(isnan(h(o)), true); diff --git a/js/src/jit-test/tests/basic/testModuloWithNegative1.js b/js/src/jit-test/tests/basic/testModuloWithNegative1.js new file mode 100644 index 0000000000..ed767a7a2a --- /dev/null +++ b/js/src/jit-test/tests/basic/testModuloWithNegative1.js @@ -0,0 +1,11 @@ +function testModuloWithNegative1() { + var v = 0; + for (var i = 0; i < 2; ++i) { + c = v; + v -= 1; + for (var j = 0; j < 2; ++j) + c %= -1; + } + return 1/c; +} +assertEq(testModuloWithNegative1(), -Infinity); diff --git a/js/src/jit-test/tests/basic/testModuloWithNegative2.js b/js/src/jit-test/tests/basic/testModuloWithNegative2.js new file mode 100644 index 0000000000..dfd1e3deb8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testModuloWithNegative2.js @@ -0,0 +1,7 @@ +function f(v, e) { + for (var i = 0; i < 9; i++) + v %= e; + return v; +} +f(0, 1); +assertEq(f(-2, 2), -0); diff --git a/js/src/jit-test/tests/basic/testMoreArgcThanNargs.js b/js/src/jit-test/tests/basic/testMoreArgcThanNargs.js new file mode 100644 index 0000000000..9fcda77e37 --- /dev/null +++ b/js/src/jit-test/tests/basic/testMoreArgcThanNargs.js @@ -0,0 +1,14 @@ +function doTestMoreArgcThanNargs() +{ + var x = 0; + for (var i = 0; i < 10; i++) + { + x = x + arguments[3]; + } + return x; +} +function testMoreArgcThanNargs() +{ + return doTestMoreArgcThanNargs(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +} +assertEq(testMoreArgcThanNargs(), 4*10); diff --git a/js/src/jit-test/tests/basic/testMoreClosures.js b/js/src/jit-test/tests/basic/testMoreClosures.js new file mode 100644 index 0000000000..5592bcba37 --- /dev/null +++ b/js/src/jit-test/tests/basic/testMoreClosures.js @@ -0,0 +1,14 @@ +function testMoreClosures() { + var f = {}, max = 3; + + var hello = function(n) { + function howdy() { return n * n } + f.test = howdy; + }; + + for (var i = 0; i <= max; i++) + hello(i); + + return f.test(); +} +assertEq(testMoreClosures(), 9); diff --git a/js/src/jit-test/tests/basic/testMulOverflow.js b/js/src/jit-test/tests/basic/testMulOverflow.js new file mode 100644 index 0000000000..5d7a1339fc --- /dev/null +++ b/js/src/jit-test/tests/basic/testMulOverflow.js @@ -0,0 +1,6 @@ +function testMulOverflow() { + var a = []; + for (let j=0;j<5;++j) a.push(0 | ((0x60000009) * 0x60000009)); + return a.join(","); +} +assertEq(testMulOverflow(), "-1073741824,-1073741824,-1073741824,-1073741824,-1073741824"); diff --git a/js/src/jit-test/tests/basic/testMultipleArgumentsObjects.js b/js/src/jit-test/tests/basic/testMultipleArgumentsObjects.js new file mode 100644 index 0000000000..dd8285d643 --- /dev/null +++ b/js/src/jit-test/tests/basic/testMultipleArgumentsObjects.js @@ -0,0 +1,12 @@ +function testMultipleArgumentsObjects() { + var testargs = arguments; + var f = function (name, which) { + var args = [testargs, arguments]; + return args[which][0]; + }; + var arr = [0, 0, 0, 0, 1]; + for (var i = 0; i < arr.length; i++) + arr[i] = f("f", arr[i]); + return arr + ''; +} +assertEq(testMultipleArgumentsObjects(), ",,,,f"); diff --git a/js/src/jit-test/tests/basic/testMultipleFunctionRedeclarations.js b/js/src/jit-test/tests/basic/testMultipleFunctionRedeclarations.js new file mode 100644 index 0000000000..701782378f --- /dev/null +++ b/js/src/jit-test/tests/basic/testMultipleFunctionRedeclarations.js @@ -0,0 +1,44 @@ +function f1() { + assertEq(g(), 3); + function g() { return 1 } + assertEq(g(), 3); + function g() { return 2 } + assertEq(g(), 3); + function g() { return 3 } + assertEq(g(), 3); +} +f1(); + +function f2() { + assertEq(g(), 2); + var g = 3; + assertEq(g, 3); + function g() { return 1 } + function g() { return 2 } +} +f2(); + +function f3() { + assertEq(g(), 2); + var g = 3; + assertEq(g, 3); + function g() { return 1 } + var g = 4; + assertEq(g, 4); + function g() { return 2 } +} +f3(); + +function f4() { + assertEq(g(), 4); + function g() { return 1 } + assertEq(g(), 4); + function g() { return 2 } + var g = 9; + assertEq(g, 9); + function g() { return 3 } + assertEq(g, 9); + function g() { return 4 } + assertEq(g, 9); +} +f4(); diff --git a/js/src/jit-test/tests/basic/testMultiplePendingGlobalWrites.js b/js/src/jit-test/tests/basic/testMultiplePendingGlobalWrites.js new file mode 100644 index 0000000000..06d54dfbbb --- /dev/null +++ b/js/src/jit-test/tests/basic/testMultiplePendingGlobalWrites.js @@ -0,0 +1,11 @@ +var a, b; +function g(x) { + var y = x++; + return [x, y]; +} +function f() { + for(var i=0; i<20; i++) { + [a,b] = g("10"); + } +} +f(); diff --git a/js/src/jit-test/tests/basic/testNEWINIT.js b/js/src/jit-test/tests/basic/testNEWINIT.js new file mode 100644 index 0000000000..bca645b2f1 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNEWINIT.js @@ -0,0 +1,8 @@ +function testNEWINIT() +{ + var a; + for (var i = 0; i < 10; ++i) + a = [{}]; + return JSON.stringify(a); +} +assertEq(testNEWINIT(), "[{}]"); diff --git a/js/src/jit-test/tests/basic/testNEWINIT_DOUBLE.js b/js/src/jit-test/tests/basic/testNEWINIT_DOUBLE.js new file mode 100644 index 0000000000..238e5de72a --- /dev/null +++ b/js/src/jit-test/tests/basic/testNEWINIT_DOUBLE.js @@ -0,0 +1,6 @@ +function testNEWINIT_DOUBLE() +{ + for (var z = 0; z < 2; ++z) { ({ 0.1: null })} + return "ok"; +} +assertEq(testNEWINIT_DOUBLE(), "ok"); diff --git a/js/src/jit-test/tests/basic/testNativeArgsRooting.js b/js/src/jit-test/tests/basic/testNativeArgsRooting.js new file mode 100644 index 0000000000..1ce8259f2d --- /dev/null +++ b/js/src/jit-test/tests/basic/testNativeArgsRooting.js @@ -0,0 +1,14 @@ +if ('gczeal' in this) +(function () { + (eval("\ + (function () {\ + for (var y = 0; y < 16; ++y) {\ + if (y % 3 == 2) {\ + gczeal(1);\ + } else {\ + print(0 / 0);\ + }\ + }\ + });\ + "))() +})(); diff --git a/js/src/jit-test/tests/basic/testNativeLog.js b/js/src/jit-test/tests/basic/testNativeLog.js new file mode 100644 index 0000000000..5a81c79e77 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNativeLog.js @@ -0,0 +1,8 @@ +function testNativeLog() { + var a = new Array(5); + for (var i = 0; i < 5; i++) { + a[i] = Math.log(Math.pow(Math.E, 10)); + } + return a.join(","); +} +assertEq(testNativeLog(), "10,10,10,10,10"); diff --git a/js/src/jit-test/tests/basic/testNativeMax.js b/js/src/jit-test/tests/basic/testNativeMax.js new file mode 100644 index 0000000000..ef36dbe5c6 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNativeMax.js @@ -0,0 +1,20 @@ +function testNativeMax() { + var out = [], k; + for (var i = 0; i < 5; ++i) { + k = Math.max(k, i); + } + out.push(k); + + k = 0; + for (var i = 0; i < 5; ++i) { + k = Math.max(k, i); + } + out.push(k); + + for (var i = 0; i < 5; ++i) { + k = Math.max(0, -0); + } + out.push((1 / k) < 0); + return out.join(","); +} +assertEq(testNativeMax(), "NaN,4,false"); diff --git a/js/src/jit-test/tests/basic/testNativeSetter.js b/js/src/jit-test/tests/basic/testNativeSetter.js new file mode 100644 index 0000000000..79ddf56f93 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNativeSetter.js @@ -0,0 +1,8 @@ +function testNativeSetter() { + var re = /foo/; + var N = 19; + for (var i = 0; i < N; i++) + re.lastIndex = i; + assertEq(re.lastIndex, N - 1); +} +testNativeSetter(); diff --git a/js/src/jit-test/tests/basic/testNegZero1.js b/js/src/jit-test/tests/basic/testNegZero1.js new file mode 100644 index 0000000000..fe9aabdf2c --- /dev/null +++ b/js/src/jit-test/tests/basic/testNegZero1.js @@ -0,0 +1,9 @@ +function testNegZero1Helper(z) { + for (let j = 0; j < 5; ++j) { z = -z; } + return Math.atan2(0, -0) == Math.atan2(0, z); +} + +var testNegZero1 = function() { return testNegZero1Helper(0); } +testNegZero1.name = 'testNegZero1'; +testNegZero1Helper(1); +assertEq(testNegZero1(), true); diff --git a/js/src/jit-test/tests/basic/testNegativeArrayLength.js b/js/src/jit-test/tests/basic/testNegativeArrayLength.js new file mode 100644 index 0000000000..1719ceeb97 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNegativeArrayLength.js @@ -0,0 +1,10 @@ +function f() { + try { + for ( var i = 7; i > -2; i-- ) + new Array(i).join('*'); + } catch (e) { + return e instanceof RangeError; + } + return false; +} +assertEq(f(), true); diff --git a/js/src/jit-test/tests/basic/testNegativeGETELEMIndex.js b/js/src/jit-test/tests/basic/testNegativeGETELEMIndex.js new file mode 100644 index 0000000000..da7b748121 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNegativeGETELEMIndex.js @@ -0,0 +1,6 @@ +function testNegativeGETELEMIndex() +{ + for (let i=0;i<3;++i) /x/[-4]; + return "ok"; +} +assertEq(testNegativeGETELEMIndex(), "ok"); diff --git a/js/src/jit-test/tests/basic/testNestedClosures.js b/js/src/jit-test/tests/basic/testNestedClosures.js new file mode 100644 index 0000000000..445ea6e39f --- /dev/null +++ b/js/src/jit-test/tests/basic/testNestedClosures.js @@ -0,0 +1,23 @@ +function testNestedClosures() { + function f(a, b) { + function g(x, y) { + function h(m, n) { + function k(u, v) { + var s = ''; + for (var i = 0; i < 5; ++i) + s = a + ',' + b + ',' + x + ',' + y + ',' + m + ',' + n + ',' + u + ',' + v; + return s; + } + return k(m+1, n+1); + } + return h(x+1, y+1); + } + return g(a+1, b+1); + } + + var s1; + for (var i = 0; i < 5; ++i) + s1 = f(i, i+i); + return s1; +} +assertEq(testNestedClosures(), '4,8,5,9,6,10,7,11'); diff --git a/js/src/jit-test/tests/basic/testNestedDeepBail.js b/js/src/jit-test/tests/basic/testNestedDeepBail.js new file mode 100644 index 0000000000..8e59b04cda --- /dev/null +++ b/js/src/jit-test/tests/basic/testNestedDeepBail.js @@ -0,0 +1,20 @@ +var _quit; +function testNestedDeepBail() +{ + _quit = false; + function loop() { + for (var i = 0; i < 4; i++) + ; + } + loop(); + + function f() { + loop(); + _quit = true; + } + + var stk = [[1], [], [], [], []]; + while (!_quit) + stk.pop().forEach(f); +} +testNestedDeepBail(); diff --git a/js/src/jit-test/tests/basic/testNestedEscapingLambdas.js b/js/src/jit-test/tests/basic/testNestedEscapingLambdas.js new file mode 100644 index 0000000000..8b896f1936 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNestedEscapingLambdas.js @@ -0,0 +1,31 @@ +function testNestedEscapingLambdas() +{ + try { + return (function() { + var a = [], r = []; + function setTimeout(f, t) { + a.push(f); + } + + function runTimeouts() { + for (var i = 0; i < a.length; i++) + a[i](); + } + + var $foo = "#nothiddendiv"; + setTimeout(function(){ + r.push($foo); + setTimeout(function(){ + r.push($foo); + }, 100); + }, 100); + + runTimeouts(); + + return r.join(""); + })(); + } catch (e) { + return e; + } +} +assertEq(testNestedEscapingLambdas(), "#nothiddendiv#nothiddendiv"); diff --git a/js/src/jit-test/tests/basic/testNestedExitStackOuter.js b/js/src/jit-test/tests/basic/testNestedExitStackOuter.js new file mode 100644 index 0000000000..5da8a1f968 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNestedExitStackOuter.js @@ -0,0 +1,29 @@ +// Test stack reconstruction after a nested exit +function testNestedExitStackInner(j, counter) { + ++counter; + var b = 0; + for (var i = 1; i <= 9; i++) { + ++b; + var a; + // Make sure that once everything has been traced we suddenly switch to + // a different control flow the first time we run the outermost tree, + // triggering a side exit. + if (j < 9) + a = 1; + else + a = 0; + ++b; + b += a; + } + return counter + b; +} +function testNestedExitStackOuter() { + var counter = 0; + for (var j = 1; j <= 9; ++j) { + for (var k = 1; k <= 9; ++k) { + counter = testNestedExitStackInner(j, counter); + } + } + return counter; +} +//assertEq(testNestedExitStackOuter(), 81); diff --git a/js/src/jit-test/tests/basic/testNestedForIn.js b/js/src/jit-test/tests/basic/testNestedForIn.js new file mode 100644 index 0000000000..1541775f87 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNestedForIn.js @@ -0,0 +1,9 @@ +function testNestedForIn() { + var a = {x: 1, y: 2, z: 3}; + var s = ''; + for (var p1 in a) + for (var p2 in a) + s += p1 + p2 + ' '; + return s; +} +assertEq(testNestedForIn(), 'xx xy xz yx yy yz zx zy zz '); diff --git a/js/src/jit-test/tests/basic/testNeutering.js b/js/src/jit-test/tests/basic/testNeutering.js new file mode 100644 index 0000000000..fc49e3f99e --- /dev/null +++ b/js/src/jit-test/tests/basic/testNeutering.js @@ -0,0 +1,23 @@ +var ab = new ArrayBuffer(4); +var i32 = new Int32Array(ab); +i32[0] = 42; +detachArrayBuffer(ab); +assertEq(i32.length, 0); +assertEq(ab.byteLength, 0); +assertEq(i32[0], undefined); + +var ab = new ArrayBuffer(12); +var i32 = new Int32Array(ab); +i32[0] = 42; +detachArrayBuffer(ab); +assertEq(i32.length, 0); +assertEq(ab.byteLength, 0); +assertEq(i32[0], undefined); + +var ab = new ArrayBuffer(4096); +var i32 = new Int32Array(ab); +i32[0] = 42; +detachArrayBuffer(ab); +assertEq(i32.length, 0); +assertEq(ab.byteLength, 0); +assertEq(i32[0], undefined); diff --git a/js/src/jit-test/tests/basic/testNewArrayCount.js b/js/src/jit-test/tests/basic/testNewArrayCount.js new file mode 100644 index 0000000000..cb7e6d9843 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNewArrayCount.js @@ -0,0 +1,12 @@ +function testNewArrayCount() +{ + function count(a) { var n = 0; for (var p in a) n++; return n; } + var a = []; + for (var i = 0; i < 5; i++) + a = [0]; + assertEq(count(a), 1); + for (var i = 0; i < 5; i++) + a = [0, , 2]; + assertEq(count(a), 2); +} +testNewArrayCount(); diff --git a/js/src/jit-test/tests/basic/testNewArrayCount2.js b/js/src/jit-test/tests/basic/testNewArrayCount2.js new file mode 100644 index 0000000000..6318e4c25f --- /dev/null +++ b/js/src/jit-test/tests/basic/testNewArrayCount2.js @@ -0,0 +1,8 @@ +function testNewArrayCount2() { + function count(a) { var n = 0; for (var p in a) n++; return n; } + var x = 0; + for (var i = 0; i < 10; ++i) + x = count(new Array(1,2,3)); + return x; +} +assertEq(testNewArrayCount2(), 3); diff --git a/js/src/jit-test/tests/basic/testNewObject.js b/js/src/jit-test/tests/basic/testNewObject.js new file mode 100644 index 0000000000..028523c011 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNewObject.js @@ -0,0 +1,8 @@ +function testNewObject() +{ + var a = {}; + for (var i = 0; i < 10; ++i) + a = new Object(); + return a; +} +assertEq(testNewObject().__proto__, {}.__proto__); diff --git a/js/src/jit-test/tests/basic/testNewString.js b/js/src/jit-test/tests/basic/testNewString.js new file mode 100644 index 0000000000..e0f378bbc0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNewString.js @@ -0,0 +1,21 @@ +function testNewString() +{ + var o = { toString: function() { return "string"; } }; + var r = []; + for (var i = 0; i < 5; i++) + r.push(typeof new String(o)); + for (var i = 0; i < 5; i++) + r.push(typeof new String(3)); + for (var i = 0; i < 5; i++) + r.push(typeof new String(2.5)); + for (var i = 0; i < 5; i++) + r.push(typeof new String("string")); + for (var i = 0; i < 5; i++) + r.push(typeof new String(null)); + for (var i = 0; i < 5; i++) + r.push(typeof new String(true)); + for (var i = 0; i < 5; i++) + r.push(typeof new String(undefined)); + return r.length === 35 && r.every(function(v) { return v === "object"; }); +} +assertEq(testNewString(), true); diff --git a/js/src/jit-test/tests/basic/testNewWithClone.js b/js/src/jit-test/tests/basic/testNewWithClone.js new file mode 100644 index 0000000000..ef976df585 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNewWithClone.js @@ -0,0 +1,7 @@ +with({}) { + function f() { + this.foo = "bar"; + } + o = new f(); + assertEq(o.foo, "bar"); +} diff --git a/js/src/jit-test/tests/basic/testNewWithNonNativeProto.js b/js/src/jit-test/tests/basic/testNewWithNonNativeProto.js new file mode 100644 index 0000000000..dc950efc7c --- /dev/null +++ b/js/src/jit-test/tests/basic/testNewWithNonNativeProto.js @@ -0,0 +1,9 @@ +function testNewWithNonNativeProto() +{ + function f() { } + var a = f.prototype = []; + for (var i = 0; i < 5; i++) + var o = new f(); + return Object.getPrototypeOf(o) === a && o.splice === Array.prototype.splice; +} +assertEq(testNewWithNonNativeProto(), true); diff --git a/js/src/jit-test/tests/basic/testNot.js b/js/src/jit-test/tests/basic/testNot.js new file mode 100644 index 0000000000..746ca5739c --- /dev/null +++ b/js/src/jit-test/tests/basic/testNot.js @@ -0,0 +1,8 @@ +function testNot() { + var a = new Object(), b = null, c = "foo", d = "", e = 5, f = 0, g = 5.5, h = -0, i = true, j = false, k = undefined; + var r; + for (var i = 0; i < 10; ++i) + r = [!a, !b, !c, !d, !e, !f, !g, !h, !i, !j, !k]; + return r.join(","); +} +assertEq(testNot(), "false,true,false,true,false,true,false,true,false,true,true"); diff --git a/js/src/jit-test/tests/basic/testNullCallee.js b/js/src/jit-test/tests/basic/testNullCallee.js new file mode 100644 index 0000000000..7eab7d55c9 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNullCallee.js @@ -0,0 +1,16 @@ +function testNullCallee() { + try { + function f() { + var x = new Array(5); + for (var i = 0; i < 5; i++) + x[i] = a[i].toString(); + return x.join(','); + } + f([[1],[2],[3],[4],[5]]); + f([null, null, null, null, null]); + } catch (e) { + return true; + } + return false; +} +assertEq(testNullCallee(), true); diff --git a/js/src/jit-test/tests/basic/testNullIncrement.js b/js/src/jit-test/tests/basic/testNullIncrement.js new file mode 100644 index 0000000000..b7ffd03b4c --- /dev/null +++ b/js/src/jit-test/tests/basic/testNullIncrement.js @@ -0,0 +1,14 @@ +function f() { + var n; + var k; + for (var i = 0; i < 18; ++i) { + n = null; + k = n++; + if (k) { } + } + return [k, n]; +} + +var [a, b] = f(); +assertEq(a, 0); +assertEq(b, 1); diff --git a/js/src/jit-test/tests/basic/testNullRelCmp.js b/js/src/jit-test/tests/basic/testNullRelCmp.js new file mode 100644 index 0000000000..4531ea2c82 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNullRelCmp.js @@ -0,0 +1,6 @@ +function testNullRelCmp() { + var out = []; + for(j=0;j<3;++j) { out.push(3 > null); out.push(3 < null); out.push(0 == null); out.push(3 == null); } + return out.join(","); +} +assertEq(testNullRelCmp(), "true,false,false,false,true,false,false,false,true,false,false,false"); diff --git a/js/src/jit-test/tests/basic/testNullToString.js b/js/src/jit-test/tests/basic/testNullToString.js new file mode 100644 index 0000000000..c80feb1da1 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNullToString.js @@ -0,0 +1,13 @@ +function testNullToString() +{ + var a = []; + for (var i = 0; i < 10; i++) + a.push(String(null)); + for (i = 0; i < 10; i++) { + var t = typeof a[i]; + if (t != "string") + a.push(t); + } + return a.join(","); +} +assertEq(testNullToString(), "null,null,null,null,null,null,null,null,null,null"); diff --git a/js/src/jit-test/tests/basic/testNumToString.js b/js/src/jit-test/tests/basic/testNumToString.js new file mode 100644 index 0000000000..96f3cc725f --- /dev/null +++ b/js/src/jit-test/tests/basic/testNumToString.js @@ -0,0 +1,18 @@ +function testNumToString() { + var r = []; + var d = 123456789; + for (var i = 0; i < 10; ++i) { + r = [ + d.toString(), + (-d).toString(), + d.toString(10), + (-d).toString(10), + d.toString(16), + (-d).toString(16), + d.toString(36), + (-d).toString(36) + ]; + } + return r.join(","); +} +assertEq(testNumToString(), "123456789,-123456789,123456789,-123456789,75bcd15,-75bcd15,21i3v9,-21i3v9"); diff --git a/js/src/jit-test/tests/basic/testNumberToString.js b/js/src/jit-test/tests/basic/testNumberToString.js new file mode 100644 index 0000000000..5b79616648 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNumberToString.js @@ -0,0 +1,6 @@ +function testNumberToString() { + var x = new Number(0); + for (var i = 0; i < 4; i++) + x.toString(); +} +testNumberToString(); diff --git a/js/src/jit-test/tests/basic/testOOMInAutoEnterCompartment.js b/js/src/jit-test/tests/basic/testOOMInAutoEnterCompartment.js new file mode 100644 index 0000000000..ea78fd67ed --- /dev/null +++ b/js/src/jit-test/tests/basic/testOOMInAutoEnterCompartment.js @@ -0,0 +1,17 @@ +// |jit-test| slow; skip-if: (getBuildConfiguration("asan") && getBuildConfiguration("debug")) +// This test is too slow to run at all with ASan in a debug configuration + +function fatty() { + try { + fatty(); + } catch (e) { + foo(); + } +} + + +foo = evalcx("(function foo() { foo.bar() })"); +foo.bar = evalcx("(function bar() {})"); + +fatty(); + diff --git a/js/src/jit-test/tests/basic/testObjectConstructorReturningObject.js b/js/src/jit-test/tests/basic/testObjectConstructorReturningObject.js new file mode 100644 index 0000000000..c18863db64 --- /dev/null +++ b/js/src/jit-test/tests/basic/testObjectConstructorReturningObject.js @@ -0,0 +1,12 @@ +for (var i = 0; i < 12; ++i) { + var o; + + o = new Object(Object); + assertEq(o, Object); + + (function () { + x = constructor + })(); + o = new(x)(x); + assertEq(o, Object); +} diff --git a/js/src/jit-test/tests/basic/testObjectLength.js b/js/src/jit-test/tests/basic/testObjectLength.js new file mode 100644 index 0000000000..3813a6e51b --- /dev/null +++ b/js/src/jit-test/tests/basic/testObjectLength.js @@ -0,0 +1,10 @@ +function testObjectLength() +{ + var counter = 0; + var a = {}; + a.length = 10000; + for (var i = 0; i < a.length; i++) + counter++; + return counter; +} +assertEq(testObjectLength(), 10000); diff --git a/js/src/jit-test/tests/basic/testObjectOrderedCmp.js b/js/src/jit-test/tests/basic/testObjectOrderedCmp.js new file mode 100644 index 0000000000..7065ad8fc9 --- /dev/null +++ b/js/src/jit-test/tests/basic/testObjectOrderedCmp.js @@ -0,0 +1,7 @@ +function testObjectOrderedCmp() +{ + var a = new Array(5); + for(var i=0;i<5;++i) a[i] = ({} < {}); + return a.join(","); +} +assertEq(testObjectOrderedCmp(), "false,false,false,false,false"); diff --git a/js/src/jit-test/tests/basic/testObjectOrderedCmp2.js b/js/src/jit-test/tests/basic/testObjectOrderedCmp2.js new file mode 100644 index 0000000000..6790799c37 --- /dev/null +++ b/js/src/jit-test/tests/basic/testObjectOrderedCmp2.js @@ -0,0 +1,7 @@ +function testObjectOrderedCmp2() +{ + var a = new Array(5); + for(var i=0;i<5;++i) a[i] = ("" <= null); + return a.join(","); +} +assertEq(testObjectOrderedCmp2(), "true,true,true,true,true"); diff --git a/js/src/jit-test/tests/basic/testObjectToNumber.js b/js/src/jit-test/tests/basic/testObjectToNumber.js new file mode 100644 index 0000000000..d6353a6a68 --- /dev/null +++ b/js/src/jit-test/tests/basic/testObjectToNumber.js @@ -0,0 +1,8 @@ +function testObjectToNumber() { + var o = {valueOf: () => -3}; + var x = 0; + for (var i = 0; i < 10; i++) + x -= o; + return x; +} +assertEq(testObjectToNumber(), 30); diff --git a/js/src/jit-test/tests/basic/testObjectToString.js b/js/src/jit-test/tests/basic/testObjectToString.js new file mode 100644 index 0000000000..ba47d00f0b --- /dev/null +++ b/js/src/jit-test/tests/basic/testObjectToString.js @@ -0,0 +1,8 @@ +function testObjectToString() { + var o = {toString: () => "foo"}; + var s = ""; + for (var i = 0; i < 10; i++) + s += o; + return s; +} +assertEq(testObjectToString(), "foofoofoofoofoofoofoofoofoofoo"); diff --git a/js/src/jit-test/tests/basic/testObjectVsPrototype.js b/js/src/jit-test/tests/basic/testObjectVsPrototype.js new file mode 100644 index 0000000000..194b05fa78 --- /dev/null +++ b/js/src/jit-test/tests/basic/testObjectVsPrototype.js @@ -0,0 +1,12 @@ +function testObjectVsPrototype() { + function D() {} + var b = D.prototype = {x: 1}; + var d = new D; + var arr = [b, b, b, d]; + for (var i = 0; i < 4; i++) + arr[i].x = i; + + d.y = 12; + assertEq(d.x, 3); +} +testObjectVsPrototype(); diff --git a/js/src/jit-test/tests/basic/testOverOOMInFixupArity.js b/js/src/jit-test/tests/basic/testOverOOMInFixupArity.js new file mode 100644 index 0000000000..1b81d84ec0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testOverOOMInFixupArity.js @@ -0,0 +1,15 @@ +function foo() { + bar(1,2,3,4,5,6,7,8,9); +} + +function bar() { + foo(1,2,3,4,5,6,7,8,9); +} + +var caught = false; +try { + foo(); +} catch (e) { + caught = true; +} +assertEq(caught, true); diff --git a/js/src/jit-test/tests/basic/testOverRecursed1.js b/js/src/jit-test/tests/basic/testOverRecursed1.js new file mode 100644 index 0000000000..d44da136c2 --- /dev/null +++ b/js/src/jit-test/tests/basic/testOverRecursed1.js @@ -0,0 +1,6 @@ +// |jit-test| error:InternalError + +var a = []; +var f = a.forEach.bind(a); +a.push(f); +f(f); diff --git a/js/src/jit-test/tests/basic/testOverRecursed2.js b/js/src/jit-test/tests/basic/testOverRecursed2.js new file mode 100644 index 0000000000..bcd59d8b2e --- /dev/null +++ b/js/src/jit-test/tests/basic/testOverRecursed2.js @@ -0,0 +1,7 @@ +// |jit-test| error:InternalError + +var a = []; +var sort = a.sort.bind(a); +a.push(sort); +a.push(sort); +sort(sort); diff --git a/js/src/jit-test/tests/basic/testOverRecursed3.js b/js/src/jit-test/tests/basic/testOverRecursed3.js new file mode 100644 index 0000000000..100e7e762d --- /dev/null +++ b/js/src/jit-test/tests/basic/testOverRecursed3.js @@ -0,0 +1,6 @@ +// |jit-test| error:InternalError + +var x = []; +x.push(x, x); // more than one so the sort can't be optimized away +x.toString = x.sort; +x.toString(); diff --git a/js/src/jit-test/tests/basic/testOverRecursed4.js b/js/src/jit-test/tests/basic/testOverRecursed4.js new file mode 100644 index 0000000000..e29d4bf7d8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testOverRecursed4.js @@ -0,0 +1,9 @@ +function tryItOut(code) { + f = eval("(function(){" + code + "})") + try { + f() + } catch (e) {} +} +tryItOut("x=7"); +tryItOut("\"use strict\";for(d in[x=arguments]){}"); +tryItOut("for(v in((Object.seal)(x)));x.length=Function") diff --git a/js/src/jit-test/tests/basic/testOverRecursed6.js b/js/src/jit-test/tests/basic/testOverRecursed6.js new file mode 100644 index 0000000000..7c30bc7b61 --- /dev/null +++ b/js/src/jit-test/tests/basic/testOverRecursed6.js @@ -0,0 +1,3 @@ +// |jit-test| error:InternalError + +"" + {toString: Date.prototype.toJSON}; diff --git a/js/src/jit-test/tests/basic/testOverwrittenArgumentsWithUndefined.js b/js/src/jit-test/tests/basic/testOverwrittenArgumentsWithUndefined.js new file mode 100644 index 0000000000..5f899243b7 --- /dev/null +++ b/js/src/jit-test/tests/basic/testOverwrittenArgumentsWithUndefined.js @@ -0,0 +1,24 @@ +function f() { + var a = arguments; + eval("assertEq(arguments[0], 42)"); + eval("assertEq(arguments, a)"); + arguments = undefined; + eval("assertEq(arguments, undefined)"); + arguments = a; + eval("assertEq(arguments[0], 42)"); + eval("assertEq(arguments, a)"); +} +f(42); + +function f(z) { + var a = arguments; + eval("assertEq(arguments[0], 42)"); + eval("assertEq(arguments, a)"); + arguments = undefined; + eval("assertEq(arguments, undefined)"); + z = 17; + eval("assertEq(a[0], 17)"); + a[0] = 'ponies'; + eval("assertEq(z, 'ponies')"); +} +f(42); diff --git a/js/src/jit-test/tests/basic/testOwnPropertyWithInOperator.js b/js/src/jit-test/tests/basic/testOwnPropertyWithInOperator.js new file mode 100644 index 0000000000..2224dba2d6 --- /dev/null +++ b/js/src/jit-test/tests/basic/testOwnPropertyWithInOperator.js @@ -0,0 +1,9 @@ +function testOwnPropertyWithInOperator() +{ + var o = { 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6 }; + var a = []; + for (var i = 0; i < 7; i++) + a.push(i in o); + return a.join(","); +} +assertEq(testOwnPropertyWithInOperator(), "true,true,true,true,true,true,true"); diff --git a/js/src/jit-test/tests/basic/testParseInt.js b/js/src/jit-test/tests/basic/testParseInt.js new file mode 100644 index 0000000000..d3706b2f08 --- /dev/null +++ b/js/src/jit-test/tests/basic/testParseInt.js @@ -0,0 +1,48 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function testInt(n, result) { + var x = 0; + for (var i = 0; i < 15; i++) { + assertEq(parseInt(n, 10), result); + assertEq(parseInt(n, 0), result); + assertEq(parseInt(n), result); + assertEq(parseInt(n, x), result); + + if (x % 2 == 0) + x = 10; + else + x = 0; + } +} + +function testDouble(n, result) { + var x = 0; + for (var i = 0; i < 15; i++) { + assertEq(parseInt(n, 10), result); + assertEq(parseInt(n, 0), result); + assertEq(parseInt(n), result); + assertEq(parseInt(n, x), result); + + if (x % 2 == 0) + x = 10; + else + x = 0; + } +} + +testInt(2147483647, 2147483647); +testInt(-2147483648, -2147483648); +testInt(17, 17); +testInt(-1, -1); +testInt(0, 0); + +testDouble(1e21, 1); +testDouble(-5.7, -5); +testDouble(1.7, 1); +testDouble(1.0e-6, 0); +testDouble(1.0e-7, 1); +testDouble(NaN, NaN); +testDouble(1e20, 1e20); diff --git a/js/src/jit-test/tests/basic/testPartialFlatClosure.js b/js/src/jit-test/tests/basic/testPartialFlatClosure.js new file mode 100644 index 0000000000..9998ce306b --- /dev/null +++ b/js/src/jit-test/tests/basic/testPartialFlatClosure.js @@ -0,0 +1,10 @@ +assertEq((('-r', function (s) { + function C(i) { + this.m = function () { return i * t; } + } + var t = s; + var a = []; + for (var i = 0; i < 5; i++) + a[a.length] = new C(i); + return a; +})(42))[4].m(), 168); diff --git a/js/src/jit-test/tests/basic/testPaths.js b/js/src/jit-test/tests/basic/testPaths.js new file mode 100644 index 0000000000..a2b78323ea --- /dev/null +++ b/js/src/jit-test/tests/basic/testPaths.js @@ -0,0 +1,68 @@ +// load() and snarf() (aka read()) should resolve paths relative to the current +// working directory. This is a little hard to test because the shell doesn't +// really have any (portable) notion of the current directory (and it can't +// create files to enforce an expected layout.) loadRelativeToScript() and +// readRelativeToScript() do what their names say, which is much easier to +// test. + +loaded = {} +snarfed = {} +loadRel = {} +snarfRel = {} +for (let f of ['local.js', '../basic/local.js', 'Y.js']) { + try { + load(f); + loaded[f] = true; + } catch(e) { + loaded[f] = !/can't open/.test(e); + } + + try { + snarf(f); + snarfed[f] = true; + } catch(e) { + snarfed[f] = !/can't open/.test(e); + } + + try { + readRelativeToScript(f); + snarfRel[f] = true; + } catch(e) { + snarfRel[f] = !/can't open/.test(e); + } + + try { + loadRelativeToScript(f); + loadRel[f] = true; + } catch(e) { + loadRel[f] = !/can't open/.test(e); + } +} + +// local.js in the same dir as this script, so should be found by the +// script-relative calls but not the cwd-relative ones -- unless you happen to +// be in that directory or a sibling directory. +assertEq(loadRel['local.js'], true); +assertEq(loadRel['../basic/local.js'], true); +assertEq(snarfRel['local.js'], true); +assertEq(snarfRel['../basic/local.js'], true); +var cwd = os.getenv('PWD'); +if (cwd !== undefined && !(/test.*[\/\\][^\//]+[\/\\]/.test(cwd))) { + assertEq(loaded['local.js'], false); + assertEq(loaded['../basic/local.js'], false); + assertEq(snarfed['local.js'], false); + assertEq(snarfed['../basic/local.js'], false); +} + +// Y.js is in the root of the objdir, where |make check| is normally +// run from. +assertEq(loadRel['Y.js'], false); +assertEq(snarfRel['Y.js'], false); +if (!snarfed['Y.js']) { + print("WARNING: expected to be able to find Y.js in current directory\n"); + print("(not failing because it depends on where this test was run from)\n"); +} +if (!loaded['Y.js']) { + print("WARNING: expected to be able to find Y.js in current directory\n"); + print("(not failing because it depends on where this test was run from)\n"); +} diff --git a/js/src/jit-test/tests/basic/testPrimitiveConstructorPrototype.js b/js/src/jit-test/tests/basic/testPrimitiveConstructorPrototype.js new file mode 100644 index 0000000000..f0154082cd --- /dev/null +++ b/js/src/jit-test/tests/basic/testPrimitiveConstructorPrototype.js @@ -0,0 +1,7 @@ +function testPrimitiveConstructorPrototype() { + var f = function(){}; + f.prototype = false; + for (let j=0;j<5;++j) { new f; } + return "ok"; +} +assertEq(testPrimitiveConstructorPrototype(), "ok"); diff --git a/js/src/jit-test/tests/basic/testPropagatedFunArgs.js b/js/src/jit-test/tests/basic/testPropagatedFunArgs.js new file mode 100644 index 0000000000..19052d1fe9 --- /dev/null +++ b/js/src/jit-test/tests/basic/testPropagatedFunArgs.js @@ -0,0 +1,34 @@ +function testPropagatedFunArgs() +{ + var win = this; + var res = [], q = []; + function addEventListener(name, func, flag) { + q.push(func); + } + + var pageInfo, obs; + addEventListener("load", handleLoad, true); + + var observer = { + observe: function(win, topic, data) { + // obs.removeObserver(observer, "page-info-dialog-loaded"); + handlePageInfo(); + } + }; + + function handleLoad() { + pageInfo = { toString: function() { return "pageInfo"; } }; + obs = { addObserver: function (obs, topic, data) { obs.observe(win, topic, data); } }; + obs.addObserver(observer, "page-info-dialog-loaded", false); + } + + function handlePageInfo() { + res.push(pageInfo); + function $(aId) { res.push(pageInfo); }; + var feedTab = $("feedTab"); + } + + q[0](); + return res.join(','); +} +assertEq(testPropagatedFunArgs(), "pageInfo,pageInfo"); diff --git a/js/src/jit-test/tests/basic/testProxyDefinePropertyWithMissingSetter.js b/js/src/jit-test/tests/basic/testProxyDefinePropertyWithMissingSetter.js new file mode 100644 index 0000000000..19bb715836 --- /dev/null +++ b/js/src/jit-test/tests/basic/testProxyDefinePropertyWithMissingSetter.js @@ -0,0 +1,21 @@ +// throw, don't crash + +var actual = ""; + +try { + +var x = new Proxy({}, { + defineProperty: function(target, name, desc) { + Object.defineProperty(x, name, desc) + }, +}); + +Object.defineProperty(x, "", ({ + get: function() {} +})) + +} catch (e) { + actual = '' + e; +} + +assertEq(actual, "InternalError: too much recursion"); diff --git a/js/src/jit-test/tests/basic/testProxyPrototypes.js b/js/src/jit-test/tests/basic/testProxyPrototypes.js new file mode 100644 index 0000000000..3b805e4c4d --- /dev/null +++ b/js/src/jit-test/tests/basic/testProxyPrototypes.js @@ -0,0 +1,81 @@ +"use strict" +// Helpers. +function makeAccessorProp(obj, propName, initialValue, hiddenName) { + if (!hiddenName) + hiddenName = propName + '_'; + if (initialValue) + Object.defineProperty(obj, hiddenName, { value: initialValue, writable: true, enumerable: false }); + Object.defineProperty(obj, propName, + { configurable: true, + enumerable: true, + get: function() { return this[hiddenName]; }, + set: function(x) { + Object.defineProperty(this, hiddenName, { value: x, writable: true, enumerable: false }); + } + }); +} + +// Set up a prototype with 4 properties. +var proto = {valueProp: 11, valuePropShadowed: 22}; +makeAccessorProp(proto, 'accessorProp', 33); +makeAccessorProp(proto, 'accessorPropShadowed', 44); + +// Set up a proxy that uses |proto| as a prototype. +var proxyTarget = {valuePropShadowed: 21}; +makeAccessorProp(proxyTarget, 'accessorPropShadowed', -44, 'accessorPropShadowed__'); +var proxy = wrapWithProto(proxyTarget, proto); + +// Value getters. +assertEq(proxy.valueProp, 11); +assertEq(proxy.valuePropShadowed, 21); +// Iteration, enumeration, etc. +var propNames = []; +for (var i in proxy) + propNames.push(i); +assertEq(propNames.length, 4); +assertEq('valueProp' in proxy, true); +assertEq(proxy.hasOwnProperty('valueProp'), false); +assertEq(Object.getOwnPropertyNames(proxy).indexOf('valueProp'), -1); +assertEq('valuePropShadowed' in proxy, true); +assertEq(Object.getOwnPropertyNames(proxy).indexOf('valuePropShadowed') == -1, false); +assertEq(proxy.hasOwnProperty('valuePropShadowed'), true); +// Value setters. +proxy.valuePropShadowed = 20; +proxy.valueProp = 10; +assertEq(proxyTarget.valuePropShadowed, 20); +assertEq(proxyTarget.valueProp, 10); +// Accessor getters. +assertEq(proxy.accessorProp, 33); +assertEq(proxy.accessorPropShadowed, -44); +// Accessor setters. +proxy.accessorProp = 32; +proxy.accessorPropShadowed = -43; +assertEq(proxy.accessorProp, 32); +assertEq(proxy.accessorPropShadowed, -43); +// Make sure the underlying objects look right. +assertEq(proto.accessorProp_, 33); +assertEq(proto.accessorPropShadowed_, 44); +assertEq(proto.hasOwnProperty('accessorPropShadowed__'), false); +assertEq(proxyTarget.accessorProp_, 32); +assertEq(proxyTarget.hasOwnProperty('accessorPropShadowed_'), false); +assertEq(proxyTarget.accessorPropShadowed__, -43); + +// Now, create a new object prototyped to |proxy| and make sure |proxy| behaves +// well on the prototype chain. +function Constructor() { + this.foo = 2; +} +Constructor.prototype = proxy; +var child = new Constructor(); +assertEq(child.valueProp, 10); +assertEq(child.valuePropShadowed, 20); +var childPropNames = []; +for (var i in child) + childPropNames.push(i); +assertEq(childPropNames.length, 5); +child.accessorProp = 5; +child.accessorPropShadowed = 6; +assertEq(child.accessorProp, 5); +assertEq(child.accessorPropShadowed, 6); +assertEq(child.accessorProp_, 5); +assertEq(child.accessorPropShadowed__, 6); diff --git a/js/src/jit-test/tests/basic/testPutOnEmptyArgsObject.js b/js/src/jit-test/tests/basic/testPutOnEmptyArgsObject.js new file mode 100644 index 0000000000..b230897857 --- /dev/null +++ b/js/src/jit-test/tests/basic/testPutOnEmptyArgsObject.js @@ -0,0 +1,16 @@ +var g; + +function h() { + return arguments.length; +} + +function f() { + var args = arguments; + g = function() { return h.apply(this, args); } +} + +for (var i = 0; i < 10; ++i) { + f(); +} + +assertEq(g(), 0); diff --git a/js/src/jit-test/tests/basic/testReallyDeepNestedExit.js b/js/src/jit-test/tests/basic/testReallyDeepNestedExit.js new file mode 100644 index 0000000000..f27c7315c1 --- /dev/null +++ b/js/src/jit-test/tests/basic/testReallyDeepNestedExit.js @@ -0,0 +1,38 @@ +function reallyDeepNestedExit(schedule) +{ + var c = 0, j = 0; + for (var i = 0; i < 5; i++) { + for (j = 0; j < 4; j++) { + c += (schedule[i*4 + j] == 1) ? 1 : 2; + } + } + return c; +} +function testReallyDeepNestedExit() +{ + var c = 0; + var schedule1 = new Array(5*4); + var schedule2 = new Array(5*4); + for (var i = 0; i < 5*4; i++) { + schedule1[i] = 0; + schedule2[i] = 0; + } + /** + * First innermost compile: true branch runs through. + * Second '': false branch compiles new loop edge. + * First outer compile: expect true branch. + * Second '': hit false branch. + */ + schedule1[0*4 + 3] = 1; + var schedules = [schedule1, + schedule2, + schedule1, + schedule2, + schedule2]; + + for (var i = 0; i < 5; i++) { + c += reallyDeepNestedExit(schedules[i]); + } + return c; +} +assertEq(testReallyDeepNestedExit(), 198); diff --git a/js/src/jit-test/tests/basic/testRebranding.js b/js/src/jit-test/tests/basic/testRebranding.js new file mode 100644 index 0000000000..f21fc5c192 --- /dev/null +++ b/js/src/jit-test/tests/basic/testRebranding.js @@ -0,0 +1,10 @@ +q = ""; +function g() { q += "g"; } +function h() { q += "h"; } +a = [g, g, g, g, h]; +for (i=0; i<5; i++) { f = a[i]; f(); } + +function testRebranding() { + return q; +} +assertEq(testRebranding(), "ggggh"); diff --git a/js/src/jit-test/tests/basic/testRebranding2.js b/js/src/jit-test/tests/basic/testRebranding2.js new file mode 100644 index 0000000000..7349c4fc02 --- /dev/null +++ b/js/src/jit-test/tests/basic/testRebranding2.js @@ -0,0 +1,21 @@ +delete q; +delete g; +delete h; +delete a; +delete f; + +function testRebranding2() { + // Same as testRebranding, but the object to be rebranded isn't the global. + var x = "FAIL"; + function g(){} + function h(){ x = "ok"; } + var obj = {m: g}; + var arr = [g, g, g, g, h]; + //assertEq(arr.length > 9, true); + for (var i = 0; i < 5; i++) { + obj.m = arr[i]; + obj.m(); + } + return x; +} +assertEq(testRebranding2(), "ok"); diff --git a/js/src/jit-test/tests/basic/testRegExpTest.js b/js/src/jit-test/tests/basic/testRegExpTest.js new file mode 100644 index 0000000000..d7121b9871 --- /dev/null +++ b/js/src/jit-test/tests/basic/testRegExpTest.js @@ -0,0 +1,10 @@ +// |jit-test| valgrind + +function testRegExpTest() { + var r = /abc/; + var flag = false; + for (var i = 0; i < 10; ++i) + flag = r.test("abc"); + return flag; +} +assertEq(testRegExpTest(), true); diff --git a/js/src/jit-test/tests/basic/testRegexpGet.js b/js/src/jit-test/tests/basic/testRegexpGet.js new file mode 100644 index 0000000000..c8900098fb --- /dev/null +++ b/js/src/jit-test/tests/basic/testRegexpGet.js @@ -0,0 +1,8 @@ +function testRegexpGet() { + var re = /hi/; + var a = []; + for (let i = 0; i < 5; ++i) + a.push(re.source); + return a.toString(); +} +assertEq(testRegexpGet(), "hi,hi,hi,hi,hi"); diff --git a/js/src/jit-test/tests/basic/testReplace2.js b/js/src/jit-test/tests/basic/testReplace2.js new file mode 100644 index 0000000000..20685adf2a --- /dev/null +++ b/js/src/jit-test/tests/basic/testReplace2.js @@ -0,0 +1,7 @@ +function testReplace2() { + var s = "H e l l o", s1; + for (i = 0; i < 100; ++i) + s1 = s.replace(" ", ""); + return s1; +} +assertEq(testReplace2(), "He l l o"); diff --git a/js/src/jit-test/tests/basic/testReplaceMap.js b/js/src/jit-test/tests/basic/testReplaceMap.js new file mode 100644 index 0000000000..929f52ce8e --- /dev/null +++ b/js/src/jit-test/tests/basic/testReplaceMap.js @@ -0,0 +1,27 @@ + +// String.replace on functions returning hashmap elements. + +function first() { + var arr = {a: "hello", b: "there"}; + var s = 'a|b'; + return s.replace(/[a-z]/g, function(a) { return arr[a]; }, 'g'); +} +assertEq(first(), "hello|there"); + +function second() { + var arr = {a: "hello", c: "there"}; + var s = 'a|b|c'; + return s.replace(/[a-z]/g, function(a) { return arr[a]; }, 'g'); +} +assertEq(second(), "hello|undefined|there"); + +Object.defineProperty(Object.prototype, "b", {get: function() { return "what"; }}); + +assertEq(second(), "hello|what|there"); + +function third() { + var arr = {a: "hello", b: {toString: function() { arr = {}; return "three"; }}, c: "there"}; + var s = 'a|b|c'; + return s.replace(/[a-z]/g, function(a) { return arr[a]; }, 'g'); +} +assertEq(third(), "hello|three|undefined"); diff --git a/js/src/jit-test/tests/basic/testReplaceWithLambda.js b/js/src/jit-test/tests/basic/testReplaceWithLambda.js new file mode 100644 index 0000000000..9aad5ef98b --- /dev/null +++ b/js/src/jit-test/tests/basic/testReplaceWithLambda.js @@ -0,0 +1,52 @@ +// optimized +(function(b) { + assertEq("abc".replace(/a|b/g, function(a) { return b[a] }), 'ABc'); +})({a:'A', b:'B' }); +(function() { + var b = {a:'A', b:'B' }; + assertEq("abc".replace(/a|b/g, function(a) { return b[a] }), 'ABc'); +})(); +(function() { + { + let b = {a:'A', b:'B' }; + assertEq("abc".replace(/a|b/g, function(a) { return b[a] }), 'ABc'); + } +})(); +(function() { + var b = {a:'A', b:'B' }; + (function () { + assertEq("abc".replace(/a|b/g, function(a) { return b[a] }), 'ABc'); + })(); +})(); +(function() { + { + let b = {a:'A', b:'B' }; + (function () { + assertEq("abc".replace(/a|b/g, function(a) { return b[a] }), 'ABc'); + })(); + } +})(); +(function() { + var b = {a:'A', b:'B' }; + (function () { + (function () { + assertEq("abc".replace(/a|b/g, function(a) { return b[a] }), 'ABc'); + })(); + })(); +})(); + +// not optimized: +(function() { + var b = {a:'A', b:'B' }; + with ({}) { + (function () { + assertEq("abc".replace(/a|b/g, function(a) { return b[a] }), 'ABc'); + })(); + } +})(); +(function() { + var b = {a:'A', b:'B' }; + var bad = function() { b = {a:1, b:2}; return 'X' } + Object.defineProperty(b, 'x', {get:bad}); + assertEq("xabc".replace(/x|a|b/g, function(a) { return b[a] }), 'X12c'); +})(); diff --git a/js/src/jit-test/tests/basic/testResumeOp.js b/js/src/jit-test/tests/basic/testResumeOp.js new file mode 100644 index 0000000000..2acb18f562 --- /dev/null +++ b/js/src/jit-test/tests/basic/testResumeOp.js @@ -0,0 +1,8 @@ +function testResumeOp() { + var a = [1,"2",3,"4",5,"6",7,"8",9,"10",11,"12",13,"14",15,"16"]; + var x = ""; + while (a.length > 0) + x += a.pop(); + return x; +} +assertEq(testResumeOp(), "16151413121110987654321"); diff --git a/js/src/jit-test/tests/basic/testReverseArgTypes.js b/js/src/jit-test/tests/basic/testReverseArgTypes.js new file mode 100644 index 0000000000..f36fed348f --- /dev/null +++ b/js/src/jit-test/tests/basic/testReverseArgTypes.js @@ -0,0 +1,5 @@ +function testReverseArgTypes() { + for (var j = 0; j < 4; ++j) ''.replace('', /x/); + return 1; +} +assertEq(testReverseArgTypes(), 1); diff --git a/js/src/jit-test/tests/basic/testRopeMarking.js b/js/src/jit-test/tests/basic/testRopeMarking.js new file mode 100644 index 0000000000..fcf5311416 --- /dev/null +++ b/js/src/jit-test/tests/basic/testRopeMarking.js @@ -0,0 +1,13 @@ +for (var i = 0; i < 10; ++i) { + var arr = []; + var s = "abcdefghijklmnop"; + for (var j = 0; j < 5000; ++j) { + s = "<" + s + ">"; + arr.push(s); + } + gc(); + for (var j = 0; j < 5000; ++j) { + arr[j].search("a"); + } + gc(); +} diff --git a/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP-2.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP-2.js new file mode 100644 index 0000000000..f9899b1926 --- /dev/null +++ b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP-2.js @@ -0,0 +1,13 @@ +// Test that the tracer is not confused by a.m() when a is the same shape each +// time through the loop but a.m is a scripted getter that returns different +// functions. + +function f() { return 'f'; } +function g() { return 'g'; } +var arr = [f, f, f, f, f, f, f, f, g]; +var a = {get m() { return arr[i]; }}; + +var s = ''; +for (var i = 0; i < 9; i++) + s += a.m(); +assertEq(s, 'ffffffffg'); diff --git a/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js new file mode 100644 index 0000000000..d16895e15d --- /dev/null +++ b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js @@ -0,0 +1,9 @@ +var a = {_val: 'q', + get p() { return f; }}; + +function f() { return this._val; } + +var g = ''; +for (var i = 0; i < 9; i++) + g += a.p(); +assertEq(g, 'qqqqqqqqq'); diff --git a/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETARGPROP.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETARGPROP.js new file mode 100644 index 0000000000..3a865edcf5 --- /dev/null +++ b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETARGPROP.js @@ -0,0 +1,7 @@ +function test(a) { + var s = ''; + for (var i = 0; i < 9; i++) + s += a.p; + assertEq(s, 'qqqqqqqqq'); +} +test({get p() { return 'q'; }}); diff --git a/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETLOCALPROP.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETLOCALPROP.js new file mode 100644 index 0000000000..1add26e6eb --- /dev/null +++ b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETLOCALPROP.js @@ -0,0 +1,8 @@ +function test() { + var a = {get p() { return 'q'; }}; + var s = ''; + for (var i = 0; i < 9; i++) + s += a.p; + assertEq(s, 'qqqqqqqqq'); +} +test(); diff --git a/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETPROP.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETPROP.js new file mode 100644 index 0000000000..963c506c48 --- /dev/null +++ b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETPROP.js @@ -0,0 +1,8 @@ +var a = {get p() { return 11; }}; + +function f() { return a; } + +var g = 0; +for (var i = 0; i < 9; i++) + g += f().p; +assertEq(g, 99); diff --git a/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETTHISPROP.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETTHISPROP.js new file mode 100644 index 0000000000..b878a78efb --- /dev/null +++ b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETTHISPROP.js @@ -0,0 +1,9 @@ +var a = { + get p() { return 11; }, + test: function () { + var s = 0; + for (var i = 0; i < 9; i++) + s += this.p; + assertEq(s, 99); + }}; +a.test(); diff --git a/js/src/jit-test/tests/basic/testSetGetterOnlyProperty.js b/js/src/jit-test/tests/basic/testSetGetterOnlyProperty.js new file mode 100644 index 0000000000..d08ea7a56b --- /dev/null +++ b/js/src/jit-test/tests/basic/testSetGetterOnlyProperty.js @@ -0,0 +1,5 @@ +var o = { get x() { return 17; } }; +for (var j = 0; j < 5; ++j) + o.x = 42; + +assertEq(true, true); diff --git a/js/src/jit-test/tests/basic/testSetPropNeitherMissNorHit.js b/js/src/jit-test/tests/basic/testSetPropNeitherMissNorHit.js new file mode 100644 index 0000000000..906a2c1473 --- /dev/null +++ b/js/src/jit-test/tests/basic/testSetPropNeitherMissNorHit.js @@ -0,0 +1,5 @@ +function testSetPropNeitherMissNorHit() { + for (var j = 0; j < 5; ++j) { if (({}).__proto__ = 1) { } } + return "ok"; +} +assertEq(testSetPropNeitherMissNorHit(), "ok"); diff --git a/js/src/jit-test/tests/basic/testSetPropertyFail.js b/js/src/jit-test/tests/basic/testSetPropertyFail.js new file mode 100644 index 0000000000..0ca6257609 --- /dev/null +++ b/js/src/jit-test/tests/basic/testSetPropertyFail.js @@ -0,0 +1,22 @@ +function test(name, fn, val) { + gc(); + var ok = {}, bad = {}; + bad.__defineSetter__(name, fn); + var arr = [ok, ok, ok, ok, ok, bad]; + + var log = ''; + try { + for (var i = 0; i < arr.length; i++) { + arr[i][name] = val; + log += '.'; + } + } catch (exc) { + log += 'E'; + } + assertEq(log, '.....E'); +} + +test("x", Function.prototype.call, null); // TypeError: Function.prototype.call called on incompatible [object Object] +test("y", Array, 0.1); // RangeError: invalid array length +test(1, Function.prototype.call, null); // TypeError: Function.prototype.call called on incompatible [object Object] +test(1, Array, 0.1); // RangeError: invalid array length diff --git a/js/src/jit-test/tests/basic/testSetProtoRegeneratesObjectShape.js b/js/src/jit-test/tests/basic/testSetProtoRegeneratesObjectShape.js new file mode 100644 index 0000000000..1c6e0da3cc --- /dev/null +++ b/js/src/jit-test/tests/basic/testSetProtoRegeneratesObjectShape.js @@ -0,0 +1,24 @@ +function testSetProtoRegeneratesObjectShape() +{ + var f = function() {}; + var g = function() {}; + g.prototype.__proto__ = {}; + + function iq(obj) + { + for (var i = 0; i < 10; ++i) + "" + obj.prototype; + } + + iq(f); + iq(f); + iq(f); + iq(f); + iq(g); + + if (shapeOf(f.prototype) === shapeOf(g.prototype)) + return "object shapes same after proto of one is changed"; + + return true; +} +assertEq(testSetProtoRegeneratesObjectShape(), true); diff --git a/js/src/jit-test/tests/basic/testSetelemWithFloatIndex.js b/js/src/jit-test/tests/basic/testSetelemWithFloatIndex.js new file mode 100644 index 0000000000..20ec897586 --- /dev/null +++ b/js/src/jit-test/tests/basic/testSetelemWithFloatIndex.js @@ -0,0 +1,4 @@ +var x, a = {}; +for (var i = 0; i < 9; i++) + x = a[-3.5] = "ok"; +assertEq(x, "ok"); diff --git a/js/src/jit-test/tests/basic/testShiftLeft.js b/js/src/jit-test/tests/basic/testShiftLeft.js new file mode 100644 index 0000000000..341b59aa52 --- /dev/null +++ b/js/src/jit-test/tests/basic/testShiftLeft.js @@ -0,0 +1,36 @@ +// |jit-test| valgrind + +/* Test the proper operation of the left shift operator. This is especially + * important on ARM as an explicit mask is required at the native instruction + * level. */ + +function testShiftLeft() +{ + var r = []; + var i = 0; + var j = 0; + + var shifts = [0,1,7,8,15,16,23,24,31]; + + /* Samples from the simple shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << shifts[i]; + + /* Samples outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << (shifts[i] + 32); + + /* Samples far outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << (shifts[i] + 224); + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << (shifts[i] + 256); + + return r.join(","); +} + +assertEq(testShiftLeft(), + "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ + "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ + "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ + "1,2,128,256,32768,65536,8388608,16777216,-2147483648"); diff --git a/js/src/jit-test/tests/basic/testShiftRightArithmetic.js b/js/src/jit-test/tests/basic/testShiftRightArithmetic.js new file mode 100644 index 0000000000..6ecdcc4a90 --- /dev/null +++ b/js/src/jit-test/tests/basic/testShiftRightArithmetic.js @@ -0,0 +1,42 @@ +/* Test the proper operation of the arithmetic right shift operator. This is + * especially important on ARM as an explicit mask is required at the native + * instruction level. */ + +/* Test different combinations of literals/variables. */ +var s = 4; +var t = 100; +assertEq(42 >> s, 2); +assertEq(s >> 1, 2); +assertEq(23 >> 3, 2); +assertEq(t >> s, 6); + + +function testShiftRightArithmetic() +{ + var r = []; + var i = 0; + var j = 0; + + var shifts = [0,1,7,8,15,16,23,24,31]; + + /* Samples from the simple shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> shifts[i]; + + /* Samples outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> (shifts[i] + 32); + + /* Samples far outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> (shifts[i] + 224); + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> (shifts[i] + 256); + + return r.join(","); +} +assertEq(testShiftRightArithmetic(), + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1"); diff --git a/js/src/jit-test/tests/basic/testShiftRightLogical.js b/js/src/jit-test/tests/basic/testShiftRightLogical.js new file mode 100644 index 0000000000..72bc56d54e --- /dev/null +++ b/js/src/jit-test/tests/basic/testShiftRightLogical.js @@ -0,0 +1,36 @@ +/* Test the proper operation of the logical right shift operator. This is + * especially important on ARM as an explicit mask is required at the native + * instruction level. */ + +function testShiftRightLogical() +{ + var r = []; + var i = 0; + var j = 0; + + var shifts = [0,1,7,8,15,16,23,24,31]; + + /* Samples from the simple shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >>> shifts[i]; + + /* Samples outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >>> (shifts[i] + 32); + + /* Samples far outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >>> (shifts[i] + 224); + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >>> (shifts[i] + 256); + + return r.join(","); +} +/* Note: Arguments to the ">>>" operator are converted to unsigned 32-bit + * integers during evaluation. As a result, -2147483648 >>> 0 evaluates to the + * unsigned interpretation of the same value, which is 2147483648. */ +assertEq(testShiftRightLogical(), + "2147483648,1073741824,16777216,8388608,65536,32768,256,128,1,"+ + "2147483648,1073741824,16777216,8388608,65536,32768,256,128,1,"+ + "2147483648,1073741824,16777216,8388608,65536,32768,256,128,1,"+ + "2147483648,1073741824,16777216,8388608,65536,32768,256,128,1"); diff --git a/js/src/jit-test/tests/basic/testSlowArrayLength.js b/js/src/jit-test/tests/basic/testSlowArrayLength.js new file mode 100644 index 0000000000..f19ec4bfad --- /dev/null +++ b/js/src/jit-test/tests/basic/testSlowArrayLength.js @@ -0,0 +1,10 @@ +function testSlowArrayLength() +{ + var counter = 0; + var a = []; + a[10000 - 1] = 0; + for (var i = 0; i < a.length; i++) + counter++; + return counter; +} +assertEq(testSlowArrayLength(), 10000); diff --git a/js/src/jit-test/tests/basic/testSlowArrayPop.js b/js/src/jit-test/tests/basic/testSlowArrayPop.js new file mode 100644 index 0000000000..f3602aa091 --- /dev/null +++ b/js/src/jit-test/tests/basic/testSlowArrayPop.js @@ -0,0 +1,12 @@ +function testSlowArrayPop() { + var a = []; + for (var i = 0; i < 9; i++) + a[i] = [0]; + a[8].__defineGetter__("0", function () { return 'xyzzy'; }); + + var last; + for (var i = 0; i < 9; i++) + last = a[i].pop(); // reenters interpreter in getter + return last; +} +assertEq(testSlowArrayPop(), 'xyzzy'); diff --git a/js/src/jit-test/tests/basic/testSlowArrayPopMultiFrame.js b/js/src/jit-test/tests/basic/testSlowArrayPopMultiFrame.js new file mode 100644 index 0000000000..a1917ff64e --- /dev/null +++ b/js/src/jit-test/tests/basic/testSlowArrayPopMultiFrame.js @@ -0,0 +1,24 @@ +// Same thing but it needs to reconstruct multiple stack frames (so, +// multiple functions called inside the loop) +function testSlowArrayPopMultiFrame() { + var a = []; + for (var i = 0; i < 9; i++) + a[i] = [0]; + a[8].__defineGetter__("0", function () { return 23; }); + + function child(a, i) { + return a[i].pop(); // reenters interpreter in getter + } + function parent(a, i) { + return child(a, i); + } + function gramps(a, i) { + return parent(a, i); + } + + var last; + for (var i = 0; i < 9; i++) + last = gramps(a, i); + return last; +} +assertEq(testSlowArrayPopMultiFrame(), 23); diff --git a/js/src/jit-test/tests/basic/testSlowArrayPopNestedTrees.js b/js/src/jit-test/tests/basic/testSlowArrayPopNestedTrees.js new file mode 100644 index 0000000000..0ad4dbaaee --- /dev/null +++ b/js/src/jit-test/tests/basic/testSlowArrayPopNestedTrees.js @@ -0,0 +1,36 @@ +// Same thing but nested trees, each reconstructing one or more stack frames +// (so, several functions with loops, such that the loops end up being +// nested though they are not lexically nested) + +function testSlowArrayPopNestedTrees() { + var a = []; + for (var i = 0; i < 9; i++) + a[i] = [0]; + a[8].__defineGetter__("0", function () { return 3.14159 }); + + function child(a, i, j, k) { + var last = 2.71828; + for (var l = 0; l < 9; l++) + if (i == 8 && j == 8 && k == 8) + last = a[l].pop(); // reenters interpreter in getter + return last; + } + function parent(a, i, j) { + var last; + for (var k = 0; k < 9; k++) + last = child(a, i, j, k); + return last; + } + function gramps(a, i) { + var last; + for (var j = 0; j < 9; j++) + last = parent(a, i, j); + return last; + } + + var last; + for (var i = 0; i < 9; i++) + last = gramps(a, i); + return last; +} +assertEq(testSlowArrayPopNestedTrees(), 3.14159); diff --git a/js/src/jit-test/tests/basic/testSlowNativeBail.js b/js/src/jit-test/tests/basic/testSlowNativeBail.js new file mode 100644 index 0000000000..07def4543b --- /dev/null +++ b/js/src/jit-test/tests/basic/testSlowNativeBail.js @@ -0,0 +1,11 @@ +function testSlowNativeBail() { + var a = ['0', '1', '2', '3', '+']; + try { + for (var i = 0; i < a.length; i++) + new RegExp(a[i]); + assertEq(true, false); + } catch (exc) { + assertEq(exc instanceof SyntaxError, true); + } +} +testSlowNativeBail(); diff --git a/js/src/jit-test/tests/basic/testSlowNativeCtor.js b/js/src/jit-test/tests/basic/testSlowNativeCtor.js new file mode 100644 index 0000000000..345546a720 --- /dev/null +++ b/js/src/jit-test/tests/basic/testSlowNativeCtor.js @@ -0,0 +1,7 @@ +delete _quit; + +function testSlowNativeCtor() { + for (var i = 0; i < 4; i++) + new Date().valueOf(); +} +testSlowNativeCtor(); diff --git a/js/src/jit-test/tests/basic/testSlowNativeWithNullThis.js b/js/src/jit-test/tests/basic/testSlowNativeWithNullThis.js new file mode 100644 index 0000000000..b90b4f10d7 --- /dev/null +++ b/js/src/jit-test/tests/basic/testSlowNativeWithNullThis.js @@ -0,0 +1,6 @@ +x = 0 +for (a = 0; a < 3; a++) { + new ((function () { + return Float64Array + })())(x, 1) +} diff --git a/js/src/jit-test/tests/basic/testStaticEvalScope.js b/js/src/jit-test/tests/basic/testStaticEvalScope.js new file mode 100644 index 0000000000..6850f3bf4c --- /dev/null +++ b/js/src/jit-test/tests/basic/testStaticEvalScope.js @@ -0,0 +1,3 @@ +// Test that static eval scopes don't mess with statement nested scope logic in +// the frontend. +eval("if (true) { { let y; } } else {}") diff --git a/js/src/jit-test/tests/basic/testStaticsInRegExp.js b/js/src/jit-test/tests/basic/testStaticsInRegExp.js new file mode 100644 index 0000000000..16d8698744 --- /dev/null +++ b/js/src/jit-test/tests/basic/testStaticsInRegExp.js @@ -0,0 +1,8 @@ +'abcdef'.replace(/a(\w+)c/, function() { + assertEq(RegExp.lastMatch, 'abc'); + '123456'.replace(/1(\d+)3/, function() { + assertEq(RegExp.lastMatch, '123'); + }); + assertEq(RegExp.lastMatch, '123'); +}); +assertEq(RegExp.lastMatch, '123'); diff --git a/js/src/jit-test/tests/basic/testStrict.js b/js/src/jit-test/tests/basic/testStrict.js new file mode 100644 index 0000000000..583a2b065d --- /dev/null +++ b/js/src/jit-test/tests/basic/testStrict.js @@ -0,0 +1,11 @@ +function testStrict() { + var n = 10, a = []; + for (var i = 0; i < 10; ++i) { + a[0] = (n === 10); + a[1] = (n !== 10); + a[2] = (n === null); + a[3] = (n == null); + } + return a.join(","); +} +assertEq(testStrict(), "true,false,false,false"); diff --git a/js/src/jit-test/tests/basic/testString.js b/js/src/jit-test/tests/basic/testString.js new file mode 100644 index 0000000000..cb7e1e5b3a --- /dev/null +++ b/js/src/jit-test/tests/basic/testString.js @@ -0,0 +1,14 @@ +function testString() { + var q; + for (var i = 0; i <= 9; ++i) { + q = []; + q.push(String(void 0)); + q.push(String(true)); + q.push(String(5)); + q.push(String(5.5)); + q.push(String("5")); + q.push(String([5])); + } + return q.join(","); +} +assertEq(testString(), "undefined,true,5,5.5,5,5"); diff --git a/js/src/jit-test/tests/basic/testStringBufferMallocAccounting.js b/js/src/jit-test/tests/basic/testStringBufferMallocAccounting.js new file mode 100644 index 0000000000..e016f3b6bc --- /dev/null +++ b/js/src/jit-test/tests/basic/testStringBufferMallocAccounting.js @@ -0,0 +1,18 @@ +// first build a big honkin' string +str = "a"; +for (var i = 0; i < 20; ++i) + str = str + str; +str.indexOf('a'); + +var f; +f = makeFinalizeObserver(); +assertEq(finalizeCount(), 0); + +// Create another observer to make sure that we overwrite all conservative +// roots for the previous one and can observer the GC. +f = makeFinalizeObserver(); + +// if the assert fails, add more iterations +for (var i = 0; i < 80; ++i) + str.replace(/(a)/, '$1'); +//assertEq(finalizeCount(), 1); diff --git a/js/src/jit-test/tests/basic/testStringConstructorWithExtraArg.js b/js/src/jit-test/tests/basic/testStringConstructorWithExtraArg.js new file mode 100644 index 0000000000..b4986c53f9 --- /dev/null +++ b/js/src/jit-test/tests/basic/testStringConstructorWithExtraArg.js @@ -0,0 +1,6 @@ +function testStringConstructorWithExtraArg() { + for (let i = 0; i < 5; ++i) + new String(new String(), 2); + return "ok"; +} +assertEq(testStringConstructorWithExtraArg(), "ok"); diff --git a/js/src/jit-test/tests/basic/testStringIncrement.js b/js/src/jit-test/tests/basic/testStringIncrement.js new file mode 100644 index 0000000000..b0cc6775ec --- /dev/null +++ b/js/src/jit-test/tests/basic/testStringIncrement.js @@ -0,0 +1,20 @@ +var a, b; + +function f(str) { + var n; + var k; + for (var i = 0; i < 18; ++i) { + n = str; + k = n++; + if (k) { } + } + return [k, n]; +} + +[a, b] = f("10"); +assertEq(a, 10); +assertEq(b, 11); + +[a, b] = f("5"); +assertEq(a, 5); +assertEq(b, 6); diff --git a/js/src/jit-test/tests/basic/testStringLengthNoTinyId.js b/js/src/jit-test/tests/basic/testStringLengthNoTinyId.js new file mode 100644 index 0000000000..e08f5a697a --- /dev/null +++ b/js/src/jit-test/tests/basic/testStringLengthNoTinyId.js @@ -0,0 +1,64 @@ +// Second testPropagatedFunArgs test -- this is a crash-test. +(function () { + var escapee; + + function testPropagatedFunArgs() + { + const magic = 42; + + var win = this; + var res = [], q = []; + function addEventListener(name, func, flag) { + q.push(func); + } + + var pageInfo = "pageInfo", obs; + addEventListener("load", handleLoad, true); + + var observer = { + observe: function(win, topic, data) { + // obs.removeObserver(observer, "page-info-dialog-loaded"); + handlePageInfo(); + } + }; + + function handleLoad() { + //pageInfo = { toString: function() { return "pageInfo"; } }; + obs = { addObserver: function (obs, topic, data) { obs.observe(win, topic, data); } }; + obs.addObserver(observer, "page-info-dialog-loaded", false); + } + + function handlePageInfo() { + res.push(pageInfo); + function $(aId) { + function notSafe() { + return magic; + } + notSafe(); + res.push(pageInfo); + }; + var feedTab = $("feedTab"); + } + + escapee = q[0]; + return res.join(','); + } + + testPropagatedFunArgs(); + + escapee(); +})(); + +function testStringLengthNoTinyId() +{ + var x = "unset"; + var t = new String(""); + for (var i = 0; i < 5; i++) + x = t["-1"]; + + var r = "t['-1'] is " + x; + t["-1"] = "foo"; + r += " when unset, '" + t["-1"] + "' when set"; + return r; +} +assertEq(testStringLengthNoTinyId(), "t['-1'] is undefined when unset, 'foo' when set"); diff --git a/js/src/jit-test/tests/basic/testStringObjectLength.js b/js/src/jit-test/tests/basic/testStringObjectLength.js new file mode 100644 index 0000000000..d908ff63a8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testStringObjectLength.js @@ -0,0 +1,7 @@ +function testStringObjectLength() { + var x = new String("foo"), y = 0; + for (var i = 0; i < 10; ++i) + y = x.length; + return y; +} +assertEq(testStringObjectLength(), 3); diff --git a/js/src/jit-test/tests/basic/testStringToInt32.js b/js/src/jit-test/tests/basic/testStringToInt32.js new file mode 100644 index 0000000000..ca1ca349fa --- /dev/null +++ b/js/src/jit-test/tests/basic/testStringToInt32.js @@ -0,0 +1,6 @@ +function testStringToInt32() { + var s = ""; + for (let j = 0; j < 5; ++j) s += ("1e+81" ^ 3); + return s; +} +assertEq(testStringToInt32(), "33333"); diff --git a/js/src/jit-test/tests/basic/testStringToNumber.js b/js/src/jit-test/tests/basic/testStringToNumber.js new file mode 100644 index 0000000000..7f7aa57266 --- /dev/null +++ b/js/src/jit-test/tests/basic/testStringToNumber.js @@ -0,0 +1,37 @@ +enableOsiPointRegisterChecks(); + +function convertToInt(str) { + return str | 0; +} + +function convertToIntOnTrace(str) { + var z; + for (var i = 0; i < 9; ++i) { + z = str | 0; + } + return z; +} + +function convertToDouble(str) { + return str * 1.5; +} + +function convertToDoubleOnTrace(str) { + var z; + for (var i = 0; i < 9; ++i) { + z = str * 1.5; + } + return z; +} + +assertEq(convertToInt("0x10"), 16); +assertEq(convertToInt("-0x10"), 0); + +assertEq(convertToIntOnTrace("0x10"), 16); +assertEq(convertToIntOnTrace("-0x10"), 0); + +assertEq(convertToDouble("0x10"), 24); +assertEq(convertToDouble("-0x10"), NaN); + +assertEq(convertToDoubleOnTrace("0x10"), 24); +assertEq(convertToDoubleOnTrace("-0x10"), NaN); diff --git a/js/src/jit-test/tests/basic/testStringify.js b/js/src/jit-test/tests/basic/testStringify.js new file mode 100644 index 0000000000..003e4fd38a --- /dev/null +++ b/js/src/jit-test/tests/basic/testStringify.js @@ -0,0 +1,20 @@ +function testStringify() { + var t = true, f = false, u = undefined, n = 5, d = 5.5, s = "x"; + var a = []; + for (var i = 0; i < 10; ++i) { + a[0] = "" + t; + a[1] = t + ""; + a[2] = "" + f; + a[3] = f + ""; + a[4] = "" + u; + a[5] = u + ""; + a[6] = "" + n; + a[7] = n + ""; + a[8] = "" + d; + a[9] = d + ""; + a[10] = "" + s; + a[11] = s + ""; + } + return a.join(","); +} +assertEq(testStringify(), "true,true,false,false,undefined,undefined,5,5,5.5,5.5,x,x"); diff --git a/js/src/jit-test/tests/basic/testSubstring.js b/js/src/jit-test/tests/basic/testSubstring.js new file mode 100644 index 0000000000..5916c23ab0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testSubstring.js @@ -0,0 +1,7 @@ +function testSubstring() { + for (var i = 0; i < 5; ++i) { + actual = "".substring(5); + } + return actual; +} +assertEq(testSubstring(), ""); diff --git a/js/src/jit-test/tests/basic/testSwitch.js b/js/src/jit-test/tests/basic/testSwitch.js new file mode 100644 index 0000000000..c2127d4a6c --- /dev/null +++ b/js/src/jit-test/tests/basic/testSwitch.js @@ -0,0 +1,25 @@ +function testSwitch() { + var x = 0; + var ret = 0; + for (var i = 0; i < 100; ++i) { + switch (x) { + case 0: + ret += 1; + break; + case 1: + ret += 2; + break; + case 2: + ret += 3; + break; + case 3: + ret += 4; + break; + default: + x = 0; + } + x++; + } + return ret; +} +assertEq(testSwitch(), 226); diff --git a/js/src/jit-test/tests/basic/testSwitchString.js b/js/src/jit-test/tests/basic/testSwitchString.js new file mode 100644 index 0000000000..323763a3f2 --- /dev/null +++ b/js/src/jit-test/tests/basic/testSwitchString.js @@ -0,0 +1,28 @@ +function testSwitchString() { + var x = "asdf"; + var ret = 0; + for (var i = 0; i < 100; ++i) { + switch (x) { + case "asdf": + x = "asd"; + ret += 1; + break; + case "asd": + x = "as"; + ret += 2; + break; + case "as": + x = "a"; + ret += 3; + break; + case "a": + x = "foo"; + ret += 4; + break; + default: + x = "asdf"; + } + } + return ret; +} +assertEq(testSwitchString(), 200); diff --git a/js/src/jit-test/tests/basic/testSwitchUndefined.js b/js/src/jit-test/tests/basic/testSwitchUndefined.js new file mode 100644 index 0000000000..44d27ca38c --- /dev/null +++ b/js/src/jit-test/tests/basic/testSwitchUndefined.js @@ -0,0 +1,15 @@ +function testSwitchUndefined() +{ + var x = undefined; + var y = 0; + for (var i = 0; i < 5; i++) + { + switch (x) + { + default: + y++; + } + } + return y; +} +assertEq(testSwitchUndefined(), 5); diff --git a/js/src/jit-test/tests/basic/testTableSwitch1.js b/js/src/jit-test/tests/basic/testTableSwitch1.js new file mode 100644 index 0000000000..db212c0de8 --- /dev/null +++ b/js/src/jit-test/tests/basic/testTableSwitch1.js @@ -0,0 +1,13 @@ +function testTableSwitch1() { + var x = 'miss'; + var i, j = 0; + for (i = 0; i < 19; i++) { + switch (x) { + case 1: case 2: case 3: case 4: case 5: throw "FAIL"; + default: j++; + } + } + assertEq(i, j); +} + +testTableSwitch1(); diff --git a/js/src/jit-test/tests/basic/testTableSwitch2.js b/js/src/jit-test/tests/basic/testTableSwitch2.js new file mode 100644 index 0000000000..8953aa2eb2 --- /dev/null +++ b/js/src/jit-test/tests/basic/testTableSwitch2.js @@ -0,0 +1,18 @@ +function testTableSwitch2() { + var arr = [2, 2, 2, 2, 2, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5]; + var s = ''; + for (var i = 0; i < arr.length; i++) { + switch (arr[i]) { + case 0: case 1: case 3: case 4: + throw "FAIL"; + case 2: + s += '2'; + break; + case 5: + s += '5'; + } + } + assertEq(s, arr.join("")); +} + +testTableSwitch2(); diff --git a/js/src/jit-test/tests/basic/testThinLoopDemote.js b/js/src/jit-test/tests/basic/testThinLoopDemote.js new file mode 100644 index 0000000000..b26c460a78 --- /dev/null +++ b/js/src/jit-test/tests/basic/testThinLoopDemote.js @@ -0,0 +1,13 @@ +function testThinLoopDemote() { + function f() + { + var k = 1; + for (var n = 0; n < 4; n++) { + k = (k * 10); + } + return k; + } + f(); + return f(); +} +assertEq(testThinLoopDemote(), 10000); diff --git a/js/src/jit-test/tests/basic/testThrowWhileWrappingException.js b/js/src/jit-test/tests/basic/testThrowWhileWrappingException.js new file mode 100644 index 0000000000..51169339ab --- /dev/null +++ b/js/src/jit-test/tests/basic/testThrowWhileWrappingException.js @@ -0,0 +1,7 @@ +var caught = false; +try { + evalcx("eval(\"throw<x/>\")", Function.a) +} catch (e) { + caught = true; +} +assertEq(caught, true); diff --git a/js/src/jit-test/tests/basic/testThrowingObjectEqUndefined.js b/js/src/jit-test/tests/basic/testThrowingObjectEqUndefined.js new file mode 100644 index 0000000000..5104c52ee7 --- /dev/null +++ b/js/src/jit-test/tests/basic/testThrowingObjectEqUndefined.js @@ -0,0 +1,15 @@ +function testThrowingObjectEqUndefined() +{ + try + { + var obj = { toString: function() { throw 0; } }; + for (var i = 0; i < 5; i++) + "" + (obj == undefined); + return i === 5; + } + catch (e) + { + return "" + e; + } +} +assertEq(testThrowingObjectEqUndefined(), true); diff --git a/js/src/jit-test/tests/basic/testToLocaleString.js b/js/src/jit-test/tests/basic/testToLocaleString.js new file mode 100644 index 0000000000..158e08b462 --- /dev/null +++ b/js/src/jit-test/tests/basic/testToLocaleString.js @@ -0,0 +1,2 @@ +var str = (3.14).toLocaleString(); +assertEq(str[str.length-1], "4");
\ No newline at end of file diff --git a/js/src/jit-test/tests/basic/testToStringBeforeValueOf.js b/js/src/jit-test/tests/basic/testToStringBeforeValueOf.js new file mode 100644 index 0000000000..b3550371ee --- /dev/null +++ b/js/src/jit-test/tests/basic/testToStringBeforeValueOf.js @@ -0,0 +1,9 @@ +function testToStringBeforeValueOf() +{ + var o = {toString: function() { return "s"; }, valueOf: function() { return "v"; } }; + var a = []; + for (var i = 0; i < 10; i++) + a.push(String(o)); + return a.join(","); +} +assertEq(testToStringBeforeValueOf(), "s,s,s,s,s,s,s,s,s,s"); diff --git a/js/src/jit-test/tests/basic/testToUpperToLower.js b/js/src/jit-test/tests/basic/testToUpperToLower.js new file mode 100644 index 0000000000..4bd78f3530 --- /dev/null +++ b/js/src/jit-test/tests/basic/testToUpperToLower.js @@ -0,0 +1,9 @@ +function testToUpperToLower() { + var s = "Hello", s1, s2; + for (i = 0; i < 100; ++i) { + s1 = s.toLowerCase(); + s2 = s.toUpperCase(); + } + return s1 + s2; +} +assertEq(testToUpperToLower(), "helloHELLO"); diff --git a/js/src/jit-test/tests/basic/testTruncatedMod.js b/js/src/jit-test/tests/basic/testTruncatedMod.js new file mode 100644 index 0000000000..61789417cd --- /dev/null +++ b/js/src/jit-test/tests/basic/testTruncatedMod.js @@ -0,0 +1,18 @@ +var f = function(i,j) { return i%j|0 }; +assertEq(f(10, 0), 0); +var f = function(i,j) { return i%j|0 }; +assertEq(f(0, 0), 0); +var f = function(i,j) { return i%j|0 }; +assertEq(f(-Math.pow(2,31), -1), 0); +var f = function(i,j) { return i%j|0 }; +assertEq(f(-4, 4), 0); + +var f = function(i) { return i%4|0 }; +assertEq(f(-4), 0); +var f = function(i) { return i%4|0 }; +assertEq(f(0), 0); + +var f = function(i) { return i%3|0 }; +assertEq(f(-3), 0); +var f = function(i) { return i%3|0 }; +assertEq(f(0), 0); diff --git a/js/src/jit-test/tests/basic/testTypeUnstableForIn.js b/js/src/jit-test/tests/basic/testTypeUnstableForIn.js new file mode 100644 index 0000000000..0f6b10be40 --- /dev/null +++ b/js/src/jit-test/tests/basic/testTypeUnstableForIn.js @@ -0,0 +1,10 @@ +function testTypeUnstableForIn() { + var a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]; + var x = 0; + for (var i in a) { + i = parseInt(i); + x++; + } + return x; +} +assertEq(testTypeUnstableForIn(), 16); diff --git a/js/src/jit-test/tests/basic/testTypedArrayByteRegs.js b/js/src/jit-test/tests/basic/testTypedArrayByteRegs.js new file mode 100644 index 0000000000..09c6d320ba --- /dev/null +++ b/js/src/jit-test/tests/basic/testTypedArrayByteRegs.js @@ -0,0 +1,30 @@ +// Uint8Array and Int8Array need single byte registers. +// Test for id and value having the same backing. +function f() { + var x = new Uint8Array(30); + for (var i=0; i<x.length; i++) { + x[i] = i; + } + + var res = 0; + for (var i=0; i<x.length; i++) { + res += x[i]; + } + assertEq(res, 435); +} +f(); + +// Test for id and value having a different backing. +function g() { + var x = new Int8Array(30); + for (var i=1; i<x.length; i++) { + x[i-1] = i; + } + + var res = 0; + for (var i=0; i<x.length; i++) { + res += x[i]; + } + assertEq(res, 435); +} +g(); diff --git a/js/src/jit-test/tests/basic/testTypedArrayClamping.js b/js/src/jit-test/tests/basic/testTypedArrayClamping.js new file mode 100644 index 0000000000..58015edbe0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testTypedArrayClamping.js @@ -0,0 +1,41 @@ +function f() { + var input = []; + var expected = []; + + var add = function(inp, exp) { + input.push(inp); + expected.push(exp); + }; + + add(-0, 0); + add(-0.1, 0); + add(-0.7, 0); + add(0.1, 0); + add(NaN, 0); + add(-Infinity, 0); + add(Infinity, 255); + add(0.7, 1); + add(1.2, 1); + add(3.5, 4); + add(4.5, 4); + add(254.4, 254); + add(254.5, 254); + add(254.6, 255); + add(254.9, 255); + add(255.1, 255); + add(255.4, 255); + add(255.5, 255); + add(255.9, 255); + + var len = input.length; + var a = new Uint8ClampedArray(len); + + for (var i=0; i<len; i++) { + a[i] = input[i]; + } + for (var i=0; i<len; i++) { + assertEq(a[i], expected[i], "Failed: " + input[i]); + } +} +f(); +f(); diff --git a/js/src/jit-test/tests/basic/testTypedArrayInit.js b/js/src/jit-test/tests/basic/testTypedArrayInit.js new file mode 100644 index 0000000000..8441460d4d --- /dev/null +++ b/js/src/jit-test/tests/basic/testTypedArrayInit.js @@ -0,0 +1,30 @@ +// |jit-test| skip-if: getBuildConfiguration("arm64-simulator") === true +// +// The ARM64 Simulator can take upwards of 6 minutes to execute this test, +// which fails intermittently with timeouts. +// +// Arrays should be initialized to zero. + +function f() { + for (var ctor of [ Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array ]) + { + for (var len of [ 3, 30, 300, 3000, 30000 ]) { + var arr = new ctor(len); + for (var i = 0; i < arr.length; i++) + assertEq(arr[i], 0, "index " + i + " of " + ctor.name + " len " + len); + } + } +} + +f(); +f(); +gc() +f(); diff --git a/js/src/jit-test/tests/basic/testTypedArrayMaybeUndefined.js b/js/src/jit-test/tests/basic/testTypedArrayMaybeUndefined.js new file mode 100644 index 0000000000..e2dc941928 --- /dev/null +++ b/js/src/jit-test/tests/basic/testTypedArrayMaybeUndefined.js @@ -0,0 +1,46 @@ +// Testing GETELEM and SETELEM on a typed array where the +// type set of the object may include undefined or other +// primitive types. + +// Argument x has type {void, double, Uint16Array}. +function testSet(x) { + var y = 0; + for (var i=0; i<40; i++) { + x[i] = 3; + } + return x[10]; +} + +// Argument x has type {void, int32, Uint16Array}. +function testGet(x) { + var y = 0; + for (var i=0; i<40; i++) { + y += x[i]; + } + return y; +} + +var arr = new Uint16Array(40); +assertEq(testSet(arr), 3); +try { + testSet(undefined); +} catch(e) { + assertEq(e instanceof TypeError, true); +} +try { + testSet(4.5); +} catch(e) { + assertEq(e instanceof TypeError, true); +} + +assertEq(testGet(arr), 120); +try { + testGet(undefined); +} catch(e) { + assertEq(e instanceof TypeError, true); +} +try { + testGet(12345); +} catch(e) { + assertEq(e instanceof TypeError, true); +} diff --git a/js/src/jit-test/tests/basic/testTypedArrayOutOfBounds.js b/js/src/jit-test/tests/basic/testTypedArrayOutOfBounds.js new file mode 100644 index 0000000000..8c2d85441c --- /dev/null +++ b/js/src/jit-test/tests/basic/testTypedArrayOutOfBounds.js @@ -0,0 +1,32 @@ +function f1() { + var a = new Int32Array(50); + for (var i=0; i<100; i++) { + var x = a[i]; + assertEq(typeof x, i < a.length ? "number" : "undefined"); + } + + var b = new Float32Array(50); + for (var i=0; i<100; i++) { + var x = b[i]; + assertEq(typeof x, i < b.length ? "number" : "undefined"); + } +} +f1(); + +function f2() { + // Test that values on the prototype are ignored, + // even for OOB accesses. This behavior is new + // with ECMA 6 (see bug 829896). + Object.prototype[50] = 4.4; + Object.prototype[55] = Math; + + var a = new Int16Array(50); + for (var i=0; i<100; i++) { + var x = a[i]; + if (i < a.length) + assertEq(x, 0); + else + assertEq(x, undefined); + } +} +f2(); diff --git a/js/src/jit-test/tests/basic/testTypedArrayPunning.js b/js/src/jit-test/tests/basic/testTypedArrayPunning.js new file mode 100644 index 0000000000..59f6b744fc --- /dev/null +++ b/js/src/jit-test/tests/basic/testTypedArrayPunning.js @@ -0,0 +1,42 @@ +function testNonCanonicalNan() +{ + const bytes = 128; + var buf = new ArrayBuffer(bytes); + + /* create an array of non-canonical double nans */ + var ui8arr = new Uint8Array(buf); + for (var i = 0; i < ui8arr.length; ++i) + ui8arr[i] = 0xff; + + var dblarr = new Float64Array(buf); + assertEq(dblarr.length, bytes / 8); + + /* ensure they are canonicalized */ + for (var i = 0; i < dblarr.length; ++i) { + var asstr = dblarr[i] + ""; + var asnum = dblarr[i] + 0.0; + assertEq(asstr, "NaN"); + assertEq(asnum, NaN); + } + + /* create an array of non-canonical float nans */ + for (var i = 0; i < ui8arr.length; i += 4) { + ui8arr[i+0] = 0xffff; + ui8arr[i+1] = 0xffff; + ui8arr[i+2] = 0xffff; + ui8arr[i+3] = 0xffff; + } + + var fltarr = new Float32Array(buf); + assertEq(fltarr.length, bytes / 4); + + /* ensure they are canonicalized */ + for (var i = 0; i < fltarr.length; ++i) { + var asstr = fltarr[i] + ""; + var asnum = fltarr[i] + 0.0; + assertEq(asstr, "NaN"); + assertEq(asnum, NaN); + } +} + +testNonCanonicalNan(); diff --git a/js/src/jit-test/tests/basic/testTypedArraySetConversion.js b/js/src/jit-test/tests/basic/testTypedArraySetConversion.js new file mode 100644 index 0000000000..c50cf236dc --- /dev/null +++ b/js/src/jit-test/tests/basic/testTypedArraySetConversion.js @@ -0,0 +1,15 @@ +var n = 16;
+var a = new Int32Array(n);
+for (var i = 0; i < n; ++i) {
+ a[i] = i;
+}
+var b = new Int32Array(n);
+for (var i = 0; i < n; ++i) {
+ b[i] = i * 2;
+}
+
+a.set(b, 0.99);
+
+for (var i = 0; i < n; ++i) {
+ assertEq(a[i], b[i]);
+}
diff --git a/js/src/jit-test/tests/basic/testTypedArrayUint32.js b/js/src/jit-test/tests/basic/testTypedArrayUint32.js new file mode 100644 index 0000000000..587e70895a --- /dev/null +++ b/js/src/jit-test/tests/basic/testTypedArrayUint32.js @@ -0,0 +1,19 @@ +function f() { + var input = [0, 1, 2, 0x80000000, 0xfffffff0, + 0xffffffff, 0xffffffff + 1, 0xffffffff + 2, + 101]; + + var arr = new Uint32Array(input.length); + for (var i=0; i < arr.length; i++) { + arr[i] = input[i]; + } + + var expected = [0, 1, 2, 0x80000000, 0xfffffff0, + 0xffffffff, 0, 1, 101]; + for (var i=0; i < arr.length; i++) { + assertEq(arr[i], expected[i]); + } +} +for (var i=0; i<5; i++) { + f(); +} diff --git a/js/src/jit-test/tests/basic/testTypedArrayUndefinedAndHoles.js b/js/src/jit-test/tests/basic/testTypedArrayUndefinedAndHoles.js new file mode 100644 index 0000000000..0800b10859 --- /dev/null +++ b/js/src/jit-test/tests/basic/testTypedArrayUndefinedAndHoles.js @@ -0,0 +1,32 @@ +function holeArray(sparse) { + var a = [,,]; + if (sparse) + a.length = 1000; + return a; +} + +function undefinedArray(sparse) { + var a = [ undefined, undefined, undefined ]; + if (sparse) + a.length = 1000; + return a; +} + +var a; +a = new Int32Array(holeArray(false)); +assertEq(a[0], 0); +a = new Int32Array(holeArray(true)); +assertEq(a[0], 0); +a = new Int32Array(undefinedArray(false)); +assertEq(a[0], 0); +a = new Int32Array(undefinedArray(true)); +assertEq(a[0], 0); + +a = new Float64Array(holeArray(false)); +assertEq(a[0], NaN); +a = new Float64Array(holeArray(true)); +assertEq(a[0], NaN); +a = new Float64Array(undefinedArray(false)); +assertEq(a[0], NaN); +a = new Float64Array(undefinedArray(true)); +assertEq(a[0], NaN); diff --git a/js/src/jit-test/tests/basic/testTypedArrays.js b/js/src/jit-test/tests/basic/testTypedArrays.js new file mode 100644 index 0000000000..eb2ff4d230 --- /dev/null +++ b/js/src/jit-test/tests/basic/testTypedArrays.js @@ -0,0 +1,96 @@ +function testBasicTypedArrays() +{ + var ar, aridx, idx; + + var a = new Uint8Array(16); + var b = new Uint16Array(16); + var c = new Uint32Array(16); + var d = new Int8Array(16); + var e = new Int16Array(16); + var f = new Int32Array(16); + + var g = new Float32Array(16); + var h = new Float64Array(16); + + var iarrays = [ a, b, c, d, e, f ]; + for (aridx = 0; aridx < iarrays.length; ++aridx) { + ar = iarrays[aridx]; + + for (idx = 0; idx < ar.length-4; ++idx) { + ar[idx] = 22; + ar[idx+1] = 12.7; + ar[idx+2] = "99"; + ar[idx+3] = { k: "thing" }; + ar[idx+4] = Infinity; + } + + assertEq(ar[ar.length-5], 22); + assertEq(ar[ar.length-4], 12); + assertEq(ar[ar.length-3], 99); + assertEq(ar[ar.length-2], 0); + assertEq(ar[ar.length-1], 0); + } + + var farrays = [ g, h ]; + for (aridx = 0; aridx < farrays.length; ++aridx) { + ar = farrays[aridx]; + + for (idx = 0; idx < ar.length-4; ++idx) { + ar[idx] = 22; + ar[idx+1] = 12.25; + ar[idx+2] = "99"; + ar[idx+3] = { k: "thing" }; + ar[idx+4] = Infinity; + } + + assertEq(ar[ar.length-5], 22); + assertEq(ar[ar.length-4], 12.25); + assertEq(ar[ar.length-3], 99); + assertEq(!(ar[ar.length-2] == ar[ar.length-2]), true); + assertEq(ar[ar.length-1], Infinity); + } +} + +function testSpecialTypedArrays() +{ + var ar, aridx, idx; + + ar = new Uint8ClampedArray(16); + for (idx = 0; idx < ar.length-4; ++idx) { + ar[idx] = -200; + ar[idx+1] = 127.5; + ar[idx+2] = 987; + ar[idx+3] = Infinity; + ar[idx+4] = "hello world"; + } + + assertEq(ar[ar.length-5], 0); + assertEq(ar[ar.length-4], 128); + assertEq(ar[ar.length-3], 255); + assertEq(ar[ar.length-2], 255); + assertEq(ar[ar.length-1], 0); +} + +function testTypedArrayOther() +{ + var ar = new Int32Array(16); + for (var i = 0; i < ar.length; ++i) { + ar[i] = i; + } + + for (var i = 0; i < ar.length; ++i) { + // deliberate out of bounds access + ar[i-2] = ar[i+2]; + } + + var t = 0; + for (var i = 0; i < ar.length; ++i) { + t += ar[i]; + } + + assertEq(t, 143); +} + +testBasicTypedArrays(); +testSpecialTypedArrays(); +testTypedArrayOther(); diff --git a/js/src/jit-test/tests/basic/testTypeofHole.js b/js/src/jit-test/tests/basic/testTypeofHole.js new file mode 100644 index 0000000000..9538dd79cf --- /dev/null +++ b/js/src/jit-test/tests/basic/testTypeofHole.js @@ -0,0 +1,8 @@ +function testTypeofHole() { + var a = new Array(6); + a[5] = 3; + for (var i = 0; i < 6; ++i) + a[i] = typeof a[i]; + return a.join(","); +} +assertEq(testTypeofHole(), "undefined,undefined,undefined,undefined,undefined,number"); diff --git a/js/src/jit-test/tests/basic/testUnaryImacros.js b/js/src/jit-test/tests/basic/testUnaryImacros.js new file mode 100644 index 0000000000..884d856d26 --- /dev/null +++ b/js/src/jit-test/tests/basic/testUnaryImacros.js @@ -0,0 +1,26 @@ +function testUnaryImacros() +{ + function checkArg(x) + { + return 1; + } + + var o = { valueOf: checkArg, toString: null }; + var count = 0; + var v = 0; + for (var i = 0; i < 5; i++) + v += +o + -(-o); + + var results = [v === 10 ? "valueOf passed" : "valueOf failed"]; + + o.valueOf = null; + o.toString = checkArg; + + for (var i = 0; i < 5; i++) + v += +o + -(-o); + + results.push(v === 20 ? "toString passed" : "toString failed"); + + return results.join(", "); +} +assertEq(testUnaryImacros(), "valueOf passed, toString passed"); diff --git a/js/src/jit-test/tests/basic/testUndefinedBooleanCmp.js b/js/src/jit-test/tests/basic/testUndefinedBooleanCmp.js new file mode 100644 index 0000000000..cd21469829 --- /dev/null +++ b/js/src/jit-test/tests/basic/testUndefinedBooleanCmp.js @@ -0,0 +1,24 @@ +function testUndefinedBooleanCmp() +{ + var t = true, f = false, x = []; + for (var i = 0; i < 10; ++i) { + x[0] = t == undefined; + x[1] = t != undefined; + x[2] = t === undefined; + x[3] = t !== undefined; + x[4] = t < undefined; + x[5] = t > undefined; + x[6] = t <= undefined; + x[7] = t >= undefined; + x[8] = f == undefined; + x[9] = f != undefined; + x[10] = f === undefined; + x[11] = f !== undefined; + x[12] = f < undefined; + x[13] = f > undefined; + x[14] = f <= undefined; + x[15] = f >= undefined; + } + return x.join(","); +} +assertEq(testUndefinedBooleanCmp(), "false,true,false,true,false,false,false,false,false,true,false,true,false,false,false,false"); diff --git a/js/src/jit-test/tests/basic/testUndefinedCmp.js b/js/src/jit-test/tests/basic/testUndefinedCmp.js new file mode 100644 index 0000000000..48a0dd5a10 --- /dev/null +++ b/js/src/jit-test/tests/basic/testUndefinedCmp.js @@ -0,0 +1,6 @@ +function testUndefinedCmp() { + var a = false; + for (var j = 0; j < 4; ++j) { if (undefined < false) { a = true; } } + return a; +} +assertEq(testUndefinedCmp(), false); diff --git a/js/src/jit-test/tests/basic/testUndefinedIncrement.js b/js/src/jit-test/tests/basic/testUndefinedIncrement.js new file mode 100644 index 0000000000..a42557b3b7 --- /dev/null +++ b/js/src/jit-test/tests/basic/testUndefinedIncrement.js @@ -0,0 +1,15 @@ +function f() { + var n; + var k; + for (var i = 0; i < 18; ++i) { + n = undefined; + k = n++; + if (k) { } + } + return [k, n]; +} + +var [a, b] = f(); + +assertEq(isNaN(a), true); +assertEq(isNaN(b), true); diff --git a/js/src/jit-test/tests/basic/testUndefinedPropertyAccess.js b/js/src/jit-test/tests/basic/testUndefinedPropertyAccess.js new file mode 100644 index 0000000000..3828f326c5 --- /dev/null +++ b/js/src/jit-test/tests/basic/testUndefinedPropertyAccess.js @@ -0,0 +1,12 @@ +function testUndefinedPropertyAccess() { + var x = [1,2,3]; + var y = {}; + var a = { foo: 1 }; + y.__proto__ = x; + var z = [x, x, x, y, y, y, y, a, a, a]; + var s = ""; + for (var i = 0; i < z.length; ++i) + s += z[i].foo; + return s; +} +assertEq(testUndefinedPropertyAccess(), "undefinedundefinedundefinedundefinedundefinedundefinedundefined111"); diff --git a/js/src/jit-test/tests/basic/testUndemotableBinaryOp.js b/js/src/jit-test/tests/basic/testUndemotableBinaryOp.js new file mode 100644 index 0000000000..6fd79cda0e --- /dev/null +++ b/js/src/jit-test/tests/basic/testUndemotableBinaryOp.js @@ -0,0 +1,6 @@ +function testUndemotableBinaryOp() { + var out = []; + for (let j = 0; j < 5; ++j) { out.push(6 - ((void 0) ^ 0x80000005)); } + return out.join(","); +} +assertEq(testUndemotableBinaryOp(), "2147483649,2147483649,2147483649,2147483649,2147483649"); diff --git a/js/src/jit-test/tests/basic/testWeirdDateParse.js b/js/src/jit-test/tests/basic/testWeirdDateParse.js new file mode 100644 index 0000000000..77fdd33bf2 --- /dev/null +++ b/js/src/jit-test/tests/basic/testWeirdDateParse.js @@ -0,0 +1,38 @@ +var global = this; +function testWeirdDateParseOuter() +{ + var vDateParts = ["11", "17", "2008"]; + var out = []; + for (var vI = 0; vI < vDateParts.length; vI++) + out.push(testWeirdDateParseInner(vDateParts[vI])); + /* Mutate the global shape so we fall off trace; this causes + * additional oddity */ + global.x = Math.random(); + return out; +} +function testWeirdDateParseInner(pVal) +{ + var vR = 0; + for (var vI = 0; vI < pVal.length; vI++) { + var vC = pVal.charAt(vI); + if ((vC >= '0') && (vC <= '9')) + vR = (vR * 10) + parseInt(vC); + } + return vR; +} +function testWeirdDateParse() { + var result = []; + result.push(testWeirdDateParseInner("11")); + result.push(testWeirdDateParseInner("17")); + result.push(testWeirdDateParseInner("2008")); + result.push(testWeirdDateParseInner("11")); + result.push(testWeirdDateParseInner("17")); + result.push(testWeirdDateParseInner("2008")); + result = result.concat(testWeirdDateParseOuter()); + result = result.concat(testWeirdDateParseOuter()); + result.push(testWeirdDateParseInner("11")); + result.push(testWeirdDateParseInner("17")); + result.push(testWeirdDateParseInner("2008")); + return result.join(","); +} +assertEq(testWeirdDateParse(), "11,17,2008,11,17,2008,11,17,2008,11,17,2008,11,17,2008"); diff --git a/js/src/jit-test/tests/basic/testWeirdGetterInvocation.js b/js/src/jit-test/tests/basic/testWeirdGetterInvocation.js new file mode 100644 index 0000000000..f272f3df97 --- /dev/null +++ b/js/src/jit-test/tests/basic/testWeirdGetterInvocation.js @@ -0,0 +1,6 @@ +function getArgs() { return arguments; } +var a1 = getArgs(1); +var a2 = getArgs(1); +a1.__proto__ = a2; +delete a1[0]; +a1[0]; diff --git a/js/src/jit-test/tests/basic/testWeirdThingsInFunctionConstructor.js b/js/src/jit-test/tests/basic/testWeirdThingsInFunctionConstructor.js new file mode 100644 index 0000000000..f262f22020 --- /dev/null +++ b/js/src/jit-test/tests/basic/testWeirdThingsInFunctionConstructor.js @@ -0,0 +1,6 @@ +var f = new Function('x', 'var f = 3; if (x) function f() {}; return f'); +assertEq(f(false), 3); +assertEq(typeof f(true), "function"); + +var f = new Function('x', '"use strict"; x = 3; return arguments[0]'); +assertEq(f(42), 42); diff --git a/js/src/jit-test/tests/basic/testWhileObjectOrNull.js b/js/src/jit-test/tests/basic/testWhileObjectOrNull.js new file mode 100644 index 0000000000..51316ae8ec --- /dev/null +++ b/js/src/jit-test/tests/basic/testWhileObjectOrNull.js @@ -0,0 +1,18 @@ +function testWhileObjectOrNull() +{ + try + { + for (var i = 0; i < 3; i++) + { + var o = { p: { p: null } }; + while (o.p) + o = o.p; + } + return "pass"; + } + catch (e) + { + return "threw exception: " + e; + } +} +assertEq(testWhileObjectOrNull(), "pass"); diff --git a/js/src/jit-test/tests/basic/testWhileWithContinue.js b/js/src/jit-test/tests/basic/testWhileWithContinue.js new file mode 100644 index 0000000000..823fdd9da4 --- /dev/null +++ b/js/src/jit-test/tests/basic/testWhileWithContinue.js @@ -0,0 +1,10 @@ +// Test using 'while' with 'continue' -- the most ancient, the most powerful, +// the most rare of all coding incantations. + +var i = 0; +while (i < 12) { + ++i; + continue; +} +assertEq(i, 12); + diff --git a/js/src/jit-test/tests/basic/testWith.js b/js/src/jit-test/tests/basic/testWith.js new file mode 100644 index 0000000000..ec1a42a847 --- /dev/null +++ b/js/src/jit-test/tests/basic/testWith.js @@ -0,0 +1,8 @@ + +// basic 'with' functionality + +var o = {foo: true}; +with(o) { + foo = 10; +} +assertEq(o.foo, 10); diff --git a/js/src/jit-test/tests/basic/testWithAndShadowing.js b/js/src/jit-test/tests/basic/testWithAndShadowing.js new file mode 100644 index 0000000000..07922c8993 --- /dev/null +++ b/js/src/jit-test/tests/basic/testWithAndShadowing.js @@ -0,0 +1,14 @@ +// see bug 470795 +var o = [{},{},{i:42}] +var i; +var s = []; +for (var j = 0; j < 3; ++j) { + with (o[j]) { + for (i = 0; i < 2; ++i) { + s.push(j); + s.push(i); + } + } +} +assertEq(s.join(), '0,0,0,1,1,0,1,1,2,0,2,1'); + diff --git a/js/src/jit-test/tests/basic/test_JSOP_ARGCNT.js b/js/src/jit-test/tests/basic/test_JSOP_ARGCNT.js new file mode 100644 index 0000000000..6e558a07fe --- /dev/null +++ b/js/src/jit-test/tests/basic/test_JSOP_ARGCNT.js @@ -0,0 +1,27 @@ +function test_JSOP_ARGCNT() { + function f0() { return arguments.length; } + function f1() { return arguments.length; } + function f2() { return arguments.length; } + function f3() { return arguments.length; } + function f4() { return arguments.length; } + function f5() { return arguments.length; } + function f6() { return arguments.length; } + function f7() { return arguments.length; } + function f8() { return arguments.length; } + function f9() { return arguments.length; } + var a = []; + for (var i = 0; i < 10; i++) { + a[0] = f0('a'); + a[1] = f1('a','b'); + a[2] = f2('a','b','c'); + a[3] = f3('a','b','c','d'); + a[4] = f4('a','b','c','d','e'); + a[5] = f5('a','b','c','d','e','f'); + a[6] = f6('a','b','c','d','e','f','g'); + a[7] = f7('a','b','c','d','e','f','g','h'); + a[8] = f8('a','b','c','d','e','f','g','h','i'); + a[9] = f9('a','b','c','d','e','f','g','h','i','j'); + } + return a.join(","); +} +assertEq(test_JSOP_ARGCNT(), "1,2,3,4,5,6,7,8,9,10"); diff --git a/js/src/jit-test/tests/basic/test_JSOP_ARGSUB.js b/js/src/jit-test/tests/basic/test_JSOP_ARGSUB.js new file mode 100644 index 0000000000..1a4d27cda9 --- /dev/null +++ b/js/src/jit-test/tests/basic/test_JSOP_ARGSUB.js @@ -0,0 +1,27 @@ +function test_JSOP_ARGSUB() { + function f0() { return arguments[0]; } + function f1() { return arguments[1]; } + function f2() { return arguments[2]; } + function f3() { return arguments[3]; } + function f4() { return arguments[4]; } + function f5() { return arguments[5]; } + function f6() { return arguments[6]; } + function f7() { return arguments[7]; } + function f8() { return arguments[8]; } + function f9() { return arguments[9]; } + var a = []; + for (var i = 0; i < 10; i++) { + a[0] = f0('a'); + a[1] = f1('a','b'); + a[2] = f2('a','b','c'); + a[3] = f3('a','b','c','d'); + a[4] = f4('a','b','c','d','e'); + a[5] = f5('a','b','c','d','e','f'); + a[6] = f6('a','b','c','d','e','f','g'); + a[7] = f7('a','b','c','d','e','f','g','h'); + a[8] = f8('a','b','c','d','e','f','g','h','i'); + a[9] = f9('a','b','c','d','e','f','g','h','i','j'); + } + return a.join(""); +} +assertEq(test_JSOP_ARGSUB(), "abcdefghij"); diff --git a/js/src/jit-test/tests/basic/testif.js b/js/src/jit-test/tests/basic/testif.js new file mode 100644 index 0000000000..f7b2864e90 --- /dev/null +++ b/js/src/jit-test/tests/basic/testif.js @@ -0,0 +1,11 @@ +function testif() { + var q = 0; + for (var i = 0; i < 100; i++) { + if ((i & 1) == 0) + q++; + else + q--; + } + return q; +} +assertEq(testif(), 0); diff --git a/js/src/jit-test/tests/basic/testincops.js b/js/src/jit-test/tests/basic/testincops.js new file mode 100644 index 0000000000..85e36abe36 --- /dev/null +++ b/js/src/jit-test/tests/basic/testincops.js @@ -0,0 +1,24 @@ +var globalinc = 0; +function testincops(n) { + var i = 0, o = {p:0}, a = [0]; + n = 100; + + for (i = 0; i < n; i++); + while (i-- > 0); + for (i = 0; i < n; ++i); + while (--i >= 0); + + for (o.p = 0; o.p < n; o.p++) globalinc++; + while (o.p-- > 0) --globalinc; + for (o.p = 0; o.p < n; ++o.p) ++globalinc; + while (--o.p >= 0) globalinc--; + + ++i; // set to 0 + for (a[i] = 0; a[i] < n; a[i]++); + while (a[i]-- > 0); + for (a[i] = 0; a[i] < n; ++a[i]); + while (--a[i] >= 0); + + return [++o.p, ++a[i], globalinc].toString(); +} +assertEq(testincops(), "0,0,0"); diff --git a/js/src/jit-test/tests/basic/this-binding-with-eval.js b/js/src/jit-test/tests/basic/this-binding-with-eval.js new file mode 100644 index 0000000000..caeda02305 --- /dev/null +++ b/js/src/jit-test/tests/basic/this-binding-with-eval.js @@ -0,0 +1,51 @@ +function Test1() { + this.x = 8; + this.y = 5; + this.z = 2; + var o = {".this": {x: 1}}; + var res; + with (o) { + res = this.x + (() => this.z)() + eval("this.x + (() => this.y)()"); + } + assertEq(res, 23); +} +new Test1(); + +function Test2() { + this.x = 8; + var o = {".this": {x: 1}}; + with (o) { + return eval("() => this.x"); + } +} +var fun = new Test2(); +assertEq(fun(), 8); + +function Test3() { + this.x = 8; + var o = {".this": {x: 1}}; + with (o) { + assertEq(this.x, 8); + } +} +new Test3(); + +function test4() { + var o = {".this": {x: 1}}; + with (o) { + return () => this; + } +} +assertEq(test4()(), this); + +function test5() { + var o = {".this": {x: 1}}; + with (o) { + return this; + } +} +assertEq(test5(), this); + +var global = this; +evaluate("with({}) { assertEq(this, global); }"); +eval("with({}) { assertEq(this, global); }"); diff --git a/js/src/jit-test/tests/basic/throw-apply-too-many-args.js b/js/src/jit-test/tests/basic/throw-apply-too-many-args.js new file mode 100644 index 0000000000..21569c2895 --- /dev/null +++ b/js/src/jit-test/tests/basic/throw-apply-too-many-args.js @@ -0,0 +1,27 @@ +function g(a, b, c, d) {} +function f(a, b, c) +{ + arguments.length = getMaxArgs() + 1; + g.apply(this, arr); +} +let x = []; +x.length = getMaxArgs() + 1; +var args = [[5], [5], [5], [5], [5], [5], [5], [5], [5], [5], [5], x] +try +{ + for (var i = 0; i < args.length; i++) { arr = args[i]; f(); } + throw new Error("didn't throw"); +} +catch (e) +{ + assertEq(e instanceof RangeError, true, "wrong exception: " + e); +} +try +{ + for (var i = 0; i < args.length; i++) { arr = args[i]; f(); } + throw new Error("didn't throw"); +} +catch (e) +{ + assertEq(e instanceof RangeError, true, "wrong exception: " + e); +} diff --git a/js/src/jit-test/tests/basic/throw-exception-stack-location.js b/js/src/jit-test/tests/basic/throw-exception-stack-location.js new file mode 100644 index 0000000000..d3c5ea9dab --- /dev/null +++ b/js/src/jit-test/tests/basic/throw-exception-stack-location.js @@ -0,0 +1,49 @@ +function throwValue(value) { + throw value; +} + +// Test for-of loops keep the exception stack. +function testForOfLoop() { + function f() { + for (let _ of [null]) { + throwValue("exception-value"); + } + } + + let info = getExceptionInfo(f); + assertEq(info.exception, "exception-value"); + assertEq(info.stack.includes("throwValue"), true); +} +testForOfLoop(); + +// Test try-finally keep the exception stack. +function testFinally() { + function f() { + try { + throwValue("exception-value"); + } finally { + } + } + + let info = getExceptionInfo(f); + assertEq(info.exception, "exception-value"); + assertEq(info.stack.includes("throwValue"), true); +} +testFinally(); + +// Test try-catch-finally keep the exception stack. +function testCatchFinally() { + function f() { + try { + throw null; + } catch { + throwValue("exception-value"); + } finally { + } + } + + let info = getExceptionInfo(f); + assertEq(info.exception, "exception-value"); + assertEq(info.stack.includes("throwValue"), true); +} +testCatchFinally(); diff --git a/js/src/jit-test/tests/basic/throw-exception-stack.js b/js/src/jit-test/tests/basic/throw-exception-stack.js new file mode 100644 index 0000000000..729f354ea2 --- /dev/null +++ b/js/src/jit-test/tests/basic/throw-exception-stack.js @@ -0,0 +1,76 @@ +// Simple tests for getExceptionInfo behavior. +function testTestingFunction() { + let vals = [{}, 1, "foo", null, undefined]; + for (let v of vals) { + let thrower = () => { throw v; }; + let info = getExceptionInfo(thrower); + assertEq(info.exception, v); + assertEq(info.stack.includes("thrower@"), true); + } + + // Returns null if there was no exception. + assertEq(getExceptionInfo(() => 123), null); + + // OOM exceptions don't have a stack trace. + let info = getExceptionInfo(throwOutOfMemory); + assertEq(info.exception, "out of memory"); + assertEq(info.stack, null); +} +testTestingFunction(); + +/** + * Check that the expected number of stack traces are generated for a given + * global where 100 "throws" are generated + */ +function assertStacksCount(global, expectedStacksCount) { + global.evaluate("(" + function(_expectedStacksCount) { + let thrower = () => { throw 123; }; + for (let i = 0; i < 100; i++) { + let info = getExceptionInfo(thrower); + assertEq(info.exception, 123); + // NOTE: if this ever gets increased, update the tests above too! + if (i <= _expectedStacksCount) { + assertEq(info.stack.includes("thrower@"), true); + } else { + assertEq(info.stack, null); + } + } + } + `)(${expectedStacksCount})`); +} + +// Debuggee globals always get an exception stack. +function testDebuggee() { + let g = newGlobal({newCompartment: true}); + let dbg = new Debugger(g); + assertStacksCount(g, 100); +} +testDebuggee(); + +// Globals with trusted principals always get an exception stack. +function testTrustedPrincipals() { + let g = newGlobal({newCompartment: true, systemPrincipal: true}); + assertStacksCount(g, 100); +} +testTrustedPrincipals(); + +// In normal cases, a stack is captured only for the first 50 exceptions per realm. +function testNormal() { + let g = newGlobal(); + assertStacksCount(g, 50); +} +testNormal(); + +// Non debuggee with unlimited stacks capturing enabled should always get a stack. +function testEnableUnlimitedStacksCapturing() { + let dbg = new Debugger(); + let g = newGlobal(); + dbg.enableUnlimitedStacksCapturing(g); + assertStacksCount(g, 100); + + dbg.disableUnlimitedStacksCapturing(g); + assertStacksCount(g, 50); + + dbg.enableUnlimitedStacksCapturing(g); + assertStacksCount(g, 100); +} +testEnableUnlimitedStacksCapturing(); diff --git a/js/src/jit-test/tests/basic/timeout-check.js b/js/src/jit-test/tests/basic/timeout-check.js new file mode 100644 index 0000000000..ece69a2584 --- /dev/null +++ b/js/src/jit-test/tests/basic/timeout-check.js @@ -0,0 +1,14 @@ +// |jit-test| exitstatus: 6; skip-if: getBuildConfiguration("wasi") +function f(x) { + if (x === 0) + return; + f(x - 1); + f(x - 1); + f(x - 1); + f(x - 1); + f(x - 1); + f(x - 1); +} +timeout(0.1); +f(100); +assertEq(0, 1); diff --git a/js/src/jit-test/tests/basic/track-allocation-sites.js b/js/src/jit-test/tests/basic/track-allocation-sites.js new file mode 100644 index 0000000000..fb329b7002 --- /dev/null +++ b/js/src/jit-test/tests/basic/track-allocation-sites.js @@ -0,0 +1,24 @@ +// Test that we can track allocation sites. + +enableTrackAllocations(); + +const tests = [ + { name: "object literal", object: {}, line: Error().lineNumber }, + { name: "array literal", object: [], line: Error().lineNumber }, + { name: "regexp literal", object: /(two|2)\s*problems/, line: Error().lineNumber }, + { name: "new constructor", object: new function Ctor(){}, line: Error().lineNumber }, + { name: "new Object", object: new Object(), line: Error().lineNumber }, + { name: "new Array", object: new Array(), line: Error().lineNumber }, + { name: "new Date", object: new Date(), line: Error().lineNumber } +]; + +disableTrackAllocations(); + +for (let { name, object, line } of tests) { + print("Entering test: " + name); + + let allocationSite = getAllocationMetadata(object); + print(allocationSite); + + assertEq(allocationSite.line, line); +} diff --git a/js/src/jit-test/tests/basic/transplant-dom-slot2.js b/js/src/jit-test/tests/basic/transplant-dom-slot2.js new file mode 100644 index 0000000000..c4c2e8c482 --- /dev/null +++ b/js/src/jit-test/tests/basic/transplant-dom-slot2.js @@ -0,0 +1,7 @@ +// Make sure to transplant DOM_OBJECT_SLOT2 for FakeDOMObject +let source = new FakeDOMObject(); +assertEq(source.slot, 42); +let {object: target, transplant} = transplantableObject({object: source}); +transplant(this); +assertEq(source.slot, 42); +assertEq(target.slot, 42); diff --git a/js/src/jit-test/tests/basic/trees.js b/js/src/jit-test/tests/basic/trees.js new file mode 100644 index 0000000000..7638f089a1 --- /dev/null +++ b/js/src/jit-test/tests/basic/trees.js @@ -0,0 +1,10 @@ +function trees() { + var i = 0, o = [0,0,0]; + for (i = 0; i < 100; ++i) { + if ((i & 1) == 0) o[0]++; + else if ((i & 2) == 0) o[1]++; + else o[2]++; + } + return String(o); +} +assertEq(trees(), "50,25,25"); diff --git a/js/src/jit-test/tests/basic/truncateDouble.js b/js/src/jit-test/tests/basic/truncateDouble.js new file mode 100644 index 0000000000..b5c4990768 --- /dev/null +++ b/js/src/jit-test/tests/basic/truncateDouble.js @@ -0,0 +1,10 @@ + +// check correctness of truncation of doubles slightly outside the int32_t range. + +function truncate(x) { + return x | 0; +} + +assertEq(truncate(0xffffffff), -1); +assertEq(truncate(0xffffffff + 5000.5), 4999); +assertEq(truncate(-0xffffffff - 5000.5), -4999); diff --git a/js/src/jit-test/tests/basic/truthies.js b/js/src/jit-test/tests/basic/truthies.js new file mode 100644 index 0000000000..af8e6097be --- /dev/null +++ b/js/src/jit-test/tests/basic/truthies.js @@ -0,0 +1,45 @@ +load(libdir + 'andTestHelper.js'); +load(libdir + 'orTestHelper.js'); + +function source(x) { + switch (typeof x) { + case "number": + case "boolean": + return String(x); + case "undefined": + return "(void 0)"; + case "string": + return JSON.stringify(x); + case "object": + if (x === null) { + return "null"; + } + return `(${JSON.stringify(x)})`; + default: + throw new Error("not implemented: " + typeof x); + } +} + +(function () { + var opsies = ["||", "&&"]; + var falsies = [null, undefined, false, NaN, 0, ""]; + var truthies = [{}, true, 1, 42, 1/0, -1/0, "blah"]; + var boolies = [falsies, truthies]; + + for (var op of opsies) { + for (var i in boolies) { + for (var j in boolies[i]) { + var x = source(boolies[i][j]); + for (var k in boolies) { + for (var l in boolies[k]) { + var y = source(boolies[k][l]); + var prefix = (op == "||") ? "or" : "and"; + var f = new Function("return " + prefix + "TestHelper(" + x + "," + y + ",10)"); + var expected = eval(x + op + y) ? 45 : 0; + assertEq(f(), expected); + } + } + } + } + } + })(); diff --git a/js/src/jit-test/tests/basic/typeMonitorCall.js b/js/src/jit-test/tests/basic/typeMonitorCall.js new file mode 100644 index 0000000000..d80a7dc626 --- /dev/null +++ b/js/src/jit-test/tests/basic/typeMonitorCall.js @@ -0,0 +1,19 @@ + +/* Make sure we are checking argument types when going through unknown but monomorphic call sites. */ + +function foo(x) { + return x + 10; +} + +var array = [1,2,3,4,5,6,7,"eight"]; + +/* Jump through hoops to make 'f' unknown. */ +var f = this[eval("'foo'")]; + +for (var i = 0; i < array.length; i++) { + var res = f(array[i]); + if (i != 7) + assertEq(res, i + 11); + else + assertEq(res, "eight10"); +} diff --git a/js/src/jit-test/tests/basic/typeMonitorSingleton.js b/js/src/jit-test/tests/basic/typeMonitorSingleton.js new file mode 100644 index 0000000000..be01dcaeb4 --- /dev/null +++ b/js/src/jit-test/tests/basic/typeMonitorSingleton.js @@ -0,0 +1,17 @@ +// |jit-test| error: TypeError + +var x = {f:20}; + +function foo() { + for (var i = 0; i < 10; i++) + x.f; +} +foo(); + +gc(); + +// a type barrier needs to be generated for the access on x within foo, +// even though its type set is initially empty after the GC. +x = undefined; + +foo(); diff --git a/js/src/jit-test/tests/basic/typed-array-copyWithin.js b/js/src/jit-test/tests/basic/typed-array-copyWithin.js new file mode 100644 index 0000000000..0bcc0bdd72 --- /dev/null +++ b/js/src/jit-test/tests/basic/typed-array-copyWithin.js @@ -0,0 +1,214 @@ +// Bug 1021379 - Rename typed arrays' move method to copyWithin, +// fix up to ES6 semantics +// Tests for TypedArray#copyWithin + +load(libdir + "asserts.js"); + +const constructors = [ + Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array +]; + +for (var constructor of constructors) { + + assertEq(constructor.prototype.copyWithin.length, 2); + + // works with two arguments + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0, 3), + new constructor([4, 5, 3, 4, 5])); + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(1, 3), + new constructor([1, 4, 5, 4, 5])); + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(1, 2), + new constructor([1, 3, 4, 5, 5])); + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(2, 2), + new constructor([1, 2, 3, 4, 5])); + + // works with three arguments + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0, 3, 4), + new constructor([4, 2, 3, 4, 5])); + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(1, 3, 4), + new constructor([1, 4, 3, 4, 5])); + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(1, 2, 4), + new constructor([1, 3, 4, 4, 5])); + + // works with negative arguments + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0, -2), + new constructor([4, 5, 3, 4, 5])); + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0, -2, -1), + new constructor([4, 2, 3, 4, 5])); + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(-4, -3, -2), + new constructor([1, 3, 3, 4, 5])); + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(-4, -3, -1), + new constructor([1, 3, 4, 4, 5])); + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(-4, -3), + new constructor([1, 3, 4, 5, 5])); + + // throws on null/undefined values + assertThrowsInstanceOf(function() { + constructor.prototype.copyWithin.call(null, 0, 3); + }, TypeError, "Assert that copyWithin fails if this value is null"); + + assertThrowsInstanceOf(function() { + var throw42 = { valueOf: function() { throw 42; } }; + constructor.prototype.copyWithin.call(null, throw42, throw42, throw42); + }, TypeError, "Assert that copyWithin fails if this value is null"); + + assertThrowsInstanceOf(function() { + var throw42 = { valueOf: function() { throw 42; } }; + constructor.prototype.copyWithin.call(undefined, throw42, throw42, throw42); + }, TypeError, "Assert that copyWithin fails if this value is undefined"); + + assertThrowsInstanceOf(function() { + constructor.prototype.copyWithin.call(undefined, 0, 3); + }, TypeError, "Assert that copyWithin fails if this value is undefined"); + + // test with this value as string + assertThrowsInstanceOf(function() { + constructor.prototype.copyWithin.call("hello world", 0, 3); + }, TypeError, "Assert that copyWithin fails if this value is string"); + + assertThrowsInstanceOf(function() { + var throw42 = { valueOf: function() { throw 42; } }; + constructor.prototype.copyWithin.call("hello world", throw42, throw42, throw42); + }, TypeError, "Assert that copyWithin fails if this value is string"); + + // test with target > start on 2 arguments + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(3, 0), + new constructor([1, 2, 3, 1, 2])); + + // test with target > start on 3 arguments + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(3, 0, 4), + new constructor([1, 2, 3, 1, 2])); + + // test on fractional arguments + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0.2, 3.9), + new constructor([4, 5, 3, 4, 5])); + + // test with -0 + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(-0, 3), + new constructor([4, 5, 3, 4, 5])); + + // test with arguments more than this.length + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0, 7), + new constructor([1, 2, 3, 4, 5])); + + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(7, 0), + new constructor([1, 2, 3, 4, 5])); + + // test with arguments less than -this.length + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(-7, 0), + new constructor([1, 2, 3, 4, 5])); + + // test with arguments equal to -this.length + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(-5, 0), + new constructor([1, 2, 3, 4, 5])); + + // test on empty constructor + assertDeepEq(new constructor([]).copyWithin(0, 3), + new constructor([])); + + // test with target range being shorter than end - start + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(2, 1, 4), + new constructor([1, 2, 2, 3, 4])); + + // test overlapping ranges + arr = new constructor([1, 2, 3, 4, 5]); + arr.copyWithin(2, 1, 4); + assertDeepEq(arr.copyWithin(2, 1, 4), + new constructor([1, 2, 2, 2, 3])); + + // undefined as third argument + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0, 3, undefined), + new constructor([4, 5, 3, 4, 5])); + + // test that this.length is never called + arr = new constructor([0, 1, 2, 3, 5]); + Object.defineProperty(arr, "length", { + get: function () { throw new Error("length accessor called"); } + }); + arr.copyWithin(1, 3); + + var large = 10000; + + // test on a large constructor + arr = new constructor(large); + assertDeepEq(arr.copyWithin(45, 900), arr); + + // test on floating point numbers + for (var i = 0; i < large; i++) { + arr[i] = Math.random(); + } + arr.copyWithin(45, 900); + + // test on constructor of objects + for (var i = 0; i < large; i++) { + arr[i] = { num: Math.random() }; + } + arr.copyWithin(45, 900); + + // test constructor length remains same + assertEq(arr.length, large); + + // test null on third argument is handled correctly + assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0, 3, null), + new constructor([1, 2, 3, 4, 5])); + + //Any argument referenced, but not provided, has the value |undefined| + var tarray = new constructor(8); + try + { + tarray.copyWithin({ valueOf: function() { throw 42; } }); + throw new Error("expected to throw"); + } + catch (e) + { + assertEq(e, 42, "should have failed converting target to index"); + } + + function detachAndConvertTo(x) { + return { valueOf() { + detachArrayBuffer(tarray.buffer); + return x; + } }; + } + + // Detaching during argument processing triggers a TypeError. + tarray = new constructor([1, 2, 3, 4, 5]); + try + { + tarray.copyWithin(0, 3, detachAndConvertTo(4)); + throw new Error("expected to throw"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "expected throw with detached buffer during set"); + } + + // ...unless no elements are to be copied. + tarray = new constructor([1, 2, 3, 4, 5]); + assertDeepEq(tarray.copyWithin(0, 3, detachAndConvertTo(3)), + new constructor([])); + + /* // fails, unclear whether it should, disabling for now + // test with a proxy object + var handler = { + get: function(recipient, name) { + return recipient[name] + 2; + } + }; + + var p = new Proxy(new constructor([1, 2, 3, 4, 5]), handler); + + assertThrowsInstanceOf(function() { + constructor.prototype.copyWithin.call(p, 0, 3); + }, TypeError, "Assert that copyWithin fails if used with a proxy object"); + */ +} diff --git a/js/src/jit-test/tests/basic/typed-array-getprop-out-of-range.js b/js/src/jit-test/tests/basic/typed-array-getprop-out-of-range.js new file mode 100644 index 0000000000..601d9f3c55 --- /dev/null +++ b/js/src/jit-test/tests/basic/typed-array-getprop-out-of-range.js @@ -0,0 +1,11 @@ +var r = Object.prototype[0] = /a/; + +function test() +{ + for (var i = 0, sz = 9; i < sz; i++) + { + var ta = new Int8Array(); + assertEq(ta[0], undefined); + } +} +test(); diff --git a/js/src/jit-test/tests/basic/typed-array-index-out-of-range.js b/js/src/jit-test/tests/basic/typed-array-index-out-of-range.js new file mode 100644 index 0000000000..f44c7806ce --- /dev/null +++ b/js/src/jit-test/tests/basic/typed-array-index-out-of-range.js @@ -0,0 +1,169 @@ + +// Out of bounds writes on typed arrays are uneffectful for all integers. + +var x = new Int32Array(10); + +// 7.1.16 CanonicalNumericIndexString ( argument ) +function CanonicalNumericIndexString(argument) { + // Step 1. + assertEq(typeof argument, "string"); + + // Step 2. + if (argument === "-0") { + return -0; + } + + // Step 3. + var n = Number(argument); + + // Step 4. + if (String(n) !== argument) { + return undefined; + } + + // Step 5. + return n; +} + +function CanonicalIndexInRange(argument) { + return Number.isInteger(argument) && !Object.is(argument, -0) && + argument >= 0 && argument < x.length; +} + +function assertCanonicalNumericIndexString(i) { + var canonical = CanonicalNumericIndexString(i); + assertEq(canonical !== undefined, true, + `Argument ${i} is not a canonical numeric index string`); + + x[i] = 0; // Clear any previous value. + x[i] = 1; + + var expected = CanonicalIndexInRange(canonical) ? 1 : undefined; + assertEq(x[i], expected, `${i} is a canonical index string`); + + // Also test when accessing with a number instead of a string. + + x[canonical] = 0; // Clear any previous value. + x[canonical] = 2; + + // Add +0 to convert -0 to +0. + var expected = CanonicalIndexInRange(canonical + 0) ? 2 : undefined; + assertEq(x[canonical], expected, `${i} is a canonical index string`); +} + +function assertNotCanonicalNumericIndexString(i) { + assertEq(CanonicalNumericIndexString(i) === undefined, true, + `Argument ${i} is a canonical numeric index string`); + + x[i] = ""; // Clear any previous value. + x[i] = "test"; + + assertEq(x[i], "test", `${i} isn't a canonical index string`); +} + +function f() { + for (var i = -100; i < 100; i++) { + assertCanonicalNumericIndexString(String(i)); + } +} +f(); + +// INT32_MAX and UINT32_MAX are canonical numeric indices. + +assertCanonicalNumericIndexString("2147483647"); +assertCanonicalNumericIndexString("4294967295"); + +// Neither INT64_MAX nor UINT64_MAX are canonical numeric indices. + +assertNotCanonicalNumericIndexString("9223372036854775807"); +assertNotCanonicalNumericIndexString("18446744073709551615"); + +// "18446744073709552000" and "18446744073709556000" are canonical numeric indices. + +assertEq(String(18446744073709551615), "18446744073709552000"); + +assertCanonicalNumericIndexString("18446744073709552000"); +assertCanonicalNumericIndexString("18446744073709556000"); + +// Number.MAX_SAFE_INTEGER and Number.MAX_SAFE_INTEGER + 1 are canonical numeric +// indices, but Number.MAX_SAFE_INTEGER + 2 is not. + +assertEq(String(Number.MAX_SAFE_INTEGER), "9007199254740991"); + +assertCanonicalNumericIndexString("9007199254740991"); +assertCanonicalNumericIndexString("9007199254740992"); +assertNotCanonicalNumericIndexString("9007199254740993"); + +// Number.MIN_SAFE_INTEGER and Number.MIN_SAFE_INTEGER - 1 are canonical numeric +// indices, but Number.MIN_SAFE_INTEGER - 2 is not. + +assertEq(String(Number.MIN_SAFE_INTEGER), "-9007199254740991"); + +assertCanonicalNumericIndexString("-9007199254740991"); +assertCanonicalNumericIndexString("-9007199254740992"); +assertNotCanonicalNumericIndexString("-9007199254740993"); + +// -0 is a canonical numeric index. + +assertCanonicalNumericIndexString("-0"); + +// 0.1 and -0.1 are canonical numeric indices. + +assertCanonicalNumericIndexString("0.1"); +assertCanonicalNumericIndexString("-0.1"); + +// 0.10 and -0.10 aren't canonical numeric indices. + +assertNotCanonicalNumericIndexString("0.10"); +assertNotCanonicalNumericIndexString("-0.10"); + +// Number.MIN_VALUE and -Number.MIN_VALUE are canonical numeric indices. + +assertEq(String(Number.MIN_VALUE), "5e-324"); +assertEq(String(-Number.MIN_VALUE), "-5e-324"); + +assertCanonicalNumericIndexString("5e-324"); +assertCanonicalNumericIndexString("-5e-324"); + +assertNotCanonicalNumericIndexString("5E-324"); +assertNotCanonicalNumericIndexString("-5E-324"); + +// 1e2, -1e2, 1e-2, and -1e-2 aren't canonical numeric indices. + +assertNotCanonicalNumericIndexString("1e2"); +assertNotCanonicalNumericIndexString("-1e2"); +assertNotCanonicalNumericIndexString("1e+2"); +assertNotCanonicalNumericIndexString("-1e+2"); +assertNotCanonicalNumericIndexString("1e-2"); +assertNotCanonicalNumericIndexString("-1e-2"); + +assertNotCanonicalNumericIndexString("1E2"); +assertNotCanonicalNumericIndexString("-1E2"); +assertNotCanonicalNumericIndexString("1E+2"); +assertNotCanonicalNumericIndexString("-1E+2"); +assertNotCanonicalNumericIndexString("1E-2"); +assertNotCanonicalNumericIndexString("-1E-2"); + +// Number.MAX_VALUE and -Number.MAX_VALUE are canonical numeric indices. + +assertEq(String(Number.MAX_VALUE), "1.7976931348623157e+308"); +assertEq(String(-Number.MAX_VALUE), "-1.7976931348623157e+308"); + +assertCanonicalNumericIndexString("1.7976931348623157e+308"); +assertCanonicalNumericIndexString("-1.7976931348623157e+308"); + +assertNotCanonicalNumericIndexString("1.7976931348623157E+308"); +assertNotCanonicalNumericIndexString("-1.7976931348623157E+308"); + +// Infinity, -Infinity, and NaN are canonical numeric indices and are handled +// the same way as other out-of-bounds accesses. + +assertCanonicalNumericIndexString("Infinity"); +assertCanonicalNumericIndexString("-Infinity"); +assertCanonicalNumericIndexString("NaN"); + +// +Infinity, +NaN, or -NaN are not canonical numeric indices. + +assertNotCanonicalNumericIndexString("+Infinity"); +assertNotCanonicalNumericIndexString("+NaN"); +assertNotCanonicalNumericIndexString("-NaN"); diff --git a/js/src/jit-test/tests/basic/typed-array-offsets.js b/js/src/jit-test/tests/basic/typed-array-offsets.js new file mode 100644 index 0000000000..00e953edc0 --- /dev/null +++ b/js/src/jit-test/tests/basic/typed-array-offsets.js @@ -0,0 +1,11 @@ +function f(x, y) { + for (var i = 0; i < 100; i++) + assertEq(x[0], y); +} +var a = new ArrayBuffer(20); +var b = new Int32Array(a, 12, 2); +var c = new Int32Array(a, 0, 2); +b[0] = 10; +f(b, 10); +c[0] = 20; +f(c, 20); diff --git a/js/src/jit-test/tests/basic/typed-array-sealed-frozen.js b/js/src/jit-test/tests/basic/typed-array-sealed-frozen.js new file mode 100644 index 0000000000..a98d4b89c2 --- /dev/null +++ b/js/src/jit-test/tests/basic/typed-array-sealed-frozen.js @@ -0,0 +1,85 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load(libdir + "asserts.js") + +const constructors = [ + Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array +]; + +for (constructor of constructors) { + print("testing non-empty " + constructor.name); + let a = new constructor(10); + assertEq(Object.isExtensible(a), true); + assertEq(Object.isSealed(a), false); + assertEq(Object.isFrozen(a), false); + + // Should complain that it can't change attributes of indexed typed array properties. + assertThrowsInstanceOf(() => Object.seal(a), TypeError); + + // Should complain that it can't change attributes of indexed typed array properties. + assertThrowsInstanceOf(() => Object.freeze(a), TypeError); +} + +print(); + +for (constructor of constructors) { + print("testing zero-length " + constructor.name); + let a = new constructor(0); + assertEq(Object.isExtensible(a), true); + assertEq(Object.isSealed(a), false); + assertEq(Object.isFrozen(a), false); + + // Should not throw. + Object.seal(a); + Object.freeze(a); +} + +// isSealed and isFrozen should not try to build an array of all the +// property names of a typed array, since they're often especially large. +// This should not throw an allocation error. +let a = new Uint8Array(1 << 24); +Object.isSealed(a); +Object.isFrozen(a); + +for (constructor of constructors) { + print("testing extensibility " + constructor.name); + let a = new constructor(10); + + // New named properties should show up on typed arrays. + a.foo = "twelve"; + assertEq(a.foo, "twelve"); + + // New indexed properties should not show up on typed arrays. + a[20] = "twelve"; + assertEq(a[20], undefined); + + // Watch for especially large indexed properties. + a[-10 >>> 0] = "twelve"; + assertEq(a[-10 >>> 0], undefined); + + // Watch for really large indexed properties too. + a[Math.pow(2, 53)] = "twelve"; + assertEq(a[Math.pow(2, 53)], undefined); + + // Don't define old properties. + Object.defineProperty(a, 5, {value: 3}); + assertEq(a[5], 3); + + // Don't define new properties. + assertThrowsInstanceOf(() => Object.defineProperty(a, 20, {value: 3}), TypeError); + assertEq(a[20], undefined); + + // Don't delete indexed properties. + a[3] = 3; + delete a[3]; + assertEq(a[3], 3); +} diff --git a/js/src/jit-test/tests/basic/typedarray-selfhosted-cross-compartment.js b/js/src/jit-test/tests/basic/typedarray-selfhosted-cross-compartment.js new file mode 100644 index 0000000000..ee2ef412c6 --- /dev/null +++ b/js/src/jit-test/tests/basic/typedarray-selfhosted-cross-compartment.js @@ -0,0 +1,13 @@ +/* + * Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ + */ + +var global = newGlobal(); +var array = new global.Int8Array(10); + +assertEq(array.find(v => v == 1), undefined) +assertEq(array.findIndex(v => v == 0), 0) + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/jit-test/tests/basic/typeof-array.js b/js/src/jit-test/tests/basic/typeof-array.js new file mode 100644 index 0000000000..d384dd973e --- /dev/null +++ b/js/src/jit-test/tests/basic/typeof-array.js @@ -0,0 +1,9 @@ + +function typeOf(o) { + assertEq(typeof o, "object"); +} + +typeOf([]); +typeOf(new Float32Array()); +typeOf(new Int32Array()); +typeOf(new ArrayBuffer()); diff --git a/js/src/jit-test/tests/basic/typeofTest.js b/js/src/jit-test/tests/basic/typeofTest.js new file mode 100644 index 0000000000..90dadbb541 --- /dev/null +++ b/js/src/jit-test/tests/basic/typeofTest.js @@ -0,0 +1,8 @@ +function typeofTest() +{ + var values = ["hi", "hi", "hi", null, 5, 5.1, true, undefined, /foo/, typeofTest, [], {}], types = []; + for (var i = 0; i < values.length; i++) + types[i] = typeof values[i]; + return types.toString(); +} +assertEq(typeofTest(), "string,string,string,object,number,number,boolean,undefined,object,function,object,object"); diff --git a/js/src/jit-test/tests/basic/unboxint.js b/js/src/jit-test/tests/basic/unboxint.js new file mode 100644 index 0000000000..1aa4312974 --- /dev/null +++ b/js/src/jit-test/tests/basic/unboxint.js @@ -0,0 +1,8 @@ +function unboxint() { + var q = 0; + var o = [4]; + for (var i = 0; i < 100; ++i) + q = o[0] << 1; + return q; +} +assertEq(unboxint(), 8); diff --git a/js/src/jit-test/tests/basic/valuetosource.js b/js/src/jit-test/tests/basic/valuetosource.js new file mode 100644 index 0000000000..739b385056 --- /dev/null +++ b/js/src/jit-test/tests/basic/valuetosource.js @@ -0,0 +1,38 @@ +// |jit-test| --disable-tosource + +const TEST_CASES = [ + [`undefined`, "(void 0)"], + [`null`, "null"], + [`true`, "true"], + [`Symbol("abc")`, `Symbol("abc")`], + [`15`, "15"], + [`-0`, "-0"], + [`"abc"`, `"abc"`], + [`(function a() { return 1; })`, `(function a() { return 1; })`], + [`[1, 2, 3]`, `[1, 2, 3]`], + [`[1, {a: 0, b: 0}, 2]`, `[1, {a:0, b:0}, 2]`], + [`({a: [1, 2, 3]})`, `({a:[1, 2, 3]})`], + [`new Error("msg", "file", 1)`, `(new Error("msg", "file", 1))`], + [`new TypeError("msg", "file", 1)`, `(new TypeError("msg", "file", 1))`], + [`new class X extends Error { + constructor() { + super("msg", "file", 1); + this.name = "X"; + } + }`, `(new X("msg", "file", 1))`], + [`/a(b)c/`, `/a(b)c/`], + [`/abc/gi`, `/abc/gi`], + [`new Boolean(false)`, `new Boolean(false)`], + [`Object(false)`, `new Boolean(false)`], + [`new String("abc")`, `new String("abc")`], + [`Object("abc")`, `new String("abc")`], + [`new Number(42)`, `new Number(42)`], + [`Object(42)`, `new Number(42)`], + [`new Date(1579447335)`, `new Date(1579447335)`], +] + +let g = newGlobal({newCompartment: true}); +for (let [actual, expected] of TEST_CASES) { + assertEq(valueToSource(eval(actual)), expected); + assertEq(valueToSource(g.eval(actual)), expected); +} diff --git a/js/src/jit-test/tests/basic/weird-scopechains.js b/js/src/jit-test/tests/basic/weird-scopechains.js new file mode 100644 index 0000000000..c992f315bb --- /dev/null +++ b/js/src/jit-test/tests/basic/weird-scopechains.js @@ -0,0 +1,31 @@ +function checkNameLookup() { + return "global"; +} + +function assertWithMessage(got, expected, message) { + assertEq(message + ": " + got, message + ": " + expected); +} + +var obj = { + checkNameLookup: function() { + return "local"; + }, + + checkThisBinding: function() { + return this.checkNameLookup(); + }, +}; + +evaluate("(" + function() { + assertWithMessage(checkNameLookup(), "local", "nameLookup"); + assertWithMessage(checkThisBinding(), "local", "thisBinding"); + + // Important: lambda needs to close over "reason", so it won't just get the + // scope of testFunc as its scope. Instead it'll get the Call object + // "reason" lives in. + var reason = " in lambda in Call"; + (function() { + assertWithMessage(checkNameLookup(), "local", "nameLookup" + reason); + assertWithMessage(checkThisBinding(), "local", "thisBinding" + reason); + })(); +} + ")()", {envChainObject: obj}); diff --git a/js/src/jit-test/tests/basic/withSourceHook.js b/js/src/jit-test/tests/basic/withSourceHook.js new file mode 100644 index 0000000000..5df79c9721 --- /dev/null +++ b/js/src/jit-test/tests/basic/withSourceHook.js @@ -0,0 +1,53 @@ +// |jit-test| skip-if: typeof withSourceHook !== 'function' + +// Check that withSourceHook passes URLs, propagates exceptions, and +// properly restores the original source hooks. + +load(libdir + 'asserts.js'); + +var log = ''; + +// Establish an outermost source hook. +withSourceHook(function (url) { + log += 'o'; + assertEq(url, 'outer'); + return '(function outer() { 3; })'; +}, function () { + log += 'O'; + // Verify that withSourceHook propagates exceptions thrown by source hooks. + assertThrowsValue(function () { + // Establish a source hook that throws. + withSourceHook(function (url) { + log += 'm'; + assertEq(url, 'middle'); + throw 'borborygmus'; // middle + }, function () { + log += 'M'; + // Establish an innermost source hook that does not throw, + // and verify that it is in force. + assertEq(withSourceHook(function (url) { + log += 'i'; + assertEq(url, 'inner'); + return '(function inner() { 1; })'; + }, function () { + log += 'I'; + return evaluate('(function inner() { 2; })', + { fileName: 'inner', sourceIsLazy: true }) + .toString(); + }), + 'function inner() { 1; }'); + // Verify that the source hook that throws has been reinstated. + evaluate('(function middle() { })', + { fileName: 'middle', sourceIsLazy: true }) + .toString(); + }); + }, 'borborygmus'); + + // Verify that the outermost source hook has been restored. + assertEq(evaluate('(function outer() { 4; })', + { fileName: 'outer', sourceIsLazy: true }) + .toString(), + 'function outer() { 3; }'); +}); + +assertEq(log, 'OMIimo'); diff --git a/js/src/jit-test/tests/basic/wrapping-dead-wrapper.js b/js/src/jit-test/tests/basic/wrapping-dead-wrapper.js new file mode 100644 index 0000000000..406fdaa172 --- /dev/null +++ b/js/src/jit-test/tests/basic/wrapping-dead-wrapper.js @@ -0,0 +1,9 @@ +// Make sure the wrapper machinery returns a dead wrapper instead of a CCW when +// attempting to wrap a dead wrapper. +var g1 = newGlobal({newCompartment: true}); +var g2 = newGlobal({newCompartment: true}); +var wrapper = g1.Math; +nukeCCW(wrapper); +assertEq(isSameCompartment(wrapper, this), true); +g2.wrapper = wrapper; +g2.eval("assertEq(isSameCompartment(wrapper, this), true)"); diff --git a/js/src/jit-test/tests/basic/write-frozen-dense-strict-inlinecache.js b/js/src/jit-test/tests/basic/write-frozen-dense-strict-inlinecache.js new file mode 100644 index 0000000000..abb620c6eb --- /dev/null +++ b/js/src/jit-test/tests/basic/write-frozen-dense-strict-inlinecache.js @@ -0,0 +1,20 @@ +// |jit-test| --no-threads; --ion-eager; +setJitCompilerOption('ion.forceinlineCaches', 1); +function foo(t) { + "use strict"; + var stop; + do { + let ok = false; + stop = inIon(); + try { + t[0] = 2; + } catch(e) { + ok = true; + } + assertEq(ok, true); + } while (!stop); +} +var t = [4]; +Object.freeze(t); +foo(t); +foo(t); diff --git a/js/src/jit-test/tests/basic/write-frozen-dense-strict.js b/js/src/jit-test/tests/basic/write-frozen-dense-strict.js new file mode 100644 index 0000000000..9ee6b6c6dc --- /dev/null +++ b/js/src/jit-test/tests/basic/write-frozen-dense-strict.js @@ -0,0 +1,14 @@ +"use strict"; +var t = [4]; +var stop; +Object.freeze(t); +do { + let ok = false; + stop = inIon(); + try { + t[0] = 2; + } catch(e) { + ok = true; + } + assertEq(ok, true); +} while (!stop); diff --git a/js/src/jit-test/tests/basic/write-frozen-dense.js b/js/src/jit-test/tests/basic/write-frozen-dense.js new file mode 100644 index 0000000000..7e09c330b0 --- /dev/null +++ b/js/src/jit-test/tests/basic/write-frozen-dense.js @@ -0,0 +1,8 @@ +var t = [4]; +var stop; +Object.freeze(t); +do { + stop = inIon(); + t[0] = 2; + assertEq(t[0], 4); +} while (!stop); diff --git a/js/src/jit-test/tests/basic/write-frozen-property-strict.js b/js/src/jit-test/tests/basic/write-frozen-property-strict.js new file mode 100644 index 0000000000..c9c4027612 --- /dev/null +++ b/js/src/jit-test/tests/basic/write-frozen-property-strict.js @@ -0,0 +1,14 @@ +function foo(x) { + "use strict"; + var ok = false; + try { + x.a = 10; + } catch(e) { + ok = true; + } + assertEq(ok, true); + assertEq(x.a, 0); +} +x = {a:0,b:1}; +Object.freeze(x); +foo(x); diff --git a/js/src/jit-test/tests/basic/write-frozen-property.js b/js/src/jit-test/tests/basic/write-frozen-property.js new file mode 100644 index 0000000000..a6228fbb00 --- /dev/null +++ b/js/src/jit-test/tests/basic/write-frozen-property.js @@ -0,0 +1,7 @@ +function foo(x) { + x.a = 10; + assertEq(x.a, 0); +} +x = {a:0,b:1}; +Object.freeze(x); +foo(x); diff --git a/js/src/jit-test/tests/basic/xml-in-strict.js b/js/src/jit-test/tests/basic/xml-in-strict.js new file mode 100644 index 0000000000..0e2ddf89b5 --- /dev/null +++ b/js/src/jit-test/tests/basic/xml-in-strict.js @@ -0,0 +1,17 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function checkSyntaxError(code) { + var error; + try { + eval(code); + } catch (e) { + error = e; + } + assertEq(error.name, 'SyntaxError'); +} + +checkSyntaxError('"use strict"; *'); +checkSyntaxError('"use strict"; @7'); diff --git a/js/src/jit-test/tests/basic/xprop.js b/js/src/jit-test/tests/basic/xprop.js new file mode 100644 index 0000000000..9fdbb66637 --- /dev/null +++ b/js/src/jit-test/tests/basic/xprop.js @@ -0,0 +1,8 @@ +function xprop() +{ + a = 0; + for (var i = 0; i < 20; i++) + a += 7; + return a; +} +assertEq(xprop(), 140); |