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 |