Reviewers: arv, rossberg,
Description:
Fix up ParseProgram and ParseModule to do something sane with module scopes
The FunctionLiteral returned from the parser for modules now has a
MODULE_SCOPE,
instead of associating the module scope with a Block inside it. This makes
it easy to get at the ModuleDescriptor from the caller of Parse(), so I've
added
a basic test that pokes at the scope and the descriptor. Expect more tests
in this vein.
BUG=v8:1569
Please review this at https://codereview.chromium.org/953983002/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+55, -36 lines):
M src/parser.h
M src/parser.cc
M test/cctest/test-parsing.cc
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index
b1d427e2529f4ec23a4ac702094ba4f874657443..e50a5efdcbde94f5bd4a49c2e4108cb31192a2eb
100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -928,6 +928,8 @@ FunctionLiteral*
Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
}
} else if (info->is_global()) {
*scope = NewScope(*scope, SCRIPT_SCOPE);
+ } else if (info->is_module()) {
+ *scope = NewScope(*scope, MODULE_SCOPE);
}
(*scope)->set_start_position(0);
// End position will be set by the caller.
@@ -951,10 +953,7 @@ FunctionLiteral*
Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
int beg_pos = scanner()->location().beg_pos;
if (info->is_module()) {
DCHECK(allow_harmony_modules());
- Statement* stmt = ParseModule(&ok);
- if (ok) {
- body->Add(stmt, zone());
- }
+ ParseModule(body, &ok);
} else {
ParseStatementList(body, Token::EOS, info->is_eval(), eval_scope,
&ok);
}
@@ -1254,7 +1253,7 @@ Statement* Parser::ParseModuleItem(bool* ok) {
}
-Statement* Parser::ParseModule(bool* ok) {
+void* Parser::ParseModule(ZoneList<Statement*>* body, bool* ok) {
// (Ecma 262 6th Edition, 15.2):
// Module :
// ModuleBody?
@@ -1262,31 +1261,22 @@ Statement* Parser::ParseModule(bool* ok) {
// ModuleBody :
// ModuleItem*
- Block* body = factory()->NewBlock(NULL, 16, false,
RelocInfo::kNoPosition);
- Scope* scope = NewScope(scope_, MODULE_SCOPE);
- scope->set_start_position(scanner()->location().beg_pos);
- scope->SetLanguageMode(
- static_cast<LanguageMode>(scope->language_mode() | STRICT_BIT));
-
- {
- BlockState block_state(&scope_, scope);
+ DCHECK(scope_->is_module_scope());
+ scope_->SetLanguageMode(
+ static_cast<LanguageMode>(scope_->language_mode() | STRICT_BIT));
- while (peek() != Token::EOS) {
- Statement* stat = ParseModuleItem(CHECK_OK);
- if (stat && !stat->IsEmpty()) {
- body->AddStatement(stat, zone());
- }
+ while (peek() != Token::EOS) {
+ Statement* stat = ParseModuleItem(CHECK_OK);
+ if (stat && !stat->IsEmpty()) {
+ body->Add(stat, zone());
}
}
- scope->set_end_position(scanner()->location().end_pos);
- body->set_scope(scope);
-
// Check that all exports are bound.
- ModuleDescriptor* descriptor = scope->module();
+ ModuleDescriptor* descriptor = scope_->module();
for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
it.Advance()) {
- if (scope->LookupLocal(it.local_name()) == NULL) {
+ 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.
@@ -1296,8 +1286,8 @@ Statement* Parser::ParseModule(bool* ok) {
}
}
- scope->module()->Freeze();
- return body;
+ scope_->module()->Freeze();
+ return NULL;
}
Index: src/parser.h
diff --git a/src/parser.h b/src/parser.h
index
bc0b7ab51b0546257d807260331c540098d6d133..26255b28cb4b947128401a77db1fb321113d2edf
100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -703,7 +703,7 @@ class Parser : public ParserBase<ParserTraits> {
void* ParseStatementList(ZoneList<Statement*>* body, int end_token,
bool is_eval, Scope** ad_hoc_eval_scope, bool*
ok);
Statement* ParseStatementListItem(bool* ok);
- Statement* ParseModule(bool* ok);
+ void* ParseModule(ZoneList<Statement*>* body, bool* ok);
Statement* ParseModuleItem(bool* ok);
Literal* ParseModuleSpecifier(bool* ok);
Statement* ParseImportDeclaration(bool* ok);
Index: test/cctest/test-parsing.cc
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index
a62504f23c11585aa6798695ccd2d692e69c5cbb..31d3ce34bd0244a7a31580c0aa2f4ee5f0f804b0
100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -5072,12 +5072,8 @@ TEST(BasicImportExportParsing) {
128 * 1024);
for (unsigned i = 0; i < arraysize(kSources); ++i) {
- int kProgramByteSize = i::StrLength(kSources[i]);
- i::ScopedVector<char> program(kProgramByteSize + 1);
- i::SNPrintF(program, "%s", kSources[i]);
i::Handle<i::String> source =
- factory->NewStringFromUtf8(i::CStrVector(program.start()))
- .ToHandleChecked();
+ factory->NewStringFromAsciiChecked(kSources[i]);
// Show that parsing as a module works
{
@@ -5197,12 +5193,8 @@ TEST(ImportExportParsingErrors) {
128 * 1024);
for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
- int kProgramByteSize = i::StrLength(kErrorSources[i]);
- i::ScopedVector<char> program(kProgramByteSize + 1);
- i::SNPrintF(program, "%s", kErrorSources[i]);
i::Handle<i::String> source =
- factory->NewStringFromUtf8(i::CStrVector(program.start()))
- .ToHandleChecked();
+ factory->NewStringFromAsciiChecked(kErrorSources[i]);
i::Handle<i::Script> script = factory->NewScript(source);
i::CompilationInfoWithZone info(script);
@@ -5217,6 +5209,43 @@ TEST(ImportExportParsingErrors) {
}
+TEST(ModuleParsingInternals) {
+ i::Isolate* isolate = CcTest::i_isolate();
+ i::Factory* factory = isolate->factory();
+ v8::HandleScope handles(CcTest::isolate());
+ v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
+ v8::Context::Scope context_scope(context);
+ isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
+ 128 * 1024);
+
+ static const char kSource[] = "let x = 5; export { x as y };";
+ 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_classes(true);
+ parser.set_allow_harmony_modules(true);
+ parser.set_allow_harmony_scoping(true);
+ info.MarkAsModule();
+ CHECK(parser.Parse(&info));
+ i::FunctionLiteral* func = info.function();
+ 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_EQ(*name_x, *it.local_name());
+ CHECK_EQ(*name_y, *it.export_name());
+ }
+ CHECK_EQ(1, num_exports);
+}
+
+
TEST(DuplicateProtoError) {
const char* context_data[][2] = {
{"({", "});"},
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.