@@ -524,6 +524,7 @@ Maybe<std::string> ReadIfFile(const std::string& path) {
524
524
using Exists = PackageConfig::Exists;
525
525
using IsValid = PackageConfig::IsValid;
526
526
using HasMain = PackageConfig::HasMain;
527
+ using HasExports = PackageConfig::HasExports;
527
528
using IsESM = PackageConfig::IsESM;
528
529
529
530
Maybe<const PackageConfig*> GetPackageConfig (Environment* env,
@@ -538,8 +539,8 @@ Maybe<const PackageConfig*> GetPackageConfig(Environment* env,
538
539
539
540
if (source.IsNothing ()) {
540
541
auto entry = env->package_json_cache .emplace (path,
541
- PackageConfig { Exists::No, IsValid::Yes, HasMain::No, " " ,
542
- IsESM::No });
542
+ PackageConfig { Exists::No, IsValid::Yes, HasMain::No, HasExports::No ,
543
+ " " , IsESM::No });
543
544
return Just (&entry.first ->second );
544
545
}
545
546
@@ -565,8 +566,8 @@ Maybe<const PackageConfig*> GetPackageConfig(Environment* env,
565
566
566
567
if (!parsed) {
567
568
(void )env->package_json_cache .emplace (path,
568
- PackageConfig { Exists::Yes, IsValid::No, HasMain::No, " " ,
569
- IsESM::No });
569
+ PackageConfig { Exists::Yes, IsValid::No, HasMain::No, HasExports::No ,
570
+ " " , IsESM::No });
570
571
std::string msg = " Invalid JSON in '" + path +
571
572
" ' imported from " + base.ToFilePath ();
572
573
node::THROW_ERR_INVALID_PACKAGE_CONFIG (env, msg.c_str ());
@@ -575,8 +576,17 @@ Maybe<const PackageConfig*> GetPackageConfig(Environment* env,
575
576
576
577
Local<Value> pkg_main;
577
578
HasMain::Bool has_main = HasMain::No;
579
+ HasExports::Bool has_exports = HasExports::No;
578
580
std::string main_std;
579
- if (pkg_json->Get (env->context (), env->main_string ()).ToLocal (&pkg_main)) {
581
+ if (pkg_json->Get (env->context (), env->exports_string ()).ToLocal (&pkg_main)) {
582
+ if (pkg_main->IsString ()) {
583
+ has_main = HasMain::Yes;
584
+ has_exports = HasExports::Yes;
585
+ }
586
+ Utf8Value main_utf8 (isolate, pkg_main);
587
+ main_std.assign (std::string (*main_utf8, main_utf8.length ()));
588
+ } else if (pkg_json->Get (env->context (),
589
+ env->main_string ()).ToLocal (&pkg_main)) {
580
590
if (pkg_main->IsString ()) {
581
591
has_main = HasMain::Yes;
582
592
}
@@ -592,24 +602,9 @@ Maybe<const PackageConfig*> GetPackageConfig(Environment* env,
592
602
}
593
603
}
594
604
595
- Local<Value> exports_v;
596
- if (pkg_json->Get (env->context (),
597
- env->exports_string ()).ToLocal (&exports_v) &&
598
- (exports_v->IsObject () || exports_v->IsString () ||
599
- exports_v->IsBoolean ())) {
600
- Persistent<Value> exports;
601
- // esm = IsESM::Yes;
602
- exports.Reset (env->isolate (), exports_v);
603
-
604
- auto entry = env->package_json_cache .emplace (path,
605
- PackageConfig { Exists::Yes, IsValid::Yes, has_main, main_std,
606
- esm });
607
- return Just (&entry.first ->second );
608
- }
609
-
610
605
auto entry = env->package_json_cache .emplace (path,
611
- PackageConfig { Exists::Yes, IsValid::Yes, has_main, main_std ,
612
- esm });
606
+ PackageConfig { Exists::Yes, IsValid::Yes, has_main, has_exports ,
607
+ main_std, esm });
613
608
return Just (&entry.first ->second );
614
609
}
615
610
@@ -630,8 +625,8 @@ Maybe<const PackageConfig*> GetPackageBoundaryConfig(Environment* env,
630
625
// (can't just check "/package.json" for Windows support).
631
626
if (pjson_url.path () == last_pjson_url.path ()) {
632
627
auto entry = env->package_json_cache .emplace (pjson_url.ToFilePath (),
633
- PackageConfig { Exists::No, IsValid::Yes, HasMain::No, " " ,
634
- IsESM::No });
628
+ PackageConfig { Exists::No, IsValid::Yes, HasMain::No,
629
+ HasExports::No, " " , IsESM::No });
635
630
return Just (&entry.first ->second );
636
631
}
637
632
}
@@ -757,15 +752,20 @@ Maybe<ModuleResolution> PackageMainResolve(Environment* env,
757
752
node::THROW_ERR_MODULE_NOT_FOUND (env, msg.c_str ());
758
753
return Nothing<ModuleResolution>();
759
754
}
760
- if (pcfg.has_main == HasMain::Yes &&
761
- pcfg.main .substr (pcfg.main .length () - 4 , 4 ) == " .mjs" ) {
762
- return FinalizeResolution (env, URL (pcfg.main , pjson_url), base, true );
763
- }
764
- if (pcfg.esm == IsESM::Yes &&
765
- pcfg.main .substr (pcfg.main .length () - 3 , 3 ) == " .js" ) {
755
+ if (pcfg.has_exports == HasExports::Yes) {
756
+ const size_t main_len = pcfg.main .length ();
757
+ if (main_len > 4 && pcfg.main .substr (main_len - 4 , 4 ) == " .cjs" ||
758
+ (pcfg.esm == IsESM::No &&
759
+ main_len > 3 && pcfg.main .substr (main_len - 3 , 3 ) == " .js" )) {
760
+ std::string msg = " Cannot load exports entry point '" +
761
+ pcfg.main + " ' in " + URL (" ." , pjson_url).ToFilePath () +
762
+ " imported from " + base.ToFilePath () +
763
+ " as it would be loaded as CommonJS." ;
764
+ node::THROW_ERR_UNSUPPORTED_MODULE_FORMAT (env, msg.c_str ());
765
+ return Nothing<ModuleResolution>();
766
+ }
766
767
return FinalizeResolution (env, URL (pcfg.main , pjson_url), base, true );
767
768
}
768
-
769
769
Maybe<URL> resolved = LegacyMainResolve (pjson_url, pcfg);
770
770
// Legacy main resolution error
771
771
if (resolved.IsNothing ()) {
0 commit comments