diff options
Diffstat (limited to 'js/src/jit-test/tests/arguments')
246 files changed, 6956 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/arguments/access-formals.js b/js/src/jit-test/tests/arguments/access-formals.js new file mode 100644 index 0000000000..a63098500c --- /dev/null +++ b/js/src/jit-test/tests/arguments/access-formals.js @@ -0,0 +1,44 @@ +function g1(x, args) { + args[0] = 88; +} + +// We assume we can optimize arguments access in |f|. +// +// Then the apply-call invalidates the arguments optimization, +// and creates a real arguments object. +// +// Test that x and y fetch the values from the args object when +// that happens. +function f1(x, y, o) { + var res = 0; + for (var i=0; i<50; i++) { + res += x + y; + if (i > 10) + o.apply(null, arguments); + } + return res; +} + +var o1 = {apply: g1}; +assertEq(f1(3, 5, o1), 3630); +assertEq(f1(3, 5, o1), 3630); + +// In strict mode, the arguments object does not alias formals. +function g2(x, args) { + args[0] = 88; +} + +function f2(x, y, o) { + "use strict"; + var res = 0; + for (var i=0; i<50; i++) { + res += x + y; + if (i > 10) + o.apply(null, arguments); + } + return res; +} + +var o2 = {apply: g2}; +assertEq(f2(3, 5, o2), 400); +assertEq(f2(3, 5, o2), 400); diff --git a/js/src/jit-test/tests/arguments/alias-function-closed.js b/js/src/jit-test/tests/arguments/alias-function-closed.js new file mode 100644 index 0000000000..ba91cc6f66 --- /dev/null +++ b/js/src/jit-test/tests/arguments/alias-function-closed.js @@ -0,0 +1,167 @@ +function f1(a, aIs, // without default parameter + b=()=>62, bIs, // with default parameter + // before function body + c=(assertEq(a(), aIs), assertEq(b(), bIs), + ()=>63), + cIs) { + // before function declarations + assertEq(a(), 52); + assertEq(b(), 53); + assertEq(c(), 55); + + function a() { + return 52; + } + function c() { + return 54; + } + function g() { + // close here + assertEq(a(), 52); // after function declaration + assertEq(b(), 53); // before function declaration + assertEq(c(), 55); // before last function declaration + } + // function declaration after closed + function b() { + return 53; + } + + assertEq(a(), 52); // after function declaration + assertEq(b(), 53); // after function declaration + assertEq(c(), 55); // before last function declaration + + g(); + c = ()=>72; + assertEq(c(), 72); // after assignment in body + h(); + assertEq(c(), 82); // after assignment in closed function + + function h() { + assertEq(c(), 72); // after assignment in body + c = ()=>82; + assertEq(c(), 82); // after assignment in closed function + } + // function re-declaration after closed and assignment + function c() { + return 55; + } +} +f1(()=>42, 42, undefined, 62, undefined, 63); +f1(()=>42, 42, undefined, 62, ()=>44, 44); +f1(()=>42, 42, ()=>43, 43, undefined, 63); +f1(()=>42, 42, ()=>43, 43, ()=>44, 44); + +function f2(a, aIs, + // call before body + b=(function() { assertEq(a(), aIs); })(), + // a inside body not accessible from defaults + c=function() { assertEq(a(), 42); }) { + function a() { + return 52; + } + function g() { + // close here + assertEq(a(), 52); + } + + assertEq(a(), 52); + g(); + c(); +} +f2(()=>42, 42); + +function f3(a, aIs, + // call before body + // close here + b=(function() { assertEq(a(), aIs); })(), + // a inside body not accessible from defaults + c=function() { assertEq(a(), 42); }) { + function a() { + return 52; + } + + assertEq(a(), 52); + c(); +} +f3(()=>42, 42); + +function f4(a, + // assignment before body + b=a=()=>62, + c=(assertEq(a(), 62)), + e=(assertEq(a(), 62))) { + function a() { + return 52; + } + function g() { + // close here + assertEq(a(), 52); + } + + assertEq(a(), 52); + g(); +} +f4(()=>42); + +function f5(a, b, c, d) { + // before var/function declarations + assertEq(a(), 52); + assertEq(b(), 53); + assertEq(c(), 54); + assertEq(d(), 55); + + function g() { + // before var/function declarations, called after var declarations + // close here + assertEq(a(), 52); + assertEq(b(), 63); + assertEq(c(), 54); + assertEq(d(), 65); + } + + var a, b = ()=>63; + var c, d = ()=>65; + + // after var declarations, before function declarations + assertEq(a(), 52); + assertEq(b(), 63); + assertEq(c(), 54); + assertEq(d(), 65); + + function h() { + // after var declarations, before function declarations + assertEq(a(), 52); + assertEq(b(), 63); + assertEq(c(), 54); + assertEq(d(), 65); + } + function a() { + return 52; + } + function b() { + return 53; + } + function c() { + return 54; + } + function d() { + return 55; + } + function i() { + // after var/function declarations + assertEq(a(), 52); + assertEq(b(), 63); + assertEq(c(), 54); + assertEq(d(), 65); + } + + // after var/function declarations + assertEq(a(), 52); + assertEq(b(), 63); + assertEq(c(), 54); + assertEq(d(), 65); + g(); + h(); + i(); +} +f5(()=>42, ()=>43, ()=>44, ()=>45); diff --git a/js/src/jit-test/tests/arguments/alias-function-not-closed.js b/js/src/jit-test/tests/arguments/alias-function-not-closed.js new file mode 100644 index 0000000000..3de71f7c8e --- /dev/null +++ b/js/src/jit-test/tests/arguments/alias-function-not-closed.js @@ -0,0 +1,87 @@ +function f1(a, aIs, // without default parameter + b=()=>62, bIs, // with default parameter + // before function body + c=(assertEq(a(), aIs), assertEq(b(), bIs), + ()=>63), + cIs) { + // before function declarations + assertEq(a(), 52); + assertEq(b(), 53); + assertEq(c(), 55); + + function a() { + return 52; + } + function b() { + return 53; + } + function c() { + return 54; + } + + assertEq(a(), 52); // after function declaration + assertEq(b(), 53); // after function declaration + assertEq(c(), 55); // before last function declaration + + c = ()=>72; + assertEq(c(), 72); // after assignment in body + + // function re-declaration after assignment + function c() { + return 55; + } +} +f1(()=>42, 42, undefined, 62, undefined, 63); +f1(()=>42, 42, undefined, 62, ()=>44, 44); +f1(()=>42, 42, ()=>43, 43, undefined, 63); +f1(()=>42, 42, ()=>43, 43, ()=>44, 44); + +function f2(a, + // assignment before body + b=a=()=>62, + c=(assertEq(a(), 62)), + e=(assertEq(a(), 62))) { + function a() { + return 52; + } + + assertEq(a(), 52); +} +f2(()=>42); + +function f3(a, b, c, d) { + // before var/function declarations + assertEq(a(), 52); + assertEq(b(), 53); + assertEq(c(), 54); + assertEq(d(), 55); + + var a, b = ()=>63; + var c, d = ()=>65; + + // after var declarations, before function declarations + assertEq(a(), 52); + assertEq(b(), 63); + assertEq(c(), 54); + assertEq(d(), 65); + + function a() { + return 52; + } + function b() { + return 53; + } + function c() { + return 54; + } + function d() { + return 55; + } + + // after var/function declarations + assertEq(a(), 52); + assertEq(b(), 63); + assertEq(c(), 54); + assertEq(d(), 65); +} +f3(()=>42, ()=>43, ()=>44, ()=>45); diff --git a/js/src/jit-test/tests/arguments/apply-args-obj-01.js b/js/src/jit-test/tests/arguments/apply-args-obj-01.js new file mode 100644 index 0000000000..586787f963 --- /dev/null +++ b/js/src/jit-test/tests/arguments/apply-args-obj-01.js @@ -0,0 +1,18 @@ +function escape(x) { with ({}) {} } + +function foo() { + escape(arguments); + return bar.apply({}, arguments); +} + +function bar(x,y) { + return x + y; +} + +with ({}) {} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 300); diff --git a/js/src/jit-test/tests/arguments/apply-args-obj-02.js b/js/src/jit-test/tests/arguments/apply-args-obj-02.js new file mode 100644 index 0000000000..f619309818 --- /dev/null +++ b/js/src/jit-test/tests/arguments/apply-args-obj-02.js @@ -0,0 +1,16 @@ +function foo() { + arguments[0] = 3; + return bar.apply({}, arguments); +} + +function bar(x,y) { + return x + y; +} + +with ({}) {} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 500); diff --git a/js/src/jit-test/tests/arguments/apply-args-obj-03.js b/js/src/jit-test/tests/arguments/apply-args-obj-03.js new file mode 100644 index 0000000000..03fe82f683 --- /dev/null +++ b/js/src/jit-test/tests/arguments/apply-args-obj-03.js @@ -0,0 +1,20 @@ +function escape() { with ({}) {} } + +function foo(i) { + return i; +} + +function bar(n) { + escape(arguments); + return foo.apply({}, arguments); +} + +function baz(a, n) { + return bar(n); +} + +var sum = 0; +for (var i = 0; i < 10000; i++) { + sum += baz(0, 1); +} +assertEq(sum, 10000); diff --git a/js/src/jit-test/tests/arguments/apply-args-obj-04.js b/js/src/jit-test/tests/arguments/apply-args-obj-04.js new file mode 100644 index 0000000000..2a1e8b098e --- /dev/null +++ b/js/src/jit-test/tests/arguments/apply-args-obj-04.js @@ -0,0 +1,21 @@ +var result; + +function g(a, b) { + with ({}) {} + result = a + b; +} + +function escape() { with({}) {} } + +function f() { + escape(arguments); + for (var i = 0; i < 50; ++i) { + g.apply(this, arguments); + } +} + +f(1, 2); +assertEq(result, 3); + +f(""); +assertEq(result, "undefined"); diff --git a/js/src/jit-test/tests/arguments/apply-closed-over-arguments-strict.js b/js/src/jit-test/tests/arguments/apply-closed-over-arguments-strict.js new file mode 100644 index 0000000000..71565cde94 --- /dev/null +++ b/js/src/jit-test/tests/arguments/apply-closed-over-arguments-strict.js @@ -0,0 +1,15 @@ +'use strict' +function bar(x,y) { + return x + y; +} + +function foo(x, y) { + function closeOver() { return x; } + return bar.apply({}, arguments); +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 300) diff --git a/js/src/jit-test/tests/arguments/apply-closed-over-arguments.js b/js/src/jit-test/tests/arguments/apply-closed-over-arguments.js new file mode 100644 index 0000000000..708d4cdb09 --- /dev/null +++ b/js/src/jit-test/tests/arguments/apply-closed-over-arguments.js @@ -0,0 +1,14 @@ +function bar(x,y) { + return x + y; +} + +function foo(x, y) { + function closeOver() { return x; } + return bar.apply({}, arguments); +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 300) diff --git a/js/src/jit-test/tests/arguments/apply-redefine-length.js b/js/src/jit-test/tests/arguments/apply-redefine-length.js new file mode 100644 index 0000000000..4dd5cb68d7 --- /dev/null +++ b/js/src/jit-test/tests/arguments/apply-redefine-length.js @@ -0,0 +1,18 @@ +function foo() { + arguments.length = 2; + return bar.apply({}, arguments); +} + +function bar() { + var result = 0; + for (var x of arguments) { + result += x; + } + return result; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2,3,4,5,6); +} +assertEq(sum,300); diff --git a/js/src/jit-test/tests/arguments/args-attributes.js b/js/src/jit-test/tests/arguments/args-attributes.js new file mode 100644 index 0000000000..5182202371 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-attributes.js @@ -0,0 +1,75 @@ +function strictArgs() { + return (function (a, b, c) {'use strict'; return arguments; })(1, 2); +} + +function normalArgs() { + return (function (a, b, c) { return arguments; })(1, 2); +} + +function checkProperty(options, prop, shouldThrow) { + var desc, orig; + var obj = options.strict ? strictArgs() : normalArgs(); + var objType = options.strict ? "strict arguments." : "normal arguments."; + + function check() { + orig = Object.getOwnPropertyDescriptor(obj, prop); + + var threw = false; + try { + obj[prop] = obj[prop]; + } + catch (e) { + threw = true; + } + assertEq(threw, shouldThrow, objType + prop + " threw"); + + if (orig === undefined) { + // The property wasn't defined, so we can skip it. + return; + } + + desc = Object.getOwnPropertyDescriptor(obj, prop); + if ("value" in orig) { + assertEq(desc.value, orig.value, objType + prop + " value"); + } else { + assertEq(desc.get, orig.get, objType + prop + " get"); + assertEq(desc.set, orig.set, objType + prop + " set"); + } + assertEq(desc.writable, orig.writable, objType + prop + " writable"); + assertEq(desc.enumerable, orig.enumerable, objType + prop + " enumerable"); + assertEq(desc.configurable, orig.configurable, objType + prop + " configurable"); + } + + check(); + + if (orig && orig.configurable) { + if(options.refresh) { obj = options.strict ? strictArgs() : normalArgs(); } + Object.defineProperty(obj, prop, {writable: false, enumerable: true}); + check(); + + if(options.refresh) { obj = options.strict ? strictArgs() : normalArgs(); } + Object.defineProperty(obj, prop, {writable: true, enumerable: false}); + check(); + + if(options.refresh) { obj = options.strict ? strictArgs() : normalArgs(); } + Object.defineProperty(obj, prop, {writable: false, configurable: false}); + check(); + } +} + +checkProperty({strict: true, refresh: true}, 'callee', true); +checkProperty({strict: true, refresh: false}, 'callee', true); +checkProperty({strict: false, refresh: true}, 'callee', false); +checkProperty({strict: false, refresh: false}, 'callee', false); + +checkProperty({strict: true, refresh: true}, 'length', false); +checkProperty({strict: true, refresh: false}, 'length', false); +checkProperty({strict: false, refresh: true}, 'length', false); +checkProperty({strict: false, refresh: false}, 'length', false); + +for (var i = 0; i <= 5; i++) { + checkProperty({strict: true, refresh: true}, "" + i, false); + checkProperty({strict: true, refresh: false}, "" + i, false); + checkProperty({strict: false, refresh: true}, "" + i, false); + checkProperty({strict: false, refresh: false}, "" + i, false); +} diff --git a/js/src/jit-test/tests/arguments/args-createontrace.js b/js/src/jit-test/tests/arguments/args-createontrace.js new file mode 100644 index 0000000000..9f9f0a4082 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-createontrace.js @@ -0,0 +1,18 @@ +actual = ''; +expected = '5,4,3,2,1,X,5,4,3,2,1,Y,5,4,3,2,1,'; + +function f() { + for (var i = 0; i < 5; ++i) { + var args = arguments; + appendToActual(args[i]); + } +} + +f(5, 4, 3, 2, 1); +appendToActual("X"); +f(5, 4, 3, 2, 1); +appendToActual("Y"); +f(5, 4, 3, 2, 1); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args-exists-own.js b/js/src/jit-test/tests/arguments/args-exists-own.js new file mode 100644 index 0000000000..937c26608e --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-exists-own.js @@ -0,0 +1,109 @@ +// Test |Object.hasOwn| on arguments objects. + +function testBasic() { + function arg0() { return Object.hasOwn(arguments, 0); } + function arg1() { return Object.hasOwn(arguments, 1); } + function arg100() { return Object.hasOwn(arguments, 100); } + function argn1() { return Object.hasOwn(arguments, -1); } + function argv(i) { return Object.hasOwn(arguments, i); } + + for (let i = 0; i < 100; ++i) { + assertEq(arg0(), false); + assertEq(arg0(1), true); + assertEq(arg0(1, 2), true); + assertEq(arg0(1, 2, 3), true); + assertEq(arg0(1, 2, 3, 4), true); + assertEq(arg0(1, 2, 3, 4, 5), true); + + assertEq(arg1(), false); + assertEq(arg1(1), false); + assertEq(arg1(1, 2), true); + assertEq(arg1(1, 2, 3), true); + assertEq(arg1(1, 2, 3, 4), true); + assertEq(arg1(1, 2, 3, 4, 5), true); + + assertEq(arg100(), false); + assertEq(arg100(1), false); + assertEq(arg100(1, 2), false); + assertEq(arg100(1, 2, 3), false); + assertEq(arg100(1, 2, 3, 4), false); + assertEq(arg100(1, 2, 3, 4, 5), false); + + assertEq(argn1(), false); + assertEq(argn1(1), false); + assertEq(argn1(1, 2), false); + assertEq(argn1(1, 2, 3), false); + assertEq(argn1(1, 2, 3, 4), false); + assertEq(argn1(1, 2, 3, 4, 5), false); + + assertEq(argv(i & 3), (i&3) <= 0); + assertEq(argv(i & 3, 1), (i&3) <= 1); + assertEq(argv(i & 3, 1, 2), (i&3) <= 2); + assertEq(argv(i & 3, 1, 2, 3), true); + assertEq(argv(i & 3, 1, 2, 3, 4), true); + assertEq(argv(i & 3, 1, 2, 3, 4, 5), true); + } +} +testBasic(); + +// Modifying |arguments.length| doesn't change the result. +function testOverriddenLength() { + function f(i) { + if (i === 100) { + arguments.length = 100; + } + return Object.hasOwn(arguments, 1); + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i), false); + } +} +testOverriddenLength(); + +// Overridden elements are correctly detected. +function testOverriddenElement() { + function f(i) { + if (i === 100) { + arguments[1] = 0; + } + return Object.hasOwn(arguments, 1); + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i), i === 100); + } +} +testOverriddenElement(); + +// Deleted elements are correctly detected. +function testDeletedElement() { + function f(i) { + if (i === 100) { + delete arguments[0]; + } + return Object.hasOwn(arguments, 0); + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i), i !== 100); + } +} +testDeletedElement(); + +// Contrary to most other arguments object optimisations, forwarded arguments +// don't inhibit optimising |Object.hasOwn|. +function testForwardedArg() { + function f(i) { + function closedOver() { + if (i === 100) i = 0; + } + closedOver(); + return Object.hasOwn(arguments, 0); + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i), true); + } +} +testForwardedArg(); diff --git a/js/src/jit-test/tests/arguments/args-exists.js b/js/src/jit-test/tests/arguments/args-exists.js new file mode 100644 index 0000000000..35ea8e20bb --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-exists.js @@ -0,0 +1,109 @@ +// Test |in| operator on arguments objects. + +function testBasic() { + function arg0() { return 0 in arguments; } + function arg1() { return 1 in arguments; } + function arg100() { return 100 in arguments; } + function argn1() { return -1 in arguments; } + function argv(i) { return i in arguments; } + + for (let i = 0; i < 100; ++i) { + assertEq(arg0(), false); + assertEq(arg0(1), true); + assertEq(arg0(1, 2), true); + assertEq(arg0(1, 2, 3), true); + assertEq(arg0(1, 2, 3, 4), true); + assertEq(arg0(1, 2, 3, 4, 5), true); + + assertEq(arg1(), false); + assertEq(arg1(1), false); + assertEq(arg1(1, 2), true); + assertEq(arg1(1, 2, 3), true); + assertEq(arg1(1, 2, 3, 4), true); + assertEq(arg1(1, 2, 3, 4, 5), true); + + assertEq(arg100(), false); + assertEq(arg100(1), false); + assertEq(arg100(1, 2), false); + assertEq(arg100(1, 2, 3), false); + assertEq(arg100(1, 2, 3, 4), false); + assertEq(arg100(1, 2, 3, 4, 5), false); + + assertEq(argn1(), false); + assertEq(argn1(1), false); + assertEq(argn1(1, 2), false); + assertEq(argn1(1, 2, 3), false); + assertEq(argn1(1, 2, 3, 4), false); + assertEq(argn1(1, 2, 3, 4, 5), false); + + assertEq(argv(i & 3), (i&3) <= 0); + assertEq(argv(i & 3, 1), (i&3) <= 1); + assertEq(argv(i & 3, 1, 2), (i&3) <= 2); + assertEq(argv(i & 3, 1, 2, 3), true); + assertEq(argv(i & 3, 1, 2, 3, 4), true); + assertEq(argv(i & 3, 1, 2, 3, 4, 5), true); + } +} +testBasic(); + +// Modifying |arguments.length| doesn't change the result. +function testOverriddenLength() { + function f(i) { + if (i === 100) { + arguments.length = 100; + } + return 1 in arguments; + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i), false); + } +} +testOverriddenLength(); + +// Overridden elements are correctly detected. +function testOverriddenElement() { + function f(i) { + if (i === 100) { + arguments[1] = 0; + } + return 1 in arguments; + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i), i === 100); + } +} +testOverriddenElement(); + +// Deleted elements are correctly detected. +function testDeletedElement() { + function f(i) { + if (i === 100) { + delete arguments[0]; + } + return 0 in arguments; + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i), i !== 100); + } +} +testDeletedElement(); + +// Contrary to most other arguments object optimisations, forwarded arguments +// don't inhibit optimising the |in| operator. +function testForwardedArg() { + function f(i) { + function closedOver() { + if (i === 100) i = 0; + } + closedOver(); + return 0 in arguments; + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i), true); + } +} +testForwardedArg(); diff --git a/js/src/jit-test/tests/arguments/args-mochi-2.js b/js/src/jit-test/tests/arguments/args-mochi-2.js new file mode 100644 index 0000000000..4fec2dd9b0 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-mochi-2.js @@ -0,0 +1,23 @@ +actual = ''; +expected = 'true,'; + +var isNotEmpty = function (args, i) { + var o = args[i]; + if (!(o && o.length)) { + return false; + } + return true; +}; + +var f = function(obj) { + for (var i = 0; i < arguments.length; i++) { + if (!isNotEmpty(arguments, i)) + return false; + } + return true; +} + +appendToActual(f([1], [1], [1], "asdf", [1])); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args-mochi-2a.js b/js/src/jit-test/tests/arguments/args-mochi-2a.js new file mode 100644 index 0000000000..5c8895b15a --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-mochi-2a.js @@ -0,0 +1,23 @@ +actual = ''; +expected = 'true,'; + +function isNotEmpty(args, i) { + var o = args[i]; + if (!(o && o.length)) { + return false; + } + return true; +}; + +function f(obj) { + for (var i = 0; i < arguments.length; i++) { + if (!isNotEmpty(arguments, i)) + return false; + } + return true; +} + +appendToActual(f([1], [1], [1], "asdf", [1])); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args-mochi.js b/js/src/jit-test/tests/arguments/args-mochi.js new file mode 100644 index 0000000000..c477ef0972 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-mochi.js @@ -0,0 +1,17 @@ +actual = ''; +expected = 'true,'; + +var isNotEmpty = function (obj) { + for (var i = 0; i < arguments.length; i++) { + var o = arguments[i]; + if (!(o && o.length)) { + return false; + } + } + return true; +}; + +appendToActual(isNotEmpty([1], [1], [1], "asdf", [1])); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args-mutate-length-1.js b/js/src/jit-test/tests/arguments/args-mutate-length-1.js new file mode 100644 index 0000000000..cea55bc36a --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-mutate-length-1.js @@ -0,0 +1,16 @@ +actual = ''; +expected = '0,0,0,'; + +function f() { + arguments.length--; + for (var i = 0; i < arguments.length; ++i) { + appendToActual(i); + } +} + +f(1, 2); +f(1, 2); +f(2, 2); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args-mutate-length-2.js b/js/src/jit-test/tests/arguments/args-mutate-length-2.js new file mode 100644 index 0000000000..1db881b423 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-mutate-length-2.js @@ -0,0 +1,15 @@ +actual = ''; +expected = '0,1,0,1,0,1,'; + +function f() { + for (var i = 0; i < arguments.length; ++i) { + appendToActual(i); + } +} + +f(1, 2); +f(1, 2); +f(2, 2); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args-mutate-proto-1.js b/js/src/jit-test/tests/arguments/args-mutate-proto-1.js new file mode 100644 index 0000000000..fc3b8c5b23 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-mutate-proto-1.js @@ -0,0 +1,15 @@ +function outOfBounds() { + var proto = ["pass"]; + + var N = 100; + for (var i = 0; i <= N; ++i) { + if (i === N) { + Object.setPrototypeOf(arguments, proto); + } + + var arg = arguments[0]; + + assertEq(arg, i !== N ? undefined : "pass"); + } +} +outOfBounds(); diff --git a/js/src/jit-test/tests/arguments/args-mutate-proto-2.js b/js/src/jit-test/tests/arguments/args-mutate-proto-2.js new file mode 100644 index 0000000000..9645f88090 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-mutate-proto-2.js @@ -0,0 +1,16 @@ +function outOfBounds() { + var proto = []; + Object.setPrototypeOf(arguments, proto); + + var N = 100; + for (var i = 0; i <= N; ++i) { + if (i === N) { + proto[0] = "pass"; + } + + var arg = arguments[0]; + + assertEq(arg, i !== N ? undefined : "pass"); + } +} +outOfBounds(); diff --git a/js/src/jit-test/tests/arguments/args-mutate-proto-3.js b/js/src/jit-test/tests/arguments/args-mutate-proto-3.js new file mode 100644 index 0000000000..ccfb924dec --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-mutate-proto-3.js @@ -0,0 +1,15 @@ +function outOfBounds() { + Object.setPrototypeOf(arguments, Array.prototype); + + var N = 100; + for (var i = 0; i <= N; ++i) { + if (i === N) { + Array.prototype[0] = "pass"; + } + + var arg = arguments[0]; + + assertEq(arg, i !== N ? undefined : "pass"); + } +} +outOfBounds(); diff --git a/js/src/jit-test/tests/arguments/args-mutate-proto-4.js b/js/src/jit-test/tests/arguments/args-mutate-proto-4.js new file mode 100644 index 0000000000..d971669ca8 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-mutate-proto-4.js @@ -0,0 +1,13 @@ +function outOfBounds() { + var N = 100; + for (var i = 0; i <= N; ++i) { + if (i === N) { + Object.prototype[0] = "pass"; + } + + var arg = arguments[0]; + + assertEq(arg, i !== N ? undefined : "pass"); + } +} +outOfBounds(); diff --git a/js/src/jit-test/tests/arguments/args-range-2.js b/js/src/jit-test/tests/arguments/args-range-2.js new file mode 100644 index 0000000000..393d574df5 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-range-2.js @@ -0,0 +1,37 @@ +actual = ''; +expected = "undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,"; + +var index; + +function h() { + for (var i = 0; i < 5; ++i) { + var a = arguments; + appendToActual(a[index]); + } +} + +index = 0; +h(); +index = -1; +h(); +index = 1; +h(); + +index = -9999999; +h(1, 2, 3); +index = -1; +h(1, 2, 3); +index = 0; +h(1, 2, 3); +index = 1; +h(1, 2, 3); +index = 2; +h(1, 2, 3); +index = 3; +h(1, 2, 3); +index = 4; +h(1, 2, 3); +index = 9999999; +h(1, 2, 3); + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args-range-const.js b/js/src/jit-test/tests/arguments/args-range-const.js new file mode 100644 index 0000000000..d4a9193b9e --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-range-const.js @@ -0,0 +1,14 @@ +actual = ''; +expected = 'undefined,undefined,undefined,undefined,undefined,'; + +function h() { + for (var i = 0; i < 5; ++i) { + var a = arguments; + appendToActual(a[100]); + } +} + +h(); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args-range.js b/js/src/jit-test/tests/arguments/args-range.js new file mode 100644 index 0000000000..a5e40acaab --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-range.js @@ -0,0 +1,18 @@ +actual = ''; +expected = '0,0,0,0,0,88,88,88,88,88,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,'; + +function h(k) { + for (var i = 0; i < 5; ++i) { + var a = arguments; + appendToActual(a[k]); + } +} + +h(0); +h(2, 99, 88, 77); +h(-5); +h(46); +h('adf'); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args-redefine-iterator-1.js b/js/src/jit-test/tests/arguments/args-redefine-iterator-1.js new file mode 100644 index 0000000000..77241a6ae7 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-redefine-iterator-1.js @@ -0,0 +1,14 @@ +function t() +{ + var a = arguments; + Object.defineProperty(a, Symbol.iterator, { }); + for (var i = 0; i < 5; i++) + assertEq(a[Symbol.iterator], Array.prototype[Symbol.iterator]); + + var desc = Object.getOwnPropertyDescriptor(a, Symbol.iterator); + assertEq(desc.value, Array.prototype[Symbol.iterator]); + assertEq(desc.writable, true); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, true); +} +t(); diff --git a/js/src/jit-test/tests/arguments/args-redefine-iterator-2.js b/js/src/jit-test/tests/arguments/args-redefine-iterator-2.js new file mode 100644 index 0000000000..186be930c4 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-redefine-iterator-2.js @@ -0,0 +1,14 @@ +function t() +{ + var a = arguments; + Object.defineProperty(a, Symbol.iterator, { writable: false, enumerable: true, configurable: false }); + for (var i = 0; i < 5; i++) + assertEq(a[Symbol.iterator], Array.prototype[Symbol.iterator]); + + var desc = Object.getOwnPropertyDescriptor(a, Symbol.iterator); + assertEq(desc.value, Array.prototype[Symbol.iterator]); + assertEq(desc.writable, false); + assertEq(desc.enumerable, true); + assertEq(desc.configurable, false); +} +t(); diff --git a/js/src/jit-test/tests/arguments/args-redefine-length-1.js b/js/src/jit-test/tests/arguments/args-redefine-length-1.js new file mode 100644 index 0000000000..c71c97b1cb --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-redefine-length-1.js @@ -0,0 +1,7 @@ +function t() +{ + Object.defineProperty(arguments, "length", { value: 17 }); + for (var i = 0; i < 5; i++) + assertEq(arguments.length, 17); +} +t(); diff --git a/js/src/jit-test/tests/arguments/args-redefine-length-2.js b/js/src/jit-test/tests/arguments/args-redefine-length-2.js new file mode 100644 index 0000000000..fe1c9cf2fe --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-redefine-length-2.js @@ -0,0 +1,8 @@ +function t() +{ + var a = arguments; + Object.defineProperty(a, "length", { value: 17 }); + for (var i = 0; i < 5; i++) + assertEq(a.length, 17); +} +t(); diff --git a/js/src/jit-test/tests/arguments/args-redefine-length-3.js b/js/src/jit-test/tests/arguments/args-redefine-length-3.js new file mode 100644 index 0000000000..a4d6823acf --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-redefine-length-3.js @@ -0,0 +1,14 @@ +function t() +{ + var a = arguments; + Object.defineProperty(a, "length", { }); + for (var i = 0; i < 5; i++) + assertEq(a.length, 0); + + var desc = Object.getOwnPropertyDescriptor(a, "length"); + assertEq(desc.value, 0); + assertEq(desc.writable, true); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, true); +} +t(); diff --git a/js/src/jit-test/tests/arguments/args-redefine-length-4.js b/js/src/jit-test/tests/arguments/args-redefine-length-4.js new file mode 100644 index 0000000000..1029e8fca3 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-redefine-length-4.js @@ -0,0 +1,14 @@ +function t() +{ + var a = arguments; + Object.defineProperty(a, "length", { writable: false }); + for (var i = 0; i < 5; i++) + assertEq(a.length, 0); + + var desc = Object.getOwnPropertyDescriptor(a, "length"); + assertEq(desc.value, 0); + assertEq(desc.writable, false); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, true); +} +t(); diff --git a/js/src/jit-test/tests/arguments/args-redefine-length-5.js b/js/src/jit-test/tests/arguments/args-redefine-length-5.js new file mode 100644 index 0000000000..2ae30bf0f7 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-redefine-length-5.js @@ -0,0 +1,14 @@ +function t() +{ + var a = arguments; + Object.defineProperty(a, "length", { enumerable: true }); + for (var i = 0; i < 5; i++) + assertEq(a.length, 0); + + var desc = Object.getOwnPropertyDescriptor(a, "length"); + assertEq(desc.value, 0); + assertEq(desc.writable, true); + assertEq(desc.enumerable, true); + assertEq(desc.configurable, true); +} +t(); diff --git a/js/src/jit-test/tests/arguments/args-redefine-length-6.js b/js/src/jit-test/tests/arguments/args-redefine-length-6.js new file mode 100644 index 0000000000..a4b768d4bd --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-redefine-length-6.js @@ -0,0 +1,14 @@ +function t() +{ + var a = arguments; + Object.defineProperty(a, "length", { configurable: false }); + for (var i = 0; i < 5; i++) + assertEq(a.length, 0); + + var desc = Object.getOwnPropertyDescriptor(a, "length"); + assertEq(desc.value, 0); + assertEq(desc.writable, true); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, false); +} +t(); diff --git a/js/src/jit-test/tests/arguments/args-redefine-length-7.js b/js/src/jit-test/tests/arguments/args-redefine-length-7.js new file mode 100644 index 0000000000..042b224740 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-redefine-length-7.js @@ -0,0 +1,14 @@ +function t() +{ + var a = arguments; + Object.defineProperty(a, "length", { value: 0 }); + for (var i = 0; i < 5; i++) + assertEq(a.length, 0); + + var desc = Object.getOwnPropertyDescriptor(a, "length"); + assertEq(desc.value, 0); + assertEq(desc.writable, true); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, true); +} +t(); diff --git a/js/src/jit-test/tests/arguments/args-sum.js b/js/src/jit-test/tests/arguments/args-sum.js new file mode 100644 index 0000000000..04946e0fe8 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-sum.js @@ -0,0 +1,16 @@ +actual = ''; +expected = '666,'; + +function h() { + var ans = 0; + for (var i = 0; i < arguments.length; ++i) { + ans += arguments[i]; + } + return ans; +} + +var q = h(600, 60, 6); +appendToActual(q); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args-vargc.js b/js/src/jit-test/tests/arguments/args-vargc.js new file mode 100644 index 0000000000..615323c48a --- /dev/null +++ b/js/src/jit-test/tests/arguments/args-vargc.js @@ -0,0 +1,18 @@ +actual = ''; +expected = '1 2,1 2,1 2,1 2,1 2,1 2,1 2,1 2,1 undefined,1 undefined,1 undefined,1 undefined,1 undefined,1 undefined,1 undefined,1 undefined,'; + +function g(a, b) { + appendToActual(a + ' ' + b); +} + +function f() { + for (var i = 0; i < 8; ++i) { + g.apply(this, arguments); + } +} + +f(1, 2); +f(1); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args1.js b/js/src/jit-test/tests/arguments/args1.js new file mode 100644 index 0000000000..3efc2994cf --- /dev/null +++ b/js/src/jit-test/tests/arguments/args1.js @@ -0,0 +1,15 @@ +actual = ''; +expected = 'a,'; + +function f() { + arguments; +} + +for (var i = 0; i < 1000; ++i) { + f(1, 2); +} + +appendToActual('a') + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args10.js b/js/src/jit-test/tests/arguments/args10.js new file mode 100644 index 0000000000..4f31084e06 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args10.js @@ -0,0 +1,16 @@ +actual = ''; +expected = 'function h(x, y) { return arguments; },2,4,8,'; + +function h(x, y) { return arguments; } + +var p; +for (var i = 0; i < 5; ++i) { + p = h(i, i*2); +} +appendToActual(p.callee); +appendToActual(p.length); +appendToActual(p[0]); +appendToActual(p[1]); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args11.js b/js/src/jit-test/tests/arguments/args11.js new file mode 100644 index 0000000000..13e5893a5d --- /dev/null +++ b/js/src/jit-test/tests/arguments/args11.js @@ -0,0 +1,14 @@ +actual = ''; +expected = 'true,true,true,true,true,'; + +function h() { + var a = arguments; + for (var i = 0; i < 5; ++i) { + appendToActual(a == arguments); + } +} + +h(); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args2.js b/js/src/jit-test/tests/arguments/args2.js new file mode 100644 index 0000000000..2c19c3198e --- /dev/null +++ b/js/src/jit-test/tests/arguments/args2.js @@ -0,0 +1,20 @@ +actual = ''; +expected = '151,'; + +var g = 0; + +function add(a, b) { + g = a + b; +} + +function f() { + add.apply(this, arguments); +} + +for (var i = 0; i < 5; ++i) { + f(100, 51); +} +appendToActual(g); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args2a.js b/js/src/jit-test/tests/arguments/args2a.js new file mode 100644 index 0000000000..627aef0eb8 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args2a.js @@ -0,0 +1,17 @@ +actual = ''; +expected = 'g,g,g,g,g,'; + +function g() { + appendToActual('g'); +} + +function f() { + g.apply(this, arguments); +} + +for (var i = 0; i < 5; ++i) { + f(); +} + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args2b.js b/js/src/jit-test/tests/arguments/args2b.js new file mode 100644 index 0000000000..aa477863e7 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args2b.js @@ -0,0 +1,17 @@ +actual = ''; +expected = 'g 0,g 1,g 2,g 3,g 4,'; + +function g(x) { + appendToActual('g ' + x); +} + +function f() { + g.apply(this, arguments); +} + +for (var i = 0; i < 5; ++i) { + f(i); +} + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args2c.js b/js/src/jit-test/tests/arguments/args2c.js new file mode 100644 index 0000000000..9e83a424dc --- /dev/null +++ b/js/src/jit-test/tests/arguments/args2c.js @@ -0,0 +1,19 @@ +actual = ''; +expected = 'g 0 0,g 1 2,g 2 4,g 3 6,g 4 8,'; + +function g(x, y) { + appendToActual('g ' + x + ' ' + y); + //appendToActual('g ' + x + ' ' + y); + //appendToActual('g ' + y); +} + +function f() { + g.apply(this, arguments); +} + +for (var i = 0; i < 5; ++i) { + f(i, i*2); +} + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args2d.js b/js/src/jit-test/tests/arguments/args2d.js new file mode 100644 index 0000000000..a95c821fe6 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args2d.js @@ -0,0 +1,17 @@ +actual = ''; +expected = 'g 0 0 0,g 1 2 1,g 2 4 4,g 3 6 9,g 4 8 16,'; + +function g(x, y, z) { + appendToActual('g ' + x + ' ' + y + ' ' + z); +} + +function f() { + g.apply(this, arguments); +} + +for (var i = 0; i < 5; ++i) { + f(i, i*2, i*i); +} + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args3.js b/js/src/jit-test/tests/arguments/args3.js new file mode 100644 index 0000000000..7098521222 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args3.js @@ -0,0 +1,20 @@ +actual = ''; +expected = '51,'; + +var g = 0; + +function add(a, b) { + g = a + b; +} + +function f() { + g = arguments[1]; +} + +for (var i = 0; i < 10000; ++i) { + f(100, 51); +} +appendToActual(g); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args4.js b/js/src/jit-test/tests/arguments/args4.js new file mode 100644 index 0000000000..bd13c88156 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args4.js @@ -0,0 +1,21 @@ +actual = ''; +expected = '51,'; + +var g = 0; + +function h(args) { + g = args[1]; +} + +function f() { + h(arguments); +} + +for (var i = 0; i < 10000; ++i) { + f(100, 51); +} + +appendToActual(g); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args5.js b/js/src/jit-test/tests/arguments/args5.js new file mode 100644 index 0000000000..8bd1c1cb46 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args5.js @@ -0,0 +1,24 @@ +actual = ''; +expected = '150,'; + +var g = 0; + +function h(args) { + var ans = 0; + for (var i = 0; i < 5; ++i) { + ans += args[i]; + } + g = ans; +} + +function f() { + h(arguments); +} + +for (var i = 0; i < 5; ++i) { + f(10, 20, 30, 40, 50); +} +appendToActual(g); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args6.js b/js/src/jit-test/tests/arguments/args6.js new file mode 100644 index 0000000000..a2fc60d36a --- /dev/null +++ b/js/src/jit-test/tests/arguments/args6.js @@ -0,0 +1,22 @@ +actual = ''; +expected = '6,'; + +// tracing length + +var g = 0; + +function h(args) { + g = args.length; +} + +function f() { + h(arguments); +} + +for (var i = 0; i < 5; ++i) { + f(10, 20, 30, 40, 50, 60); +} +appendToActual(g); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args6a.js b/js/src/jit-test/tests/arguments/args6a.js new file mode 100644 index 0000000000..ce5206da1c --- /dev/null +++ b/js/src/jit-test/tests/arguments/args6a.js @@ -0,0 +1,23 @@ +actual = ''; +expected = '5,'; + +// tracing length + +var g = 0; + +function h(args) { + for (var i = 0; i < 6; ++i) + g = args.length; +} + +function f() { + h(arguments); +} + +for (var i = 0; i < 5; ++i) { + f(10, 20, 30, 40, 50); +} +appendToActual(g); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args7.js b/js/src/jit-test/tests/arguments/args7.js new file mode 100644 index 0000000000..5d713e81ac --- /dev/null +++ b/js/src/jit-test/tests/arguments/args7.js @@ -0,0 +1,14 @@ +actual = ''; +expected = '5,4,3,2,1,'; + +function f() { + while (arguments.length > 0) { + appendToActual(arguments[arguments.length-1]); + arguments.length--; + } +} + +f(1, 2, 3, 4, 5); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args8.js b/js/src/jit-test/tests/arguments/args8.js new file mode 100644 index 0000000000..57938d9e23 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args8.js @@ -0,0 +1,14 @@ +actual = ''; +expected = '[object Arguments],[object Arguments],[object Arguments],[object Arguments],[object Arguments],'; + +function h() { + return arguments; +} + +for (var i = 0; i < 5; ++i) { + var p = h(i, i*2); + appendToActual(p); +} + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args9.js b/js/src/jit-test/tests/arguments/args9.js new file mode 100644 index 0000000000..79a54dfaef --- /dev/null +++ b/js/src/jit-test/tests/arguments/args9.js @@ -0,0 +1,16 @@ +actual = ''; +expected = '10,20,'; + +function h() { + var p; + for (var i = 0; i < 5; ++i) { + p = arguments; + } + appendToActual(p[0]); + appendToActual(p[1]); +} + +h(10, 20); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/argsub.js b/js/src/jit-test/tests/arguments/argsub.js new file mode 100644 index 0000000000..e52992c6b5 --- /dev/null +++ b/js/src/jit-test/tests/arguments/argsub.js @@ -0,0 +1,13 @@ +actual = ''; +expected = 'undefined,undefined,undefined,undefined,undefined,'; + +function h() { + for (var i = 0; i < 5; ++i) { + appendToActual(arguments[100]); + } +} + +h(); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/argsx-1.js b/js/src/jit-test/tests/arguments/argsx-1.js new file mode 100644 index 0000000000..ea9d0906e4 --- /dev/null +++ b/js/src/jit-test/tests/arguments/argsx-1.js @@ -0,0 +1,22 @@ +actual = ''; +expected = "function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,1,2,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,[object Object],a,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def,function f() {\n var a = arguments;\n \n for (var i = 0; i < 10; ++i) {\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},2,abc,def," + +// args object created by interpreter + +function f() { + var a = arguments; + + for (var i = 0; i < 10; ++i) { + appendToActual(a.callee); + appendToActual(a.length); + appendToActual(a[0]); + appendToActual(a[1]); + } +} + +f(1, 2, 3); +f({}, 'a'); +f('abc', 'def'); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/argsx-2.js b/js/src/jit-test/tests/arguments/argsx-2.js new file mode 100644 index 0000000000..5fe9af97d8 --- /dev/null +++ b/js/src/jit-test/tests/arguments/argsx-2.js @@ -0,0 +1,23 @@ +actual = ''; +expected = "function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},3,1,2,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,[object Object],a,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def,function f() {\n var a = arguments;\n \n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n},2,abc,def," + +// args object created on trace + +function f() { + var a = arguments; + + appendToActual(a.callee); + appendToActual(a.length); + appendToActual(a[0]); + appendToActual(a[1]); +} + +for (var i = 0; i < 10; ++i) + f(1, 2, 3); +for (var i = 0; i < 10; ++i) + f({}, 'a'); +for (var i = 0; i < 10; ++i) + f('abc', 'def'); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/argsx-3.js b/js/src/jit-test/tests/arguments/argsx-3.js new file mode 100644 index 0000000000..ad5942c618 --- /dev/null +++ b/js/src/jit-test/tests/arguments/argsx-3.js @@ -0,0 +1,27 @@ +actual = ''; +expected = "true,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,false,abc," + +// args object created by interpreter at record time, but not always at run time. + +function f(t) { + if (t) { + var b = arguments; + appendToActual(b[0]); + } + + for (var i = 0; i < 10; ++i) { + var a = arguments; + appendToActual(a.callee); + appendToActual(a.length); + appendToActual(a[0]); + appendToActual(a[1]); + } +} + +f(true, 1, 2, 3); +f(false, 1, 2, 3); +f(false, {}, 'a'); +f(false, 'abc', 'def'); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/argsx-3a.js b/js/src/jit-test/tests/arguments/argsx-3a.js new file mode 100644 index 0000000000..fd278c039b --- /dev/null +++ b/js/src/jit-test/tests/arguments/argsx-3a.js @@ -0,0 +1,27 @@ +actual = ''; +expected = "function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,false,1,true,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},4,true,1,true,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,[object Object],true,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc,function f(t) {\n if (t) {\n var b = arguments;\n appendToActual(b[0]);\n }\n \n for (var i = 0; i < 10; ++i) {\n var a = arguments;\n appendToActual(a.callee);\n appendToActual(a.length);\n appendToActual(a[0]);\n appendToActual(a[1]);\n }\n},3,true,abc," + +// args object not created by interpreter at record time, but maybe at run time + +function f(t) { + if (t) { + var b = arguments; + appendToActual(b[0]); + } + + for (var i = 0; i < 10; ++i) { + var a = arguments; + appendToActual(a.callee); + appendToActual(a.length); + appendToActual(a[0]); + appendToActual(a[1]); + } +} + +f(false, 1, 2, 3); +f(true, 1, 2, 3); +f(true, {}, 'a'); +f(true, 'abc', 'def'); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/argsx-4.js b/js/src/jit-test/tests/arguments/argsx-4.js new file mode 100644 index 0000000000..b52b14853c --- /dev/null +++ b/js/src/jit-test/tests/arguments/argsx-4.js @@ -0,0 +1,23 @@ +actual = ''; +expected = '[object Arguments] undefined undefined,[object Arguments] undefined undefined,'; + +function f() { + g(arguments); +} + +function g(a, b, c) { + h(arguments); + a = 1; + b = 2; + c = 3; + h(arguments); +} + +function h(a, b, c) { + appendToActual(a + ' ' + b + ' ' + c); +} + +f(4, 5, 6); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/arguments-on-proto.js b/js/src/jit-test/tests/arguments/arguments-on-proto.js new file mode 100644 index 0000000000..745c77b9da --- /dev/null +++ b/js/src/jit-test/tests/arguments/arguments-on-proto.js @@ -0,0 +1,27 @@ +function create() { + return Object.create(arguments, {2: {value: "shadowed"}}); +} + +function createStrict() { + "use strict"; + return Object.create(arguments, {40: {value: "shadowed2"}}); +} + +function f() { + var args = [createStrict(10, 20, 30, 40), create(1, 2, 3)]; + + var threshold = getJitCompilerOptions()["ion.warmup.trigger"] + 101; + + for (var i = 0; i < threshold; i++) { + // We switch between different arguments objects, to make + // sure the right IC is triggered. + var a = args[i % 2]; + assertEq(a.length, (i % 2) ? 3 : 4); + assertEq(a[0], (i % 2) ? 1 : 10); + assertEq(a[1], (i % 2) ? 2 : 20); + assertEq(a[2], (i % 2) ? "shadowed" : 30); + assertEq(a[3], (i % 2) ? undefined : 40); + } +} + +f(); diff --git a/js/src/jit-test/tests/arguments/bug-917585-relax-aliasing-constraints.js b/js/src/jit-test/tests/arguments/bug-917585-relax-aliasing-constraints.js new file mode 100644 index 0000000000..03f77d7a7f --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug-917585-relax-aliasing-constraints.js @@ -0,0 +1,18 @@ + +function foo(a, b) { + blah(function (x) { a = x; }, b); + return arguments[0]; +} + +function blah(f, b) { + f(b); +} + +function main() { + for (var i = 0; i < 1500; i++) { + var x = foo(i, i*2); + assertEq(x, i*2); + } +} + +main(); diff --git a/js/src/jit-test/tests/arguments/bug1051760.js b/js/src/jit-test/tests/arguments/bug1051760.js new file mode 100644 index 0000000000..aeb54feecc --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug1051760.js @@ -0,0 +1,4 @@ +function test() { + eval("var { [arguments] : y } = {};"); +} +test(); diff --git a/js/src/jit-test/tests/arguments/bug1227287.js b/js/src/jit-test/tests/arguments/bug1227287.js new file mode 100644 index 0000000000..d0c6b88262 --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug1227287.js @@ -0,0 +1,8 @@ +// Note: Ion/Warp have known issues with function.arguments. See bug 1626294. + +function f(y) { + y = 1; + assertEq(arguments.callee.arguments[0], 1); + return () => y; +} +f(0); diff --git a/js/src/jit-test/tests/arguments/bug1423937.js b/js/src/jit-test/tests/arguments/bug1423937.js new file mode 100644 index 0000000000..ea4d4890a0 --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug1423937.js @@ -0,0 +1,16 @@ +// |jit-test| exitstatus: 6; skip-if: getBuildConfiguration('pbl') +var global = 0; +setInterruptCallback(function() { + foo("A"); +}); +function foo(x) { + for (var i = 0; i < 1000; i++) { + var stack = getBacktrace({args: true}); + } + if (global > 2) return; + global++; + interruptIf(true); + foo("B"); + (function() { g = x;}); +} +foo("C"); diff --git a/js/src/jit-test/tests/arguments/bug1503071.js b/js/src/jit-test/tests/arguments/bug1503071.js new file mode 100644 index 0000000000..d2beeca982 --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug1503071.js @@ -0,0 +1,16 @@ +// |jit-test| exitstatus: 6; skip-if: getBuildConfiguration('pbl') +var g = true + +setInterruptCallback(function() { + print(getBacktrace({args: true})); +}); + +function foo(bt, x=3, y = eval("g")) { + if (g) { + g = false + interruptIf(true); + foo(false); + } + (function() { n = bt;}); +} +foo(false); diff --git a/js/src/jit-test/tests/arguments/bug1621265.js b/js/src/jit-test/tests/arguments/bug1621265.js new file mode 100644 index 0000000000..8eaf37c480 --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug1621265.js @@ -0,0 +1,17 @@ +// |jit-test| error:null + +function f(a) { + // Add |arguments[0]| to mark the function as having an arguments + // access. Even though there's a |JSOp::SetArg| bytecode is present, we can + // still use lazy arguments here, because the |JSOp::SetArg| bytecode is + // always unreachable. + var v = arguments[0]; + assertEq(v, 1); + + // Anything below the |throw| is unreachable. + throw null; + + // Add an unreachable |JSOp::SetArg| bytecode. + a = 4; +} +f(1); diff --git a/js/src/jit-test/tests/arguments/bug1692833.js b/js/src/jit-test/tests/arguments/bug1692833.js new file mode 100644 index 0000000000..a7c7523eed --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug1692833.js @@ -0,0 +1,25 @@ +// |jit-test| skip-if: getBuildConfiguration('pbl') +g13 = newGlobal({newCompartment: true}) +g13.parent = this; +g13.eval("(" + function() { + Debugger(parent).onExceptionUnwind = function(frame) { + frame.older; + } +} + ")()"); + +function foo(depth) { + try { + if (depth > 0) { + bar(depth - arguments.length); + } else { + throw 1; + } + } catch (e) { throw e } +} +function bar(depth) { + foo(depth); +} + +try { + foo(50); +} catch {} diff --git a/js/src/jit-test/tests/arguments/bug1696181.js b/js/src/jit-test/tests/arguments/bug1696181.js new file mode 100644 index 0000000000..816a8c00e3 --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug1696181.js @@ -0,0 +1,15 @@ +function b() {} +function c() {} + +function foo() { + for (f of [b,c]) { + (function () { + f.apply({}, arguments); + })(1,2,3,4) + } +} + +with({}) {} +for (var i = 0; i < 100; i++) { + foo(); +} diff --git a/js/src/jit-test/tests/arguments/bug1711414.js b/js/src/jit-test/tests/arguments/bug1711414.js new file mode 100644 index 0000000000..174a78b507 --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug1711414.js @@ -0,0 +1,11 @@ +function bar() { this[0] = "overwritten"; } + +function foo() { + bar.apply(arguments, arguments); + return arguments[0]; +} + +with ({}) {} +for (var i = 0; i < 100; i++) { + assertEq(foo("original"), "overwritten"); +} diff --git a/js/src/jit-test/tests/arguments/bug1749460.js b/js/src/jit-test/tests/arguments/bug1749460.js new file mode 100644 index 0000000000..e78cf43f22 --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug1749460.js @@ -0,0 +1,14 @@ +function opaque(x) { + with ({}) {} + return x; +} + +function foo() { + "use strict"; + Object.defineProperty(arguments, 0, {value: 1}); + return opaque(...arguments); +} + +for (var i = 0; i < 50; i++) { + assertEq(foo(0), 1); +} diff --git a/js/src/jit-test/tests/arguments/bug1762575-1.js b/js/src/jit-test/tests/arguments/bug1762575-1.js new file mode 100644 index 0000000000..b4b15ddf98 --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug1762575-1.js @@ -0,0 +1,44 @@ +// Tests on mapped arguments objects. + +function ArraySlice() { + Object.defineProperty(arguments, 0, {value: 1}); + var result = Array.prototype.slice.call(arguments); + assertEq(result[0], 1); +} +ArraySlice(0); + +function ArrayShift() { + Object.defineProperty(arguments, 0, {value: 1}); + var result = Array.prototype.shift.call(arguments); + assertEq(result, 1); +} +ArrayShift(0); + +function ArrayPop() { + Object.defineProperty(arguments, 0, {value: 1}); + var result = Array.prototype.pop.call(arguments); + assertEq(result, 1); +} +ArrayPop(0); + +function ArrayJoin() { + Object.defineProperty(arguments, 0, {value: 1}); + var result = Array.prototype.join.call(arguments); + assertEq(result, "1"); +} +ArrayJoin(0); + +function ArrayIncludes() { + Object.defineProperty(arguments, 0, {value: 1}); + var result = Array.prototype.includes.call(arguments, 1); + assertEq(result, true); +} +ArrayIncludes(0); + +function FunctionApply() { + Object.defineProperty(arguments, 0, {value: 1}); + var id = x => x; + var result = id.apply(null, arguments); + assertEq(result, 1); +} +FunctionApply(0); diff --git a/js/src/jit-test/tests/arguments/bug1762575-2.js b/js/src/jit-test/tests/arguments/bug1762575-2.js new file mode 100644 index 0000000000..683e5420ae --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug1762575-2.js @@ -0,0 +1,50 @@ +// Tests on unmapped arguments objects. + +function ArraySlice() { + "use strict"; + Object.defineProperty(arguments, 0, {value: 1}); + var result = Array.prototype.slice.call(arguments); + assertEq(result[0], 1); +} +ArraySlice(0); + +function ArrayShift() { + "use strict"; + Object.defineProperty(arguments, 0, {value: 1}); + var result = Array.prototype.shift.call(arguments); + assertEq(result, 1); +} +ArrayShift(0); + +function ArrayPop() { + "use strict"; + Object.defineProperty(arguments, 0, {value: 1}); + var result = Array.prototype.pop.call(arguments); + assertEq(result, 1); +} +ArrayPop(0); + +function ArrayJoin() { + "use strict"; + Object.defineProperty(arguments, 0, {value: 1}); + var result = Array.prototype.join.call(arguments); + assertEq(result, "1"); +} +ArrayJoin(0); + +function ArrayIncludes() { + "use strict"; + Object.defineProperty(arguments, 0, {value: 1}); + var result = Array.prototype.includes.call(arguments, 1); + assertEq(result, true); +} +ArrayIncludes(0); + +function FunctionApply() { + "use strict"; + Object.defineProperty(arguments, 0, {value: 1}); + var id = x => x; + var result = id.apply(null, arguments); + assertEq(result, 1); +} +FunctionApply(0); diff --git a/js/src/jit-test/tests/arguments/bug1762575-3.js b/js/src/jit-test/tests/arguments/bug1762575-3.js new file mode 100644 index 0000000000..371eab009f --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug1762575-3.js @@ -0,0 +1,89 @@ +// Test implementation details when arguments object keep strong references +// to their elements. + +function checkWeakRef(f, isCleared = true) { + let [wr, args] = f({}); + + assertEq(wr.deref() !== undefined, true); + + clearKeptObjects(); + gc(); + + // In an ideal world, the reference is always cleared. But in specific + // circumstances we're currently keeping the reference alive. Should this + // ever change, feel free to update this test case accordingly. IOW having + // |isCleared == false| is okay for spec correctness, but it isn't optimal. + assertEq(wr.deref() === undefined, isCleared); +} + +checkWeakRef(function() { + // Create a weak-ref for the first argument. + let wr = new WeakRef(arguments[0]); + + // Clear the reference from the arguments object. + arguments[0] = null; + + // Let the arguments object escape. + return [wr, arguments]; +}); + +checkWeakRef(function() { + // Create a weak-ref for the first argument. + let wr = new WeakRef(arguments[0]); + + // Clear the reference from the arguments object. + Object.defineProperty(arguments, 0, {value: null}); + + // Let the arguments object escape. + return [wr, arguments]; +}); + +checkWeakRef(function self() { + // Create a weak-ref for the first argument. + let wr = new WeakRef(arguments[0]); + + // Delete operation doesn't clear the reference! + delete arguments[0]; + + // Let the arguments object escape. + return [wr, arguments]; +}, /*isCleared=*/ false); + +checkWeakRef(function() { + "use strict"; + + // Create a weak-ref for the first argument. + let wr = new WeakRef(arguments[0]); + + // Clear the reference from the arguments object. + arguments[0] = null; + + // Let the arguments object escape. + return [wr, arguments]; +}); + +checkWeakRef(function() { + "use strict"; + + // Create a weak-ref for the first argument. + let wr = new WeakRef(arguments[0]); + + // This define operation doesn't clear the reference! + Object.defineProperty(arguments, 0, {value: null}); + + // Let the arguments object escape. + return [wr, arguments]; +}, /*isCleared=*/ false); + +checkWeakRef(function() { + "use strict"; + + // Create a weak-ref for the first argument. + let wr = new WeakRef(arguments[0]); + + // Delete operation doesn't clear the reference! + delete arguments[0]; + + // Let the arguments object escape. + return [wr, arguments]; +}, /*isCleared=*/ false); diff --git a/js/src/jit-test/tests/arguments/bug1825907.js b/js/src/jit-test/tests/arguments/bug1825907.js new file mode 100644 index 0000000000..5e9be25d2f --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug1825907.js @@ -0,0 +1,7 @@ +function f(arg) { + eval(`var y = 1; function f() {return y}; f();`); + delete y; + arguments[0] = 5; + assertEq(arg, 5); +} +f(0); diff --git a/js/src/jit-test/tests/arguments/bug1827073.js b/js/src/jit-test/tests/arguments/bug1827073.js new file mode 100644 index 0000000000..d87ec97b48 --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug1827073.js @@ -0,0 +1,15 @@ +// |jit-test| --fast-warmup +let depth = 0; +function f1(a2, a3, a4, a5) { + f2(); +} +function f2() { + // Recursion depth reduced to allow PBL with debug build (hence larger + // frames) to work. + if (depth++ > 75) { + return; + } + f1(1, 2); + assertEq(JSON.stringify(Array.from(f1.arguments)), "[1,2]"); +} +f1(1, 2); diff --git a/js/src/jit-test/tests/arguments/bug503772.js b/js/src/jit-test/tests/arguments/bug503772.js new file mode 100644 index 0000000000..6ef8e1f974 --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug503772.js @@ -0,0 +1,16 @@ +function f(a) { + // Create arguments on trace + var z = arguments; + // Make f need a call object + if (false) { + var p = function() { ++a; } + } +} + +function g() { + for (var i = 0; i < 5; ++i) { + f(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); + } +} + +g(); diff --git a/js/src/jit-test/tests/arguments/bug508178.js b/js/src/jit-test/tests/arguments/bug508178.js new file mode 100644 index 0000000000..c779c82200 --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug508178.js @@ -0,0 +1,18 @@ +actual = ''; +expected = 'g,g,g,g,f,'; + +function test() { + 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]); + appendToActual(arr); +} +test('g'); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/bug633020.js b/js/src/jit-test/tests/arguments/bug633020.js new file mode 100644 index 0000000000..6e30bd1250 --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug633020.js @@ -0,0 +1,11 @@ +var N = 10; +function f(b) { + var a = []; + for (var i = 0; i < N; i++) + a[i] = {}; + a[N-1] = arguments; + for (var i = 0; i < N; i++) + a[i][0] = i; + assertEq(b, N - 1); +} +f(null); diff --git a/js/src/jit-test/tests/arguments/bug843985.js b/js/src/jit-test/tests/arguments/bug843985.js new file mode 100644 index 0000000000..3365b9ec87 --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug843985.js @@ -0,0 +1,5 @@ + +for (x in (function*() { + eval("arguments[0]"); + yield; +})())(function() {}) diff --git a/js/src/jit-test/tests/arguments/bug956173.js b/js/src/jit-test/tests/arguments/bug956173.js new file mode 100644 index 0000000000..d88efaa7ab --- /dev/null +++ b/js/src/jit-test/tests/arguments/bug956173.js @@ -0,0 +1,7 @@ +function foo() { + { + let x=arguments; + return function() { return x; }; + } +} +foo()(); diff --git a/js/src/jit-test/tests/arguments/defaults-basic.js b/js/src/jit-test/tests/arguments/defaults-basic.js new file mode 100644 index 0000000000..bca8528581 --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-basic.js @@ -0,0 +1,35 @@ +function f1(a, bIs, b=3) { + assertEq(a, 1); + assertEq(b, bIs); +} +assertEq(f1.length, 2); +f1(1, 3); +f1(1, 42, 42); +f1(1, 3, undefined); +function f2(a, bIs, cIs, b=3, c=4) { + assertEq(a, 1); + assertEq(b, bIs); + assertEq(c, cIs); +} +assertEq(f2.length, 3); +f2(1, 3, 4); +f2(1, 42, 4, 42); +f2(1, 42, 43, 42, 43); +f2(1, 3, 4, undefined); +f2(1, 42, 4, 42, undefined); +f2(1, 3, 42, undefined, 42); +function f3(a, b, c=4) { + assertEq(a, 1); + assertEq(b, undefined); + assertEq(c, 4); +} +f3(1); +function f4(a, bIs, cIs, b=3, c) { + assertEq(a, 1); + assertEq(b, bIs); + assertEq(c, cIs); +} +assertEq(f4.length, 3); +f4(1, 3, undefined); +f4(1, 4, undefined, 4); +f4(1, 4, 5, 4, 5); diff --git a/js/src/jit-test/tests/arguments/defaults-bound-to-function.js b/js/src/jit-test/tests/arguments/defaults-bound-to-function.js new file mode 100644 index 0000000000..28a1c3b455 --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-bound-to-function.js @@ -0,0 +1,43 @@ +load(libdir + "asserts.js"); + +function f(a=42) { + return a; + function a() { return 19; } +} +assertEq(f()(), 19); +function h(a=b, b=43) { + return [a, b]; + function b() { return 42; } +} +// TDZ +assertThrowsInstanceOf(h, ReferenceError); +function i(b=FAIL) { + function b() {} +} +assertThrowsInstanceOf(i, ReferenceError); +i(42); +function j(a=(b=42), b=8) { + return b; + function b() { return 43; } +} +// TDZ +assertThrowsInstanceOf(j, ReferenceError); +function k(a=(b=42), b=8) { + return b; + function a() { return 43; } +} +// TDZ +assertThrowsInstanceOf(k, ReferenceError); +function l(a=8, b=a) { + return b; + function a() { return 42; } +} +assertEq(l(), 8); +function m([a, b]=[1, 2], c=a) { + function a() { return 42; } + assertEq(typeof a, "function"); + assertEq(a(), 42); + assertEq(b, 2); + assertEq(c, 1); +} +m(); diff --git a/js/src/jit-test/tests/arguments/defaults-bug759904.js b/js/src/jit-test/tests/arguments/defaults-bug759904.js new file mode 100644 index 0000000000..f1ea39208a --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-bug759904.js @@ -0,0 +1,4 @@ +function* a(b=3) { + yield +} +a() diff --git a/js/src/jit-test/tests/arguments/defaults-call-function.js b/js/src/jit-test/tests/arguments/defaults-call-function.js new file mode 100644 index 0000000000..d3dcda0865 --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-call-function.js @@ -0,0 +1,15 @@ +load(libdir + "asserts.js"); + +function f1(a=g()) { + function g() { + } +} +assertThrowsInstanceOf(f1, ReferenceError); + +function f2(a=g()) { + function g() { + return 43; + } + assertEq(a, 42); +} +f2(42); diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-array.js b/js/src/jit-test/tests/arguments/defaults-destructuring-array.js new file mode 100644 index 0000000000..e3994a8795 --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-destructuring-array.js @@ -0,0 +1,17 @@ +function f1(a, bIs, [b]=[3]) { + assertEq(a, 1); + assertEq(b, bIs); +} +assertEq(f1.length, 2); +f1(1, 3); +f1(1, 42, [42]); +f1(1, 3, undefined); + +function f2(a, bIs, [b]=[]) { + assertEq(a, 1); + assertEq(b, bIs); +} +assertEq(f2.length, 2); +f2(1, undefined); +f2(1, 42, [42]); +f2(1, undefined, undefined); diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-expression-closure.js b/js/src/jit-test/tests/arguments/defaults-destructuring-expression-closure.js new file mode 100644 index 0000000000..750289e44e --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-destructuring-expression-closure.js @@ -0,0 +1,19 @@ +function f1(a, bIs, cIs, dIs, {b}={b: 3}, c=4, [d]=[5]) { + assertEq(a, 1), + assertEq(b, bIs), + assertEq(c, cIs), + assertEq(d, dIs) +} +assertEq(f1.length, 4); +f1(1, 3, 4, 5); +f1(1, 42, 43, 44, {b: 42}, 43, [44]); + +let f2 = (a, bIs, cIs, dIs, {b}={b: 3}, c=4, [d]=[5]) => ( + assertEq(a, 1), + assertEq(b, bIs), + assertEq(c, cIs), + assertEq(d, dIs) +); +assertEq(f2.length, 4); +f2(1, 3, 4, 5); +f2(1, 42, 43, 44, {b: 42}, 43, [44]); diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-function-expression.js b/js/src/jit-test/tests/arguments/defaults-destructuring-function-expression.js new file mode 100644 index 0000000000..9517a5c4d4 --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-destructuring-function-expression.js @@ -0,0 +1,9 @@ +let f = function(a, bIs, cIs, dIs, {b}={b: 3}, c=4, [d]=[5]) { + assertEq(a, 1); + assertEq(b, bIs); + assertEq(c, cIs); + assertEq(d, dIs); +}; +assertEq(f.length, 4); +f(1, 3, 4, 5); +f(1, 42, 43, 44, {b: 42}, 43, [44]); diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-mixed-default-value.js b/js/src/jit-test/tests/arguments/defaults-destructuring-mixed-default-value.js new file mode 100644 index 0000000000..e54255579e --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-destructuring-mixed-default-value.js @@ -0,0 +1,55 @@ +function f1(a=1, + [b, c=(assertEq(a, 2), a=3, 42)]=[(assertEq(a, 1), a=2, 43)], + {d, e:e=(assertEq(a, 4), a=5, 44)}={d: (assertEq(a, 3), a=4, 45)}, + f=(assertEq(a, 5), a=6, 46)) { + assertEq(a, 6); + assertEq(b, 43); + assertEq(c, 42); + assertEq(d, 45); + assertEq(e, 44); + assertEq(f, 46); +} +assertEq(f1.length, 0); +f1(); + +function f2(a=1, + [b, c=assertEq(false)]=[(assertEq(a, 1), a=2, 42), (assertEq(a, 2), a=3, 43)], + {d, e:e=assertEq(false)}={d: (assertEq(a, 3), a=4, 44), e: (assertEq(a, 4), a=5, 45)}, + f=(assertEq(a, 5), a=6, 46)) { + assertEq(a, 6); + assertEq(b, 42); + assertEq(c, 43); + assertEq(d, 44); + assertEq(e, 45); + assertEq(f, 46); +} +assertEq(f2.length, 0); +f2(); + +function f3(a=1, + [b, c=(assertEq(a, 1), a=2, 42)]=[assertEq(false)], + {d, e:e=(assertEq(a, 2), a=3, 43)}={d: assertEq(false)}, + f=(assertEq(a, 3), a=4, 44)) { + assertEq(a, 4); + assertEq(b, 8); + assertEq(c, 42); + assertEq(d, 9); + assertEq(e, 43); + assertEq(f, 44); +} +assertEq(f3.length, 0); +f3(undefined, [8], {d: 9}); + +function f4(a=1, + [b, c=assertEq(false)]=[assertEq(false), assertEq(false)], + {d, e:e=assertEq(false)}={d: assertEq(false), e: assertEq(false)}, + f=(assertEq(a, 1), a=2, 42)) { + assertEq(a, 2); + assertEq(b, 8); + assertEq(c, 9); + assertEq(d, 10); + assertEq(e, 11); + assertEq(f, 42); +} +assertEq(f4.length, 0); +f4(undefined, [8, 9], {d: 10, e: 11}); diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-mixed.js b/js/src/jit-test/tests/arguments/defaults-destructuring-mixed.js new file mode 100644 index 0000000000..74cb00f1f2 --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-destructuring-mixed.js @@ -0,0 +1,29 @@ +function f1(a, bIs, cIs, dIs, b=3, {c}={c: 4}, [d]=[5]) { + assertEq(a, 1); + assertEq(b, bIs); + assertEq(c, cIs); + assertEq(d, dIs); +} +assertEq(f1.length, 4); +f1(1, 3, 4, 5); +f1(1, 42, 4, 5, 42); +f1(1, 42, 43, 5, 42, {c: 43}); +f1(1, 42, 43, 44, 42, {c: 43}, [44]); +f1(1, 3, 4, 5, undefined); +f1(1, 42, 4, 5, 42, undefined); +f1(1, 3, 42, 5, undefined, {c: 42}); +f1(1, 3, 4, 42, undefined, undefined, [42]); + +function f2(a, bIs, cIs, dIs, eIs, {b}={b: 3}, [c]=[b], d=c, {ee: e}={ee: d}) { + assertEq(a, 1); + assertEq(b, bIs); + assertEq(c, cIs); + assertEq(d, dIs); + assertEq(e, eIs); +} +assertEq(f2.length, 5); +f2(1, 3, 3, 3, 3); +f2(1, 42, 42, 42, 42, {b: 42}); +f2(1, 42, 43, 43, 43, {b: 42}, [43]); +f2(1, 42, 43, 44, 44, {b: 42}, [43], 44); +f2(1, 42, 43, 44, 45, {b: 42}, [43], 44, {ee: 45}); diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-object.js b/js/src/jit-test/tests/arguments/defaults-destructuring-object.js new file mode 100644 index 0000000000..0ca970a144 --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-destructuring-object.js @@ -0,0 +1,27 @@ +function f1(a, bIs, cIs, {b}={b: 3}, {cc: c}={cc: 4}) { + assertEq(a, 1); + assertEq(b, bIs); + assertEq(c, cIs); +} +assertEq(f1.length, 3); +f1(1, 3, 4); +f1(1, 42, 4, {b: 42}); +f1(1, 42, 4, {b: 42}, undefined); +f1(1, 42, 43, {b: 42}, {cc: 43}); +f1(1, 3, 4, undefined); +f1(1, 3, 4, undefined, undefined); +f1(1, 3, 43, undefined, {cc: 43}); + +function f2(a, bIs, cIs, {b}={}, {cc: c}={}) { + assertEq(a, 1); + assertEq(b, bIs); + assertEq(c, cIs); +} +assertEq(f2.length, 3); +f2(1, undefined, undefined); +f2(1, 42, undefined, {b: 42}); +f2(1, 42, undefined, {b: 42}, undefined); +f2(1, 42, 43, {b: 42}, {cc: 43}); +f2(1, undefined, undefined, undefined); +f2(1, undefined, undefined, undefined, undefined); +f2(1, undefined, 43, undefined, {cc: 43}); diff --git a/js/src/jit-test/tests/arguments/defaults-destructuring-with-rest.js b/js/src/jit-test/tests/arguments/defaults-destructuring-with-rest.js new file mode 100644 index 0000000000..26c35f6a43 --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-destructuring-with-rest.js @@ -0,0 +1,29 @@ +load(libdir + "asserts.js"); +load(libdir + "eqArrayHelper.js"); + +function f1(a, bIs, [b]=[3], ...rest) { + assertEq(a, 1); + assertEq(bIs, b); + assertEqArray(rest, []); +} +assertEq(f1.length, 2); +f1(1, 3); +f1(1, 42, [42]); + +function f2([a]=[rest], ...rest) { + assertEq(a, undefined); +} +// TDZ +assertThrowsInstanceOf(f2, ReferenceError); + +function f3([a]=[rest], ...rest) { + assertEq(a, 1); + assertEqArray(rest, [2, 3, 4]); +} +// TDZ +assertThrowsInstanceOf(f3, ReferenceError); + +function f4([a]=rest, ...rest) { +} +// TDZ +assertThrowsInstanceOf(f4, ReferenceError); diff --git a/js/src/jit-test/tests/arguments/defaults-evaluation-order.js b/js/src/jit-test/tests/arguments/defaults-evaluation-order.js new file mode 100644 index 0000000000..c4ddff7372 --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-evaluation-order.js @@ -0,0 +1,27 @@ +function f1(a, bIs, cIs, dIs, b=a, c=5, d=c) { + assertEq(a, 1); + assertEq(b, bIs); + assertEq(c, cIs); + assertEq(d, dIs); +} +f1(1, 1, 5, 5); +f1(1, 42, 5, 5, 42); +f1(1, 42, 43, 43, 42, 43); +f1(1, 42, 43, 44, 42, 43, 44); +function f2(a=[]) { return a; } +assertEq(f2() !== f2(), true); +function f3(a=function () {}) { return a; } +assertEq(f3() !== f3(), true); +function f4(a=Date) { return a; } +assertEq(f4(), Date); +Date = 0; +assertEq(f4(), 0); +function f5(x=FAIL()) {}; // don't throw +var n = 0; +function f6(a=n++) {} +assertEq(n, 0); +function f7([a, b], A=a, B=b) { + assertEq(A, a); + assertEq(B, b); +} +f7([0, 1]); diff --git a/js/src/jit-test/tests/arguments/defaults-exceptions.js b/js/src/jit-test/tests/arguments/defaults-exceptions.js new file mode 100644 index 0000000000..ab8d9c1b69 --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-exceptions.js @@ -0,0 +1,6 @@ +load(libdir + "asserts.js"); + +function die() { throw "x"; } +var ok = true; +function f(a = die()) { ok = false; } +assertThrowsValue(f, "x"); diff --git a/js/src/jit-test/tests/arguments/defaults-invalid-syntax.js b/js/src/jit-test/tests/arguments/defaults-invalid-syntax.js new file mode 100644 index 0000000000..f1e1e508af --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-invalid-syntax.js @@ -0,0 +1,30 @@ +load(libdir + "asserts.js"); + +assertThrowsInstanceOf(function () { + eval("function f(...rest=23) {}"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + eval("function f(a=yield 24) {}"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + eval("function f(a={a : 19 + (yield 24).prop}) {}"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + eval("function f(a=1,a=1) {}"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + eval("function f(a,a=1) {}"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + eval("function f(a=1,a) {}"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + eval("function f(a,a,b=1) {}"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + eval("function f(a,b=1,a=1) {}"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + eval("function f(a=1,b=1,a=1) {}"); +}, SyntaxError); +function silly_but_okay(a=(function* () { yield 97; })) {} diff --git a/js/src/jit-test/tests/arguments/defaults-scoping.js b/js/src/jit-test/tests/arguments/defaults-scoping.js new file mode 100644 index 0000000000..366439590e --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-scoping.js @@ -0,0 +1,36 @@ +load(libdir + "asserts.js"); + +var x = 'global'; +function f(a=x) { // global variable x + var x = 'local'; + return a; +} +assertEq(f(), 'global'); + +var i = 42; +function g(f=function () { return ++i; }) { // closes on global variable i + var i = 0; + return f; +} +var gf = g(); +assertEq(gf(), 43); +assertEq(gf(), 44); +gf = g(); +assertEq(gf(), 45); + +function h(f=function (s) { return eval(s); }) { // closes on global scope + var x = 'hlocal'; + return f; +} +var hf = h(); +assertEq(hf('x'), 'global'); +assertEq(hf('f'), hf); +assertEq(hf('var x = 3; x'), 3); + +function j(expr, v=eval(expr)) { + return v; +} +assertEq(j("expr"), "expr"); +assertThrowsInstanceOf(() => j("v"), ReferenceError); +assertEq(j("Array"), Array); +assertEq(j("arguments").length, 1); diff --git a/js/src/jit-test/tests/arguments/defaults-strict-mode.js b/js/src/jit-test/tests/arguments/defaults-strict-mode.js new file mode 100644 index 0000000000..c4ba7bd63d --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-strict-mode.js @@ -0,0 +1,41 @@ +load(libdir + "asserts.js"); + +eval(`"use strict"; +function f1(f=(function () { return typeof this !== "object"; })) { return f; } +assertEq(f1()(), true); +`); + +function f2(f=(function () { "use strict"; return (function () { return typeof this !== "object"; }) })) { assertEq(typeof this, "object"); return f; } +assertEq(f2()()(), true); + +eval(`"use strict"; +function f3(f=(function () { return (function () { return typeof this !== "object"; }) })) { return f; } +assertEq(f3()()(), true); +`); + +// These should be okay. +function f4(f=(function () { with (Object) {} }), g=(function () { "use strict"; })) {} +function f5(g=(function () { "use strict"; }), f=(function () { with (Object) {} })) {} + +assertThrowsInstanceOf(function () { + eval("'use strict'; function f(a=delete x) { }"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + Math.sin(4); + eval("'use strict'; function f(a='\\251') { }"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + eval("'use strict'; function f(a='\\251', b=delete x) { }"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + eval("'use strict'; function f(a=delete x, b='\\251') { }"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + eval("'use strict'; function f(a=(function () { '\\251'; })) { }"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + eval("'use strict'; function f(a=(function () { with (Object) {} })) { }"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + eval("'use strict'; function f(a=(function (b, b) {})) { }"); +}, SyntaxError); diff --git a/js/src/jit-test/tests/arguments/defaults-with-arguments.js b/js/src/jit-test/tests/arguments/defaults-with-arguments.js new file mode 100644 index 0000000000..9924c7c238 --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-with-arguments.js @@ -0,0 +1,10 @@ +function f(a=1, b=2, c=3) { return arguments; } +var args = f(); +assertEq(args.length, 0); +assertEq("0" in args, false); +args = f(5, 6); +assertEq(args.length, 2); +assertEq(args[1], 6); +args = f(9, 8, 7, 6, 5); +assertEq(args.length, 5); +assertEq(args[4], 5); diff --git a/js/src/jit-test/tests/arguments/defaults-with-rest.js b/js/src/jit-test/tests/arguments/defaults-with-rest.js new file mode 100644 index 0000000000..b0c7c8bcf9 --- /dev/null +++ b/js/src/jit-test/tests/arguments/defaults-with-rest.js @@ -0,0 +1,23 @@ +load(libdir + "eqArrayHelper.js"); +load(libdir + "asserts.js"); + +function f1(a, bIs, b=3, ...rest) { + assertEq(a, 1); + assertEq(bIs, b); + assertEqArray(rest, []); +} +assertEq(f1.length, 2); +f1(1, 3); +f1(1, 42, 42); +function f2(a=rest, ...rest) { +} +// TDZ +assertThrowsInstanceOf(f2, ReferenceError); +function f3(a=rest, ...rest) { +} +assertThrowsInstanceOf(f3, ReferenceError); +function f4(a=42, ...f) { + assertEq(typeof f, "function"); + function f() {} +} +f4() diff --git a/js/src/jit-test/tests/arguments/destructuring-after-defaults.js b/js/src/jit-test/tests/arguments/destructuring-after-defaults.js new file mode 100644 index 0000000000..66f24a8342 --- /dev/null +++ b/js/src/jit-test/tests/arguments/destructuring-after-defaults.js @@ -0,0 +1,14 @@ +load(libdir + "asserts.js"); + +function f1(a, bIs, cIs, dIs, b=1, [c], {d}) { + assertEq(a, 1); + assertEq(b, bIs); + assertEq(c, cIs); + assertEq(d, dIs); +} +assertEq(f1.length, 4); +f1(1, 1, 42, 43, undefined, [42], {d: 43}); +f1(1, 42, 43, 44, 42, [43], {d: 44}); +assertThrowsInstanceOf(function () { + f1(1, 1, 1, 1); +}, TypeError); diff --git a/js/src/jit-test/tests/arguments/destructuring-default-value-scope.js b/js/src/jit-test/tests/arguments/destructuring-default-value-scope.js new file mode 100644 index 0000000000..c4b16ea4df --- /dev/null +++ b/js/src/jit-test/tests/arguments/destructuring-default-value-scope.js @@ -0,0 +1,10 @@ +var a = 10; +function f1(a, + [b=(assertEq(a, 1), a=2, 42)], + {c:c=(assertEq(a, 2), a=3, 43)}) { + assertEq(a, 3); + assertEq(b, 42); + assertEq(c, 43); +} +f1(1, [], {}); +assertEq(a, 10); diff --git a/js/src/jit-test/tests/arguments/destructuring-exprbody.js b/js/src/jit-test/tests/arguments/destructuring-exprbody.js new file mode 100644 index 0000000000..5f3f04ecb7 --- /dev/null +++ b/js/src/jit-test/tests/arguments/destructuring-exprbody.js @@ -0,0 +1,8 @@ +// See bug 763313 +load(libdir + "iteration.js"); +function f([a]) { return a; } +var i = 0; +var o = {[Symbol.iterator]: function () { i++; return { + next: function () { i++; return {value: 42, done: false}; }}}}; +assertEq(f(o), 42); +assertEq(i, 2); diff --git a/js/src/jit-test/tests/arguments/destructuring-with-rest.js b/js/src/jit-test/tests/arguments/destructuring-with-rest.js new file mode 100644 index 0000000000..81e69ce54d --- /dev/null +++ b/js/src/jit-test/tests/arguments/destructuring-with-rest.js @@ -0,0 +1,21 @@ +load(libdir + "eqArrayHelper.js"); + +function f1(a, bIs, [b], ...rest) { + assertEq(a, 1); + assertEq(bIs, b); + assertEqArray(rest, []); +} +assertEq(f1.length, 3); +f1(1, 3, [3]); +f1(1, 42, [42]); + +function f2([a], ...rest) { + assertEq(a, undefined); +} +f2([]); + +function f3([a], ...rest) { + assertEq(a, 1); + assertEqArray(rest, [2, 3, 4]); +} +f3([1], 2, 3, 4); diff --git a/js/src/jit-test/tests/arguments/dynamicBindings.js b/js/src/jit-test/tests/arguments/dynamicBindings.js new file mode 100644 index 0000000000..326038e12b --- /dev/null +++ b/js/src/jit-test/tests/arguments/dynamicBindings.js @@ -0,0 +1,32 @@ + +function testEval(x, y) { + x = 5; + eval("arguments[0] += 10"); + assertEq(x, 15); +} +for (var i = 0; i < 5; i++) + testEval(3); + +function testEvalWithArguments(x, y) { + eval("arguments[0] += 10"); + assertEq(arguments[y], 13); +} +for (var i = 0; i < 5; i++) + testEvalWithArguments(3, 0); + +function testNestedEval(x, y) { + x = 5; + eval("eval('arguments[0] += 10')"); + assertEq(x, 15); +} +for (var i = 0; i < 5; i++) + testNestedEval(3); + +function testWith(x, y) { + with ({}) { + arguments[0] += 10; + assertEq(x, 13); + } +} +for (var i = 0; i < 5; i++) + testWith(3); diff --git a/js/src/jit-test/tests/arguments/external-arguments-apply-forwarded.js b/js/src/jit-test/tests/arguments/external-arguments-apply-forwarded.js new file mode 100644 index 0000000000..b2f388dd7e --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-apply-forwarded.js @@ -0,0 +1,18 @@ +function foo(x,y) { + function capture() { return x; } + return bar(arguments); +} + +function bar(x) { + return baz.apply({}, x) + arguments.length; +} + +function baz(x,y) { + return x + y; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 400) diff --git a/js/src/jit-test/tests/arguments/external-arguments-apply.js b/js/src/jit-test/tests/arguments/external-arguments-apply.js new file mode 100644 index 0000000000..997aafa2d2 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-apply.js @@ -0,0 +1,17 @@ +function foo(x,y) { + return bar(arguments); +} + +function bar(x) { + return baz.apply({}, x) + arguments.length; +} + +function baz(x,y) { + return x + y; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 400) diff --git a/js/src/jit-test/tests/arguments/external-arguments-callee.js b/js/src/jit-test/tests/arguments/external-arguments-callee.js new file mode 100644 index 0000000000..cee9edba51 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-callee.js @@ -0,0 +1,13 @@ +function foo() { + with ({}) {} + return bar(arguments); +} + +function bar(x) { + assertEq(x.callee.name, "foo"); + assertEq(arguments.callee.name, "bar"); +} + +for (var i = 0; i < 100; i++) { + foo(); +} diff --git a/js/src/jit-test/tests/arguments/external-arguments-element-deleted-exists-oob.js b/js/src/jit-test/tests/arguments/external-arguments-element-deleted-exists-oob.js new file mode 100644 index 0000000000..d6ff36060e --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-element-deleted-exists-oob.js @@ -0,0 +1,14 @@ +function foo(x,y) { + delete arguments[1]; + return bar(arguments); +} + +function bar(x) { + return (100 in x) + arguments.length; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 100); diff --git a/js/src/jit-test/tests/arguments/external-arguments-element-deleted-exists.js b/js/src/jit-test/tests/arguments/external-arguments-element-deleted-exists.js new file mode 100644 index 0000000000..a65abe83e5 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-element-deleted-exists.js @@ -0,0 +1,14 @@ +function foo(x,y) { + delete arguments[1]; + return bar(arguments); +} + +function bar(x) { + return (1 in x) + arguments.length; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 100); diff --git a/js/src/jit-test/tests/arguments/external-arguments-element-deleted-oob.js b/js/src/jit-test/tests/arguments/external-arguments-element-deleted-oob.js new file mode 100644 index 0000000000..8a38aaa8d6 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-element-deleted-oob.js @@ -0,0 +1,14 @@ +function foo(x,y) { + delete arguments[0]; + return bar(arguments); +} + +function bar(x) { + return (x[100]|0) + arguments.length; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 100); diff --git a/js/src/jit-test/tests/arguments/external-arguments-element-deleted.js b/js/src/jit-test/tests/arguments/external-arguments-element-deleted.js new file mode 100644 index 0000000000..f1ba46818a --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-element-deleted.js @@ -0,0 +1,14 @@ +function foo(x,y) { + delete arguments[0]; + return bar(arguments); +} + +function bar(x) { + return x[1] + arguments.length; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 300); diff --git a/js/src/jit-test/tests/arguments/external-arguments-element-exists-oob.js b/js/src/jit-test/tests/arguments/external-arguments-element-exists-oob.js new file mode 100644 index 0000000000..2af2140f37 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-element-exists-oob.js @@ -0,0 +1,13 @@ +function foo(x,y) { + return bar(arguments); +} + +function bar(x) { + return (100 in x) + arguments.length; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 100); diff --git a/js/src/jit-test/tests/arguments/external-arguments-element-exists.js b/js/src/jit-test/tests/arguments/external-arguments-element-exists.js new file mode 100644 index 0000000000..f8e8aadd7c --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-element-exists.js @@ -0,0 +1,13 @@ +function foo(x,y) { + return bar(arguments); +} + +function bar(x) { + return (1 in x) + arguments.length; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 200); diff --git a/js/src/jit-test/tests/arguments/external-arguments-element-oob.js b/js/src/jit-test/tests/arguments/external-arguments-element-oob.js new file mode 100644 index 0000000000..452f08768d --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-element-oob.js @@ -0,0 +1,13 @@ +function foo(x,y) { + return bar(arguments); +} + +function bar(x) { + return (x[100]|0) + arguments.length; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 100); diff --git a/js/src/jit-test/tests/arguments/external-arguments-element.js b/js/src/jit-test/tests/arguments/external-arguments-element.js new file mode 100644 index 0000000000..644eecec82 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-element.js @@ -0,0 +1,13 @@ +function foo(x,y) { + return bar(arguments); +} + +function bar(x) { + return x[1] + arguments.length; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 300); diff --git a/js/src/jit-test/tests/arguments/external-arguments-inlined-apply.js b/js/src/jit-test/tests/arguments/external-arguments-inlined-apply.js new file mode 100644 index 0000000000..882476bf0a --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-inlined-apply.js @@ -0,0 +1,14 @@ +function foo() { + return bar(arguments); +} +function bar(argsFromFoo) { + return baz.apply({}, argsFromFoo) +} +function baz(a,b) { return a + b; } + +var sum = 0; +with ({}) {} +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 300); diff --git a/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-1.js b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-1.js new file mode 100644 index 0000000000..ad42ff1be8 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-1.js @@ -0,0 +1,15 @@ +function foo() { + return bar(arguments); +} +function bar(argsFromFoo) { + var args = Array.prototype.slice.call(argsFromFoo); + return baz(args[0], args[1]); +} +function baz(a,b) { return a + b; } + +var sum = 0; +with ({}) {} +for (var i = 0; i < 100; i++) { + sum += foo(1, 2); +} +assertEq(sum, 300); diff --git a/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-2.js b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-2.js new file mode 100644 index 0000000000..d78abe3a45 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-2.js @@ -0,0 +1,15 @@ +function foo() { + return bar(arguments); +} +function bar(argsFromFoo) { + var args = Array.prototype.slice.call(argsFromFoo, 1); + return baz(args[0], args[1]); +} +function baz(a,b) { return a + b; } + +var sum = 0; +with ({}) {} +for (var i = 0; i < 100; i++) { + sum += foo(0, 1, 2); +} +assertEq(sum, 300); diff --git a/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-3.js b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-3.js new file mode 100644 index 0000000000..ffe6076177 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-3.js @@ -0,0 +1,15 @@ +function foo() { + return bar(arguments); +} +function bar(argsFromFoo) { + var args = Array.prototype.slice.call(argsFromFoo, -2); + return baz(args[0], args[1]); +} +function baz(a,b) { return a + b; } + +var sum = 0; +with ({}) {} +for (var i = 0; i < 100; i++) { + sum += foo(0, 1, 2); +} +assertEq(sum, 300); diff --git a/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-4.js b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-4.js new file mode 100644 index 0000000000..f292fe12b7 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-inlined-slice-4.js @@ -0,0 +1,15 @@ +function foo() { + return bar(arguments); +} +function bar(argsFromFoo) { + var args = Array.prototype.slice.call(argsFromFoo, 1, 3); + return baz(args[0], args[1]); +} +function baz(a,b) { return a + b; } + +var sum = 0; +with ({}) {} +for (var i = 0; i < 100; i++) { + sum += foo(0, 1, 2, 3); +} +assertEq(sum, 300); diff --git a/js/src/jit-test/tests/arguments/external-arguments-inlined-spread.js b/js/src/jit-test/tests/arguments/external-arguments-inlined-spread.js new file mode 100644 index 0000000000..d4be0829bd --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-inlined-spread.js @@ -0,0 +1,14 @@ +function foo() { + return bar(arguments); +} +function bar(argsFromFoo) { + return baz(...argsFromFoo) +} +function baz(a,b) { return a + b; } + +var sum = 0; +with ({}) {} +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 300); diff --git a/js/src/jit-test/tests/arguments/external-arguments-length.js b/js/src/jit-test/tests/arguments/external-arguments-length.js new file mode 100644 index 0000000000..cac00cccb2 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-length.js @@ -0,0 +1,14 @@ +function foo(x,y) { + with ({}) {} + return bar(arguments); +} + +function bar(x) { + return x.length + arguments.length; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 300); diff --git a/js/src/jit-test/tests/arguments/external-arguments-mutate-callee.js b/js/src/jit-test/tests/arguments/external-arguments-mutate-callee.js new file mode 100644 index 0000000000..9cb4af6f1c --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-mutate-callee.js @@ -0,0 +1,13 @@ +function foo() { + arguments.callee = {name: "mutated"}; + return bar(arguments); +} + +function bar(x) { + assertEq(x.callee.name, "mutated"); + assertEq(arguments.callee.name, "bar"); +} + +for (var i = 0; i < 100; i++) { + foo(); +} diff --git a/js/src/jit-test/tests/arguments/external-arguments-set-length.js b/js/src/jit-test/tests/arguments/external-arguments-set-length.js new file mode 100644 index 0000000000..85ac8a5481 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-set-length.js @@ -0,0 +1,14 @@ +function foo(x,y) { + arguments.length = 3; + return bar(arguments); +} + +function bar(x) { + return x.length + arguments.length; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 400); diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-1.js b/js/src/jit-test/tests/arguments/external-arguments-slice-1.js new file mode 100644 index 0000000000..eeb8dfaccf --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-slice-1.js @@ -0,0 +1,18 @@ +function foo(x, y) { + return bar(arguments); +} + +function bar(x) { + var args = Array.prototype.slice.call(x); + return baz(args[0], args[1]) + arguments.length; +} + +function baz(x, y) { + return x + y; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1, 2); +} +assertEq(sum, 400) diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-2.js b/js/src/jit-test/tests/arguments/external-arguments-slice-2.js new file mode 100644 index 0000000000..51aa928e39 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-slice-2.js @@ -0,0 +1,18 @@ +function foo(x, y) { + return bar(arguments); +} + +function bar(x) { + var args = Array.prototype.slice.call(x, 1); + return baz(args[0], args[1]) + arguments.length; +} + +function baz(x, y) { + return x + y; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(0, 1, 2); +} +assertEq(sum, 400) diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-3.js b/js/src/jit-test/tests/arguments/external-arguments-slice-3.js new file mode 100644 index 0000000000..9b58be0465 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-slice-3.js @@ -0,0 +1,18 @@ +function foo(x, y) { + return bar(arguments); +} + +function bar(x) { + var args = Array.prototype.slice.call(x, -2); + return baz(args[0], args[1]) + arguments.length; +} + +function baz(x, y) { + return x + y; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(0, 1, 2); +} +assertEq(sum, 400) diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-4.js b/js/src/jit-test/tests/arguments/external-arguments-slice-4.js new file mode 100644 index 0000000000..5844fa72e0 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-slice-4.js @@ -0,0 +1,18 @@ +function foo(x, y) { + return bar(arguments); +} + +function bar(x) { + var args = Array.prototype.slice.call(x, 1, 3); + return baz(args[0], args[1]) + arguments.length; +} + +function baz(x, y) { + return x + y; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(0, 1, 2, 3); +} +assertEq(sum, 400) diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-1.js b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-1.js new file mode 100644 index 0000000000..fb6fb75a97 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-1.js @@ -0,0 +1,19 @@ +function foo(x,y) { + function capture() { return x; } + return bar(arguments); +} + +function bar(x) { + var args = Array.prototype.slice.call(x); + return baz(args[0], args[1]) + arguments.length; +} + +function baz(x,y) { + return x + y; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1, 2); +} +assertEq(sum, 400) diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-2.js b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-2.js new file mode 100644 index 0000000000..20a079be98 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-2.js @@ -0,0 +1,19 @@ +function foo(x,y) { + function capture() { return x; } + return bar(arguments); +} + +function bar(x) { + var args = Array.prototype.slice.call(x, 1); + return baz(args[0], args[1]) + arguments.length; +} + +function baz(x,y) { + return x + y; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(0, 1, 2); +} +assertEq(sum, 400) diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-3.js b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-3.js new file mode 100644 index 0000000000..386594b3bd --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-3.js @@ -0,0 +1,19 @@ +function foo(x,y) { + function capture() { return x; } + return bar(arguments); +} + +function bar(x) { + var args = Array.prototype.slice.call(x, -2); + return baz(args[0], args[1]) + arguments.length; +} + +function baz(x,y) { + return x + y; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(0, 1, 2); +} +assertEq(sum, 400) diff --git a/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-4.js b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-4.js new file mode 100644 index 0000000000..f909d79f74 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-slice-forwarded-4.js @@ -0,0 +1,19 @@ +function foo(x,y) { + function capture() { return x; } + return bar(arguments); +} + +function bar(x) { + var args = Array.prototype.slice.call(x, 1, 3); + return baz(args[0], args[1]) + arguments.length; +} + +function baz(x,y) { + return x + y; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(0, 1, 2, 3); +} +assertEq(sum, 400) diff --git a/js/src/jit-test/tests/arguments/external-arguments-spread-forwarded.js b/js/src/jit-test/tests/arguments/external-arguments-spread-forwarded.js new file mode 100644 index 0000000000..7a70189c28 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-spread-forwarded.js @@ -0,0 +1,18 @@ +function foo(x,y) { + function capture() { return x; } + return bar(arguments); +} + +function bar(x) { + return baz(...x) + arguments.length; +} + +function baz(x,y) { + return x + y; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 400) diff --git a/js/src/jit-test/tests/arguments/external-arguments-spread.js b/js/src/jit-test/tests/arguments/external-arguments-spread.js new file mode 100644 index 0000000000..cc0f1e18f1 --- /dev/null +++ b/js/src/jit-test/tests/arguments/external-arguments-spread.js @@ -0,0 +1,17 @@ +function foo(x,y) { + return bar(arguments); +} + +function bar(x) { + return baz(...x) + arguments.length; +} + +function baz(x,y) { + return x + y; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 400) diff --git a/js/src/jit-test/tests/arguments/function_dot_caller_restrictions.js b/js/src/jit-test/tests/arguments/function_dot_caller_restrictions.js new file mode 100644 index 0000000000..414f348eb6 --- /dev/null +++ b/js/src/jit-test/tests/arguments/function_dot_caller_restrictions.js @@ -0,0 +1,78 @@ + +function g() { } +function strict() { + "use strict"; +} + +let bound = g.bind(); +let arrow = x => 0; + +async function fn_async() { } +function * fn_generator() { } + +let o = { + mtd() {}, + get x() {}, + set x(v) {}, +}; + +class Base { } +class Derived extends Base { } + +function asm_mod() { + "use asm"; + function mtd() {} + return { mtd: mtd } +} + +let asm_fun = (new asm_mod).mtd; + +let builtin_selfhost = [].sort; +let builtin_native = Math.sin; + +let dot_caller = Object.getOwnPropertyDescriptor(Function.__proto__, + "caller").get; + +// Returns true if fn.caller is allowed +function check(fn) { + try { + (function() { + fn.caller; + })(); + } + catch (e) { + assertEq(e instanceof TypeError, true); + return false; + } + return true; +} + +// Normal sloppy functions are allowed, even if they also are intended as +// asm.js. +assertEq(check(g), true); +assertEq(check(asm_mod), true); +assertEq(check(asm_fun), true); + +// Most others are not +assertEq(check(strict), false); +assertEq(check(bound), false); +assertEq(check(arrow), false); +assertEq(check(fn_async), false); +assertEq(check(fn_generator), false); +assertEq(check(o.mtd), false) +assertEq(check(Object.getOwnPropertyDescriptor(o, "x").get), false) +assertEq(check(Object.getOwnPropertyDescriptor(o, "x").set), false) +assertEq(check(Base), false); +assertEq(check(Derived), false); +assertEq(check(builtin_selfhost), false); +assertEq(check(builtin_native), false); +assertEq(check(dot_caller), false); + +// Have a native invoke .caller on our behalf. +function foo() { + function inner() { + return callFunctionFromNativeFrame(dot_caller.bind(inner)) + } + return inner(); +} +assertEq(foo, foo()); diff --git a/js/src/jit-test/tests/arguments/inline-arguments-apply-rectifier.js b/js/src/jit-test/tests/arguments/inline-arguments-apply-rectifier.js new file mode 100644 index 0000000000..299b3cafec --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-apply-rectifier.js @@ -0,0 +1,40 @@ +// |jit-test| --fast-warmup + +function foo(a,b) { + with ({}) {} + return a + b; +} + +var obj = {}; +function inner(x,y) { + assertEq(x + y, foo.apply(obj, arguments)); +} + +function outer0() { + trialInline(); + inner(); +} + +function outer1() { + trialInline(); + inner(1); +} + +function outer2() { + trialInline(); + inner(1, 2); +} + +function outer3() { + trialInline(); + inner(1,2,3); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + outer0(); + outer1(); + outer2(); + outer3(); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-apply.js b/js/src/jit-test/tests/arguments/inline-arguments-apply.js new file mode 100644 index 0000000000..0d46785715 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-apply.js @@ -0,0 +1,46 @@ +// |jit-test| --fast-warmup + + +function foo(...args) { + with ({}) {} + return args.length; +} + +function inner() { + return foo.apply({}, arguments); +} + +function outer0() { + trialInline(); + return inner(); +} + +function outer1() { + trialInline(); + return inner(1); +} + +function outer2() { + trialInline(); + return inner(1, 2); +} + +function outer3() { + trialInline(); + return inner(1,2,3) +} + +function outer4() { + trialInline(); + return inner(1,2,3,4) +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), 0); + assertEq(outer1(), 1); + assertEq(outer2(), 2); + assertEq(outer3(), 3); + assertEq(outer4(), 4); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-callee.js b/js/src/jit-test/tests/arguments/inline-arguments-callee.js new file mode 100644 index 0000000000..f825839a0f --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-callee.js @@ -0,0 +1,16 @@ +function inner() { + return arguments.callee; +} +function inner_escaped() { + return arguments; +} +function outer() { + assertEq(inner(), inner); + assertEq(inner_escaped().callee, inner_escaped); + assertEq(arguments.callee, outer); +} + +with({}) {} +for (var i = 0; i < 100; i++) { + outer(); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-apply.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-apply.js new file mode 100644 index 0000000000..29230abb87 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-apply.js @@ -0,0 +1,45 @@ +// |jit-test| --fast-warmup + +function foo(...args) { + with ({}) {} + return args.length +} + +function inner() { + return arguments; +} + +function outer0() { + trialInline(); + return foo.apply({}, inner()); +} + +function outer1() { + trialInline(); + return foo.apply({}, inner(1)); +} + +function outer2() { + trialInline(); + return foo.apply({}, inner(1,2)); +} + +function outer3() { + trialInline(); + return foo.apply({}, inner(1,2,3)); +} + +function outer4() { + trialInline(); + return foo.apply({}, inner(1,2,3,4)); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), 0); + assertEq(outer1(), 1); + assertEq(outer2(), 2); + assertEq(outer3(), 3); + assertEq(outer4(), 4); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant-exists.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant-exists.js new file mode 100644 index 0000000000..d80959d4b6 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant-exists.js @@ -0,0 +1,40 @@ +// |jit-test| --fast-warmup + +function inner() { + return arguments +} + +function outer0() { + trialInline(); + return 1 in inner(); +} + +function outer1() { + trialInline(); + return 1 in inner(1); +} + +function outer2() { + trialInline(); + return 1 in inner(1, 2); +} + +function outer3() { + trialInline(); + return 1 in inner(1,2,3); +} + +function outer4() { + trialInline(); + return 1 in inner(1,2,3,4); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), false); + assertEq(outer1(), false); + assertEq(outer2(), true); + assertEq(outer3(), true); + assertEq(outer4(), true); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant-oob.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant-oob.js new file mode 100644 index 0000000000..052c564197 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant-oob.js @@ -0,0 +1,40 @@ +// |jit-test| --fast-warmup + +function inner() { + return arguments +} + +function outer0() { + trialInline(); + return inner()[100]; +} + +function outer1() { + trialInline(); + return inner(1)[100]; +} + +function outer2() { + trialInline(); + return inner(1, 2)[100]; +} + +function outer3() { + trialInline(); + return inner(1,2,3)[100] +} + +function outer4() { + trialInline(); + return inner(1,2,3,4)[100] +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), undefined); + assertEq(outer1(), undefined); + assertEq(outer2(), undefined); + assertEq(outer3(), undefined); + assertEq(outer4(), undefined); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant.js new file mode 100644 index 0000000000..1a5ffd3cfa --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-constant.js @@ -0,0 +1,40 @@ +// |jit-test| --fast-warmup + +function inner() { + return arguments +} + +function outer0() { + trialInline(); + return inner()[0]; +} + +function outer1() { + trialInline(); + return inner(1)[0]; +} + +function outer2() { + trialInline(); + return inner(1, 2)[0]; +} + +function outer3() { + trialInline(); + return inner(1,2,3)[0] +} + +function outer4() { + trialInline(); + return inner(1,2,3,4)[0] +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), undefined); + assertEq(outer1(), 1); + assertEq(outer2(), 1); + assertEq(outer3(), 1); + assertEq(outer4(), 1); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-var.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-var.js new file mode 100644 index 0000000000..4f3856dfe0 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-index-var.js @@ -0,0 +1,44 @@ +// |jit-test| --fast-warmup + +var idx; + +function inner() { + return arguments; +} + +function outer0() { + trialInline(); + return inner()[idx]; +} + +function outer1() { + trialInline(); + return inner(0)[idx]; +} + +function outer2() { + trialInline(); + return inner(0, 1)[idx]; +} + +function outer3() { + trialInline(); + return inner(0,1,2)[idx] +} + +function outer4() { + trialInline(); + return inner(0,1,2,3)[idx] +} + +with ({}) {} + +for (idx = 0; idx < 4; idx++) { + for (var i = 0; i < 50; i++) { + assertEq(outer0(), idx < 0 ? idx : undefined); + assertEq(outer1(), idx < 1 ? idx : undefined); + assertEq(outer2(), idx < 2 ? idx : undefined); + assertEq(outer3(), idx < 3 ? idx : undefined); + assertEq(outer4(), idx < 4 ? idx : undefined); + } +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-length.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-length.js new file mode 100644 index 0000000000..2c275dd3d6 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-length.js @@ -0,0 +1,42 @@ +// |jit-test| --fast-warmup + +var arg = 0; + +function inner() { + return arguments; +} + +function outer0() { + trialInline(); + return inner().length; +} + +function outer1() { + trialInline(); + return inner(arg).length; +} + +function outer2() { + trialInline(); + return inner(arg, arg).length; +} + +function outer3() { + trialInline(); + return inner(arg, arg, arg).length; +} + +function outer4() { + trialInline(); + return inner(arg, arg, arg, arg).length; +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), 0); + assertEq(outer1(), 1); + assertEq(outer2(), 2); + assertEq(outer3(), 3); + assertEq(outer4(), 4); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-new-spread-optimization.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-new-spread-optimization.js new file mode 100644 index 0000000000..e576339069 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-new-spread-optimization.js @@ -0,0 +1,50 @@ +// |jit-test| --fast-warmup + +function foo(...args) { + with ({}) {} + return {result: args.length}; +} + +function inner() { + return arguments; +} + +function outer0() { + trialInline(); + var args = inner(); + return new foo(...args); +} + +function outer1() { + trialInline(); + var args = inner(1); + return new foo(...args); +} + +function outer2() { + trialInline(); + var args = inner(1,2); + return new foo(...args); +} + +function outer3() { + trialInline(); + var args = inner(1,2,3); + return new foo(...args); +} + +function outer4() { + trialInline(); + var args = inner(1,2,3,4); + return new foo(...args); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0().result, 0); + assertEq(outer1().result, 1); + assertEq(outer2().result, 2); + assertEq(outer3().result, 3); + assertEq(outer4().result, 4); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-1.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-1.js new file mode 100644 index 0000000000..e428f87e89 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-1.js @@ -0,0 +1,50 @@ +// |jit-test| --fast-warmup + +function foo(args) { + with ({}) {} + return args.length; +} + +function inner() { + return arguments; +} + +function outer0() { + trialInline(); + var args = Array.prototype.slice.call(inner()); + return foo(args); +} + +function outer1() { + trialInline(); + var args = Array.prototype.slice.call(inner(1)); + return foo(args); +} + +function outer2() { + trialInline(); + var args = Array.prototype.slice.call(inner(1, 2)); + return foo(args); +} + +function outer3() { + trialInline(); + var args = Array.prototype.slice.call(inner(1, 2, 3)); + return foo(args); +} + +function outer4() { + trialInline(); + var args = Array.prototype.slice.call(inner(1, 2, 3, 4)); + return foo(args); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), 0); + assertEq(outer1(), 1); + assertEq(outer2(), 2); + assertEq(outer3(), 3); + assertEq(outer4(), 4); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-2.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-2.js new file mode 100644 index 0000000000..4c831b99f6 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-2.js @@ -0,0 +1,50 @@ +// |jit-test| --fast-warmup + +function foo(args) { + with ({}) {} + return args.length; +} + +function inner() { + return arguments; +} + +function outer0() { + trialInline(); + var args = Array.prototype.slice.call(inner(), 1); + return foo(args); +} + +function outer1() { + trialInline(); + var args = Array.prototype.slice.call(inner(1), 1); + return foo(args); +} + +function outer2() { + trialInline(); + var args = Array.prototype.slice.call(inner(1, 2), 1); + return foo(args); +} + +function outer3() { + trialInline(); + var args = Array.prototype.slice.call(inner(1, 2, 3), 1); + return foo(args); +} + +function outer4() { + trialInline(); + var args = Array.prototype.slice.call(inner(1, 2, 3, 4), 1); + return foo(args); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), 0); + assertEq(outer1(), 0); + assertEq(outer2(), 1); + assertEq(outer3(), 2); + assertEq(outer4(), 3); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-3.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-3.js new file mode 100644 index 0000000000..1e354140af --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-3.js @@ -0,0 +1,50 @@ +// |jit-test| --fast-warmup + +function foo(args) { + with ({}) {} + return args.length; +} + +function inner() { + return arguments; +} + +function outer0() { + trialInline(); + var args = Array.prototype.slice.call(inner(), -2); + return foo(args); +} + +function outer1() { + trialInline(); + var args = Array.prototype.slice.call(inner(1), -2); + return foo(args); +} + +function outer2() { + trialInline(); + var args = Array.prototype.slice.call(inner(1, 2), -2); + return foo(args); +} + +function outer3() { + trialInline(); + var args = Array.prototype.slice.call(inner(1, 2, 3), -2); + return foo(args); +} + +function outer4() { + trialInline(); + var args = Array.prototype.slice.call(inner(1, 2, 3, 4), -2); + return foo(args); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), 0); + assertEq(outer1(), 1); + assertEq(outer2(), 2); + assertEq(outer3(), 2); + assertEq(outer4(), 2); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-4.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-4.js new file mode 100644 index 0000000000..f12410b08f --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-slice-4.js @@ -0,0 +1,50 @@ +// |jit-test| --fast-warmup + +function foo(args) { + with ({}) {} + return args.length; +} + +function inner() { + return arguments; +} + +function outer0() { + trialInline(); + var args = Array.prototype.slice.call(inner(), 1, 3); + return foo(args); +} + +function outer1() { + trialInline(); + var args = Array.prototype.slice.call(inner(1), 1, 3); + return foo(args); +} + +function outer2() { + trialInline(); + var args = Array.prototype.slice.call(inner(1, 2), 1, 3); + return foo(args); +} + +function outer3() { + trialInline(); + var args = Array.prototype.slice.call(inner(1, 2, 3), 1, 3); + return foo(args); +} + +function outer4() { + trialInline(); + var args = Array.prototype.slice.call(inner(1, 2, 3, 4), 1, 3); + return foo(args); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), 0); + assertEq(outer1(), 0); + assertEq(outer2(), 1); + assertEq(outer3(), 2); + assertEq(outer4(), 2); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-escaped-spread-optimization.js b/js/src/jit-test/tests/arguments/inline-arguments-escaped-spread-optimization.js new file mode 100644 index 0000000000..a5092339e3 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-escaped-spread-optimization.js @@ -0,0 +1,50 @@ +// |jit-test| --fast-warmup + +function foo(...args) { + with ({}) {} + return args.length; +} + +function inner() { + return arguments; +} + +function outer0() { + trialInline(); + var args = inner(); + return foo(...args); +} + +function outer1() { + trialInline(); + var args = inner(1); + return foo(...args); +} + +function outer2() { + trialInline(); + var args = inner(1,2); + return foo(...args); +} + +function outer3() { + trialInline(); + var args = inner(1,2,3); + return foo(...args); +} + +function outer4() { + trialInline(); + var args = inner(1,2,3,4); + return foo(...args); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), 0); + assertEq(outer1(), 1); + assertEq(outer2(), 2); + assertEq(outer3(), 3); + assertEq(outer4(), 4); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-exists-negative-index-1.js b/js/src/jit-test/tests/arguments/inline-arguments-exists-negative-index-1.js new file mode 100644 index 0000000000..21dbbb0863 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-exists-negative-index-1.js @@ -0,0 +1,34 @@ +// |jit-test| --fast-warmup + +function inner(i) { + return i in arguments; +} + +function outer(i) { + trialInline(); + + // Loop header to trigger OSR. + let r = 0; + for (let j = 0; j < 1; ++j) { + r += inner(i, + // Add extra arguments to ensure we read the arguments from the frame. + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + ); + } + return r; +} + +let count = 0; + +for (let i = 0; i <= 100; ++i) { + if (i === 50) { + Object.prototype[-1] = 0; + } + count += outer(i < 100 ? i : -1); +} + +assertEq(count, 1 + 21); diff --git a/js/src/jit-test/tests/arguments/inline-arguments-exists-negative-index-2.js b/js/src/jit-test/tests/arguments/inline-arguments-exists-negative-index-2.js new file mode 100644 index 0000000000..52e877d549 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-exists-negative-index-2.js @@ -0,0 +1,27 @@ +// |jit-test| --fast-warmup + +function inner(i) { + return i in arguments; +} + +function outer(i) { + trialInline(); + + // Loop header to trigger OSR. + let r = 0; + for (let j = 0; j < 1; ++j) { + r += inner(i); + } + return r; +} + +let count = 0; + +for (let i = 0; i <= 100; ++i) { + if (i === 50) { + Object.prototype[-1] = 0; + } + count += outer(i < 100 ? i : -1); +} + +assertEq(count, 1 + 1); diff --git a/js/src/jit-test/tests/arguments/inline-arguments-formals.js b/js/src/jit-test/tests/arguments/inline-arguments-formals.js new file mode 100644 index 0000000000..8b081999b6 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-formals.js @@ -0,0 +1,37 @@ +// |jit-test| --fast-warmup + +var dummy; + +function inner(x,y) { + dummy = arguments.length; + return y; +} + +function outer0() { + trialInline(); + return inner(); +} + +function outer1() { + trialInline(); + return inner(0); +} + +function outer2() { + trialInline(); + return inner(0, 1); +} + +function outer3() { + trialInline(); + return inner(0,1,2); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), undefined); + assertEq(outer1(), undefined); + assertEq(outer2(), 1); + assertEq(outer3(), 1); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-index-constant-exists.js b/js/src/jit-test/tests/arguments/inline-arguments-index-constant-exists.js new file mode 100644 index 0000000000..f6f90c63a2 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-index-constant-exists.js @@ -0,0 +1,40 @@ +// |jit-test| --fast-warmup + +function inner() { + return 1 in arguments; +} + +function outer0() { + trialInline(); + return inner(); +} + +function outer1() { + trialInline(); + return inner(1); +} + +function outer2() { + trialInline(); + return inner(1, 2); +} + +function outer3() { + trialInline(); + return inner(1,2,3) +} + +function outer4() { + trialInline(); + return inner(1,2,3,4) +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), false); + assertEq(outer1(), false); + assertEq(outer2(), true); + assertEq(outer3(), true); + assertEq(outer4(), true); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-index-constant-oob.js b/js/src/jit-test/tests/arguments/inline-arguments-index-constant-oob.js new file mode 100644 index 0000000000..4e1dc925e1 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-index-constant-oob.js @@ -0,0 +1,40 @@ +// |jit-test| --fast-warmup + +function inner() { + return arguments[100] +} + +function outer0() { + trialInline(); + return inner(); +} + +function outer1() { + trialInline(); + return inner(1); +} + +function outer2() { + trialInline(); + return inner(1, 2); +} + +function outer3() { + trialInline(); + return inner(1,2,3) +} + +function outer4() { + trialInline(); + return inner(1,2,3,4) +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), undefined); + assertEq(outer1(), undefined); + assertEq(outer2(), undefined); + assertEq(outer3(), undefined); + assertEq(outer4(), undefined); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-index-constant.js b/js/src/jit-test/tests/arguments/inline-arguments-index-constant.js new file mode 100644 index 0000000000..41ef531d22 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-index-constant.js @@ -0,0 +1,40 @@ +// |jit-test| --fast-warmup + +function inner() { + return arguments[0] +} + +function outer0() { + trialInline(); + return inner(); +} + +function outer1() { + trialInline(); + return inner(1); +} + +function outer2() { + trialInline(); + return inner(1, 2); +} + +function outer3() { + trialInline(); + return inner(1,2,3) +} + +function outer4() { + trialInline(); + return inner(1,2,3,4) +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), undefined); + assertEq(outer1(), 1); + assertEq(outer2(), 1); + assertEq(outer3(), 1); + assertEq(outer4(), 1); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-index-var.js b/js/src/jit-test/tests/arguments/inline-arguments-index-var.js new file mode 100644 index 0000000000..21a71d2c29 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-index-var.js @@ -0,0 +1,44 @@ +// |jit-test| --fast-warmup + +var idx; + +function inner() { + return arguments[idx] +} + +function outer0() { + trialInline(); + return inner(); +} + +function outer1() { + trialInline(); + return inner(0); +} + +function outer2() { + trialInline(); + return inner(0, 1); +} + +function outer3() { + trialInline(); + return inner(0,1,2) +} + +function outer4() { + trialInline(); + return inner(0,1,2,3) +} + +with ({}) {} + +for (idx = 0; idx < 4; idx++) { + for (var i = 0; i < 50; i++) { + assertEq(outer0(), idx < 0 ? idx : undefined); + assertEq(outer1(), idx < 1 ? idx : undefined); + assertEq(outer2(), idx < 2 ? idx : undefined); + assertEq(outer3(), idx < 3 ? idx : undefined); + assertEq(outer4(), idx < 4 ? idx : undefined); + } +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-length.js b/js/src/jit-test/tests/arguments/inline-arguments-length.js new file mode 100644 index 0000000000..efd9dedaf7 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-length.js @@ -0,0 +1,42 @@ +// |jit-test| --fast-warmup + +var arg = 0; + +function inner() { + return arguments.length; +} + +function outer0() { + trialInline(); + return inner(); +} + +function outer1() { + trialInline(); + return inner(arg); +} + +function outer2() { + trialInline(); + return inner(arg, arg); +} + +function outer3() { + trialInline(); + return inner(arg, arg, arg); +} + +function outer4() { + trialInline(); + return inner(arg, arg, arg, arg); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), 0); + assertEq(outer1(), 1); + assertEq(outer2(), 2); + assertEq(outer3(), 3); + assertEq(outer4(), 4); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-new-spread-optimization-rectifier.js b/js/src/jit-test/tests/arguments/inline-arguments-new-spread-optimization-rectifier.js new file mode 100644 index 0000000000..6aa15d876f --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-new-spread-optimization-rectifier.js @@ -0,0 +1,39 @@ +// |jit-test| --fast-warmup + +function foo(a,b) { + with ({}) {} + return {result: a + b}; +} + +function inner(x,y) { + assertEq(x + y, new foo(...arguments).result); +} + +function outer0() { + trialInline(); + inner(); +} + +function outer1() { + trialInline(); + inner(1); +} + +function outer2() { + trialInline(); + inner(1, 2); +} + +function outer3() { + trialInline(); + inner(1,2,3); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + outer0(); + outer1(); + outer2(); + outer3(); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-new-spread-optimization.js b/js/src/jit-test/tests/arguments/inline-arguments-new-spread-optimization.js new file mode 100644 index 0000000000..2dab581e68 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-new-spread-optimization.js @@ -0,0 +1,47 @@ +// |jit-test| --fast-warmup + + +function foo(...args) { + with ({}) {} + return {result: args.length}; +} + +function inner() { + // Single argument spread calls with |arguments| can be optimised. + return new foo(...arguments); +} + +function outer0() { + trialInline(); + return inner(); +} + +function outer1() { + trialInline(); + return inner(1); +} + +function outer2() { + trialInline(); + return inner(1, 2); +} + +function outer3() { + trialInline(); + return inner(1,2,3) +} + +function outer4() { + trialInline(); + return inner(1,2,3,4) +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0().result, 0); + assertEq(outer1().result, 1); + assertEq(outer2().result, 2); + assertEq(outer3().result, 3); + assertEq(outer4().result, 4); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-oob-negative-index-1.js b/js/src/jit-test/tests/arguments/inline-arguments-oob-negative-index-1.js new file mode 100644 index 0000000000..b60140b3a6 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-oob-negative-index-1.js @@ -0,0 +1,39 @@ +// |jit-test| --fast-warmup + +function inner(i) { + // Can't be eliminated because negative indices cause a bailout. + arguments[i]; + arguments[i]; + arguments[i]; +} + +function outer(i) { + trialInline(); + + // Loop header to trigger OSR. + for (let j = 0; j < 1; ++j) { + inner(i, + // Add extra arguments to ensure we read the arguments from the frame. + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + ); + } +} + +let count = 0; + +for (let i = 0; i <= 100; ++i) { + if (i === 50) { + Object.defineProperty(Object.prototype, -1, { + get() { + count++; + } + }); + } + outer(i < 100 ? i : -1); +} + +assertEq(count, 3); diff --git a/js/src/jit-test/tests/arguments/inline-arguments-oob-negative-index-2.js b/js/src/jit-test/tests/arguments/inline-arguments-oob-negative-index-2.js new file mode 100644 index 0000000000..e5c9f0cd6e --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-oob-negative-index-2.js @@ -0,0 +1,32 @@ +// |jit-test| --fast-warmup + +function inner(i) { + // Can't be eliminated because negative indices cause a bailout. + arguments[i]; + arguments[i]; + arguments[i]; +} + +function outer(i) { + trialInline(); + + // Loop header to trigger OSR. + for (let j = 0; j < 1; ++j) { + inner(i); + } +} + +let count = 0; + +for (let i = 0; i <= 100; ++i) { + if (i === 50) { + Object.defineProperty(Object.prototype, -1, { + get() { + count++; + } + }); + } + outer(i < 100 ? i : -1); +} + +assertEq(count, 3); diff --git a/js/src/jit-test/tests/arguments/inline-arguments-profiler.js b/js/src/jit-test/tests/arguments/inline-arguments-profiler.js new file mode 100644 index 0000000000..6d89b3d72b --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-profiler.js @@ -0,0 +1,11 @@ +function foo() { return arguments; } +function bar(x) { return foo(x); } + +// Turning on the profiler uses up a register and increases register pressure. +enableGeckoProfiling(); +with ({}) {} +for (var i = 0; i < 100; i++) { + var result = bar(3); + assertEq(result.length, 1); + assertEq(result[0], 3); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-1.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-1.js new file mode 100644 index 0000000000..19021aae4a --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-1.js @@ -0,0 +1,46 @@ +// |jit-test| --fast-warmup + + +function foo(args) { + with ({}) {} + return args.length; +} + +function inner() { + return foo(Array.prototype.slice.call(arguments)); +} + +function outer0() { + trialInline(); + return inner(); +} + +function outer1() { + trialInline(); + return inner(1); +} + +function outer2() { + trialInline(); + return inner(1, 2); +} + +function outer3() { + trialInline(); + return inner(1, 2, 3) +} + +function outer4() { + trialInline(); + return inner(1, 2, 3, 4) +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), 0); + assertEq(outer1(), 1); + assertEq(outer2(), 2); + assertEq(outer3(), 3); + assertEq(outer4(), 4); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-2.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-2.js new file mode 100644 index 0000000000..f3af77f844 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-2.js @@ -0,0 +1,46 @@ +// |jit-test| --fast-warmup + + +function foo(args) { + with ({}) {} + return args.length; +} + +function inner() { + return foo(Array.prototype.slice.call(arguments, 1)); +} + +function outer0() { + trialInline(); + return inner(); +} + +function outer1() { + trialInline(); + return inner(1); +} + +function outer2() { + trialInline(); + return inner(1, 2); +} + +function outer3() { + trialInline(); + return inner(1, 2, 3) +} + +function outer4() { + trialInline(); + return inner(1, 2, 3, 4) +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), 0); + assertEq(outer1(), 0); + assertEq(outer2(), 1); + assertEq(outer3(), 2); + assertEq(outer4(), 3); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-3.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-3.js new file mode 100644 index 0000000000..af16586d6c --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-3.js @@ -0,0 +1,46 @@ +// |jit-test| --fast-warmup + + +function foo(args) { + with ({}) {} + return args.length; +} + +function inner() { + return foo(Array.prototype.slice.call(arguments, -2)); +} + +function outer0() { + trialInline(); + return inner(); +} + +function outer1() { + trialInline(); + return inner(1); +} + +function outer2() { + trialInline(); + return inner(1, 2); +} + +function outer3() { + trialInline(); + return inner(1, 2, 3) +} + +function outer4() { + trialInline(); + return inner(1, 2, 3, 4) +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), 0); + assertEq(outer1(), 1); + assertEq(outer2(), 2); + assertEq(outer3(), 2); + assertEq(outer4(), 2); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-4.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-4.js new file mode 100644 index 0000000000..26cf0563af --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-4.js @@ -0,0 +1,46 @@ +// |jit-test| --fast-warmup + + +function foo(args) { + with ({}) {} + return args.length; +} + +function inner() { + return foo(Array.prototype.slice.call(arguments, 1, 3)); +} + +function outer0() { + trialInline(); + return inner(); +} + +function outer1() { + trialInline(); + return inner(1); +} + +function outer2() { + trialInline(); + return inner(1, 2); +} + +function outer3() { + trialInline(); + return inner(1, 2, 3) +} + +function outer4() { + trialInline(); + return inner(1, 2, 3, 4) +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), 0); + assertEq(outer1(), 0); + assertEq(outer2(), 1); + assertEq(outer3(), 2); + assertEq(outer4(), 2); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-5.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-5.js new file mode 100644 index 0000000000..725b14b752 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-5.js @@ -0,0 +1,97 @@ +// |jit-test| --fast-warmup + +function blackhole() { + // Prevent Ion from optimising away this function and its arguments. + with ({}); +} + +function inner() { + // Compile-time constants after GVN, but not during scalar replacement. + // We don't want these to be constants during scalar replacement to ensure + // we don't optimise away the slice() call. + const zero = Math.pow(0, 1); + const one = Math.pow(1, 1); + const two = Math.pow(2, 1); + const three = Math.pow(3, 1); + const four = Math.pow(4, 1); + + // Test with constant |begin| and |count| a constant after GVN. + { + let a0 = Array.prototype.slice.call(arguments, 0, zero); + let a1 = Array.prototype.slice.call(arguments, 0, one); + let a2 = Array.prototype.slice.call(arguments, 0, two); + let a3 = Array.prototype.slice.call(arguments, 0, three); + let a4 = Array.prototype.slice.call(arguments, 0, four); + blackhole(a0, a1, a2, a3, a4); + } + { + let a0 = Array.prototype.slice.call(arguments, 1, zero); + let a1 = Array.prototype.slice.call(arguments, 1, one); + let a2 = Array.prototype.slice.call(arguments, 1, two); + let a3 = Array.prototype.slice.call(arguments, 1, three); + let a4 = Array.prototype.slice.call(arguments, 1, four); + blackhole(a0, a1, a2, a3, a4); + } + + // Same as above, but this time |begin| isn't a constant during scalar replacement. + { + let a0 = Array.prototype.slice.call(arguments, zero, zero); + let a1 = Array.prototype.slice.call(arguments, zero, one); + let a2 = Array.prototype.slice.call(arguments, zero, two); + let a3 = Array.prototype.slice.call(arguments, zero, three); + let a4 = Array.prototype.slice.call(arguments, zero, four); + blackhole(a0, a1, a2, a3, a4); + } + { + let a0 = Array.prototype.slice.call(arguments, one, zero); + let a1 = Array.prototype.slice.call(arguments, one, one); + let a2 = Array.prototype.slice.call(arguments, one, two); + let a3 = Array.prototype.slice.call(arguments, one, three); + let a4 = Array.prototype.slice.call(arguments, one, four); + blackhole(a0, a1, a2, a3, a4); + } +} + +// Ensure |inner| can be inlined. +assertEq(isSmallFunction(inner), true); + +// Zero arguments. +function outer0() { + trialInline(); + return inner(); +} + +// One argument. +function outer1() { + trialInline(); + return inner(1); +} + +// Two arguments. +function outer2() { + trialInline(); + return inner(1, 2); +} + +// Three arguments. +function outer3() { + trialInline(); + return inner(1, 2, 3); +} + +// Four arguments. (|inner| can't be inlined anymore!) +function outer4() { + trialInline(); + return inner(1, 2, 3, 4); +} + +// Don't Ion compile the top-level script. +with ({}); + +for (var i = 0; i < 50; i++) { + outer0(); + outer1(); + outer2(); + outer3(); + outer4(); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-1.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-1.js new file mode 100644 index 0000000000..f17d6b20a9 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-1.js @@ -0,0 +1,40 @@ +// |jit-test| --fast-warmup + +function foo(a, b) { + with ({}) {} + return a + b; +} + +function inner(x, y) { + var args = Array.prototype.slice.call(arguments); + assertEq(x + y, foo(args[0], args[1])); +} + +function outer0() { + trialInline(); + inner(); +} + +function outer1() { + trialInline(); + inner(1); +} + +function outer2() { + trialInline(); + inner(1, 2); +} + +function outer3() { + trialInline(); + inner(1, 2, 3); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + outer0(); + outer1(); + outer2(); + outer3(); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-2.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-2.js new file mode 100644 index 0000000000..ad6f8cfcd5 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-2.js @@ -0,0 +1,40 @@ +// |jit-test| --fast-warmup + +function foo(a, b) { + with ({}) {} + return a + b; +} + +function inner(x, y, z) { + var args = Array.prototype.slice.call(arguments, 1); + assertEq(y + z, foo(args[0], args[1])); +} + +function outer0() { + trialInline(); + inner(); +} + +function outer1() { + trialInline(); + inner(1); +} + +function outer2() { + trialInline(); + inner(1, 2); +} + +function outer3() { + trialInline(); + inner(1, 2, 3); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + outer0(); + outer1(); + outer2(); + outer3(); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-3.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-3.js new file mode 100644 index 0000000000..083c4ace68 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-3.js @@ -0,0 +1,40 @@ +// |jit-test| --fast-warmup + +function foo(a, b) { + with ({}) {} + return a + b; +} + +function inner(x, y, z) { + var args = Array.prototype.slice.call(arguments, -2); + assertEq((z !== undefined ? y + z : x + y), foo(args[0], args[1])); +} + +function outer0() { + trialInline(); + inner(); +} + +function outer1() { + trialInline(); + inner(1); +} + +function outer2() { + trialInline(); + inner(1, 2); +} + +function outer3() { + trialInline(); + inner(1, 2, 3); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + outer0(); + outer1(); + outer2(); + outer3(); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-4.js b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-4.js new file mode 100644 index 0000000000..a7a63d77a8 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-slice-rectifier-4.js @@ -0,0 +1,40 @@ +// |jit-test| --fast-warmup + +function foo(a, b) { + with ({}) {} + return a + b; +} + +function inner(w, x, y, z) { + var args = Array.prototype.slice.call(arguments, 1, 3); + assertEq(x + y, foo(args[0], args[1])); +} + +function outer0() { + trialInline(); + inner(); +} + +function outer1() { + trialInline(); + inner(1); +} + +function outer2() { + trialInline(); + inner(1, 2); +} + +function outer3() { + trialInline(); + inner(1, 2, 3); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + outer0(); + outer1(); + outer2(); + outer3(); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-spread-optimization-rectifier.js b/js/src/jit-test/tests/arguments/inline-arguments-spread-optimization-rectifier.js new file mode 100644 index 0000000000..a89abcdc0b --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-spread-optimization-rectifier.js @@ -0,0 +1,39 @@ +// |jit-test| --fast-warmup + +function foo(a,b) { + with ({}) {} + return a + b; +} + +function inner(x,y) { + assertEq(x + y, foo(...arguments)); +} + +function outer0() { + trialInline(); + inner(); +} + +function outer1() { + trialInline(); + inner(1); +} + +function outer2() { + trialInline(); + inner(1, 2); +} + +function outer3() { + trialInline(); + inner(1,2,3); +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + outer0(); + outer1(); + outer2(); + outer3(); +} diff --git a/js/src/jit-test/tests/arguments/inline-arguments-spread-optimization.js b/js/src/jit-test/tests/arguments/inline-arguments-spread-optimization.js new file mode 100644 index 0000000000..21505e9437 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-arguments-spread-optimization.js @@ -0,0 +1,47 @@ +// |jit-test| --fast-warmup + + +function foo(...args) { + with ({}) {} + return args.length; +} + +function inner() { + // Single argument spread calls with |arguments| can be optimised. + return foo(...arguments); +} + +function outer0() { + trialInline(); + return inner(); +} + +function outer1() { + trialInline(); + return inner(1); +} + +function outer2() { + trialInline(); + return inner(1, 2); +} + +function outer3() { + trialInline(); + return inner(1,2,3) +} + +function outer4() { + trialInline(); + return inner(1,2,3,4) +} + +with ({}) {} + +for (var i = 0; i < 50; i++) { + assertEq(outer0(), 0); + assertEq(outer1(), 1); + assertEq(outer2(), 2); + assertEq(outer3(), 3); + assertEq(outer4(), 4); +} diff --git a/js/src/jit-test/tests/arguments/inline-rest-array-creation.js b/js/src/jit-test/tests/arguments/inline-rest-array-creation.js new file mode 100644 index 0000000000..34998d4cb4 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-rest-array-creation.js @@ -0,0 +1,83 @@ +function zero(...rest) +{ + assertEq(rest.length, 0, "zero rest wrong length"); +} + +function tzero() +{ + zero(); +} + +tzero(); tzero(); tzero(); + +function one(...rest) +{ + assertEq(rest.length, 1, "one rest wrong length"); +} + +function tone() +{ + one(0); +} + +tone(); tone(); tone(); + +function two(...rest) +{ + assertEq(rest.length, 2, "two rest wrong length"); +} + +function ttwo() +{ + two(0, 1); +} + +ttwo(); ttwo(); ttwo(); + +function zeroWithLeading0(x, ...rest) +{ + assertEq(rest.length, 0, "zeroWithLeading0 rest wrong length"); +} + +function tzeroWithLeading0() +{ + zeroWithLeading0(); +} + +tzeroWithLeading0(); tzeroWithLeading0(); tzeroWithLeading0(); + +function zeroWithLeading1(x, ...rest) +{ + assertEq(rest.length, 0, "zeroWithLeading1 rest wrong length"); +} + +function tzeroWithLeading1() +{ + zeroWithLeading1(0); +} + +tzeroWithLeading1(); tzeroWithLeading1(); tzeroWithLeading1(); + +function oneWithLeading(x, ...rest) +{ + assertEq(rest.length, 1, "oneWithLeading rest wrong length"); +} + +function toneWithLeading() +{ + oneWithLeading(0, 1); +} + +toneWithLeading(); toneWithLeading(); toneWithLeading(); + +function twoWithLeading(x, ...rest) +{ + assertEq(rest.length, 2, "twoWithLeading rest wrong length"); +} + +function ttwoWithLeading() +{ + twoWithLeading(0, 1, 2); +} + +ttwoWithLeading(); ttwoWithLeading(); ttwoWithLeading(); diff --git a/js/src/jit-test/tests/arguments/inline-transpile.js b/js/src/jit-test/tests/arguments/inline-transpile.js new file mode 100644 index 0000000000..0720256593 --- /dev/null +++ b/js/src/jit-test/tests/arguments/inline-transpile.js @@ -0,0 +1,17 @@ +function foo(i) { + return i; +} + +function bar(n) { + return foo.apply({}, arguments); +} + +function baz(a, n) { + return bar(n); +} + +var sum = 0; +for (var i = 0; i < 10000; i++) { + sum += baz(0, 1); +} +assertEq(sum, 10000); diff --git a/js/src/jit-test/tests/arguments/iterator-set-and-redefine.js b/js/src/jit-test/tests/arguments/iterator-set-and-redefine.js new file mode 100644 index 0000000000..bcf182790f --- /dev/null +++ b/js/src/jit-test/tests/arguments/iterator-set-and-redefine.js @@ -0,0 +1,33 @@ +function mapped() { + var Iterator = {}; + + // First overwrite the iterator. + arguments[Symbol.iterator] = Iterator; + + // And then redefine a property attribute. + Object.defineProperty(arguments, Symbol.iterator, { + writable: false + }); + + // Make sure redefining an attribute doesn't reset the iterator value. + assertEq(arguments[Symbol.iterator], Iterator); +} +mapped(); + +function unmapped() { + "use strict"; + + var Iterator = {}; + + // First overwrite the iterator. + arguments[Symbol.iterator] = Iterator; + + // And then redefine a property attribute. + Object.defineProperty(arguments, Symbol.iterator, { + writable: false + }); + + // Make sure redefining an attribute doesn't reset the iterator value. + assertEq(arguments[Symbol.iterator], Iterator); +} +unmapped(); diff --git a/js/src/jit-test/tests/arguments/mapped-define.js b/js/src/jit-test/tests/arguments/mapped-define.js new file mode 100644 index 0000000000..0c806f618b --- /dev/null +++ b/js/src/jit-test/tests/arguments/mapped-define.js @@ -0,0 +1,81 @@ +load(libdir + "asserts.js"); + +function testMapped(a) { + assertEq(arguments[0], 1); + + Object.defineProperty(arguments, 0, {value: 23, writable: true, configurable: true}); + assertEq(arguments[0], 23); + assertEq(a, 23); + + a = 12; + assertEq(a, 12); + assertEq(arguments[0], 12); + + Object.defineProperty(arguments, 0, {value: 9, writable: false, configurable: false}); + assertEq(arguments[0], 9); + assertEq(a, 9); + + a = 4; + assertEq(arguments[0], 9); + assertEq(a, 4); +} +for (var i = 0; i < 5; i++) { + testMapped(1); +} + +function testAttributes(x) { + Object.defineProperty(arguments, 0, {enumerable:true, + writable:true, + configurable:true, + value: 4}); + + // Should inherit enumerable/configurable attributes. + Object.defineProperty(arguments, 0, {writable:true, + value: 8}); + assertEq(JSON.stringify(Object.getOwnPropertyDescriptor(arguments, 0)), + '{"value":8,"writable":true,"enumerable":true,"configurable":true}'); + assertEq(x, 8); + + // Property becomes non-configurable. + Object.defineProperty(arguments, 0, {writable:true, + configurable:false, + value: 6}); + assertEq(JSON.stringify(Object.getOwnPropertyDescriptor(arguments, 0)), + '{"value":6,"writable":true,"enumerable":true,"configurable":false}'); + assertEq(x, 6); + + // Can no longer make it non-enumerable. + assertThrowsInstanceOf(() => Object.defineProperty(arguments, 0, {writable:true, + configurable:false, + enumerable:false, + value: 6}), + TypeError); + + // Can no longer make it configurable. + assertThrowsInstanceOf(() => Object.defineProperty(arguments, 0, {writable:true, + configurable:true, + value: 6}), + TypeError); + + // Can still make it non-writable. + Object.defineProperty(arguments, 0, {writable:false, + enumerable:true, + configurable:false, + value: 3}); + assertEq(x, 3); + + // No longer a mapped property. + x = 5; + assertEq(arguments[0], 3); + + // Can no longer make it writable. + assertThrowsInstanceOf(() => Object.defineProperty(arguments, 0, {writable:true, + enumerable:true, + configurable:false, + value: 5}), + TypeError); + assertEq(x, 5); +} +for (var i = 0; i < 5; i++) { + testAttributes(i); +} diff --git a/js/src/jit-test/tests/arguments/mapped-freeze.js b/js/src/jit-test/tests/arguments/mapped-freeze.js new file mode 100644 index 0000000000..e60cb24233 --- /dev/null +++ b/js/src/jit-test/tests/arguments/mapped-freeze.js @@ -0,0 +1,8 @@ +function f(a) { + Object.freeze(arguments); + a = 1; + return arguments[0]; +} + +assertEq(f(10), 10); +assertEq(f("hello"), "hello"); diff --git a/js/src/jit-test/tests/arguments/mapped-unmapped-args.js b/js/src/jit-test/tests/arguments/mapped-unmapped-args.js new file mode 100644 index 0000000000..d1b063be3d --- /dev/null +++ b/js/src/jit-test/tests/arguments/mapped-unmapped-args.js @@ -0,0 +1,61 @@ +// An unmapped arguments object is created for strict functions or functions +// with default/rest/destructuring args. + +load(libdir + "asserts.js"); + +function testDefaults(a, b=3) { + a = 3; + b = 4; + assertEq(arguments.length, 1); + assertEq(arguments[0], 1); + assertEq(arguments[1], undefined); + arguments[0] = 5; + assertEq(a, 3); + assertThrowsInstanceOf(() => arguments.callee, TypeError); +} +testDefaults(1); + +function testRest(a, ...rest) { + a = 3; + assertEq(arguments.length, 3); + assertEq(arguments[0], 1); + assertEq(arguments[1], 2); + arguments[0] = 5; + assertEq(a, 3); + arguments[1] = 6; + assertEq(arguments[1], 6); + assertEq(rest.toString(), "2,3"); + assertThrowsInstanceOf(() => arguments.callee, TypeError); +} +testRest(1, 2, 3); + +function testDestructuring(a, {foo, bar}, b) { + a = 3; + bar = 4; + b = 1; + assertEq(arguments.length, 3); + assertEq(arguments[0], 1); + assertEq(arguments[1].bar, 2); + assertEq(arguments[2], 9); + assertThrowsInstanceOf(() => arguments.callee, TypeError); +} +testDestructuring(1, {foo: 1, bar: 2}, 9); + +function testStrict(a) { + "use strict"; + a = 3; + assertEq(arguments[0], 1); + arguments[0] = 8; + assertEq(a, 3); + assertThrowsInstanceOf(() => arguments.callee, TypeError); +} +testStrict(1, 2); + +function testMapped(a) { + a = 3; + assertEq(arguments[0], 3); + arguments[0] = 5; + assertEq(a, 5); + assertEq(arguments.callee, testMapped); +} +testMapped(1); diff --git a/js/src/jit-test/tests/arguments/nonstrict-args.js b/js/src/jit-test/tests/arguments/nonstrict-args.js new file mode 100644 index 0000000000..750bcc1e78 --- /dev/null +++ b/js/src/jit-test/tests/arguments/nonstrict-args.js @@ -0,0 +1,24 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function args(a) { return arguments; } + +var a1, a2, a3, a4; + +for (var i = 0; i < 5; i++) +{ + a1 = args(); + a2 = args(1); + a3 = args(1, obj); + a4 = args("foopy"); +} + +assertEq(arraysEqual(a1, []), true); +assertEq(arraysEqual(a2, [1]), true); +assertEq(arraysEqual(a3, [1, obj]), true); +assertEq(arraysEqual(a4, ["foopy"]), true); diff --git a/js/src/jit-test/tests/arguments/nonstrict-assign-element-get-parameter.js b/js/src/jit-test/tests/arguments/nonstrict-assign-element-get-parameter.js new file mode 100644 index 0000000000..c55588daa4 --- /dev/null +++ b/js/src/jit-test/tests/arguments/nonstrict-assign-element-get-parameter.js @@ -0,0 +1,13 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function assignElementGetParameter(a) +{ + arguments[0] = 17; + return a; +} + +for (var i = 0; i < 5; i++) + assertEq(assignElementGetParameter(42), 17); diff --git a/js/src/jit-test/tests/arguments/nonstrict-assign-parameter-get-element.js b/js/src/jit-test/tests/arguments/nonstrict-assign-parameter-get-element.js new file mode 100644 index 0000000000..747abbad31 --- /dev/null +++ b/js/src/jit-test/tests/arguments/nonstrict-assign-parameter-get-element.js @@ -0,0 +1,13 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function assignParameterGetElement(a) +{ + a = 17; + return arguments[0]; +} + +for (var i = 0; i < 5; i++) + assertEq(assignParameterGetElement(42), 17); diff --git a/js/src/jit-test/tests/arguments/nonstrict-assign.js b/js/src/jit-test/tests/arguments/nonstrict-assign.js new file mode 100644 index 0000000000..8dd75e7209 --- /dev/null +++ b/js/src/jit-test/tests/arguments/nonstrict-assign.js @@ -0,0 +1,17 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +function assign(a) +{ + a = 17; + return arguments; +} + +var a1; +for (var i = 0; i < 5; i++) + a1 = assign(1); + +assertEq(arraysEqual(a1, [17]), true); diff --git a/js/src/jit-test/tests/arguments/nonstrict-later-assign.js b/js/src/jit-test/tests/arguments/nonstrict-later-assign.js new file mode 100644 index 0000000000..fbf72abc4c --- /dev/null +++ b/js/src/jit-test/tests/arguments/nonstrict-later-assign.js @@ -0,0 +1,18 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +function getLaterAssign(a) +{ + var o = arguments; + a = 17; + return o; +} + +var a1, a2; +for (var i = 0; i < 5; i++) + a1 = getLaterAssign(1); + +assertEq(arraysEqual(a1, [17]), true); diff --git a/js/src/jit-test/tests/arguments/nonstrict-noargs.js b/js/src/jit-test/tests/arguments/nonstrict-noargs.js new file mode 100644 index 0000000000..ef1bca7dee --- /dev/null +++ b/js/src/jit-test/tests/arguments/nonstrict-noargs.js @@ -0,0 +1,21 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function noargs() { return arguments; } + +var a1, a2, a3; +for (var i = 0; i < 5; i++) +{ + a1 = noargs(); + a2 = noargs(1); + a3 = noargs(2, obj, 8); +} + +assertEq(arraysEqual(a1, []), true); +assertEq(arraysEqual(a2, [1]), true); +assertEq(arraysEqual(a3, [2, obj, 8]), true); diff --git a/js/src/jit-test/tests/arguments/polymorphic-getelem.js b/js/src/jit-test/tests/arguments/polymorphic-getelem.js new file mode 100644 index 0000000000..95672c7ca7 --- /dev/null +++ b/js/src/jit-test/tests/arguments/polymorphic-getelem.js @@ -0,0 +1,15 @@ +function foo(s) { + return arguments[s]; +} + +for (var i = 0; i < 100; i++) { + assertEq(foo("callee"), foo); +} + +for (var i = 0; i < 100; i++) { + assertEq(foo("length"), 1); +} + +for (var i = 0; i < 100; i++) { + assertEq(foo(0), 0); +} diff --git a/js/src/jit-test/tests/arguments/recover-osr-arguments-oob.js b/js/src/jit-test/tests/arguments/recover-osr-arguments-oob.js new file mode 100644 index 0000000000..72e322dd85 --- /dev/null +++ b/js/src/jit-test/tests/arguments/recover-osr-arguments-oob.js @@ -0,0 +1,27 @@ +setJitCompilerOption("baseline.warmup.trigger", 0); +setJitCompilerOption("ion.warmup.trigger", 120); +gczeal(0); +with ({}) {} + +function bar(i) { + // |arguments| can be recovered, even if this is inlined into an OSR script. + assertRecoveredOnBailout(arguments, true); + return arguments[i & 1]|0; +} + +function foo(n) { + // |arguments| for an OSR script can't be recovered. + assertRecoveredOnBailout(arguments, false); + var sum = 0; + for (var i = 0; i < n; i++) { + sum += bar(i); + } + trialInline(); + return sum; +} + +// Trigger trial-inlining of bar into foo. +foo(110); + +// OSR-compile foo. +assertEq(foo(1000), 249500); diff --git a/js/src/jit-test/tests/arguments/recover-osr-arguments.js b/js/src/jit-test/tests/arguments/recover-osr-arguments.js new file mode 100644 index 0000000000..88756d4a54 --- /dev/null +++ b/js/src/jit-test/tests/arguments/recover-osr-arguments.js @@ -0,0 +1,27 @@ +setJitCompilerOption("baseline.warmup.trigger", 0); +setJitCompilerOption("ion.warmup.trigger", 120); +gczeal(0); +with ({}) {} + +function bar() { + // |arguments| can be recovered, even if this is inlined into an OSR script. + assertRecoveredOnBailout(arguments, true); + return arguments[0]; +} + +function foo(n) { + // |arguments| for an OSR script can't be recovered. + assertRecoveredOnBailout(arguments, false); + var sum = 0; + for (var i = 0; i < n; i++) { + sum += bar(i); + } + trialInline(); + return sum; +} + +// Trigger trial-inlining of bar into foo. +foo(110); + +// OSR-compile foo. +assertEq(foo(1000), 499500); diff --git a/js/src/jit-test/tests/arguments/recover-spread-opt-arguments-after-bail.js b/js/src/jit-test/tests/arguments/recover-spread-opt-arguments-after-bail.js new file mode 100644 index 0000000000..c8c76c278a --- /dev/null +++ b/js/src/jit-test/tests/arguments/recover-spread-opt-arguments-after-bail.js @@ -0,0 +1,22 @@ +function outer(fn, x, y) { + fn(...arguments); +} + +function inner1(fn, x, y) { + assertEq(fn, inner1); + assertEq(x, y); +} + +function inner2(fn, x, y) { + assertEq(fn, inner2); + assertEq(x, 100); + assertEq(y, 200); +} + +for (let i = 0; i < 100; i++) { + outer(inner1, i, i); +} + +// Call with a different function to cause a bailout. This will lead to +// recovering the |arguments| object. +outer(inner2, 100, 200); diff --git a/js/src/jit-test/tests/arguments/redefine-callee.js b/js/src/jit-test/tests/arguments/redefine-callee.js new file mode 100644 index 0000000000..c200f5326d --- /dev/null +++ b/js/src/jit-test/tests/arguments/redefine-callee.js @@ -0,0 +1,31 @@ +function test() { + let count = 0; + for (var i = 0; i < 30; i++) { + assertEq(arguments.callee, i > 20 ? 3 : test); + if (i === 20) { + Object.defineProperty(arguments, "callee", {get: function() { count++; return 3; }}); + } + } + assertEq(count, 9); +} +test(); + +function testUnusedResult() { + let count = 0; + for (var i = 0; i < 30; i++) { + arguments.callee; + if (i === 20) { + Object.defineProperty(arguments, "callee", {get: function() { count++; return 3; }}); + } + } + assertEq(count, 9); +} +testUnusedResult(); + +function testSetter() { + Object.defineProperty(arguments, "callee", {set: function() {}}); + for (var i = 0; i < 15; i++) { + assertEq(arguments.callee, undefined); + } +} +testSetter(); diff --git a/js/src/jit-test/tests/arguments/rest-alias-function.js b/js/src/jit-test/tests/arguments/rest-alias-function.js new file mode 100644 index 0000000000..1dda665210 --- /dev/null +++ b/js/src/jit-test/tests/arguments/rest-alias-function.js @@ -0,0 +1,10 @@ +function no_defaults(a, ...rest) { + return rest; + function rest() { return a; } +} +assertEq(typeof no_defaults(), "function"); +function with_defaults(a=42, ...rest) { + return rest; + function rest() { return a; } +} +assertEq(typeof with_defaults(), "function"); diff --git a/js/src/jit-test/tests/arguments/rest-arguments-as-parameters.js b/js/src/jit-test/tests/arguments/rest-arguments-as-parameters.js new file mode 100644 index 0000000000..120b0ce1c0 --- /dev/null +++ b/js/src/jit-test/tests/arguments/rest-arguments-as-parameters.js @@ -0,0 +1,9 @@ +function f1(...arguments) { + assertEq("1,2,3", arguments.toString()); +} +f1(1, 2, 3); +function f2(arguments, ...rest) { + assertEq(arguments, 42); + assertEq("1,2,3", rest.toString()); +} +f2(42, 1, 2, 3);
\ No newline at end of file diff --git a/js/src/jit-test/tests/arguments/rest-basic.js b/js/src/jit-test/tests/arguments/rest-basic.js new file mode 100644 index 0000000000..cb050d13b3 --- /dev/null +++ b/js/src/jit-test/tests/arguments/rest-basic.js @@ -0,0 +1,15 @@ +function check(expected, ...rest) { + assertEq(expected.toString(), rest.toString()); +} + +assertEq(check.length, 1); +check([]); +check(['a', 'b'], 'a', 'b'); +check(['a', 'b', 'c', 'd'], 'a', 'b', 'c', 'd'); +check.apply(null, [['a', 'b'], 'a', 'b']) +check.call(null, ['a', 'b'], 'a', 'b') + +var g = newGlobal(); +g.eval("function f(...rest) { return rest; }"); +var a = g.f(1, 2, 3); +assertEq(a instanceof g.Array, true);
\ No newline at end of file diff --git a/js/src/jit-test/tests/arguments/rest-bug763954.js b/js/src/jit-test/tests/arguments/rest-bug763954.js new file mode 100644 index 0000000000..3884abf8e2 --- /dev/null +++ b/js/src/jit-test/tests/arguments/rest-bug763954.js @@ -0,0 +1,5 @@ +for (i in ['']) {} +function f(...patterns) { + patterns[i]; +}; +f(''); diff --git a/js/src/jit-test/tests/arguments/rest-debugger.js b/js/src/jit-test/tests/arguments/rest-debugger.js new file mode 100644 index 0000000000..be9016a07c --- /dev/null +++ b/js/src/jit-test/tests/arguments/rest-debugger.js @@ -0,0 +1,17 @@ +var g = newGlobal({newCompartment: true}); +g.eval("function f(...x) {}"); +var dbg = new Debugger; +var gw = dbg.addDebuggee(g); +var fw = gw.getOwnPropertyDescriptor("f").value; +assertEq(fw.parameterNames.toString(), "x"); + +var g = newGlobal({newCompartment: true}); +g.eval("function f(...rest) { debugger; }"); +var dbg = Debugger(g); +dbg.onDebuggerStatement = function (frame) { + frame.eval("args = arguments"); +}; +g.f(9, 8, 7); + +assertEq(g.args.length, 3); +assertEq(g.args[2], 7); diff --git a/js/src/jit-test/tests/arguments/rest-disallow-arguments-strict.js b/js/src/jit-test/tests/arguments/rest-disallow-arguments-strict.js new file mode 100644 index 0000000000..7f54e5ef7a --- /dev/null +++ b/js/src/jit-test/tests/arguments/rest-disallow-arguments-strict.js @@ -0,0 +1,8 @@ +"use strict"; +load(libdir + "asserts.js"); +assertThrowsInstanceOf(function () { + eval("(function (...arguments) {})"); +}, SyntaxError); +assertThrowsInstanceOf(function () { + eval("(function (...eval) {})"); +}, SyntaxError); diff --git a/js/src/jit-test/tests/arguments/rest-in-Function.js b/js/src/jit-test/tests/arguments/rest-in-Function.js new file mode 100644 index 0000000000..e2966be691 --- /dev/null +++ b/js/src/jit-test/tests/arguments/rest-in-Function.js @@ -0,0 +1,3 @@ +h = Function("a", "b", "c", "...rest", "return rest.toString();"); +assertEq(h.length, 3); +assertEq(h(1, 2, 3, 4, 5), "4,5"); diff --git a/js/src/jit-test/tests/arguments/rest-invalid-syntax.js b/js/src/jit-test/tests/arguments/rest-invalid-syntax.js new file mode 100644 index 0000000000..f91d93ea62 --- /dev/null +++ b/js/src/jit-test/tests/arguments/rest-invalid-syntax.js @@ -0,0 +1,12 @@ +load(libdir + "asserts.js"); +var ieval = eval; +var offenders = [["..."], ["...rest"," x"], ["...rest", "[x]"], + ["...rest", "...rest2"]]; +for (var arglist of offenders) { + assertThrowsInstanceOf(function () { + ieval("function x(" + arglist.join(", ") + ") {}"); + }, SyntaxError); + assertThrowsInstanceOf(function () { + Function.apply(null, arglist.concat("return 0;")); + }, SyntaxError); +}
\ No newline at end of file diff --git a/js/src/jit-test/tests/arguments/rest-nested-arguments.js b/js/src/jit-test/tests/arguments/rest-nested-arguments.js new file mode 100644 index 0000000000..18f5ca56df --- /dev/null +++ b/js/src/jit-test/tests/arguments/rest-nested-arguments.js @@ -0,0 +1,7 @@ +function f(...rest) { + function nested() { + return arguments.length; + } + return nested; +} +assertEq(f()(1, 2, 3), 3); diff --git a/js/src/jit-test/tests/arguments/rest-nested.js b/js/src/jit-test/tests/arguments/rest-nested.js new file mode 100644 index 0000000000..0ad82e5475 --- /dev/null +++ b/js/src/jit-test/tests/arguments/rest-nested.js @@ -0,0 +1,7 @@ +function f(...rest) { + function nested () { + return rest; + } + return nested; +} +assertEq(f(1, 2, 3)().toString(), [1, 2, 3].toString());
\ No newline at end of file diff --git a/js/src/jit-test/tests/arguments/rest-underflow.js b/js/src/jit-test/tests/arguments/rest-underflow.js new file mode 100644 index 0000000000..bb9b39c50b --- /dev/null +++ b/js/src/jit-test/tests/arguments/rest-underflow.js @@ -0,0 +1,9 @@ +function f(a, b, c, ...rest) { + assertEq(a, 1); + assertEq(b, undefined); + assertEq(c, undefined); + assertEq(Array.isArray(rest), true); + assertEq(rest.length, 0); + assertEq(Object.getPrototypeOf(rest), Array.prototype); +} +f(1); diff --git a/js/src/jit-test/tests/arguments/rest-with-arguments.js b/js/src/jit-test/tests/arguments/rest-with-arguments.js new file mode 100644 index 0000000000..7dfc63c739 --- /dev/null +++ b/js/src/jit-test/tests/arguments/rest-with-arguments.js @@ -0,0 +1,40 @@ +// 'arguments' is allowed with rest parameters. + +var args; + +function restWithArgs(a, b, ...rest) { + return arguments; +} + +args = restWithArgs(1, 3, 6, 9); +assertEq(args.length, 4); +assertEq(JSON.stringify(args), '{"0":1,"1":3,"2":6,"3":9}'); + +args = restWithArgs(); +assertEq(args.length, 0); + +args = restWithArgs(4, 5); +assertEq(args.length, 2); +assertEq(JSON.stringify(args), '{"0":4,"1":5}'); + +function restWithArgsEval(a, b, ...rest) { + return eval("arguments"); +} + +args = restWithArgsEval(1, 3, 6, 9); +assertEq(args.length, 4); +assertEq(JSON.stringify(args), '{"0":1,"1":3,"2":6,"3":9}'); + +function g(...rest) { + h(); +} +function h() { + g.arguments; +} +g(); + +// eval() is evil, but you can still use it with rest parameters! +function still_use_eval(...rest) { + eval("x = 4"); +} +still_use_eval(); diff --git a/js/src/jit-test/tests/arguments/slice-args-obj-01.js b/js/src/jit-test/tests/arguments/slice-args-obj-01.js new file mode 100644 index 0000000000..6d3a826d8e --- /dev/null +++ b/js/src/jit-test/tests/arguments/slice-args-obj-01.js @@ -0,0 +1,19 @@ +function escape(x) { with ({}) {} } + +function foo() { + escape(arguments); + var args = Array.prototype.slice.call(arguments); + return bar(args[0], args[1]); +} + +function bar(x, y) { + return x + y; +} + +with ({}) {} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1, 2); +} +assertEq(sum, 300); diff --git a/js/src/jit-test/tests/arguments/slice-args-obj-02.js b/js/src/jit-test/tests/arguments/slice-args-obj-02.js new file mode 100644 index 0000000000..03581fbdf0 --- /dev/null +++ b/js/src/jit-test/tests/arguments/slice-args-obj-02.js @@ -0,0 +1,17 @@ +function foo() { + arguments[0] = 3; + var args = Array.prototype.slice.call(arguments); + return bar(args[0], args[1]); +} + +function bar(x, y) { + return x + y; +} + +with ({}) {} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1, 2); +} +assertEq(sum, 500); diff --git a/js/src/jit-test/tests/arguments/slice-args-obj-03.js b/js/src/jit-test/tests/arguments/slice-args-obj-03.js new file mode 100644 index 0000000000..3205580229 --- /dev/null +++ b/js/src/jit-test/tests/arguments/slice-args-obj-03.js @@ -0,0 +1,21 @@ +function escape() { with ({}) {} } + +function foo(i) { + return i; +} + +function bar(n) { + escape(arguments); + var args = Array.prototype.slice.call(arguments); + return foo(args[0]); +} + +function baz(a, n) { + return bar(n); +} + +var sum = 0; +for (var i = 0; i < 10000; i++) { + sum += baz(0, 1); +} +assertEq(sum, 10000); diff --git a/js/src/jit-test/tests/arguments/slice-args-obj-04.js b/js/src/jit-test/tests/arguments/slice-args-obj-04.js new file mode 100644 index 0000000000..2cddb3351b --- /dev/null +++ b/js/src/jit-test/tests/arguments/slice-args-obj-04.js @@ -0,0 +1,22 @@ +var result; + +function g(a, b) { + with ({}) {} + result = a + b; +} + +function escape() { with({}) {} } + +function f() { + escape(arguments); + for (var i = 0; i < 50; ++i) { + var args = Array.prototype.slice.call(arguments); + g(args[0], args[1]); + } +} + +f(1, 2); +assertEq(result, 3); + +f(""); +assertEq(result, "undefined"); diff --git a/js/src/jit-test/tests/arguments/slice-closed-over-arguments-strict.js b/js/src/jit-test/tests/arguments/slice-closed-over-arguments-strict.js new file mode 100644 index 0000000000..71815f0b43 --- /dev/null +++ b/js/src/jit-test/tests/arguments/slice-closed-over-arguments-strict.js @@ -0,0 +1,17 @@ +"use strict"; + +function bar(x, y) { + return x + y; +} + +function foo(x, y) { + function closeOver() { return x; } + var args = Array.prototype.slice.call(arguments); + return bar(args[0], args[1]); +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1, 2); +} +assertEq(sum, 300) diff --git a/js/src/jit-test/tests/arguments/slice-closed-over-arguments.js b/js/src/jit-test/tests/arguments/slice-closed-over-arguments.js new file mode 100644 index 0000000000..4a61c4005b --- /dev/null +++ b/js/src/jit-test/tests/arguments/slice-closed-over-arguments.js @@ -0,0 +1,15 @@ +function bar(x, y) { + return x + y; +} + +function foo(x, y) { + function closeOver() { return x; } + var args = Array.prototype.slice.call(arguments); + return bar(args[0], args[1]); +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1, 2); +} +assertEq(sum, 300) diff --git a/js/src/jit-test/tests/arguments/slice-redefine-length.js b/js/src/jit-test/tests/arguments/slice-redefine-length.js new file mode 100644 index 0000000000..9b776064d7 --- /dev/null +++ b/js/src/jit-test/tests/arguments/slice-redefine-length.js @@ -0,0 +1,19 @@ +function foo() { + arguments.length = 2; + var args = Array.prototype.slice.call(arguments); + return bar(args); +} + +function bar(args) { + var result = 0; + for (var x of args) { + result += x; + } + return result; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1, 2, 3, 4, 5, 6); +} +assertEq(sum, 300); diff --git a/js/src/jit-test/tests/arguments/slice.js b/js/src/jit-test/tests/arguments/slice.js new file mode 100644 index 0000000000..3ab3d82b67 --- /dev/null +++ b/js/src/jit-test/tests/arguments/slice.js @@ -0,0 +1,366 @@ +// Tests when |arguments| are used with Array.prototype.slice. + +function testBasic() { + // Return the number of arguments. + function argslen() { return arguments.length; } + + // Return the first argument. + function arg0() { return arguments[0]; } + + // Return the argument at the request index. + function argIndex(i) { return arguments[i]; } + + // Call the above functions when no formals are present. + function noFormalsLen() { return argslen(...Array.prototype.slice.call(arguments)); } + function noFormals0() { return arg0(...Array.prototype.slice.call(arguments)); } + function noFormalsIndex() { return argIndex(...Array.prototype.slice.call(arguments)); } + + // Call the above functions when some formals are present. + function formalsLen(x, y, z) { return argslen(...Array.prototype.slice.call(arguments)); } + function formals0(x, y, z) { return arg0(...Array.prototype.slice.call(arguments)); } + function formalsIndex(x, y, z) { return argIndex(...Array.prototype.slice.call(arguments)); } + + // Call the above functions when a rest argument is present. + function restLen(...rest) { return argslen(...Array.prototype.slice.call(arguments)); } + function rest0(...rest) { return arg0(...Array.prototype.slice.call(arguments)); } + function restIndex(...rest) { return argIndex(...Array.prototype.slice.call(arguments)); } + + // Call the above functions when default parameters are present. + function defaultLen(x = 0) { return argslen(...Array.prototype.slice.call(arguments)); } + function default0(x = 0) { return arg0(...Array.prototype.slice.call(arguments)); } + function defaultIndex(x = 0) { return argIndex(...Array.prototype.slice.call(arguments)); } + + for (let i = 0; i < 100; ++i) { + assertEq(noFormalsLen(), 0); + assertEq(noFormalsLen(1), 1); + assertEq(noFormalsLen(1, 2, 3), 3); + + assertEq(formalsLen(), 0); + assertEq(formalsLen(1), 1); + assertEq(formalsLen(1, 2, 3), 3); + + assertEq(restLen(), 0); + assertEq(restLen(1), 1); + assertEq(restLen(1, 2, 3), 3); + + assertEq(defaultLen(), 0); + assertEq(defaultLen(1), 1); + assertEq(defaultLen(1, 2, 3), 3); + + assertEq(noFormals0(), undefined); + assertEq(noFormals0(100), 100); + assertEq(noFormals0(100, 200, 300), 100); + + assertEq(formals0(), undefined); + assertEq(formals0(100), 100); + assertEq(formals0(100, 200, 300), 100); + + assertEq(rest0(), undefined); + assertEq(rest0(100), 100); + assertEq(rest0(100, 200, 300), 100); + + assertEq(default0(), undefined); + assertEq(default0(100), 100); + assertEq(default0(100, 200, 300), 100); + + assertEq(noFormalsIndex(), undefined); + assertEq(noFormalsIndex(0), 0); + assertEq(noFormalsIndex(0, 100), 0); + assertEq(noFormalsIndex(0, 100, 200, 300), 0); + assertEq(noFormalsIndex(1, 100), 100); + assertEq(noFormalsIndex(1, 100, 200, 300), 100); + + assertEq(formalsIndex(), undefined); + assertEq(formalsIndex(0), 0); + assertEq(formalsIndex(0, 100), 0); + assertEq(formalsIndex(0, 100, 200, 300), 0); + assertEq(formalsIndex(1, 100), 100); + assertEq(formalsIndex(1, 100, 200, 300), 100); + + assertEq(restIndex(), undefined); + assertEq(restIndex(0), 0); + assertEq(restIndex(0, 100), 0); + assertEq(restIndex(0, 100, 200, 300), 0); + assertEq(restIndex(1, 100), 100); + assertEq(restIndex(1, 100, 200, 300), 100); + + assertEq(defaultIndex(), undefined); + assertEq(defaultIndex(0), 0); + assertEq(defaultIndex(0, 100), 0); + assertEq(defaultIndex(0, 100, 200, 300), 0); + assertEq(defaultIndex(1, 100), 100); + assertEq(defaultIndex(1, 100, 200, 300), 100); + } +} +testBasic(); + +// Same as testBasic, except that the first argument is removed. +function testRemoveFirst() { + // Return the number of arguments. + function argslen() { return arguments.length; } + + // Return the first argument. + function arg0() { return arguments[0]; } + + // Return the argument at the request index. + function argIndex(i) { return arguments[i]; } + + // Call the above functions when no formals are present. + function noFormalsLen() { return argslen(...Array.prototype.slice.call(arguments, 1)); } + function noFormals0() { return arg0(...Array.prototype.slice.call(arguments, 1)); } + function noFormalsIndex() { return argIndex(...Array.prototype.slice.call(arguments, 1)); } + + // Call the above functions when some formals are present. + function formalsLen(x, y, z) { return argslen(...Array.prototype.slice.call(arguments, 1)); } + function formals0(x, y, z) { return arg0(...Array.prototype.slice.call(arguments, 1)); } + function formalsIndex(x, y, z) { return argIndex(...Array.prototype.slice.call(arguments, 1)); } + + // Call the above functions when a rest argument is present. + function restLen(...rest) { return argslen(...Array.prototype.slice.call(arguments, 1)); } + function rest0(...rest) { return arg0(...Array.prototype.slice.call(arguments, 1)); } + function restIndex(...rest) { return argIndex(...Array.prototype.slice.call(arguments, 1)); } + + // Call the above functions when default parameters are present. + function defaultLen(x = 0) { return argslen(...Array.prototype.slice.call(arguments, 1)); } + function default0(x = 0) { return arg0(...Array.prototype.slice.call(arguments, 1)); } + function defaultIndex(x = 0) { return argIndex(...Array.prototype.slice.call(arguments, 1)); } + + for (let i = 0; i < 100; ++i) { + assertEq(noFormalsLen(), 0); + assertEq(noFormalsLen(1), 0); + assertEq(noFormalsLen(1, 2, 3), 2); + + assertEq(formalsLen(), 0); + assertEq(formalsLen(1), 0); + assertEq(formalsLen(1, 2, 3), 2); + + assertEq(restLen(), 0); + assertEq(restLen(1), 0); + assertEq(restLen(1, 2, 3), 2); + + assertEq(defaultLen(), 0); + assertEq(defaultLen(1), 0); + assertEq(defaultLen(1, 2, 3), 2); + + assertEq(noFormals0(), undefined); + assertEq(noFormals0(100), undefined); + assertEq(noFormals0(100, 200, 300), 200); + + assertEq(formals0(), undefined); + assertEq(formals0(100), undefined); + assertEq(formals0(100, 200, 300), 200); + + assertEq(rest0(), undefined); + assertEq(rest0(100), undefined); + assertEq(rest0(100, 200, 300), 200); + + assertEq(default0(), undefined); + assertEq(default0(100), undefined); + assertEq(default0(100, 200, 300), 200); + + assertEq(noFormalsIndex(), undefined); + assertEq(noFormalsIndex(0), undefined); + assertEq(noFormalsIndex(0, 100), undefined); + assertEq(noFormalsIndex(0, 0, 100), 0); + assertEq(noFormalsIndex(0, 0, 100, 200, 300), 0); + assertEq(noFormalsIndex(0, 1, 100), 100); + assertEq(noFormalsIndex(0, 1, 100, 200, 300), 100); + + assertEq(formalsIndex(), undefined); + assertEq(formalsIndex(0), undefined); + assertEq(formalsIndex(0, 100), undefined); + assertEq(formalsIndex(0, 0, 100), 0); + assertEq(formalsIndex(0, 0, 100, 200, 300), 0); + assertEq(formalsIndex(0, 1, 100), 100); + assertEq(formalsIndex(0, 1, 100, 200, 300), 100); + + assertEq(restIndex(), undefined); + assertEq(restIndex(0), undefined); + assertEq(restIndex(0, 0), 0); + assertEq(restIndex(0, 0, 100), 0); + assertEq(restIndex(0, 0, 100, 200, 300), 0); + assertEq(restIndex(0, 1, 100), 100); + assertEq(restIndex(0, 1, 100, 200, 300), 100); + + assertEq(defaultIndex(), undefined); + assertEq(defaultIndex(0), undefined); + assertEq(defaultIndex(0, 0), 0); + assertEq(defaultIndex(0, 0, 100), 0); + assertEq(defaultIndex(0, 0, 100, 200, 300), 0); + assertEq(defaultIndex(0, 1, 100), 100); + assertEq(defaultIndex(0, 1, 100, 200, 300), 100); + } +} +testRemoveFirst(); + +// Same as testBasic, except that the last argument is removed. +function testRemoveLast() { + // Return the number of arguments. + function argslen() { return arguments.length; } + + // Return the first argument. + function arg0() { return arguments[0]; } + + // Return the argument at the request index. + function argIndex(i) { return arguments[i]; } + + // Call the above functions when no formals are present. + function noFormalsLen() { return argslen(...Array.prototype.slice.call(arguments, 0, -1)); } + function noFormals0() { return arg0(...Array.prototype.slice.call(arguments, 0, -1)); } + function noFormalsIndex() { return argIndex(...Array.prototype.slice.call(arguments, 0, -1)); } + + // Call the above functions when some formals are present. + function formalsLen(x, y, z) { return argslen(...Array.prototype.slice.call(arguments, 0, -1)); } + function formals0(x, y, z) { return arg0(...Array.prototype.slice.call(arguments, 0, -1)); } + function formalsIndex(x, y, z) { return argIndex(...Array.prototype.slice.call(arguments, 0, -1)); } + + // Call the above functions when a rest argument is present. + function restLen(...rest) { return argslen(...Array.prototype.slice.call(arguments, 0, -1)); } + function rest0(...rest) { return arg0(...Array.prototype.slice.call(arguments, 0, -1)); } + function restIndex(...rest) { return argIndex(...Array.prototype.slice.call(arguments, 0, -1)); } + + // Call the above functions when default parameters are present. + function defaultLen(x = 0) { return argslen(...Array.prototype.slice.call(arguments, 0, -1)); } + function default0(x = 0) { return arg0(...Array.prototype.slice.call(arguments, 0, -1)); } + function defaultIndex(x = 0) { return argIndex(...Array.prototype.slice.call(arguments, 0, -1)); } + + for (let i = 0; i < 100; ++i) { + assertEq(noFormalsLen(), 0); + assertEq(noFormalsLen(1), 0); + assertEq(noFormalsLen(1, 2, 3), 2); + + assertEq(formalsLen(), 0); + assertEq(formalsLen(1), 0); + assertEq(formalsLen(1, 2, 3), 2); + + assertEq(restLen(), 0); + assertEq(restLen(1), 0); + assertEq(restLen(1, 2, 3), 2); + + assertEq(defaultLen(), 0); + assertEq(defaultLen(1), 0); + assertEq(defaultLen(1, 2, 3), 2); + + assertEq(noFormals0(), undefined); + assertEq(noFormals0(100), undefined); + assertEq(noFormals0(100, 200, 300), 100); + + assertEq(formals0(), undefined); + assertEq(formals0(100), undefined); + assertEq(formals0(100, 200, 300), 100); + + assertEq(rest0(), undefined); + assertEq(rest0(100), undefined); + assertEq(rest0(100, 200, 300), 100); + + assertEq(default0(), undefined); + assertEq(default0(100), undefined); + assertEq(default0(100, 200, 300), 100); + + assertEq(noFormalsIndex(), undefined); + assertEq(noFormalsIndex(0), undefined); + assertEq(noFormalsIndex(0, 100), 0); + assertEq(noFormalsIndex(0, 100, 200, 300), 0); + assertEq(noFormalsIndex(1, 100), undefined); + assertEq(noFormalsIndex(1, 100, 200, 300), 100); + + assertEq(formalsIndex(), undefined); + assertEq(formalsIndex(0), undefined); + assertEq(formalsIndex(0, 100), 0); + assertEq(formalsIndex(0, 100, 200, 300), 0); + assertEq(formalsIndex(1, 100), undefined); + assertEq(formalsIndex(1, 100, 200, 300), 100); + + assertEq(restIndex(), undefined); + assertEq(restIndex(0), undefined); + assertEq(restIndex(0, 100), 0); + assertEq(restIndex(0, 100, 200, 300), 0); + assertEq(restIndex(1, 100), undefined); + assertEq(restIndex(1, 100, 200, 300), 100); + + assertEq(defaultIndex(), undefined); + assertEq(defaultIndex(0), undefined); + assertEq(defaultIndex(0, 100), 0); + assertEq(defaultIndex(0, 100, 200, 300), 0); + assertEq(defaultIndex(1, 100), undefined); + assertEq(defaultIndex(1, 100, 200, 300), 100); + } +} +testRemoveLast(); + +function testOverriddenLength() { + function g(x, y = 0) { + return x + y; + } + + function f(i) { + if (i === 100) { + arguments.length = 1; + } + var args = Array.prototype.slice.call(arguments); + return g.apply(null, args); + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i, i), i !== 100 ? i * 2 : i); + } +} +testOverriddenLength(); + +function testOverriddenElement() { + function g(x, y) { + return x + y; + } + + function f(i) { + if (i === 100) { + arguments[1] = 0; + } + var args = Array.prototype.slice.call(arguments); + return g(args[0], args[1]); + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i, i), i !== 100 ? i * 2 : i); + } +} +testOverriddenElement(); + +function testDeletedElement() { + function g(x, y = 0) { + return x + y; + } + + function f(i) { + if (i === 100) { + delete arguments[1]; + } + var args = Array.prototype.slice.call(arguments); + return g.apply(null, args); + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i, i), i !== 100 ? i * 2 : i); + } +} +testDeletedElement(); + +function testForwardedArg() { + function g(x, y) { + return x + y; + } + + function f(i) { + function closedOver() { + if (i === 100) i = 0; + } + closedOver(); + var args = Array.prototype.slice.call(arguments); + return g(args[0], args[1]); + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i, i), i !== 100 ? i * 2 : i); + } +} +testForwardedArg(); diff --git a/js/src/jit-test/tests/arguments/spread-args-obj-01.js b/js/src/jit-test/tests/arguments/spread-args-obj-01.js new file mode 100644 index 0000000000..2528922a4a --- /dev/null +++ b/js/src/jit-test/tests/arguments/spread-args-obj-01.js @@ -0,0 +1,18 @@ +function escape(x) { with ({}) {} } + +function foo() { + escape(arguments); + return bar(...arguments); +} + +function bar(x,y) { + return x + y; +} + +with ({}) {} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 300); diff --git a/js/src/jit-test/tests/arguments/spread-args-obj-02.js b/js/src/jit-test/tests/arguments/spread-args-obj-02.js new file mode 100644 index 0000000000..6bb14851c5 --- /dev/null +++ b/js/src/jit-test/tests/arguments/spread-args-obj-02.js @@ -0,0 +1,16 @@ +function foo() { + arguments[0] = 3; + return bar(...arguments); +} + +function bar(x,y) { + return x + y; +} + +with ({}) {} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 500); diff --git a/js/src/jit-test/tests/arguments/spread-args-obj-03.js b/js/src/jit-test/tests/arguments/spread-args-obj-03.js new file mode 100644 index 0000000000..702884272a --- /dev/null +++ b/js/src/jit-test/tests/arguments/spread-args-obj-03.js @@ -0,0 +1,20 @@ +function escape() { with ({}) {} } + +function foo(i) { + return i; +} + +function bar(n) { + escape(arguments); + return foo(...arguments); +} + +function baz(a, n) { + return bar(n); +} + +var sum = 0; +for (var i = 0; i < 10000; i++) { + sum += baz(0, 1); +} +assertEq(sum, 10000); diff --git a/js/src/jit-test/tests/arguments/spread-args-obj-04.js b/js/src/jit-test/tests/arguments/spread-args-obj-04.js new file mode 100644 index 0000000000..b72322a365 --- /dev/null +++ b/js/src/jit-test/tests/arguments/spread-args-obj-04.js @@ -0,0 +1,21 @@ +var result; + +function g(a, b) { + with ({}) {} + result = a + b; +} + +function escape() { with({}) {} } + +function f() { + escape(arguments); + for (var i = 0; i < 50; ++i) { + g(...arguments); + } +} + +f(1, 2); +assertEq(result, 3); + +f(""); +assertEq(result, "undefined"); diff --git a/js/src/jit-test/tests/arguments/spread-call-optimization.js b/js/src/jit-test/tests/arguments/spread-call-optimization.js new file mode 100644 index 0000000000..5ebc68de36 --- /dev/null +++ b/js/src/jit-test/tests/arguments/spread-call-optimization.js @@ -0,0 +1,216 @@ +// Tests when |arguments| are used in optimized spread calls. + +function testBasic() { + // Return the number of arguments. + function argslen() { return arguments.length; } + + // Return the first argument. + function arg0() { return arguments[0]; } + + // Return the argument at the request index. + function argIndex(i) { return arguments[i]; } + + // Call the above functions when no formals are present. + function noFormalsLen() { return argslen(...arguments); } + function noFormals0() { return arg0(...arguments); } + function noFormalsIndex() { return argIndex(...arguments); } + + // Call the above functions when some formals are present. + function formalsLen(x, y, z) { return argslen(...arguments); } + function formals0(x, y, z) { return arg0(...arguments); } + function formalsIndex(x, y, z) { return argIndex(...arguments); } + + // Call the above functions when a rest argument is present. + function restLen(...rest) { return argslen(...arguments); } + function rest0(...rest) { return arg0(...arguments); } + function restIndex(...rest) { return argIndex(...arguments); } + + // Call the above functions when default parameters are present. + function defaultLen(x = 0) { return argslen(...arguments); } + function default0(x = 0) { return arg0(...arguments); } + function defaultIndex(x = 0) { return argIndex(...arguments); } + + for (let i = 0; i < 100; ++i) { + assertEq(noFormalsLen(), 0); + assertEq(noFormalsLen(1), 1); + assertEq(noFormalsLen(1, 2, 3), 3); + + assertEq(formalsLen(), 0); + assertEq(formalsLen(1), 1); + assertEq(formalsLen(1, 2, 3), 3); + + assertEq(restLen(), 0); + assertEq(restLen(1), 1); + assertEq(restLen(1, 2, 3), 3); + + assertEq(defaultLen(), 0); + assertEq(defaultLen(1), 1); + assertEq(defaultLen(1, 2, 3), 3); + + assertEq(noFormals0(), undefined); + assertEq(noFormals0(100), 100); + assertEq(noFormals0(100, 200, 300), 100); + + assertEq(formals0(), undefined); + assertEq(formals0(100), 100); + assertEq(formals0(100, 200, 300), 100); + + assertEq(rest0(), undefined); + assertEq(rest0(100), 100); + assertEq(rest0(100, 200, 300), 100); + + assertEq(default0(), undefined); + assertEq(default0(100), 100); + assertEq(default0(100, 200, 300), 100); + + assertEq(noFormalsIndex(), undefined); + assertEq(noFormalsIndex(0), 0); + assertEq(noFormalsIndex(0, 100), 0); + assertEq(noFormalsIndex(0, 100, 200, 300), 0); + assertEq(noFormalsIndex(1, 100), 100); + assertEq(noFormalsIndex(1, 100, 200, 300), 100); + + assertEq(formalsIndex(), undefined); + assertEq(formalsIndex(0), 0); + assertEq(formalsIndex(0, 100), 0); + assertEq(formalsIndex(0, 100, 200, 300), 0); + assertEq(formalsIndex(1, 100), 100); + assertEq(formalsIndex(1, 100, 200, 300), 100); + + assertEq(restIndex(), undefined); + assertEq(restIndex(0), 0); + assertEq(restIndex(0, 100), 0); + assertEq(restIndex(0, 100, 200, 300), 0); + assertEq(restIndex(1, 100), 100); + assertEq(restIndex(1, 100, 200, 300), 100); + + assertEq(defaultIndex(), undefined); + assertEq(defaultIndex(0), 0); + assertEq(defaultIndex(0, 100), 0); + assertEq(defaultIndex(0, 100, 200, 300), 0); + assertEq(defaultIndex(1, 100), 100); + assertEq(defaultIndex(1, 100, 200, 300), 100); + } +} +testBasic(); + +function testOverriddenIterator() { + function g(x) { + return x; + } + + function f(i) { + if (i === 100) { + arguments[Symbol.iterator] = function() { + return ["bad"].values(); + }; + } + return g(...arguments); + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i), i !== 100 ? i : "bad"); + } +} +testOverriddenIterator(); + +function testOverriddenLength() { + function g(x, y = 0) { + return x + y; + } + + function f(i) { + if (i === 100) { + arguments.length = 1; + } + return g(...arguments); + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i, i), i !== 100 ? i * 2 : i); + } +} +testOverriddenLength(); + +function testOverriddenElement() { + function g(x, y) { + return x + y; + } + + function f(i) { + if (i === 100) { + arguments[1] = 0; + } + return g(...arguments); + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i, i), i !== 100 ? i * 2 : i); + } +} +testOverriddenElement(); + +function testDeletedElement() { + function g(x, y = 0) { + return x + y; + } + + function f(i) { + if (i === 100) { + delete arguments[1]; + } + return g(...arguments); + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i, i), i !== 100 ? i * 2 : i); + } +} +testDeletedElement(); + +function testForwardedArg() { + function g(x, y) { + return x + y; + } + + function f(i) { + function closedOver() { + if (i === 100) i = 0; + } + closedOver(); + return g(...arguments); + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i, i), i !== 100 ? i * 2 : i); + } +} +testForwardedArg(); + +function testModifiedArrayIteratorPrototype() { + function g(x, y) { + return x + y; + } + + const ArrayIteratorPrototype = Reflect.getPrototypeOf([][Symbol.iterator]()); + const ArrayIteratorPrototypeNext = ArrayIteratorPrototype.next; + function newNext() { + var result = ArrayIteratorPrototypeNext.call(this); + if (!result.done) { + result.value *= 2; + } + return result; + } + + function f(i) { + if (i === 100) { + ArrayIteratorPrototype.next = newNext; + } + return g(...arguments); + } + + for (let i = 0; i <= 150; ++i) { + assertEq(f(i, i), i < 100 ? i * 2 : i * 4); + } +} +testModifiedArrayIteratorPrototype(); diff --git a/js/src/jit-test/tests/arguments/spread-closed-over-arguments-strict.js b/js/src/jit-test/tests/arguments/spread-closed-over-arguments-strict.js new file mode 100644 index 0000000000..05ce6ec831 --- /dev/null +++ b/js/src/jit-test/tests/arguments/spread-closed-over-arguments-strict.js @@ -0,0 +1,15 @@ +'use strict' +function bar(x,y) { + return x + y; +} + +function foo(x, y) { + function closeOver() { return x; } + return bar(...arguments); +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 300) diff --git a/js/src/jit-test/tests/arguments/spread-closed-over-arguments.js b/js/src/jit-test/tests/arguments/spread-closed-over-arguments.js new file mode 100644 index 0000000000..15dd800ae3 --- /dev/null +++ b/js/src/jit-test/tests/arguments/spread-closed-over-arguments.js @@ -0,0 +1,14 @@ +function bar(x,y) { + return x + y; +} + +function foo(x, y) { + function closeOver() { return x; } + return bar(...arguments); +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2); +} +assertEq(sum, 300) diff --git a/js/src/jit-test/tests/arguments/spread-redefine-length.js b/js/src/jit-test/tests/arguments/spread-redefine-length.js new file mode 100644 index 0000000000..8c62ddd5d9 --- /dev/null +++ b/js/src/jit-test/tests/arguments/spread-redefine-length.js @@ -0,0 +1,18 @@ +function foo() { + arguments.length = 2; + return bar(...arguments); +} + +function bar() { + var result = 0; + for (var x of arguments) { + result += x; + } + return result; +} + +var sum = 0; +for (var i = 0; i < 100; i++) { + sum += foo(1,2,3,4,5,6); +} +assertEq(sum,300); diff --git a/js/src/jit-test/tests/arguments/strict-args-flushstack.js b/js/src/jit-test/tests/arguments/strict-args-flushstack.js new file mode 100644 index 0000000000..257018ba3f --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-args-flushstack.js @@ -0,0 +1,27 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +var args; + +function test() +{ + "use strict"; + eval("args = arguments;"); + var a = []; + for (var i = 0; i < 9; i++) + a.push(arguments); + return a; +} + +var a = test(); + +assertEq(Array.isArray(a), true); +assertEq(a.length, 9); + +var count = 0; +a.forEach(function(v, i) { count++; assertEq(v, args); }); +assertEq(count, 9); + +assertEq(Object.prototype.toString.call(args), "[object Arguments]"); +assertEq(args.length, 0); diff --git a/js/src/jit-test/tests/arguments/strict-args-generator-flushstack.js b/js/src/jit-test/tests/arguments/strict-args-generator-flushstack.js new file mode 100644 index 0000000000..ecef5dde74 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-args-generator-flushstack.js @@ -0,0 +1,27 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +var args; + +function* upToTen() +{ + "use strict"; + eval("args = arguments;"); + for (var i = 0; i < 9; i++) + yield i; +} + +var gen = upToTen(); + +var i = 0; +for (var v of gen) +{ + assertEq(v, i); + i++; +} + +assertEq(i, 9); + +assertEq(Object.prototype.toString.call(args), "[object Arguments]"); +assertEq(args.length, 0); diff --git a/js/src/jit-test/tests/arguments/strict-args.js b/js/src/jit-test/tests/arguments/strict-args.js new file mode 100644 index 0000000000..c6d68b2b1f --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-args.js @@ -0,0 +1,25 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function strictArgs(a) +{ + "use strict"; + return arguments; +} + +var a1, a2, a3; +for (var i = 0; i < 9; i++) +{ + a1 = strictArgs(); + a2 = strictArgs(1); + a3 = strictArgs(1, obj); +} + +assertEq(arraysEqual(a1, []), true); +assertEq(arraysEqual(a2, [1]), true); +assertEq(arraysEqual(a3, [1, obj]), true); diff --git a/js/src/jit-test/tests/arguments/strict-assign-after.js b/js/src/jit-test/tests/arguments/strict-assign-after.js new file mode 100644 index 0000000000..b295321c3b --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-assign-after.js @@ -0,0 +1,28 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +var upper; +function strictAssignAfter(a) +{ + "use strict"; + upper = arguments; + a = 42; + return upper; +} + +var a1, a2, a3; +for (var i = 0; i < 5; i++) +{ + a1 = strictAssignAfter(); + a2 = strictAssignAfter(17); + a3 = strictAssignAfter(obj); +} + +assertEq(arraysEqual(a1, []), true); +assertEq(arraysEqual(a2, [17]), true); +assertEq(arraysEqual(a3, [obj]), true); diff --git a/js/src/jit-test/tests/arguments/strict-assign-arguments-element.js b/js/src/jit-test/tests/arguments/strict-assign-arguments-element.js new file mode 100644 index 0000000000..d2f4f1e5b8 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-assign-arguments-element.js @@ -0,0 +1,21 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function strictAssignArgumentsElement(a) +{ + "use strict"; + arguments[0] = 42; + return a; +} + +for (var i = 0; i < 5; i++) +{ + assertEq(strictAssignArgumentsElement(), undefined); + assertEq(strictAssignArgumentsElement(obj), obj); + assertEq(strictAssignArgumentsElement(17), 17); +} diff --git a/js/src/jit-test/tests/arguments/strict-assign-outer-param-psych.js b/js/src/jit-test/tests/arguments/strict-assign-outer-param-psych.js new file mode 100644 index 0000000000..6b8fb680eb --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-assign-outer-param-psych.js @@ -0,0 +1,27 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function strictAssignOuterParamPSYCH(p) +{ + "use strict"; + function inner(p) { p = 17; } + inner(); + return arguments; +} + +var a1, a2, a3; +for (var i = 0; i < 5; i++) +{ + a1 = strictAssignOuterParamPSYCH(); + a2 = strictAssignOuterParamPSYCH(17); + a3 = strictAssignOuterParamPSYCH(obj); +} + +assertEq(arraysEqual(a1, []), true); +assertEq(arraysEqual(a2, [17]), true); +assertEq(arraysEqual(a3, [obj]), true); diff --git a/js/src/jit-test/tests/arguments/strict-assign-outer-param.js b/js/src/jit-test/tests/arguments/strict-assign-outer-param.js new file mode 100644 index 0000000000..f6e4f47675 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-assign-outer-param.js @@ -0,0 +1,27 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function strictAssignOuterParam(p) +{ + "use strict"; + function inner() { p = 17; } + inner(); + return arguments; +} + +var a1, a2, a3; +for (var i = 0; i < 5; i++) +{ + a1 = strictAssignOuterParam(); + a2 = strictAssignOuterParam(42); + a3 = strictAssignOuterParam(obj); +} + +assertEq(arraysEqual(a1, []), true); +assertEq(arraysEqual(a2, [42]), true); +assertEq(arraysEqual(a3, [obj]), true); diff --git a/js/src/jit-test/tests/arguments/strict-assign-parameter-get-element.js b/js/src/jit-test/tests/arguments/strict-assign-parameter-get-element.js new file mode 100644 index 0000000000..ca283fb9b6 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-assign-parameter-get-element.js @@ -0,0 +1,14 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function strictAssignParameterGetElement(a) +{ + "use strict"; + a = 17; + return arguments[0]; +} + +for (var i = 0; i < 5; i++) + assertEq(strictAssignParameterGetElement(42), 42); diff --git a/js/src/jit-test/tests/arguments/strict-assign.js b/js/src/jit-test/tests/arguments/strict-assign.js new file mode 100644 index 0000000000..6666dec9bb --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-assign.js @@ -0,0 +1,26 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function strictAssign(a) +{ + "use strict"; + a = 17; + return arguments; +} + +var a1, a2, a3; +for (var i = 0; i < 5; i++) +{ + a1 = strictAssign(); + a2 = strictAssign(1); + a3 = strictAssign(1, obj); +} + +assertEq(arraysEqual(a1, []), true); +assertEq(arraysEqual(a2, [1]), true); +assertEq(arraysEqual(a3, [1, obj]), true); diff --git a/js/src/jit-test/tests/arguments/strict-eval-mutation.js b/js/src/jit-test/tests/arguments/strict-eval-mutation.js new file mode 100644 index 0000000000..d33a05c3a0 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-eval-mutation.js @@ -0,0 +1,24 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function strictEvalMutation(code) +{ + "use strict"; + return eval(code); +} + +var a1, a2; +for (var i = 0; i < 5; i++) +{ + a1 = strictEvalMutation("code = 17; arguments"); + a2 = strictEvalMutation("arguments[0] = 17; arguments"); + assertEq(strictEvalMutation("arguments[0] = 17; code"), "arguments[0] = 17; code"); +} + +assertEq(arraysEqual(a1, ["code = 17; arguments"]), true); +assertEq(arraysEqual(a2, [17]), true); diff --git a/js/src/jit-test/tests/arguments/strict-eval.js b/js/src/jit-test/tests/arguments/strict-eval.js new file mode 100644 index 0000000000..22ffb7fd85 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-eval.js @@ -0,0 +1,30 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +function strictEval(code, p) +{ + "use strict"; + eval(code); + return arguments; +} + +var a1, a2, a3, a4, a5, a6; +for (var i = 0; i < 5; i++) +{ + a1 = strictEval("1", 2); + a2 = strictEval("arguments"); + a3 = strictEval("p = 2"); + a4 = strictEval("p = 2", 17); + a5 = strictEval("arguments[0] = 17"); + a6 = strictEval("arguments[0] = 17", 42); +} + +assertEq(arraysEqual(a1, ["1", 2]), true); +assertEq(arraysEqual(a2, ["arguments"]), true); +assertEq(arraysEqual(a3, ["p = 2"]), true); +assertEq(arraysEqual(a4, ["p = 2", 17]), true); +assertEq(arraysEqual(a5, [17]), true); +assertEq(arraysEqual(a6, [17, 42]), true); diff --git a/js/src/jit-test/tests/arguments/strict-maybe-assign-outer.js b/js/src/jit-test/tests/arguments/strict-maybe-assign-outer.js new file mode 100644 index 0000000000..63f9f69248 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-maybe-assign-outer.js @@ -0,0 +1,26 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function strictMaybeAssignOuterParam(p) +{ + "use strict"; + function inner() { p = 17; } + return arguments; +} + +var a1, a2, a3; +for (var i = 0; i < 5; i++) +{ + a1 = strictMaybeAssignOuterParam(); + a2 = strictMaybeAssignOuterParam(17); + a3 = strictMaybeAssignOuterParam(obj); +} + +assertEq(arraysEqual(a1, []), true); +assertEq(arraysEqual(a2, [17]), true); +assertEq(arraysEqual(a3, [obj]), true); diff --git a/js/src/jit-test/tests/arguments/strict-maybe-nested-eval.js b/js/src/jit-test/tests/arguments/strict-maybe-nested-eval.js new file mode 100644 index 0000000000..a1fe88fd35 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-maybe-nested-eval.js @@ -0,0 +1,26 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +function strictMaybeNestedEval(code, p) +{ + "use strict"; + function inner() { eval(code); } + return arguments; +} + +var a1, a2, a3, a4; +for (var i = 0; i < 5; i++) +{ + a1 = strictMaybeNestedEval("1", 2); + a2 = strictMaybeNestedEval("arguments"); + a3 = strictMaybeNestedEval("p = 2"); + a4 = strictMaybeNestedEval("p = 2", 17); +} + +assertEq(arraysEqual(a1, ["1", 2]), true); +assertEq(arraysEqual(a2, ["arguments"]), true); +assertEq(arraysEqual(a3, ["p = 2"]), true); +assertEq(arraysEqual(a4, ["p = 2", 17]), true); diff --git a/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-call.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-call.js new file mode 100644 index 0000000000..a9430e3247 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-call.js @@ -0,0 +1,33 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function strictNestedAssignShadowFunctionCall(p) +{ + "use strict"; + function inner() + { + function p() { } + p = 1776; + } + inner(); + return arguments; +} + +var a1, a2, a3, a4; +for (var i = 0; i < 5; i++) +{ + a1 = strictNestedAssignShadowFunctionCall(); + a2 = strictNestedAssignShadowFunctionCall(99); + a3 = strictNestedAssignShadowFunctionCall(""); + a4 = strictNestedAssignShadowFunctionCall(obj); +} + +assertEq(arraysEqual(a1, []), true); +assertEq(arraysEqual(a2, [99]), true); +assertEq(arraysEqual(a3, [""]), true); +assertEq(arraysEqual(a4, [obj]), true); diff --git a/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-name.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-name.js new file mode 100644 index 0000000000..e8ae3177aa --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-name.js @@ -0,0 +1,33 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function strictNestedAssignShadowFunctionName(p) +{ + "use strict"; + function inner() + { + function p() { p = 1776; } + p(); + } + inner(); + return arguments; +} + +var a1, a2, a3, a4, a5; +for (var i = 0; i < 5; i++) +{ + a1 = strictNestedAssignShadowFunctionName(); + a2 = strictNestedAssignShadowFunctionName(99); + a3 = strictNestedAssignShadowFunctionName(""); + a4 = strictNestedAssignShadowFunctionName(obj); +} + +assertEq(arraysEqual(a1, []), true); +assertEq(arraysEqual(a2, [99]), true); +assertEq(arraysEqual(a3, [""]), true); +assertEq(arraysEqual(a4, [obj]), true); diff --git a/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function.js new file mode 100644 index 0000000000..46e0acfd04 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function.js @@ -0,0 +1,32 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function strictNestedAssignShadowFunction(p) +{ + "use strict"; + function inner() + { + function p() { } + p = 1776; + } + return arguments; +} + +var a1, a2, a3, a4; +for (var i = 0; i < 5; i++) +{ + a1 = strictNestedAssignShadowFunction(); + a2 = strictNestedAssignShadowFunction(99); + a3 = strictNestedAssignShadowFunction(""); + a4 = strictNestedAssignShadowFunction(obj); +} + +assertEq(arraysEqual(a1, []), true); +assertEq(arraysEqual(a2, [99]), true); +assertEq(arraysEqual(a3, [""]), true); +assertEq(arraysEqual(a4, [obj]), true); diff --git a/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch-call.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch-call.js new file mode 100644 index 0000000000..03c5e027de --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch-call.js @@ -0,0 +1,39 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function strictNestedAssignShadowCatchCall(p) +{ + "use strict"; + function inner() + { + try + { + } + catch (p) + { + var f = function innermost() { p = 1776; return 12; }; + f(); + } + } + inner(); + return arguments; +} + +var a1, a2, a3, a4; +for (var i = 0; i < 5; i++) +{ + a1 = strictNestedAssignShadowCatchCall(); + a2 = strictNestedAssignShadowCatchCall(99); + a3 = strictNestedAssignShadowCatchCall(""); + a4 = strictNestedAssignShadowCatchCall(obj); +} + +assertEq(arraysEqual(a1, []), true); +assertEq(arraysEqual(a2, [99]), true); +assertEq(arraysEqual(a3, [""]), true); +assertEq(arraysEqual(a4, [obj]), true); diff --git a/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch.js new file mode 100644 index 0000000000..06df3f9149 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch.js @@ -0,0 +1,39 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function strictNestedAssignShadowCatch(p) +{ + "use strict"; + function inner() + { + try + { + } + catch (p) + { + var f = function innermost() { p = 1776; return 12; }; + f(); + } + } + return arguments; +} + +var a1, a2, a3, a4; +for (var i = 0; i < 5; i++) +{ + a1 = strictNestedAssignShadowCatch(); + a2 = strictNestedAssignShadowCatch(99); + a3 = strictNestedAssignShadowCatch(""); + a4 = strictNestedAssignShadowCatch(obj); +} + +assertEq(arraysEqual(a1, []), true); +assertEq(arraysEqual(a2, [99]), true); +assertEq(arraysEqual(a3, [""]), true); +assertEq(arraysEqual(a4, [obj]), true); + diff --git a/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-var.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-var.js new file mode 100644 index 0000000000..8248bed338 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-var.js @@ -0,0 +1,29 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +/******************** + * STRICT ARGUMENTS * + ********************/ + +function strictNestedAssignShadowVar(p) +{ + "use strict"; + function inner() + { + var p = 12; + function innermost() { p = 1776; return 12; } + return innermost(); + } + return arguments; +} + +assertEq(arraysEqual(strictNestedAssignShadowVar(), []), true); +assertEq(arraysEqual(strictNestedAssignShadowVar(99), [99]), true); +assertEq(arraysEqual(strictNestedAssignShadowVar(""), [""]), true); +assertEq(arraysEqual(strictNestedAssignShadowVar(obj), [obj]), true); + diff --git a/js/src/jit-test/tests/arguments/strict-nested-eval.js b/js/src/jit-test/tests/arguments/strict-nested-eval.js new file mode 100644 index 0000000000..1f6eab54e4 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-nested-eval.js @@ -0,0 +1,31 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +function strictNestedEval(code, p) +{ + "use strict"; + function inner() { eval(code); } + inner(); + return arguments; +} + +var a1, a2, a3, a4, a5, a6; +for (var i = 0; i < 5; i++) +{ + a1 = strictNestedEval("1", 2); + a2 = strictNestedEval("arguments"); + a3 = strictNestedEval("p = 2"); + a4 = strictNestedEval("p = 2", 17); + a5 = strictNestedEval("arguments[0] = 17"); + a6 = strictNestedEval("arguments[0] = 17", 42); +} + +assertEq(arraysEqual(a1, ["1", 2]), true); +assertEq(arraysEqual(a2, ["arguments"]), true); +assertEq(arraysEqual(a3, ["p = 2"]), true); +assertEq(arraysEqual(a4, ["p = 2", 17]), true); +assertEq(arraysEqual(a5, ["arguments[0] = 17"]), true); +assertEq(arraysEqual(a6, ["arguments[0] = 17", 42]), true); diff --git a/js/src/jit-test/tests/arguments/strict-nested-shadow-eval.js b/js/src/jit-test/tests/arguments/strict-nested-shadow-eval.js new file mode 100644 index 0000000000..d80b7be0a7 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-nested-shadow-eval.js @@ -0,0 +1,30 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +function strictNestedShadowEval(code, p) +{ + "use strict"; + function inner(p) { eval(code); } + return arguments; +} + +var a1, a2, a3, a4, a5, a6; +for (var i = 0; i < 5; i++) +{ + a1 = strictNestedShadowEval("1", 2); + a2 = strictNestedShadowEval("arguments"); + a3 = strictNestedShadowEval("p = 2"); + a4 = strictNestedShadowEval("p = 2", 17); + a5 = strictNestedShadowEval("arguments[0] = 17"); + a6 = strictNestedShadowEval("arguments[0] = 17", 42); +} + +assertEq(arraysEqual(a1, ["1", 2]), true); +assertEq(arraysEqual(a2, ["arguments"]), true); +assertEq(arraysEqual(a3, ["p = 2"]), true); +assertEq(arraysEqual(a4, ["p = 2", 17]), true); +assertEq(arraysEqual(a5, ["arguments[0] = 17"]), true); +assertEq(arraysEqual(a6, ["arguments[0] = 17", 42]), true); diff --git a/js/src/jit-test/tests/arguments/strict-nested-shadow-maybe-eval.js b/js/src/jit-test/tests/arguments/strict-nested-shadow-maybe-eval.js new file mode 100644 index 0000000000..cf9edea9ee --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-nested-shadow-maybe-eval.js @@ -0,0 +1,30 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +function strictNestedShadowMaybeEval(code, p) +{ + "use strict"; + function inner(p) { eval(code); } + return arguments; +} + +var a1, a2, a3, a4, a5, a6; +for (var i = 0; i < 5; i++) +{ + a1 = strictNestedShadowMaybeEval("1", 2); + a2 = strictNestedShadowMaybeEval("arguments"); + a3 = strictNestedShadowMaybeEval("p = 2"); + a4 = strictNestedShadowMaybeEval("p = 2", 17); + a5 = strictNestedShadowMaybeEval("arguments[0] = 17"); + a6 = strictNestedShadowMaybeEval("arguments[0] = 17", 42); +} + +assertEq(arraysEqual(a1, ["1", 2]), true); +assertEq(arraysEqual(a2, ["arguments"]), true); +assertEq(arraysEqual(a3, ["p = 2"]), true); +assertEq(arraysEqual(a4, ["p = 2", 17]), true); +assertEq(arraysEqual(a5, ["arguments[0] = 17"]), true); +assertEq(arraysEqual(a6, ["arguments[0] = 17", 42]), true); diff --git a/js/src/jit-test/tests/arguments/strict-noargs.js b/js/src/jit-test/tests/arguments/strict-noargs.js new file mode 100644 index 0000000000..dfee3c8583 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-noargs.js @@ -0,0 +1,25 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +load(libdir + 'array-compare.js'); + +var obj = {}; + +function strictNoargs() +{ + "use strict"; + return arguments; +} + +var a1, a2, a3; +for (var i = 0; i < 5; i++) +{ + a1 = strictNoargs(); + a2 = strictNoargs(1); + a3 = strictNoargs(1, obj); +} + +assertEq(arraysEqual(a1, []), true); +assertEq(arraysEqual(a2, [1]), true); +assertEq(arraysEqual(a3, [1, obj]), true); diff --git a/js/src/jit-test/tests/arguments/strict-osr-shadowed-args.js b/js/src/jit-test/tests/arguments/strict-osr-shadowed-args.js new file mode 100644 index 0000000000..5c193b99f6 --- /dev/null +++ b/js/src/jit-test/tests/arguments/strict-osr-shadowed-args.js @@ -0,0 +1,13 @@ + +"use strict"; + +function loop(a) { + a = arguments.length; + var result = 0; + for (var i = 0; i < 5000; i++) { + result += a; + } + return result; +} + +assertEq(loop(11), 5000); diff --git a/js/src/jit-test/tests/arguments/testDelArg1.js b/js/src/jit-test/tests/arguments/testDelArg1.js new file mode 100644 index 0000000000..a6b5eee326 --- /dev/null +++ b/js/src/jit-test/tests/arguments/testDelArg1.js @@ -0,0 +1,13 @@ +function f(x,y,z) { + z = 9; + delete arguments[2]; + assertEq(arguments[2], undefined); + o = arguments; + assertEq(o[2], undefined); + assertEq(o[2] == undefined, true); +} + +for (var i = 0; i < 10; ++i) { + print(i); + f(1,2,3) +} diff --git a/js/src/jit-test/tests/arguments/testDelArg2.js b/js/src/jit-test/tests/arguments/testDelArg2.js new file mode 100644 index 0000000000..09fcf1f57d --- /dev/null +++ b/js/src/jit-test/tests/arguments/testDelArg2.js @@ -0,0 +1,13 @@ +function f(del) { + o = arguments; + if (del) + delete o[2]; + for (var i = 0; i < 10; ++i) + assertEq(o[2] == undefined, del); +} + +// record without arg deleted +f(false, 1,2,3,4); + +// run with arg deleted +f(true, 1,2,3,4); diff --git a/js/src/jit-test/tests/arguments/testDelArg3.js b/js/src/jit-test/tests/arguments/testDelArg3.js new file mode 100644 index 0000000000..4931870bbc --- /dev/null +++ b/js/src/jit-test/tests/arguments/testDelArg3.js @@ -0,0 +1,42 @@ +function assertGood(x) { + assertEq(x, "good"); +} + +(function() { + var a = arguments; + return function() { + assertGood.apply(null, a); + } +})("good")(); + +(function() { + var a = arguments; + return function() { + a[0] = "good"; + assertGood.apply(null, a); + } +})("bad")(); + +Object.prototype[0] = "good"; + +(function() { + var a = arguments; + return function() { + delete a[0]; + assertGood.apply(null, a); + } +})("bad")(); + +delete Object.prototype[0]; + +function assertUndefined(x) { + assertEq(x, undefined); +} + +(function() { + var a = arguments; + return function() { + a[0] = "bad"; + assertUndefined.apply(null, a); + } +})()(); diff --git a/js/src/jit-test/tests/arguments/testDelArg3Strict.js b/js/src/jit-test/tests/arguments/testDelArg3Strict.js new file mode 100644 index 0000000000..77d247a4d8 --- /dev/null +++ b/js/src/jit-test/tests/arguments/testDelArg3Strict.js @@ -0,0 +1,44 @@ +"use strict"; + +function assertGood(x) { + assertEq(x, "good"); +} + +(function() { + var a = arguments; + return function() { + assertGood.apply(null, a); + } +})("good")(); + +(function() { + var a = arguments; + return function() { + a[0] = "good"; + assertGood.apply(null, a); + } +})("bad")(); + +Object.prototype[0] = "good"; + +(function() { + var a = arguments; + return function() { + delete a[0]; + assertGood.apply(null, a); + } +})("bad")(); + +delete Object.prototype[0]; + +function assertUndefined(x) { + assertEq(x, undefined); +} + +(function() { + var a = arguments; + return function() { + a[0] = "bad"; + assertUndefined.apply(null, a); + } +})()(); |