OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1602 // *var is untouched; in particular, it is the caller's responsibility | 1602 // *var is untouched; in particular, it is the caller's responsibility |
1603 // to initialize it properly. This mechanism is used for the parsing | 1603 // to initialize it properly. This mechanism is used for the parsing |
1604 // of 'for-in' loops. | 1604 // of 'for-in' loops. |
1605 Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context, | 1605 Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context, |
1606 Handle<String>* out, | 1606 Handle<String>* out, |
1607 bool* ok) { | 1607 bool* ok) { |
1608 // VariableDeclarations :: | 1608 // VariableDeclarations :: |
1609 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] | 1609 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] |
1610 | 1610 |
1611 Variable::Mode mode = Variable::VAR; | 1611 Variable::Mode mode = Variable::VAR; |
| 1612 // True if the binding needs initialization. 'let' and 'const' declared |
| 1613 // bindings are created uninitialized by their declaration nodes and |
| 1614 // need initialization. 'var' declared bindings are always initialized |
| 1615 // immediately by their declaration nodes. |
| 1616 bool needs_init = false; |
1612 bool is_const = false; | 1617 bool is_const = false; |
| 1618 Token::Value init_op = Token::INIT_VAR; |
1613 if (peek() == Token::VAR) { | 1619 if (peek() == Token::VAR) { |
1614 Consume(Token::VAR); | 1620 Consume(Token::VAR); |
1615 } else if (peek() == Token::CONST) { | 1621 } else if (peek() == Token::CONST) { |
1616 Consume(Token::CONST); | 1622 Consume(Token::CONST); |
1617 if (top_scope_->is_strict_mode()) { | 1623 if (top_scope_->is_strict_mode()) { |
1618 ReportMessage("strict_const", Vector<const char*>::empty()); | 1624 ReportMessage("strict_const", Vector<const char*>::empty()); |
1619 *ok = false; | 1625 *ok = false; |
1620 return NULL; | 1626 return NULL; |
1621 } | 1627 } |
1622 mode = Variable::CONST; | 1628 mode = Variable::CONST; |
1623 is_const = true; | 1629 is_const = true; |
| 1630 needs_init = true; |
| 1631 init_op = Token::INIT_CONST; |
1624 } else if (peek() == Token::LET) { | 1632 } else if (peek() == Token::LET) { |
1625 Consume(Token::LET); | 1633 Consume(Token::LET); |
1626 if (var_context != kSourceElement && | 1634 if (var_context != kSourceElement && |
1627 var_context != kForStatement) { | 1635 var_context != kForStatement) { |
1628 ASSERT(var_context == kStatement); | 1636 ASSERT(var_context == kStatement); |
1629 ReportMessage("unprotected_let", Vector<const char*>::empty()); | 1637 ReportMessage("unprotected_let", Vector<const char*>::empty()); |
1630 *ok = false; | 1638 *ok = false; |
1631 return NULL; | 1639 return NULL; |
1632 } | 1640 } |
1633 mode = Variable::LET; | 1641 mode = Variable::LET; |
| 1642 needs_init = true; |
| 1643 init_op = Token::INIT_LET; |
1634 } else { | 1644 } else { |
1635 UNREACHABLE(); // by current callers | 1645 UNREACHABLE(); // by current callers |
1636 } | 1646 } |
1637 | 1647 |
1638 Scope* declaration_scope = mode == Variable::LET | 1648 Scope* declaration_scope = mode == Variable::LET |
1639 ? top_scope_ : top_scope_->DeclarationScope(); | 1649 ? top_scope_ : top_scope_->DeclarationScope(); |
1640 // The scope of a var/const declared variable anywhere inside a function | 1650 // The scope of a var/const declared variable anywhere inside a function |
1641 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can | 1651 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can |
1642 // transform a source-level var/const declaration into a (Function) | 1652 // transform a source-level var/const declaration into a (Function) |
1643 // Scope declaration, and rewrite the source-level initialization into an | 1653 // Scope declaration, and rewrite the source-level initialization into an |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1725 position = scanner().location().beg_pos; | 1735 position = scanner().location().beg_pos; |
1726 value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); | 1736 value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); |
1727 // Don't infer if it is "a = function(){...}();"-like expression. | 1737 // Don't infer if it is "a = function(){...}();"-like expression. |
1728 if (fni_ != NULL && | 1738 if (fni_ != NULL && |
1729 value->AsCall() == NULL && | 1739 value->AsCall() == NULL && |
1730 value->AsCallNew() == NULL) { | 1740 value->AsCallNew() == NULL) { |
1731 fni_->Infer(); | 1741 fni_->Infer(); |
1732 } | 1742 } |
1733 } | 1743 } |
1734 | 1744 |
1735 // Make sure that 'const c' actually initializes 'c' to undefined | 1745 // Make sure that 'const x' and 'let x' initialize 'x' to undefined. |
1736 // even though it seems like a stupid thing to do. | 1746 if (value == NULL && needs_init) { |
1737 if (value == NULL && is_const) { | |
1738 value = GetLiteralUndefined(); | 1747 value = GetLiteralUndefined(); |
1739 } | 1748 } |
1740 | 1749 |
1741 // Global variable declarations must be compiled in a specific | 1750 // Global variable declarations must be compiled in a specific |
1742 // way. When the script containing the global variable declaration | 1751 // way. When the script containing the global variable declaration |
1743 // is entered, the global variable must be declared, so that if it | 1752 // is entered, the global variable must be declared, so that if it |
1744 // doesn't exist (not even in a prototype of the global object) it | 1753 // doesn't exist (not even in a prototype of the global object) it |
1745 // gets created with an initial undefined value. This is handled | 1754 // gets created with an initial undefined value. This is handled |
1746 // by the declarations part of the function representing the | 1755 // by the declarations part of the function representing the |
1747 // top-level global code; see Runtime::DeclareGlobalVariable. If | 1756 // top-level global code; see Runtime::DeclareGlobalVariable. If |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1815 // we still have a pending initialization value. We must distinguish | 1824 // we still have a pending initialization value. We must distinguish |
1816 // between variables and constants: Variable initializations are simply | 1825 // between variables and constants: Variable initializations are simply |
1817 // assignments (with all the consequences if they are inside a 'with' | 1826 // assignments (with all the consequences if they are inside a 'with' |
1818 // statement - they may change a 'with' object property). Constant | 1827 // statement - they may change a 'with' object property). Constant |
1819 // initializations always assign to the declared constant which is | 1828 // initializations always assign to the declared constant which is |
1820 // always at the function scope level. This is only relevant for | 1829 // always at the function scope level. This is only relevant for |
1821 // dynamically looked-up variables and constants (the start context | 1830 // dynamically looked-up variables and constants (the start context |
1822 // for constant lookups is always the function context, while it is | 1831 // for constant lookups is always the function context, while it is |
1823 // the top context for variables). Sigh... | 1832 // the top context for variables). Sigh... |
1824 if (value != NULL) { | 1833 if (value != NULL) { |
1825 Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR); | |
1826 bool in_with = is_const ? false : inside_with(); | 1834 bool in_with = is_const ? false : inside_with(); |
1827 VariableProxy* proxy = | 1835 VariableProxy* proxy = |
1828 initialization_scope->NewUnresolved(name, in_with); | 1836 initialization_scope->NewUnresolved(name, in_with); |
1829 Assignment* assignment = | 1837 Assignment* assignment = |
1830 new(zone()) Assignment(isolate(), op, proxy, value, position); | 1838 new(zone()) Assignment(isolate(), init_op, proxy, value, position); |
1831 if (block) { | 1839 if (block) { |
1832 block->AddStatement(new(zone()) ExpressionStatement(assignment)); | 1840 block->AddStatement(new(zone()) ExpressionStatement(assignment)); |
1833 } | 1841 } |
1834 } | 1842 } |
1835 | 1843 |
1836 if (fni_ != NULL) fni_->Leave(); | 1844 if (fni_ != NULL) fni_->Leave(); |
1837 } while (peek() == Token::COMMA); | 1845 } while (peek() == Token::COMMA); |
1838 | 1846 |
1839 // If there was a single non-const declaration, return it in the output | 1847 // If there was a single non-const declaration, return it in the output |
1840 // parameter for possible use by for/in. | 1848 // parameter for possible use by for/in. |
(...skipping 3334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5175 result = parser.ParseProgram(source, | 5183 result = parser.ParseProgram(source, |
5176 info->is_global(), | 5184 info->is_global(), |
5177 info->StrictMode()); | 5185 info->StrictMode()); |
5178 } | 5186 } |
5179 } | 5187 } |
5180 info->SetFunction(result); | 5188 info->SetFunction(result); |
5181 return (result != NULL); | 5189 return (result != NULL); |
5182 } | 5190 } |
5183 | 5191 |
5184 } } // namespace v8::internal | 5192 } } // namespace v8::internal |
OLD | NEW |