зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset f023c533e279 (bug 1066827)
This commit is contained in:
Родитель
2fd965d25b
Коммит
9d4fce3e37
|
@ -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) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче