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

Side by Side Diff: src/parsing/parser.cc

Issue 2280033002: Move Parser::Declare to Scope. (Closed)
Patch Set: code review (verwaest@) Created 4 years, 3 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
« src/ast/scopes.cc ('K') | « src/ast/scopes.cc ('k') | no next file » | 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/parsing/parser.h" 5 #include "src/parsing/parser.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/ast/ast-expression-rewriter.h" 10 #include "src/ast/ast-expression-rewriter.h"
(...skipping 1656 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 Declaration* declaration = 1667 Declaration* declaration =
1668 factory()->NewVariableDeclaration(proxy, this->scope(), pos); 1668 factory()->NewVariableDeclaration(proxy, this->scope(), pos);
1669 Declare(declaration, DeclarationDescriptor::NORMAL, mode, init, CHECK_OK); 1669 Declare(declaration, DeclarationDescriptor::NORMAL, mode, init, CHECK_OK);
1670 return declaration; 1670 return declaration;
1671 } 1671 }
1672 1672
1673 Variable* Parser::Declare(Declaration* declaration, 1673 Variable* Parser::Declare(Declaration* declaration,
1674 DeclarationDescriptor::Kind declaration_kind, 1674 DeclarationDescriptor::Kind declaration_kind,
1675 VariableMode mode, InitializationFlag init, bool* ok, 1675 VariableMode mode, InitializationFlag init, bool* ok,
1676 Scope* scope) { 1676 Scope* scope) {
1677 DCHECK(IsDeclaredVariableMode(mode) && mode != CONST_LEGACY); 1677 if (scope == nullptr) {
1678 1678 scope = this->scope();
1679 VariableProxy* proxy = declaration->proxy(); 1679 }
1680 DCHECK(proxy->raw_name() != NULL); 1680 bool sloppy_mode_block_scope_function_redefinition = false;
1681 const AstRawString* name = proxy->raw_name(); 1681 Variable* variable = scope->DeclareVariable(
1682 1682 declaration, mode, init, allow_harmony_restrictive_generators(),
1683 if (scope == nullptr) scope = this->scope(); 1683 &sloppy_mode_block_scope_function_redefinition, ok);
1684 if (mode == VAR) scope = scope->GetDeclarationScope(); 1684 if (!*ok) {
1685 DCHECK(!scope->is_catch_scope()); 1685 if (declaration_kind == DeclarationDescriptor::NORMAL) {
1686 DCHECK(!scope->is_with_scope()); 1686 ReportMessage(MessageTemplate::kVarRedeclaration,
1687 DCHECK(scope->is_declaration_scope() || 1687 declaration->proxy()->raw_name());
1688 (IsLexicalVariableMode(mode) && scope->is_block_scope())); 1688 } else {
1689 1689 ReportMessage(MessageTemplate::kParamDupe);
1690 bool is_function_declaration = declaration->IsFunctionDeclaration();
1691
1692 Variable* var = NULL;
1693 if (scope->is_eval_scope() && is_sloppy(scope->language_mode()) &&
1694 mode == VAR) {
1695 // In a var binding in a sloppy direct eval, pollute the enclosing scope
1696 // with this new binding by doing the following:
1697 // The proxy is bound to a lookup variable to force a dynamic declaration
1698 // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
1699 Variable::Kind kind = Variable::NORMAL;
1700 // TODO(sigurds) figure out if kNotAssigned is OK here
1701 var = new (zone()) Variable(scope, name, mode, kind, init, kNotAssigned);
1702 var->AllocateTo(VariableLocation::LOOKUP, -1);
1703 } else {
1704 // Declare the variable in the declaration scope.
1705 var = scope->LookupLocal(name);
1706 if (var == NULL) {
1707 // Declare the name.
1708 Variable::Kind kind = Variable::NORMAL;
1709 if (is_function_declaration) {
1710 kind = Variable::FUNCTION;
1711 }
1712 var = scope->DeclareLocal(name, mode, init, kind, kNotAssigned);
1713 } else if (IsLexicalVariableMode(mode) ||
1714 IsLexicalVariableMode(var->mode())) {
1715 // Allow duplicate function decls for web compat, see bug 4693.
1716 bool duplicate_allowed = false;
1717 if (is_sloppy(scope->language_mode()) && is_function_declaration &&
1718 var->is_function()) {
1719 DCHECK(IsLexicalVariableMode(mode) &&
1720 IsLexicalVariableMode(var->mode()));
1721 // If the duplication is allowed, then the var will show up
1722 // in the SloppyBlockFunctionMap and the new FunctionKind
1723 // will be a permitted duplicate.
1724 FunctionKind function_kind =
1725 declaration->AsFunctionDeclaration()->fun()->kind();
1726 duplicate_allowed =
1727 scope->GetDeclarationScope()->sloppy_block_function_map()->Lookup(
1728 const_cast<AstRawString*>(name), name->hash()) != nullptr &&
1729 !IsAsyncFunction(function_kind) &&
1730 !(allow_harmony_restrictive_generators() &&
1731 IsGeneratorFunction(function_kind));
1732 }
1733 if (duplicate_allowed) {
1734 ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition];
1735 } else {
1736 // The name was declared in this scope before; check for conflicting
1737 // re-declarations. We have a conflict if either of the declarations
1738 // is not a var (in script scope, we also have to ignore legacy const
1739 // for compatibility). There is similar code in runtime.cc in the
1740 // Declare functions. The function CheckConflictingVarDeclarations
1741 // checks for var and let bindings from different scopes whereas this
1742 // is a check for conflicting declarations within the same scope. This
1743 // check also covers the special case
1744 //
1745 // function () { let x; { var x; } }
1746 //
1747 // because the var declaration is hoisted to the function scope where
1748 // 'x' is already bound.
1749 DCHECK(IsDeclaredVariableMode(var->mode()));
1750 // In harmony we treat re-declarations as early errors. See
1751 // ES5 16 for a definition of early errors.
1752 if (declaration_kind == DeclarationDescriptor::NORMAL) {
1753 ReportMessage(MessageTemplate::kVarRedeclaration, name);
1754 } else {
1755 ReportMessage(MessageTemplate::kParamDupe);
1756 }
1757 *ok = false;
1758 return nullptr;
1759 }
1760 } else if (mode == VAR) {
1761 var->set_maybe_assigned();
1762 } 1690 }
adamk 2016/08/30 18:58:32 I'd prefer if there was an explicit "return nullpt
marja 2016/08/31 07:44:53 Ah, true, it's definitely good to return nullptr h
1763 } 1691 }
1764 DCHECK_NOT_NULL(var); 1692 if (sloppy_mode_block_scope_function_redefinition) {
1765 1693 ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition];
1766 // We add a declaration node for every declaration. The compiler 1694 }
1767 // will only generate code if necessary. In particular, declarations 1695 return variable;
1768 // for inner local variables that do not represent functions won't
1769 // result in any generated code.
1770 //
1771 // This will lead to multiple declaration nodes for the
1772 // same variable if it is declared several times. This is not a
1773 // semantic issue, but it may be a performance issue since it may
1774 // lead to repeated DeclareEvalVar or DeclareEvalFunction calls.
1775 scope->AddDeclaration(declaration);
1776 proxy->BindTo(var);
1777 return var;
1778 } 1696 }
1779 1697
1780
1781 // Language extension which is only enabled for source files loaded 1698 // Language extension which is only enabled for source files loaded
1782 // through the API's extension mechanism. A native function 1699 // through the API's extension mechanism. A native function
1783 // declaration is resolved by looking up the function through a 1700 // declaration is resolved by looking up the function through a
1784 // callback provided by the extension. 1701 // callback provided by the extension.
1785 Statement* Parser::ParseNativeDeclaration(bool* ok) { 1702 Statement* Parser::ParseNativeDeclaration(bool* ok) {
1786 int pos = peek_position(); 1703 int pos = peek_position();
1787 Expect(Token::FUNCTION, CHECK_OK); 1704 Expect(Token::FUNCTION, CHECK_OK);
1788 // Allow "eval" or "arguments" for backward compatibility. 1705 // Allow "eval" or "arguments" for backward compatibility.
1789 const AstRawString* name = 1706 const AstRawString* name =
1790 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); 1707 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
(...skipping 3246 matching lines...) Expand 10 before | Expand all | Expand 10 after
5037 if (!should_hoist) continue; 4954 if (!should_hoist) continue;
5038 4955
5039 // Declare a var-style binding for the function in the outer scope 4956 // Declare a var-style binding for the function in the outer scope
5040 if (!var_created) { 4957 if (!var_created) {
5041 var_created = true; 4958 var_created = true;
5042 VariableProxy* proxy = scope->NewUnresolved(factory(), name); 4959 VariableProxy* proxy = scope->NewUnresolved(factory(), name);
5043 Declaration* declaration = 4960 Declaration* declaration =
5044 factory()->NewVariableDeclaration(proxy, scope, kNoSourcePosition); 4961 factory()->NewVariableDeclaration(proxy, scope, kNoSourcePosition);
5045 Declare(declaration, DeclarationDescriptor::NORMAL, VAR, 4962 Declare(declaration, DeclarationDescriptor::NORMAL, VAR,
5046 DefaultInitializationFlag(VAR), ok, scope); 4963 DefaultInitializationFlag(VAR), ok, scope);
5047 DCHECK(ok); // Based on the preceding check, this should not fail 4964 DCHECK(*ok); // Based on the preceding check, this should not fail
5048 if (!ok) return; 4965 if (!*ok) return;
5049 } 4966 }
5050 4967
5051 // Read from the local lexical scope and write to the function scope 4968 // Read from the local lexical scope and write to the function scope
5052 VariableProxy* to = scope->NewUnresolved(factory(), name); 4969 VariableProxy* to = scope->NewUnresolved(factory(), name);
5053 VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name); 4970 VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name);
5054 Expression* assignment = 4971 Expression* assignment =
5055 factory()->NewAssignment(Token::ASSIGN, to, from, kNoSourcePosition); 4972 factory()->NewAssignment(Token::ASSIGN, to, from, kNoSourcePosition);
5056 Statement* statement = 4973 Statement* statement =
5057 factory()->NewExpressionStatement(assignment, kNoSourcePosition); 4974 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
5058 delegate->set_statement(statement); 4975 delegate->set_statement(statement);
(...skipping 1682 matching lines...) Expand 10 before | Expand all | Expand 10 after
6741 node->Print(Isolate::Current()); 6658 node->Print(Isolate::Current());
6742 } 6659 }
6743 #endif // DEBUG 6660 #endif // DEBUG
6744 6661
6745 #undef CHECK_OK 6662 #undef CHECK_OK
6746 #undef CHECK_OK_VOID 6663 #undef CHECK_OK_VOID
6747 #undef CHECK_FAILED 6664 #undef CHECK_FAILED
6748 6665
6749 } // namespace internal 6666 } // namespace internal
6750 } // namespace v8 6667 } // namespace v8
OLDNEW
« src/ast/scopes.cc ('K') | « src/ast/scopes.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698