Skip to content

Commit fe9109b

Browse files
committed
src: simplify legacy resolve functionality
1 parent f870bbc commit fe9109b

File tree

2 files changed

+86
-125
lines changed

2 files changed

+86
-125
lines changed

src/node_file.cc

Lines changed: 68 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,7 @@ void AfterOpenFileHandle(uv_fs_t* req) {
845845
// Reverse the logic applied by path.toNamespacedPath() to create a
846846
// namespace-prefixed path.
847847
void FromNamespacedPath(std::string* path) {
848+
DCHECK_NOT_NULL(path);
848849
#ifdef _WIN32
849850
if (path->compare(0, 8, "\\\\?\\UNC\\", 8) == 0) {
850851
*path = path->substr(8);
@@ -2729,70 +2730,55 @@ static void Mkdtemp(const FunctionCallbackInfo<Value>& args) {
27292730
}
27302731
}
27312732

2732-
static bool FileURLToPath(
2733-
Environment* env,
2734-
const ada::url_aggregator& file_url,
2735-
/* The linter can't detect the assign for result_file_path
2736-
So we need to ignore since it suggest to put const */
2737-
// NOLINTNEXTLINE(runtime/references)
2738-
std::string& result_file_path) {
2733+
static bool FileURLToPath(Environment* env,
2734+
const ada::url_aggregator& file_url,
2735+
std::string* result_file_path) {
2736+
DCHECK_NOT_NULL(result_file_path);
27392737
if (file_url.type != ada::scheme::FILE) {
2740-
env->isolate()->ThrowException(ERR_INVALID_URL_SCHEME(env->isolate()));
2741-
2738+
THROW_ERR_INVALID_URL_SCHEME(env);
27422739
return false;
27432740
}
27442741

27452742
std::string_view pathname = file_url.get_pathname();
27462743
#ifdef _WIN32
2747-
size_t first_percent = std::string::npos;
27482744
size_t pathname_size = pathname.size();
2749-
std::string pathname_escaped_slash;
2745+
std::string pathname_escaped_slash{};
2746+
pathname_escaped_slash.reserve(pathname_size);
27502747

27512748
for (size_t i = 0; i < pathname_size; i++) {
27522749
if (pathname[i] == '/') {
27532750
pathname_escaped_slash += '\\';
2754-
} else {
2755-
pathname_escaped_slash += pathname[i];
2751+
continue;
27562752
}
27572753

2758-
if (pathname[i] != '%') continue;
2759-
2760-
if (first_percent == std::string::npos) {
2761-
first_percent = i;
2762-
}
2763-
2764-
// just safe-guard against access the pathname
2765-
// outside the bounds
2766-
if ((i + 2) >= pathname_size) continue;
2767-
2768-
char third = pathname[i + 2] | 0x20;
2754+
pathname_escaped_slash += pathname[i];
27692755

2770-
bool is_slash = pathname[i + 1] == '2' && third == 102;
2771-
bool is_forward_slash = pathname[i + 1] == '5' && third == 99;
2756+
if (pathname[i] == '%' && (i + 2) <= pathname_size) {
2757+
char third = pathname[i + 2] | 0x20;
2758+
bool is_slash = pathname[i + 1] == '2' && third == 102;
2759+
bool is_forward_slash = pathname[i + 1] == '5' && third == 99;
27722760

2773-
if (!is_slash && !is_forward_slash) continue;
2774-
2775-
env->isolate()->ThrowException(ERR_INVALID_FILE_URL_PATH(
2776-
env->isolate(),
2777-
"File URL path must not include encoded \\ or / characters"));
2778-
2779-
return false;
2761+
if (is_slash || is_forward_slash) {
2762+
THROW_ERR_INVALID_FILE_URL_PATH(
2763+
env, "File URL path must not include encoded \\ or / characters");
2764+
return false;
2765+
}
2766+
}
27802767
}
27812768

2782-
std::string_view hostname = file_url.get_hostname();
27832769
std::string decoded_pathname = ada::unicode::percent_decode(
2784-
std::string_view(pathname_escaped_slash), first_percent);
2770+
pathname_escaped_slash, pathname_escaped_slash.find('%'));
27852771

2786-
if (hostname.size() > 0) {
2772+
if (!file_url.has_empty_hostname()) {
27872773
// If hostname is set, then we have a UNC path
27882774
// Pass the hostname through domainToUnicode just in case
27892775
// it is an IDN using punycode encoding. We do not need to worry
27902776
// about percent encoding because the URL parser will have
27912777
// already taken care of that for us. Note that this only
27922778
// causes IDNs with an appropriate `xn--` prefix to be decoded.
2793-
result_file_path =
2794-
"\\\\" + ada::unicode::to_unicode(hostname) + decoded_pathname;
2795-
2779+
*result_file_path = "\\\\" +
2780+
ada::unicode::to_unicode(file_url.get_hostname()) +
2781+
decoded_pathname;
27962782
return true;
27972783
}
27982784

@@ -2801,62 +2787,51 @@ static bool FileURLToPath(
28012787

28022788
// a..z A..Z
28032789
if (letter < 'a' || letter > 'z' || sep != ':') {
2804-
env->isolate()->ThrowException(ERR_INVALID_FILE_URL_PATH(
2805-
env->isolate(), "File URL path must be absolute"));
2806-
2790+
THROW_ERR_INVALID_FILE_URL_PATH(env, "File URL path must be absolute");
28072791
return false;
28082792
}
28092793

2810-
result_file_path = decoded_pathname.substr(1);
2794+
*result_file_path = decoded_pathname.substr(1);
28112795

28122796
return true;
28132797
#else // _WIN32
2814-
std::string_view hostname = file_url.get_hostname();
2815-
2816-
if (hostname.size() > 0) {
2798+
if (!file_url.has_empty_hostname()) {
28172799
std::string error_message =
2818-
std::string("File URL host must be \"localhost\" or empty on ") +
2800+
"File URL host must be \"localhost\" or empty on " +
28192801
std::string(per_process::metadata.platform);
2820-
env->isolate()->ThrowException(
2821-
ERR_INVALID_FILE_URL_HOST(env->isolate(), error_message.c_str()));
2822-
2802+
THROW_ERR_INVALID_FILE_URL_HOST(env, error_message.c_str());
28232803
return false;
28242804
}
28252805

2826-
size_t first_percent = std::string::npos;
2827-
for (size_t i = 0; (i + 2) < pathname.size(); i++) {
2828-
if (pathname[i] != '%') continue;
2829-
2830-
if (first_percent == std::string::npos) {
2831-
first_percent = i;
2832-
}
2806+
auto first_percent = pathname.find('%');
28332807

2834-
if (pathname[i + 1] == '2' && (pathname[i + 2] | 0x20) == 102) {
2835-
env->isolate()->ThrowException(ERR_INVALID_FILE_URL_PATH(
2836-
env->isolate(),
2837-
"File URL path must not include encoded / characters"));
2838-
2839-
return false;
2808+
if (first_percent != std::string_view::npos) {
2809+
for (size_t i = first_percent; (i + 2) < pathname.size(); i++) {
2810+
if (pathname[i + 1] == '2' && (pathname[i + 2] | 0x20) == 102) {
2811+
THROW_ERR_INVALID_FILE_URL_PATH(
2812+
env, "File URL path must not include encoded / characters");
2813+
return false;
2814+
}
28402815
}
28412816
}
28422817

2843-
result_file_path = ada::unicode::percent_decode(pathname, first_percent);
2818+
*result_file_path = ada::unicode::percent_decode(pathname, first_percent);
28442819

28452820
return true;
28462821
#endif // _WIN32
28472822
}
28482823

28492824
BindingData::FilePathIsFileReturnType BindingData::FilePathIsFile(
2850-
Environment* env, const std::string& file_path) {
2825+
Environment* env, const std::string_view file_path) {
28512826
THROW_IF_INSUFFICIENT_PERMISSIONS(
28522827
env,
28532828
permission::PermissionScope::kFileSystemRead,
28542829
file_path,
2855-
BindingData::FilePathIsFileReturnType::kThrowInsufficientPermissions);
2830+
FilePathIsFileReturnType::kThrowInsufficientPermissions);
28562831

28572832
uv_fs_t req;
28582833

2859-
int rc = uv_fs_stat(env->event_loop(), &req, file_path.c_str(), nullptr);
2834+
int rc = uv_fs_stat(env->event_loop(), &req, file_path.data(), nullptr);
28602835

28612836
if (rc == 0) {
28622837
const uv_stat_t* const s = static_cast<const uv_stat_t*>(req.ptr);
@@ -2871,22 +2846,6 @@ BindingData::FilePathIsFileReturnType BindingData::FilePathIsFile(
28712846
return BindingData::FilePathIsFileReturnType::kIsNotFile;
28722847
}
28732848

2874-
// the possible file extensions that should be tested
2875-
// 0-6: when packageConfig.main is defined
2876-
// 7-9: when packageConfig.main is NOT defined,
2877-
// or when the previous case didn't found the file
2878-
const std::array<std::string, 10> BindingData::legacy_main_extensions = {
2879-
"",
2880-
".js",
2881-
".json",
2882-
".node",
2883-
"/index.js",
2884-
"/index.json",
2885-
"/index.node",
2886-
".js",
2887-
".json",
2888-
".node"};
2889-
28902849
void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
28912850
CHECK_GE(args.Length(), 1);
28922851
CHECK(args[0]->IsString());
@@ -2898,38 +2857,32 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
28982857
ada::parse<ada::url_aggregator>(utf8_package_json_url.ToStringView());
28992858

29002859
if (!package_json_url) {
2901-
env->isolate()->ThrowException(
2902-
ERR_INVALID_URL(env->isolate(), "Invalid URL"));
2903-
2860+
THROW_ERR_INVALID_URL(env, "Invalid URL");
29042861
return;
29052862
}
29062863

29072864
ada::result<ada::url_aggregator> file_path_url;
29082865
std::string initial_file_path;
2909-
std::string file_path;
29102866

2911-
if (args.Length() >= 2 && !args[1]->IsNullOrUndefined() &&
2912-
args[1]->IsString()) {
2867+
if (args.Length() >= 2 && args[1]->IsString()) {
29132868
std::string package_config_main =
29142869
Utf8Value(env->isolate(), args[1].As<String>()).ToString();
29152870

2916-
file_path_url = ada::parse<ada::url_aggregator>(
2917-
std::string("./") + package_config_main, &package_json_url.value());
2871+
file_path_url = ada::parse<ada::url_aggregator>("./" + package_config_main,
2872+
&package_json_url.value());
29182873

29192874
if (!file_path_url) {
2920-
env->isolate()->ThrowException(
2921-
ERR_INVALID_URL(env->isolate(), "Invalid URL"));
2922-
2875+
THROW_ERR_INVALID_URL(env, "Invalid URL");
29232876
return;
29242877
}
29252878

2926-
if (!FileURLToPath(env, file_path_url.value(), initial_file_path)) return;
2879+
if (!FileURLToPath(env, *file_path_url, &initial_file_path)) return;
29272880

29282881
FromNamespacedPath(&initial_file_path);
29292882

2930-
for (int i = 0; i < BindingData::legacy_main_extensions_with_main_end;
2931-
i++) {
2932-
file_path = initial_file_path + BindingData::legacy_main_extensions[i];
2883+
for (int i = 0; i < legacy_main_extensions_with_main_end; i++) {
2884+
auto file_path = initial_file_path +
2885+
std::string(BindingData::legacy_main_extensions[i]);
29332886

29342887
switch (FilePathIsFile(env, file_path)) {
29352888
case BindingData::FilePathIsFileReturnType::kIsFile:
@@ -2952,20 +2905,19 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
29522905
ada::parse<ada::url_aggregator>("./index", &package_json_url.value());
29532906

29542907
if (!file_path_url) {
2955-
env->isolate()->ThrowException(
2956-
ERR_INVALID_URL(env->isolate(), "Invalid URL"));
2957-
2908+
THROW_ERR_INVALID_URL(env, "Invalid URL");
29582909
return;
29592910
}
29602911

2961-
if (!FileURLToPath(env, file_path_url.value(), initial_file_path)) return;
2912+
if (!FileURLToPath(env, *file_path_url, &initial_file_path)) return;
29622913

29632914
FromNamespacedPath(&initial_file_path);
29642915

2965-
for (int i = BindingData::legacy_main_extensions_with_main_end;
2966-
i < BindingData::legacy_main_extensions_package_fallback_end;
2916+
for (int i = legacy_main_extensions_with_main_end;
2917+
i < legacy_main_extensions_package_fallback_end;
29672918
i++) {
2968-
file_path = initial_file_path + BindingData::legacy_main_extensions[i];
2919+
auto file_path =
2920+
initial_file_path + std::string(BindingData::legacy_main_extensions[i]);
29692921

29702922
switch (FilePathIsFile(env, file_path)) {
29712923
case BindingData::FilePathIsFileReturnType::kIsFile:
@@ -2985,34 +2937,29 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
29852937
std::string module_path;
29862938
std::string module_base;
29872939

2988-
if (!FileURLToPath(env, package_json_url.value(), module_path)) return;
2940+
if (!FileURLToPath(env, *package_json_url, &module_path)) return;
29892941

2990-
if (args.Length() >= 3 && !args[2]->IsNullOrUndefined() &&
2991-
args[2]->IsString()) {
2942+
if (args.Length() >= 3 && args[2]->IsString()) {
29922943
Utf8Value utf8_base_path(env->isolate(), args[2].As<String>());
29932944
auto base_url =
29942945
ada::parse<ada::url_aggregator>(utf8_base_path.ToStringView());
29952946

29962947
if (!base_url) {
2997-
env->isolate()->ThrowException(
2998-
ERR_INVALID_URL(env->isolate(), "Invalid URL"));
2999-
2948+
THROW_ERR_INVALID_URL(env->isolate(), "Invalid URL");
30002949
return;
30012950
}
30022951

3003-
if (!FileURLToPath(env, base_url.value(), module_base)) return;
3004-
} else {
3005-
std::string err_arg_message =
3006-
"The \"base\" argument must be of type string or an instance of URL.";
3007-
env->isolate()->ThrowException(
3008-
ERR_INVALID_ARG_TYPE(env->isolate(), err_arg_message.c_str()));
2952+
if (!FileURLToPath(env, *base_url, &module_base)) return;
2953+
2954+
std::string err_module_message = "Cannot find package '" + module_path +
2955+
"' imported from " + module_base;
2956+
THROW_ERR_MODULE_NOT_FOUND(env, err_module_message.c_str());
30092957
return;
30102958
}
30112959

3012-
std::string err_module_message =
3013-
"Cannot find package '" + module_path + "' imported from " + module_base;
3014-
env->isolate()->ThrowException(
3015-
ERR_MODULE_NOT_FOUND(env->isolate(), err_module_message.c_str()));
2960+
THROW_ERR_INVALID_ARG_TYPE(
2961+
env,
2962+
"The \"base\" argument must be of type string or an instance of URL.");
30162963
}
30172964

30182965
void BindingData::MemoryInfo(MemoryTracker* tracker) const {

src/node_file.h

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,24 @@ class BindingData : public SnapshotableObject {
100100
private:
101101
InternalFieldInfo* internal_field_info_ = nullptr;
102102

103-
static FilePathIsFileReturnType FilePathIsFile(Environment* env,
104-
const std::string& file_path);
105-
106-
static const std::array<std::string, 10> legacy_main_extensions;
103+
static FilePathIsFileReturnType FilePathIsFile(
104+
Environment* env, const std::string_view file_path);
105+
106+
// the possible file extensions that should be tested
107+
// 0-6: when packageConfig.main is defined
108+
// 7-9: when packageConfig.main is NOT defined,
109+
// or when the previous case didn't found the file
110+
static constexpr std::array<std::string_view, 10> legacy_main_extensions = {
111+
"",
112+
".js",
113+
".json",
114+
".node",
115+
"/index.js",
116+
"/index.json",
117+
"/index.node",
118+
".js",
119+
".json",
120+
".node"};
107121
// define the final index of the algorithm resolution
108122
// when packageConfig.main is defined.
109123
static const uint8_t legacy_main_extensions_with_main_end = 7;

0 commit comments

Comments
 (0)