Chromium Code Reviews| 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 1123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1134 Statement* Parser::ParseSourceElement(ZoneStringList* labels, | 1134 Statement* Parser::ParseSourceElement(ZoneStringList* labels, |
| 1135 bool* ok) { | 1135 bool* ok) { |
| 1136 // (Ecma 262 5th Edition, clause 14): | 1136 // (Ecma 262 5th Edition, clause 14): |
| 1137 // SourceElement: | 1137 // SourceElement: |
| 1138 // Statement | 1138 // Statement |
| 1139 // FunctionDeclaration | 1139 // FunctionDeclaration |
| 1140 // | 1140 // |
| 1141 // In harmony mode we allow additionally the following productions | 1141 // In harmony mode we allow additionally the following productions |
| 1142 // SourceElement: | 1142 // SourceElement: |
| 1143 // LetDeclaration | 1143 // LetDeclaration |
| 1144 // ConstDeclaration | |
| 1144 | 1145 |
| 1145 if (peek() == Token::FUNCTION) { | 1146 if (peek() == Token::FUNCTION) { |
| 1146 return ParseFunctionDeclaration(ok); | 1147 return ParseFunctionDeclaration(ok); |
| 1147 } else if (peek() == Token::LET) { | 1148 } else if (peek() == Token::LET) { |
| 1148 return ParseVariableStatement(kSourceElement, ok); | 1149 return ParseVariableStatement(kSourceElement, ok); |
| 1149 } else { | 1150 } else if (peek() == Token::CONST && harmony_scoping_) { |
| 1150 return ParseStatement(labels, ok); | 1151 return ParseHarmonyConstDeclaration(ok); |
| 1151 } | 1152 } |
| 1153 return ParseStatement(labels, ok); | |
| 1152 } | 1154 } |
| 1153 | 1155 |
| 1154 | 1156 |
| 1155 void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, | 1157 void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, |
| 1156 int end_token, | 1158 int end_token, |
| 1157 bool* ok) { | 1159 bool* ok) { |
| 1158 // SourceElements :: | 1160 // SourceElements :: |
| 1159 // (SourceElement)* <end_token> | 1161 // (SourceElement)* <end_token> |
| 1160 | 1162 |
| 1161 // Allocate a target stack to use for this set of source | 1163 // Allocate a target stack to use for this set of source |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1359 | 1361 |
| 1360 VariableProxy* Parser::Declare(Handle<String> name, | 1362 VariableProxy* Parser::Declare(Handle<String> name, |
| 1361 VariableMode mode, | 1363 VariableMode mode, |
| 1362 FunctionLiteral* fun, | 1364 FunctionLiteral* fun, |
| 1363 bool resolve, | 1365 bool resolve, |
| 1364 bool* ok) { | 1366 bool* ok) { |
| 1365 Variable* var = NULL; | 1367 Variable* var = NULL; |
| 1366 // If we are inside a function, a declaration of a var/const variable is a | 1368 // If we are inside a function, a declaration of a var/const variable is a |
| 1367 // truly local variable, and the scope of the variable is always the function | 1369 // truly local variable, and the scope of the variable is always the function |
| 1368 // scope. | 1370 // scope. |
| 1371 // Let/const variables in harmony mode are always added to the immediately | |
| 1372 // enclosing scope. | |
| 1373 Scope* declaration_scope = mode == LET || mode == CONST_HARMONY | |
| 1374 ? top_scope_ : top_scope_->DeclarationScope(); | |
| 1369 | 1375 |
| 1370 // If a function scope exists, then we can statically declare this | 1376 // If a function scope exists, then we can statically declare this |
| 1371 // variable and also set its mode. In any case, a Declaration node | 1377 // variable and also set its mode. In any case, a Declaration node |
| 1372 // will be added to the scope so that the declaration can be added | 1378 // will be added to the scope so that the declaration can be added |
| 1373 // to the corresponding activation frame at runtime if necessary. | 1379 // to the corresponding activation frame at runtime if necessary. |
| 1374 // For instance declarations inside an eval scope need to be added | 1380 // For instance declarations inside an eval scope need to be added |
| 1375 // to the calling function context. | 1381 // to the calling function context. |
| 1376 // Similarly, strict mode eval scope does not leak variable declarations to | 1382 // Similarly, strict mode eval scope does not leak variable declarations to |
| 1377 // the caller's scope so we declare all locals, too. | 1383 // the caller's scope so we declare all locals, too. |
| 1378 | 1384 // Also for block scoped let/const bindings the variable can be |
| 1379 Scope* declaration_scope = mode == LET ? top_scope_ | 1385 // statically declared. |
| 1380 : top_scope_->DeclarationScope(); | |
| 1381 if (declaration_scope->is_function_scope() || | 1386 if (declaration_scope->is_function_scope() || |
| 1382 declaration_scope->is_strict_mode_eval_scope() || | 1387 declaration_scope->is_strict_mode_eval_scope() || |
| 1383 declaration_scope->is_block_scope()) { | 1388 declaration_scope->is_block_scope()) { |
| 1384 // Declare the variable in the function scope. | 1389 // Declare the variable in the function scope. |
| 1385 var = declaration_scope->LocalLookup(name); | 1390 var = declaration_scope->LocalLookup(name); |
| 1386 if (var == NULL) { | 1391 if (var == NULL) { |
| 1387 // Declare the name. | 1392 // Declare the name. |
| 1388 var = declaration_scope->DeclareLocal(name, mode); | 1393 var = declaration_scope->DeclareLocal(name, mode); |
| 1389 } else { | 1394 } else { |
| 1390 // The name was declared in this scope before; check for conflicting | 1395 // The name was declared in this scope before; check for conflicting |
| 1391 // re-declarations. We have a conflict if either of the declarations is | 1396 // re-declarations. We have a conflict if either of the declarations is |
| 1392 // not a var. There is similar code in runtime.cc in the Declare | 1397 // not a var. There is similar code in runtime.cc in the Declare |
| 1393 // functions. The function CheckNonConflictingScope checks for conflicting | 1398 // functions. The function CheckNonConflictingScope checks for conflicting |
| 1394 // var and let bindings from different scopes whereas this is a check for | 1399 // var and let bindings from different scopes whereas this is a check for |
| 1395 // conflicting declarations within the same scope. This check also covers | 1400 // conflicting declarations within the same scope. This check also covers |
| 1396 // | 1401 // |
| 1397 // function () { let x; { var x; } } | 1402 // function () { let x; { var x; } } |
| 1398 // | 1403 // |
| 1399 // because the var declaration is hoisted to the function scope where 'x' | 1404 // because the var declaration is hoisted to the function scope where 'x' |
| 1400 // is already bound. | 1405 // is already bound. |
| 1401 if ((mode != VAR) || (var->mode() != VAR)) { | 1406 if ((mode != VAR) || (var->mode() != VAR)) { |
| 1402 // We only have vars, consts and lets in declarations. | 1407 // We only have vars, consts and lets in declarations. |
| 1403 ASSERT(var->mode() == VAR || | 1408 ASSERT(var->mode() == VAR || |
| 1404 var->mode() == CONST || | 1409 var->mode() == CONST || |
| 1410 var->mode() == CONST_HARMONY || | |
| 1405 var->mode() == LET); | 1411 var->mode() == LET); |
| 1406 if (harmony_scoping_) { | 1412 if (harmony_scoping_) { |
| 1407 // In harmony mode we treat re-declarations as early errors. See | 1413 // In harmony mode we treat re-declarations as early errors. See |
| 1408 // ES5 16 for a definition of early errors. | 1414 // ES5 16 for a definition of early errors. |
| 1409 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS); | 1415 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS); |
| 1410 const char* elms[2] = { "Variable", *c_string }; | 1416 const char* elms[2] = { "Variable", *c_string }; |
| 1411 Vector<const char*> args(elms, 2); | 1417 Vector<const char*> args(elms, 2); |
| 1412 ReportMessage("redeclaration", args); | 1418 ReportMessage("redeclaration", args); |
| 1413 *ok = false; | 1419 *ok = false; |
| 1414 return NULL; | 1420 return NULL; |
| 1415 } | 1421 } |
| 1416 const char* type = (var->mode() == VAR) ? "var" : | 1422 const char* type = (var->mode() == VAR) |
| 1417 (var->mode() == CONST) ? "const" : "let"; | 1423 ? "var" : var->is_const_mode() ? "const" : "let"; |
| 1418 Handle<String> type_string = | 1424 Handle<String> type_string = |
| 1419 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED); | 1425 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED); |
| 1420 Expression* expression = | 1426 Expression* expression = |
| 1421 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(), | 1427 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(), |
| 1422 type_string, name); | 1428 type_string, name); |
| 1423 declaration_scope->SetIllegalRedeclaration(expression); | 1429 declaration_scope->SetIllegalRedeclaration(expression); |
| 1424 } | 1430 } |
| 1425 } | 1431 } |
| 1426 } | 1432 } |
| 1427 | 1433 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1440 // same variable if it is declared several times. This is not a | 1446 // same variable if it is declared several times. This is not a |
| 1441 // semantic issue as long as we keep the source order, but it may be | 1447 // semantic issue as long as we keep the source order, but it may be |
| 1442 // a performance issue since it may lead to repeated | 1448 // a performance issue since it may lead to repeated |
| 1443 // Runtime::DeclareContextSlot() calls. | 1449 // Runtime::DeclareContextSlot() calls. |
| 1444 VariableProxy* proxy = declaration_scope->NewUnresolved( | 1450 VariableProxy* proxy = declaration_scope->NewUnresolved( |
| 1445 name, scanner().location().beg_pos); | 1451 name, scanner().location().beg_pos); |
| 1446 declaration_scope->AddDeclaration( | 1452 declaration_scope->AddDeclaration( |
| 1447 new(zone()) Declaration(proxy, mode, fun, top_scope_)); | 1453 new(zone()) Declaration(proxy, mode, fun, top_scope_)); |
| 1448 | 1454 |
| 1449 // For global const variables we bind the proxy to a variable. | 1455 // For global const variables we bind the proxy to a variable. |
| 1450 if (mode == CONST && declaration_scope->is_global_scope()) { | 1456 if ((mode == CONST || mode == CONST_HARMONY) && |
| 1457 declaration_scope->is_global_scope()) { | |
| 1451 ASSERT(resolve); // should be set by all callers | 1458 ASSERT(resolve); // should be set by all callers |
| 1452 Variable::Kind kind = Variable::NORMAL; | 1459 Variable::Kind kind = Variable::NORMAL; |
| 1453 var = new(zone()) Variable(declaration_scope, name, CONST, true, kind); | 1460 var = new(zone()) Variable(declaration_scope, name, CONST, true, kind); |
| 1454 } | 1461 } |
| 1455 | 1462 |
| 1456 // If requested and we have a local variable, bind the proxy to the variable | 1463 // If requested and we have a local variable, bind the proxy to the variable |
| 1457 // at parse-time. This is used for functions (and consts) declared inside | 1464 // at parse-time. This is used for functions (and consts) declared inside |
| 1458 // statements: the corresponding function (or const) variable must be in the | 1465 // statements: the corresponding function (or const) variable must be in the |
| 1459 // function scope and not a statement-local scope, e.g. as provided with a | 1466 // function scope and not a statement-local scope, e.g. as provided with a |
| 1460 // 'with' statement: | 1467 // 'with' statement: |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1638 return result; | 1645 return result; |
| 1639 } | 1646 } |
| 1640 | 1647 |
| 1641 | 1648 |
| 1642 bool Parser::IsEvalOrArguments(Handle<String> string) { | 1649 bool Parser::IsEvalOrArguments(Handle<String> string) { |
| 1643 return string.is_identical_to(isolate()->factory()->eval_symbol()) || | 1650 return string.is_identical_to(isolate()->factory()->eval_symbol()) || |
| 1644 string.is_identical_to(isolate()->factory()->arguments_symbol()); | 1651 string.is_identical_to(isolate()->factory()->arguments_symbol()); |
| 1645 } | 1652 } |
| 1646 | 1653 |
| 1647 | 1654 |
| 1655 Block* Parser::ParseHarmonyConstDeclaration(bool* ok) { | |
| 1656 // ES6 Draft Rev3 | |
| 1657 // | |
| 1658 // ConstDeclaration :: | |
| 1659 // const ConstBinding (',' ConstBinding)* ';' | |
| 1660 // ConstBinding :: | |
| 1661 // Identifier '=' AssignmentExpression | |
| 1662 // | |
| 1663 // TODO(ES6): | |
| 1664 // ConstBinding :: | |
| 1665 // BindingPattern '=' AssignmentExpression | |
| 1666 | |
| 1667 Consume(Token::CONST); | |
| 1668 | |
| 1669 // A block is used to collect the initialization assignments and it | |
| 1670 // is marked as an initializer block to prevent the rewriter from | |
| 1671 // adding a '.result' assignment to such a block. | |
| 1672 // | |
| 1673 // Create new block with one expected declaration. | |
| 1674 Block* block = new(zone()) Block(isolate(), NULL, 1, true); | |
| 1675 Handle<String> name; | |
| 1676 do { | |
| 1677 if (fni_ != NULL) fni_->Enter(); | |
| 1678 | |
| 1679 // Parse variable name. | |
| 1680 name = ParseIdentifier(CHECK_OK); | |
| 1681 if (fni_ != NULL) fni_->PushVariableName(name); | |
| 1682 | |
| 1683 // Strict mode variables may not be named eval or arguments | |
| 1684 if (IsEvalOrArguments(name)) { | |
| 1685 ReportMessage("strict_var_name", Vector<const char*>::empty()); | |
| 1686 *ok = false; | |
| 1687 return NULL; | |
| 1688 } | |
| 1689 | |
| 1690 // Declare the variable. The proxy can always be pre-resolved to the | |
| 1691 // declared variable, because it resides in the same scope as the | |
| 1692 // declaration. | |
| 1693 VariableProxy* proxy = Declare(name, CONST_HARMONY, NULL, true, CHECK_OK); | |
| 1694 if (top_scope_->num_var_or_const() > kMaxNumFunctionLocals) { | |
|
fschneider
2011/10/21 09:19:40
This function contains a lot of duplicated code. C
Steven
2011/10/24 09:37:55
Done. Was actually easier than I thought to add it
| |
| 1695 ReportMessageAt(scanner().location(), "too_many_variables", | |
| 1696 Vector<const char*>::empty()); | |
| 1697 *ok = false; | |
| 1698 return NULL; | |
| 1699 } | |
| 1700 | |
| 1701 // Parse initialiser. | |
| 1702 Expression* value = NULL; | |
| 1703 Expect(Token::ASSIGN, CHECK_OK); | |
| 1704 int position = scanner().location().beg_pos; | |
| 1705 value = ParseAssignmentExpression(false, CHECK_OK); | |
| 1706 | |
| 1707 // Don't infer if it is "a = function(){...}();"-like expression. | |
| 1708 if (fni_ != NULL && value->AsCall() == NULL && value->AsCallNew() == NULL) { | |
| 1709 fni_->Infer(); | |
| 1710 } | |
| 1711 | |
| 1712 // Global variable declarations must be compiled in a specific | |
| 1713 // way. When the script containing the global variable declaration | |
| 1714 // is entered, the global variable must be declared, so that if it | |
| 1715 // doesn't exist (not even in a prototype of the global object) it | |
| 1716 // gets created with an initial undefined value. This is handled | |
| 1717 // by the declarations part of the function representing the | |
| 1718 // top-level global code; see Runtime::DeclareGlobals. If | |
| 1719 // it already exists (in the object or in a prototype), it is | |
| 1720 // *not* touched until the variable declaration statement is | |
| 1721 // executed. | |
| 1722 // | |
| 1723 // Executing the variable declaration statement will always | |
| 1724 // guarantee to give the global object a "local" variable; a | |
| 1725 // variable defined in the global object and not in any | |
| 1726 // prototype. This way, global variable declarations can shadow | |
| 1727 // properties in the prototype chain, but only after the variable | |
| 1728 // declaration statement has been executed. This is important in | |
| 1729 // browsers where the global object (window) has lots of | |
| 1730 // properties defined in prototype objects. | |
| 1731 if (top_scope_->is_global_scope()) { | |
| 1732 // Compute the arguments for the runtime call. | |
| 1733 ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3); | |
| 1734 // We have at least 1 parameter. | |
| 1735 arguments->Add(NewLiteral(name)); | |
| 1736 arguments->Add(value); | |
| 1737 | |
| 1738 // Construct the call to Runtime_InitializeConstGlobal | |
| 1739 // and add it to the initialization statement block. | |
| 1740 CallRuntime* initialize = | |
| 1741 new(zone()) CallRuntime( | |
| 1742 isolate(), | |
| 1743 isolate()->factory()->InitializeConstGlobal_symbol(), | |
| 1744 Runtime::FunctionForId(Runtime::kInitializeConstGlobal), | |
| 1745 arguments); | |
| 1746 | |
| 1747 block->AddStatement(new(zone()) ExpressionStatement(initialize)); | |
| 1748 } else { | |
| 1749 // Add an assignment node for the initializations to the initialization | |
| 1750 // statement block. | |
| 1751 Assignment* assignment = new(zone()) Assignment( | |
| 1752 isolate(), Token::INIT_CONST_HARMONY, proxy, value, position); | |
| 1753 block->AddStatement(new(zone()) ExpressionStatement(assignment)); | |
| 1754 } | |
| 1755 if (fni_ != NULL) fni_->Leave(); | |
| 1756 } while (Check(Token::COMMA)); | |
| 1757 | |
| 1758 ExpectSemicolon(CHECK_OK); | |
| 1759 return block; | |
| 1760 } | |
| 1761 | |
| 1762 | |
| 1648 // If the variable declaration declares exactly one non-const | 1763 // If the variable declaration declares exactly one non-const |
| 1649 // variable, then *var is set to that variable. In all other cases, | 1764 // variable, then *var is set to that variable. In all other cases, |
| 1650 // *var is untouched; in particular, it is the caller's responsibility | 1765 // *var is untouched; in particular, it is the caller's responsibility |
| 1651 // to initialize it properly. This mechanism is used for the parsing | 1766 // to initialize it properly. This mechanism is used for the parsing |
| 1652 // of 'for-in' loops. | 1767 // of 'for-in' loops. |
| 1653 Block* Parser::ParseVariableDeclarations( | 1768 Block* Parser::ParseVariableDeclarations( |
| 1654 VariableDeclarationContext var_context, | 1769 VariableDeclarationContext var_context, |
| 1655 VariableDeclarationProperties* decl_props, | 1770 VariableDeclarationProperties* decl_props, |
| 1656 Handle<String>* out, | 1771 Handle<String>* out, |
| 1657 bool* ok) { | 1772 bool* ok) { |
| 1658 // VariableDeclarations :: | 1773 // VariableDeclarations :: |
| 1659 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] | 1774 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] |
| 1660 | 1775 |
| 1661 VariableMode mode = VAR; | 1776 VariableMode mode = VAR; |
| 1662 // True if the binding needs initialization. 'let' and 'const' declared | 1777 // True if the binding needs initialization. 'let' and 'const' declared |
| 1663 // bindings are created uninitialized by their declaration nodes and | 1778 // bindings are created uninitialized by their declaration nodes and |
| 1664 // need initialization. 'var' declared bindings are always initialized | 1779 // need initialization. 'var' declared bindings are always initialized |
| 1665 // immediately by their declaration nodes. | 1780 // immediately by their declaration nodes. |
| 1666 bool needs_init = false; | 1781 bool needs_init = false; |
| 1667 bool is_const = false; | 1782 bool is_const = false; |
| 1668 Token::Value init_op = Token::INIT_VAR; | 1783 Token::Value init_op = Token::INIT_VAR; |
| 1669 if (peek() == Token::VAR) { | 1784 if (peek() == Token::VAR) { |
| 1670 Consume(Token::VAR); | 1785 Consume(Token::VAR); |
| 1671 } else if (peek() == Token::CONST) { | 1786 } else if (peek() == Token::CONST) { |
| 1672 Consume(Token::CONST); | 1787 Consume(Token::CONST); |
| 1788 if (harmony_scoping_) { | |
| 1789 ASSERT(var_context == kForStatement || | |
| 1790 var_context == kStatement); | |
| 1791 // In harmony mode 'const' declarations are only allowed in source | |
| 1792 // element positions and that is handled by ParseHarmonyConstDeclaration. | |
| 1793 ReportMessage("unprotected_const", Vector<const char*>::empty()); | |
| 1794 *ok = false; | |
| 1795 return NULL; | |
| 1796 } | |
| 1673 if (top_scope_->is_strict_mode()) { | 1797 if (top_scope_->is_strict_mode()) { |
| 1674 ReportMessage("strict_const", Vector<const char*>::empty()); | 1798 ReportMessage("strict_const", Vector<const char*>::empty()); |
| 1675 *ok = false; | 1799 *ok = false; |
| 1676 return NULL; | 1800 return NULL; |
| 1677 } | 1801 } |
| 1678 mode = CONST; | 1802 mode = CONST; |
| 1679 is_const = true; | 1803 is_const = true; |
| 1680 needs_init = true; | 1804 needs_init = true; |
| 1681 init_op = Token::INIT_CONST; | 1805 init_op = Token::INIT_CONST; |
| 1682 } else if (peek() == Token::LET) { | 1806 } else if (peek() == Token::LET) { |
| 1683 Consume(Token::LET); | 1807 Consume(Token::LET); |
| 1684 if (var_context != kSourceElement && | 1808 if (var_context != kSourceElement && |
| 1685 var_context != kForStatement) { | 1809 var_context != kForStatement) { |
| 1810 // Let declarations are only allowed in source element positions. | |
| 1686 ASSERT(var_context == kStatement); | 1811 ASSERT(var_context == kStatement); |
| 1687 ReportMessage("unprotected_let", Vector<const char*>::empty()); | 1812 ReportMessage("unprotected_let", Vector<const char*>::empty()); |
| 1688 *ok = false; | 1813 *ok = false; |
| 1689 return NULL; | 1814 return NULL; |
| 1690 } | 1815 } |
| 1691 mode = LET; | 1816 mode = LET; |
| 1692 needs_init = true; | 1817 needs_init = true; |
| 1693 init_op = Token::INIT_LET; | 1818 init_op = Token::INIT_LET; |
| 1694 } else { | 1819 } else { |
| 1695 UNREACHABLE(); // by current callers | 1820 UNREACHABLE(); // by current callers |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1733 // assignment for variables and constants because the value must be assigned | 1858 // assignment for variables and constants because the value must be assigned |
| 1734 // when the variable is encountered in the source. But the variable/constant | 1859 // when the variable is encountered in the source. But the variable/constant |
| 1735 // is declared (and set to 'undefined') upon entering the function within | 1860 // is declared (and set to 'undefined') upon entering the function within |
| 1736 // which the variable or constant is declared. Only function variables have | 1861 // which the variable or constant is declared. Only function variables have |
| 1737 // an initial value in the declaration (because they are initialized upon | 1862 // an initial value in the declaration (because they are initialized upon |
| 1738 // entering the function). | 1863 // entering the function). |
| 1739 // | 1864 // |
| 1740 // If we have a const declaration, in an inner scope, the proxy is always | 1865 // If we have a const declaration, in an inner scope, the proxy is always |
| 1741 // bound to the declared variable (independent of possibly surrounding with | 1866 // bound to the declared variable (independent of possibly surrounding with |
| 1742 // statements). | 1867 // statements). |
| 1743 Declare(name, mode, NULL, is_const /* always bound for CONST! */, | 1868 // For let/const declarations in harmony mode, we can also immediately |
| 1744 CHECK_OK); | 1869 // pre-resolve the proxy because it resides in the same scope as the |
| 1870 // declaration. | |
| 1871 Declare(name, mode, NULL, mode != VAR, CHECK_OK); | |
| 1745 nvars++; | 1872 nvars++; |
| 1746 if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) { | 1873 if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) { |
| 1747 ReportMessageAt(scanner().location(), "too_many_variables", | 1874 ReportMessageAt(scanner().location(), "too_many_variables", |
| 1748 Vector<const char*>::empty()); | 1875 Vector<const char*>::empty()); |
| 1749 *ok = false; | 1876 *ok = false; |
| 1750 return NULL; | 1877 return NULL; |
| 1751 } | 1878 } |
| 1752 | 1879 |
| 1753 // Parse initialization expression if present and/or needed. A | 1880 // Parse initialization expression if present and/or needed. A |
| 1754 // declaration of the form: | 1881 // declaration of the form: |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1876 // Add an assignment node to the initialization statement block if we still | 2003 // Add an assignment node to the initialization statement block if we still |
| 1877 // have a pending initialization value. We must distinguish between | 2004 // have a pending initialization value. We must distinguish between |
| 1878 // different kinds of declarations: 'var' initializations are simply | 2005 // different kinds of declarations: 'var' initializations are simply |
| 1879 // assignments (with all the consequences if they are inside a 'with' | 2006 // assignments (with all the consequences if they are inside a 'with' |
| 1880 // statement - they may change a 'with' object property). Constant | 2007 // statement - they may change a 'with' object property). Constant |
| 1881 // initializations always assign to the declared constant which is | 2008 // initializations always assign to the declared constant which is |
| 1882 // always at the function scope level. This is only relevant for | 2009 // always at the function scope level. This is only relevant for |
| 1883 // dynamically looked-up variables and constants (the start context | 2010 // dynamically looked-up variables and constants (the start context |
| 1884 // for constant lookups is always the function context, while it is | 2011 // for constant lookups is always the function context, while it is |
| 1885 // the top context for var declared variables). Sigh... | 2012 // the top context for var declared variables). Sigh... |
| 1886 // For 'let' declared variables the initialization is in the same scope | 2013 // For 'let' and 'const' declared variables in harmony mode the |
| 1887 // as the declaration. Thus dynamic lookups are unnecessary even if the | 2014 // initialization is in the same scope as the declaration. Thus dynamic |
| 1888 // block scope is inside a with. | 2015 // lookups are unnecessary even if the block scope is inside a with. |
| 1889 if (value != NULL) { | 2016 if (value != NULL) { |
| 1890 VariableProxy* proxy = initialization_scope->NewUnresolved(name); | 2017 VariableProxy* proxy = initialization_scope->NewUnresolved(name); |
| 1891 Assignment* assignment = | 2018 Assignment* assignment = |
| 1892 new(zone()) Assignment(isolate(), init_op, proxy, value, position); | 2019 new(zone()) Assignment(isolate(), init_op, proxy, value, position); |
| 1893 block->AddStatement(new(zone()) ExpressionStatement(assignment)); | 2020 block->AddStatement(new(zone()) ExpressionStatement(assignment)); |
| 1894 } | 2021 } |
| 1895 | 2022 |
| 1896 if (fni_ != NULL) fni_->Leave(); | 2023 if (fni_ != NULL) fni_->Leave(); |
| 1897 } while (peek() == Token::COMMA); | 2024 } while (peek() == Token::COMMA); |
| 1898 | 2025 |
| (...skipping 1971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3870 | 3997 |
| 3871 Expect(Token::LBRACE, CHECK_OK); | 3998 Expect(Token::LBRACE, CHECK_OK); |
| 3872 | 3999 |
| 3873 // If we have a named function expression, we add a local variable | 4000 // If we have a named function expression, we add a local variable |
| 3874 // declaration to the body of the function with the name of the | 4001 // declaration to the body of the function with the name of the |
| 3875 // function and let it refer to the function itself (closure). | 4002 // function and let it refer to the function itself (closure). |
| 3876 // NOTE: We create a proxy and resolve it here so that in the | 4003 // NOTE: We create a proxy and resolve it here so that in the |
| 3877 // future we can change the AST to only refer to VariableProxies | 4004 // future we can change the AST to only refer to VariableProxies |
| 3878 // instead of Variables and Proxis as is the case now. | 4005 // instead of Variables and Proxis as is the case now. |
| 3879 if (type == FunctionLiteral::NAMED_EXPRESSION) { | 4006 if (type == FunctionLiteral::NAMED_EXPRESSION) { |
| 3880 Variable* fvar = top_scope_->DeclareFunctionVar(function_name); | 4007 VariableMode fvar_mode; |
| 4008 Token::Value fvar_init_op; | |
| 4009 if (harmony_scoping_) { | |
| 4010 fvar_mode = CONST_HARMONY; | |
| 4011 fvar_init_op = Token::INIT_CONST_HARMONY; | |
| 4012 } else { | |
| 4013 fvar_mode = CONST; | |
| 4014 fvar_init_op = Token::INIT_CONST; | |
| 4015 } | |
| 4016 Variable* fvar = top_scope_->DeclareFunctionVar(function_name, fvar_mode); | |
| 3881 VariableProxy* fproxy = top_scope_->NewUnresolved(function_name); | 4017 VariableProxy* fproxy = top_scope_->NewUnresolved(function_name); |
| 3882 fproxy->BindTo(fvar); | 4018 fproxy->BindTo(fvar); |
| 3883 body->Add(new(zone()) ExpressionStatement( | 4019 body->Add(new(zone()) ExpressionStatement( |
| 3884 new(zone()) Assignment(isolate(), | 4020 new(zone()) Assignment(isolate(), |
| 3885 Token::INIT_CONST, | 4021 fvar_init_op, |
| 3886 fproxy, | 4022 fproxy, |
| 3887 new(zone()) ThisFunction(isolate()), | 4023 new(zone()) ThisFunction(isolate()), |
| 3888 RelocInfo::kNoPosition))); | 4024 RelocInfo::kNoPosition))); |
| 3889 } | 4025 } |
| 3890 | 4026 |
| 3891 // Determine if the function will be lazily compiled. The mode can only | 4027 // Determine if the function will be lazily compiled. The mode can only |
| 3892 // be PARSE_LAZILY if the --lazy flag is true. We will not lazily | 4028 // be PARSE_LAZILY if the --lazy flag is true. We will not lazily |
| 3893 // compile if we do not have preparser data for the function. | 4029 // compile if we do not have preparser data for the function. |
| 3894 bool is_lazily_compiled = (mode() == PARSE_LAZILY && | 4030 bool is_lazily_compiled = (mode() == PARSE_LAZILY && |
| 3895 top_scope_->outer_scope()->is_global_scope() && | 4031 top_scope_->outer_scope()->is_global_scope() && |
| (...skipping 1432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5328 result = parser.ParseProgram(source, | 5464 result = parser.ParseProgram(source, |
| 5329 info->is_global(), | 5465 info->is_global(), |
| 5330 info->StrictMode()); | 5466 info->StrictMode()); |
| 5331 } | 5467 } |
| 5332 } | 5468 } |
| 5333 info->SetFunction(result); | 5469 info->SetFunction(result); |
| 5334 return (result != NULL); | 5470 return (result != NULL); |
| 5335 } | 5471 } |
| 5336 | 5472 |
| 5337 } } // namespace v8::internal | 5473 } } // namespace v8::internal |
| OLD | NEW |