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 793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
804 Handle<FixedArray> elements = factory->NewFixedArray(args.length()); | 804 Handle<FixedArray> elements = factory->NewFixedArray(args.length()); |
805 for (int i = 0; i < args.length(); i++) { | 805 for (int i = 0; i < args.length(); i++) { |
806 elements->set(i, *args[i]); | 806 elements->set(i, *args[i]); |
807 } | 807 } |
808 Handle<JSArray> array = factory->NewJSArrayWithElements(elements); | 808 Handle<JSArray> array = factory->NewJSArrayWithElements(elements); |
809 Handle<Object> result = factory->NewSyntaxError(type, array); | 809 Handle<Object> result = factory->NewSyntaxError(type, array); |
810 isolate()->Throw(*result, &location); | 810 isolate()->Throw(*result, &location); |
811 } | 811 } |
812 | 812 |
813 void Parser::SetHarmonyBlockScoping(bool block_scoping) { | 813 void Parser::SetHarmonyBlockScoping(bool block_scoping) { |
| 814 scanner().SetHarmonyBlockScoping(block_scoping); |
814 harmony_block_scoping_ = block_scoping; | 815 harmony_block_scoping_ = block_scoping; |
815 } | 816 } |
816 | 817 |
817 // Base class containing common code for the different finder classes used by | 818 // Base class containing common code for the different finder classes used by |
818 // the parser. | 819 // the parser. |
819 class ParserFinder { | 820 class ParserFinder { |
820 protected: | 821 protected: |
821 ParserFinder() {} | 822 ParserFinder() {} |
822 static Assignment* AsAssignment(Statement* stat) { | 823 static Assignment* AsAssignment(Statement* stat) { |
823 if (stat == NULL) return NULL; | 824 if (stat == NULL) return NULL; |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1086 } | 1087 } |
1087 | 1088 |
1088 Isolate* isolate_; | 1089 Isolate* isolate_; |
1089 bool only_simple_this_property_assignments_; | 1090 bool only_simple_this_property_assignments_; |
1090 ZoneStringList* names_; | 1091 ZoneStringList* names_; |
1091 ZoneList<int>* assigned_arguments_; | 1092 ZoneList<int>* assigned_arguments_; |
1092 ZoneObjectList* assigned_constants_; | 1093 ZoneObjectList* assigned_constants_; |
1093 }; | 1094 }; |
1094 | 1095 |
1095 | 1096 |
| 1097 Statement* Parser::ParseSourceElement(ZoneStringList* labels, |
| 1098 bool* ok) { |
| 1099 if (peek() == Token::FUNCTION) { |
| 1100 // FunctionDeclaration is only allowed in the context of SourceElements |
| 1101 // (Ecma 262 5th Edition, clause 14): |
| 1102 // SourceElement: |
| 1103 // Statement |
| 1104 // FunctionDeclaration |
| 1105 // Common language extension is to allow function declaration in place |
| 1106 // of any statement. This language extension is disabled in strict mode. |
| 1107 return ParseFunctionDeclaration(ok); |
| 1108 } else if (peek() == Token::LET) { |
| 1109 return ParseVariableStatement(kSourceElement, ok); |
| 1110 } else { |
| 1111 return ParseStatement(labels, ok); |
| 1112 } |
| 1113 } |
| 1114 |
| 1115 |
1096 void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, | 1116 void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, |
1097 int end_token, | 1117 int end_token, |
1098 bool* ok) { | 1118 bool* ok) { |
1099 // SourceElements :: | 1119 // SourceElements :: |
1100 // (Statement)* <end_token> | 1120 // (Statement)* <end_token> |
1101 | 1121 |
1102 // Allocate a target stack to use for this set of source | 1122 // Allocate a target stack to use for this set of source |
1103 // elements. This way, all scripts and functions get their own | 1123 // elements. This way, all scripts and functions get their own |
1104 // target stack thus avoiding illegal breaks and continues across | 1124 // target stack thus avoiding illegal breaks and continues across |
1105 // functions. | 1125 // functions. |
1106 TargetScope scope(&this->target_stack_); | 1126 TargetScope scope(&this->target_stack_); |
1107 | 1127 |
1108 ASSERT(processor != NULL); | 1128 ASSERT(processor != NULL); |
1109 InitializationBlockFinder block_finder(top_scope_, target_stack_); | 1129 InitializationBlockFinder block_finder(top_scope_, target_stack_); |
1110 ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate()); | 1130 ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate()); |
1111 bool directive_prologue = true; // Parsing directive prologue. | 1131 bool directive_prologue = true; // Parsing directive prologue. |
1112 | 1132 |
1113 while (peek() != end_token) { | 1133 while (peek() != end_token) { |
1114 if (directive_prologue && peek() != Token::STRING) { | 1134 if (directive_prologue && peek() != Token::STRING) { |
1115 directive_prologue = false; | 1135 directive_prologue = false; |
1116 } | 1136 } |
1117 | 1137 |
1118 Scanner::Location token_loc = scanner().peek_location(); | 1138 Scanner::Location token_loc = scanner().peek_location(); |
1119 | 1139 Statement* stat = ParseSourceElement(NULL, CHECK_OK); |
1120 Statement* stat; | |
1121 if (peek() == Token::FUNCTION) { | |
1122 // FunctionDeclaration is only allowed in the context of SourceElements | |
1123 // (Ecma 262 5th Edition, clause 14): | |
1124 // SourceElement: | |
1125 // Statement | |
1126 // FunctionDeclaration | |
1127 // Common language extension is to allow function declaration in place | |
1128 // of any statement. This language extension is disabled in strict mode. | |
1129 stat = ParseFunctionDeclaration(CHECK_OK); | |
1130 } else { | |
1131 stat = ParseStatement(NULL, CHECK_OK); | |
1132 } | |
1133 | |
1134 if (stat == NULL || stat->IsEmpty()) { | 1140 if (stat == NULL || stat->IsEmpty()) { |
1135 directive_prologue = false; // End of directive prologue. | 1141 directive_prologue = false; // End of directive prologue. |
1136 continue; | 1142 continue; |
1137 } | 1143 } |
1138 | 1144 |
1139 if (directive_prologue) { | 1145 if (directive_prologue) { |
1140 // A shot at a directive. | 1146 // A shot at a directive. |
1141 ExpressionStatement *e_stat; | 1147 ExpressionStatement *e_stat; |
1142 Literal *literal; | 1148 Literal *literal; |
1143 // Still processing directive prologue? | 1149 // Still processing directive prologue? |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1211 | 1217 |
1212 // Keep the source position of the statement | 1218 // Keep the source position of the statement |
1213 int statement_pos = scanner().peek_location().beg_pos; | 1219 int statement_pos = scanner().peek_location().beg_pos; |
1214 Statement* stmt = NULL; | 1220 Statement* stmt = NULL; |
1215 switch (peek()) { | 1221 switch (peek()) { |
1216 case Token::LBRACE: | 1222 case Token::LBRACE: |
1217 return ParseBlock(labels, ok); | 1223 return ParseBlock(labels, ok); |
1218 | 1224 |
1219 case Token::CONST: // fall through | 1225 case Token::CONST: // fall through |
1220 case Token::VAR: | 1226 case Token::VAR: |
1221 stmt = ParseVariableStatement(ok); | 1227 stmt = ParseVariableStatement(kStatement, ok); |
1222 break; | 1228 break; |
1223 | 1229 |
1224 case Token::SEMICOLON: | 1230 case Token::SEMICOLON: |
1225 Next(); | 1231 Next(); |
1226 return EmptyStatement(); | 1232 return EmptyStatement(); |
1227 | 1233 |
1228 case Token::IF: | 1234 case Token::IF: |
1229 stmt = ParseIfStatement(labels, ok); | 1235 stmt = ParseIfStatement(labels, ok); |
1230 break; | 1236 break; |
1231 | 1237 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1306 return stmt; | 1312 return stmt; |
1307 } | 1313 } |
1308 | 1314 |
1309 | 1315 |
1310 VariableProxy* Parser::Declare(Handle<String> name, | 1316 VariableProxy* Parser::Declare(Handle<String> name, |
1311 Variable::Mode mode, | 1317 Variable::Mode mode, |
1312 FunctionLiteral* fun, | 1318 FunctionLiteral* fun, |
1313 bool resolve, | 1319 bool resolve, |
1314 bool* ok) { | 1320 bool* ok) { |
1315 Variable* var = NULL; | 1321 Variable* var = NULL; |
1316 // If we are inside a function, a declaration of a variable | 1322 // If we are inside a function, a declaration of a var/const variable is a |
1317 // is a truly local variable, and the scope of the variable | 1323 // truly local variable, and the scope of the variable is always the function |
1318 // is always the function scope. | 1324 // scope. |
1319 | 1325 |
1320 // If a function scope exists, then we can statically declare this | 1326 // If a function scope exists, then we can statically declare this |
1321 // variable and also set its mode. In any case, a Declaration node | 1327 // variable and also set its mode. In any case, a Declaration node |
1322 // will be added to the scope so that the declaration can be added | 1328 // will be added to the scope so that the declaration can be added |
1323 // to the corresponding activation frame at runtime if necessary. | 1329 // to the corresponding activation frame at runtime if necessary. |
1324 // For instance declarations inside an eval scope need to be added | 1330 // For instance declarations inside an eval scope need to be added |
1325 // to the calling function context. | 1331 // to the calling function context. |
1326 // Similarly, strict mode eval scope does not leak variable declarations to | 1332 // Similarly, strict mode eval scope does not leak variable declarations to |
1327 // the caller's scope so we declare all locals, too. | 1333 // the caller's scope so we declare all locals, too. |
1328 Scope* declaration_scope = top_scope_->DeclarationScope(); | 1334 |
| 1335 Scope* declaration_scope = mode == Variable::LET ? top_scope_ |
| 1336 : top_scope_->DeclarationScope(); |
1329 if (declaration_scope->is_function_scope() || | 1337 if (declaration_scope->is_function_scope() || |
1330 declaration_scope->is_strict_mode_eval_scope()) { | 1338 declaration_scope->is_strict_mode_eval_scope() || |
| 1339 declaration_scope->is_block_scope()) { |
1331 // Declare the variable in the function scope. | 1340 // Declare the variable in the function scope. |
1332 var = declaration_scope->LocalLookup(name); | 1341 var = declaration_scope->LocalLookup(name); |
1333 if (var == NULL) { | 1342 if (var == NULL) { |
1334 // Declare the name. | 1343 // Declare the name. |
1335 var = declaration_scope->DeclareLocal(name, mode); | 1344 var = declaration_scope->DeclareLocal(name, mode); |
1336 } else { | 1345 } else { |
1337 // The name was declared before; check for conflicting | 1346 // The name was declared before; check for conflicting re-declarations. |
1338 // re-declarations. If the previous declaration was a const or the | 1347 // We have a conflict if either of the declarations is not a var. There |
1339 // current declaration is a const then we have a conflict. There is | 1348 // is similar code in runtime.cc in the Declare functions. |
1340 // similar code in runtime.cc in the Declare functions. | 1349 if ((mode != Variable::VAR) || (var->mode() != Variable::VAR)) { |
1341 if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) { | 1350 // We only have vars, consts and lets in declarations. |
1342 // We only have vars and consts in declarations. | |
1343 ASSERT(var->mode() == Variable::VAR || | 1351 ASSERT(var->mode() == Variable::VAR || |
1344 var->mode() == Variable::CONST); | 1352 var->mode() == Variable::CONST || |
1345 const char* type = (var->mode() == Variable::VAR) ? "var" : "const"; | 1353 var->mode() == Variable::LET); |
| 1354 const char* type = (var->mode() == Variable::VAR) ? "var" : |
| 1355 (var->mode() == Variable::CONST) ? "const" : "let"; |
1346 Handle<String> type_string = | 1356 Handle<String> type_string = |
1347 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED); | 1357 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED); |
1348 Expression* expression = | 1358 Expression* expression = |
1349 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(), | 1359 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(), |
1350 type_string, name); | 1360 type_string, name); |
1351 declaration_scope->SetIllegalRedeclaration(expression); | 1361 declaration_scope->SetIllegalRedeclaration(expression); |
1352 } | 1362 } |
1353 } | 1363 } |
1354 } | 1364 } |
1355 | 1365 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1478 Handle<String> name = ParseIdentifierOrStrictReservedWord( | 1488 Handle<String> name = ParseIdentifierOrStrictReservedWord( |
1479 &is_strict_reserved, CHECK_OK); | 1489 &is_strict_reserved, CHECK_OK); |
1480 FunctionLiteral* fun = ParseFunctionLiteral(name, | 1490 FunctionLiteral* fun = ParseFunctionLiteral(name, |
1481 is_strict_reserved, | 1491 is_strict_reserved, |
1482 function_token_position, | 1492 function_token_position, |
1483 FunctionLiteral::DECLARATION, | 1493 FunctionLiteral::DECLARATION, |
1484 CHECK_OK); | 1494 CHECK_OK); |
1485 // Even if we're not at the top-level of the global or a function | 1495 // Even if we're not at the top-level of the global or a function |
1486 // scope, we treat is as such and introduce the function with it's | 1496 // scope, we treat is as such and introduce the function with it's |
1487 // initial value upon entering the corresponding scope. | 1497 // initial value upon entering the corresponding scope. |
1488 Declare(name, Variable::VAR, fun, true, CHECK_OK); | 1498 Variable::Mode mode = harmony_block_scoping_ ? Variable::LET : Variable::VAR; |
| 1499 Declare(name, mode, fun, true, CHECK_OK); |
1489 return EmptyStatement(); | 1500 return EmptyStatement(); |
1490 } | 1501 } |
1491 | 1502 |
1492 | 1503 |
1493 Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { | 1504 Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { |
1494 if (harmony_block_scoping_) return ParseScopedBlock(labels, ok); | 1505 if (harmony_block_scoping_) return ParseScopedBlock(labels, ok); |
1495 | 1506 |
1496 // Block :: | 1507 // Block :: |
1497 // '{' Statement* '}' | 1508 // '{' Statement* '}' |
1498 | 1509 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1533 | 1544 |
1534 // Parse the statements and collect escaping labels. | 1545 // Parse the statements and collect escaping labels. |
1535 TargetCollector collector; | 1546 TargetCollector collector; |
1536 Target target(&this->target_stack_, &collector); | 1547 Target target(&this->target_stack_, &collector); |
1537 Expect(Token::LBRACE, CHECK_OK); | 1548 Expect(Token::LBRACE, CHECK_OK); |
1538 { | 1549 { |
1539 Target target_body(&this->target_stack_, body); | 1550 Target target_body(&this->target_stack_, body); |
1540 InitializationBlockFinder block_finder(top_scope_, target_stack_); | 1551 InitializationBlockFinder block_finder(top_scope_, target_stack_); |
1541 | 1552 |
1542 while (peek() != Token::RBRACE) { | 1553 while (peek() != Token::RBRACE) { |
1543 Statement* stat = ParseStatement(NULL, CHECK_OK); | 1554 Statement* stat = ParseSourceElement(NULL, CHECK_OK); |
1544 if (stat && !stat->IsEmpty()) { | 1555 if (stat && !stat->IsEmpty()) { |
1545 body->AddStatement(stat); | 1556 body->AddStatement(stat); |
1546 block_finder.Update(stat); | 1557 block_finder.Update(stat); |
1547 } | 1558 } |
1548 } | 1559 } |
1549 } | 1560 } |
1550 Expect(Token::RBRACE, CHECK_OK); | 1561 Expect(Token::RBRACE, CHECK_OK); |
1551 | 1562 |
1552 // Create exit block. | 1563 // Create exit block. |
1553 Block* exit = new(zone()) Block(isolate(), NULL, 1, false); | 1564 Block* exit = new(zone()) Block(isolate(), NULL, 1, false); |
1554 exit->AddStatement(new(zone()) ExitContextStatement()); | 1565 exit->AddStatement(new(zone()) ExitContextStatement()); |
1555 | 1566 |
1556 // Create a try-finally statement. | 1567 // Create a try-finally statement. |
1557 TryFinallyStatement* try_finally = | 1568 TryFinallyStatement* try_finally = |
1558 new(zone()) TryFinallyStatement(body, exit); | 1569 new(zone()) TryFinallyStatement(body, exit); |
1559 try_finally->set_escaping_targets(collector.targets()); | 1570 try_finally->set_escaping_targets(collector.targets()); |
1560 top_scope_ = saved_scope; | 1571 top_scope_ = saved_scope; |
1561 | 1572 |
1562 // Create a result block. | 1573 // Create a result block. |
1563 Block* result = new(zone()) Block(isolate(), NULL, 1, false); | 1574 Block* result = new(zone()) Block(isolate(), NULL, 1, false); |
1564 result->AddStatement(try_finally); | 1575 result->AddStatement(try_finally); |
1565 return result; | 1576 return result; |
1566 } | 1577 } |
1567 | 1578 |
1568 | 1579 |
1569 Block* Parser::ParseVariableStatement(bool* ok) { | 1580 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, |
| 1581 bool* ok) { |
1570 // VariableStatement :: | 1582 // VariableStatement :: |
1571 // VariableDeclarations ';' | 1583 // VariableDeclarations ';' |
1572 | 1584 |
1573 Handle<String> ignore; | 1585 Handle<String> ignore; |
1574 Block* result = ParseVariableDeclarations(true, &ignore, CHECK_OK); | 1586 Block* result = ParseVariableDeclarations(var_context, |
| 1587 &ignore, |
| 1588 CHECK_OK); |
1575 ExpectSemicolon(CHECK_OK); | 1589 ExpectSemicolon(CHECK_OK); |
1576 return result; | 1590 return result; |
1577 } | 1591 } |
1578 | 1592 |
1579 | 1593 |
1580 bool Parser::IsEvalOrArguments(Handle<String> string) { | 1594 bool Parser::IsEvalOrArguments(Handle<String> string) { |
1581 return string.is_identical_to(isolate()->factory()->eval_symbol()) || | 1595 return string.is_identical_to(isolate()->factory()->eval_symbol()) || |
1582 string.is_identical_to(isolate()->factory()->arguments_symbol()); | 1596 string.is_identical_to(isolate()->factory()->arguments_symbol()); |
1583 } | 1597 } |
1584 | 1598 |
1585 | 1599 |
1586 // If the variable declaration declares exactly one non-const | 1600 // If the variable declaration declares exactly one non-const |
1587 // variable, then *var is set to that variable. In all other cases, | 1601 // variable, then *var is set to that variable. In all other cases, |
1588 // *var is untouched; in particular, it is the caller's responsibility | 1602 // *var is untouched; in particular, it is the caller's responsibility |
1589 // to initialize it properly. This mechanism is used for the parsing | 1603 // to initialize it properly. This mechanism is used for the parsing |
1590 // of 'for-in' loops. | 1604 // of 'for-in' loops. |
1591 Block* Parser::ParseVariableDeclarations(bool accept_IN, | 1605 Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context, |
1592 Handle<String>* out, | 1606 Handle<String>* out, |
1593 bool* ok) { | 1607 bool* ok) { |
1594 // VariableDeclarations :: | 1608 // VariableDeclarations :: |
1595 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] | 1609 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] |
1596 | 1610 |
1597 Variable::Mode mode = Variable::VAR; | 1611 Variable::Mode mode = Variable::VAR; |
1598 bool is_const = false; | 1612 bool is_const = false; |
1599 Scope* declaration_scope = top_scope_->DeclarationScope(); | |
1600 if (peek() == Token::VAR) { | 1613 if (peek() == Token::VAR) { |
1601 Consume(Token::VAR); | 1614 Consume(Token::VAR); |
1602 } else if (peek() == Token::CONST) { | 1615 } else if (peek() == Token::CONST) { |
1603 Consume(Token::CONST); | 1616 Consume(Token::CONST); |
1604 if (declaration_scope->is_strict_mode()) { | 1617 if (top_scope_->is_strict_mode()) { |
1605 ReportMessage("strict_const", Vector<const char*>::empty()); | 1618 ReportMessage("strict_const", Vector<const char*>::empty()); |
1606 *ok = false; | 1619 *ok = false; |
1607 return NULL; | 1620 return NULL; |
1608 } | 1621 } |
1609 mode = Variable::CONST; | 1622 mode = Variable::CONST; |
1610 is_const = true; | 1623 is_const = true; |
| 1624 } else if (peek() == Token::LET) { |
| 1625 Consume(Token::LET); |
| 1626 if (var_context != kSourceElement && |
| 1627 var_context != kForStatement) { |
| 1628 ASSERT(var_context == kStatement); |
| 1629 ReportMessage("unprotected_let", Vector<const char*>::empty()); |
| 1630 *ok = false; |
| 1631 return NULL; |
| 1632 } |
| 1633 mode = Variable::LET; |
1611 } else { | 1634 } else { |
1612 UNREACHABLE(); // by current callers | 1635 UNREACHABLE(); // by current callers |
1613 } | 1636 } |
1614 | 1637 |
1615 // The scope of a variable/const declared anywhere inside a function | 1638 Scope* declaration_scope = mode == Variable::LET |
| 1639 ? top_scope_ : top_scope_->DeclarationScope(); |
| 1640 // The scope of a var/const declared variable anywhere inside a function |
1616 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can | 1641 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can |
1617 // transform a source-level variable/const declaration into a (Function) | 1642 // transform a source-level var/const declaration into a (Function) |
1618 // Scope declaration, and rewrite the source-level initialization into an | 1643 // Scope declaration, and rewrite the source-level initialization into an |
1619 // assignment statement. We use a block to collect multiple assignments. | 1644 // assignment statement. We use a block to collect multiple assignments. |
1620 // | 1645 // |
1621 // We mark the block as initializer block because we don't want the | 1646 // We mark the block as initializer block because we don't want the |
1622 // rewriter to add a '.result' assignment to such a block (to get compliant | 1647 // rewriter to add a '.result' assignment to such a block (to get compliant |
1623 // behavior for code such as print(eval('var x = 7')), and for cosmetic | 1648 // behavior for code such as print(eval('var x = 7')), and for cosmetic |
1624 // reasons when pretty-printing. Also, unless an assignment (initialization) | 1649 // reasons when pretty-printing. Also, unless an assignment (initialization) |
1625 // is inside an initializer block, it is ignored. | 1650 // is inside an initializer block, it is ignored. |
1626 // | 1651 // |
1627 // Create new block with one expected declaration. | 1652 // Create new block with one expected declaration. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1691 // The "variable" c initialized to x is the same as the declared | 1716 // The "variable" c initialized to x is the same as the declared |
1692 // one - there is no re-lookup (see the last parameter of the | 1717 // one - there is no re-lookup (see the last parameter of the |
1693 // Declare() call above). | 1718 // Declare() call above). |
1694 | 1719 |
1695 Scope* initialization_scope = is_const ? declaration_scope : top_scope_; | 1720 Scope* initialization_scope = is_const ? declaration_scope : top_scope_; |
1696 Expression* value = NULL; | 1721 Expression* value = NULL; |
1697 int position = -1; | 1722 int position = -1; |
1698 if (peek() == Token::ASSIGN) { | 1723 if (peek() == Token::ASSIGN) { |
1699 Expect(Token::ASSIGN, CHECK_OK); | 1724 Expect(Token::ASSIGN, CHECK_OK); |
1700 position = scanner().location().beg_pos; | 1725 position = scanner().location().beg_pos; |
1701 value = ParseAssignmentExpression(accept_IN, CHECK_OK); | 1726 value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); |
1702 // Don't infer if it is "a = function(){...}();"-like expression. | 1727 // Don't infer if it is "a = function(){...}();"-like expression. |
1703 if (fni_ != NULL && | 1728 if (fni_ != NULL && |
1704 value->AsCall() == NULL && | 1729 value->AsCall() == NULL && |
1705 value->AsCallNew() == NULL) { | 1730 value->AsCallNew() == NULL) { |
1706 fni_->Infer(); | 1731 fni_->Infer(); |
1707 } | 1732 } |
1708 } | 1733 } |
1709 | 1734 |
1710 // Make sure that 'const c' actually initializes 'c' to undefined | 1735 // Make sure that 'const c' actually initializes 'c' to undefined |
1711 // even though it seems like a stupid thing to do. | 1736 // even though it seems like a stupid thing to do. |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2291 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 2316 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
2292 | 2317 |
2293 Statement* init = NULL; | 2318 Statement* init = NULL; |
2294 | 2319 |
2295 Expect(Token::FOR, CHECK_OK); | 2320 Expect(Token::FOR, CHECK_OK); |
2296 Expect(Token::LPAREN, CHECK_OK); | 2321 Expect(Token::LPAREN, CHECK_OK); |
2297 if (peek() != Token::SEMICOLON) { | 2322 if (peek() != Token::SEMICOLON) { |
2298 if (peek() == Token::VAR || peek() == Token::CONST) { | 2323 if (peek() == Token::VAR || peek() == Token::CONST) { |
2299 Handle<String> name; | 2324 Handle<String> name; |
2300 Block* variable_statement = | 2325 Block* variable_statement = |
2301 ParseVariableDeclarations(false, &name, CHECK_OK); | 2326 ParseVariableDeclarations(kForStatement, &name, CHECK_OK); |
2302 | 2327 |
2303 if (peek() == Token::IN && !name.is_null()) { | 2328 if (peek() == Token::IN && !name.is_null()) { |
2304 VariableProxy* each = top_scope_->NewUnresolved(name, inside_with()); | 2329 VariableProxy* each = top_scope_->NewUnresolved(name, inside_with()); |
2305 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels); | 2330 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels); |
2306 Target target(&this->target_stack_, loop); | 2331 Target target(&this->target_stack_, loop); |
2307 | 2332 |
2308 Expect(Token::IN, CHECK_OK); | 2333 Expect(Token::IN, CHECK_OK); |
2309 Expression* enumerable = ParseExpression(true, CHECK_OK); | 2334 Expression* enumerable = ParseExpression(true, CHECK_OK); |
2310 Expect(Token::RPAREN, CHECK_OK); | 2335 Expect(Token::RPAREN, CHECK_OK); |
2311 | 2336 |
(...skipping 1338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3650 // handle as the function name. Remember if we were passed a non-empty | 3675 // handle as the function name. Remember if we were passed a non-empty |
3651 // handle to decide whether to invoke function name inference. | 3676 // handle to decide whether to invoke function name inference. |
3652 bool should_infer_name = function_name.is_null(); | 3677 bool should_infer_name = function_name.is_null(); |
3653 | 3678 |
3654 // We want a non-null handle as the function name. | 3679 // We want a non-null handle as the function name. |
3655 if (should_infer_name) { | 3680 if (should_infer_name) { |
3656 function_name = isolate()->factory()->empty_symbol(); | 3681 function_name = isolate()->factory()->empty_symbol(); |
3657 } | 3682 } |
3658 | 3683 |
3659 int num_parameters = 0; | 3684 int num_parameters = 0; |
3660 // Function declarations are hoisted. | 3685 // Function declarations are function scoped in normal mode, so they are |
3661 Scope* scope = (type == FunctionLiteral::DECLARATION) | 3686 // hoisted. In harmony block scoping mode they are block scoped, so they |
| 3687 // are not hoisted. |
| 3688 Scope* scope = (type == FunctionLiteral::DECLARATION && |
| 3689 !harmony_block_scoping_) |
3662 ? NewScope(top_scope_->DeclarationScope(), Scope::FUNCTION_SCOPE, false) | 3690 ? NewScope(top_scope_->DeclarationScope(), Scope::FUNCTION_SCOPE, false) |
3663 : NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); | 3691 : NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); |
3664 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8); | 3692 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8); |
3665 int materialized_literal_count; | 3693 int materialized_literal_count; |
3666 int expected_property_count; | 3694 int expected_property_count; |
3667 int start_pos; | 3695 int start_pos; |
3668 int end_pos; | 3696 int end_pos; |
3669 bool only_simple_this_property_assignments; | 3697 bool only_simple_this_property_assignments; |
3670 Handle<FixedArray> this_property_assignments; | 3698 Handle<FixedArray> this_property_assignments; |
3671 bool has_duplicate_parameters = false; | 3699 bool has_duplicate_parameters = false; |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3953 Literal* Parser::GetLiteralTheHole() { | 3981 Literal* Parser::GetLiteralTheHole() { |
3954 return NewLiteral(isolate()->factory()->the_hole_value()); | 3982 return NewLiteral(isolate()->factory()->the_hole_value()); |
3955 } | 3983 } |
3956 | 3984 |
3957 | 3985 |
3958 Literal* Parser::GetLiteralNumber(double value) { | 3986 Literal* Parser::GetLiteralNumber(double value) { |
3959 return NewNumberLiteral(value); | 3987 return NewNumberLiteral(value); |
3960 } | 3988 } |
3961 | 3989 |
3962 | 3990 |
3963 // Parses and identifier that is valid for the current scope, in particular it | 3991 // Parses an identifier that is valid for the current scope, in particular it |
3964 // fails on strict mode future reserved keywords in a strict scope. | 3992 // fails on strict mode future reserved keywords in a strict scope. |
3965 Handle<String> Parser::ParseIdentifier(bool* ok) { | 3993 Handle<String> Parser::ParseIdentifier(bool* ok) { |
3966 if (top_scope_->is_strict_mode()) { | 3994 if (top_scope_->is_strict_mode()) { |
3967 Expect(Token::IDENTIFIER, ok); | 3995 Expect(Token::IDENTIFIER, ok); |
3968 } else if (!Check(Token::IDENTIFIER)) { | 3996 } else if (!Check(Token::IDENTIFIER)) { |
3969 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok); | 3997 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok); |
3970 } | 3998 } |
3971 if (!*ok) return Handle<String>(); | 3999 if (!*ok) return Handle<String>(); |
3972 return GetSymbol(ok); | 4000 return GetSymbol(ok); |
3973 } | 4001 } |
(...skipping 1060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5034 data++; | 5062 data++; |
5035 } | 5063 } |
5036 *source = data; | 5064 *source = data; |
5037 return result; | 5065 return result; |
5038 } | 5066 } |
5039 | 5067 |
5040 | 5068 |
5041 // Create a Scanner for the preparser to use as input, and preparse the source. | 5069 // Create a Scanner for the preparser to use as input, and preparse the source. |
5042 static ScriptDataImpl* DoPreParse(UC16CharacterStream* source, | 5070 static ScriptDataImpl* DoPreParse(UC16CharacterStream* source, |
5043 bool allow_lazy, | 5071 bool allow_lazy, |
5044 ParserRecorder* recorder) { | 5072 ParserRecorder* recorder, |
| 5073 bool harmony_block_scoping) { |
5045 Isolate* isolate = Isolate::Current(); | 5074 Isolate* isolate = Isolate::Current(); |
5046 JavaScriptScanner scanner(isolate->unicode_cache()); | 5075 JavaScriptScanner scanner(isolate->unicode_cache()); |
5047 scanner.Initialize(source); | 5076 scanner.Initialize(source); |
| 5077 scanner.SetHarmonyBlockScoping(harmony_block_scoping); |
5048 intptr_t stack_limit = isolate->stack_guard()->real_climit(); | 5078 intptr_t stack_limit = isolate->stack_guard()->real_climit(); |
5049 if (!preparser::PreParser::PreParseProgram(&scanner, | 5079 if (!preparser::PreParser::PreParseProgram(&scanner, |
5050 recorder, | 5080 recorder, |
5051 allow_lazy, | 5081 allow_lazy, |
5052 stack_limit)) { | 5082 stack_limit)) { |
5053 isolate->StackOverflow(); | 5083 isolate->StackOverflow(); |
5054 return NULL; | 5084 return NULL; |
5055 } | 5085 } |
5056 | 5086 |
5057 // Extract the accumulated data from the recorder as a single | 5087 // Extract the accumulated data from the recorder as a single |
5058 // contiguous vector that we are responsible for disposing. | 5088 // contiguous vector that we are responsible for disposing. |
5059 Vector<unsigned> store = recorder->ExtractData(); | 5089 Vector<unsigned> store = recorder->ExtractData(); |
5060 return new ScriptDataImpl(store); | 5090 return new ScriptDataImpl(store); |
5061 } | 5091 } |
5062 | 5092 |
5063 | 5093 |
5064 // Preparse, but only collect data that is immediately useful, | 5094 // Preparse, but only collect data that is immediately useful, |
5065 // even if the preparser data is only used once. | 5095 // even if the preparser data is only used once. |
5066 ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source, | 5096 ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source, |
5067 v8::Extension* extension) { | 5097 v8::Extension* extension, |
| 5098 bool harmony_block_scoping) { |
5068 bool allow_lazy = FLAG_lazy && (extension == NULL); | 5099 bool allow_lazy = FLAG_lazy && (extension == NULL); |
5069 if (!allow_lazy) { | 5100 if (!allow_lazy) { |
5070 // Partial preparsing is only about lazily compiled functions. | 5101 // Partial preparsing is only about lazily compiled functions. |
5071 // If we don't allow lazy compilation, the log data will be empty. | 5102 // If we don't allow lazy compilation, the log data will be empty. |
5072 return NULL; | 5103 return NULL; |
5073 } | 5104 } |
5074 PartialParserRecorder recorder; | 5105 PartialParserRecorder recorder; |
5075 return DoPreParse(source, allow_lazy, &recorder); | 5106 return DoPreParse(source, allow_lazy, &recorder, harmony_block_scoping); |
5076 } | 5107 } |
5077 | 5108 |
5078 | 5109 |
5079 ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source, | 5110 ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source, |
5080 v8::Extension* extension) { | 5111 v8::Extension* extension, |
| 5112 bool harmony_block_scoping) { |
5081 Handle<Script> no_script; | 5113 Handle<Script> no_script; |
5082 bool allow_lazy = FLAG_lazy && (extension == NULL); | 5114 bool allow_lazy = FLAG_lazy && (extension == NULL); |
5083 CompleteParserRecorder recorder; | 5115 CompleteParserRecorder recorder; |
5084 return DoPreParse(source, allow_lazy, &recorder); | 5116 return DoPreParse(source, allow_lazy, &recorder, harmony_block_scoping); |
5085 } | 5117 } |
5086 | 5118 |
5087 | 5119 |
5088 bool RegExpParser::ParseRegExp(FlatStringReader* input, | 5120 bool RegExpParser::ParseRegExp(FlatStringReader* input, |
5089 bool multiline, | 5121 bool multiline, |
5090 RegExpCompileData* result) { | 5122 RegExpCompileData* result) { |
5091 ASSERT(result != NULL); | 5123 ASSERT(result != NULL); |
5092 RegExpParser parser(input, &result->error, multiline); | 5124 RegExpParser parser(input, &result->error, multiline); |
5093 RegExpTree* tree = parser.ParsePattern(); | 5125 RegExpTree* tree = parser.ParsePattern(); |
5094 if (parser.failed()) { | 5126 if (parser.failed()) { |
5095 ASSERT(tree == NULL); | 5127 ASSERT(tree == NULL); |
5096 ASSERT(!result->error.is_null()); | 5128 ASSERT(!result->error.is_null()); |
5097 } else { | 5129 } else { |
5098 ASSERT(tree != NULL); | 5130 ASSERT(tree != NULL); |
5099 ASSERT(result->error.is_null()); | 5131 ASSERT(result->error.is_null()); |
5100 result->tree = tree; | 5132 result->tree = tree; |
5101 int capture_count = parser.captures_started(); | 5133 int capture_count = parser.captures_started(); |
5102 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0; | 5134 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0; |
5103 result->contains_anchor = parser.contains_anchor(); | 5135 result->contains_anchor = parser.contains_anchor(); |
5104 result->capture_count = capture_count; | 5136 result->capture_count = capture_count; |
5105 } | 5137 } |
5106 return !parser.failed(); | 5138 return !parser.failed(); |
5107 } | 5139 } |
5108 | 5140 |
5109 | 5141 |
5110 bool ParserApi::Parse(CompilationInfo* info) { | 5142 bool ParserApi::Parse(CompilationInfo* info) { |
5111 ASSERT(info->function() == NULL); | 5143 ASSERT(info->function() == NULL); |
5112 FunctionLiteral* result = NULL; | 5144 FunctionLiteral* result = NULL; |
5113 Handle<Script> script = info->script(); | 5145 Handle<Script> script = info->script(); |
| 5146 bool harmony_block_scoping = !info->is_native() && |
| 5147 FLAG_harmony_block_scoping; |
5114 if (info->is_lazy()) { | 5148 if (info->is_lazy()) { |
5115 Parser parser(script, true, NULL, NULL); | 5149 Parser parser(script, true, NULL, NULL); |
5116 parser.SetHarmonyBlockScoping(!info->is_native() && | 5150 parser.SetHarmonyBlockScoping(harmony_block_scoping); |
5117 FLAG_harmony_block_scoping); | |
5118 result = parser.ParseLazy(info); | 5151 result = parser.ParseLazy(info); |
5119 } else { | 5152 } else { |
5120 // Whether we allow %identifier(..) syntax. | 5153 // Whether we allow %identifier(..) syntax. |
5121 bool allow_natives_syntax = | 5154 bool allow_natives_syntax = |
5122 info->allows_natives_syntax() || FLAG_allow_natives_syntax; | 5155 info->allows_natives_syntax() || FLAG_allow_natives_syntax; |
5123 ScriptDataImpl* pre_data = info->pre_parse_data(); | 5156 ScriptDataImpl* pre_data = info->pre_parse_data(); |
5124 Parser parser(script, allow_natives_syntax, info->extension(), pre_data); | 5157 Parser parser(script, |
5125 parser.SetHarmonyBlockScoping(!info->is_native() && | 5158 allow_natives_syntax, |
5126 FLAG_harmony_block_scoping); | 5159 info->extension(), |
| 5160 pre_data); |
| 5161 parser.SetHarmonyBlockScoping(harmony_block_scoping); |
5127 if (pre_data != NULL && pre_data->has_error()) { | 5162 if (pre_data != NULL && pre_data->has_error()) { |
5128 Scanner::Location loc = pre_data->MessageLocation(); | 5163 Scanner::Location loc = pre_data->MessageLocation(); |
5129 const char* message = pre_data->BuildMessage(); | 5164 const char* message = pre_data->BuildMessage(); |
5130 Vector<const char*> args = pre_data->BuildArgs(); | 5165 Vector<const char*> args = pre_data->BuildArgs(); |
5131 parser.ReportMessageAt(loc, message, args); | 5166 parser.ReportMessageAt(loc, message, args); |
5132 DeleteArray(message); | 5167 DeleteArray(message); |
5133 for (int i = 0; i < args.length(); i++) { | 5168 for (int i = 0; i < args.length(); i++) { |
5134 DeleteArray(args[i]); | 5169 DeleteArray(args[i]); |
5135 } | 5170 } |
5136 DeleteArray(args.start()); | 5171 DeleteArray(args.start()); |
5137 ASSERT(info->isolate()->has_pending_exception()); | 5172 ASSERT(info->isolate()->has_pending_exception()); |
5138 } else { | 5173 } else { |
5139 Handle<String> source = Handle<String>(String::cast(script->source())); | 5174 Handle<String> source = Handle<String>(String::cast(script->source())); |
5140 result = parser.ParseProgram(source, | 5175 result = parser.ParseProgram(source, |
5141 info->is_global(), | 5176 info->is_global(), |
5142 info->StrictMode()); | 5177 info->StrictMode()); |
5143 } | 5178 } |
5144 } | 5179 } |
5145 info->SetFunction(result); | 5180 info->SetFunction(result); |
5146 return (result != NULL); | 5181 return (result != NULL); |
5147 } | 5182 } |
5148 | 5183 |
5149 } } // namespace v8::internal | 5184 } } // namespace v8::internal |
OLD | NEW |