Commit 096125de authored by caitpotter88's avatar caitpotter88 Committed by Commit bot

[es6] allow any LeftHandSideExpression in for-of loops

Fix an earlier regression which forbid non-VariableProxy LHS from being
used in for-of loops. Like for-in loops, the spec allows any LHS to be used,
with the sole exception that ObjectLiterals and ArrayLiterals must be valid
AssignmentPatterns.

Also fixes a bug in TurboFan which resulted in incorrectly replacing a variable load with a constant value in some instances, due to the AstLoopAssignmentAnalyzer failing to record the assignment to ForOfStatement's value.

BUG=v8:4418, v8:2720
LOG=N
R=wingo@igalia.com, littledan@chromium.org, adamk@chromium.org, bmeurer@chromium.org

Review URL: https://codereview.chromium.org/1411873004

Cr-Commit-Position: refs/heads/master@{#31816}
parent 8c1a4330
......@@ -261,7 +261,9 @@ void ALAA::VisitForInStatement(ForInStatement* loop) {
void ALAA::VisitForOfStatement(ForOfStatement* loop) {
Visit(loop->assign_iterator());
Enter(loop);
Visit(loop->assign_each());
Visit(loop->each());
Visit(loop->subject());
Visit(loop->body());
......
......@@ -3635,12 +3635,11 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
int num_decl = parsing_result.declarations.length();
bool accept_IN = num_decl >= 1;
bool accept_OF = true;
ForEachStatement::VisitMode mode;
int each_beg_pos = scanner()->location().beg_pos;
int each_end_pos = scanner()->location().end_pos;
if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) {
if (accept_IN && CheckInOrOf(&mode, ok)) {
if (!*ok) return nullptr;
if (num_decl != 1) {
const char* loop_type =
......@@ -3798,13 +3797,12 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
Expression* expression = ParseExpression(false, CHECK_OK);
int lhs_end_pos = scanner()->location().end_pos;
ForEachStatement::VisitMode mode;
bool accept_OF = expression->IsVariableProxy();
is_let_identifier_expression =
expression->IsVariableProxy() &&
expression->AsVariableProxy()->raw_name() ==
ast_value_factory()->let_string();
if (CheckInOrOf(accept_OF, &mode, ok)) {
if (CheckInOrOf(&mode, ok)) {
if (!*ok) return nullptr;
expression = this->CheckAndRewriteReferenceExpression(
expression, lhs_beg_pos, lhs_end_pos,
......
......@@ -925,8 +925,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) {
&first_initializer_loc, &bindings_loc,
CHECK_OK);
bool accept_IN = decl_count >= 1;
bool accept_OF = true;
if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) {
if (accept_IN && CheckInOrOf(&mode, ok)) {
if (!*ok) return Statement::Default();
if (decl_count != 1) {
const char* loop_type =
......@@ -961,7 +960,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) {
int lhs_end_pos = scanner()->location().end_pos;
is_let_identifier_expression =
lhs.IsIdentifier() && lhs.AsIdentifier().IsLet();
if (CheckInOrOf(lhs.IsIdentifier(), &mode, ok)) {
if (CheckInOrOf(&mode, ok)) {
if (!*ok) return Statement::Default();
lhs = CheckAndRewriteReferenceExpression(
lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
......
......@@ -421,8 +421,7 @@ class ParserBase : public Traits {
}
}
bool CheckInOrOf(
bool accept_OF, ForEachStatement::VisitMode* visit_mode, bool* ok) {
bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode, bool* ok) {
if (Check(Token::IN)) {
if (is_strong(language_mode())) {
ReportMessageAt(scanner()->location(), MessageTemplate::kStrongForIn);
......@@ -431,7 +430,7 @@ class ParserBase : public Traits {
*visit_mode = ForEachStatement::ENUMERATE;
}
return true;
} else if (accept_OF && CheckContextualKeyword(CStrVector("of"))) {
} else if (CheckContextualKeyword(CStrVector("of"))) {
*visit_mode = ForEachStatement::ITERATE;
return true;
}
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function TestForOfName() {
var result = 0;
var index;
for (index of [1, 2, 3, 4, 5]) result += index;
assertEquals(result, 15);
assertEquals(index, 5);
})();
(function TestForOfProperty() {
var O = {};
var result = 0;
for (O.index of [1, 2, 3, 4, 5]) result += O.index;
assertEquals(result, 15);
assertEquals(O.index, 5);
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment