Index: src/d8.cc |
diff --git a/src/d8.cc b/src/d8.cc |
index 2458249d18cef06164c8e330abce2fcc9d2f1351..170eccddb6de055e3d81c09d4b2043558c695d2f 100644 |
--- a/src/d8.cc |
+++ b/src/d8.cc |
@@ -9,6 +9,8 @@ |
#include <algorithm> |
#include <fstream> |
+#include <map> |
+#include <utility> |
#include <vector> |
#ifdef ENABLE_VTUNE_JIT_INTERFACE |
@@ -461,7 +463,7 @@ MaybeLocal<Script> Shell::CompileString( |
// Executes a string within the current v8 context. |
bool Shell::ExecuteString(Isolate* isolate, Local<String> source, |
Local<Value> name, bool print_result, |
- bool report_exceptions, SourceType source_type) { |
+ bool report_exceptions) { |
HandleScope handle_scope(isolate); |
TryCatch try_catch(isolate); |
try_catch.SetVerbose(true); |
@@ -472,31 +474,14 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source, |
Local<Context> realm = |
Local<Context>::New(isolate, data->realms_[data->realm_current_]); |
Context::Scope context_scope(realm); |
- if (source_type == SCRIPT) { |
- Local<Script> script; |
- if (!Shell::CompileString(isolate, source, name, options.compile_options) |
- .ToLocal(&script)) { |
- // Print errors that happened during compilation. |
- if (report_exceptions) ReportException(isolate, &try_catch); |
- return false; |
- } |
- maybe_result = script->Run(realm); |
- } else { |
- DCHECK_EQ(MODULE, source_type); |
- Local<Module> module; |
- ScriptOrigin origin(name); |
- ScriptCompiler::Source script_source(source, origin); |
- // TODO(adamk): Make use of compile options for Modules. |
- if (!ScriptCompiler::CompileModule(isolate, &script_source) |
- .ToLocal(&module)) { |
- // Print errors that happened during compilation. |
- if (report_exceptions) ReportException(isolate, &try_catch); |
- return false; |
- } |
- // This can't fail until we support linking. |
- CHECK(module->Instantiate(realm)); |
- maybe_result = module->Evaluate(realm); |
+ Local<Script> script; |
+ if (!Shell::CompileString(isolate, source, name, options.compile_options) |
+ .ToLocal(&script)) { |
+ // Print errors that happened during compilation. |
+ if (report_exceptions) ReportException(isolate, &try_catch); |
+ return false; |
} |
+ maybe_result = script->Run(realm); |
EmptyMessageQueues(isolate); |
data->realm_current_ = data->realm_switch_; |
} |
@@ -526,6 +511,95 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source, |
return true; |
} |
+MaybeLocal<Module> Shell::FetchModuleTree( |
+ Isolate* isolate, const std::string& file_name, |
+ std::map<std::string, Global<Module>>* module_map) { |
+ TryCatch try_catch(isolate); |
+ try_catch.SetVerbose(true); |
+ Local<String> source_text = ReadFile(isolate, file_name.c_str()); |
+ if (source_text.IsEmpty()) { |
+ printf("Error reading '%s'\n", file_name.c_str()); |
+ Shell::Exit(1); |
+ } |
+ ScriptOrigin origin( |
+ String::NewFromUtf8(isolate, file_name.c_str(), NewStringType::kNormal) |
+ .ToLocalChecked()); |
+ ScriptCompiler::Source source(source_text, origin); |
+ Local<Module> module; |
+ if (!ScriptCompiler::CompileModule(isolate, &source).ToLocal(&module)) { |
+ ReportException(isolate, &try_catch); |
+ return MaybeLocal<Module>(); |
+ } |
+ module_map->insert( |
+ std::make_pair(file_name, Global<Module>(isolate, module))); |
+ for (int i = 0, length = module->GetModuleRequestsLength(); i < length; ++i) { |
+ Local<String> name = module->GetModuleRequest(i); |
+ // TODO(adamk): Resolve the imported module to a full path. |
+ std::string str = *String::Utf8Value(name); |
+ if (!module_map->count(str)) { |
+ if (FetchModuleTree(isolate, str, module_map).IsEmpty()) { |
+ return MaybeLocal<Module>(); |
+ } |
+ } |
+ } |
+ |
+ return module; |
+} |
+ |
+namespace { |
+ |
+MaybeLocal<Module> ResolveModuleCallback(Local<Context> context, |
+ Local<String> specifier, |
+ Local<Module> referrer, |
+ Local<Value> data) { |
+ Isolate* isolate = context->GetIsolate(); |
+ auto module_map = static_cast<std::map<std::string, Global<Module>>*>( |
+ External::Cast(*data)->Value()); |
+ std::string str_specifier = *String::Utf8Value(specifier); |
+ // TODO(adamk): Resolve the specifier using the referrer |
+ auto it = module_map->find(str_specifier); |
+ if (it != module_map->end()) { |
+ return it->second.Get(isolate); |
+ } |
+ return MaybeLocal<Module>(); |
+} |
+ |
+} // anonymous namespace |
+ |
+bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) { |
+ HandleScope handle_scope(isolate); |
+ |
+ Local<Module> root_module; |
+ std::map<std::string, Global<Module>> module_map; |
+ if (!FetchModuleTree(isolate, file_name, &module_map).ToLocal(&root_module)) { |
+ return false; |
+ } |
+ |
+ TryCatch try_catch(isolate); |
+ try_catch.SetVerbose(true); |
+ |
+ MaybeLocal<Value> maybe_result; |
+ { |
+ PerIsolateData* data = PerIsolateData::Get(isolate); |
+ Local<Context> realm = data->realms_[data->realm_current_].Get(isolate); |
+ Context::Scope context_scope(realm); |
+ |
+ // This can't fail until we support linking. |
+ CHECK(root_module->Instantiate(realm, ResolveModuleCallback, |
+ External::New(isolate, &module_map))); |
+ maybe_result = root_module->Evaluate(realm); |
+ EmptyMessageQueues(isolate); |
+ } |
+ Local<Value> result; |
+ if (!maybe_result.ToLocal(&result)) { |
+ DCHECK(try_catch.HasCaught()); |
+ // Print errors that happened during execution. |
+ ReportException(isolate, &try_catch); |
+ return false; |
+ } |
+ DCHECK(!try_catch.HasCaught()); |
+ return true; |
+} |
PerIsolateData::RealmScope::RealmScope(PerIsolateData* data) : data_(data) { |
data_->realm_count_ = 1; |
@@ -1580,7 +1654,6 @@ void SourceGroup::Execute(Isolate* isolate) { |
bool exception_was_thrown = false; |
for (int i = begin_offset_; i < end_offset_; ++i) { |
const char* arg = argv_[i]; |
- Shell::SourceType source_type = Shell::SCRIPT; |
if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) { |
// Execute argument given to -e option directly. |
HandleScope handle_scope(isolate); |
@@ -1599,8 +1672,13 @@ void SourceGroup::Execute(Isolate* isolate) { |
continue; |
} else if (strcmp(arg, "--module") == 0 && i + 1 < end_offset_) { |
// Treat the next file as a module. |
- source_type = Shell::MODULE; |
arg = argv_[++i]; |
+ Shell::options.script_executed = true; |
+ if (!Shell::ExecuteModule(isolate, arg)) { |
+ exception_was_thrown = true; |
+ break; |
+ } |
+ continue; |
} else if (arg[0] == '-') { |
// Ignore other options. They have been parsed already. |
continue; |
@@ -1617,8 +1695,7 @@ void SourceGroup::Execute(Isolate* isolate) { |
Shell::Exit(1); |
} |
Shell::options.script_executed = true; |
- if (!Shell::ExecuteString(isolate, source, file_name, false, true, |
- source_type)) { |
+ if (!Shell::ExecuteString(isolate, source, file_name, false, true)) { |
exception_was_thrown = true; |
break; |
} |