Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(299)

Side by Side Diff: src/scopes.cc

Issue 968263002: [strong] Fix scoping related errors for methods. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: code review (arv, rossberg) Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/scopes.h ('k') | test/mjsunit/strong/declaration-after-use.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/scopes.h" 7 #include "src/scopes.h"
8 8
9 #include "src/accessors.h" 9 #include "src/accessors.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 return reinterpret_cast<Variable*>(p->value); 59 return reinterpret_cast<Variable*>(p->value);
60 } 60 }
61 return NULL; 61 return NULL;
62 } 62 }
63 63
64 64
65 // ---------------------------------------------------------------------------- 65 // ----------------------------------------------------------------------------
66 // Implementation of Scope 66 // Implementation of Scope
67 67
68 Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type, 68 Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type,
69 AstValueFactory* ast_value_factory) 69 AstValueFactory* ast_value_factory, FunctionKind function_kind)
70 : inner_scopes_(4, zone), 70 : inner_scopes_(4, zone),
71 variables_(zone), 71 variables_(zone),
72 internals_(4, zone), 72 internals_(4, zone),
73 temps_(4, zone), 73 temps_(4, zone),
74 params_(4, zone), 74 params_(4, zone),
75 unresolved_(16, zone), 75 unresolved_(16, zone),
76 decls_(4, zone), 76 decls_(4, zone),
77 module_descriptor_( 77 module_descriptor_(
78 scope_type == MODULE_SCOPE ? ModuleDescriptor::New(zone) : NULL), 78 scope_type == MODULE_SCOPE ? ModuleDescriptor::New(zone) : NULL),
79 already_resolved_(false), 79 already_resolved_(false),
80 ast_value_factory_(ast_value_factory), 80 ast_value_factory_(ast_value_factory),
81 zone_(zone) { 81 zone_(zone) {
82 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null()); 82 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null(),
83 function_kind);
83 // The outermost scope must be a script scope. 84 // The outermost scope must be a script scope.
84 DCHECK(scope_type == SCRIPT_SCOPE || outer_scope != NULL); 85 DCHECK(scope_type == SCRIPT_SCOPE || outer_scope != NULL);
85 DCHECK(!HasIllegalRedeclaration()); 86 DCHECK(!HasIllegalRedeclaration());
86 } 87 }
87 88
88 89
89 Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, 90 Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type,
90 Handle<ScopeInfo> scope_info, AstValueFactory* value_factory) 91 Handle<ScopeInfo> scope_info, AstValueFactory* value_factory)
91 : inner_scopes_(4, zone), 92 : inner_scopes_(4, zone),
92 variables_(zone), 93 variables_(zone),
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 Variable* variable = variables_.Declare(this, 132 Variable* variable = variables_.Declare(this,
132 catch_variable_name, 133 catch_variable_name,
133 VAR, 134 VAR,
134 true, // Valid left-hand side. 135 true, // Valid left-hand side.
135 Variable::NORMAL, 136 Variable::NORMAL,
136 kCreatedInitialized); 137 kCreatedInitialized);
137 AllocateHeapSlot(variable); 138 AllocateHeapSlot(variable);
138 } 139 }
139 140
140 141
141 void Scope::SetDefaults(ScopeType scope_type, 142 void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope,
142 Scope* outer_scope, 143 Handle<ScopeInfo> scope_info,
143 Handle<ScopeInfo> scope_info) { 144 FunctionKind function_kind) {
144 outer_scope_ = outer_scope; 145 outer_scope_ = outer_scope;
145 scope_type_ = scope_type; 146 scope_type_ = scope_type;
147 function_kind_ = function_kind;
148 block_scope_is_class_scope_ = false;
146 scope_name_ = ast_value_factory_->empty_string(); 149 scope_name_ = ast_value_factory_->empty_string();
147 dynamics_ = NULL; 150 dynamics_ = NULL;
148 receiver_ = NULL; 151 receiver_ = NULL;
149 new_target_ = nullptr; 152 new_target_ = nullptr;
150 function_ = NULL; 153 function_ = NULL;
151 arguments_ = NULL; 154 arguments_ = NULL;
152 illegal_redecl_ = NULL; 155 illegal_redecl_ = NULL;
153 scope_inside_with_ = false; 156 scope_inside_with_ = false;
154 scope_contains_with_ = false; 157 scope_contains_with_ = false;
155 scope_calls_eval_ = false; 158 scope_calls_eval_ = false;
(...skipping 18 matching lines...) Expand all
174 num_modules_ = 0; 177 num_modules_ = 0;
175 module_var_ = NULL, 178 module_var_ = NULL,
176 rest_parameter_ = NULL; 179 rest_parameter_ = NULL;
177 rest_index_ = -1; 180 rest_index_ = -1;
178 scope_info_ = scope_info; 181 scope_info_ = scope_info;
179 start_position_ = RelocInfo::kNoPosition; 182 start_position_ = RelocInfo::kNoPosition;
180 end_position_ = RelocInfo::kNoPosition; 183 end_position_ = RelocInfo::kNoPosition;
181 if (!scope_info.is_null()) { 184 if (!scope_info.is_null()) {
182 scope_calls_eval_ = scope_info->CallsEval(); 185 scope_calls_eval_ = scope_info->CallsEval();
183 language_mode_ = scope_info->language_mode(); 186 language_mode_ = scope_info->language_mode();
187 block_scope_is_class_scope_ = scope_info->block_scope_is_class_scope();
188 function_kind_ = scope_info->function_kind();
184 } 189 }
185 } 190 }
186 191
187 192
188 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, 193 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
189 Context* context, Scope* script_scope) { 194 Context* context, Scope* script_scope) {
190 // Reconstruct the outer scope chain from a closure's context chain. 195 // Reconstruct the outer scope chain from a closure's context chain.
191 Scope* current_scope = NULL; 196 Scope* current_scope = NULL;
192 Scope* innermost_scope = NULL; 197 Scope* innermost_scope = NULL;
193 bool contains_with = false; 198 bool contains_with = false;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 : FLAG_print_scopes) { 282 : FLAG_print_scopes) {
278 scope->Print(); 283 scope->Print();
279 } 284 }
280 #endif 285 #endif
281 286
282 info->PrepareForCompilation(scope); 287 info->PrepareForCompilation(scope);
283 return true; 288 return true;
284 } 289 }
285 290
286 291
287 void Scope::Initialize(bool subclass_constructor) { 292 void Scope::Initialize() {
293 bool subclass_constructor = IsSubclassConstructor(function_kind_);
288 DCHECK(!already_resolved()); 294 DCHECK(!already_resolved());
289 295
290 // Add this scope as a new inner scope of the outer scope. 296 // Add this scope as a new inner scope of the outer scope.
291 if (outer_scope_ != NULL) { 297 if (outer_scope_ != NULL) {
292 outer_scope_->inner_scopes_.Add(this, zone()); 298 outer_scope_->inner_scopes_.Add(this, zone());
293 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope(); 299 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope();
294 } else { 300 } else {
295 scope_inside_with_ = is_with_scope(); 301 scope_inside_with_ = is_with_scope();
296 } 302 }
297 303
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 // (functions and consts may be resolved by the parser). 1069 // (functions and consts may be resolved by the parser).
1064 if (proxy->is_resolved()) return true; 1070 if (proxy->is_resolved()) return true;
1065 1071
1066 // Otherwise, try to resolve the variable. 1072 // Otherwise, try to resolve the variable.
1067 BindingKind binding_kind; 1073 BindingKind binding_kind;
1068 Variable* var = LookupRecursive(proxy, &binding_kind, factory); 1074 Variable* var = LookupRecursive(proxy, &binding_kind, factory);
1069 switch (binding_kind) { 1075 switch (binding_kind) {
1070 case BOUND: 1076 case BOUND:
1071 // We found a variable binding. 1077 // We found a variable binding.
1072 if (is_strong(language_mode())) { 1078 if (is_strong(language_mode())) {
1073 // Check for declaration-after use (for variables) in strong mode. Note 1079 if (!CheckStrongModeDeclaration(proxy, var)) return false;
1074 // that we can only do this in the case where we have seen the
1075 // declaration. And we always allow referencing functions (for now).
1076
1077 // If both the use and the declaration are inside an eval scope
1078 // (possibly indirectly), or one of them is, we need to check whether
1079 // they are inside the same eval scope or different
1080 // ones.
1081
1082 // TODO(marja,rossberg): Detect errors across different evals (depends
1083 // on the future of eval in strong mode).
1084 const Scope* eval_for_use = NearestOuterEvalScope();
1085 const Scope* eval_for_declaration =
1086 var->scope()->NearestOuterEvalScope();
1087
1088 if (proxy->position() != RelocInfo::kNoPosition &&
1089 proxy->position() < var->initializer_position() &&
1090 !var->is_function() && eval_for_use == eval_for_declaration) {
1091 DCHECK(proxy->end_position() != RelocInfo::kNoPosition);
1092 ReportMessage(proxy->position(), proxy->end_position(),
1093 "strong_use_before_declaration", proxy->raw_name());
1094 return false;
1095 }
1096 } 1080 }
1097 break; 1081 break;
1098 1082
1099 case BOUND_EVAL_SHADOWED: 1083 case BOUND_EVAL_SHADOWED:
1100 // We either found a variable binding that might be shadowed by eval or 1084 // We either found a variable binding that might be shadowed by eval or
1101 // gave up on it (e.g. by encountering a local with the same in the outer 1085 // gave up on it (e.g. by encountering a local with the same in the outer
1102 // scope which was not promoted to a context, this can happen if we use 1086 // scope which was not promoted to a context, this can happen if we use
1103 // debugger to evaluate arbitrary expressions at a break point). 1087 // debugger to evaluate arbitrary expressions at a break point).
1104 if (var->IsGlobalObjectProperty()) { 1088 if (var->IsGlobalObjectProperty()) {
1105 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); 1089 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
(...skipping 24 matching lines...) Expand all
1130 1114
1131 DCHECK(var != NULL); 1115 DCHECK(var != NULL);
1132 if (proxy->is_assigned()) var->set_maybe_assigned(); 1116 if (proxy->is_assigned()) var->set_maybe_assigned();
1133 1117
1134 proxy->BindTo(var); 1118 proxy->BindTo(var);
1135 1119
1136 return true; 1120 return true;
1137 } 1121 }
1138 1122
1139 1123
1124 bool Scope::CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var) {
1125 // Check for declaration-after use (for variables) in strong mode. Note that
1126 // we can only do this in the case where we have seen the declaration. And we
1127 // always allow referencing functions (for now).
1128
1129 // Allow referencing the class name from methods of that class, even though
1130 // the initializer position for class names is only after the body.
1131 Scope* scope = this;
1132 while (scope) {
1133 if (scope->ClassVariableForMethod() == var) return true;
1134 scope = scope->outer_scope();
1135 }
1136
1137 // If both the use and the declaration are inside an eval scope (possibly
1138 // indirectly), or one of them is, we need to check whether they are inside
1139 // the same eval scope or different ones.
1140
1141 // TODO(marja,rossberg): Detect errors across different evals (depends on the
1142 // future of eval in strong mode).
1143 const Scope* eval_for_use = NearestOuterEvalScope();
1144 const Scope* eval_for_declaration = var->scope()->NearestOuterEvalScope();
1145
1146 if (proxy->position() != RelocInfo::kNoPosition &&
1147 proxy->position() < var->initializer_position() && !var->is_function() &&
1148 eval_for_use == eval_for_declaration) {
1149 DCHECK(proxy->end_position() != RelocInfo::kNoPosition);
1150 ReportMessage(proxy->position(), proxy->end_position(),
1151 "strong_use_before_declaration", proxy->raw_name());
1152 return false;
1153 }
1154 return true;
1155 }
1156
1157
1158 Variable* Scope::ClassVariableForMethod() const {
1159 if (!is_function_scope()) return nullptr;
1160 if (!IsConciseMethod(function_kind_) && !IsConstructor(function_kind_) &&
1161 !IsAccessorFunction(function_kind_)) {
1162 return nullptr;
1163 }
1164 DCHECK_NOT_NULL(outer_scope_);
1165 DCHECK(outer_scope_->is_class_scope());
1166 // The class scope contains at most one variable, the class name.
1167 DCHECK(outer_scope_->variables_.occupancy() <= 1);
1168 if (outer_scope_->variables_.occupancy() == 0) return nullptr;
1169 VariableMap::Entry* p = outer_scope_->variables_.Start();
1170 return reinterpret_cast<Variable*>(p->value);
1171 }
1172
1173
1140 bool Scope::ResolveVariablesRecursively(CompilationInfo* info, 1174 bool Scope::ResolveVariablesRecursively(CompilationInfo* info,
1141 AstNodeFactory* factory) { 1175 AstNodeFactory* factory) {
1142 DCHECK(info->script_scope()->is_script_scope()); 1176 DCHECK(info->script_scope()->is_script_scope());
1143 1177
1144 // Resolve unresolved variables for this scope. 1178 // Resolve unresolved variables for this scope.
1145 for (int i = 0; i < unresolved_.length(); i++) { 1179 for (int i = 0; i < unresolved_.length(); i++) {
1146 if (!ResolveVariable(info, unresolved_[i], factory)) return false; 1180 if (!ResolveVariable(info, unresolved_[i], factory)) return false;
1147 } 1181 }
1148 1182
1149 // Resolve unresolved variables for inner scopes. 1183 // Resolve unresolved variables for inner scopes.
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
1423 return num_stack_slots() - 1457 return num_stack_slots() -
1424 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); 1458 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0);
1425 } 1459 }
1426 1460
1427 1461
1428 int Scope::ContextLocalCount() const { 1462 int Scope::ContextLocalCount() const {
1429 if (num_heap_slots() == 0) return 0; 1463 if (num_heap_slots() == 0) return 0;
1430 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - 1464 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
1431 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); 1465 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0);
1432 } 1466 }
1433
1434 } } // namespace v8::internal 1467 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/scopes.h ('k') | test/mjsunit/strong/declaration-after-use.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698