Index: src/parsing/parser.cc |
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc |
index 21614e53cbbec330c2d16fbfc36bfb1b1e4034ad..8155dcc42889c1973ae76d7466f66ba3ebcf6c1d 100644 |
--- a/src/parsing/parser.cc |
+++ b/src/parsing/parser.cc |
@@ -1969,30 +1969,39 @@ Variable* Parser::Declare(Declaration* declaration, |
var = declaration_scope->DeclareLocal( |
name, mode, declaration->initialization(), kind, kNotAssigned, |
declaration_group_start); |
- } else if (((IsLexicalVariableMode(mode) || |
- IsLexicalVariableMode(var->mode())) && |
- // Allow duplicate function decls for web compat, see bug 4693. |
- (is_strict(language_mode()) || !is_function_declaration || |
- !var->is_function())) || |
- ((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 |
- // compatibility). There is similar code in runtime.cc in the Declare |
- // functions. The function CheckConflictingVarDeclarations checks for |
- // var and let bindings from different scopes whereas this is a check for |
- // conflicting declarations within the same scope. This check also covers |
- // the special case |
- // |
- // function () { let x; { var x; } } |
- // |
- // because the var declaration is hoisted to the function scope where 'x' |
- // is already bound. |
- DCHECK(IsDeclaredVariableMode(var->mode())); |
- if (is_strict(language_mode()) || |
- (allow_harmony_sloppy() && mode != CONST_LEGACY && |
- var->mode() != CONST_LEGACY)) { |
+ } else if ((mode == CONST_LEGACY || var->mode() == CONST_LEGACY) && |
+ !declaration_scope->is_script_scope()) { |
+ // Duplicate legacy const definitions throw at runtime. |
+ DCHECK(is_sloppy(language_mode())); |
+ Expression* expression = NewThrowSyntaxError( |
+ MessageTemplate::kVarRedeclaration, name, declaration->position()); |
+ declaration_scope->SetIllegalRedeclaration(expression); |
+ } else if ((IsLexicalVariableMode(mode) || |
+ IsLexicalVariableMode(var->mode())) && |
+ // Lexical bindings may appear for some parameters in sloppy |
+ // mode even with --harmony-sloppy off. |
+ (is_strict(language_mode()) || allow_harmony_sloppy())) { |
+ // Allow duplicate function decls for web compat, see bug 4693. |
+ if (is_sloppy(language_mode()) && is_function_declaration && |
+ var->is_function()) { |
+ DCHECK(IsLexicalVariableMode(mode) && |
+ IsLexicalVariableMode(var->mode())); |
+ ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition]; |
+ } else { |
+ // 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 compatibility). There is similar code in runtime.cc in the |
+ // Declare functions. The function CheckConflictingVarDeclarations |
+ // checks for var and let bindings from different scopes whereas this |
+ // is a check for conflicting declarations within the same scope. This |
+ // check also covers the special case |
+ // |
+ // function () { let x; { var x; } } |
+ // |
+ // because the var declaration is hoisted to the function scope where |
+ // 'x' is already bound. |
+ DCHECK(IsDeclaredVariableMode(var->mode())); |
// In harmony we treat re-declarations as early errors. See |
// ES5 16 for a definition of early errors. |
if (declaration_kind == DeclarationDescriptor::NORMAL) { |
@@ -2003,9 +2012,6 @@ Variable* Parser::Declare(Declaration* declaration, |
*ok = false; |
return nullptr; |
} |
- Expression* expression = NewThrowSyntaxError( |
- MessageTemplate::kVarRedeclaration, name, declaration->position()); |
- declaration_scope->SetIllegalRedeclaration(expression); |
} else if (mode == VAR) { |
var->set_maybe_assigned(); |
} |
@@ -3641,6 +3647,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
// special case for legacy for (var/const x =.... in) |
if (!IsLexicalVariableMode(parsing_result.descriptor.mode) && |
decl.pattern->IsVariableProxy() && decl.initializer != nullptr) { |
+ ++use_counts_[v8::Isolate::kForInInitializer]; |
const AstRawString* name = |
decl.pattern->AsVariableProxy()->raw_name(); |
VariableProxy* single_var = scope_->NewUnresolved( |