Index: src/ast/scopes.cc |
diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc |
index c2b05b7c040ca6ed11f700d952a10947fb4e893c..b9ad06482f52dcb46b73111004220213cb39eb12 100644 |
--- a/src/ast/scopes.cc |
+++ b/src/ast/scopes.cc |
@@ -27,12 +27,10 @@ VariableMap::VariableMap(Zone* zone) |
zone_(zone) {} |
VariableMap::~VariableMap() {} |
- |
Variable* VariableMap::Declare(Scope* scope, const AstRawString* name, |
VariableMode mode, Variable::Kind kind, |
InitializationFlag initialization_flag, |
- MaybeAssignedFlag maybe_assigned_flag, |
- int declaration_group_start) { |
+ MaybeAssignedFlag maybe_assigned_flag) { |
// AstRawStrings are unambiguous, i.e., the same string is always represented |
// by the same AstRawString*. |
// FIXME(marja): fix the type of Lookup. |
@@ -42,14 +40,8 @@ Variable* VariableMap::Declare(Scope* scope, const AstRawString* name, |
if (p->value == NULL) { |
// The variable has not been declared yet -> insert it. |
DCHECK(p->key == name); |
- if (kind == Variable::CLASS) { |
- p->value = new (zone()) |
- ClassVariable(scope, name, mode, initialization_flag, |
- maybe_assigned_flag, declaration_group_start); |
- } else { |
- p->value = new (zone()) Variable( |
- scope, name, mode, kind, initialization_flag, maybe_assigned_flag); |
- } |
+ p->value = new (zone()) Variable(scope, name, mode, kind, |
+ initialization_flag, maybe_assigned_flag); |
} |
return reinterpret_cast<Variable*>(p->value); |
} |
@@ -103,8 +95,7 @@ Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type, |
sloppy_block_function_map_(zone), |
already_resolved_(false), |
ast_value_factory_(ast_value_factory), |
- zone_(zone), |
- class_declaration_group_start_(-1) { |
+ zone_(zone) { |
SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null(), |
function_kind); |
// The outermost scope must be a script scope. |
@@ -112,7 +103,6 @@ Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type, |
DCHECK(!HasIllegalRedeclaration()); |
} |
- |
Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, |
Handle<ScopeInfo> scope_info, AstValueFactory* value_factory) |
: inner_scopes_(4, zone), |
@@ -125,8 +115,7 @@ Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, |
sloppy_block_function_map_(zone), |
already_resolved_(true), |
ast_value_factory_(value_factory), |
- zone_(zone), |
- class_declaration_group_start_(-1) { |
+ zone_(zone) { |
SetDefaults(scope_type, NULL, scope_info); |
if (!scope_info.is_null()) { |
num_heap_slots_ = scope_info_->ContextLength(); |
@@ -137,7 +126,6 @@ Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, |
AddInnerScope(inner_scope); |
} |
- |
Scope::Scope(Zone* zone, Scope* inner_scope, |
const AstRawString* catch_variable_name, |
AstValueFactory* value_factory) |
@@ -151,8 +139,7 @@ Scope::Scope(Zone* zone, Scope* inner_scope, |
sloppy_block_function_map_(zone), |
already_resolved_(true), |
ast_value_factory_(value_factory), |
- zone_(zone), |
- class_declaration_group_start_(-1) { |
+ zone_(zone) { |
SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); |
AddInnerScope(inner_scope); |
++num_var_or_const_; |
@@ -528,11 +515,9 @@ Variable* Scope::DeclareParameter( |
return var; |
} |
- |
Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, |
InitializationFlag init_flag, Variable::Kind kind, |
- MaybeAssignedFlag maybe_assigned_flag, |
- int declaration_group_start) { |
+ MaybeAssignedFlag maybe_assigned_flag) { |
DCHECK(!already_resolved()); |
// This function handles VAR, LET, and CONST modes. DYNAMIC variables are |
// introduces during variable allocation, and TEMPORARY variables are |
@@ -540,7 +525,7 @@ Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, |
DCHECK(IsDeclaredVariableMode(mode)); |
++num_var_or_const_; |
return variables_.Declare(this, name, mode, kind, init_flag, |
- maybe_assigned_flag, declaration_group_start); |
+ maybe_assigned_flag); |
} |
@@ -660,11 +645,9 @@ class VarAndOrder { |
int order_; |
}; |
- |
-void Scope::CollectStackAndContextLocals( |
- ZoneList<Variable*>* stack_locals, ZoneList<Variable*>* context_locals, |
- ZoneList<Variable*>* context_globals, |
- ZoneList<Variable*>* strong_mode_free_variables) { |
+void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals, |
+ ZoneList<Variable*>* context_locals, |
+ ZoneList<Variable*>* context_globals) { |
DCHECK(stack_locals != NULL); |
DCHECK(context_locals != NULL); |
DCHECK(context_globals != NULL); |
@@ -691,11 +674,6 @@ void Scope::CollectStackAndContextLocals( |
p != NULL; |
p = variables_.Next(p)) { |
Variable* var = reinterpret_cast<Variable*>(p->value); |
- if (strong_mode_free_variables && var->has_strong_mode_reference() && |
- var->mode() == DYNAMIC_GLOBAL) { |
- strong_mode_free_variables->Add(var, zone()); |
- } |
- |
if (var->is_used()) { |
vars.Add(VarAndOrder(var, p->order), zone()); |
} |
@@ -1017,9 +995,7 @@ void Scope::Print(int n) { |
if (HasTrivialOuterContext()) { |
Indent(n1, "// scope has trivial outer context\n"); |
} |
- if (is_strong(language_mode())) { |
- Indent(n1, "// strong mode scope\n"); |
- } else if (is_strict(language_mode())) { |
+ if (is_strict(language_mode())) { |
Indent(n1, "// strict mode scope\n"); |
} |
if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); |
@@ -1204,10 +1180,6 @@ bool Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy, |
switch (binding_kind) { |
case BOUND: |
- // We found a variable binding. |
- if (is_strong(language_mode())) { |
- if (!CheckStrongModeDeclaration(proxy, var)) return false; |
- } |
break; |
case BOUND_EVAL_SHADOWED: |
@@ -1245,126 +1217,12 @@ bool Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy, |
DCHECK(var != NULL); |
if (proxy->is_assigned()) var->set_maybe_assigned(); |
- if (is_strong(language_mode())) { |
- // Record that the variable is referred to from strong mode. Also, record |
- // the position. |
- var->RecordStrongModeReference(proxy->position(), proxy->end_position()); |
- } |
- |
proxy->BindTo(var); |
return true; |
} |
-bool Scope::CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var) { |
- // Check for declaration-after use (for variables) in strong mode. Note that |
- // we can only do this in the case where we have seen the declaration. And we |
- // always allow referencing functions (for now). |
- |
- // This might happen during lazy compilation; we don't keep track of |
- // initializer positions for variables stored in ScopeInfo, so we cannot check |
- // bindings against them. TODO(marja, rossberg): remove this hack. |
- if (var->initializer_position() == RelocInfo::kNoPosition) return true; |
- |
- // Allow referencing the class name from methods of that class, even though |
- // the initializer position for class names is only after the body. |
- Scope* scope = this; |
- while (scope) { |
- if (scope->ClassVariableForMethod() == var) return true; |
- scope = scope->outer_scope(); |
- } |
- |
- // Allow references from methods to classes declared later, if we detect no |
- // problematic dependency cycles. Note that we can be inside multiple methods |
- // at the same time, and it's enough if we find one where the reference is |
- // allowed. |
- if (var->is_class() && |
- var->AsClassVariable()->declaration_group_start() >= 0) { |
- for (scope = this; scope && scope != var->scope(); |
- scope = scope->outer_scope()) { |
- ClassVariable* class_var = scope->ClassVariableForMethod(); |
- // A method is referring to some other class, possibly declared |
- // later. Referring to a class declared earlier is always OK and covered |
- // by the code outside this if. Here we only need to allow special cases |
- // for referring to a class which is declared later. |
- |
- // Referring to a class C declared later is OK under the following |
- // circumstances: |
- |
- // 1. The class declarations are in a consecutive group with no other |
- // declarations or statements in between, and |
- |
- // 2. There is no dependency cycle where the first edge is an |
- // initialization time dependency (computed property name or extends |
- // clause) from C to something that depends on this class directly or |
- // transitively. |
- if (class_var && |
- class_var->declaration_group_start() == |
- var->AsClassVariable()->declaration_group_start()) { |
- return true; |
- } |
- |
- // TODO(marja,rossberg): implement the dependency cycle detection. Here we |
- // undershoot the target and allow referring to any class in the same |
- // consectuive declaration group. |
- |
- // The cycle detection can work roughly like this: 1) detect init-time |
- // references here (they are free variables which are inside the class |
- // scope but not inside a method scope - no parser changes needed to |
- // detect them) 2) if we encounter an init-time reference here, allow it, |
- // but record it for a later dependency cycle check 3) also record |
- // non-init-time references here 4) after scope analysis is done, analyse |
- // the dependency cycles: an illegal cycle is one starting with an |
- // init-time reference and leading back to the starting point with either |
- // non-init-time and init-time references. |
- } |
- } |
- |
- // If both the use and the declaration are inside an eval scope (possibly |
- // indirectly), or one of them is, we need to check whether they are inside |
- // the same eval scope or different ones. |
- |
- // TODO(marja,rossberg): Detect errors across different evals (depends on the |
- // future of eval in strong mode). |
- const Scope* eval_for_use = NearestOuterEvalScope(); |
- const Scope* eval_for_declaration = var->scope()->NearestOuterEvalScope(); |
- |
- if (proxy->position() != RelocInfo::kNoPosition && |
- proxy->position() < var->initializer_position() && !var->is_function() && |
- eval_for_use == eval_for_declaration) { |
- DCHECK(proxy->end_position() != RelocInfo::kNoPosition); |
- ReportMessage(proxy->position(), proxy->end_position(), |
- MessageTemplate::kStrongUseBeforeDeclaration, |
- proxy->raw_name()); |
- return false; |
- } |
- return true; |
-} |
- |
- |
-ClassVariable* Scope::ClassVariableForMethod() const { |
- // TODO(marja, rossberg): This fails to find a class variable in the following |
- // cases: |
- // let A = class { ... } |
- // It needs to be investigated whether this causes any practical problems. |
- if (!is_function_scope()) return nullptr; |
- if (IsInObjectLiteral(function_kind_)) return nullptr; |
- if (!IsConciseMethod(function_kind_) && !IsClassConstructor(function_kind_) && |
- !IsAccessorFunction(function_kind_)) { |
- return nullptr; |
- } |
- DCHECK_NOT_NULL(outer_scope_); |
- // The class scope contains at most one variable, the class name. |
- DCHECK(outer_scope_->variables_.occupancy() <= 1); |
- if (outer_scope_->variables_.occupancy() == 0) return nullptr; |
- VariableMap::Entry* p = outer_scope_->variables_.Start(); |
- Variable* var = reinterpret_cast<Variable*>(p->value); |
- if (!var->is_class()) return nullptr; |
- return var->AsClassVariable(); |
-} |
- |
- |
bool Scope::ResolveVariablesRecursively(ParseInfo* info, |
AstNodeFactory* factory) { |
DCHECK(info->script_scope()->is_script_scope()); |