Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index 32f73cf4f75bca9c810ccda4c2ac457da4958fea..e868d7fe1bfc84a42bca8b1780d0d7f9d04f705f 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -706,7 +706,9 @@ Literal* ParserTraits::ExpressionFromLiteral(Token::Value token, int pos, |
Expression* ParserTraits::ExpressionFromIdentifier(const AstRawString* name, |
- int pos, Scope* scope, |
+ int start_position, |
+ int end_position, |
+ Scope* scope, |
AstNodeFactory* factory) { |
if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name); |
@@ -715,8 +717,10 @@ Expression* ParserTraits::ExpressionFromIdentifier(const AstRawString* name, |
// for Traits::DeclareArrowParametersFromExpression() to be able to |
// pick the names of the parameters. |
return parser_->parsing_lazy_arrow_parameters_ |
- ? factory->NewVariableProxy(name, false, pos) |
- : scope->NewUnresolved(factory, name, pos); |
+ ? factory->NewVariableProxy(name, false, start_position, |
+ end_position) |
+ : scope->NewUnresolved(factory, name, start_position, |
+ end_position); |
} |
@@ -1771,11 +1775,13 @@ VariableProxy* Parser::NewUnresolved(const AstRawString* name, |
// scope. |
// Let/const variables in harmony mode are always added to the immediately |
// enclosing scope. |
- return DeclarationScope(mode)->NewUnresolved(factory(), name, position()); |
+ return DeclarationScope(mode)->NewUnresolved(factory(), name, |
+ scanner()->location().beg_pos, |
+ scanner()->location().end_pos); |
} |
-void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { |
+Variable* Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { |
VariableProxy* proxy = declaration->proxy(); |
DCHECK(proxy->raw_name() != NULL); |
const AstRawString* name = proxy->raw_name(); |
@@ -1801,10 +1807,14 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { |
if (var == NULL) { |
// Declare the name. |
var = declaration_scope->DeclareLocal( |
- name, mode, declaration->initialization(), kNotAssigned); |
- } else if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(var->mode()) |
- || ((mode == CONST_LEGACY || var->mode() == CONST_LEGACY) && |
- !declaration_scope->is_script_scope())) { |
+ name, mode, declaration->initialization(), |
+ declaration->IsFunctionDeclaration() ? Variable::FUNCTION |
+ : Variable::NORMAL, |
+ kNotAssigned); |
+ } else if (IsLexicalVariableMode(mode) || |
+ IsLexicalVariableMode(var->mode()) || |
+ ((mode == CONST_LEGACY || var->mode() == CONST_LEGACY) && |
+ !declaration_scope->is_script_scope())) { |
// The name was declared in this scope before; check for conflicting |
// re-declarations. We have a conflict if either of the declarations is |
// not a var (in script scope, we also have to ignore legacy const for |
@@ -1824,7 +1834,7 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { |
// ES5 16 for a definition of early errors. |
ParserTraits::ReportMessage("var_redeclaration", name); |
*ok = false; |
- return; |
+ return nullptr; |
} |
Expression* expression = NewThrowTypeError( |
"var_redeclaration", name, declaration->position()); |
@@ -1898,6 +1908,7 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { |
if (resolve && var != NULL) { |
proxy->BindTo(var); |
} |
+ return var; |
} |
@@ -2018,7 +2029,7 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, |
Declaration* declaration = |
factory()->NewVariableDeclaration(proxy, mode, scope_, pos); |
Declare(declaration, true, CHECK_OK); |
- proxy->var()->set_initializer_position(pos); |
+ proxy->var()->set_initializer_position(position()); |
Token::Value init_op = |
is_strong(language_mode()) ? Token::INIT_CONST : Token::INIT_LET; |
@@ -2227,7 +2238,9 @@ Block* Parser::ParseVariableDeclarations( |
VariableProxy* proxy = NewUnresolved(name, mode); |
Declaration* declaration = |
factory()->NewVariableDeclaration(proxy, mode, scope_, pos); |
- Declare(declaration, mode != VAR, CHECK_OK); |
+ Variable* var = Declare(declaration, mode != VAR, CHECK_OK); |
+ DCHECK_NOT_NULL(var); |
+ DCHECK(!proxy->is_resolved() || proxy->var() == var); |
nvars++; |
if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) { |
ReportMessage("too_many_variables"); |
@@ -2281,11 +2294,11 @@ Block* Parser::ParseVariableDeclarations( |
fni_->RemoveLastFunction(); |
} |
if (decl_props != NULL) *decl_props = kHasInitializers; |
- } |
- |
- // Record the end position of the initializer. |
- if (proxy->is_resolved()) { |
- proxy->var()->set_initializer_position(position()); |
+ // End position of the initializer is after the assignment expression. |
+ var->set_initializer_position(scanner()->location().end_pos); |
+ } else { |
+ // End position of the initializer is after the variable. |
+ var->set_initializer_position(position()); |
} |
// Make sure that 'const x' and 'let x' initialize 'x' to undefined. |
@@ -2790,7 +2803,8 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { |
Expect(Token::RPAREN, CHECK_OK); |
- catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized); |
+ catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized, |
+ Variable::NORMAL); |
BlockState block_state(&scope_, catch_scope); |
catch_block = ParseBlock(NULL, CHECK_OK); |
@@ -3082,16 +3096,16 @@ Statement* Parser::DesugarLetBindingsInForStatement( |
// make statement: let x = temp_x. |
for (int i = 0; i < names->length(); i++) { |
VariableProxy* proxy = NewUnresolved(names->at(i), LET); |
- Declaration* declaration = |
- factory()->NewVariableDeclaration(proxy, LET, scope_, pos); |
+ Declaration* declaration = factory()->NewVariableDeclaration( |
+ proxy, LET, scope_, RelocInfo::kNoPosition); |
Declare(declaration, true, CHECK_OK); |
inner_vars.Add(declaration->proxy()->var(), zone()); |
VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); |
Assignment* assignment = factory()->NewAssignment( |
Token::INIT_LET, proxy, temp_proxy, pos); |
- Statement* assignment_statement = factory()->NewExpressionStatement( |
- assignment, pos); |
- proxy->var()->set_initializer_position(pos); |
+ Statement* assignment_statement = |
+ factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
+ proxy->var()->set_initializer_position(init->position()); |
inner_block->AddStatement(assignment_statement, zone()); |
} |
@@ -3239,7 +3253,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
CHECK_OK); |
bool accept_OF = decl_props == kHasNoInitializers; |
ForEachStatement::VisitMode mode; |
- int each_pos = position(); |
+ int each_beg_pos = scanner()->location().beg_pos; |
+ int each_end_pos = scanner()->location().end_pos; |
if (name != NULL && CheckInOrOf(accept_OF, &mode, ok)) { |
if (!*ok) return nullptr; |
@@ -3250,7 +3265,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
Expression* enumerable = ParseExpression(true, CHECK_OK); |
Expect(Token::RPAREN, CHECK_OK); |
- VariableProxy* each = scope_->NewUnresolved(factory(), name, each_pos); |
+ VariableProxy* each = |
+ scope_->NewUnresolved(factory(), name, each_beg_pos, each_end_pos); |
Statement* body = ParseSubStatement(NULL, CHECK_OK); |
InitializeForEachStatement(loop, each, enumerable, body); |
Block* result = |
@@ -3277,7 +3293,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
bool accept_IN = name != NULL && decl_props != kHasInitializers; |
bool accept_OF = decl_props == kHasNoInitializers; |
ForEachStatement::VisitMode mode; |
- int each_pos = position(); |
+ 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 (!*ok) return nullptr; |
@@ -3299,7 +3316,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
// implementing stack allocated block scoped variables. |
Variable* temp = scope_->DeclarationScope()->NewTemporary( |
ast_value_factory()->dot_for_string()); |
- VariableProxy* temp_proxy = factory()->NewVariableProxy(temp, each_pos); |
+ VariableProxy* temp_proxy = |
+ factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); |
ForEachStatement* loop = |
factory()->NewForEachStatement(mode, labels, stmt_pos); |
Target target(&this->target_stack_, loop); |
@@ -3310,7 +3328,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
scope_ = for_scope; |
Expect(Token::RPAREN, CHECK_OK); |
- VariableProxy* each = scope_->NewUnresolved(factory(), name, each_pos); |
+ VariableProxy* each = |
+ scope_->NewUnresolved(factory(), name, each_beg_pos, each_end_pos); |
Statement* body = ParseSubStatement(NULL, CHECK_OK); |
Block* body_block = |
factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); |
@@ -4094,6 +4113,8 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, |
bool has_seen_constructor = false; |
Expect(Token::LBRACE, CHECK_OK); |
+ int body_beg_pos = scanner()->location().beg_pos; |
+ |
const bool has_extends = extends != nullptr; |
while (peek() != Token::RBRACE) { |
if (Check(Token::SEMICOLON)) continue; |
@@ -4133,7 +4154,7 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, |
if (name != NULL) { |
DCHECK_NOT_NULL(proxy); |
DCHECK_NOT_NULL(block_scope); |
- proxy->var()->set_initializer_position(end_pos); |
+ proxy->var()->set_initializer_position(body_beg_pos); |
} |
return factory()->NewClassLiteral(name, block_scope, proxy, extends, |