Skip to content

Commit

Permalink
src: simplify legacy resolve functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
anonrig committed Jul 3, 2023
1 parent f870bbc commit 3c1be57
Showing 1 changed file with 43 additions and 71 deletions.
114 changes: 43 additions & 71 deletions src/node_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2737,16 +2737,15 @@ static bool FileURLToPath(
// NOLINTNEXTLINE(runtime/references)
std::string& result_file_path) {
if (file_url.type != ada::scheme::FILE) {
env->isolate()->ThrowException(ERR_INVALID_URL_SCHEME(env->isolate()));

THROW_ERR_INVALID_URL_SCHEME(env->isolate());
return false;
}

std::string_view pathname = file_url.get_pathname();
#ifdef _WIN32
size_t first_percent = std::string::npos;
size_t pathname_size = pathname.size();
std::string pathname_escaped_slash;
std::string pathname_escaped_slash{};
pathname_escaped_slash.reserve(pathname_size);

for (size_t i = 0; i < pathname_size; i++) {
if (pathname[i] == '/') {
Expand All @@ -2755,44 +2754,38 @@ static bool FileURLToPath(
pathname_escaped_slash += pathname[i];
}

if (pathname[i] != '%') continue;

if (first_percent == std::string::npos) {
first_percent = i;
// skip all non-percentage characters and skip
// last 2 characters
if (pathname[i] != '%' || (i + 2) >= pathname_size) {
continue;
}

// just safe-guard against access the pathname
// outside the bounds
if ((i + 2) >= pathname_size) continue;

char third = pathname[i + 2] | 0x20;

bool is_slash = pathname[i + 1] == '2' && third == 102;
bool is_forward_slash = pathname[i + 1] == '5' && third == 99;

if (!is_slash && !is_forward_slash) continue;

env->isolate()->ThrowException(ERR_INVALID_FILE_URL_PATH(
if (is_slash || is_forward_slash) {
THROW_ERR_INVALID_FILE_URL_PATH(
env->isolate(),
"File URL path must not include encoded \\ or / characters"));

return false;
return false;
}
}

std::string_view hostname = file_url.get_hostname();
std::string decoded_pathname = ada::unicode::percent_decode(
std::string_view(pathname_escaped_slash), first_percent);
std::string decoded_pathname =
ada::unicode::percent_decode(pathname_escaped_slash, pathname_escaped_slash.find('%'));

if (hostname.size() > 0) {
if (!file_url.has_empty_hostname()) {
// If hostname is set, then we have a UNC path
// Pass the hostname through domainToUnicode just in case
// it is an IDN using punycode encoding. We do not need to worry
// about percent encoding because the URL parser will have
// already taken care of that for us. Note that this only
// causes IDNs with an appropriate `xn--` prefix to be decoded.
auto hostname = file_url.get_hostname();
result_file_path =
"\\\\" + ada::unicode::to_unicode(hostname) + decoded_pathname;

return true;
}

Expand All @@ -2801,42 +2794,33 @@ static bool FileURLToPath(

// a..z A..Z
if (letter < 'a' || letter > 'z' || sep != ':') {
env->isolate()->ThrowException(ERR_INVALID_FILE_URL_PATH(
THROW_ERR_INVALID_FILE_URL_PATH(
env->isolate(), "File URL path must be absolute"));

return false;
}

result_file_path = decoded_pathname.substr(1);

return true;
#else // _WIN32
std::string_view hostname = file_url.get_hostname();

if (hostname.size() > 0) {
if (!file_url.has_empty_hostname()) {
std::string error_message =
std::string("File URL host must be \"localhost\" or empty on ") +
"File URL host must be \"localhost\" or empty on " +
std::string(per_process::metadata.platform);
env->isolate()->ThrowException(
ERR_INVALID_FILE_URL_HOST(env->isolate(), error_message.c_str()));

THROW_ERR_INVALID_FILE_URL_HOST(env->isolate(), error_message.c_str());
return false;
}

size_t first_percent = std::string::npos;
for (size_t i = 0; (i + 2) < pathname.size(); i++) {
if (pathname[i] != '%') continue;
auto first_percent = pathname.find('%');

if (first_percent == std::string::npos) {
first_percent = i;
}

if (pathname[i + 1] == '2' && (pathname[i + 2] | 0x20) == 102) {
env->isolate()->ThrowException(ERR_INVALID_FILE_URL_PATH(
env->isolate(),
"File URL path must not include encoded / characters"));

return false;
if (first_percent != std::string_view::npos) {
for (size_t i = first_percent; (i + 2) < pathname.size(); i++) {
if (pathname[i + 1] == '2' && (pathname[i + 2] | 0x20) == 102) {
THROW_ERR_INVALID_FILE_URL_PATH(
env->isolate(),
"File URL path must not include encoded / characters");
return false;
}
}
}

Expand Down Expand Up @@ -2898,28 +2882,23 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
ada::parse<ada::url_aggregator>(utf8_package_json_url.ToStringView());

if (!package_json_url) {
env->isolate()->ThrowException(
ERR_INVALID_URL(env->isolate(), "Invalid URL"));

THROW_ERR_INVALID_URL(env->isolate(), "Invalid URL");
return;
}

ada::result<ada::url_aggregator> file_path_url;
std::string initial_file_path;
std::string file_path;

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

file_path_url = ada::parse<ada::url_aggregator>(
std::string("./") + package_config_main, &package_json_url.value());
file_path_url = ada::parse<ada::url_aggregator>("./" + package_config_main,
&package_json_url.value());

if (!file_path_url) {
env->isolate()->ThrowException(
ERR_INVALID_URL(env->isolate(), "Invalid URL"));

THROW_ERR_INVALID_URL(env->isolate(), "Invalid URL");
return;
}

Expand Down Expand Up @@ -2952,9 +2931,7 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
ada::parse<ada::url_aggregator>("./index", &package_json_url.value());

if (!file_path_url) {
env->isolate()->ThrowException(
ERR_INVALID_URL(env->isolate(), "Invalid URL"));

THROW_ERR_INVALID_URL(env->isolate(), "Invalid URL");
return;
}

Expand Down Expand Up @@ -2987,32 +2964,27 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {

if (!FileURLToPath(env, package_json_url.value(), module_path)) return;

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

if (!base_url) {
env->isolate()->ThrowException(
ERR_INVALID_URL(env->isolate(), "Invalid URL"));

THROW_ERR_INVALID_URL(env->isolate(), "Invalid URL");
return;
}

if (!FileURLToPath(env, base_url.value(), module_base)) return;
} else {
std::string err_arg_message =
"The \"base\" argument must be of type string or an instance of URL.";
env->isolate()->ThrowException(
ERR_INVALID_ARG_TYPE(env->isolate(), err_arg_message.c_str()));

std::string err_module_message = "Cannot find package '" + module_path +
"' imported from " + module_base;
THROW_ERR_MODULE_NOT_FOUND(env->isolate(), err_module_message.c_str());
return;
}

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

void BindingData::MemoryInfo(MemoryTracker* tracker) const {
Expand Down

0 comments on commit 3c1be57

Please sign in to comment.