IncrementNodeCount();
DisableOptimization(kImportDeclaration);
VisitVariableProxy(node->proxy());
- Visit(node->module());
}
public:
DECLARE_NODE_TYPE(ImportDeclaration)
- Module* module() const { return module_; }
+ const AstRawString* import_name() const { return import_name_; }
+ const AstRawString* module_specifier() const { return module_specifier_; }
+ void set_module_specifier(const AstRawString* module_specifier) {
+ DCHECK(module_specifier_ == NULL);
+ module_specifier_ = module_specifier;
+ }
InitializationFlag initialization() const OVERRIDE {
- return kCreatedInitialized;
+ return kNeedsInitialization;
}
protected:
- ImportDeclaration(Zone* zone,
- VariableProxy* proxy,
- Module* module,
- Scope* scope,
- int pos)
- : Declaration(zone, proxy, LET, scope, pos),
- module_(module) {
- }
+ ImportDeclaration(Zone* zone, VariableProxy* proxy,
+ const AstRawString* import_name,
+ const AstRawString* module_specifier, Scope* scope, int pos)
+ : Declaration(zone, proxy, IMPORT, scope, pos),
+ import_name_(import_name),
+ module_specifier_(module_specifier) {}
private:
- Module* module_;
+ const AstRawString* import_name_;
+ const AstRawString* module_specifier_;
};
}
ImportDeclaration* NewImportDeclaration(VariableProxy* proxy,
- Module* module,
- Scope* scope,
- int pos) {
- return new (zone_) ImportDeclaration(zone_, proxy, module, scope, pos);
+ const AstRawString* import_name,
+ const AstRawString* module_specifier,
+ Scope* scope, int pos) {
+ return new (zone_) ImportDeclaration(zone_, proxy, import_name,
+ module_specifier, scope, pos);
}
ExportDeclaration* NewExportDeclaration(VariableProxy* proxy,
? IMMUTABLE_CHECK_INITIALIZED_HARMONY
: IMMUTABLE_IS_INITIALIZED_HARMONY;
break;
+ case IMPORT:
+ // TODO(ES6)
+ UNREACHABLE();
+ break;
case DYNAMIC:
case DYNAMIC_GLOBAL:
case DYNAMIC_LOCAL:
CONST_LEGACY, // declared via legacy 'const' declarations
- LET, // declared via 'let' declarations
+ LET, // declared via 'let' declarations (first lexical)
CONST, // declared via 'const' declarations
+ IMPORT, // declared via 'import' declarations (last lexical)
+
// Variables introduced by the compiler:
INTERNAL, // like VAR, but not user-visible (may or may not
// be in a context)
inline bool IsDeclaredVariableMode(VariableMode mode) {
- return mode >= VAR && mode <= CONST;
+ return mode >= VAR && mode <= IMPORT;
}
inline bool IsLexicalVariableMode(VariableMode mode) {
- return mode == LET || mode == CONST;
+ return mode >= LET && mode <= IMPORT;
}
inline bool IsImmutableVariableMode(VariableMode mode) {
- return mode == CONST || mode == CONST_LEGACY;
+ return mode == CONST || mode == CONST_LEGACY || mode == IMPORT;
}
}
-Literal* Parser::ParseModuleSpecifier(bool* ok) {
+const AstRawString* Parser::ParseModuleSpecifier(bool* ok) {
// ModuleSpecifier :
// StringLiteral
- int pos = peek_position();
Expect(Token::STRING, CHECK_OK);
- return factory()->NewStringLiteral(GetSymbol(scanner()), pos);
+ return GetSymbol(scanner());
}
}
-void* Parser::ParseNamedImports(ZoneList<const AstRawString*>* import_names,
- ZoneList<const AstRawString*>* local_names,
- bool* ok) {
+ZoneList<ImportDeclaration*>* Parser::ParseNamedImports(int pos, bool* ok) {
// NamedImports :
// '{' '}'
// '{' ImportsList '}'
Expect(Token::LBRACE, CHECK_OK);
+ ZoneList<ImportDeclaration*>* result =
+ new (zone()) ZoneList<ImportDeclaration*>(1, zone());
while (peek() != Token::RBRACE) {
const AstRawString* import_name = ParseIdentifierName(CHECK_OK);
const AstRawString* local_name = import_name;
ReportMessage("strict_eval_arguments");
return NULL;
}
- import_names->Add(import_name, zone());
- local_names->Add(local_name, zone());
+ VariableProxy* proxy = NewUnresolved(local_name, IMPORT);
+ ImportDeclaration* declaration =
+ factory()->NewImportDeclaration(proxy, import_name, NULL, scope_, pos);
+ Declare(declaration, true, CHECK_OK);
+ result->Add(declaration, zone());
if (peek() == Token::RBRACE) break;
Expect(Token::COMMA, CHECK_OK);
}
Expect(Token::RBRACE, CHECK_OK);
- return NULL;
+ return result;
}
// 'import' ModuleSpecifier ';'
if (tok == Token::STRING) {
- Literal* module_specifier = ParseModuleSpecifier(CHECK_OK);
+ const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
ExpectSemicolon(CHECK_OK);
// TODO(ES6): Add module to the requested modules of scope_->module().
USE(module_specifier);
if (tok != Token::MUL && tok != Token::LBRACE) {
imported_default_binding =
ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+ // TODO(ES6): Add an appropriate declaration.
}
const AstRawString* module_instance_binding = NULL;
- ZoneList<const AstRawString*> local_names(1, zone());
- ZoneList<const AstRawString*> import_names(1, zone());
+ ZoneList<ImportDeclaration*>* named_declarations = NULL;
if (imported_default_binding == NULL || Check(Token::COMMA)) {
switch (peek()) {
case Token::MUL: {
ExpectContextualKeyword(CStrVector("as"), CHECK_OK);
module_instance_binding =
ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+ // TODO(ES6): Add an appropriate declaration.
break;
}
case Token::LBRACE:
- ParseNamedImports(&import_names, &local_names, CHECK_OK);
+ named_declarations = ParseNamedImports(pos, CHECK_OK);
break;
default:
}
ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
- Literal* module = ParseModuleSpecifier(CHECK_OK);
- USE(module);
-
+ const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
ExpectSemicolon(CHECK_OK);
if (module_instance_binding != NULL) {
- // TODO(ES6): Bind name to the Module Instance Object of module.
+ // TODO(ES6): Set the module specifier for the module namespace binding.
}
if (imported_default_binding != NULL) {
- // TODO(ES6): Add an appropriate declaration.
+ // TODO(ES6): Set the module specifier for the default binding.
}
- const int length = import_names.length();
- DCHECK_EQ(length, local_names.length());
- for (int i = 0; i < length; ++i) {
- // TODO(ES6): Add an appropriate declaration for each name
+ if (named_declarations != NULL) {
+ for (int i = 0; i < named_declarations->length(); ++i) {
+ named_declarations->at(i)->set_module_specifier(module_specifier);
+ }
}
return factory()->NewEmptyStatement(pos);
case Token::MUL: {
Consume(Token::MUL);
ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
- Literal* module = ParseModuleSpecifier(CHECK_OK);
+ const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
ExpectSemicolon(CHECK_OK);
// TODO(ES6): scope_->module()->AddStarExport(...)
- USE(module);
+ USE(module_specifier);
return factory()->NewEmptyStatement(pos);
}
ZoneList<const AstRawString*> local_names(1, zone());
ParseExportClause(&export_names, &export_locations, &local_names,
&reserved_loc, CHECK_OK);
- Literal* indirect_export_module_specifier = NULL;
+ const AstRawString* indirect_export_module_specifier = NULL;
if (CheckContextualKeyword(CStrVector("from"))) {
indirect_export_module_specifier = ParseModuleSpecifier(CHECK_OK);
} else if (reserved_loc.IsValid()) {
Statement* ParseStatementListItem(bool* ok);
void* ParseModuleItemList(ZoneList<Statement*>* body, bool* ok);
Statement* ParseModuleItem(bool* ok);
- Literal* ParseModuleSpecifier(bool* ok);
+ const AstRawString* ParseModuleSpecifier(bool* ok);
Statement* ParseImportDeclaration(bool* ok);
Statement* ParseExportDeclaration(bool* ok);
Statement* ParseExportDefault(bool* ok);
ZoneList<Scanner::Location>* export_locations,
ZoneList<const AstRawString*>* local_names,
Scanner::Location* reserved_loc, bool* ok);
- void* ParseNamedImports(ZoneList<const AstRawString*>* import_names,
- ZoneList<const AstRawString*>* local_names, bool* ok);
+ ZoneList<ImportDeclaration*>* ParseNamedImports(int pos, bool* ok);
Statement* ParseStatement(ZoneList<const AstRawString*>* labels, bool* ok);
Statement* ParseSubStatement(ZoneList<const AstRawString*>* labels, bool* ok);
Statement* ParseFunctionDeclaration(ZoneList<const AstRawString*>* names,
void CallPrinter::VisitImportDeclaration(ImportDeclaration* node) {
- Find(node->module());
}
Print("import ");
PrintLiteral(node->proxy()->name(), false);
Print(" from ");
- Visit(node->module());
+ PrintLiteral(node->module_specifier()->string(), true);
Print(";");
}
void AstPrinter::VisitImportDeclaration(ImportDeclaration* node) {
IndentedScope indent(this, "IMPORT");
PrintLiteralIndented("NAME", node->proxy()->name(), true);
- Visit(node->module());
+ PrintLiteralIndented("FROM", node->module_specifier()->string(), true);
}
case VAR:
case LET:
case CONST:
- case CONST_LEGACY: {
+ case CONST_LEGACY:
+ case IMPORT: {
PropertyAttributes attr =
IsImmutableVariableMode(mode) ? FROZEN : SEALED;
Handle<AccessorInfo> info =
void AstTyper::VisitImportDeclaration(ImportDeclaration* declaration) {
- RECURSE(Visit(declaration->module()));
}
case CONST_LEGACY: return "CONST_LEGACY";
case LET: return "LET";
case CONST: return "CONST";
+ case IMPORT: return "IMPORT";
case DYNAMIC: return "DYNAMIC";
case DYNAMIC_GLOBAL: return "DYNAMIC_GLOBAL";
case DYNAMIC_LOCAL: return "DYNAMIC_LOCAL";
isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
128 * 1024);
- static const char kSource[] = "let x = 5; export { x as y };";
+ static const char kSource[] =
+ "let x = 5; export { x as y }; import { q as z } from 'm.js';";
i::Handle<i::String> source = factory->NewStringFromAsciiChecked(kSource);
i::Handle<i::Script> script = factory->NewScript(source);
i::CompilationInfoWithZone info(script);
- i::AstValueFactory avf(info.zone(), isolate->heap()->HashSeed());
i::Parser parser(&info, isolate->stack_guard()->real_climit(),
isolate->heap()->HashSeed(), isolate->unicode_cache());
parser.set_allow_harmony_modules(true);
CHECK_EQ(i::MODULE_SCOPE, func->scope()->scope_type());
i::ModuleDescriptor* descriptor = func->scope()->module();
CHECK_NOT_NULL(descriptor);
- const i::AstRawString* name_x = avf.GetOneByteString("x");
- const i::AstRawString* name_y = avf.GetOneByteString("y");
int num_exports = 0;
for (auto it = descriptor->iterator(); !it.done(); it.Advance()) {
++num_exports;
- CHECK(*name_x == *it.local_name());
- CHECK(*name_y == *it.export_name());
+ CHECK(it.local_name()->IsOneByteEqualTo("x"));
+ CHECK(it.export_name()->IsOneByteEqualTo("y"));
}
CHECK_EQ(1, num_exports);
+ i::ZoneList<i::Declaration*>* declarations = func->scope()->declarations();
+ CHECK_EQ(2, declarations->length());
+ CHECK(declarations->at(0)->proxy()->raw_name()->IsOneByteEqualTo("x"));
+ i::ImportDeclaration* import_decl =
+ declarations->at(1)->AsImportDeclaration();
+ CHECK(import_decl->import_name()->IsOneByteEqualTo("q"));
+ CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("z"));
+ CHECK(import_decl->module_specifier()->IsOneByteEqualTo("m.js"));
}
--- /dev/null
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MODULE
+
+let foo = 42;
+import { bar as foo } from "mod";
--- /dev/null
+# Copyright 2015 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+*%(basename)s:8: SyntaxError: Identifier 'foo' has already been declared
+import { bar as foo } from "mod";
+ ^^^
+SyntaxError: Identifier 'foo' has already been declared
--- /dev/null
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MODULE
+
+let foo = 42;
+import { foo } from "mod";
--- /dev/null
+# Copyright 2015 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+*%(basename)s:8: SyntaxError: Identifier 'foo' has already been declared
+import { foo } from "mod";
+ ^^^
+SyntaxError: Identifier 'foo' has already been declared