Commit 707ed29a authored by dslomov@chromium.org's avatar dslomov@chromium.org

Revert "harmony-scoping: Allow 'const' iteration variables in strict mode."

This reverts commit r24834 for breaking debug tests.

TBR=bmeurer@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24839 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4ac3d140
...@@ -2156,7 +2156,6 @@ Block* Parser::ParseVariableDeclarations( ...@@ -2156,7 +2156,6 @@ Block* Parser::ParseVariableDeclarations(
Block* block = factory()->NewBlock(NULL, 1, true, pos); Block* block = factory()->NewBlock(NULL, 1, true, pos);
int nvars = 0; // the number of variables declared int nvars = 0; // the number of variables declared
const AstRawString* name = NULL; const AstRawString* name = NULL;
bool is_for_iteration_variable;
do { do {
if (fni_ != NULL) fni_->Enter(); if (fni_ != NULL) fni_->Enter();
...@@ -2180,13 +2179,6 @@ Block* Parser::ParseVariableDeclarations( ...@@ -2180,13 +2179,6 @@ Block* Parser::ParseVariableDeclarations(
// For let/const declarations in harmony mode, we can also immediately // For let/const declarations in harmony mode, we can also immediately
// pre-resolve the proxy because it resides in the same scope as the // pre-resolve the proxy because it resides in the same scope as the
// declaration. // declaration.
is_for_iteration_variable =
var_context == kForStatement &&
(peek() == Token::IN || PeekContextualKeyword(CStrVector("of")));
if (is_for_iteration_variable && mode == CONST) {
needs_init = false;
}
Interface* interface = Interface* interface =
is_const ? Interface::NewConst() : Interface::NewValue(); is_const ? Interface::NewConst() : Interface::NewValue();
VariableProxy* proxy = NewUnresolved(name, mode, interface); VariableProxy* proxy = NewUnresolved(name, mode, interface);
...@@ -2232,8 +2224,7 @@ Block* Parser::ParseVariableDeclarations( ...@@ -2232,8 +2224,7 @@ Block* Parser::ParseVariableDeclarations(
Expression* value = NULL; Expression* value = NULL;
int pos = -1; int pos = -1;
// Harmony consts have non-optional initializers. // Harmony consts have non-optional initializers.
if (peek() == Token::ASSIGN || if (peek() == Token::ASSIGN || mode == CONST) {
(mode == CONST && !is_for_iteration_variable)) {
Expect(Token::ASSIGN, CHECK_OK); Expect(Token::ASSIGN, CHECK_OK);
pos = position(); pos = position();
value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
...@@ -2366,7 +2357,7 @@ Block* Parser::ParseVariableDeclarations( ...@@ -2366,7 +2357,7 @@ Block* Parser::ParseVariableDeclarations(
// If there was a single non-const declaration, return it in the output // If there was a single non-const declaration, return it in the output
// parameter for possible use by for/in. // parameter for possible use by for/in.
if (nvars == 1 && (!is_const || is_for_iteration_variable)) { if (nvars == 1 && !is_const) {
*out = name; *out = name;
} }
...@@ -3103,8 +3094,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, ...@@ -3103,8 +3094,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
Expect(Token::LPAREN, CHECK_OK); Expect(Token::LPAREN, CHECK_OK);
for_scope->set_start_position(scanner()->location().beg_pos); for_scope->set_start_position(scanner()->location().beg_pos);
if (peek() != Token::SEMICOLON) { if (peek() != Token::SEMICOLON) {
if (peek() == Token::VAR || if (peek() == Token::VAR || peek() == Token::CONST) {
(peek() == Token::CONST && strict_mode() == SLOPPY)) {
bool is_const = peek() == Token::CONST; bool is_const = peek() == Token::CONST;
const AstRawString* name = NULL; const AstRawString* name = NULL;
VariableDeclarationProperties decl_props = kHasNoInitializers; VariableDeclarationProperties decl_props = kHasNoInitializers;
...@@ -3141,10 +3131,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, ...@@ -3141,10 +3131,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
} else { } else {
init = variable_statement; init = variable_statement;
} }
} else if ((peek() == Token::LET || peek() == Token::CONST) && } else if (peek() == Token::LET && strict_mode() == STRICT) {
strict_mode() == STRICT) {
DCHECK(allow_harmony_scoping()); DCHECK(allow_harmony_scoping());
bool is_const = peek() == Token::CONST;
const AstRawString* name = NULL; const AstRawString* name = NULL;
VariableDeclarationProperties decl_props = kHasNoInitializers; VariableDeclarationProperties decl_props = kHasNoInitializers;
Block* variable_statement = Block* variable_statement =
...@@ -3157,13 +3145,13 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, ...@@ -3157,13 +3145,13 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
if (accept_IN && CheckInOrOf(accept_OF, &mode)) { if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
// Rewrite a for-in statement of the form // Rewrite a for-in statement of the form
// //
// for (let/const x in e) b // for (let x in e) b
// //
// into // into
// //
// <let x' be a temporary variable> // <let x' be a temporary variable>
// for (x' in e) { // for (x' in e) {
// let/const x; // let x;
// x = x'; // x = x';
// b; // b;
// } // }
...@@ -3183,13 +3171,13 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, ...@@ -3183,13 +3171,13 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
scope_ = for_scope; scope_ = for_scope;
Expect(Token::RPAREN, CHECK_OK); Expect(Token::RPAREN, CHECK_OK);
VariableProxy* each = scope_->NewUnresolved(factory(), name); VariableProxy* each =
scope_->NewUnresolved(factory(), name, Interface::NewValue());
Statement* body = ParseStatement(NULL, CHECK_OK); Statement* body = ParseStatement(NULL, CHECK_OK);
Block* body_block = Block* body_block =
factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN;
Assignment* assignment = factory()->NewAssignment( Assignment* assignment = factory()->NewAssignment(
init_op, each, temp_proxy, RelocInfo::kNoPosition); Token::ASSIGN, each, temp_proxy, RelocInfo::kNoPosition);
Statement* assignment_statement = factory()->NewExpressionStatement( Statement* assignment_statement = factory()->NewExpressionStatement(
assignment, RelocInfo::kNoPosition); assignment, RelocInfo::kNoPosition);
body_block->AddStatement(variable_statement, zone()); body_block->AddStatement(variable_statement, zone());
......
...@@ -409,7 +409,6 @@ PreParser::Statement PreParser::ParseVariableDeclarations( ...@@ -409,7 +409,6 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
// ConstBinding :: // ConstBinding ::
// BindingPattern '=' AssignmentExpression // BindingPattern '=' AssignmentExpression
bool require_initializer = false; bool require_initializer = false;
bool is_strict_const = false;
if (peek() == Token::VAR) { if (peek() == Token::VAR) {
Consume(Token::VAR); Consume(Token::VAR);
} else if (peek() == Token::CONST) { } else if (peek() == Token::CONST) {
...@@ -431,8 +430,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations( ...@@ -431,8 +430,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
*ok = false; *ok = false;
return Statement::Default(); return Statement::Default();
} }
is_strict_const = true; require_initializer = true;
require_initializer = var_context != kForStatement;
} else { } else {
Scanner::Location location = scanner()->peek_location(); Scanner::Location location = scanner()->peek_location();
ReportMessageAt(location, "strict_const"); ReportMessageAt(location, "strict_const");
...@@ -462,9 +460,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations( ...@@ -462,9 +460,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
if (nvars > 0) Consume(Token::COMMA); if (nvars > 0) Consume(Token::COMMA);
ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
nvars++; nvars++;
if (peek() == Token::ASSIGN || require_initializer || if (peek() == Token::ASSIGN || require_initializer) {
// require initializers for multiple consts.
(is_strict_const && peek() == Token::COMMA)) {
Expect(Token::ASSIGN, CHECK_OK); Expect(Token::ASSIGN, CHECK_OK);
ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
if (decl_props != NULL) *decl_props = kHasInitializers; if (decl_props != NULL) *decl_props = kHasInitializers;
...@@ -682,14 +678,13 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) { ...@@ -682,14 +678,13 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) {
if (peek() != Token::SEMICOLON) { if (peek() != Token::SEMICOLON) {
if (peek() == Token::VAR || peek() == Token::CONST || if (peek() == Token::VAR || peek() == Token::CONST ||
(peek() == Token::LET && strict_mode() == STRICT)) { (peek() == Token::LET && strict_mode() == STRICT)) {
bool is_lexical = peek() == Token::LET || bool is_let = peek() == Token::LET;
(peek() == Token::CONST && strict_mode() == STRICT);
int decl_count; int decl_count;
VariableDeclarationProperties decl_props = kHasNoInitializers; VariableDeclarationProperties decl_props = kHasNoInitializers;
ParseVariableDeclarations( ParseVariableDeclarations(
kForStatement, &decl_props, &decl_count, CHECK_OK); kForStatement, &decl_props, &decl_count, CHECK_OK);
bool has_initializers = decl_props == kHasInitializers; bool has_initializers = decl_props == kHasInitializers;
bool accept_IN = decl_count == 1 && !(is_lexical && has_initializers); bool accept_IN = decl_count == 1 && !(is_let && has_initializers);
bool accept_OF = !has_initializers; bool accept_OF = !has_initializers;
if (accept_IN && CheckInOrOf(accept_OF)) { if (accept_IN && CheckInOrOf(accept_OF)) {
ParseExpression(true, CHECK_OK); ParseExpression(true, CHECK_OK);
......
...@@ -344,18 +344,14 @@ class ParserBase : public Traits { ...@@ -344,18 +344,14 @@ class ParserBase : public Traits {
} }
bool CheckContextualKeyword(Vector<const char> keyword) { bool CheckContextualKeyword(Vector<const char> keyword) {
if (PeekContextualKeyword(keyword)) { if (peek() == Token::IDENTIFIER &&
scanner()->is_next_contextual_keyword(keyword)) {
Consume(Token::IDENTIFIER); Consume(Token::IDENTIFIER);
return true; return true;
} }
return false; return false;
} }
bool PeekContextualKeyword(Vector<const char> keyword) {
return peek() == Token::IDENTIFIER &&
scanner()->is_next_contextual_keyword(keyword);
}
void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) { void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
Expect(Token::IDENTIFIER, ok); Expect(Token::IDENTIFIER, ok);
if (!*ok) return; if (!*ok) return;
......
...@@ -4205,42 +4205,3 @@ TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) { ...@@ -4205,42 +4205,3 @@ TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) {
RunParserSyncTest(context_data, name_data, kError, NULL, 0, RunParserSyncTest(context_data, name_data, kError, NULL, 0,
always_flags, arraysize(always_flags)); always_flags, arraysize(always_flags));
} }
TEST(ConstParsingInForIn) {
const char* context_data[][2] = {{"'use strict';", ""},
{"function foo(){ 'use strict';", "}"},
{NULL, NULL}};
const char* data[] = {
"for(const x = 1; ; ) {}",
"for(const x = 1, y = 2;;){}",
"for(const x in [1,2,3]) {}",
"for(const x of [1,2,3]) {}",
NULL};
static const ParserFlag always_flags[] = {kAllowHarmonyScoping};
RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
arraysize(always_flags));
}
TEST(ConstParsingInForInError) {
const char* context_data[][2] = {{"'use strict';", ""},
{"function foo(){ 'use strict';", "}"},
{NULL, NULL}};
const char* data[] = {
"for(const x,y = 1; ; ) {}",
"for(const x = 4 in [1,2,3]) {}",
"for(const x = 4, y in [1,2,3]) {}",
"for(const x = 4 of [1,2,3]) {}",
"for(const x = 4, y of [1,2,3]) {}",
"for(const x = 1, y = 2 in []) {}",
"for(const x,y in []) {}",
"for(const x = 1, y = 2 of []) {}",
"for(const x,y of []) {}",
NULL};
static const ParserFlag always_flags[] = {kAllowHarmonyScoping};
RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
arraysize(always_flags));
}
// Copyright 2014 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.
//
// Flags: --harmony-scoping
'use strict';
// Top-level code
let s = 0;
let f = [undefined, undefined, undefined]
for (const x of [1,2,3]) {
s += x;
f[x-1] = function() { return x; }
}
assertEquals(6, s);
assertEquals(1, f[0]());
assertEquals(2, f[1]());
assertEquals(3, f[2]());
let x = 1;
s = 0;
for (const x of [x, x+1, x+2]) {
s += x;
}
assertEquals(6, s);
s = 0;
var q = 1;
for (const q of [q, q+1, q+2]) {
s += q;
}
assertEquals(6, s);
let z = 1;
s = 0;
for (const x = 1; z < 2; z++) {
s += x + z;
}
assertEquals(2, s);
s = "";
for (const x in [1,2,3]) {
s += x;
}
assertEquals("012", s);
assertThrows(function() { for(const x in [1,2,3]) { x++ } }, SyntaxError);
// Function scope
(function() {
let s = 0;
for (const x of [1,2,3]) {
s += x;
}
assertEquals(6, s);
let x = 1;
s = 0;
for (const x of [x, x+1, x+2]) {
s += x;
}
assertEquals(6, s);
s = 0;
var q = 1;
for (const q of [q, q+1, q+2]) {
s += q;
}
assertEquals(6, s);
s = "";
for (const x in [1,2,3]) {
s += x;
}
assertEquals("012", s);
}());
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