summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/module_wrap.cc158
-rw-r--r--src/node_errors.h2
2 files changed, 51 insertions, 109 deletions
diff --git a/src/module_wrap.cc b/src/module_wrap.cc
index 933ff65201..6214888286 100644
--- a/src/module_wrap.cc
+++ b/src/module_wrap.cc
@@ -467,104 +467,37 @@ std::string ReadFile(uv_file file) {
return contents;
}
-enum CheckFileOptions {
- LEAVE_OPEN_AFTER_CHECK,
- CLOSE_AFTER_CHECK
+enum DescriptorType {
+ NONE,
+ FILE,
+ DIRECTORY
};
-Maybe<uv_file> CheckFile(const std::string& path,
- CheckFileOptions opt = CLOSE_AFTER_CHECK) {
+DescriptorType CheckDescriptor(const std::string& path) {
uv_fs_t fs_req;
- if (path.empty()) {
- return Nothing<uv_file>();
- }
-
- uv_file fd = uv_fs_open(nullptr, &fs_req, path.c_str(), O_RDONLY, 0, nullptr);
- uv_fs_req_cleanup(&fs_req);
-
- if (fd < 0) {
- return Nothing<uv_file>();
- }
-
- uv_fs_fstat(nullptr, &fs_req, fd, nullptr);
- uint64_t is_directory = fs_req.statbuf.st_mode & S_IFDIR;
- uv_fs_req_cleanup(&fs_req);
-
- if (is_directory) {
- CHECK_EQ(0, uv_fs_close(nullptr, &fs_req, fd, nullptr));
- uv_fs_req_cleanup(&fs_req);
- return Nothing<uv_file>();
- }
-
- if (opt == CLOSE_AFTER_CHECK) {
- CHECK_EQ(0, uv_fs_close(nullptr, &fs_req, fd, nullptr));
+ int rc = uv_fs_stat(nullptr, &fs_req, path.c_str(), nullptr);
+ if (rc == 0) {
+ uint64_t is_directory = fs_req.statbuf.st_mode & S_IFDIR;
uv_fs_req_cleanup(&fs_req);
+ return is_directory ? DIRECTORY : FILE;
}
-
- return Just(fd);
-}
-
-enum ResolveExtensionsOptions {
- TRY_EXACT_NAME,
- ONLY_VIA_EXTENSIONS
-};
-
-inline bool ResolvesToFile(const URL& search) {
- std::string filePath = search.ToFilePath();
- Maybe<uv_file> check = CheckFile(filePath);
- return !check.IsNothing();
-}
-
-template <ResolveExtensionsOptions options>
-Maybe<URL> ResolveExtensions(const URL& search) {
- if (options == TRY_EXACT_NAME) {
- std::string filePath = search.ToFilePath();
- Maybe<uv_file> check = CheckFile(filePath);
- if (!check.IsNothing()) {
- return Just(search);
- }
- }
-
- for (const char* extension : EXTENSIONS) {
- URL guess(search.path() + extension, &search);
- Maybe<uv_file> check = CheckFile(guess.ToFilePath());
- if (!check.IsNothing()) {
- return Just(guess);
- }
- }
-
- return Nothing<URL>();
-}
-
-inline Maybe<URL> ResolveIndex(const URL& search) {
- return ResolveExtensions<ONLY_VIA_EXTENSIONS>(URL("index", search));
+ uv_fs_req_cleanup(&fs_req);
+ return NONE;
}
-Maybe<URL> ResolveModule(Environment* env,
- const std::string& specifier,
- const URL& base) {
+Maybe<URL> PackageResolve(Environment* env,
+ const std::string& specifier,
+ const URL& base) {
URL parent(".", base);
- URL dir("");
+ std::string last_path;
do {
- dir = parent;
- Maybe<URL> check =
- Resolve(env, "./node_modules/" + specifier, dir);
- if (!check.IsNothing()) {
- const size_t limit = specifier.find('/');
- const size_t spec_len =
- limit == std::string::npos ? specifier.length() :
- limit + 1;
- std::string chroot =
- dir.path() + "node_modules/" + specifier.substr(0, spec_len);
- if (check.FromJust().path().substr(0, chroot.length()) != chroot) {
- return Nothing<URL>();
- }
- return check;
- } else {
- // TODO(bmeck) PREVENT FALLTHROUGH
- }
- parent = URL("..", &dir);
- } while (parent.path() != dir.path());
+ URL pkg_url("./node_modules/" + specifier, &parent);
+ DescriptorType check = CheckDescriptor(pkg_url.ToFilePath());
+ if (check == FILE) return Just(pkg_url);
+ last_path = parent.path();
+ parent = URL("..", &parent);
+ // cross-platform root check
+ } while (parent.path() != last_path);
return Nothing<URL>();
}
@@ -573,26 +506,27 @@ Maybe<URL> ResolveModule(Environment* env,
Maybe<URL> Resolve(Environment* env,
const std::string& specifier,
const URL& base) {
- URL pure_url(specifier);
- if (!(pure_url.flags() & URL_FLAGS_FAILED)) {
- // just check existence, without altering
- Maybe<uv_file> check = CheckFile(pure_url.ToFilePath());
- if (check.IsNothing()) {
- return Nothing<URL>();
+ // Order swapped from spec for minor perf gain.
+ // Ok since relative URLs cannot parse as URLs.
+ URL resolved;
+ if (ShouldBeTreatedAsRelativeOrAbsolutePath(specifier)) {
+ resolved = URL(specifier, base);
+ } else {
+ URL pure_url(specifier);
+ if (!(pure_url.flags() & URL_FLAGS_FAILED)) {
+ resolved = pure_url;
+ } else {
+ return PackageResolve(env, specifier, base);
}
- return Just(pure_url);
}
- if (specifier.length() == 0) {
+ DescriptorType check = CheckDescriptor(resolved.ToFilePath());
+ if (check != FILE) {
+ std::string msg = "Cannot find module '" + resolved.ToFilePath() +
+ "' imported from " + base.ToFilePath();
+ node::THROW_ERR_MODULE_NOT_FOUND(env, msg.c_str());
return Nothing<URL>();
}
- if (ShouldBeTreatedAsRelativeOrAbsolutePath(specifier)) {
- URL resolved(specifier, base);
- if (ResolvesToFile(resolved))
- return Just(resolved);
- return Nothing<URL>();
- } else {
- return ResolveModule(env, specifier, base);
- }
+ return Just(resolved);
}
void ModuleWrap::Resolve(const FunctionCallbackInfo<Value>& args) {
@@ -614,10 +548,18 @@ void ModuleWrap::Resolve(const FunctionCallbackInfo<Value>& args) {
env, "second argument is not a URL string");
}
+ TryCatch try_catch(env->isolate());
Maybe<URL> result = node::loader::Resolve(env, specifier_std, url);
- if (result.IsNothing() || (result.FromJust().flags() & URL_FLAGS_FAILED)) {
- std::string msg = "Cannot find module " + specifier_std;
- return node::THROW_ERR_MISSING_MODULE(env, msg.c_str());
+ if (try_catch.HasCaught()) {
+ try_catch.ReThrow();
+ return;
+ } else if (result.IsNothing() ||
+ (result.FromJust().flags() & URL_FLAGS_FAILED)) {
+ std::string msg = "Cannot find module '" + specifier_std +
+ "' imported from " + url.ToFilePath();
+ node::THROW_ERR_MODULE_NOT_FOUND(env, msg.c_str());
+ try_catch.ReThrow();
+ return;
}
args.GetReturnValue().Set(result.FromJust().ToObject(env));
diff --git a/src/node_errors.h b/src/node_errors.h
index 7638ff4251..7b516fb140 100644
--- a/src/node_errors.h
+++ b/src/node_errors.h
@@ -63,8 +63,8 @@ void FatalException(const v8::FunctionCallbackInfo<v8::Value>& args);
V(ERR_MEMORY_ALLOCATION_FAILED, Error) \
V(ERR_MISSING_ARGS, TypeError) \
V(ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST, TypeError) \
- V(ERR_MISSING_MODULE, Error) \
V(ERR_MISSING_PLATFORM_FOR_WORKER, Error) \
+ V(ERR_MODULE_NOT_FOUND, Error) \
V(ERR_OUT_OF_RANGE, RangeError) \
V(ERR_SCRIPT_EXECUTION_INTERRUPTED, Error) \
V(ERR_SCRIPT_EXECUTION_TIMEOUT, Error) \