Index: src/d8.cc |
diff --git a/src/d8.cc b/src/d8.cc |
index 170eccddb6de055e3d81c09d4b2043558c695d2f..43049499ab7a7f5b115c41b99fba13da61c44852 100644 |
--- a/src/d8.cc |
+++ b/src/d8.cc |
@@ -511,9 +511,64 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source, |
return true; |
} |
+namespace { |
+ |
+bool IsAbsolutePath(const char* path) { |
+#if defined(_WIN32) || defined(_WIN64) |
+ // TODO(adamk): This is an incorrect approximation, but should |
+ // work for all our test-running cases. |
+ return strchr(path, ':') != nullptr; |
+#else |
+ return path[0] == '/'; |
+#endif |
+} |
+ |
+std::string GetWorkingDirectory() { |
+#if defined(_WIN32) || defined(_WIN64) |
+ char system_buffer[MAX_PATH]; |
+ // TODO(adamk): Support Unicode paths. |
+ DWORD len = GetCurrentDirectoryA(MAX_PATH, system_buffer); |
+ CHECK(len > 0); |
+ return system_buffer; |
+#else |
+ char curdir[PATH_MAX]; |
+ CHECK_NOT_NULL(getcwd(curdir, PATH_MAX)); |
+ return curdir; |
+#endif |
+} |
+ |
+std::string DirName(const std::string& path) { |
+ DCHECK(IsAbsolutePath(path.c_str())); |
+ size_t last_slash = path.find_last_of("/\\"); |
+ DCHECK(last_slash != std::string::npos); |
+ return path.substr(0, last_slash + 1); |
+} |
+ |
+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()); |
+ String::Utf8Value specifier_utf8(specifier); |
+ CHECK(!IsAbsolutePath(*specifier_utf8)); |
+ Local<String> dir_name = Local<String>::Cast(referrer->GetEmbedderData()); |
+ std::string absolute_path = *String::Utf8Value(dir_name); |
+ absolute_path.append(*specifier_utf8); |
+ auto it = module_map->find(absolute_path); |
+ if (it != module_map->end()) { |
+ return it->second.Get(isolate); |
+ } |
+ return MaybeLocal<Module>(); |
+} |
+ |
+} // anonymous namespace |
+ |
MaybeLocal<Module> Shell::FetchModuleTree( |
Isolate* isolate, const std::string& file_name, |
std::map<std::string, Global<Module>>* module_map) { |
+ DCHECK(IsAbsolutePath(file_name.c_str())); |
TryCatch try_catch(isolate); |
try_catch.SetVerbose(true); |
Local<String> source_text = ReadFile(isolate, file_name.c_str()); |
@@ -532,12 +587,24 @@ MaybeLocal<Module> Shell::FetchModuleTree( |
} |
module_map->insert( |
std::make_pair(file_name, Global<Module>(isolate, module))); |
+ |
+ std::string dir_name = DirName(file_name); |
+ module->SetEmbedderData( |
+ String::NewFromUtf8(isolate, dir_name.c_str(), NewStringType::kNormal) |
+ .ToLocalChecked()); |
+ |
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()) { |
+ String::Utf8Value utf8_value(name); |
+ std::string absolute_path; |
+ if (IsAbsolutePath(*utf8_value)) { |
+ absolute_path = *utf8_value; |
+ } else { |
+ absolute_path = dir_name; |
+ absolute_path.append(*utf8_value); |
+ } |
+ if (!module_map->count(absolute_path)) { |
+ if (FetchModuleTree(isolate, absolute_path, module_map).IsEmpty()) { |
return MaybeLocal<Module>(); |
} |
} |
@@ -546,32 +613,22 @@ MaybeLocal<Module> Shell::FetchModuleTree( |
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); |
+ std::string absolute_path; |
+ if (IsAbsolutePath(file_name)) { |
+ absolute_path = file_name; |
+ } else { |
+ absolute_path = GetWorkingDirectory(); |
+ absolute_path.push_back('/'); |
+ absolute_path.append(file_name); |
+ } |
+ |
Local<Module> root_module; |
std::map<std::string, Global<Module>> module_map; |
- if (!FetchModuleTree(isolate, file_name, &module_map).ToLocal(&root_module)) { |
+ if (!FetchModuleTree(isolate, absolute_path, &module_map) |
+ .ToLocal(&root_module)) { |
return false; |
} |