diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 0a9f5f39d297..616acb3a5d4e 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -1642,7 +1642,7 @@ Parser::functionArguments(FunctionSyntaxKind kind, Node *listp, No #endif /* JS_HAS_DESTRUCTURING */ case TOK_YIELD: - if (!checkYieldNameValidity(JSMSG_MISSING_FORMAL)) + if (!checkYieldNameValidity()) return false; goto TOK_NAME; @@ -1720,20 +1720,6 @@ Parser::functionArguments(FunctionSyntaxKind kind, Node *listp, No return true; } -template -bool -Parser::checkFunctionName(HandlePropertyName funName) -{ - if (pc->isStarGenerator() && funName == context->names().yield) { - // The name of a named function expression is specified to be bound in - // the outer context as if via "let". In an ES6 generator, "yield" is - // not a valid name for a let-bound variable. - report(ParseError, false, null(), JSMSG_RESERVED_ID, "yield"); - return false; - } - return true; -} - template <> bool Parser::checkFunctionDefinition(HandlePropertyName funName, @@ -1746,9 +1732,6 @@ Parser::checkFunctionDefinition(HandlePropertyName funName, /* Function statements add a binding to the enclosing scope. */ bool bodyLevel = pc->atBodyLevel(); - if (!checkFunctionName(funName)) - return false; - if (kind == Statement) { /* * Handle redeclaration and optimize cases where we can statically bind the @@ -1940,9 +1923,6 @@ Parser::checkFunctionDefinition(HandlePropertyName funName, /* Function statements add a binding to the enclosing scope. */ bool bodyLevel = pc->atBodyLevel(); - if (!checkFunctionName(funName)) - return false; - if (kind == Statement) { /* * Handle redeclaration and optimize cases where we can statically bind the @@ -2419,15 +2399,11 @@ Parser::moduleDecl() template bool -Parser::checkYieldNameValidity(unsigned errorNumber) +Parser::checkYieldNameValidity() { - // In star generators and in JS >= 1.7, yield is a keyword. - if (pc->isStarGenerator() || versionNumber() >= JSVERSION_1_7) { - report(ParseError, false, null(), errorNumber); - return false; - } - // Otherwise in strict mode, yield is a future reserved word. - if (pc->sc->strict) { + // In star generators and in JS >= 1.7, yield is a keyword. Otherwise in + // strict mode, yield is a future reserved word. + if (pc->isStarGenerator() || versionNumber() >= JSVERSION_1_7 || pc->sc->strict) { report(ParseError, false, null(), JSMSG_RESERVED_ID, "yield"); return false; } @@ -2445,16 +2421,20 @@ Parser::functionStmt() RootedPropertyName name(context); GeneratorKind generatorKind = NotGenerator; - TokenKind tt = tokenStream.getToken(TokenStream::KeywordIsName); + TokenKind tt = tokenStream.getToken(); if (tt == TOK_MUL) { tokenStream.tell(&start); - tt = tokenStream.getToken(TokenStream::KeywordIsName); + tt = tokenStream.getToken(); generatorKind = StarGenerator; } if (tt == TOK_NAME) { name = tokenStream.currentName(); + } else if (tt == TOK_YIELD) { + if (!checkYieldNameValidity()) + return null(); + name = tokenStream.currentName(); } else { /* Unnamed function expressions are forbidden in statement context. */ report(ParseError, false, null(), JSMSG_UNNAMED_FUNCTION_STMT); @@ -2478,20 +2458,25 @@ Parser::functionExpr() TokenStream::Position start(keepAtoms); tokenStream.tell(&start); - RootedPropertyName name(context); GeneratorKind generatorKind = NotGenerator; - TokenKind tt = tokenStream.getToken(TokenStream::KeywordIsName); + TokenKind tt = tokenStream.getToken(); if (tt == TOK_MUL) { tokenStream.tell(&start); - tt = tokenStream.getToken(TokenStream::KeywordIsName); + tt = tokenStream.getToken(); generatorKind = StarGenerator; } - if (tt == TOK_NAME) + RootedPropertyName name(context); + if (tt == TOK_NAME) { name = tokenStream.currentName(); - else + } else if (tt == TOK_YIELD) { + if (!checkYieldNameValidity()) + return null(); + name = tokenStream.currentName(); + } else { tokenStream.ungetToken(); + } return functionDef(name, start, Normal, Expression, generatorKind); } @@ -3570,7 +3555,7 @@ Parser::variables(ParseNodeKind kind, bool *psimple, if (tt != TOK_NAME) { if (tt == TOK_YIELD) { - if (!checkYieldNameValidity(JSMSG_NO_VARIABLE_NAME)) + if (!checkYieldNameValidity()) return null(); } else { if (tt != TOK_ERROR) @@ -4882,7 +4867,7 @@ Parser::tryStatement() #endif case TOK_YIELD: - if (!checkYieldNameValidity(JSMSG_CATCH_IDENTIFIER)) + if (!checkYieldNameValidity()) return null(); // Fall through. case TOK_NAME: diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 2a252eb869a3..f171c04dbb88 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -458,6 +458,11 @@ class Parser : private AutoGCRooter, public StrictModeGetter bool functionArgsAndBodyGeneric(Node pn, HandleFunction fun, FunctionType type, FunctionSyntaxKind kind, Directives *newDirectives); + // Determine whether |yield| is a valid name in the current context, or + // whether it's prohibited due to strictness, JS version, or occurrence + // inside a star generator. + bool checkYieldNameValidity(); + virtual bool strictMode() { return pc->sc->strict; } const CompileOptions &options() const { @@ -546,7 +551,6 @@ class Parser : private AutoGCRooter, public StrictModeGetter Node identifierName(); bool matchLabel(MutableHandle label); - bool checkYieldNameValidity(unsigned errorNumber = JSMSG_SYNTAX_ERROR); bool allowsForEachIn() { #if !JS_HAS_FOR_EACH_IN @@ -568,7 +572,6 @@ class Parser : private AutoGCRooter, public StrictModeGetter bool checkFunctionArguments(); bool makeDefIntoUse(Definition *dn, Node pn, JSAtom *atom); - bool checkFunctionName(HandlePropertyName funName); bool checkFunctionDefinition(HandlePropertyName funName, Node *pn, FunctionSyntaxKind kind, bool *pbodyProcessed); bool finishFunctionDefinition(Node pn, FunctionBox *funbox, Node prelude, Node body); diff --git a/js/src/jit/AsmJS.cpp b/js/src/jit/AsmJS.cpp index d30056077a53..d9b1fa387875 100644 --- a/js/src/jit/AsmJS.cpp +++ b/js/src/jit/AsmJS.cpp @@ -4588,10 +4588,18 @@ ParseFunction(ModuleCompiler &m, ParseNode **fnOut) DebugOnly tk = tokenStream.getToken(); JS_ASSERT(tk == TOK_FUNCTION); - if (tokenStream.getToken(TokenStream::KeywordIsName) != TOK_NAME) - return false; // This will throw a SyntaxError, no need to m.fail. + RootedPropertyName name(m.cx()); - RootedPropertyName name(m.cx(), tokenStream.currentToken().name()); + TokenKind tt = tokenStream.getToken(); + if (tt == TOK_NAME) { + name = tokenStream.currentName(); + } else if (tt == TOK_YIELD) { + if (!m.parser().checkYieldNameValidity()) + return false; + name = m.cx()->names().yield; + } else { + return false; // The regular parser will throw a SyntaxError, no need to m.fail. + } ParseNode *fn = m.parser().handler.newFunctionDefinition(); if (!fn) diff --git a/js/src/tests/ecma_5/misc/future-reserved-words.js b/js/src/tests/ecma_5/misc/future-reserved-words.js index 207e74916d45..b4a41a2b9387 100644 --- a/js/src/tests/ecma_5/misc/future-reserved-words.js +++ b/js/src/tests/ecma_5/misc/future-reserved-words.js @@ -37,7 +37,7 @@ var strictFutureReservedWords = "yield", // enabled: this file doesn't execute as JS1.7 ]; -function testWord(word, wordKind, expectNormal, expectStrict) +function testWord(word, expectNormal, expectStrict) { var actual, status; @@ -355,22 +355,19 @@ function testWord(word, wordKind, expectNormal, expectStrict) // USE AS FUNCTION NAME IN FUNCTION DECLARATION - if (wordKind !== "reserved") + actual = ""; + status = summary + ": " + word + ": normal function name"; + try { - actual = ""; - status = summary + ": " + word + ": normal function name"; - try - { - eval("function " + word + "() { }"); - actual = "no error"; - } - catch (e) - { - actual = e.name; - status += ", " + e.name + ": " + e.message + " "; - } - reportCompare(expectNormal, actual, status); + eval("function " + word + "() { }"); + actual = "no error"; } + catch (e) + { + actual = e.name; + status += ", " + e.name + ": " + e.message + " "; + } + reportCompare(expectNormal, actual, status); actual = ""; status = summary + ": " + word + ": strict function name"; @@ -402,22 +399,19 @@ function testWord(word, wordKind, expectNormal, expectStrict) // USE AS FUNCTION NAME IN FUNCTION EXPRESSION - if (wordKind !== "reserved") + actual = ""; + status = summary + ": " + word + ": normal function expression name"; + try { - actual = ""; - status = summary + ": " + word + ": normal function expression name"; - try - { - eval("var s = (function " + word + "() { });"); - actual = "no error"; - } - catch (e) - { - actual = e.name; - status += ", " + e.name + ": " + e.message + " "; - } - reportCompare(expectNormal, actual, status); + eval("var s = (function " + word + "() { });"); + actual = "no error"; } + catch (e) + { + actual = e.name; + status += ", " + e.name + ": " + e.message + " "; + } + reportCompare(expectNormal, actual, status); actual = ""; status = summary + ": " + word + ": strict function expression name"; @@ -450,12 +444,12 @@ function testWord(word, wordKind, expectNormal, expectStrict) function testFutureReservedWord(word) { - testWord(word, "reserved", "SyntaxError", "SyntaxError"); + testWord(word, "SyntaxError", "SyntaxError"); } function testStrictFutureReservedWord(word) { - testWord(word, "strict reserved", "no error", "SyntaxError"); + testWord(word, "no error", "SyntaxError"); } futureReservedWords.forEach(testFutureReservedWord); diff --git a/js/src/tests/js1_5/LexicalConventions/regress-343675.js b/js/src/tests/js1_5/LexicalConventions/regress-343675.js deleted file mode 100644 index ae3f4200e415..000000000000 --- a/js/src/tests/js1_5/LexicalConventions/regress-343675.js +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 343675; -var summary = 'Allow keywords, reserved words as function names'; -var actual = ''; -var expect = 'No Error'; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - var words = [ - 'break', 'else', 'new', 'var', 'case', 'finally', 'return', 'void', - 'catch', 'for', 'switch', 'while', 'continue', 'function', 'this', - 'with', 'default', 'if', 'throw', 'delete', 'in', 'try', 'do', - 'instanceof', 'typeof', - 'abstract', 'enum', 'int', 'short', 'boolean', 'export', 'interface', - 'static', 'byte', 'extends', 'long', 'super', 'char', 'final', 'native', - 'synchronized', 'class', 'float', 'package', 'throws', 'const', 'goto', - 'private', 'transient', 'debugger', 'implements', 'protected', 'volatile', - 'double', 'import', 'public']; - - for (var i = 0; i < words.length; i++) - { - try - { - actual = 'No Error'; - eval('function ' + words[i] + '() {}'); - } - catch(ex) - { - actual = ex + ''; - } - reportCompare(expect, actual, summary + ': ' + words[i]); - } - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_7/lexical/regress-351515.js b/js/src/tests/js1_7/lexical/regress-351515.js index 403321df3c3a..4420f7f4e911 100644 --- a/js/src/tests/js1_7/lexical/regress-351515.js +++ b/js/src/tests/js1_7/lexical/regress-351515.js @@ -93,17 +93,5 @@ function test() } reportCompare(expect, actual, summary + ': function () { var let;}'); - try - { - expect = 'No Error'; - function yield() {} - actual = 'No Error'; - } - catch(ex) - { - actual = ex + ''; - } - reportCompare(expect, actual, summary + ': function yield()'); - exitFunc ('test'); } diff --git a/js/src/tests/js1_8_1/regress/regress-452498-117.js b/js/src/tests/js1_8_1/regress/regress-452498-117.js index 42373f610fda..4d1f9006babc 100644 --- a/js/src/tests/js1_8_1/regress/regress-452498-117.js +++ b/js/src/tests/js1_8_1/regress/regress-452498-117.js @@ -36,11 +36,7 @@ function test() // Assertion failure: !pn->isPlaceholder(), at ../jsparse.cpp:4876 // ===== - (function(){ var x; eval("var x; x = null"); })() - -// Assertion failure: regs.sp == StackBase(fp), at ../jsinterp.cpp:2984 -// ===== - function this ({x}) { function x(){} } + (function(){ var x; eval("var x; x = null"); })(); // Assertion failure: !(pnu->pn_dflags & PND_BOUND), at ../jsemit.cpp:1818 // ===== diff --git a/services/common/modules-testing/storageserver.js b/services/common/modules-testing/storageserver.js index b1fc9718ae65..da4911ff779c 100644 --- a/services/common/modules-testing/storageserver.js +++ b/services/common/modules-testing/storageserver.js @@ -111,7 +111,7 @@ ServerBSO.prototype = { return obj; }, - delete: function delete() { + delete: function delete_() { this.deleted = true; delete this.payload; @@ -571,7 +571,7 @@ StorageServerCollection.prototype = { return {success: success, failed: failed}; }, - delete: function delete(options) { + delete: function delete_(options) { options = options || {}; // Protocol 2.0 only allows the "ids" query string argument.