Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/ast.h" | 8 #include "src/ast.h" |
| 9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
| 10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
| (...skipping 1263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1274 } | 1274 } |
| 1275 } | 1275 } |
| 1276 | 1276 |
| 1277 scope->set_end_position(scanner()->location().end_pos); | 1277 scope->set_end_position(scanner()->location().end_pos); |
| 1278 body->set_scope(scope); | 1278 body->set_scope(scope); |
| 1279 | 1279 |
| 1280 // Check that all exports are bound. | 1280 // Check that all exports are bound. |
| 1281 ModuleDescriptor* descriptor = scope->module(); | 1281 ModuleDescriptor* descriptor = scope->module(); |
| 1282 for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done(); | 1282 for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done(); |
| 1283 it.Advance()) { | 1283 it.Advance()) { |
| 1284 if (scope->LookupLocal(it.name()) == NULL) { | 1284 if (scope->LookupLocal(it.local_name()) == NULL) { |
| 1285 ParserTraits::ReportMessage("module_export_undefined", it.name()); | 1285 ParserTraits::ReportMessage("module_export_undefined", it.local_name()); |
| 1286 *ok = false; | 1286 *ok = false; |
| 1287 return NULL; | 1287 return NULL; |
| 1288 } | 1288 } |
| 1289 } | 1289 } |
| 1290 | 1290 |
| 1291 scope->module()->Freeze(); | 1291 scope->module()->Freeze(); |
| 1292 return body; | 1292 return body; |
| 1293 } | 1293 } |
| 1294 | 1294 |
| 1295 | 1295 |
| 1296 Literal* Parser::ParseModuleSpecifier(bool* ok) { | 1296 Literal* Parser::ParseModuleSpecifier(bool* ok) { |
| 1297 // ModuleSpecifier : | 1297 // ModuleSpecifier : |
| 1298 // StringLiteral | 1298 // StringLiteral |
| 1299 | 1299 |
| 1300 int pos = peek_position(); | 1300 int pos = peek_position(); |
| 1301 Expect(Token::STRING, CHECK_OK); | 1301 Expect(Token::STRING, CHECK_OK); |
| 1302 return factory()->NewStringLiteral(GetSymbol(scanner()), pos); | 1302 return factory()->NewStringLiteral(GetSymbol(scanner()), pos); |
| 1303 } | 1303 } |
| 1304 | 1304 |
| 1305 | 1305 |
| 1306 void* Parser::ParseExportClause(ZoneList<const AstRawString*>* names, | 1306 void* Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names, |
| 1307 ZoneList<const AstRawString*>* local_names, | |
| 1307 Scanner::Location* reserved_loc, bool* ok) { | 1308 Scanner::Location* reserved_loc, bool* ok) { |
| 1308 // ExportClause : | 1309 // ExportClause : |
| 1309 // '{' '}' | 1310 // '{' '}' |
| 1310 // '{' ExportsList '}' | 1311 // '{' ExportsList '}' |
| 1311 // '{' ExportsList ',' '}' | 1312 // '{' ExportsList ',' '}' |
| 1312 // | 1313 // |
| 1313 // ExportsList : | 1314 // ExportsList : |
| 1314 // ExportSpecifier | 1315 // ExportSpecifier |
| 1315 // ExportsList ',' ExportSpecifier | 1316 // ExportsList ',' ExportSpecifier |
| 1316 // | 1317 // |
| 1317 // ExportSpecifier : | 1318 // ExportSpecifier : |
| 1318 // IdentifierName | 1319 // IdentifierName |
| 1319 // IdentifierName 'as' IdentifierName | 1320 // IdentifierName 'as' IdentifierName |
| 1320 | 1321 |
| 1321 Expect(Token::LBRACE, CHECK_OK); | 1322 Expect(Token::LBRACE, CHECK_OK); |
| 1322 | 1323 |
| 1323 Token::Value name_tok; | 1324 Token::Value name_tok; |
| 1324 while ((name_tok = peek()) != Token::RBRACE) { | 1325 while ((name_tok = peek()) != Token::RBRACE) { |
| 1325 // Keep track of the first reserved word encountered in case our | 1326 // Keep track of the first reserved word encountered in case our |
| 1326 // caller needs to report an error. | 1327 // caller needs to report an error. |
| 1327 if (!reserved_loc->IsValid() && | 1328 if (!reserved_loc->IsValid() && |
| 1328 !Token::IsIdentifier(name_tok, STRICT, false)) { | 1329 !Token::IsIdentifier(name_tok, STRICT, false)) { |
| 1329 *reserved_loc = scanner()->location(); | 1330 *reserved_loc = scanner()->location(); |
| 1330 } | 1331 } |
| 1331 const AstRawString* name = ParseIdentifierName(CHECK_OK); | 1332 const AstRawString* local_name = ParseIdentifierName(CHECK_OK); |
| 1332 names->Add(name, zone()); | |
| 1333 const AstRawString* export_name = NULL; | 1333 const AstRawString* export_name = NULL; |
| 1334 if (CheckContextualKeyword(CStrVector("as"))) { | 1334 if (CheckContextualKeyword(CStrVector("as"))) { |
| 1335 export_name = ParseIdentifierName(CHECK_OK); | 1335 export_name = ParseIdentifierName(CHECK_OK); |
| 1336 } | 1336 } |
| 1337 // TODO(ES6): Return the export_name as well as the name. | 1337 if (export_name == NULL) { |
| 1338 USE(export_name); | 1338 export_name = local_name; |
| 1339 } | |
| 1340 export_names->Add(export_name, zone()); | |
| 1341 local_names->Add(local_name, zone()); | |
| 1339 if (peek() == Token::RBRACE) break; | 1342 if (peek() == Token::RBRACE) break; |
| 1340 Expect(Token::COMMA, CHECK_OK); | 1343 Expect(Token::COMMA, CHECK_OK); |
| 1341 } | 1344 } |
| 1342 | 1345 |
| 1343 Expect(Token::RBRACE, CHECK_OK); | 1346 Expect(Token::RBRACE, CHECK_OK); |
| 1344 | 1347 |
| 1345 return 0; | 1348 return 0; |
| 1346 } | 1349 } |
| 1347 | 1350 |
| 1348 | 1351 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1472 return factory()->NewEmptyStatement(pos); | 1475 return factory()->NewEmptyStatement(pos); |
| 1473 } | 1476 } |
| 1474 | 1477 |
| 1475 | 1478 |
| 1476 Statement* Parser::ParseExportDefault(bool* ok) { | 1479 Statement* Parser::ParseExportDefault(bool* ok) { |
| 1477 // Supports the following productions, starting after the 'default' token: | 1480 // Supports the following productions, starting after the 'default' token: |
| 1478 // 'export' 'default' FunctionDeclaration | 1481 // 'export' 'default' FunctionDeclaration |
| 1479 // 'export' 'default' ClassDeclaration | 1482 // 'export' 'default' ClassDeclaration |
| 1480 // 'export' 'default' AssignmentExpression[In] ';' | 1483 // 'export' 'default' AssignmentExpression[In] ';' |
| 1481 | 1484 |
| 1485 Expect(Token::DEFAULT, CHECK_OK); | |
| 1486 Scanner::Location default_loc = scanner()->location(); | |
| 1487 | |
| 1488 ZoneList<const AstRawString*> names(1, zone()); | |
| 1482 Statement* result = NULL; | 1489 Statement* result = NULL; |
| 1483 switch (peek()) { | 1490 switch (peek()) { |
| 1484 case Token::FUNCTION: | 1491 case Token::FUNCTION: |
| 1485 // TODO(ES6): Support parsing anonymous function declarations here. | 1492 // TODO(ES6): Support parsing anonymous function declarations here. |
| 1486 result = ParseFunctionDeclaration(NULL, CHECK_OK); | 1493 result = ParseFunctionDeclaration(&names, CHECK_OK); |
| 1487 break; | 1494 break; |
| 1488 | 1495 |
| 1489 case Token::CLASS: | 1496 case Token::CLASS: |
| 1490 // TODO(ES6): Support parsing anonymous class declarations here. | 1497 // TODO(ES6): Support parsing anonymous class declarations here. |
| 1491 result = ParseClassDeclaration(NULL, CHECK_OK); | 1498 result = ParseClassDeclaration(&names, CHECK_OK); |
| 1492 break; | 1499 break; |
| 1493 | 1500 |
| 1494 default: { | 1501 default: { |
| 1495 int pos = peek_position(); | 1502 int pos = peek_position(); |
| 1496 Expression* expr = ParseAssignmentExpression(true, CHECK_OK); | 1503 Expression* expr = ParseAssignmentExpression(true, CHECK_OK); |
| 1497 ExpectSemicolon(CHECK_OK); | 1504 ExpectSemicolon(CHECK_OK); |
| 1498 result = factory()->NewExpressionStatement(expr, pos); | 1505 result = factory()->NewExpressionStatement(expr, pos); |
| 1499 break; | 1506 break; |
| 1500 } | 1507 } |
| 1501 } | 1508 } |
| 1502 | 1509 |
| 1503 // TODO(ES6): Add default export to scope_->module() | 1510 const AstRawString* default_string = ast_value_factory()->default_string(); |
| 1511 | |
| 1512 DCHECK_LE(names.length(), 1); | |
| 1513 if (names.length() == 1) { | |
| 1514 scope_->module()->AddLocalExport(default_string, names.first(), zone(), ok); | |
| 1515 if (!*ok) { | |
| 1516 ParserTraits::ReportMessageAt(default_loc, "duplicate_export", | |
| 1517 default_string); | |
| 1518 return NULL; | |
| 1519 } | |
| 1520 } else { | |
| 1521 // TODO(ES6): Assign result to a const binding with the name "*default*" | |
| 1522 // and add an export entry with "*default*" as the local name. | |
| 1523 } | |
| 1504 | 1524 |
| 1505 return result; | 1525 return result; |
| 1506 } | 1526 } |
| 1507 | 1527 |
| 1508 | 1528 |
| 1509 Statement* Parser::ParseExportDeclaration(bool* ok) { | 1529 Statement* Parser::ParseExportDeclaration(bool* ok) { |
| 1510 // ExportDeclaration: | 1530 // ExportDeclaration: |
| 1511 // 'export' '*' 'from' ModuleSpecifier ';' | 1531 // 'export' '*' 'from' ModuleSpecifier ';' |
| 1512 // 'export' ExportClause ('from' ModuleSpecifier)? ';' | 1532 // 'export' ExportClause ('from' ModuleSpecifier)? ';' |
| 1513 // 'export' VariableStatement | 1533 // 'export' VariableStatement |
| 1514 // 'export' Declaration | 1534 // 'export' Declaration |
| 1515 // 'export' 'default' ... (handled in ParseExportDefault) | 1535 // 'export' 'default' ... (handled in ParseExportDefault) |
| 1516 | 1536 |
| 1517 int pos = peek_position(); | 1537 int pos = peek_position(); |
| 1518 Expect(Token::EXPORT, CHECK_OK); | 1538 Expect(Token::EXPORT, CHECK_OK); |
| 1519 | 1539 |
| 1520 Statement* result = NULL; | 1540 Statement* result = NULL; |
| 1521 ZoneList<const AstRawString*> names(1, zone()); | 1541 ZoneList<const AstRawString*> names(1, zone()); |
| 1522 bool is_export_from = false; | |
| 1523 switch (peek()) { | 1542 switch (peek()) { |
| 1524 case Token::DEFAULT: | 1543 case Token::DEFAULT: |
| 1525 Consume(Token::DEFAULT); | |
| 1526 return ParseExportDefault(ok); | 1544 return ParseExportDefault(ok); |
| 1527 | 1545 |
| 1528 case Token::MUL: { | 1546 case Token::MUL: { |
| 1529 Consume(Token::MUL); | 1547 Consume(Token::MUL); |
| 1530 ExpectContextualKeyword(CStrVector("from"), CHECK_OK); | 1548 ExpectContextualKeyword(CStrVector("from"), CHECK_OK); |
| 1531 Literal* module = ParseModuleSpecifier(CHECK_OK); | 1549 Literal* module = ParseModuleSpecifier(CHECK_OK); |
| 1532 ExpectSemicolon(CHECK_OK); | 1550 ExpectSemicolon(CHECK_OK); |
| 1533 // TODO(ES6): Do something with the return value | 1551 // TODO(ES6): scope_->module()->AddStarExport(...) |
| 1534 // of ParseModuleSpecifier. | |
| 1535 USE(module); | 1552 USE(module); |
| 1536 is_export_from = true; | 1553 return factory()->NewEmptyStatement(pos); |
| 1537 result = factory()->NewEmptyStatement(pos); | |
| 1538 break; | |
| 1539 } | 1554 } |
| 1540 | 1555 |
| 1541 case Token::LBRACE: { | 1556 case Token::LBRACE: { |
| 1542 // There are two cases here: | 1557 // There are two cases here: |
| 1543 // | 1558 // |
| 1544 // 'export' ExportClause ';' | 1559 // 'export' ExportClause ';' |
| 1545 // and | 1560 // and |
| 1546 // 'export' ExportClause FromClause ';' | 1561 // 'export' ExportClause FromClause ';' |
| 1547 // | 1562 // |
| 1548 // In the first case, the exported identifiers in ExportClause must | 1563 // In the first case, the exported identifiers in ExportClause must |
| 1549 // not be reserved words, while in the latter they may be. We | 1564 // not be reserved words, while in the latter they may be. We |
| 1550 // pass in a location that gets filled with the first reserved word | 1565 // pass in a location that gets filled with the first reserved word |
| 1551 // encountered, and then throw a SyntaxError if we are in the | 1566 // encountered, and then throw a SyntaxError if we are in the |
| 1552 // non-FromClause case. | 1567 // non-FromClause case. |
| 1553 Scanner::Location reserved_loc = Scanner::Location::invalid(); | 1568 Scanner::Location reserved_loc = Scanner::Location::invalid(); |
| 1554 ParseExportClause(&names, &reserved_loc, CHECK_OK); | 1569 ZoneList<const AstRawString*> export_names(1, zone()); |
| 1570 ZoneList<const AstRawString*> local_names(1, zone()); | |
| 1571 ParseExportClause(&export_names, &local_names, &reserved_loc, CHECK_OK); | |
| 1572 Literal* indirect_export_module_specifier = NULL; | |
| 1555 if (CheckContextualKeyword(CStrVector("from"))) { | 1573 if (CheckContextualKeyword(CStrVector("from"))) { |
| 1556 Literal* module = ParseModuleSpecifier(CHECK_OK); | 1574 indirect_export_module_specifier = ParseModuleSpecifier(CHECK_OK); |
| 1557 // TODO(ES6): Do something with the return value | |
| 1558 // of ParseModuleSpecifier. | |
| 1559 USE(module); | |
| 1560 is_export_from = true; | |
| 1561 } else if (reserved_loc.IsValid()) { | 1575 } else if (reserved_loc.IsValid()) { |
| 1562 // No FromClause, so reserved words are invalid in ExportClause. | 1576 // No FromClause, so reserved words are invalid in ExportClause. |
| 1563 *ok = false; | 1577 *ok = false; |
| 1564 ReportMessageAt(reserved_loc, "unexpected_reserved"); | 1578 ReportMessageAt(reserved_loc, "unexpected_reserved"); |
| 1565 return NULL; | 1579 return NULL; |
| 1566 } | 1580 } |
| 1567 ExpectSemicolon(CHECK_OK); | 1581 ExpectSemicolon(CHECK_OK); |
| 1568 result = factory()->NewEmptyStatement(pos); | 1582 DCHECK_EQ(export_names.length(), local_names.length()); |
| 1569 break; | 1583 const int length = export_names.length(); |
| 1584 if (indirect_export_module_specifier == NULL) { | |
| 1585 for (int i = 0; i < length; ++i) { | |
| 1586 scope_->module()->AddLocalExport(export_names[i], local_names[i], | |
| 1587 zone(), ok); | |
| 1588 if (!*ok) { | |
| 1589 // TODO(adamk): Possibly report this error at the right place. | |
|
arv (Not doing code reviews)
2015/02/19 15:05:44
Maybe pass one more list with the locations to Par
adamk
2015/02/19 19:10:09
Hmm. There will be cases, with "export * from ..."
| |
| 1590 ParserTraits::ReportMessage("duplicate_export", export_names[i]); | |
| 1591 return NULL; | |
| 1592 } | |
| 1593 } | |
| 1594 } else { | |
| 1595 for (int i = 0; i < length; ++i) { | |
| 1596 // TODO(ES6): scope_->module()->AddIndirectExport(...);( | |
| 1597 } | |
| 1598 } | |
| 1599 return factory()->NewEmptyStatement(pos); | |
| 1570 } | 1600 } |
| 1571 | 1601 |
| 1572 case Token::FUNCTION: | 1602 case Token::FUNCTION: |
| 1573 result = ParseFunctionDeclaration(&names, CHECK_OK); | 1603 result = ParseFunctionDeclaration(&names, CHECK_OK); |
| 1574 break; | 1604 break; |
| 1575 | 1605 |
| 1576 case Token::CLASS: | 1606 case Token::CLASS: |
| 1577 result = ParseClassDeclaration(&names, CHECK_OK); | 1607 result = ParseClassDeclaration(&names, CHECK_OK); |
| 1578 break; | 1608 break; |
| 1579 | 1609 |
| 1580 case Token::VAR: | 1610 case Token::VAR: |
| 1581 case Token::LET: | 1611 case Token::LET: |
| 1582 case Token::CONST: | 1612 case Token::CONST: |
| 1583 result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK); | 1613 result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK); |
| 1584 break; | 1614 break; |
| 1585 | 1615 |
| 1586 default: | 1616 default: |
| 1587 *ok = false; | 1617 *ok = false; |
| 1588 ReportUnexpectedToken(scanner()->current_token()); | 1618 ReportUnexpectedToken(scanner()->current_token()); |
| 1589 return NULL; | 1619 return NULL; |
| 1590 } | 1620 } |
| 1591 | 1621 |
| 1592 // Every export of a module may be assigned. | 1622 // Extract declared names into export declarations. |
| 1623 ModuleDescriptor* descriptor = scope_->module(); | |
| 1593 for (int i = 0; i < names.length(); ++i) { | 1624 for (int i = 0; i < names.length(); ++i) { |
| 1594 Variable* var = scope_->Lookup(names[i]); | 1625 descriptor->AddLocalExport(names[i], names[i], zone(), ok); |
| 1595 if (var == NULL) { | 1626 if (!*ok) { |
| 1596 // TODO(sigurds) This is an export that has no definition yet, | 1627 // TODO(adamk): Possibly report this error at the right place. |
| 1597 // not clear what to do in this case. | 1628 ParserTraits::ReportMessage("duplicate_export", names[i]); |
| 1598 continue; | 1629 return NULL; |
| 1599 } | |
| 1600 if (!IsImmutableVariableMode(var->mode())) { | |
| 1601 var->set_maybe_assigned(); | |
| 1602 } | 1630 } |
| 1603 } | 1631 } |
| 1604 | 1632 |
| 1605 // TODO(ES6): Handle 'export from' once imports are properly implemented. | 1633 DCHECK_NOT_NULL(result); |
| 1606 // For now we just drop such exports on the floor. | |
| 1607 if (!is_export_from) { | |
| 1608 // Extract declared names into export declarations and module descriptor. | |
| 1609 ModuleDescriptor* descriptor = scope_->module(); | |
| 1610 for (int i = 0; i < names.length(); ++i) { | |
| 1611 // TODO(adamk): Make early errors here provide the right error message | |
| 1612 // (duplicate exported names). | |
| 1613 descriptor->Add(names[i], zone(), CHECK_OK); | |
| 1614 // TODO(rossberg): Rethink whether we actually need to store export | |
| 1615 // declarations (for compilation?). | |
| 1616 // ExportDeclaration* declaration = | |
| 1617 // factory()->NewExportDeclaration(proxy, scope_, position); | |
| 1618 // scope_->AddDeclaration(declaration); | |
| 1619 } | |
| 1620 } | |
| 1621 | |
| 1622 DCHECK(result != NULL); | |
| 1623 return result; | 1634 return result; |
| 1624 } | 1635 } |
| 1625 | 1636 |
| 1626 | 1637 |
| 1627 Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels, | 1638 Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels, |
| 1628 bool* ok) { | 1639 bool* ok) { |
| 1629 // Statement :: | 1640 // Statement :: |
| 1630 // EmptyStatement | 1641 // EmptyStatement |
| 1631 // ... | 1642 // ... |
| 1632 | 1643 |
| (...skipping 3807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5440 } else { | 5451 } else { |
| 5441 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); | 5452 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); |
| 5442 running_hash = StringHasher::ComputeRunningHash(running_hash, data, | 5453 running_hash = StringHasher::ComputeRunningHash(running_hash, data, |
| 5443 raw_string->length()); | 5454 raw_string->length()); |
| 5444 } | 5455 } |
| 5445 } | 5456 } |
| 5446 | 5457 |
| 5447 return running_hash; | 5458 return running_hash; |
| 5448 } | 5459 } |
| 5449 } } // namespace v8::internal | 5460 } } // namespace v8::internal |
| OLD | NEW |