| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index bb8cb52b75068f0aee6941880fd7d1ecfe58bd29..1bbc88f00f3f27804a8ef8769d7f7dfcf386a17c 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -1281,8 +1281,11 @@ Statement* Parser::ParseModule(bool* ok) {
|
| ModuleDescriptor* descriptor = scope->module();
|
| for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
|
| it.Advance()) {
|
| - if (scope->LookupLocal(it.name()) == NULL) {
|
| - ParserTraits::ReportMessage("module_export_undefined", it.name());
|
| + if (scope->LookupLocal(it.local_name()) == NULL) {
|
| + // TODO(adamk): Pass both local_name and export_name once ParserTraits
|
| + // supports multiple arg error messages.
|
| + // Also try to report this at a better location.
|
| + ParserTraits::ReportMessage("module_export_undefined", it.local_name());
|
| *ok = false;
|
| return NULL;
|
| }
|
| @@ -1303,7 +1306,9 @@ Literal* Parser::ParseModuleSpecifier(bool* ok) {
|
| }
|
|
|
|
|
| -void* Parser::ParseExportClause(ZoneList<const AstRawString*>* names,
|
| +void* Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names,
|
| + ZoneList<Scanner::Location>* export_locations,
|
| + ZoneList<const AstRawString*>* local_names,
|
| Scanner::Location* reserved_loc, bool* ok) {
|
| // ExportClause :
|
| // '{' '}'
|
| @@ -1328,14 +1333,17 @@ void* Parser::ParseExportClause(ZoneList<const AstRawString*>* names,
|
| !Token::IsIdentifier(name_tok, STRICT, false)) {
|
| *reserved_loc = scanner()->location();
|
| }
|
| - const AstRawString* name = ParseIdentifierName(CHECK_OK);
|
| - names->Add(name, zone());
|
| + const AstRawString* local_name = ParseIdentifierName(CHECK_OK);
|
| const AstRawString* export_name = NULL;
|
| if (CheckContextualKeyword(CStrVector("as"))) {
|
| export_name = ParseIdentifierName(CHECK_OK);
|
| }
|
| - // TODO(ES6): Return the export_name as well as the name.
|
| - USE(export_name);
|
| + if (export_name == NULL) {
|
| + export_name = local_name;
|
| + }
|
| + export_names->Add(export_name, zone());
|
| + local_names->Add(local_name, zone());
|
| + export_locations->Add(scanner()->location(), zone());
|
| if (peek() == Token::RBRACE) break;
|
| Expect(Token::COMMA, CHECK_OK);
|
| }
|
| @@ -1479,16 +1487,20 @@ Statement* Parser::ParseExportDefault(bool* ok) {
|
| // 'export' 'default' ClassDeclaration
|
| // 'export' 'default' AssignmentExpression[In] ';'
|
|
|
| + Expect(Token::DEFAULT, CHECK_OK);
|
| + Scanner::Location default_loc = scanner()->location();
|
| +
|
| + ZoneList<const AstRawString*> names(1, zone());
|
| Statement* result = NULL;
|
| switch (peek()) {
|
| case Token::FUNCTION:
|
| // TODO(ES6): Support parsing anonymous function declarations here.
|
| - result = ParseFunctionDeclaration(NULL, CHECK_OK);
|
| + result = ParseFunctionDeclaration(&names, CHECK_OK);
|
| break;
|
|
|
| case Token::CLASS:
|
| // TODO(ES6): Support parsing anonymous class declarations here.
|
| - result = ParseClassDeclaration(NULL, CHECK_OK);
|
| + result = ParseClassDeclaration(&names, CHECK_OK);
|
| break;
|
|
|
| default: {
|
| @@ -1500,7 +1512,20 @@ Statement* Parser::ParseExportDefault(bool* ok) {
|
| }
|
| }
|
|
|
| - // TODO(ES6): Add default export to scope_->module()
|
| + const AstRawString* default_string = ast_value_factory()->default_string();
|
| +
|
| + DCHECK_LE(names.length(), 1);
|
| + if (names.length() == 1) {
|
| + scope_->module()->AddLocalExport(default_string, names.first(), zone(), ok);
|
| + if (!*ok) {
|
| + ParserTraits::ReportMessageAt(default_loc, "duplicate_export",
|
| + default_string);
|
| + return NULL;
|
| + }
|
| + } else {
|
| + // TODO(ES6): Assign result to a const binding with the name "*default*"
|
| + // and add an export entry with "*default*" as the local name.
|
| + }
|
|
|
| return result;
|
| }
|
| @@ -1519,10 +1544,8 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
|
|
|
| Statement* result = NULL;
|
| ZoneList<const AstRawString*> names(1, zone());
|
| - bool is_export_from = false;
|
| switch (peek()) {
|
| case Token::DEFAULT:
|
| - Consume(Token::DEFAULT);
|
| return ParseExportDefault(ok);
|
|
|
| case Token::MUL: {
|
| @@ -1530,12 +1553,9 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
|
| ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
|
| Literal* module = ParseModuleSpecifier(CHECK_OK);
|
| ExpectSemicolon(CHECK_OK);
|
| - // TODO(ES6): Do something with the return value
|
| - // of ParseModuleSpecifier.
|
| + // TODO(ES6): scope_->module()->AddStarExport(...)
|
| USE(module);
|
| - is_export_from = true;
|
| - result = factory()->NewEmptyStatement(pos);
|
| - break;
|
| + return factory()->NewEmptyStatement(pos);
|
| }
|
|
|
| case Token::LBRACE: {
|
| @@ -1551,13 +1571,14 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
|
| // encountered, and then throw a SyntaxError if we are in the
|
| // non-FromClause case.
|
| Scanner::Location reserved_loc = Scanner::Location::invalid();
|
| - ParseExportClause(&names, &reserved_loc, CHECK_OK);
|
| + ZoneList<const AstRawString*> export_names(1, zone());
|
| + ZoneList<Scanner::Location> export_locations(1, zone());
|
| + ZoneList<const AstRawString*> local_names(1, zone());
|
| + ParseExportClause(&export_names, &export_locations, &local_names,
|
| + &reserved_loc, CHECK_OK);
|
| + Literal* indirect_export_module_specifier = NULL;
|
| if (CheckContextualKeyword(CStrVector("from"))) {
|
| - Literal* module = ParseModuleSpecifier(CHECK_OK);
|
| - // TODO(ES6): Do something with the return value
|
| - // of ParseModuleSpecifier.
|
| - USE(module);
|
| - is_export_from = true;
|
| + indirect_export_module_specifier = ParseModuleSpecifier(CHECK_OK);
|
| } else if (reserved_loc.IsValid()) {
|
| // No FromClause, so reserved words are invalid in ExportClause.
|
| *ok = false;
|
| @@ -1565,8 +1586,25 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
|
| return NULL;
|
| }
|
| ExpectSemicolon(CHECK_OK);
|
| - result = factory()->NewEmptyStatement(pos);
|
| - break;
|
| + const int length = export_names.length();
|
| + DCHECK_EQ(length, local_names.length());
|
| + DCHECK_EQ(length, export_locations.length());
|
| + if (indirect_export_module_specifier == NULL) {
|
| + for (int i = 0; i < length; ++i) {
|
| + scope_->module()->AddLocalExport(export_names[i], local_names[i],
|
| + zone(), ok);
|
| + if (!*ok) {
|
| + ParserTraits::ReportMessageAt(export_locations[i],
|
| + "duplicate_export", export_names[i]);
|
| + return NULL;
|
| + }
|
| + }
|
| + } else {
|
| + for (int i = 0; i < length; ++i) {
|
| + // TODO(ES6): scope_->module()->AddIndirectExport(...);(
|
| + }
|
| + }
|
| + return factory()->NewEmptyStatement(pos);
|
| }
|
|
|
| case Token::FUNCTION:
|
| @@ -1589,37 +1627,18 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
|
| return NULL;
|
| }
|
|
|
| - // Every export of a module may be assigned.
|
| + // Extract declared names into export declarations.
|
| + ModuleDescriptor* descriptor = scope_->module();
|
| for (int i = 0; i < names.length(); ++i) {
|
| - Variable* var = scope_->Lookup(names[i]);
|
| - if (var == NULL) {
|
| - // TODO(sigurds) This is an export that has no definition yet,
|
| - // not clear what to do in this case.
|
| - continue;
|
| - }
|
| - if (!IsImmutableVariableMode(var->mode())) {
|
| - var->set_maybe_assigned();
|
| - }
|
| - }
|
| -
|
| - // TODO(ES6): Handle 'export from' once imports are properly implemented.
|
| - // For now we just drop such exports on the floor.
|
| - if (!is_export_from) {
|
| - // Extract declared names into export declarations and module descriptor.
|
| - ModuleDescriptor* descriptor = scope_->module();
|
| - for (int i = 0; i < names.length(); ++i) {
|
| - // TODO(adamk): Make early errors here provide the right error message
|
| - // (duplicate exported names).
|
| - descriptor->Add(names[i], zone(), CHECK_OK);
|
| - // TODO(rossberg): Rethink whether we actually need to store export
|
| - // declarations (for compilation?).
|
| - // ExportDeclaration* declaration =
|
| - // factory()->NewExportDeclaration(proxy, scope_, position);
|
| - // scope_->AddDeclaration(declaration);
|
| + descriptor->AddLocalExport(names[i], names[i], zone(), ok);
|
| + if (!*ok) {
|
| + // TODO(adamk): Possibly report this error at the right place.
|
| + ParserTraits::ReportMessage("duplicate_export", names[i]);
|
| + return NULL;
|
| }
|
| }
|
|
|
| - DCHECK(result != NULL);
|
| + DCHECK_NOT_NULL(result);
|
| return result;
|
| }
|
|
|
|
|