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/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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |