Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuy Bedford <guybedford@gmail.com>2019-12-17 22:00:21 +0300
committerGuy Bedford <guybedford@gmail.com>2020-01-07 07:14:19 +0300
commit405e7b45575ef39264067e68ee4ef5db466eebb2 (patch)
treeeb2f9c07560b372ea24f6de78a49812c54d4d208 /src/module_wrap.cc
parent2551a21553d06e85790bdc96c6f1d528d0695d76 (diff)
module: logical conditional exports ordering
PR-URL: https://github.com/nodejs/node/pull/31008 Reviewed-By: Bradley Farias <bradley.meck@gmail.com> Reviewed-By: Jan Krems <jan.krems@gmail.com>
Diffstat (limited to 'src/module_wrap.cc')
-rw-r--r--src/module_wrap.cc94
1 files changed, 59 insertions, 35 deletions
diff --git a/src/module_wrap.cc b/src/module_wrap.cc
index 74eacf198f7..ff6f0db651a 100644
--- a/src/module_wrap.cc
+++ b/src/module_wrap.cc
@@ -12,7 +12,6 @@
#include <sys/stat.h> // S_IFDIR
#include <algorithm>
-#include <climits> // PATH_MAX
namespace node {
namespace loader {
@@ -908,6 +907,25 @@ Maybe<URL> ResolveExportsTargetString(Environment* env,
return Just(subpath_resolved);
}
+bool IsArrayIndex(Environment* env, Local<Value> p) {
+ Local<Context> context = env->context();
+ Local<String> p_str = p->ToString(context).ToLocalChecked();
+ double n_dbl = static_cast<double>(p_str->NumberValue(context).FromJust());
+ Local<Number> n = Number::New(env->isolate(), n_dbl);
+ Local<String> cmp_str = n->ToString(context).ToLocalChecked();
+ if (!p_str->Equals(context, cmp_str).FromJust()) {
+ return false;
+ }
+ if (n_dbl == 0 && std::signbit(n_dbl) == false) {
+ return true;
+ }
+ Local<Integer> cmp_integer;
+ if (!n->ToInteger(context).ToLocal(&cmp_integer)) {
+ return false;
+ }
+ return n_dbl > 0 && n_dbl < (2 ^ 32) - 1;
+}
+
Maybe<URL> ResolveExportsTarget(Environment* env,
const URL& pjson_url,
Local<Value> target,
@@ -953,44 +971,50 @@ Maybe<URL> ResolveExportsTarget(Environment* env,
return Nothing<URL>();
} else if (target->IsObject()) {
Local<Object> target_obj = target.As<Object>();
- bool matched = false;
+ Local<Array> target_obj_keys =
+ target_obj->GetOwnPropertyNames(context).ToLocalChecked();
Local<Value> conditionalTarget;
- if (env->options()->experimental_conditional_exports &&
- target_obj->HasOwnProperty(context, env->node_string()).FromJust()) {
- matched = true;
- conditionalTarget =
- target_obj->Get(context, env->node_string()).ToLocalChecked();
- Maybe<URL> resolved = ResolveExportsTarget(env, pjson_url,
- conditionalTarget, subpath, pkg_subpath, base, false);
- if (!resolved.IsNothing()) {
- ProcessEmitExperimentalWarning(env, "Conditional exports");
- return resolved;
+ bool matched = false;
+ for (uint32_t i = 0; i < target_obj_keys->Length(); ++i) {
+ Local<Value> key =
+ target_obj_keys->Get(context, i).ToLocalChecked();
+ if (IsArrayIndex(env, key)) {
+ const std::string msg = "Invalid package config for " +
+ pjson_url.ToFilePath() + ", \"exports\" cannot contain numeric " +
+ "property keys.";
+ node::THROW_ERR_INVALID_PACKAGE_CONFIG(env, msg.c_str());
+ return Nothing<URL>();
}
}
- if (env->options()->experimental_conditional_exports &&
- target_obj->HasOwnProperty(context, env->import_string()).FromJust()) {
- matched = true;
- conditionalTarget =
- target_obj->Get(context, env->import_string()).ToLocalChecked();
- Maybe<URL> resolved = ResolveExportsTarget(env, pjson_url,
+ for (uint32_t i = 0; i < target_obj_keys->Length(); ++i) {
+ Local<Value> key = target_obj_keys->Get(context, i).ToLocalChecked();
+ Utf8Value key_utf8(env->isolate(),
+ key->ToString(context).ToLocalChecked());
+ std::string key_str(*key_utf8, key_utf8.length());
+ if (key_str == "node" || key_str == "import") {
+ if (!env->options()->experimental_conditional_exports) continue;
+ matched = true;
+ conditionalTarget = target_obj->Get(context, key).ToLocalChecked();
+ Maybe<URL> resolved = ResolveExportsTarget(env, pjson_url,
conditionalTarget, subpath, pkg_subpath, base, false);
- if (!resolved.IsNothing()) {
- return resolved;
- }
- }
- if (target_obj->HasOwnProperty(context, env->default_string()).FromJust()) {
- matched = true;
- conditionalTarget =
- target_obj->Get(context, env->default_string()).ToLocalChecked();
- Maybe<URL> resolved = ResolveExportsTarget(env, pjson_url,
+ if (!resolved.IsNothing()) {
+ ProcessEmitExperimentalWarning(env, "Conditional exports");
+ return resolved;
+ }
+ } else if (key_str == "default") {
+ matched = true;
+ conditionalTarget = target_obj->Get(context, key).ToLocalChecked();
+ Maybe<URL> resolved = ResolveExportsTarget(env, pjson_url,
conditionalTarget, subpath, pkg_subpath, base, false);
- if (!resolved.IsNothing()) {
- return resolved;
+ if (!resolved.IsNothing()) {
+ ProcessEmitExperimentalWarning(env, "Conditional exports");
+ return resolved;
+ }
}
}
if (matched && throw_invalid) {
Maybe<URL> resolved = ResolveExportsTarget(env, pjson_url,
- conditionalTarget, subpath, pkg_subpath, base, true);
+ conditionalTarget, subpath, pkg_subpath, base, true);
CHECK(resolved.IsNothing());
return Nothing<URL>();
}
@@ -1013,8 +1037,8 @@ Maybe<bool> IsConditionalExportsMainSugar(Environment* env,
exports_obj->GetOwnPropertyNames(context).ToLocalChecked();
bool isConditionalSugar = false;
for (uint32_t i = 0; i < keys->Length(); ++i) {
- Local<String> key = keys->Get(context, i).ToLocalChecked().As<String>();
- Utf8Value key_utf8(env->isolate(), key);
+ Local<Value> key = keys->Get(context, i).ToLocalChecked();
+ Utf8Value key_utf8(env->isolate(), key->ToString(context).ToLocalChecked());
bool curIsConditionalSugar = key_utf8.length() == 0 || key_utf8[0] != '.';
if (i == 0) {
isConditionalSugar = curIsConditionalSugar;
@@ -1122,13 +1146,13 @@ Maybe<URL> PackageExportsResolve(Environment* env,
Local<Array> keys =
exports_obj->GetOwnPropertyNames(context).ToLocalChecked();
for (uint32_t i = 0; i < keys->Length(); ++i) {
- Local<String> key = keys->Get(context, i).ToLocalChecked().As<String>();
- Utf8Value key_utf8(isolate, key);
+ Local<Value> key = keys->Get(context, i).ToLocalChecked();
+ Utf8Value key_utf8(isolate, key->ToString(context).ToLocalChecked());
std::string key_str(*key_utf8, key_utf8.length());
if (key_str.back() != '/') continue;
if (pkg_subpath.substr(0, key_str.length()) == key_str &&
key_str.length() > best_match_str.length()) {
- best_match = key;
+ best_match = key->ToString(context).ToLocalChecked();
best_match_str = key_str;
}
}