Skip to content

Commit

Permalink
Allow 'in' to terminate expressions in the control
Browse files Browse the repository at this point in the history
of a for...in loop fixes #5203.
  • Loading branch information
rhuanjl committed May 23, 2018
1 parent 249b4af commit f095914
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 5 deletions.
9 changes: 5 additions & 4 deletions lib/Parser/Parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8337,7 +8337,7 @@ void Parser::DeferOrEmitPotentialSpreadError(ParseNodePtr pnodeT)
}
}

bool Parser::IsTerminateToken()
bool Parser::IsTerminateToken(bool inTerminate)
{
return (m_token.tk == tkRCurly ||
m_token.tk == tkRBrack ||
Expand All @@ -8346,6 +8346,7 @@ bool Parser::IsTerminateToken()
m_token.tk == tkColon ||
m_token.tk == tkComma ||
m_token.tk == tkLimKwd ||
(m_token.tk == tkIN && inTerminate) ||
this->GetScanner()->FHadNewLine());
}

Expand All @@ -8358,7 +8359,7 @@ template<bool buildAST>
bool Parser::ParseOptionalExpr(ParseNodePtr* pnode, bool fUnaryOrParen, int oplMin, BOOL *pfCanAssign, BOOL fAllowIn, BOOL fAllowEllipsis, _Inout_opt_ IdentToken* pToken)
{
*pnode = nullptr;
if (IsTerminateToken())
if (IsTerminateToken(!fAllowIn))
{
return false;
}
Expand Down Expand Up @@ -8489,7 +8490,7 @@ ParseNodePtr Parser::ParseExpr(int oplMin,

if (nop == knopYield)
{
if (!ParseOptionalExpr<buildAST>(&pnodeT, false, opl, NULL, TRUE, fAllowEllipsis))
if (!ParseOptionalExpr<buildAST>(&pnodeT, false, opl, NULL, fAllowIn, fAllowEllipsis))
{
nop = knopYieldLeaf;
if (buildAST)
Expand Down Expand Up @@ -8839,7 +8840,7 @@ ParseNodePtr Parser::ParseExpr(int oplMin,
// ArrowFunction/AsyncArrowFunction is part of AssignmentExpression, which should terminate the expression unless followed by a comma
if (m_token.tk != tkComma)
{
if (!(IsTerminateToken()))
if (!(IsTerminateToken(!fAllowIn)))
{
Error(ERRnoSemic);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Parser/Parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,7 @@ class Parser
template<bool buildAST> ParseNodePtr ParseMemberList(LPCOLESTR pNameHint, uint32 *pHintLength, tokens declarationType = tkNone);
template<bool buildAST> IdentPtr ParseSuper(bool fAllowCall);

bool IsTerminateToken();
bool IsTerminateToken(bool inTerminate);

// Used to determine the type of JavaScript object member.
// The values can be combined using bitwise OR.
Expand Down
8 changes: 8 additions & 0 deletions test/es6/generators-syntax.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@ var tests = [
assert.throws(function () { eval("function *gf() { (a = (yield) => {}) => {}; }"); }, SyntaxError, "yield expression is disallowed within arrow function default parameter expression in nested case too", "The use of a keyword for an identifier is invalid");
}
},
{
name : "yield is allowed before 'in' in a for loop control but not elsewhere bug issue #5203",
body : function () {
assert.doesNotThrow(function () { eval("function* gf() {for(var a = yield in {});}"); }, "Yield is allowed before 'in' in a for loop");
assert.throws(function () { eval("function* gf() {var a = yield in {};}"); }, SyntaxError, "Yield is not allowed before 'in' when not declaring a loop");
assert.throws(function () { eval("function* gf() {yield in {};}"); }, SyntaxError, "Yield is not allowed before 'in' when not declaring a loop");
}
}
];

testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });
3 changes: 3 additions & 0 deletions test/es6/lambda-expr.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ catch (e)
{
print(e.message);
}

// Legal case, lambda in object inside for()
for (var i = () => {} in {});

0 comments on commit f095914

Please sign in to comment.