michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: 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: /* michael@0: * In strict mode, it is a syntax error for an identifier to appear michael@0: * more than once in a function's argument list. michael@0: */ michael@0: michael@0: /* michael@0: * The parameters of ordinary function definitions should not contain michael@0: * duplicate identifiers. michael@0: */ michael@0: assertEq(testLenientAndStrict('function f(x,y) {}', michael@0: parsesSuccessfully, michael@0: parsesSuccessfully), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f(x,x) {}', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f(x,y,z,y) {}', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: michael@0: /* Exercise the hashed local name map case. */ michael@0: assertEq(testLenientAndStrict('function f(a,b,c,d,e,f,g,h,d) {}', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: michael@0: /* michael@0: * SpiderMonkey has always treated duplicates in destructuring michael@0: * patterns as an error. Strict mode should not affect this. michael@0: */ michael@0: assertEq(testLenientAndStrict('function f([x,y]) {}', michael@0: parsesSuccessfully, michael@0: parsesSuccessfully), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f([x,x]){}', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f(x,[x]){}', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: michael@0: /* michael@0: * Strict rules apply to the parameters if the function's body is michael@0: * strict. michael@0: */ michael@0: assertEq(testLenientAndStrict('function f(x,x) { "use strict" };', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: michael@0: /* michael@0: * Calls to the function constructor should not be affected by the michael@0: * strictness of the calling code, but should be affected by the michael@0: * strictness of the function body. michael@0: */ michael@0: assertEq(testLenientAndStrict('Function("x","x","")', michael@0: completesNormally, michael@0: completesNormally), michael@0: true); michael@0: assertEq(testLenientAndStrict('Function("x","y","")', michael@0: completesNormally, michael@0: completesNormally), michael@0: true); michael@0: assertEq(testLenientAndStrict('Function("x","x","\'use strict\'")', michael@0: raisesException(SyntaxError), michael@0: raisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('Function("x","y","\'use strict\'")', michael@0: completesNormally, michael@0: completesNormally), michael@0: true); michael@0: michael@0: michael@0: /* michael@0: * The parameter lists of function expressions should not contain michael@0: * duplicate identifiers. michael@0: */ michael@0: assertEq(testLenientAndStrict('(function (x,x) 2)', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function (x,y) 2)', michael@0: parsesSuccessfully, michael@0: parsesSuccessfully), michael@0: true); michael@0: michael@0: /* michael@0: * All permutations of: michael@0: * - For the two magic identifiers 'arguments' or 'eval' michael@0: * - For function definitions, function expressions, expression closures, michael@0: * and getter and setter property definitions, michael@0: * - For forms that inherit their context's strictness, and forms that michael@0: * include their own strictness directives, michael@0: * - For ordinary parameters, array destructuring parameters, and michael@0: * object destructuring parameters, michael@0: * - the magic identifiers may be used to name such parameters michael@0: * in lenient code, but not in strict code michael@0: * - the magic identifiers may be used as function names in lenient code, michael@0: * but not in strict code michael@0: */ michael@0: assertEq(testLenientAndStrict('function f(eval){}', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f([eval]){}', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f({x:eval}){}', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function eval(){}', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f(eval){"use strict";}', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f([eval]){"use strict";}', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f({x:eval}){"use strict";}', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function eval(){"use strict";}', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f(eval){})', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f([eval]){})', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f({x:eval}){})', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function eval(){})', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f(eval){"use strict";})', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f([eval]){"use strict";})', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f({x:eval}){"use strict";})', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function eval(){"use strict";})', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f(eval) 2)', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f([eval]) 2)', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f({x:eval}) 2)', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function eval() 2)', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('({set x(eval){}})', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('({set x([eval]){}})', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('({set x({x:eval}){}})', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('({set x(eval){"use strict";}})', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('({set x([eval]){"use strict";}})', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('({set x({x:eval}){"use strict";}})', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f(arguments){}', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f([arguments]){}', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f({x:arguments}){}', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function arguments(){}', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f(arguments){"use strict";}', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f([arguments]){"use strict";}', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function f({x:arguments}){"use strict";}', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('function arguments(){"use strict";}', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f(arguments){})', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f([arguments]){})', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f({x:arguments}){})', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function arguments(){})', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f(arguments){"use strict";})', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f([arguments]){"use strict";})', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f({x:arguments}){"use strict";})', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function arguments(){"use strict";})', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f(arguments) 2)', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f([arguments]) 2)', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function f({x:arguments}) 2)', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('(function arguments() 2)', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('({set x(arguments){}})', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('({set x([arguments]){}})', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('({set x({x:arguments}){}})', michael@0: parsesSuccessfully, michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('({set x(arguments){"use strict";}})', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('({set x([arguments]){"use strict";}})', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('({set x({x:arguments}){"use strict";}})', michael@0: parseRaisesException(SyntaxError), michael@0: parseRaisesException(SyntaxError)), michael@0: true); michael@0: michael@0: /* michael@0: * Functions produced using the Function constructor may not use michael@0: * 'eval' or 'arguments' as a parameter name if their body is strict michael@0: * mode code. The strictness of the calling code does not affect the michael@0: * constraints applied to the parameters. michael@0: */ michael@0: assertEq(testLenientAndStrict('Function("eval","")', michael@0: completesNormally, michael@0: completesNormally), michael@0: true); michael@0: assertEq(testLenientAndStrict('Function("eval","\'use strict\';")', michael@0: raisesException(SyntaxError), michael@0: raisesException(SyntaxError)), michael@0: true); michael@0: assertEq(testLenientAndStrict('Function("arguments","")', michael@0: completesNormally, michael@0: completesNormally), michael@0: true); michael@0: assertEq(testLenientAndStrict('Function("arguments","\'use strict\';")', michael@0: raisesException(SyntaxError), michael@0: raisesException(SyntaxError)), michael@0: true); michael@0: michael@0: michael@0: reportCompare(true, true);