Report some errors about invalid left-hand-sides in for-in/of loop heads

using code with an explicitly computed offset.
This commit is contained in:
wolfbeast 2019-04-06 10:41:42 +02:00 committed by Roy Tam
commit 71dc0dd5c0
2 changed files with 26 additions and 38 deletions

View file

@ -5415,37 +5415,6 @@ Parser<ParseHandler>::matchInOrOf(bool* isForInp, bool* isForOfp)
return true;
}
template <class ParseHandler>
bool
Parser<ParseHandler>::validateForInOrOfLHSExpression(Node target, PossibleError* possibleError)
{
if (handler.isUnparenthesizedDestructuringPattern(target))
return checkDestructuringPattern(target, Nothing(), possibleError);
// All other permitted targets are simple.
if (!reportIfNotValidSimpleAssignmentTarget(target, ForInOrOfTarget))
return false;
if (handler.isPropertyAccess(target))
return true;
if (handler.isNameAnyParentheses(target)) {
// The arguments/eval identifiers are simple in non-strict mode code,
// but warn to discourage use nonetheless.
if (!reportIfArgumentsEvalTarget(target))
return false;
handler.adjustGetToSet(target);
return true;
}
if (handler.isFunctionCall(target))
return checkAssignmentToCall(target, JSMSG_BAD_FOR_LEFTSIDE);
reportWithNode(ParseError, false, target, JSMSG_BAD_FOR_LEFTSIDE);
return false;
}
template <class ParseHandler>
bool
Parser<ParseHandler>::forHeadStart(YieldHandling yieldHandling,
@ -5526,6 +5495,10 @@ Parser<ParseHandler>::forHeadStart(YieldHandling yieldHandling,
return *forInitialPart != null();
}
uint32_t exprOffset;
if (!tokenStream.peekOffset(&exprOffset, TokenStream::Operand))
return false;
// Finally, handle for-loops that start with expressions. Pass
// |InProhibited| so that |in| isn't parsed in a RelationalExpression as a
// binary operator. |in| makes it a for-in loop, *not* an |in| expression.
@ -5569,8 +5542,29 @@ Parser<ParseHandler>::forHeadStart(YieldHandling yieldHandling,
*forHeadKind = isForIn ? PNK_FORIN : PNK_FOROF;
if (!validateForInOrOfLHSExpression(*forInitialPart, &possibleError))
// Verify the left-hand side expression doesn't have a forbidden form.
if (handler.isUnparenthesizedDestructuringPattern(*forInitialPart)) {
if (!checkDestructuringPattern(*forInitialPart, Nothing(), &possibleError))
return false;
} else if (handler.isNameAnyParentheses(*forInitialPart)) {
const char* chars = handler.nameIsArgumentsEvalAnyParentheses(*forInitialPart, context);
if (chars) {
// |chars| is "arguments" or "eval" here.
if (!strictModeErrorAt(exprOffset, JSMSG_BAD_STRICT_ASSIGN, chars))
return false;
}
handler.adjustGetToSet(*forInitialPart);
} else if (handler.isPropertyAccess(*forInitialPart)) {
// Permitted: no additional testing/fixup needed.
} else if (handler.isFunctionCall(*forInitialPart)) {
if (!strictModeErrorAt(exprOffset, JSMSG_BAD_FOR_LEFTSIDE))
return false;
} else {
errorAt(exprOffset, JSMSG_BAD_FOR_LEFTSIDE);
return false;
}
if (!possibleError.checkForExpressionError())
return false;
@ -7869,10 +7863,6 @@ Parser<ParseHandler>::reportIfNotValidSimpleAssignmentTarget(Node target, Assign
case CompoundAssignment:
errnum = JSMSG_BAD_LEFTSIDE_OF_ASS;
break;
case ForInOrOfTarget:
errnum = JSMSG_BAD_FOR_LEFTSIDE;
break;
}
reportWithNode(ParseError, pc->sc()->strict(), target, errnum, extra);