Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 // Traverse the scope tree up to the first unresolved scope or the global | 256 // Traverse the scope tree up to the first unresolved scope or the global |
| 257 // scope and start scope resolution and variable allocation from that scope. | 257 // scope and start scope resolution and variable allocation from that scope. |
| 258 while (!top->is_script_scope() && | 258 while (!top->is_script_scope() && |
| 259 !top->outer_scope()->already_resolved()) { | 259 !top->outer_scope()->already_resolved()) { |
| 260 top = top->outer_scope(); | 260 top = top->outer_scope(); |
| 261 } | 261 } |
| 262 | 262 |
| 263 // Allocate the variables. | 263 // Allocate the variables. |
| 264 { | 264 { |
| 265 AstNodeFactory ast_node_factory(info->ast_value_factory()); | 265 AstNodeFactory ast_node_factory(info->ast_value_factory()); |
| 266 if (!top->AllocateVariables(info, &ast_node_factory)) return false; | 266 if (!top->AllocateVariables(info, &ast_node_factory)) { |
| 267 DCHECK(top->pending_error_handler_.has_pending_error()); | |
| 268 top->pending_error_handler_.ThrowPendingError(info->isolate(), | |
| 269 info->script()); | |
| 270 return false; | |
| 271 } | |
| 267 } | 272 } |
| 268 | 273 |
| 269 #ifdef DEBUG | 274 #ifdef DEBUG |
| 270 if (info->isolate()->bootstrapper()->IsActive() | 275 if (info->isolate()->bootstrapper()->IsActive() |
| 271 ? FLAG_print_builtin_scopes | 276 ? FLAG_print_builtin_scopes |
| 272 : FLAG_print_scopes) { | 277 : FLAG_print_scopes) { |
| 273 scope->Print(); | 278 scope->Print(); |
| 274 } | 279 } |
| 275 #endif | 280 #endif |
| 276 | 281 |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 454 DCHECK_NULL(rest_parameter_); | 459 DCHECK_NULL(rest_parameter_); |
| 455 rest_parameter_ = var; | 460 rest_parameter_ = var; |
| 456 rest_index_ = num_parameters(); | 461 rest_index_ = num_parameters(); |
| 457 } | 462 } |
| 458 params_.Add(var, zone()); | 463 params_.Add(var, zone()); |
| 459 return var; | 464 return var; |
| 460 } | 465 } |
| 461 | 466 |
| 462 | 467 |
| 463 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, | 468 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, |
| 464 InitializationFlag init_flag, | 469 InitializationFlag init_flag, bool is_function, |
| 465 MaybeAssignedFlag maybe_assigned_flag) { | 470 MaybeAssignedFlag maybe_assigned_flag) { |
| 466 DCHECK(!already_resolved()); | 471 DCHECK(!already_resolved()); |
| 467 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are | 472 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are |
| 468 // introduces during variable allocation, INTERNAL variables are allocated | 473 // introduces during variable allocation, INTERNAL variables are allocated |
| 469 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). | 474 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). |
| 470 DCHECK(IsDeclaredVariableMode(mode)); | 475 DCHECK(IsDeclaredVariableMode(mode)); |
| 471 ++num_var_or_const_; | 476 ++num_var_or_const_; |
| 472 return variables_.Declare(this, name, mode, true, Variable::NORMAL, init_flag, | 477 return variables_.Declare(this, name, mode, true, |
| 473 maybe_assigned_flag); | 478 is_function ? Variable::FUNCTION : Variable::NORMAL, |
| 479 init_flag, maybe_assigned_flag); | |
| 474 } | 480 } |
| 475 | 481 |
| 476 | 482 |
| 477 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { | 483 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { |
| 478 DCHECK(is_script_scope()); | 484 DCHECK(is_script_scope()); |
| 479 return variables_.Declare(this, | 485 return variables_.Declare(this, |
| 480 name, | 486 name, |
| 481 DYNAMIC_GLOBAL, | 487 DYNAMIC_GLOBAL, |
| 482 true, | 488 true, |
| 483 Variable::NORMAL, | 489 Variable::NORMAL, |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 761 int end_pos = scope->end_position(); | 767 int end_pos = scope->end_position(); |
| 762 DCHECK(beg_pos >= 0 && end_pos >= 0); | 768 DCHECK(beg_pos >= 0 && end_pos >= 0); |
| 763 if (beg_pos <= position && position < end_pos) { | 769 if (beg_pos <= position && position < end_pos) { |
| 764 scope->GetNestedScopeChain(isolate, chain, position); | 770 scope->GetNestedScopeChain(isolate, chain, position); |
| 765 return; | 771 return; |
| 766 } | 772 } |
| 767 } | 773 } |
| 768 } | 774 } |
| 769 | 775 |
| 770 | 776 |
| 777 void Scope::ReportMessage(int start_position, int end_position, | |
| 778 const char* message, const AstRawString* arg) { | |
| 779 // Propagate the error to the topmost scope targeted by this scope analysis | |
| 780 // phase. | |
| 781 Scope* top = this; | |
| 782 while (!top->is_script_scope() && !top->outer_scope()->already_resolved()) { | |
| 783 top = top->outer_scope(); | |
| 784 } | |
| 785 | |
| 786 top->pending_error_handler_.ReportMessageAt(start_position, end_position, | |
| 787 message, arg, kReferenceError); | |
| 788 } | |
| 789 | |
| 790 | |
| 771 #ifdef DEBUG | 791 #ifdef DEBUG |
| 772 static const char* Header(ScopeType scope_type) { | 792 static const char* Header(ScopeType scope_type) { |
| 773 switch (scope_type) { | 793 switch (scope_type) { |
| 774 case EVAL_SCOPE: return "eval"; | 794 case EVAL_SCOPE: return "eval"; |
| 775 case FUNCTION_SCOPE: return "function"; | 795 case FUNCTION_SCOPE: return "function"; |
| 776 case MODULE_SCOPE: return "module"; | 796 case MODULE_SCOPE: return "module"; |
| 777 case SCRIPT_SCOPE: return "global"; | 797 case SCRIPT_SCOPE: return "global"; |
| 778 case CATCH_SCOPE: return "catch"; | 798 case CATCH_SCOPE: return "catch"; |
| 779 case BLOCK_SCOPE: return "block"; | 799 case BLOCK_SCOPE: return "block"; |
| 780 case WITH_SCOPE: return "with"; | 800 case WITH_SCOPE: return "with"; |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1043 // If the proxy is already resolved there's nothing to do | 1063 // If the proxy is already resolved there's nothing to do |
| 1044 // (functions and consts may be resolved by the parser). | 1064 // (functions and consts may be resolved by the parser). |
| 1045 if (proxy->is_resolved()) return true; | 1065 if (proxy->is_resolved()) return true; |
| 1046 | 1066 |
| 1047 // Otherwise, try to resolve the variable. | 1067 // Otherwise, try to resolve the variable. |
| 1048 BindingKind binding_kind; | 1068 BindingKind binding_kind; |
| 1049 Variable* var = LookupRecursive(proxy, &binding_kind, factory); | 1069 Variable* var = LookupRecursive(proxy, &binding_kind, factory); |
| 1050 switch (binding_kind) { | 1070 switch (binding_kind) { |
| 1051 case BOUND: | 1071 case BOUND: |
| 1052 // We found a variable binding. | 1072 // We found a variable binding. |
| 1073 if (is_strong(language_mode())) { | |
| 1074 // Check for declaration-after use (for variables) in strong mode. Note | |
| 1075 // that we can only do this in the case where we have seen the | |
| 1076 // declaration. And we always allow referencing functions (for now). | |
| 1077 | |
| 1078 // If both the use and the declaration are inside an eval scope | |
| 1079 // (possibly indirectly), or one of them is, we need to check whether | |
| 1080 // they are inside the same eval scope or different | |
| 1081 // ones. TODO(marja,rossberg): Detect errors across different evals | |
|
arv (Not doing code reviews)
2015/02/25 16:37:32
Move TODO to new line?
marja
2015/02/26 12:55:42
Done.
| |
| 1082 // (depends on the future of eval in strong mode). | |
| 1083 const Scope* eval_for_use = NearestOuterEvalScope(); | |
| 1084 const Scope* eval_for_declaration = | |
| 1085 var->scope()->NearestOuterEvalScope(); | |
| 1086 | |
| 1087 if (proxy->position() != RelocInfo::kNoPosition && | |
| 1088 proxy->position() < var->initializer_position() && | |
| 1089 !var->is_function() && eval_for_use == eval_for_declaration) { | |
| 1090 DCHECK(proxy->end_position() != RelocInfo::kNoPosition); | |
| 1091 ReportMessage(proxy->position(), proxy->end_position(), | |
| 1092 "strong_use_before_declaration", proxy->raw_name()); | |
| 1093 return false; | |
| 1094 } | |
| 1095 } | |
| 1053 break; | 1096 break; |
| 1054 | 1097 |
| 1055 case BOUND_EVAL_SHADOWED: | 1098 case BOUND_EVAL_SHADOWED: |
| 1056 // We either found a variable binding that might be shadowed by eval or | 1099 // We either found a variable binding that might be shadowed by eval or |
| 1057 // gave up on it (e.g. by encountering a local with the same in the outer | 1100 // gave up on it (e.g. by encountering a local with the same in the outer |
| 1058 // scope which was not promoted to a context, this can happen if we use | 1101 // scope which was not promoted to a context, this can happen if we use |
| 1059 // debugger to evaluate arbitrary expressions at a break point). | 1102 // debugger to evaluate arbitrary expressions at a break point). |
| 1060 if (var->IsGlobalObjectProperty()) { | 1103 if (var->IsGlobalObjectProperty()) { |
| 1061 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); | 1104 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); |
| 1062 } else if (var->is_dynamic()) { | 1105 } else if (var->is_dynamic()) { |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1381 } | 1424 } |
| 1382 | 1425 |
| 1383 | 1426 |
| 1384 int Scope::ContextLocalCount() const { | 1427 int Scope::ContextLocalCount() const { |
| 1385 if (num_heap_slots() == 0) return 0; | 1428 if (num_heap_slots() == 0) return 0; |
| 1386 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1429 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
| 1387 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1430 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
| 1388 } | 1431 } |
| 1389 | 1432 |
| 1390 } } // namespace v8::internal | 1433 } } // namespace v8::internal |
| OLD | NEW |