Backed out changeset f023c533e279 (bug 1066827)

This commit is contained in:
Carsten "Tomcat" Book 2014-10-28 12:23:10 +01:00
Родитель 2fd965d25b
Коммит 9d4fce3e37
3 изменённых файлов: 189 добавлений и 348 удалений

Просмотреть файл

@ -698,10 +698,7 @@ Parser<ParseHandler>::parse(JSObject *chain)
Node pn = statements(); Node pn = statements();
if (pn) { if (pn) {
bool matched; if (!tokenStream.matchToken(TOK_EOF)) {
if (!tokenStream.matchToken(&matched, TOK_EOF))
return null();
if (!matched) {
TokenKind tt; TokenKind tt;
if (!tokenStream.peekToken(&tt)) if (!tokenStream.peekToken(&tt))
return null(); return null();
@ -823,10 +820,7 @@ Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun, const AutoN
if (!pn) if (!pn)
return null(); return null();
bool matched; if (!tokenStream.matchToken(TOK_EOF)) {
if (!tokenStream.matchToken(&matched, TOK_EOF))
return null();
if (!matched) {
TokenKind tt; TokenKind tt;
if (!tokenStream.peekToken(&tt)) if (!tokenStream.peekToken(&tt))
return null(); return null();
@ -1237,8 +1231,8 @@ MatchOrInsertSemicolon(TokenStream &ts)
ts.reportError(JSMSG_SEMI_BEFORE_STMNT); ts.reportError(JSMSG_SEMI_BEFORE_STMNT);
return false; return false;
} }
bool ignored; (void) ts.matchToken(TOK_SEMI);
return ts.matchToken(&ignored, TOK_SEMI); return true;
} }
template <typename ParseHandler> template <typename ParseHandler>
@ -1563,22 +1557,12 @@ Parser<ParseHandler>::functionArguments(FunctionSyntaxKind kind, Node *listp, No
return false; return false;
handler.setFunctionBody(funcpn, argsbody); handler.setFunctionBody(funcpn, argsbody);
bool hasArguments = false; if (parenFreeArrow || !tokenStream.matchToken(TOK_RP)) {
if (parenFreeArrow) {
hasArguments = true;
} else {
bool matched;
if (!tokenStream.matchToken(&matched, TOK_RP))
return false;
if (!matched)
hasArguments = true;
}
if (hasArguments) {
bool hasDefaults = false; bool hasDefaults = false;
Node duplicatedArg = null(); Node duplicatedArg = null();
Node list = null(); Node list = null();
while (true) { do {
if (*hasRest) { if (*hasRest) {
report(ParseError, false, null(), JSMSG_PARAMETER_AFTER_REST); report(ParseError, false, null(), JSMSG_PARAMETER_AFTER_REST);
return false; return false;
@ -1674,10 +1658,7 @@ Parser<ParseHandler>::functionArguments(FunctionSyntaxKind kind, Node *listp, No
if (!defineArg(funcpn, name, disallowDuplicateArgs, &duplicatedArg)) if (!defineArg(funcpn, name, disallowDuplicateArgs, &duplicatedArg))
return false; return false;
bool matched; if (tokenStream.matchToken(TOK_ASSIGN)) {
if (!tokenStream.matchToken(&matched, TOK_ASSIGN))
return false;
if (matched) {
// A default argument without parentheses would look like: // A default argument without parentheses would look like:
// a = expr => body, but both operators are right-associative, so // a = expr => body, but both operators are right-associative, so
// that would have been parsed as a = (expr => body) instead. // that would have been parsed as a = (expr => body) instead.
@ -1712,16 +1693,7 @@ Parser<ParseHandler>::functionArguments(FunctionSyntaxKind kind, Node *listp, No
report(ParseError, false, null(), JSMSG_MISSING_FORMAL); report(ParseError, false, null(), JSMSG_MISSING_FORMAL);
return false; return false;
} }
} while (!parenFreeArrow && tokenStream.matchToken(TOK_COMMA));
if (parenFreeArrow)
break;
bool matched;
if (!tokenStream.matchToken(&matched, TOK_COMMA))
return false;
if (!matched)
break;
}
if (!parenFreeArrow) { if (!parenFreeArrow) {
TokenKind tt; TokenKind tt;
@ -2466,14 +2438,9 @@ Parser<ParseHandler>::functionArgsAndBodyGeneric(Node pn, HandleFunction fun, Fu
return false; return false;
} }
if (kind == Arrow) { if (kind == Arrow && !tokenStream.matchToken(TOK_ARROW)) {
bool matched; report(ParseError, false, null(), JSMSG_BAD_ARROW_ARGS);
if (!tokenStream.matchToken(&matched, TOK_ARROW)) return false;
return false;
if (!matched) {
report(ParseError, false, null(), JSMSG_BAD_ARROW_ARGS);
return false;
}
} }
// Parse the function body. // Parse the function body.
@ -2505,10 +2472,7 @@ Parser<ParseHandler>::functionArgsAndBodyGeneric(Node pn, HandleFunction fun, Fu
#if JS_HAS_EXPR_CLOSURES #if JS_HAS_EXPR_CLOSURES
if (bodyType == StatementListBody) { if (bodyType == StatementListBody) {
#endif #endif
bool matched; if (!tokenStream.matchToken(TOK_RC)) {
if (!tokenStream.matchToken(&matched, TOK_RC))
return false;
if (!matched) {
report(ParseError, false, null(), JSMSG_CURLY_AFTER_BODY); report(ParseError, false, null(), JSMSG_CURLY_AFTER_BODY);
return false; return false;
} }
@ -3556,41 +3520,28 @@ Parser<ParseHandler>::letBlock(LetContext letContext)
handler.setBeginPosition(pnlet, begin); handler.setBeginPosition(pnlet, begin);
bool needExprStmt = false; bool needExprStmt = false;
if (letContext == LetStatement) { if (letContext == LetStatement && !tokenStream.matchToken(TOK_LC, TokenStream::Operand)) {
bool matched; /*
if (!tokenStream.matchToken(&matched, TOK_LC, TokenStream::Operand)) * Strict mode eliminates a grammar ambiguity with unparenthesized
* LetExpressions in an ExpressionStatement. If followed immediately
* by an arguments list, it's ambiguous whether the let expression
* is the callee or the call is inside the let expression body.
*
* See bug 569464.
*/
if (!report(ParseStrictError, pc->sc->strict, pnlet,
JSMSG_STRICT_CODE_LET_EXPR_STMT))
{
return null(); return null();
if (!matched) {
/*
* Strict mode eliminates a grammar ambiguity with unparenthesized
* LetExpressions in an ExpressionStatement. If followed immediately
* by an arguments list, it's ambiguous whether the let expression
* is the callee or the call is inside the let expression body.
*
* function id(x) { return x; }
* var x = "outer";
* // Does this parse as
* // (let (loc = "inner") id)(loc) // "outer"
* // or as
* // let (loc = "inner") (id(loc)) // "inner"
* let (loc = "inner") id(loc);
*
* See bug 569464.
*/
if (!report(ParseStrictError, pc->sc->strict, pnlet,
JSMSG_STRICT_CODE_LET_EXPR_STMT))
{
return null();
}
/*
* If this is really an expression in let statement guise, then we
* need to wrap the PNK_LET node in a PNK_SEMI node so that we pop
* the return value of the expression.
*/
needExprStmt = true;
letContext = LetExpresion;
} }
/*
* If this is really an expression in let statement guise, then we
* need to wrap the PNK_LET node in a PNK_SEMI node so that we pop
* the return value of the expression.
*/
needExprStmt = true;
letContext = LetExpresion;
} }
Node expr; Node expr;
@ -3720,121 +3671,107 @@ Parser<ParseHandler>::variables(ParseNodeKind kind, bool *psimple,
bool first = true; bool first = true;
Node pn2; Node pn2;
while (true) { do {
do { if (psimple && !first)
if (psimple && !first) *psimple = false;
first = false;
TokenKind tt;
if (!tokenStream.getToken(&tt))
return null();
if (tt == TOK_LB || tt == TOK_LC) {
if (psimple)
*psimple = false; *psimple = false;
first = false;
TokenKind tt; pc->inDeclDestructuring = true;
if (!tokenStream.getToken(&tt)) pn2 = primaryExpr(tt);
return null(); pc->inDeclDestructuring = false;
if (tt == TOK_LB || tt == TOK_LC) {
if (psimple)
*psimple = false;
pc->inDeclDestructuring = true;
pn2 = primaryExpr(tt);
pc->inDeclDestructuring = false;
if (!pn2)
return null();
bool parsingForInOrOfInit = false;
if (pc->parsingForInit) {
bool isForIn, isForOf;
if (!matchInOrOf(&isForIn, &isForOf))
return null();
parsingForInOrOfInit = isForIn || isForOf;
}
// See comment below for bindBeforeInitializer in the code that
// handles the non-destructuring case.
bool bindBeforeInitializer = kind != PNK_LET || parsingForInOrOfInit;
if (bindBeforeInitializer && !checkDestructuring(&data, pn2))
return null();
if (parsingForInOrOfInit) {
tokenStream.ungetToken();
handler.addList(pn, pn2);
break;
}
MUST_MATCH_TOKEN(TOK_ASSIGN, JSMSG_BAD_DESTRUCT_DECL);
Node init = assignExpr();
if (!init)
return null();
if (!bindBeforeInitializer && !checkDestructuring(&data, pn2))
return null();
pn2 = handler.newBinaryOrAppend(PNK_ASSIGN, pn2, init, pc);
if (!pn2)
return null();
handler.addList(pn, pn2);
break;
}
if (tt != TOK_NAME) {
if (tt == TOK_YIELD) {
if (!checkYieldNameValidity())
return null();
} else {
report(ParseError, false, null(), JSMSG_NO_VARIABLE_NAME);
return null();
}
}
RootedPropertyName name(context, tokenStream.currentName());
pn2 = newBindingNode(name, kind == PNK_VAR || kind == PNK_CONST, varContext);
if (!pn2) if (!pn2)
return null(); return null();
if (data.op == JSOP_DEFCONST)
handler.setFlag(pn2, PND_CONST);
data.pn = pn2;
handler.addList(pn, pn2); bool ignored;
bool parsingForInOrOfInit = pc->parsingForInit && matchInOrOf(&ignored);
bool matched; // See comment below for bindBeforeInitializer in the code that
if (!tokenStream.matchToken(&matched, TOK_ASSIGN)) // handles the non-destructuring case.
bool bindBeforeInitializer = kind != PNK_LET || parsingForInOrOfInit;
if (bindBeforeInitializer && !checkDestructuring(&data, pn2))
return null(); return null();
if (matched) {
if (psimple)
*psimple = false;
// In ES6, lexical bindings may not be accessed until if (parsingForInOrOfInit) {
// initialized. So a declaration of the form |let x = x| results tokenStream.ungetToken();
// in a ReferenceError, as the 'x' on the RHS is accessing the let handler.addList(pn, pn2);
// binding before it is initialized. continue;
// }
// If we are not parsing a let declaration, bind the name
// now. Otherwise we must wait until after parsing the initializing
// assignment.
bool bindBeforeInitializer = kind != PNK_LET;
if (bindBeforeInitializer && !data.binder(&data, name, this))
return null();
Node init = assignExpr(); MUST_MATCH_TOKEN(TOK_ASSIGN, JSMSG_BAD_DESTRUCT_DECL);
if (!init)
return null();
if (!bindBeforeInitializer && !data.binder(&data, name, this)) Node init = assignExpr();
return null(); if (!init)
return null();
if (!handler.finishInitializerAssignment(pn2, init, data.op)) if (!bindBeforeInitializer && !checkDestructuring(&data, pn2))
return null();
pn2 = handler.newBinaryOrAppend(PNK_ASSIGN, pn2, init, pc);
if (!pn2)
return null();
handler.addList(pn, pn2);
continue;
}
if (tt != TOK_NAME) {
if (tt == TOK_YIELD) {
if (!checkYieldNameValidity())
return null(); return null();
} else { } else {
if (!data.binder(&data, name, this)) report(ParseError, false, null(), JSMSG_NO_VARIABLE_NAME);
return null(); return null();
} }
} while (false); }
bool matched; RootedPropertyName name(context, tokenStream.currentName());
if (!tokenStream.matchToken(&matched, TOK_COMMA)) pn2 = newBindingNode(name, kind == PNK_VAR || kind == PNK_CONST, varContext);
if (!pn2)
return null(); return null();
if (!matched) if (data.op == JSOP_DEFCONST)
break; handler.setFlag(pn2, PND_CONST);
} data.pn = pn2;
handler.addList(pn, pn2);
if (tokenStream.matchToken(TOK_ASSIGN)) {
if (psimple)
*psimple = false;
// In ES6, lexical bindings may not be accessed until
// initialized. So a declaration of the form |let x = x| results
// in a ReferenceError, as the 'x' on the RHS is accessing the let
// binding before it is initialized.
//
// If we are not parsing a let declaration, bind the name
// now. Otherwise we must wait until after parsing the initializing
// assignment.
bool bindBeforeInitializer = kind != PNK_LET;
if (bindBeforeInitializer && !data.binder(&data, name, this))
return null();
Node init = assignExpr();
if (!init)
return null();
if (!bindBeforeInitializer && !data.binder(&data, name, this))
return null();
if (!handler.finishInitializerAssignment(pn2, init, data.op))
return null();
} else {
if (!data.binder(&data, name, this))
return null();
}
} while (tokenStream.matchToken(TOK_COMMA));
return pn; return pn;
} }
@ -4045,7 +3982,7 @@ Parser<ParseHandler>::importDeclaration()
handler.addList(importSpecSet, importSpec); handler.addList(importSpecSet, importSpec);
} else { } else {
while (true) { do {
// Handle the forms |import {} from 'a'| and // Handle the forms |import {} from 'a'| and
// |import { ..., } from 'a'| (where ... is non empty), by // |import { ..., } from 'a'| (where ... is non empty), by
// escaping the loop early if the next token is }. // escaping the loop early if the next token is }.
@ -4093,13 +4030,7 @@ Parser<ParseHandler>::importDeclaration()
return null(); return null();
handler.addList(importSpecSet, importSpec); handler.addList(importSpecSet, importSpec);
} while (tokenStream.matchToken(TOK_COMMA));
bool matched;
if (!tokenStream.matchToken(&matched, TOK_COMMA))
return null();
if (!matched)
break;
}
MUST_MATCH_TOKEN(TOK_RC, JSMSG_RC_AFTER_IMPORT_SPEC_LIST); MUST_MATCH_TOKEN(TOK_RC, JSMSG_RC_AFTER_IMPORT_SPEC_LIST);
} }
@ -4167,7 +4098,7 @@ Parser<ParseHandler>::exportDeclaration()
return null(); return null();
if (tt == TOK_LC) { if (tt == TOK_LC) {
while (true) { do {
// Handle the forms |export {}| and |export { ..., }| (where ... // Handle the forms |export {}| and |export { ..., }| (where ...
// is non empty), by escaping the loop early if the next token // is non empty), by escaping the loop early if the next token
// is }. // is }.
@ -4202,13 +4133,7 @@ Parser<ParseHandler>::exportDeclaration()
return null(); return null();
handler.addList(kid, exportSpec); handler.addList(kid, exportSpec);
} while (tokenStream.matchToken(TOK_COMMA));
bool matched;
if (!tokenStream.matchToken(&matched, TOK_COMMA))
return null();
if (!matched)
break;
}
MUST_MATCH_TOKEN(TOK_RC, JSMSG_RC_AFTER_EXPORT_SPEC_LIST); MUST_MATCH_TOKEN(TOK_RC, JSMSG_RC_AFTER_EXPORT_SPEC_LIST);
} else { } else {
@ -4327,10 +4252,7 @@ Parser<ParseHandler>::ifStatement()
return null(); return null();
Node elseBranch; Node elseBranch;
bool matched; if (tokenStream.matchToken(TOK_ELSE, TokenStream::Operand)) {
if (!tokenStream.matchToken(&matched, TOK_ELSE, TokenStream::Operand))
return null();
if (matched) {
stmtInfo.type = STMT_ELSE; stmtInfo.type = STMT_ELSE;
elseBranch = statement(); elseBranch = statement();
if (!elseBranch) if (!elseBranch)
@ -4364,9 +4286,7 @@ Parser<ParseHandler>::doWhileStatement()
// http://bugzilla.mozilla.org/show_bug.cgi?id=238945 // http://bugzilla.mozilla.org/show_bug.cgi?id=238945
// ES3 and ES5 disagreed, but ES6 conforms to Web reality: // ES3 and ES5 disagreed, but ES6 conforms to Web reality:
// https://bugs.ecmascript.org/show_bug.cgi?id=157 // https://bugs.ecmascript.org/show_bug.cgi?id=157
bool ignored; tokenStream.matchToken(TOK_SEMI);
if (!tokenStream.matchToken(&ignored, TOK_SEMI))
return null();
return handler.newDoWhileStatement(body, cond, TokenPos(begin, pos().end)); return handler.newDoWhileStatement(body, cond, TokenPos(begin, pos().end));
} }
@ -4389,16 +4309,17 @@ Parser<ParseHandler>::whileStatement()
template <typename ParseHandler> template <typename ParseHandler>
bool bool
Parser<ParseHandler>::matchInOrOf(bool *isForInp, bool *isForOfp) Parser<ParseHandler>::matchInOrOf(bool *isForOfp)
{ {
TokenKind tt; if (tokenStream.matchToken(TOK_IN)) {
if (!tokenStream.getToken(&tt)) *isForOfp = false;
return false; return true;
*isForInp = tt == TOK_IN; }
*isForOfp = tt == TOK_NAME && tokenStream.currentToken().name() == context->names().of; if (tokenStream.matchContextualKeyword(context->names().of)) {
if (!*isForInp && !*isForOfp) *isForOfp = true;
tokenStream.ungetToken(); return true;
return true; }
return false;
} }
template <> template <>
@ -4555,13 +4476,9 @@ Parser<FullParseHandler>::forStatement()
ParseNode *pn2, *pn3; /* forHead->pn_kid2 and pn_kid3. */ ParseNode *pn2, *pn3; /* forHead->pn_kid2 and pn_kid3. */
ParseNodeKind headKind = PNK_FORHEAD; ParseNodeKind headKind = PNK_FORHEAD;
if (pn1) { if (pn1) {
bool isForIn, isForOf; bool isForOf;
if (!matchInOrOf(&isForIn, &isForOf)) if (matchInOrOf(&isForOf))
return null(); headKind = isForOf ? PNK_FOROF : PNK_FORIN;
if (isForIn)
headKind = PNK_FORIN;
else if (isForOf)
headKind = PNK_FOROF;
} }
if (headKind == PNK_FOROF || headKind == PNK_FORIN) { if (headKind == PNK_FOROF || headKind == PNK_FORIN) {
@ -4857,12 +4774,8 @@ Parser<SyntaxParseHandler>::forStatement()
* as we've excluded 'in' from being parsed in RelExpr by setting * as we've excluded 'in' from being parsed in RelExpr by setting
* pc->parsingForInit. * pc->parsingForInit.
*/ */
bool isForIn = false, isForOf = false; bool isForOf;
if (lhsNode) { if (lhsNode && matchInOrOf(&isForOf)) {
if (!matchInOrOf(&isForIn, &isForOf))
return null();
}
if (isForIn || isForOf) {
/* Parse the rest of the for/in or for/of head. */ /* Parse the rest of the for/in or for/of head. */
forStmt.type = isForOf ? STMT_FOR_OF_LOOP : STMT_FOR_IN_LOOP; forStmt.type = isForOf ? STMT_FOR_OF_LOOP : STMT_FOR_IN_LOOP;
@ -5548,10 +5461,7 @@ Parser<ParseHandler>::tryStatement()
* to avoid conflicting with the JS2/ECMAv4 type annotation * to avoid conflicting with the JS2/ECMAv4 type annotation
* catchguard syntax. * catchguard syntax.
*/ */
bool matched; if (tokenStream.matchToken(TOK_IF)) {
if (!tokenStream.matchToken(&matched, TOK_IF))
return null();
if (matched) {
catchGuard = expr(); catchGuard = expr();
if (!catchGuard) if (!catchGuard)
return null(); return null();
@ -5731,17 +5641,11 @@ typename ParseHandler::Node
Parser<ParseHandler>::expr() Parser<ParseHandler>::expr()
{ {
Node pn = assignExpr(); Node pn = assignExpr();
if (!pn) if (pn && tokenStream.matchToken(TOK_COMMA)) {
return null();
bool matched;
if (!tokenStream.matchToken(&matched, TOK_COMMA))
return null();
if (matched) {
Node seq = handler.newList(PNK_COMMA, pn); Node seq = handler.newList(PNK_COMMA, pn);
if (!seq) if (!seq)
return null(); return null();
while (true) { do {
if (handler.isUnparenthesizedYield(pn)) { if (handler.isUnparenthesizedYield(pn)) {
report(ParseError, false, pn, JSMSG_BAD_GENERATOR_SYNTAX, js_yield_str); report(ParseError, false, pn, JSMSG_BAD_GENERATOR_SYNTAX, js_yield_str);
return null(); return null();
@ -5751,12 +5655,7 @@ Parser<ParseHandler>::expr()
if (!pn) if (!pn)
return null(); return null();
handler.addList(seq, pn); handler.addList(seq, pn);
} while (tokenStream.matchToken(TOK_COMMA));
if (!tokenStream.matchToken(&matched, TOK_COMMA))
return null();
if (!matched)
break;
}
return seq; return seq;
} }
return pn; return pn;
@ -6600,7 +6499,7 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode *bodyExpr, unsigned
MOZ_ASSERT(pc->staticScope && pc->staticScope == pn->pn_objbox->object); MOZ_ASSERT(pc->staticScope && pc->staticScope == pn->pn_objbox->object);
data.initLet(HoistVars, &pc->staticScope->as<StaticBlockObject>(), JSMSG_ARRAY_INIT_TOO_BIG); data.initLet(HoistVars, &pc->staticScope->as<StaticBlockObject>(), JSMSG_ARRAY_INIT_TOO_BIG);
while (true) { do {
/* /*
* FOR node is binary, left is loop control and right is body. Use * FOR node is binary, left is loop control and right is body. Use
* index to count each block-local let-variable on the left-hand side * index to count each block-local let-variable on the left-hand side
@ -6651,10 +6550,8 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode *bodyExpr, unsigned
return null(); return null();
} }
bool isForIn, isForOf; bool isForOf;
if (!matchInOrOf(&isForIn, &isForOf)) if (!matchInOrOf(&isForOf)) {
return null();
if (!isForIn && !isForOf) {
report(ParseError, false, null(), JSMSG_IN_AFTER_FOR_NAME); report(ParseError, false, null(), JSMSG_IN_AFTER_FOR_NAME);
return null(); return null();
} }
@ -6738,18 +6635,9 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode *bodyExpr, unsigned
return null(); return null();
*pnp = pn2; *pnp = pn2;
pnp = &pn2->pn_right; pnp = &pn2->pn_right;
} while (tokenStream.matchToken(TOK_FOR));
bool matched; if (tokenStream.matchToken(TOK_IF)) {
if (!tokenStream.matchToken(&matched, TOK_FOR))
return null();
if (!matched)
break;
}
bool matched;
if (!tokenStream.matchToken(&matched, TOK_IF))
return null();
if (matched) {
pn2 = TernaryNode::create(PNK_IF, &handler); pn2 = TernaryNode::create(PNK_IF, &handler);
if (!pn2) if (!pn2)
return null(); return null();
@ -7102,15 +6990,10 @@ Parser<ParseHandler>::comprehensionTail(GeneratorKind comprehensionKind)
{ {
JS_CHECK_RECURSION(context, return null()); JS_CHECK_RECURSION(context, return null());
bool matched; if (tokenStream.matchToken(TOK_FOR, TokenStream::Operand))
if (!tokenStream.matchToken(&matched, TOK_FOR, TokenStream::Operand))
return null();
if (matched)
return comprehensionFor(comprehensionKind); return comprehensionFor(comprehensionKind);
if (!tokenStream.matchToken(&matched, TOK_IF, TokenStream::Operand)) if (tokenStream.matchToken(TOK_IF, TokenStream::Operand))
return null();
if (matched)
return comprehensionIf(comprehensionKind); return comprehensionIf(comprehensionKind);
uint32_t begin = pos().begin; uint32_t begin = pos().begin;
@ -7218,10 +7101,7 @@ template <typename ParseHandler>
bool bool
Parser<ParseHandler>::argumentList(Node listNode, bool *isSpread) Parser<ParseHandler>::argumentList(Node listNode, bool *isSpread)
{ {
bool matched; if (tokenStream.matchToken(TOK_RP, TokenStream::Operand)) {
if (!tokenStream.matchToken(&matched, TOK_RP, TokenStream::Operand))
return false;
if (matched) {
handler.setEndPosition(listNode, pos().end); handler.setEndPosition(listNode, pos().end);
return true; return true;
} }
@ -7229,12 +7109,10 @@ Parser<ParseHandler>::argumentList(Node listNode, bool *isSpread)
uint32_t startYieldOffset = pc->lastYieldOffset; uint32_t startYieldOffset = pc->lastYieldOffset;
bool arg0 = true; bool arg0 = true;
while (true) { do {
bool spread = false; bool spread = false;
uint32_t begin = 0; uint32_t begin = 0;
if (!tokenStream.matchToken(&matched, TOK_TRIPLEDOT, TokenStream::Operand)) if (tokenStream.matchToken(TOK_TRIPLEDOT, TokenStream::Operand)) {
return false;
if (matched) {
spread = true; spread = true;
begin = pos().begin; begin = pos().begin;
*isSpread = true; *isSpread = true;
@ -7259,42 +7137,32 @@ Parser<ParseHandler>::argumentList(Node listNode, bool *isSpread)
} }
} }
#if JS_HAS_GENERATOR_EXPRS #if JS_HAS_GENERATOR_EXPRS
if (!spread) { if (!spread && tokenStream.matchToken(TOK_FOR)) {
if (!tokenStream.matchToken(&matched, TOK_FOR)) if (pc->lastYieldOffset != startYieldOffset) {
reportWithOffset(ParseError, false, pc->lastYieldOffset,
JSMSG_BAD_GENEXP_BODY, js_yield_str);
return false;
}
argNode = legacyGeneratorExpr(argNode);
if (!argNode)
return false;
if (!arg0) {
report(ParseError, false, argNode, JSMSG_BAD_GENERATOR_SYNTAX, js_generator_str);
return false;
}
TokenKind tt;
if (!tokenStream.peekToken(&tt))
return false;
if (tt == TOK_COMMA) {
report(ParseError, false, argNode, JSMSG_BAD_GENERATOR_SYNTAX, js_generator_str);
return false; return false;
if (matched) {
if (pc->lastYieldOffset != startYieldOffset) {
reportWithOffset(ParseError, false, pc->lastYieldOffset,
JSMSG_BAD_GENEXP_BODY, js_yield_str);
return false;
}
argNode = legacyGeneratorExpr(argNode);
if (!argNode)
return false;
if (!arg0) {
report(ParseError, false, argNode, JSMSG_BAD_GENERATOR_SYNTAX, js_generator_str);
return false;
}
TokenKind tt;
if (!tokenStream.peekToken(&tt))
return false;
if (tt == TOK_COMMA) {
report(ParseError, false, argNode, JSMSG_BAD_GENERATOR_SYNTAX, js_generator_str);
return false;
}
} }
} }
#endif #endif
arg0 = false; arg0 = false;
handler.addList(listNode, argNode); handler.addList(listNode, argNode);
} while (tokenStream.matchToken(TOK_COMMA));
bool matched;
if (!tokenStream.matchToken(&matched, TOK_COMMA))
return false;
if (!matched)
break;
}
TokenKind tt; TokenKind tt;
if (!tokenStream.getToken(&tt)) if (!tokenStream.getToken(&tt))
@ -7331,10 +7199,7 @@ Parser<ParseHandler>::memberExpr(TokenKind tt, bool allowCallSyntax)
handler.addList(lhs, ctorExpr); handler.addList(lhs, ctorExpr);
bool matched; if (tokenStream.matchToken(TOK_LP)) {
if (!tokenStream.matchToken(&matched, TOK_LP))
return null();
if (matched) {
bool isSpread = false; bool isSpread = false;
if (!argumentList(lhs, &isSpread)) if (!argumentList(lhs, &isSpread))
return null(); return null();
@ -7518,21 +7383,16 @@ Parser<ParseHandler>::arrayInitializer()
if (!literal) if (!literal)
return null(); return null();
TokenKind tt; if (tokenStream.matchToken(TOK_RB, TokenStream::Operand)) {
if (!tokenStream.getToken(&tt, TokenStream::Operand))
return null();
if (tt == TOK_RB) {
/* /*
* Mark empty arrays as non-constant, since we cannot easily * Mark empty arrays as non-constant, since we cannot easily
* determine their type. * determine their type.
*/ */
handler.setListFlag(literal, PNX_NONCONST); handler.setListFlag(literal, PNX_NONCONST);
} else if (tt == TOK_FOR) { } else if (tokenStream.matchToken(TOK_FOR, TokenStream::Operand)) {
// ES6 array comprehension. // ES6 array comprehension.
return arrayComprehension(begin); return arrayComprehension(begin);
} else { } else {
tokenStream.ungetToken();
bool spread = false, missingTrailingComma = false; bool spread = false, missingTrailingComma = false;
uint32_t index = 0; uint32_t index = 0;
for (; ; index++) { for (; ; index++) {
@ -7572,10 +7432,7 @@ Parser<ParseHandler>::arrayInitializer()
if (tt != TOK_COMMA) { if (tt != TOK_COMMA) {
/* If we didn't already match TOK_COMMA in above case. */ /* If we didn't already match TOK_COMMA in above case. */
bool matched; if (!tokenStream.matchToken(TOK_COMMA)) {
if (!tokenStream.matchToken(&matched, TOK_COMMA))
return null();
if (!matched) {
missingTrailingComma = true; missingTrailingComma = true;
break; break;
} }
@ -7628,13 +7485,8 @@ Parser<ParseHandler>::arrayInitializer()
* the example above, is done by <i * j>; JSOP_ARRAYPUSH <array>, where * the example above, is done by <i * j>; JSOP_ARRAYPUSH <array>, where
* <array> is the index of array's stack slot. * <array> is the index of array's stack slot.
*/ */
if (index == 0 && !spread) { if (index == 0 && !spread && tokenStream.matchToken(TOK_FOR) && missingTrailingComma)
bool matched; return legacyArrayComprehension(literal);
if (!tokenStream.matchToken(&matched, TOK_FOR))
return null();
if (matched && missingTrailingComma)
return legacyArrayComprehension(literal);
}
MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_LIST); MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_LIST);
} }
@ -8051,10 +7903,7 @@ Parser<ParseHandler>::parenExprOrGeneratorComprehension()
uint32_t begin = pos().begin; uint32_t begin = pos().begin;
uint32_t startYieldOffset = pc->lastYieldOffset; uint32_t startYieldOffset = pc->lastYieldOffset;
bool matched; if (tokenStream.matchToken(TOK_FOR, TokenStream::Operand))
if (!tokenStream.matchToken(&matched, TOK_FOR, TokenStream::Operand))
return null();
if (matched)
return generatorComprehension(begin); return generatorComprehension(begin);
/* /*
@ -8071,9 +7920,7 @@ Parser<ParseHandler>::parenExprOrGeneratorComprehension()
return null(); return null();
#if JS_HAS_GENERATOR_EXPRS #if JS_HAS_GENERATOR_EXPRS
if (!tokenStream.matchToken(&matched, TOK_FOR)) if (tokenStream.matchToken(TOK_FOR)) {
return null();
if (matched) {
if (pc->lastYieldOffset != startYieldOffset) { if (pc->lastYieldOffset != startYieldOffset) {
reportWithOffset(ParseError, false, pc->lastYieldOffset, reportWithOffset(ParseError, false, pc->lastYieldOffset,
JSMSG_BAD_GENEXP_BODY, js_yield_str); JSMSG_BAD_GENEXP_BODY, js_yield_str);
@ -8149,10 +7996,7 @@ Parser<ParseHandler>::exprInParens()
return null(); return null();
#if JS_HAS_GENERATOR_EXPRS #if JS_HAS_GENERATOR_EXPRS
bool matched; if (tokenStream.matchToken(TOK_FOR)) {
if (!tokenStream.matchToken(&matched, TOK_FOR))
return null();
if (matched) {
if (pc->lastYieldOffset != startYieldOffset) { if (pc->lastYieldOffset != startYieldOffset) {
reportWithOffset(ParseError, false, pc->lastYieldOffset, reportWithOffset(ParseError, false, pc->lastYieldOffset,
JSMSG_BAD_GENEXP_BODY, js_yield_str); JSMSG_BAD_GENEXP_BODY, js_yield_str);

Просмотреть файл

@ -622,7 +622,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
}; };
bool checkAndMarkAsAssignmentLhs(Node pn, AssignmentFlavor flavor); bool checkAndMarkAsAssignmentLhs(Node pn, AssignmentFlavor flavor);
bool matchInOrOf(bool *isForInp, bool *isForOfp); bool matchInOrOf(bool *isForOfp);
bool checkFunctionArguments(); bool checkFunctionArguments();
bool makeDefIntoUse(Definition *dn, Node pn, JSAtom *atom, bool *pbodyLevelHoistedUse); bool makeDefIntoUse(Definition *dn, Node pn, JSAtom *atom, bool *pbodyLevelHoistedUse);

Просмотреть файл

@ -453,24 +453,21 @@ class MOZ_STACK_CLASS TokenStream
} }
// Get the next token from the stream if its kind is |tt|. // Get the next token from the stream if its kind is |tt|.
bool matchToken(bool *matchedp, TokenKind tt, Modifier modifier = None) { bool matchToken(TokenKind tt, Modifier modifier = None) {
TokenKind token; TokenKind token;
if (!getToken(&token, modifier)) if (!getToken(&token, modifier)) {
return false;
if (token == tt) {
*matchedp = true;
} else {
ungetToken(); ungetToken();
*matchedp = false; return false;
} }
return true; if (token == tt)
return true;
ungetToken();
return false;
} }
void consumeKnownToken(TokenKind tt) { void consumeKnownToken(TokenKind tt) {
bool matched;
MOZ_ASSERT(lookahead != 0); MOZ_ASSERT(lookahead != 0);
MOZ_ALWAYS_TRUE(matchToken(&matched, tt)); JS_ALWAYS_TRUE(matchToken(tt));
MOZ_ALWAYS_TRUE(matched);
} }
bool matchContextualKeyword(Handle<PropertyName*> keyword) { bool matchContextualKeyword(Handle<PropertyName*> keyword) {