michael@0: /* michael@0: * Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/licenses/publicdomain/ michael@0: */ michael@0: michael@0: var gTestfile = 'strict-arguments.js'; michael@0: var BUGNUMBER = 516255; michael@0: var summary = michael@0: "ES5 strict mode: arguments objects of strict mode functions must copy " + michael@0: "argument values"; michael@0: michael@0: print(BUGNUMBER + ": " + summary); michael@0: michael@0: /************** michael@0: * BEGIN TEST * michael@0: **************/ michael@0: michael@0: function arrayEvery(arr, fun) michael@0: { michael@0: return Array.prototype.every.call(arr, fun); michael@0: } michael@0: michael@0: function arraysEqual(a1, a2) michael@0: { michael@0: return a1.length === a2.length && michael@0: arrayEvery(a1, function(v, i) { return v === a2[i]; }); michael@0: } michael@0: michael@0: michael@0: /************************ michael@0: * NON-STRICT ARGUMENTS * michael@0: ************************/ michael@0: michael@0: var obj = {}; michael@0: michael@0: function noargs() { return arguments; } michael@0: michael@0: assertEq(arraysEqual(noargs(), []), true); michael@0: assertEq(arraysEqual(noargs(1), [1]), true); michael@0: assertEq(arraysEqual(noargs(2, obj, 8), [2, obj, 8]), true); michael@0: michael@0: function args(a) { return arguments; } michael@0: michael@0: assertEq(arraysEqual(args(), []), true); michael@0: assertEq(arraysEqual(args(1), [1]), true); michael@0: assertEq(arraysEqual(args(1, obj), [1, obj]), true); michael@0: assertEq(arraysEqual(args("foopy"), ["foopy"]), true); michael@0: michael@0: function assign(a) michael@0: { michael@0: a = 17; michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(assign(1), [17]), true); michael@0: michael@0: function getLaterAssign(a) michael@0: { michael@0: var o = arguments; michael@0: a = 17; michael@0: return o; michael@0: } michael@0: michael@0: assertEq(arraysEqual(getLaterAssign(1), [17]), true); michael@0: michael@0: function assignElementGetParameter(a) michael@0: { michael@0: arguments[0] = 17; michael@0: return a; michael@0: } michael@0: michael@0: assertEq(assignElementGetParameter(42), 17); michael@0: michael@0: function assignParameterGetElement(a) michael@0: { michael@0: a = 17; michael@0: return arguments[0]; michael@0: } michael@0: michael@0: assertEq(assignParameterGetElement(42), 17); michael@0: michael@0: function assignArgSub(x, y) michael@0: { michael@0: arguments[0] = 3; michael@0: return arguments[0]; michael@0: } michael@0: michael@0: assertEq(assignArgSub(1), 3); michael@0: michael@0: function assignArgSubParamUse(x, y) michael@0: { michael@0: arguments[0] = 3; michael@0: assertEq(x, 3); michael@0: return arguments[0]; michael@0: } michael@0: michael@0: assertEq(assignArgSubParamUse(1), 3); michael@0: michael@0: function assignArgumentsElement(x, y) michael@0: { michael@0: arguments[0] = 3; michael@0: return arguments[Math.random() ? "0" : 0]; // nix arguments[const] optimizations michael@0: } michael@0: michael@0: assertEq(assignArgumentsElement(1), 3); michael@0: michael@0: function assignArgumentsElementParamUse(x, y) michael@0: { michael@0: arguments[0] = 3; michael@0: assertEq(x, 3); michael@0: return arguments[Math.random() ? "0" : 0]; // nix arguments[const] optimizations michael@0: } michael@0: michael@0: assertEq(assignArgumentsElementParamUse(1), 3); michael@0: michael@0: /******************** michael@0: * STRICT ARGUMENTS * michael@0: ********************/ michael@0: michael@0: function strictNoargs() michael@0: { michael@0: "use strict"; michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictNoargs(), []), true); michael@0: assertEq(arraysEqual(strictNoargs(1), [1]), true); michael@0: assertEq(arraysEqual(strictNoargs(1, obj), [1, obj]), true); michael@0: michael@0: function strictArgs(a) michael@0: { michael@0: "use strict"; michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictArgs(), []), true); michael@0: assertEq(arraysEqual(strictArgs(1), [1]), true); michael@0: assertEq(arraysEqual(strictArgs(1, obj), [1, obj]), true); michael@0: michael@0: function strictAssign(a) michael@0: { michael@0: "use strict"; michael@0: a = 17; michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictAssign(), []), true); michael@0: assertEq(arraysEqual(strictAssign(1), [1]), true); michael@0: assertEq(arraysEqual(strictAssign(1, obj), [1, obj]), true); michael@0: michael@0: var upper; michael@0: function strictAssignAfter(a) michael@0: { michael@0: "use strict"; michael@0: upper = arguments; michael@0: a = 42; michael@0: return upper; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictAssignAfter(), []), true); michael@0: assertEq(arraysEqual(strictAssignAfter(17), [17]), true); michael@0: assertEq(arraysEqual(strictAssignAfter(obj), [obj]), true); michael@0: michael@0: function strictMaybeAssignOuterParam(p) michael@0: { michael@0: "use strict"; michael@0: function inner() { p = 17; } michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictMaybeAssignOuterParam(), []), true); michael@0: assertEq(arraysEqual(strictMaybeAssignOuterParam(42), [42]), true); michael@0: assertEq(arraysEqual(strictMaybeAssignOuterParam(obj), [obj]), true); michael@0: michael@0: function strictAssignOuterParam(p) michael@0: { michael@0: "use strict"; michael@0: function inner() { p = 17; } michael@0: inner(); michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictAssignOuterParam(), []), true); michael@0: assertEq(arraysEqual(strictAssignOuterParam(17), [17]), true); michael@0: assertEq(arraysEqual(strictAssignOuterParam(obj), [obj]), true); michael@0: michael@0: function strictAssignOuterParamPSYCH(p) michael@0: { michael@0: "use strict"; michael@0: function inner(p) { p = 17; } michael@0: inner(); michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictAssignOuterParamPSYCH(), []), true); michael@0: assertEq(arraysEqual(strictAssignOuterParamPSYCH(17), [17]), true); michael@0: assertEq(arraysEqual(strictAssignOuterParamPSYCH(obj), [obj]), true); michael@0: michael@0: function strictEval(code, p) michael@0: { michael@0: "use strict"; michael@0: eval(code); michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictEval("1", 2), ["1", 2]), true); michael@0: assertEq(arraysEqual(strictEval("arguments"), ["arguments"]), true); michael@0: assertEq(arraysEqual(strictEval("p = 2"), ["p = 2"]), true); michael@0: assertEq(arraysEqual(strictEval("p = 2", 17), ["p = 2", 17]), true); michael@0: assertEq(arraysEqual(strictEval("arguments[0] = 17"), [17]), true); michael@0: assertEq(arraysEqual(strictEval("arguments[0] = 17", 42), [17, 42]), true); michael@0: michael@0: function strictMaybeNestedEval(code, p) michael@0: { michael@0: "use strict"; michael@0: function inner() { eval(code); } michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictMaybeNestedEval("1", 2), ["1", 2]), true); michael@0: assertEq(arraysEqual(strictMaybeNestedEval("arguments"), ["arguments"]), true); michael@0: assertEq(arraysEqual(strictMaybeNestedEval("p = 2"), ["p = 2"]), true); michael@0: assertEq(arraysEqual(strictMaybeNestedEval("p = 2", 17), ["p = 2", 17]), true); michael@0: michael@0: function strictNestedEval(code, p) michael@0: { michael@0: "use strict"; michael@0: function inner() { eval(code); } michael@0: inner(); michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictNestedEval("1", 2), ["1", 2]), true); michael@0: assertEq(arraysEqual(strictNestedEval("arguments"), ["arguments"]), true); michael@0: assertEq(arraysEqual(strictNestedEval("p = 2"), ["p = 2"]), true); michael@0: assertEq(arraysEqual(strictNestedEval("p = 2", 17), ["p = 2", 17]), true); michael@0: assertEq(arraysEqual(strictNestedEval("arguments[0] = 17"), ["arguments[0] = 17"]), true); michael@0: assertEq(arraysEqual(strictNestedEval("arguments[0] = 17", 42), ["arguments[0] = 17", 42]), true); michael@0: michael@0: function strictAssignArguments(a) michael@0: { michael@0: "use strict"; michael@0: arguments[0] = 42; michael@0: return a; michael@0: } michael@0: michael@0: assertEq(strictAssignArguments(), undefined); michael@0: assertEq(strictAssignArguments(obj), obj); michael@0: assertEq(strictAssignArguments(17), 17); michael@0: michael@0: function strictAssignParameterGetElement(a) michael@0: { michael@0: "use strict"; michael@0: a = 17; michael@0: return arguments[0]; michael@0: } michael@0: michael@0: assertEq(strictAssignParameterGetElement(42), 42); michael@0: michael@0: function strictAssignArgSub(x, y) michael@0: { michael@0: "use strict"; michael@0: arguments[0] = 3; michael@0: return arguments[0]; michael@0: } michael@0: michael@0: assertEq(strictAssignArgSub(1), 3); michael@0: michael@0: function strictAssignArgSubParamUse(x, y) michael@0: { michael@0: "use strict"; michael@0: arguments[0] = 3; michael@0: assertEq(x, 1); michael@0: return arguments[0]; michael@0: } michael@0: michael@0: assertEq(strictAssignArgSubParamUse(1), 3); michael@0: michael@0: function strictAssignArgumentsElement(x, y) michael@0: { michael@0: "use strict"; michael@0: arguments[0] = 3; michael@0: return arguments[Math.random() ? "0" : 0]; // nix arguments[const] optimizations michael@0: } michael@0: michael@0: assertEq(strictAssignArgumentsElement(1), 3); michael@0: michael@0: function strictAssignArgumentsElementParamUse(x, y) michael@0: { michael@0: "use strict"; michael@0: arguments[0] = 3; michael@0: assertEq(x, 1); michael@0: return arguments[Math.random() ? "0" : 0]; // nix arguments[const] optimizations michael@0: } michael@0: michael@0: assertEq(strictAssignArgumentsElementParamUse(1), 3); michael@0: michael@0: function strictNestedAssignShadowVar(p) michael@0: { michael@0: "use strict"; michael@0: function inner() michael@0: { michael@0: var p = 12; michael@0: function innermost() { p = 1776; return 12; } michael@0: return innermost(); michael@0: } michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictNestedAssignShadowVar(), []), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowVar(99), [99]), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowVar(""), [""]), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowVar(obj), [obj]), true); michael@0: michael@0: function strictNestedAssignShadowCatch(p) michael@0: { michael@0: "use strict"; michael@0: function inner() michael@0: { michael@0: try michael@0: { michael@0: } michael@0: catch (p) michael@0: { michael@0: var f = function innermost() { p = 1776; return 12; }; michael@0: f(); michael@0: } michael@0: } michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictNestedAssignShadowCatch(), []), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowCatch(99), [99]), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowCatch(""), [""]), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowCatch(obj), [obj]), true); michael@0: michael@0: function strictNestedAssignShadowCatchCall(p) michael@0: { michael@0: "use strict"; michael@0: function inner() michael@0: { michael@0: try michael@0: { michael@0: } michael@0: catch (p) michael@0: { michael@0: var f = function innermost() { p = 1776; return 12; }; michael@0: f(); michael@0: } michael@0: } michael@0: inner(); michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictNestedAssignShadowCatchCall(), []), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowCatchCall(99), [99]), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowCatchCall(""), [""]), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowCatchCall(obj), [obj]), true); michael@0: michael@0: function strictNestedAssignShadowFunction(p) michael@0: { michael@0: "use strict"; michael@0: function inner() michael@0: { michael@0: function p() { } michael@0: p = 1776; michael@0: } michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictNestedAssignShadowFunction(), []), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowFunction(99), [99]), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowFunction(""), [""]), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowFunction(obj), [obj]), true); michael@0: michael@0: function strictNestedAssignShadowFunctionCall(p) michael@0: { michael@0: "use strict"; michael@0: function inner() michael@0: { michael@0: function p() { } michael@0: p = 1776; michael@0: } michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictNestedAssignShadowFunctionCall(), []), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowFunctionCall(99), [99]), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowFunctionCall(""), [""]), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowFunctionCall(obj), [obj]), true); michael@0: michael@0: function strictNestedShadowAndMaybeEval(code, p) michael@0: { michael@0: "use strict"; michael@0: function inner(p) { eval(code); } michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictNestedShadowAndMaybeEval("1", 2), ["1", 2]), true); michael@0: assertEq(arraysEqual(strictNestedShadowAndMaybeEval("arguments"), ["arguments"]), true); michael@0: assertEq(arraysEqual(strictNestedShadowAndMaybeEval("p = 2"), ["p = 2"]), true); michael@0: assertEq(arraysEqual(strictNestedShadowAndMaybeEval("p = 2", 17), ["p = 2", 17]), true); michael@0: assertEq(arraysEqual(strictNestedShadowAndMaybeEval("arguments[0] = 17"), ["arguments[0] = 17"]), true); michael@0: assertEq(arraysEqual(strictNestedShadowAndMaybeEval("arguments[0] = 17", 42), ["arguments[0] = 17", 42]), true); michael@0: michael@0: function strictNestedShadowAndEval(code, p) michael@0: { michael@0: "use strict"; michael@0: function inner(p) { eval(code); } michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictNestedShadowAndEval("1", 2), ["1", 2]), true); michael@0: assertEq(arraysEqual(strictNestedShadowAndEval("arguments"), ["arguments"]), true); michael@0: assertEq(arraysEqual(strictNestedShadowAndEval("p = 2"), ["p = 2"]), true); michael@0: assertEq(arraysEqual(strictNestedShadowAndEval("p = 2", 17), ["p = 2", 17]), true); michael@0: assertEq(arraysEqual(strictNestedShadowAndEval("arguments[0] = 17"), ["arguments[0] = 17"]), true); michael@0: assertEq(arraysEqual(strictNestedShadowAndEval("arguments[0] = 17", 42), ["arguments[0] = 17", 42]), true); michael@0: michael@0: function strictEvalContainsMutation(code) michael@0: { michael@0: "use strict"; michael@0: return eval(code); michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictEvalContainsMutation("code = 17; arguments"), ["code = 17; arguments"]), true); michael@0: assertEq(arraysEqual(strictEvalContainsMutation("arguments[0] = 17; arguments"), [17]), true); michael@0: assertEq(strictEvalContainsMutation("arguments[0] = 17; code"), "arguments[0] = 17; code"); michael@0: michael@0: function strictNestedAssignShadowFunctionName(p) michael@0: { michael@0: "use strict"; michael@0: function inner() michael@0: { michael@0: function p() { p = 1776; } michael@0: p(); michael@0: } michael@0: inner(); michael@0: return arguments; michael@0: } michael@0: michael@0: assertEq(arraysEqual(strictNestedAssignShadowFunctionName(), []), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowFunctionName(99), [99]), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowFunctionName(""), [""]), true); michael@0: assertEq(arraysEqual(strictNestedAssignShadowFunctionName(obj), [obj]), true); michael@0: michael@0: michael@0: /******************************************************************************/ michael@0: michael@0: if (typeof reportCompare === "function") michael@0: reportCompare(true, true); michael@0: michael@0: print("All tests passed!");