@@ -466,104 +466,37 @@ std::string ReadFile(uv_file file) {
466466 return contents;
467467}
468468
469- enum CheckFileOptions {
470- LEAVE_OPEN_AFTER_CHECK,
471- CLOSE_AFTER_CHECK
469+ enum DescriptorType {
470+ NONE,
471+ FILE,
472+ DIRECTORY
472473};
473474
474- Maybe<uv_file> CheckFile (const std::string& path,
475- CheckFileOptions opt = CLOSE_AFTER_CHECK) {
475+ DescriptorType CheckDescriptor (const std::string& path) {
476476 uv_fs_t fs_req;
477- if (path.empty ()) {
478- return Nothing<uv_file>();
479- }
480-
481- uv_file fd = uv_fs_open (nullptr , &fs_req, path.c_str (), O_RDONLY, 0 , nullptr );
482- uv_fs_req_cleanup (&fs_req);
483-
484- if (fd < 0 ) {
485- return Nothing<uv_file>();
486- }
487-
488- uv_fs_fstat (nullptr , &fs_req, fd, nullptr );
489- uint64_t is_directory = fs_req.statbuf .st_mode & S_IFDIR;
490- uv_fs_req_cleanup (&fs_req);
491-
492- if (is_directory) {
493- CHECK_EQ (0 , uv_fs_close (nullptr , &fs_req, fd, nullptr ));
494- uv_fs_req_cleanup (&fs_req);
495- return Nothing<uv_file>();
496- }
497-
498- if (opt == CLOSE_AFTER_CHECK) {
499- CHECK_EQ (0 , uv_fs_close (nullptr , &fs_req, fd, nullptr ));
477+ int rc = uv_fs_stat (nullptr , &fs_req, path.c_str (), nullptr );
478+ if (rc == 0 ) {
479+ uint64_t is_directory = fs_req.statbuf .st_mode & S_IFDIR;
500480 uv_fs_req_cleanup (&fs_req);
481+ return is_directory ? DIRECTORY : FILE;
501482 }
502-
503- return Just (fd);
504- }
505-
506- enum ResolveExtensionsOptions {
507- TRY_EXACT_NAME,
508- ONLY_VIA_EXTENSIONS
509- };
510-
511- inline bool ResolvesToFile (const URL& search) {
512- std::string filePath = search.ToFilePath ();
513- Maybe<uv_file> check = CheckFile (filePath);
514- return !check.IsNothing ();
515- }
516-
517- template <ResolveExtensionsOptions options>
518- Maybe<URL> ResolveExtensions (const URL& search) {
519- if (options == TRY_EXACT_NAME) {
520- std::string filePath = search.ToFilePath ();
521- Maybe<uv_file> check = CheckFile (filePath);
522- if (!check.IsNothing ()) {
523- return Just (search);
524- }
525- }
526-
527- for (const char * extension : EXTENSIONS) {
528- URL guess (search.path () + extension, &search);
529- Maybe<uv_file> check = CheckFile (guess.ToFilePath ());
530- if (!check.IsNothing ()) {
531- return Just (guess);
532- }
533- }
534-
535- return Nothing<URL>();
536- }
537-
538- inline Maybe<URL> ResolveIndex (const URL& search) {
539- return ResolveExtensions<ONLY_VIA_EXTENSIONS>(URL (" index" , search));
483+ uv_fs_req_cleanup (&fs_req);
484+ return NONE;
540485}
541486
542- Maybe<URL> ResolveModule (Environment* env,
543- const std::string& specifier,
544- const URL& base) {
487+ Maybe<URL> PackageResolve (Environment* env,
488+ const std::string& specifier,
489+ const URL& base) {
545490 URL parent (" ." , base);
546- URL dir ( " " ) ;
491+ std::string last_path ;
547492 do {
548- dir = parent;
549- Maybe<URL> check =
550- Resolve (env, " ./node_modules/" + specifier, dir);
551- if (!check.IsNothing ()) {
552- const size_t limit = specifier.find (' /' );
553- const size_t spec_len =
554- limit == std::string::npos ? specifier.length () :
555- limit + 1 ;
556- std::string chroot =
557- dir.path () + " node_modules/" + specifier.substr (0 , spec_len);
558- if (check.FromJust ().path ().substr (0 , chroot.length ()) != chroot) {
559- return Nothing<URL>();
560- }
561- return check;
562- } else {
563- // TODO(bmeck) PREVENT FALLTHROUGH
564- }
565- parent = URL (" .." , &dir);
566- } while (parent.path () != dir.path ());
493+ URL pkg_url (" ./node_modules/" + specifier, &parent);
494+ DescriptorType check = CheckDescriptor (pkg_url.ToFilePath ());
495+ if (check == FILE) return Just (pkg_url);
496+ last_path = parent.path ();
497+ parent = URL (" .." , &parent);
498+ // cross-platform root check
499+ } while (parent.path () != last_path);
567500 return Nothing<URL>();
568501}
569502
@@ -572,26 +505,27 @@ Maybe<URL> ResolveModule(Environment* env,
572505Maybe<URL> Resolve (Environment* env,
573506 const std::string& specifier,
574507 const URL& base) {
575- URL pure_url (specifier);
576- if (!(pure_url.flags () & URL_FLAGS_FAILED)) {
577- // just check existence, without altering
578- Maybe<uv_file> check = CheckFile (pure_url.ToFilePath ());
579- if (check.IsNothing ()) {
580- return Nothing<URL>();
508+ // Order swapped from spec for minor perf gain.
509+ // Ok since relative URLs cannot parse as URLs.
510+ URL resolved;
511+ if (ShouldBeTreatedAsRelativeOrAbsolutePath (specifier)) {
512+ resolved = URL (specifier, base);
513+ } else {
514+ URL pure_url (specifier);
515+ if (!(pure_url.flags () & URL_FLAGS_FAILED)) {
516+ resolved = pure_url;
517+ } else {
518+ return PackageResolve (env, specifier, base);
581519 }
582- return Just (pure_url);
583520 }
584- if (specifier.length () == 0 ) {
521+ DescriptorType check = CheckDescriptor (resolved.ToFilePath ());
522+ if (check != FILE) {
523+ std::string msg = " Cannot find module '" + resolved.ToFilePath () +
524+ " ' imported from " + base.ToFilePath ();
525+ node::THROW_ERR_MODULE_NOT_FOUND (env, msg.c_str ());
585526 return Nothing<URL>();
586527 }
587- if (ShouldBeTreatedAsRelativeOrAbsolutePath (specifier)) {
588- URL resolved (specifier, base);
589- if (ResolvesToFile (resolved))
590- return Just (resolved);
591- return Nothing<URL>();
592- } else {
593- return ResolveModule (env, specifier, base);
594- }
528+ return Just (resolved);
595529}
596530
597531void ModuleWrap::Resolve (const FunctionCallbackInfo<Value>& args) {
@@ -613,10 +547,18 @@ void ModuleWrap::Resolve(const FunctionCallbackInfo<Value>& args) {
613547 env, " second argument is not a URL string" );
614548 }
615549
550+ TryCatchScope try_catch (env);
616551 Maybe<URL> result = node::loader::Resolve (env, specifier_std, url);
617- if (result.IsNothing () || (result.FromJust ().flags () & URL_FLAGS_FAILED)) {
618- std::string msg = " Cannot find module " + specifier_std;
619- return node::THROW_ERR_MISSING_MODULE (env, msg.c_str ());
552+ if (try_catch.HasCaught ()) {
553+ try_catch.ReThrow ();
554+ return ;
555+ } else if (result.IsNothing () ||
556+ (result.FromJust ().flags () & URL_FLAGS_FAILED)) {
557+ std::string msg = " Cannot find module '" + specifier_std +
558+ " ' imported from " + url.ToFilePath ();
559+ node::THROW_ERR_MODULE_NOT_FOUND (env, msg.c_str ());
560+ try_catch.ReThrow ();
561+ return ;
620562 }
621563
622564 MaybeLocal<Value> obj = result.FromJust ().ToObject (env);
0 commit comments