12
12
#include < sys/stat.h> // S_IFDIR
13
13
14
14
#include < algorithm>
15
- #include < climits> // PATH_MAX
16
15
17
16
namespace node {
18
17
namespace loader {
@@ -908,6 +907,25 @@ Maybe<URL> ResolveExportsTargetString(Environment* env,
908
907
return Just (subpath_resolved);
909
908
}
910
909
910
+ bool IsArrayIndex (Environment* env, Local<Value> p) {
911
+ Local<Context> context = env->context ();
912
+ Local<String> p_str = p->ToString (context).ToLocalChecked ();
913
+ double n_dbl = static_cast <double >(p_str->NumberValue (context).FromJust ());
914
+ Local<Number> n = Number::New (env->isolate (), n_dbl);
915
+ Local<String> cmp_str = n->ToString (context).ToLocalChecked ();
916
+ if (!p_str->Equals (context, cmp_str).FromJust ()) {
917
+ return false ;
918
+ }
919
+ if (n_dbl == 0 && std::signbit (n_dbl) == false ) {
920
+ return true ;
921
+ }
922
+ Local<Integer> cmp_integer;
923
+ if (!n->ToInteger (context).ToLocal (&cmp_integer)) {
924
+ return false ;
925
+ }
926
+ return n_dbl > 0 && n_dbl < (2 ^ 32 ) - 1 ;
927
+ }
928
+
911
929
Maybe<URL> ResolveExportsTarget (Environment* env,
912
930
const URL& pjson_url,
913
931
Local<Value> target,
@@ -953,44 +971,50 @@ Maybe<URL> ResolveExportsTarget(Environment* env,
953
971
return Nothing<URL>();
954
972
} else if (target->IsObject ()) {
955
973
Local<Object> target_obj = target.As <Object>();
956
- bool matched = false ;
974
+ Local<Array> target_obj_keys =
975
+ target_obj->GetOwnPropertyNames (context).ToLocalChecked ();
957
976
Local<Value> conditionalTarget;
958
- if (env-> options ()-> experimental_conditional_exports &&
959
- target_obj-> HasOwnProperty (context, env-> node_string ()). FromJust () ) {
960
- matched = true ;
961
- conditionalTarget =
962
- target_obj-> Get (context, env-> node_string ()). ToLocalChecked ();
963
- Maybe<URL> resolved = ResolveExportsTarget (env, pjson_url,
964
- conditionalTarget, subpath, pkg_subpath, base, false );
965
- if (!resolved. IsNothing ()) {
966
- ProcessEmitExperimentalWarning (env, " Conditional exports " );
967
- return resolved ;
977
+ bool matched = false ;
978
+ for ( uint32_t i = 0 ; i < target_obj_keys-> Length (); ++i ) {
979
+ Local<Value> key =
980
+ target_obj_keys-> Get (context, i). ToLocalChecked ();
981
+ if ( IsArrayIndex (env, key)) {
982
+ const std::string msg = " Invalid package config for " +
983
+ pjson_url. ToFilePath () + " , \" exports \" cannot contain numeric " +
984
+ " property keys. " ;
985
+ node::THROW_ERR_INVALID_PACKAGE_CONFIG (env, msg. c_str () );
986
+ return Nothing<URL>() ;
968
987
}
969
988
}
970
- if (env->options ()->experimental_conditional_exports &&
971
- target_obj->HasOwnProperty (context, env->import_string ()).FromJust ()) {
972
- matched = true ;
973
- conditionalTarget =
974
- target_obj->Get (context, env->import_string ()).ToLocalChecked ();
975
- Maybe<URL> resolved = ResolveExportsTarget (env, pjson_url,
989
+ for (uint32_t i = 0 ; i < target_obj_keys->Length (); ++i) {
990
+ Local<Value> key = target_obj_keys->Get (context, i).ToLocalChecked ();
991
+ Utf8Value key_utf8 (env->isolate (),
992
+ key->ToString (context).ToLocalChecked ());
993
+ std::string key_str (*key_utf8, key_utf8.length ());
994
+ if (key_str == " node" || key_str == " import" ) {
995
+ if (!env->options ()->experimental_conditional_exports ) continue ;
996
+ matched = true ;
997
+ conditionalTarget = target_obj->Get (context, key).ToLocalChecked ();
998
+ Maybe<URL> resolved = ResolveExportsTarget (env, pjson_url,
976
999
conditionalTarget, subpath, pkg_subpath, base, false );
977
- if (!resolved.IsNothing ()) {
978
- return resolved;
979
- }
980
- }
981
- if (target_obj->HasOwnProperty (context, env->default_string ()).FromJust ()) {
982
- matched = true ;
983
- conditionalTarget =
984
- target_obj->Get (context, env->default_string ()).ToLocalChecked ();
985
- Maybe<URL> resolved = ResolveExportsTarget (env, pjson_url,
1000
+ if (!resolved.IsNothing ()) {
1001
+ ProcessEmitExperimentalWarning (env, " Conditional exports" );
1002
+ return resolved;
1003
+ }
1004
+ } else if (key_str == " default" ) {
1005
+ matched = true ;
1006
+ conditionalTarget = target_obj->Get (context, key).ToLocalChecked ();
1007
+ Maybe<URL> resolved = ResolveExportsTarget (env, pjson_url,
986
1008
conditionalTarget, subpath, pkg_subpath, base, false );
987
- if (!resolved.IsNothing ()) {
988
- return resolved;
1009
+ if (!resolved.IsNothing ()) {
1010
+ ProcessEmitExperimentalWarning (env, " Conditional exports" );
1011
+ return resolved;
1012
+ }
989
1013
}
990
1014
}
991
1015
if (matched && throw_invalid) {
992
1016
Maybe<URL> resolved = ResolveExportsTarget (env, pjson_url,
993
- conditionalTarget, subpath, pkg_subpath, base, true );
1017
+ conditionalTarget, subpath, pkg_subpath, base, true );
994
1018
CHECK (resolved.IsNothing ());
995
1019
return Nothing<URL>();
996
1020
}
@@ -1013,8 +1037,8 @@ Maybe<bool> IsConditionalExportsMainSugar(Environment* env,
1013
1037
exports_obj->GetOwnPropertyNames (context).ToLocalChecked ();
1014
1038
bool isConditionalSugar = false ;
1015
1039
for (uint32_t i = 0 ; i < keys->Length (); ++i) {
1016
- Local<String > key = keys->Get (context, i).ToLocalChecked (). As <String> ();
1017
- Utf8Value key_utf8 (env->isolate (), key);
1040
+ Local<Value > key = keys->Get (context, i).ToLocalChecked ();
1041
+ Utf8Value key_utf8 (env->isolate (), key-> ToString (context). ToLocalChecked () );
1018
1042
bool curIsConditionalSugar = key_utf8.length () == 0 || key_utf8[0 ] != ' .' ;
1019
1043
if (i == 0 ) {
1020
1044
isConditionalSugar = curIsConditionalSugar;
@@ -1122,13 +1146,13 @@ Maybe<URL> PackageExportsResolve(Environment* env,
1122
1146
Local<Array> keys =
1123
1147
exports_obj->GetOwnPropertyNames (context).ToLocalChecked ();
1124
1148
for (uint32_t i = 0 ; i < keys->Length (); ++i) {
1125
- Local<String > key = keys->Get (context, i).ToLocalChecked (). As <String> ();
1126
- Utf8Value key_utf8 (isolate, key);
1149
+ Local<Value > key = keys->Get (context, i).ToLocalChecked ();
1150
+ Utf8Value key_utf8 (isolate, key-> ToString (context). ToLocalChecked () );
1127
1151
std::string key_str (*key_utf8, key_utf8.length ());
1128
1152
if (key_str.back () != ' /' ) continue ;
1129
1153
if (pkg_subpath.substr (0 , key_str.length ()) == key_str &&
1130
1154
key_str.length () > best_match_str.length ()) {
1131
- best_match = key;
1155
+ best_match = key-> ToString (context). ToLocalChecked () ;
1132
1156
best_match_str = key_str;
1133
1157
}
1134
1158
}
0 commit comments