// Copyright 2013 the V8 project authors. All rights reserved. // Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. description( "This test thoroughly checks the behaviour of the 'arguments' object." ); function access_1(a, b, c) { return arguments[0]; } function access_2(a, b, c) { return arguments[1]; } function access_3(a, b, c) { return arguments[2]; } function access_4(a, b, c) { return arguments[3]; } function access_5(a, b, c) { return arguments[4]; } function argumentLengthIs5() { arguments.length = 5; return arguments.length; } function duplicateArgumentAndReturnLast_call(a) { Array.prototype.push.call(arguments, a); return arguments[1]; } function duplicateArgumentAndReturnFirst_call(a) { Array.prototype.push.call(arguments, a); return arguments[0]; } function duplicateArgumentAndReturnLast_apply(a) { Array.prototype.push.apply(arguments, arguments); return arguments[1]; } function duplicateArgumentAndReturnFirst_apply(a) { Array.prototype.push.apply(arguments, arguments); return arguments[0]; } shouldBe("access_1(1, 2, 3)", "1"); shouldBe("access_2(1, 2, 3)", "2"); shouldBe("access_3(1, 2, 3)", "3"); shouldBe("access_4(1, 2, 3)", "undefined"); shouldBe("access_5(1, 2, 3)", "undefined"); shouldBe("access_1(1)", "1"); shouldBe("access_2(1)", "undefined"); shouldBe("access_3(1)", "undefined"); shouldBe("access_4(1)", "undefined"); shouldBe("access_5(1)", "undefined"); shouldBe("access_1(1, 2, 3, 4, 5)", "1"); shouldBe("access_2(1, 2, 3, 4, 5)", "2"); shouldBe("access_3(1, 2, 3, 4, 5)", "3"); shouldBe("access_4(1, 2, 3, 4, 5)", "4"); shouldBe("access_5(1, 2, 3, 4, 5)", "5"); shouldBe("argumentLengthIs5()", "5"); shouldBe("argumentLengthIs5(1,2,3,4,5)", "5"); shouldBe("argumentLengthIs5(1,2,3,4,5,6,7,8,9,10)", "5"); shouldBe("duplicateArgumentAndReturnLast_call(1)", "1"); shouldBe("duplicateArgumentAndReturnFirst_call(1)", "1"); shouldBe("duplicateArgumentAndReturnLast_apply(1)", "1"); shouldBe("duplicateArgumentAndReturnFirst_apply(1)", "1"); function f(a, b, c) { return arguments; } function tear_off_equal_access_1(a, b, c) { return f(a, b, c)[0]; } function tear_off_equal_access_2(a, b, c) { return f(a, b, c)[1]; } function tear_off_equal_access_3(a, b, c) { return f(a, b, c)[2]; } function tear_off_equal_access_4(a, b, c) { return f(a, b, c)[3]; } function tear_off_equal_access_5(a, b, c) { return f(a, b, c)[4]; } shouldBe("tear_off_equal_access_1(1, 2, 3)", "1"); shouldBe("tear_off_equal_access_2(1, 2, 3)", "2"); shouldBe("tear_off_equal_access_3(1, 2, 3)", "3"); shouldBe("tear_off_equal_access_4(1, 2, 3)", "undefined"); shouldBe("tear_off_equal_access_5(1, 2, 3)", "undefined"); function tear_off_too_few_access_1(a) { return f(a)[0]; } function tear_off_too_few_access_2(a) { return f(a)[1]; } function tear_off_too_few_access_3(a) { return f(a)[2]; } function tear_off_too_few_access_4(a) { return f(a)[3]; } function tear_off_too_few_access_5(a) { return f(a)[4]; } shouldBe("tear_off_too_few_access_1(1)", "1"); shouldBe("tear_off_too_few_access_2(1)", "undefined"); shouldBe("tear_off_too_few_access_3(1)", "undefined"); shouldBe("tear_off_too_few_access_4(1)", "undefined"); shouldBe("tear_off_too_few_access_5(1)", "undefined"); function tear_off_too_many_access_1(a, b, c, d, e) { return f(a, b, c, d, e)[0]; } function tear_off_too_many_access_2(a, b, c, d, e) { return f(a, b, c, d, e)[1]; } function tear_off_too_many_access_3(a, b, c, d, e) { return f(a, b, c, d, e)[2]; } function tear_off_too_many_access_4(a, b, c, d, e) { return f(a, b, c, d, e)[3]; } function tear_off_too_many_access_5(a, b, c, d, e) { return f(a, b, c, d, e)[4]; } shouldBe("tear_off_too_many_access_1(1, 2, 3, 4, 5)", "1"); shouldBe("tear_off_too_many_access_2(1, 2, 3, 4, 5)", "2"); shouldBe("tear_off_too_many_access_3(1, 2, 3, 4, 5)", "3"); shouldBe("tear_off_too_many_access_4(1, 2, 3, 4, 5)", "4"); shouldBe("tear_off_too_many_access_5(1, 2, 3, 4, 5)", "5"); function live_1(a, b, c) { arguments[0] = 1; return a; } function live_2(a, b, c) { arguments[1] = 2; return b; } function live_3(a, b, c) { arguments[2] = 3; return c; } shouldBe("live_1(0, 2, 3)", "1"); shouldBe("live_2(1, 0, 3)", "2"); shouldBe("live_3(1, 2, 0)", "3"); // Arguments that were not provided are not live shouldBe("live_1(0)", "1"); shouldBe("live_2(1)", "undefined"); shouldBe("live_3(1)", "undefined"); shouldBe("live_1(0, 2, 3, 4, 5)", "1"); shouldBe("live_2(1, 0, 3, 4, 5)", "2"); shouldBe("live_3(1, 2, 0, 4, 5)", "3"); function extra_args_modify_4(a, b, c) { arguments[3] = 4; return arguments[3]; } function extra_args_modify_5(a, b, c) { arguments[4] = 5; return arguments[4]; } shouldBe("extra_args_modify_4(1, 2, 3, 0, 5)", "4"); shouldBe("extra_args_modify_5(1, 2, 3, 4, 0)", "5"); function tear_off_live_1(a, b, c) { var args = arguments; return function() { args[0] = 1; return a; }; } function tear_off_live_2(a, b, c) { var args = arguments; return function() { args[1] = 2; return b; }; } function tear_off_live_3(a, b, c) { var args = arguments; return function() { args[2] = 3; return c; }; } shouldBe("tear_off_live_1(0, 2, 3)()", "1"); shouldBe("tear_off_live_2(1, 0, 3)()", "2"); shouldBe("tear_off_live_3(1, 2, 0)()", "3"); // Arguments that were not provided are not live shouldBe("tear_off_live_1(0)()", "1"); shouldBe("tear_off_live_2(1)()", "undefined"); shouldBe("tear_off_live_3(1)()", "undefined"); shouldBe("tear_off_live_1(0, 2, 3, 4, 5)()", "1"); shouldBe("tear_off_live_2(1, 0, 3, 4, 5)()", "2"); shouldBe("tear_off_live_3(1, 2, 0, 4, 5)()", "3"); function tear_off_extra_args_modify_4(a, b, c) { return function() { arguments[3] = 4; return arguments[3]; } } function tear_off_extra_args_modify_5(a, b, c) { return function() { arguments[4] = 5; return arguments[4]; } } shouldBe("tear_off_extra_args_modify_4(1, 2, 3, 0, 5)()", "4"); shouldBe("tear_off_extra_args_modify_5(1, 2, 3, 4, 0)()", "5"); function delete_1(a, b, c) { delete arguments[0]; return arguments[0]; } function delete_2(a, b, c) { delete arguments[1]; return arguments[1]; } function delete_3(a, b, c) { delete arguments[2]; return arguments[2]; } function delete_4(a, b, c) { delete arguments[3]; return arguments[3]; } function delete_5(a, b, c) { delete arguments[4]; return arguments[4]; } shouldBe("delete_1(1, 2, 3)", "undefined"); shouldBe("delete_2(1, 2, 3)", "undefined"); shouldBe("delete_3(1, 2, 3)", "undefined"); shouldBe("delete_4(1, 2, 3)", "undefined"); shouldBe("delete_5(1, 2, 3)", "undefined"); shouldBe("delete_1(1)", "undefined"); shouldBe("delete_2(1)", "undefined"); shouldBe("delete_3(1)", "undefined"); shouldBe("delete_4(1)", "undefined"); shouldBe("delete_5(1)", "undefined"); shouldBe("delete_1(1, 2, 3, 4, 5)", "undefined"); shouldBe("delete_2(1, 2, 3, 4, 5)", "undefined"); shouldBe("delete_3(1, 2, 3, 4, 5)", "undefined"); shouldBe("delete_4(1, 2, 3, 4, 5)", "undefined"); shouldBe("delete_5(1, 2, 3, 4, 5)", "undefined"); function tear_off_delete_1(a, b, c) { return function() { delete arguments[0]; return arguments[0]; }; } function tear_off_delete_2(a, b, c) { return function() { delete arguments[1]; return arguments[1]; }; } function tear_off_delete_3(a, b, c) { return function() { delete arguments[2]; return arguments[2]; }; } function tear_off_delete_4(a, b, c) { return function() { delete arguments[3]; return arguments[3]; }; } function tear_off_delete_5(a, b, c) { return function() { delete arguments[4]; return arguments[4]; }; } shouldBe("tear_off_delete_1(1, 2, 3)()", "undefined"); shouldBe("tear_off_delete_2(1, 2, 3)()", "undefined"); shouldBe("tear_off_delete_3(1, 2, 3)()", "undefined"); shouldBe("tear_off_delete_4(1, 2, 3)()", "undefined"); shouldBe("tear_off_delete_5(1, 2, 3)()", "undefined"); shouldBe("tear_off_delete_1(1)()", "undefined"); shouldBe("tear_off_delete_2(1)()", "undefined"); shouldBe("tear_off_delete_3(1)()", "undefined"); shouldBe("tear_off_delete_4(1)()", "undefined"); shouldBe("tear_off_delete_5(1)()", "undefined"); shouldBe("tear_off_delete_1(1, 2, 3, 4, 5)()", "undefined"); shouldBe("tear_off_delete_2(1, 2, 3, 4, 5)()", "undefined"); shouldBe("tear_off_delete_3(1, 2, 3, 4, 5)()", "undefined"); shouldBe("tear_off_delete_4(1, 2, 3, 4, 5)()", "undefined"); shouldBe("tear_off_delete_5(1, 2, 3, 4, 5)()", "undefined"); function delete_not_live_1(a, b, c) { delete arguments[0]; return a; } function delete_not_live_2(a, b, c) { delete arguments[1]; return b; } function delete_not_live_3(a, b, c) { delete arguments[2]; return c; } shouldBe("delete_not_live_1(1, 2, 3)", "1"); shouldBe("delete_not_live_2(1, 2, 3)", "2"); shouldBe("delete_not_live_3(1, 2, 3)", "3"); shouldBe("delete_not_live_1(1)", "1"); shouldBe("delete_not_live_2(1)", "undefined"); shouldBe("delete_not_live_3(1)", "undefined"); shouldBe("delete_not_live_1(1, 2, 3, 4, 5)", "1"); shouldBe("delete_not_live_2(1, 2, 3, 4, 5)", "2"); shouldBe("delete_not_live_3(1, 2, 3, 4, 5)", "3"); function tear_off_delete_not_live_1(a, b, c) { return function() { delete arguments[0]; return a; }; } function tear_off_delete_not_live_2(a, b, c) { return function () { delete arguments[1]; return b; }; } function tear_off_delete_not_live_3(a, b, c) { return function() { delete arguments[2]; return c; }; } shouldBe("tear_off_delete_not_live_1(1, 2, 3)()", "1"); shouldBe("tear_off_delete_not_live_2(1, 2, 3)()", "2"); shouldBe("tear_off_delete_not_live_3(1, 2, 3)()", "3"); shouldBe("tear_off_delete_not_live_1(1)()", "1"); shouldBe("tear_off_delete_not_live_2(1)()", "undefined"); shouldBe("tear_off_delete_not_live_3(1)()", "undefined"); shouldBe("tear_off_delete_not_live_1(1, 2, 3, 4, 5)()", "1"); shouldBe("tear_off_delete_not_live_2(1, 2, 3, 4, 5)()", "2"); shouldBe("tear_off_delete_not_live_3(1, 2, 3, 4, 5)()", "3"); function access_after_delete_named_2(a, b, c) { delete arguments[0]; return b; } function access_after_delete_named_3(a, b, c) { delete arguments[0]; return c; } function access_after_delete_named_4(a, b, c) { delete arguments[0]; return arguments[3]; } shouldBe("access_after_delete_named_2(1, 2, 3)", "2"); shouldBe("access_after_delete_named_3(1, 2, 3)", "3"); shouldBe("access_after_delete_named_4(1, 2, 3)", "undefined"); shouldBe("access_after_delete_named_2(1)", "undefined"); shouldBe("access_after_delete_named_3(1)", "undefined"); shouldBe("access_after_delete_named_4(1)", "undefined"); shouldBe("access_after_delete_named_2(1, 2, 3, 4)", "2"); shouldBe("access_after_delete_named_3(1, 2, 3, 4)", "3"); shouldBe("access_after_delete_named_4(1, 2, 3, 4)", "4"); function access_after_delete_extra_1(a, b, c) { delete arguments[3]; return a; } function access_after_delete_extra_2(a, b, c) { delete arguments[3]; return b; } function access_after_delete_extra_3(a, b, c) { delete arguments[3]; return c; } function access_after_delete_extra_5(a, b, c) { delete arguments[3]; return arguments[4]; } shouldBe("access_after_delete_extra_1(1, 2, 3)", "1"); shouldBe("access_after_delete_extra_2(1, 2, 3)", "2"); shouldBe("access_after_delete_extra_3(1, 2, 3)", "3"); shouldBe("access_after_delete_extra_5(1, 2, 3)", "undefined"); shouldBe("access_after_delete_extra_1(1)", "1"); shouldBe("access_after_delete_extra_2(1)", "undefined"); shouldBe("access_after_delete_extra_3(1)", "undefined"); shouldBe("access_after_delete_extra_5(1)", "undefined"); shouldBe("access_after_delete_extra_1(1, 2, 3, 4, 5)", "1"); shouldBe("access_after_delete_extra_2(1, 2, 3, 4, 5)", "2"); shouldBe("access_after_delete_extra_3(1, 2, 3, 4, 5)", "3"); shouldBe("access_after_delete_extra_5(1, 2, 3, 4, 5)", "5"); function argumentsParam(arguments) { return arguments; } shouldBeTrue("argumentsParam(true)"); var argumentsFunctionConstructorParam = new Function("arguments", "return arguments;"); shouldBeTrue("argumentsFunctionConstructorParam(true)"); function argumentsVarUndefined() { var arguments; return String(arguments); } shouldBe("argumentsVarUndefined()", "'[object Arguments]'"); function argumentCalleeInException() { try { throw ""; } catch (e) { return arguments.callee; } } shouldBe("argumentCalleeInException()", "argumentCalleeInException") function shadowedArgumentsApply(arguments) { return function(a){ return a; }.apply(null, arguments); } function shadowedArgumentsLength(arguments) { return arguments.length; } function shadowedArgumentsCallee(arguments) { return arguments.callee; } function shadowedArgumentsIndex(arguments) { return arguments[0] } shouldBeTrue("shadowedArgumentsApply([true])"); shouldBe("shadowedArgumentsLength([])", '0'); shouldThrow("shadowedArgumentsLength()"); shouldBeUndefined("shadowedArgumentsCallee([])"); shouldBeTrue("shadowedArgumentsIndex([true])"); descriptor = (function(){ return Object.getOwnPropertyDescriptor(arguments, 1); })("zero","one","two"); shouldBe("descriptor.value", '"one"'); shouldBe("descriptor.writable", 'true'); shouldBe("descriptor.enumerable", 'true'); shouldBe("descriptor.configurable", 'true'); // Test cases for [[DefineOwnProperty]] applied to the arguments object. (function(a0,a1,a2,a3){ Object.defineProperties(arguments, { 1: { get: function(){ return 201; } }, 2: { value: 202, writable: false }, 3: { writable: false }, }); // Test a0 is a live mapped argument. shouldBeTrue(String( a0 === 100 )); shouldBeTrue(String( arguments[0] === 100 )); a0 = 300; shouldBeTrue(String( a0 === 300 )); shouldBeTrue(String( arguments[0] === 300 )); arguments[0] = 400; shouldBeTrue(String( a0 === 400 )); shouldBeTrue(String( arguments[0] === 400 )); // When a1 is redefined as an accessor, it is no longer live. shouldBeTrue(String( a1 === 101 )); shouldBeTrue(String( arguments[1] === 201 )); a1 = 301; shouldBeTrue(String( a1 === 301 )); shouldBeTrue(String( arguments[1] === 201 )); arguments[1] = 401; shouldBeTrue(String( a1 === 301 )); shouldBeTrue(String( arguments[1] === 201 )); // When a2 is made read-only the value is set, but it is no longer live. // (per 10.6 [[DefineOwnProperty]] 5.b.ii.1) shouldBeTrue(String( a2 === 202 )); shouldBeTrue(String( arguments[2] === 202 )); a2 = 302; shouldBeTrue(String( a2 === 302 )); shouldBeTrue(String( arguments[2] === 202 )); arguments[2] = 402; shouldBeTrue(String( a2 === 302 )); shouldBeTrue(String( arguments[2] === 202 )); // When a3 is made read-only, it is no longer live. // (per 10.6 [[DefineOwnProperty]] 5.b.ii.1) shouldBeTrue(String( a3 === 103 )); shouldBeTrue(String( arguments[3] === 103 )); a3 = 303; shouldBeTrue(String( a3 === 303 )); shouldBeTrue(String( arguments[3] === 103 )); arguments[3] = 403; shouldBeTrue(String( a3 === 303 )); shouldBeTrue(String( arguments[3] === 103 )); })(100,101,102,103); // Test cases for [[DefineOwnProperty]] applied to the arguments object. (function(arg){ shouldBeTrue(String( Object.getOwnPropertyDescriptor(arguments, 0).writable )); shouldBeTrue(String( Object.getOwnPropertyDescriptor(arguments, 0).enumerable )); Object.defineProperty(arguments, 0, { writable: false }); shouldBeFalse(String( Object.getOwnPropertyDescriptor(arguments, 0).writable )); shouldBeTrue(String( Object.getOwnPropertyDescriptor(arguments, 0).enumerable )); Object.defineProperty(arguments, 0, { enumerable: false }); shouldBeFalse(String( Object.getOwnPropertyDescriptor(arguments, 0).writable )); shouldBeFalse(String( Object.getOwnPropertyDescriptor(arguments, 0).enumerable )); delete arguments[1]; shouldBeUndefined(String( Object.getOwnPropertyDescriptor(arguments, 1) )); Object.defineProperty(arguments, 1, { writable: true }); shouldBeTrue(String( Object.getOwnPropertyDescriptor(arguments, 1).writable )); shouldBeFalse(String( Object.getOwnPropertyDescriptor(arguments, 1).enumerable )); })(0,1);