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