mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-31 11:51:17 +00:00
Remove support for non-standard let expressions, part 1: code.
Tag #773.
This commit is contained in:
+30
-108
@@ -2924,7 +2924,7 @@ Parser<ParseHandler>::reportRedeclaration(Node pn, Definition::Kind redeclKind,
|
||||
}
|
||||
|
||||
/*
|
||||
* Define a lexical binding in a block, let-expression, or comprehension scope. pc
|
||||
* Define a lexical binding in a block or comprehension scope. pc
|
||||
* must already be in such a scope.
|
||||
*
|
||||
* Throw a SyntaxError if 'atom' is an invalid name. Otherwise create a
|
||||
@@ -3613,13 +3613,13 @@ Parser<SyntaxParseHandler>::pushLetScope(HandleStaticBlockObject blockObj, StmtI
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a let block statement or let expression (determined by 'letContext').
|
||||
* Parse a let block statement.
|
||||
* In both cases, bindings are not hoisted to the top of the enclosing block
|
||||
* and thus must be carefully injected between variables() and the let body.
|
||||
*/
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::deprecatedLetBlockOrExpression(LetContext letContext)
|
||||
Parser<ParseHandler>::deprecatedLetBlock()
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LET));
|
||||
|
||||
@@ -3642,82 +3642,22 @@ Parser<ParseHandler>::deprecatedLetBlockOrExpression(LetContext letContext)
|
||||
if (!block)
|
||||
return null();
|
||||
|
||||
bool needExprStmt = false;
|
||||
if (letContext == LetStatement) {
|
||||
bool matched;
|
||||
if (!tokenStream.matchToken(&matched, TOK_LC, TokenStream::Operand))
|
||||
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 (!reportWithOffset(ParseStrictError, pc->sc->strict, begin,
|
||||
JSMSG_STRICT_CODE_LET_EXPR_STMT))
|
||||
{
|
||||
return null();
|
||||
}
|
||||
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_LET);
|
||||
|
||||
Node expr = statements(yieldHandling);
|
||||
if (!expr)
|
||||
return null();
|
||||
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_LET);
|
||||
|
||||
addTelemetry(JSCompartment::DeprecatedLetBlock);
|
||||
if (!report(ParseWarning, pc->sc->strict(), expr, JSMSG_DEPRECATED_LET_BLOCK))
|
||||
return null();
|
||||
|
||||
/*
|
||||
* If this is really an expression in let statement guise, then we
|
||||
* need to wrap the PNK_LETEXPR node in a PNK_SEMI node so that we
|
||||
* pop the return value of the expression.
|
||||
*/
|
||||
needExprStmt = true;
|
||||
letContext = LetExpression;
|
||||
}
|
||||
}
|
||||
|
||||
Node expr;
|
||||
if (letContext == LetStatement) {
|
||||
expr = statements();
|
||||
if (!expr)
|
||||
return null();
|
||||
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_LET);
|
||||
|
||||
addTelemetry(JSCompartment::DeprecatedLetBlock);
|
||||
if (!report(ParseWarning, pc->sc->strict, expr, JSMSG_DEPRECATED_LET_BLOCK))
|
||||
return null();
|
||||
} else {
|
||||
MOZ_ASSERT(letContext == LetExpression);
|
||||
expr = assignExpr();
|
||||
if (!expr)
|
||||
return null();
|
||||
|
||||
addTelemetry(JSCompartment::DeprecatedLetExpression);
|
||||
if (!report(ParseWarning, pc->sc->strict, expr, JSMSG_DEPRECATED_LET_EXPRESSION))
|
||||
return null();
|
||||
}
|
||||
handler.setLexicalScopeBody(block, expr);
|
||||
PopStatementPC(tokenStream, pc);
|
||||
|
||||
TokenPos letPos(begin, pos().end);
|
||||
|
||||
if (letContext == LetExpression) {
|
||||
if (needExprStmt) {
|
||||
if (!MatchOrInsertSemicolon(tokenStream))
|
||||
return null();
|
||||
}
|
||||
|
||||
Node letExpr = handler.newLetExpression(vars, block, letPos);
|
||||
if (!letExpr)
|
||||
return null();
|
||||
|
||||
return needExprStmt ? handler.newExprStatement(letExpr, pos().end) : letExpr;
|
||||
}
|
||||
|
||||
return handler.newLetBlock(vars, block, letPos);
|
||||
}
|
||||
|
||||
@@ -4101,23 +4041,17 @@ Parser<FullParseHandler>::letDeclarationOrBlock()
|
||||
{
|
||||
handler.disableSyntaxParser();
|
||||
|
||||
/* Check for a let statement or let expression. */
|
||||
/* Check for a let statement. */
|
||||
TokenKind tt;
|
||||
if (!tokenStream.peekToken(&tt))
|
||||
return null();
|
||||
if (tt == TOK_LP) {
|
||||
ParseNode* node = deprecatedLetBlockOrExpression(LetStatement);
|
||||
ParseNode* node = deprecatedLetBlock();
|
||||
if (!node)
|
||||
return nullptr;
|
||||
|
||||
if (node->isKind(PNK_LETBLOCK)) {
|
||||
MOZ_ASSERT(node->isArity(PN_BINARY));
|
||||
} else {
|
||||
MOZ_ASSERT(node->isKind(PNK_SEMI));
|
||||
MOZ_ASSERT(node->pn_kid->isKind(PNK_LETEXPR));
|
||||
MOZ_ASSERT(node->pn_kid->isArity(PN_BINARY));
|
||||
}
|
||||
|
||||
MOZ_ASSERT(node->isKind(PNK_LETBLOCK));
|
||||
MOZ_ASSERT(node->isArity(PN_BINARY));
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -4629,8 +4563,7 @@ Parser<FullParseHandler>::forStatement()
|
||||
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
|
||||
|
||||
/*
|
||||
* True if we have 'for (var/let/const ...)', except in the oddball case
|
||||
* where 'let' begins a let-expression in 'for (let (...) ...)'.
|
||||
* True if we have 'for (var/let/const ...)'.
|
||||
*/
|
||||
bool isForDecl = false;
|
||||
|
||||
@@ -4669,18 +4602,12 @@ Parser<FullParseHandler>::forStatement()
|
||||
handler.disableSyntaxParser();
|
||||
bool constDecl = tt == TOK_CONST;
|
||||
tokenStream.consumeKnownToken(tt);
|
||||
if (!tokenStream.peekToken(&tt))
|
||||
isForDecl = true;
|
||||
blockObj = StaticBlockObject::create(context);
|
||||
if (!blockObj)
|
||||
return null();
|
||||
if (tt == TOK_LP) {
|
||||
pn1 = deprecatedLetBlockOrExpression(LetExpression);
|
||||
} else {
|
||||
isForDecl = true;
|
||||
blockObj = StaticBlockObject::create(context);
|
||||
if (!blockObj)
|
||||
return null();
|
||||
pn1 = variables(constDecl ? PNK_CONST : PNK_LET, nullptr, blockObj,
|
||||
DontHoistVars);
|
||||
}
|
||||
pn1 = variables(constDecl ? PNK_CONST : PNK_LET, nullptr, blockObj,
|
||||
DontHoistVars);
|
||||
} else {
|
||||
pn1 = expr();
|
||||
}
|
||||
@@ -6695,9 +6622,7 @@ LegacyCompExprTransplanter::transplant(ParseNode* pn)
|
||||
// The one remaining thing to patch up is the block scope depth. We need to
|
||||
// compute the maximum block scope depth of a function, so we know how much
|
||||
// space to reserve in the fixed part of a stack frame. Normally this is done
|
||||
// whenever we leave a statement, via AccumulateBlockScopeDepth. However if the
|
||||
// head has a let expression, we need to re-assign that depth to the tail of the
|
||||
// comprehension.
|
||||
// whenever we leave a statement, via AccumulateBlockScopeDepth.
|
||||
//
|
||||
// Thing is, we don't actually know what that depth is, because the only
|
||||
// information we keep is the maximum nested depth within a statement, so we
|
||||
@@ -6768,10 +6693,9 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode* bodyExpr, unsigned
|
||||
* the comprehension's block scope. We allocate that id or one above it
|
||||
* here, by calling PushLexicalScope.
|
||||
*
|
||||
* In the case of a comprehension expression that has nested blocks
|
||||
* (e.g., let expressions), we will allocate a higher blockid but then
|
||||
* slide all blocks "to the right" to make room for the comprehension's
|
||||
* block scope.
|
||||
* In the case of a comprehension expression that has nested blocks,
|
||||
* we will allocate a higher blockid but then slide all blocks "to the
|
||||
* right" to make room for the comprehension's block scope.
|
||||
*/
|
||||
adjust = pc->blockid();
|
||||
pn = pushLexicalScope(&stmtInfo);
|
||||
@@ -7804,9 +7728,10 @@ Parser<ParseHandler>::arrayInitializer()
|
||||
*
|
||||
* [i * j for (i in o) for (j in p) if (i != j)]
|
||||
*
|
||||
* translates to roughly the following let expression:
|
||||
* translates to roughly the following code:
|
||||
*
|
||||
* let (array = new Array, i, j) {
|
||||
* {
|
||||
* let array = new Array, i, j;
|
||||
* for (i in o) let {
|
||||
* for (j in p)
|
||||
* if (i != j)
|
||||
@@ -8152,9 +8077,6 @@ Parser<ParseHandler>::primaryExpr(TokenKind tt, InvokedPrediction invoked)
|
||||
case TOK_LC:
|
||||
return objectLiteral();
|
||||
|
||||
case TOK_LET:
|
||||
return deprecatedLetBlockOrExpression(LetExpression);
|
||||
|
||||
case TOK_LP: {
|
||||
TokenKind next;
|
||||
if (!tokenStream.peekToken(&next, TokenStream::Operand))
|
||||
|
||||
Reference in New Issue
Block a user