 Chromium Code Reviews
 Chromium Code Reviews Issue 7756014:
  Detect conflicting variable bindings in harmony mode.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
    
  
    Issue 7756014:
  Detect conflicting variable bindings in harmony mode.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge| Index: src/parser.cc | 
| diff --git a/src/parser.cc b/src/parser.cc | 
| index cf907ce0a5c88d081be37a3b07bafa2e1d1c99ff..b367c2846c45432c7103d24fa60d266e268936dc 100644 | 
| --- a/src/parser.cc | 
| +++ b/src/parser.cc | 
| @@ -647,6 +647,11 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source, | 
| if (ok && top_scope_->is_strict_mode()) { | 
| CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok); | 
| } | 
| + | 
| + if (ok && harmony_block_scoping_) { | 
| + CheckConflictingVarDeclarations(scope, &ok); | 
| + } | 
| + | 
| if (ok) { | 
| result = new(zone()) FunctionLiteral( | 
| isolate(), | 
| @@ -1345,12 +1350,24 @@ VariableProxy* Parser::Declare(Handle<String> name, | 
| } else { | 
| // The name was declared before; check for conflicting re-declarations. | 
| // We have a conflict if either of the declarations is not a var. There | 
| - // is similar code in runtime.cc in the Declare functions. | 
| + // is similar code in runtime.cc in the Declare functions. Also the | 
| + // function CheckNonConflictingScope checks for conflicting hoisting | 
| + // of var declared variables. | 
| 
Lasse Reichstein
2011/09/01 07:34:04
This checks only for a redeclaration in the same s
 
Steven
2011/09/01 15:01:33
Yes. Clarified it in the comment.
On 2011/09/01 07
 | 
| if ((mode != Variable::VAR) || (var->mode() != Variable::VAR)) { | 
| // We only have vars, consts and lets in declarations. | 
| ASSERT(var->mode() == Variable::VAR || | 
| var->mode() == Variable::CONST || | 
| var->mode() == Variable::LET); | 
| + if (harmony_block_scoping_) { | 
| + // In harmony mode we treat re-declarations as early errors. See | 
| + // ES5 16 for a definition of early errors. | 
| + SmartPointer<char> c_string = name->ToCString(DISALLOW_NULLS); | 
| + const char* elms[2] = { "Variable", *c_string }; | 
| + Vector<const char*> args(elms, 2); | 
| + ReportMessage("redeclaration", args); | 
| + *ok = false; | 
| + return NULL; | 
| + } | 
| const char* type = (var->mode() == Variable::VAR) ? "var" : | 
| (var->mode() == Variable::CONST) ? "const" : "let"; | 
| Handle<String> type_string = | 
| @@ -1380,7 +1397,8 @@ VariableProxy* Parser::Declare(Handle<String> name, | 
| // a performance issue since it may lead to repeated | 
| // Runtime::DeclareContextSlot() calls. | 
| VariableProxy* proxy = declaration_scope->NewUnresolved(name, false); | 
| - declaration_scope->AddDeclaration(new(zone()) Declaration(proxy, mode, fun)); | 
| + declaration_scope->AddDeclaration( | 
| + new(zone()) Declaration(proxy, mode, fun, top_scope_)); | 
| // For global const variables we bind the proxy to a variable. | 
| if (mode == Variable::CONST && declaration_scope->is_global_scope()) { | 
| @@ -2207,7 +2225,9 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { | 
| if (top_scope_->is_strict_mode()) { | 
| catch_scope->EnableStrictMode(); | 
| } | 
| - catch_variable = catch_scope->DeclareLocal(name, Variable::VAR); | 
| + Variable::Mode mode = harmony_block_scoping_ | 
| + ? Variable::LET : Variable::VAR; | 
| + catch_variable = catch_scope->DeclareLocal(name, mode); | 
| catch_block = new(zone()) Block(isolate(), NULL, 2, false); | 
| Scope* saved_scope = top_scope_; | 
| @@ -3736,7 +3756,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name, | 
| reserved_loc = scanner().location(); | 
| } | 
| - top_scope_->DeclareParameter(param_name); | 
| + top_scope_->DeclareParameter(param_name, | 
| + harmony_block_scoping_ | 
| + ? Variable::LET | 
| + : Variable::VAR); | 
| num_parameters++; | 
| if (num_parameters > kMaxNumFunctionParameters) { | 
| ReportMessageAt(scanner().location(), "too_many_parameters", | 
| @@ -3863,6 +3886,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name, | 
| } | 
| } | 
| + if (harmony_block_scoping_) { | 
| + CheckConflictingVarDeclarations(scope, CHECK_OK); | 
| + } | 
| + | 
| FunctionLiteral* function_literal = | 
| new(zone()) FunctionLiteral(isolate(), | 
| function_name, | 
| @@ -4069,6 +4096,21 @@ void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { | 
| } | 
| +void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { | 
| + Declaration* decl = scope->CheckConflictingVarDeclarations(); | 
| + if (decl != NULL) { | 
| + // In harmony mode we treat conflicting variable bindinds as early | 
| + // errors. See ES5 16 for a definition of early errors. | 
| + Handle<String> name = decl->proxy()->name(); | 
| + SmartPointer<char> c_string = name->ToCString(DISALLOW_NULLS); | 
| + const char* elms[2] = { "Variable", *c_string }; | 
| + Vector<const char*> args(elms, 2); | 
| + ReportMessage("redeclaration", args); | 
| 
Steven
2011/08/31 21:33:00
This ReportMessage should rather be a ReportMessag
 | 
| + *ok = false; | 
| + } | 
| +} | 
| + | 
| + | 
| // This function reads an identifier name and determines whether or not it | 
| // is 'get' or 'set'. | 
| Handle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get, |