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/ast/scopes.h" | 5 #include "src/ast/scopes.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
689 MaybeAssignedFlag maybe_assigned_flag) { | 689 MaybeAssignedFlag maybe_assigned_flag) { |
690 DCHECK(!already_resolved_); | 690 DCHECK(!already_resolved_); |
691 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are | 691 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are |
692 // introduced during variable allocation, and TEMPORARY variables are | 692 // introduced during variable allocation, and TEMPORARY variables are |
693 // allocated via NewTemporary(). | 693 // allocated via NewTemporary(). |
694 DCHECK(IsDeclaredVariableMode(mode)); | 694 DCHECK(IsDeclaredVariableMode(mode)); |
695 return Declare(zone(), this, name, mode, kind, init_flag, | 695 return Declare(zone(), this, name, mode, kind, init_flag, |
696 maybe_assigned_flag); | 696 maybe_assigned_flag); |
697 } | 697 } |
698 | 698 |
699 Variable* Scope::DeclareVariable( | |
700 Declaration* declaration, VariableMode mode, InitializationFlag init, | |
701 bool allow_harmony_restrictive_generators, | |
702 bool* sloppy_mode_block_scope_function_redefinition, bool* ok) { | |
703 DCHECK(IsDeclaredVariableMode(mode) && mode != CONST_LEGACY); | |
704 DCHECK(!already_resolved_); | |
705 | |
706 if (mode == VAR && !is_declaration_scope()) { | |
707 return GetDeclarationScope()->DeclareVariable( | |
708 declaration, mode, init, allow_harmony_restrictive_generators, | |
709 sloppy_mode_block_scope_function_redefinition, ok); | |
710 } | |
711 DCHECK(!is_catch_scope()); | |
712 DCHECK(!is_with_scope()); | |
713 DCHECK(is_declaration_scope() || | |
714 (IsLexicalVariableMode(mode) && is_block_scope())); | |
715 | |
716 VariableProxy* proxy = declaration->proxy(); | |
717 DCHECK(proxy->raw_name() != NULL); | |
718 const AstRawString* name = proxy->raw_name(); | |
719 bool is_function_declaration = declaration->IsFunctionDeclaration(); | |
720 | |
721 Variable* var = nullptr; | |
722 if (is_eval_scope() && is_sloppy(language_mode()) && mode == VAR) { | |
723 // In a var binding in a sloppy direct eval, pollute the enclosing scope | |
724 // with this new binding by doing the following: | |
725 // The proxy is bound to a lookup variable to force a dynamic declaration | |
726 // using the DeclareEvalVar or DeclareEvalFunction runtime functions. | |
727 Variable::Kind kind = Variable::NORMAL; | |
728 // TODO(sigurds) figure out if kNotAssigned is OK here | |
729 var = new (zone()) Variable(this, name, mode, kind, init, kNotAssigned); | |
730 var->AllocateTo(VariableLocation::LOOKUP, -1); | |
731 } else { | |
732 // Declare the variable in the declaration scope. | |
733 var = LookupLocal(name); | |
734 if (var == NULL) { | |
735 // Declare the name. | |
736 Variable::Kind kind = Variable::NORMAL; | |
737 if (is_function_declaration) { | |
738 kind = Variable::FUNCTION; | |
739 } | |
740 var = DeclareLocal(name, mode, init, kind, kNotAssigned); | |
741 } else if (IsLexicalVariableMode(mode) || | |
742 IsLexicalVariableMode(var->mode())) { | |
743 // Allow duplicate function decls for web compat, see bug 4693. | |
744 bool duplicate_allowed = false; | |
745 if (is_sloppy(language_mode()) && is_function_declaration && | |
746 var->is_function()) { | |
747 DCHECK(IsLexicalVariableMode(mode) && | |
748 IsLexicalVariableMode(var->mode())); | |
749 // If the duplication is allowed, then the var will show up | |
750 // in the SloppyBlockFunctionMap and the new FunctionKind | |
751 // will be a permitted duplicate. | |
752 FunctionKind function_kind = | |
753 declaration->AsFunctionDeclaration()->fun()->kind(); | |
754 duplicate_allowed = | |
755 GetDeclarationScope()->sloppy_block_function_map()->Lookup( | |
756 const_cast<AstRawString*>(name), name->hash()) != nullptr && | |
757 !IsAsyncFunction(function_kind) && | |
758 !(allow_harmony_restrictive_generators && | |
759 IsGeneratorFunction(function_kind)); | |
760 } | |
761 if (duplicate_allowed) { | |
762 *sloppy_mode_block_scope_function_redefinition = true; | |
763 } else { | |
764 // The name was declared in this scope before; check for conflicting | |
adamk
2016/08/30 18:58:32
This comment seems out of place and out of date. M
marja
2016/08/31 07:44:53
Ok, then I won't do anything for it..
| |
765 // re-declarations. We have a conflict if either of the declarations | |
766 // is not a var (in script scope, we also have to ignore legacy const | |
767 // for compatibility). There is similar code in runtime.cc in the | |
768 // Declare functions. The function CheckConflictingVarDeclarations | |
769 // checks for var and let bindings from different scopes whereas this | |
770 // is a check for conflicting declarations within the same scope. This | |
771 // check also covers the special case | |
772 // | |
773 // function () { let x; { var x; } } | |
774 // | |
775 // because the var declaration is hoisted to the function scope where | |
776 // 'x' is already bound. | |
777 DCHECK(IsDeclaredVariableMode(var->mode())); | |
778 // In harmony we treat re-declarations as early errors. See | |
adamk
2016/08/30 18:58:32
This comment is now out of place (it belongs in th
marja
2016/08/31 07:44:53
Hmm, but the decision to set *ok = false is done h
adamk
2016/08/31 18:10:34
Ah, I hadn't thought about it that way. I was thin
| |
779 // ES5 16 for a definition of early errors. | |
780 *ok = false; | |
781 return nullptr; | |
782 } | |
783 } else if (mode == VAR) { | |
784 var->set_maybe_assigned(); | |
785 } | |
786 } | |
787 DCHECK_NOT_NULL(var); | |
788 | |
789 // We add a declaration node for every declaration. The compiler | |
790 // will only generate code if necessary. In particular, declarations | |
791 // for inner local variables that do not represent functions won't | |
792 // result in any generated code. | |
793 // | |
794 // This will lead to multiple declaration nodes for the | |
795 // same variable if it is declared several times. This is not a | |
796 // semantic issue, but it may be a performance issue since it may | |
797 // lead to repeated DeclareEvalVar or DeclareEvalFunction calls. | |
798 decls_.Add(declaration, zone()); | |
799 proxy->BindTo(var); | |
800 return var; | |
801 } | |
802 | |
699 Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name, | 803 Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name, |
700 Variable::Kind kind) { | 804 Variable::Kind kind) { |
701 DCHECK(is_script_scope()); | 805 DCHECK(is_script_scope()); |
702 return variables_.Declare(zone(), this, name, DYNAMIC_GLOBAL, kind, | 806 return variables_.Declare(zone(), this, name, DYNAMIC_GLOBAL, kind, |
703 kCreatedInitialized); | 807 kCreatedInitialized); |
704 } | 808 } |
705 | 809 |
706 | 810 |
707 bool Scope::RemoveUnresolved(VariableProxy* var) { | 811 bool Scope::RemoveUnresolved(VariableProxy* var) { |
708 if (unresolved_ == var) { | 812 if (unresolved_ == var) { |
(...skipping 19 matching lines...) Expand all Loading... | |
728 DeclarationScope* scope = GetClosureScope(); | 832 DeclarationScope* scope = GetClosureScope(); |
729 Variable* var = new(zone()) Variable(scope, | 833 Variable* var = new(zone()) Variable(scope, |
730 name, | 834 name, |
731 TEMPORARY, | 835 TEMPORARY, |
732 Variable::NORMAL, | 836 Variable::NORMAL, |
733 kCreatedInitialized); | 837 kCreatedInitialized); |
734 scope->AddLocal(var); | 838 scope->AddLocal(var); |
735 return var; | 839 return var; |
736 } | 840 } |
737 | 841 |
738 void Scope::AddDeclaration(Declaration* declaration) { | |
739 DCHECK(!already_resolved_); | |
740 decls_.Add(declaration, zone()); | |
741 } | |
742 | |
743 | |
744 Declaration* Scope::CheckConflictingVarDeclarations() { | 842 Declaration* Scope::CheckConflictingVarDeclarations() { |
745 int length = decls_.length(); | 843 int length = decls_.length(); |
746 for (int i = 0; i < length; i++) { | 844 for (int i = 0; i < length; i++) { |
747 Declaration* decl = decls_[i]; | 845 Declaration* decl = decls_[i]; |
748 VariableMode mode = decl->proxy()->var()->mode(); | 846 VariableMode mode = decl->proxy()->var()->mode(); |
749 if (IsLexicalVariableMode(mode) && !is_block_scope()) continue; | 847 if (IsLexicalVariableMode(mode) && !is_block_scope()) continue; |
750 | 848 |
751 // Iterate through all scopes until and including the declaration scope. | 849 // Iterate through all scopes until and including the declaration scope. |
752 Scope* previous = NULL; | 850 Scope* previous = NULL; |
753 Scope* current = decl->scope(); | 851 Scope* current = decl->scope(); |
(...skipping 862 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1616 function != nullptr && function->IsContextSlot(); | 1714 function != nullptr && function->IsContextSlot(); |
1617 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1715 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
1618 (is_function_var_in_context ? 1 : 0); | 1716 (is_function_var_in_context ? 1 : 0); |
1619 } | 1717 } |
1620 | 1718 |
1621 | 1719 |
1622 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1720 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
1623 | 1721 |
1624 } // namespace internal | 1722 } // namespace internal |
1625 } // namespace v8 | 1723 } // namespace v8 |
OLD | NEW |