| 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());
|
|
|