description( "This test checks basic and corner cases of 'f.arguments'." ); function basicTest(args) { return basicTest.arguments; } shouldBe("basicTest('one')[0]", "'one'"); shouldBeUndefined("basicTest('one')[2]"); shouldBe("basicTest('one', 'two', 'three')[1]", "'two'"); function lengthTest() { return "" + lengthTest.arguments.length; } shouldBe("lengthTest()", "'0'"); shouldBe("lengthTest('From', '%E5%8C%97%E4%BA%AC', 360, '/', 'webkit.org')", "'5'"); function assignTest() { function g() { return assignTest.arguments; } arguments = true; return g(); } shouldBe("assignTest().toString()", "'[object Arguments]'"); function assignVarUndefinedTest() { function g() { return assignVarUndefinedTest.arguments; } var arguments; return g(); } shouldBe("assignVarUndefinedTest().toString()", "'[object Arguments]'"); function assignVarUndefinedTest2() { function g() { return assignVarUndefinedTest2.arguments; } var a, arguments; return g(); } shouldBe("assignVarUndefinedTest2().toString()", "'[object Arguments]'"); function assignVarInitTest() { function g() { return assignVarInitTest.arguments; } var arguments = true; return g(); } shouldBe("assignVarInitTest().toString()", "'[object Arguments]'"); function assignVarInitTest2() { function g() { return assignVarInitTest2.arguments; } var a, arguments = true; return g(); } shouldBe("assignVarInitTest2().toString()", "'[object Arguments]'"); function assignConstUndefinedTest() { function g() { return assignConstUndefinedTest.arguments; } var arguments; return g(); } shouldBe("assignConstUndefinedTest().toString()", "'[object Arguments]'"); function assignConstUndefinedTest2() { function g() { return assignConstUndefinedTest2.arguments; } var a, arguments; return g(); } shouldBe("assignConstUndefinedTest2().toString()", "'[object Arguments]'"); function assignConstInitTest() { function g() { return assignConstInitTest.arguments; } const arguments = true; return g(); } shouldBe("assignConstInitTest().toString()", "'[object Arguments]'"); function assignConstInitTest2() { function g() { return assignConstInitTest2.arguments; } const a = 5, arguments = true; return g(); } shouldBe("assignConstInitTest2().toString()", "'[object Arguments]'"); function assignForInitTest() { function g() { return assignForInitTest.arguments; } for (var arguments = true; false;) { } return g(); } shouldBe("assignForInitTest().toString()", "'[object Arguments]'"); function assignForInitTest2() { function g() { return assignForInitTest2.arguments; } for (var a, arguments = true; false;) { } return g(); } shouldBe("assignForInitTest2().toString()", "'[object Arguments]'"); function assignForInInitTest() { function g() { return assignForInInitTest.arguments; } for (arguments = true; false;) { } return g(); } shouldBe("assignForInInitTest().toString()", "'[object Arguments]'"); function paramInitTest(arguments) { return paramInitTestCheckArguments(); } function paramInitTestCheckArguments() { return paramInitTest.arguments; } shouldBe("paramInitTest(true).toString()", "'[object Arguments]'"); var paramFunctionConstructorInitTest = Function("arguments", "return paramFunctionConstructorInitTestCheckArguments();"); function paramFunctionConstructorInitTestCheckArguments() { return paramFunctionConstructorInitTest.arguments; } shouldBe("paramFunctionConstructorInitTest(true).toString()", "'[object Arguments]'"); function tearOffTest() { function g() { var a = 1; return arguments; } var b = 2; var arguments = g(true); return arguments; } shouldBeTrue("tearOffTest()[0]"); function tearOffTest2() { function g(a) { var arguments = a; var b = 2; return arguments; } var c = 3; return g(arguments); } shouldBeTrue("tearOffTest2(true)[0]"); // Some utility functions/ function arrayify(args) { if (typeof args != "object") return args; if (typeof args.length == "undefined" || typeof args.callee == "undefined") return args; return Array.prototype.slice.call(args); } function indirectCall(callee) { return callee(); } // Test reading from caller.arguments from an inner function. function tearOffTest3(a, b, c, d) { a = 10; function inner() { return tearOffTest3.arguments; } return arrayify(inner()); } shouldBe("tearOffTest3(1, 2, 3, false)", "[10, 2, 3, false]"); function tearOffTest3a(a, b, c, d) { var x = 42; a = 10; function inner() { return tearOffTest3a.arguments; } if (d) { // Force a lexicalEnvironment to be created in the outer function. return function() { return x; } } else { return arrayify(inner()); } } shouldBe("tearOffTest3a(1, 2, 3, false)", "[10, 2, 3, false]"); function tearOffTest3b(a, b, c, d) { a = 10; function inner() { var capture = a; // Capture an arg from the outer function. return tearOffTest3b.arguments; } return arrayify(inner()); } shouldBe("tearOffTest3b(1, 2, 3, false)", "[1, 2, 3, false]"); function tearOffTest3c(a, b, c, d) { a = 10; function inner() { var capture = a; // Capture an arg from the outer function. return tearOffTest3c.arguments; } return arrayify(indirectCall(inner)); } shouldBe("tearOffTest3c(1, 2, 3, false)", "[1, 2, 3, false]"); // Test reading from caller.arguments from an external function. function tearOffTest4External() { return tearOffTest4.arguments; } function tearOffTest4(a, b, c, d) { a = 10; return arrayify(tearOffTest4External()); } shouldBe("tearOffTest4(1, 2, 3, false)", "[10, 2, 3, false]"); function tearOffTest4aExternal() { return tearOffTest4a.arguments; } function tearOffTest4a(a, b, c, d) { var x = 42; a = 10; if (d) { // Force a lexicalEnvironment to be created in the outer function. return function() { return x; } } else { return arrayify(tearOffTest4aExternal()); } } shouldBe("tearOffTest4a(1, 2, 3, false)", "[10, 2, 3, false]"); function tearOffTest4bExternal() { return tearOffTest4b.arguments; } function tearOffTest4b(a, b, c, d) { a = 10; function inner() { var capture = a; // Capture an arg from the outer function. return capture; } return arrayify(tearOffTest4bExternal()); } shouldBe("tearOffTest4b(1, 2, 3, false)", "[1, 2, 3, false]"); function tearOffTest4cExternal() { return tearOffTest4c.arguments; } function tearOffTest4c(a, b, c, d) { a = 10; function inner() { var capture = a; // Capture an arg from the outer function. return tearOffTest4c.arguments; } return arrayify(indirectCall(tearOffTest4cExternal)); } shouldBe("tearOffTest4c(1, 2, 3, false)", "[1, 2, 3, false]"); // Test reading from caller.arguments which have Deleted slow data from an inner function. function tearOffTest5(a, b, c, d) { a = 10; delete arguments[0]; function inner() { return tearOffTest5.arguments; } return arrayify(inner()); } shouldBe("tearOffTest5(1, 2, 3, false)", "[1, 2, 3, false]"); function tearOffTest5a(a, b, c, d) { var x = 42; a = 10; delete arguments[0]; function inner() { return tearOffTest5a.arguments; } if (d) { // Force a lexicalEnvironment to be created in the outer function. return function() { return x; } } else { return arrayify(inner()); } } shouldBe("tearOffTest5a(1, 2, 3, false)", "[1, 2, 3, false]"); function tearOffTest5b(a, b, c, d) { a = 10; delete arguments[0]; function inner() { var capture = a; // Capture an arg from the outer function. return tearOffTest5b.arguments; } return arrayify(inner()); } shouldBe("tearOffTest5b(1, 2, 3, false)", "[1, 2, 3, false]"); function tearOffTest5c(a, b, c, d) { a = 10; delete arguments[0]; function inner() { var capture = a; // Capture an arg from the outer function. return tearOffTest5c.arguments; } return arrayify(indirectCall(inner)); } shouldBe("tearOffTest5c(1, 2, 3, false)", "[1, 2, 3, false]"); // Test reading from caller.arguments which have Deleted slow data from an external function. function tearOffTest6External() { return tearOffTest6.arguments; } function tearOffTest6(a, b, c, d) { a = 10; delete arguments[0]; return arrayify(tearOffTest6External()); } shouldBe("tearOffTest6(1, 2, 3, false)", "[1, 2, 3, false]"); function tearOffTest6aExternal() { return tearOffTest6a.arguments; } function tearOffTest6a(a, b, c, d) { var x = 42; a = 10; delete arguments[0]; if (d) { // Force a lexicalEnvironment to be created in the outer function. return function() { return x; } } else { return arrayify(tearOffTest6aExternal()); } } shouldBe("tearOffTest6a(1, 2, 3, false)", "[1, 2, 3, false]"); function tearOffTest6bExternal() { return tearOffTest6b.arguments; } function tearOffTest6b(a, b, c, d) { a = 10; delete arguments[0]; function inner() { var capture = a; // Capture an arg from the outer function. return capture; } return arrayify(tearOffTest6bExternal()); } shouldBe("tearOffTest6b(1, 2, 3, false)", "[1, 2, 3, false]"); function tearOffTest6cExternal() { return tearOffTest6c.arguments; } function tearOffTest6c(a, b, c, d) { a = 10; delete arguments[0]; function inner() { var capture = a; // Capture an arg from the outer function. return tearOffTest6c.arguments; } return arrayify(indirectCall(tearOffTest6cExternal)); } shouldBe("tearOffTest6c(1, 2, 3, false)", "[1, 2, 3, false]"); // Test writing to caller.arguments from an inner function. function tearOffTest7(a, b, c, d) { a = 10; (function inner() { tearOffTest7.arguments[0] = 100; })(); return arrayify(arguments); } shouldBe("tearOffTest7(1, 2, 3, false)", "[10, 2, 3, false]"); function tearOffTest7a(a, b, c, d) { var x = 42; a = 10; if (d) { // Force a lexicalEnvironment to be created in the outer function. return function() { return x; } } else { (function inner() { tearOffTest7a.arguments[0] = 100; }) (); return arrayify(arguments); } } shouldBe("tearOffTest7a(1, 2, 3, false)", "[10, 2, 3, false]"); function tearOffTest7b(a, b, c, d) { a = 10; (function inner() { var capture = a; // Capture an arg from the outer function. tearOffTest7b.arguments[0] = 100; })(); return arrayify(arguments); } shouldBe("tearOffTest7b(1, 2, 3, false)", "[10, 2, 3, false]"); function tearOffTest7c(a, b, c, d) { a = 10; function inner() { var capture = a; // Capture an arg from the outer function. tearOffTest7c.arguments[0] = 100; } indirectCall(inner); return arrayify(arguments); } shouldBe("tearOffTest7c(1, 2, 3, false)", "[10, 2, 3, false]"); // Test writing to caller.arguments from an external function. function tearOffTest8External() { tearOffTest8.arguments[0] = 100; } function tearOffTest8(a, b, c, d) { a = 10; tearOffTest8External(); return arrayify(arguments); } shouldBe("tearOffTest8(1, 2, 3, false)", "[10, 2, 3, false]"); function tearOffTest8aExternal() { tearOffTest8a.arguments[0] = 100; } function tearOffTest8a(a, b, c, d) { var x = 42; a = 10; if (d) { // Force a lexicalEnvironment to be created in the outer function. return function() { return x; } } else { tearOffTest8aExternal(); return arrayify(arguments); } } shouldBe("tearOffTest8a(1, 2, 3, false)", "[10, 2, 3, false]"); function tearOffTest8bExternal() { tearOffTest8b.arguments[0] = 100; } function tearOffTest8b(a, b, c, d) { a = 10; function inner() { var capture = a; // Capture an arg from the outer function. } tearOffTest8bExternal(); return arrayify(arguments); } shouldBe("tearOffTest8b(1, 2, 3, false)", "[10, 2, 3, false]"); function tearOffTest8cExternal() { tearOffTest8c.arguments[0] = 100; } function tearOffTest8c(a, b, c, d) { a = 10; function inner() { var capture = a; // Capture an arg from the outer function. } indirectCall(tearOffTest8cExternal); return arrayify(arguments); } shouldBe("tearOffTest8c(1, 2, 3, false)", "[10, 2, 3, false]"); // Test deleting an arg in caller.arguments from an inner function. function tearOffTest9(a, b, c, d) { a = 10; delete arguments[0]; (function inner() { delete tearOffTest9.arguments[1]; })(); return arrayify(arguments); } shouldBe("tearOffTest9(1, 2, 3, false)", "[undefined, 2, 3, false]"); function tearOffTest9a(a, b, c, d) { var x = 42; delete arguments[0]; if (d) { // Force a lexicalEnvironment to be created in the outer function. return function() { return x; } } else { (function inner() { delete tearOffTest9a.arguments[1]; }) (); return arrayify(arguments); } } shouldBe("tearOffTest9a(1, 2, 3, false)", "[undefined, 2, 3, false]"); function tearOffTest9b(a, b, c, d) { delete arguments[0]; (function inner() { var capture = a; // Capture an arg from the outer function. delete tearOffTest9b.arguments[1]; })(); return arrayify(arguments); } shouldBe("tearOffTest9b(1, 2, 3, false)", "[undefined, 2, 3, false]"); function tearOffTest9c(a, b, c, d) { delete arguments[0]; function inner() { var capture = a; // Capture an arg from the outer function. delete tearOffTest9c.arguments[1]; } indirectCall(inner); return arrayify(arguments); } shouldBe("tearOffTest9c(1, 2, 3, false)", "[undefined, 2, 3, false]"); // Test deleting a arg in caller.arguments from an external function. function tearOffTest10External() { delete tearOffTest10.arguments[1]; } function tearOffTest10(a, b, c, d) { delete arguments[0]; tearOffTest10External(); return arrayify(arguments); } shouldBe("tearOffTest10(1, 2, 3, false)", "[undefined, 2, 3, false]"); function tearOffTest10aExternal() { delete tearOffTest10a.arguments[1]; } function tearOffTest10a(a, b, c, d) { var x = 42; delete arguments[0]; if (d) { // Force a lexicalEnvironment to be created in the outer function. return function() { return x; } } else { tearOffTest10aExternal(); return arrayify(arguments); } } shouldBe("tearOffTest10a(1, 2, 3, false)", "[undefined, 2, 3, false]"); function tearOffTest10bExternal() { delete tearOffTest10b.arguments[1]; } function tearOffTest10b(a, b, c, d) { delete arguments[0]; function inner() { var capture = a; // Capture an arg from the outer function. } tearOffTest10bExternal(); return arrayify(arguments); } shouldBe("tearOffTest10b(1, 2, 3, false)", "[undefined, 2, 3, false]"); function tearOffTest10cExternal() { delete tearOffTest10c.arguments[1]; } function tearOffTest10c(a, b, c, d) { delete arguments[0]; function inner() { var capture = a; // Capture an arg from the outer function. } indirectCall(tearOffTest10cExternal); return arrayify(arguments); } shouldBe("tearOffTest10c(1, 2, 3, false)", "[undefined, 2, 3, false]"); function lexicalArgumentsLiveRead1(a, b, c) { var o = arguments; a = 1; return lexicalArgumentsLiveRead1.arguments[0]; } shouldBe("lexicalArgumentsLiveRead1(0, 2, 3)", "0"); function lexicalArgumentsLiveRead2(a, b, c) { var o = arguments; b = 2; return lexicalArgumentsLiveRead2.arguments[1]; } shouldBe("lexicalArgumentsLiveRead2(1, 0, 3)", "0"); function lexicalArgumentsLiveRead3(a, b, c) { var o = arguments; c = 3; return lexicalArgumentsLiveRead3.arguments[2]; } shouldBe("lexicalArgumentsLiveRead3(1, 2, 0)", "0"); function lexicalArgumentsLiveWrite1(a, b, c) { var o = arguments; lexicalArgumentsLiveWrite1.arguments[0] = 1; return a; } shouldBe("lexicalArgumentsLiveWrite1(0, 2, 3)", "0"); function lexicalArgumentsLiveWrite2(a, b, c) { var o = arguments; lexicalArgumentsLiveWrite2.arguments[1] = 2; return b; } shouldBe("lexicalArgumentsLiveWrite2(1, 0, 3)", "0"); function lexicalArgumentsLiveWrite3(a, b, c) { var o = arguments; lexicalArgumentsLiveWrite3.arguments[2] = 3; return c; } shouldBe("lexicalArgumentsLiveWrite3(1, 2, 0)", "0"); function argumentsNotLiveRead1(a, b, c) { var o = argumentsNotLiveRead1.arguments; a = 1; return o[0]; } shouldBe("argumentsNotLiveRead1(0, 2, 3)", "0"); function argumentsNotLiveRead2(a, b, c) { var o = argumentsNotLiveRead2.arguments; b = 2; return o[1]; } shouldBe("argumentsNotLiveRead2(1, 0, 3)", "0"); function argumentsNotLiveRead3(a, b, c) { var o = argumentsNotLiveRead3.arguments; c = 3; return o[2]; } shouldBe("argumentsNotLiveRead3(1, 2, 0)", "0"); function argumentsNotLiveWrite1(a, b, c) { argumentsNotLiveWrite1.arguments[0] = 1; return a; } shouldBe("argumentsNotLiveWrite1(0, 2, 3)", "0"); function argumentsNotLiveWrite2(a, b, c) { argumentsNotLiveWrite2.arguments[1] = 2; return b; } shouldBe("argumentsNotLiveWrite2(1, 0, 3)", "0"); function argumentsNotLiveWrite3(a, b, c) { argumentsNotLiveWrite3.arguments[2] = 3; return c; } shouldBe("argumentsNotLiveWrite3(1, 2, 0)", "0"); function argumentsIdentity() { return argumentsIdentity.arguments != argumentsIdentity.arguments; } shouldBeTrue("argumentsIdentity()"); function overwroteArgumentsInDynamicScope1() { eval("arguments = true"); return arguments; } function overwroteArgumentsInDynamicScope2() { arguments = true; return eval("arguments"); } function overwroteArgumentsInDynamicScope3() { eval("arguments = true"); return overwroteArgumentsInDynamicScope3.arguments; } shouldBeTrue("overwroteArgumentsInDynamicScope1()"); shouldBeTrue("overwroteArgumentsInDynamicScope2()"); shouldBe("overwroteArgumentsInDynamicScope3().toString()", "'[object Arguments]'");