@@ -2,7 +2,7 @@ import fs from 'node:fs'
2
2
import path from 'node:path'
3
3
import colors from 'picocolors'
4
4
import type { PartialResolvedId } from 'rollup'
5
- import { resolve as _resolveExports } from 'resolve.exports'
5
+ import { resolveExports } from 'resolve.exports'
6
6
import { hasESMSyntax } from 'mlly'
7
7
import type { Plugin } from '../plugin'
8
8
import {
@@ -923,29 +923,28 @@ export function resolvePackageEntry(
923
923
return cached
924
924
}
925
925
try {
926
- let entryPoint : string | undefined | void
926
+ let entryPoints : string [ ] = [ ]
927
927
928
- // resolve exports field with highest priority
929
- // using https://github.com/lukeed/resolve.exports
928
+ // the exports field takes highest priority as described in
929
+ // https://nodejs.org/api/packages.html#package-entry-points
930
930
if ( data . exports ) {
931
- entryPoint = resolveExports ( data , '.' , options , targetWeb )
932
- }
933
-
934
- // if exports resolved to .mjs, still resolve other fields.
935
- // This is because .mjs files can technically import .cjs files which would
936
- // make them invalid for pure ESM environments - so if other module/browser
937
- // fields are present, prioritize those instead.
938
- if (
939
- targetWeb &&
940
- options . browserField &&
941
- ( ! entryPoint || entryPoint . endsWith ( '.mjs' ) )
942
- ) {
931
+ entryPoints = resolveExports (
932
+ data ,
933
+ '.' ,
934
+ options ,
935
+ getInlineConditions ( options . conditions , targetWeb )
936
+ )
937
+ if ( ! entryPoints . length ) {
938
+ packageEntryFailure ( id )
939
+ }
940
+ } else if ( targetWeb && options . browserField ) {
943
941
// check browser field
944
942
// https://github.com/defunctzombie/package-browser-field-spec
945
943
const browserEntry =
946
944
typeof data . browser === 'string'
947
945
? data . browser
948
946
: isObject ( data . browser ) && data . browser [ '.' ]
947
+
949
948
if ( browserEntry ) {
950
949
// check if the package also has a "module" field.
951
950
if (
@@ -968,34 +967,34 @@ export function resolvePackageEntry(
968
967
const content = fs . readFileSync ( resolvedBrowserEntry , 'utf-8' )
969
968
if ( hasESMSyntax ( content ) ) {
970
969
// likely ESM, prefer browser
971
- entryPoint = browserEntry
970
+ entryPoints [ 0 ] = browserEntry
972
971
} else {
973
972
// non-ESM, UMD or IIFE or CJS(!!! e.g. firebase 7.x), prefer module
974
- entryPoint = data . module
973
+ entryPoints [ 0 ] = data . module
975
974
}
976
975
}
977
976
} else {
978
- entryPoint = browserEntry
977
+ entryPoints [ 0 ] = browserEntry
979
978
}
980
979
}
981
980
}
982
981
983
- if ( ! entryPoint || entryPoint . endsWith ( '.mjs' ) ) {
982
+ if ( ! entryPoints [ 0 ] ) {
984
983
for ( const field of options . mainFields ) {
985
984
if ( field === 'browser' ) continue // already checked above
986
985
if ( typeof data [ field ] === 'string' ) {
987
- entryPoint = data [ field ]
986
+ entryPoints [ 0 ] = data [ field ]
988
987
break
989
988
}
990
989
}
990
+ entryPoints [ 0 ] ||= data . main
991
991
}
992
- entryPoint ||= data . main
993
992
994
993
// try default entry when entry is not define
995
994
// https://nodejs.org/api/modules.html#all-together
996
- const entryPoints = entryPoint
997
- ? [ entryPoint ]
998
- : [ 'index.js' , 'index.json' , 'index.node' ]
995
+ if ( ! entryPoints [ 0 ] ) {
996
+ entryPoints = [ 'index.js' , 'index.json' , 'index.node' ]
997
+ }
999
998
1000
999
for ( let entry of entryPoints ) {
1001
1000
// make sure we don't get scripts when looking for sass
@@ -1040,52 +1039,8 @@ function packageEntryFailure(id: string, details?: string) {
1040
1039
)
1041
1040
}
1042
1041
1043
- const conditionalConditions = new Set ( [ 'production' , 'development' , 'module' ] )
1044
-
1045
- function resolveExports (
1046
- pkg : PackageData [ 'data' ] ,
1047
- key : string ,
1048
- options : InternalResolveOptionsWithOverrideConditions ,
1049
- targetWeb : boolean
1050
- ) {
1051
- const overrideConditions = options . overrideConditions
1052
- ? new Set ( options . overrideConditions )
1053
- : undefined
1054
-
1055
- const conditions = [ ]
1056
- if (
1057
- ( ! overrideConditions || overrideConditions . has ( 'production' ) ) &&
1058
- options . isProduction
1059
- ) {
1060
- conditions . push ( 'production' )
1061
- }
1062
- if (
1063
- ( ! overrideConditions || overrideConditions . has ( 'development' ) ) &&
1064
- ! options . isProduction
1065
- ) {
1066
- conditions . push ( 'development' )
1067
- }
1068
- if (
1069
- ( ! overrideConditions || overrideConditions . has ( 'module' ) ) &&
1070
- ! options . isRequire
1071
- ) {
1072
- conditions . push ( 'module' )
1073
- }
1074
- if ( options . overrideConditions ) {
1075
- conditions . push (
1076
- ...options . overrideConditions . filter ( ( condition ) =>
1077
- conditionalConditions . has ( condition )
1078
- )
1079
- )
1080
- } else if ( options . conditions . length > 0 ) {
1081
- conditions . push ( ...options . conditions )
1082
- }
1083
-
1084
- return _resolveExports ( pkg , key , {
1085
- browser : targetWeb && ! conditions . includes ( 'node' ) ,
1086
- require : options . isRequire && ! conditions . includes ( 'import' ) ,
1087
- conditions
1088
- } )
1042
+ function getInlineConditions ( conditions : string [ ] , targetWeb : boolean ) {
1043
+ return targetWeb && ! conditions . includes ( 'node' ) ? [ 'browser' ] : [ 'node' ]
1089
1044
}
1090
1045
1091
1046
function resolveDeepImport (
@@ -1098,56 +1053,55 @@ function resolveDeepImport(
1098
1053
data
1099
1054
} : PackageData ,
1100
1055
targetWeb : boolean ,
1101
- options : InternalResolveOptions
1056
+ options : InternalResolveOptionsWithOverrideConditions
1102
1057
) : string | undefined {
1103
1058
const cache = getResolvedCache ( id , targetWeb )
1104
1059
if ( cache ) {
1105
1060
return cache
1106
1061
}
1107
1062
1108
- let relativeId : string | undefined | void = id
1109
1063
const { exports : exportsField , browser : browserField } = data
1064
+ const { file, postfix } = splitFileAndPostfix ( id )
1110
1065
1111
- // map relative based on exports data
1066
+ let possibleFiles : string [ ] | undefined
1112
1067
if ( exportsField ) {
1113
- if ( isObject ( exportsField ) && ! Array . isArray ( exportsField ) ) {
1114
- // resolve without postfix (see #7098)
1115
- const { file, postfix } = splitFileAndPostfix ( relativeId )
1116
- const exportsId = resolveExports ( data , file , options , targetWeb )
1117
- if ( exportsId !== undefined ) {
1118
- relativeId = exportsId + postfix
1119
- } else {
1120
- relativeId = undefined
1121
- }
1122
- } else {
1123
- // not exposed
1124
- relativeId = undefined
1125
- }
1126
- if ( ! relativeId ) {
1068
+ // map relative based on exports data
1069
+ possibleFiles = resolveExports (
1070
+ data ,
1071
+ file ,
1072
+ options ,
1073
+ getInlineConditions ( options . conditions , targetWeb ) ,
1074
+ options . overrideConditions
1075
+ )
1076
+ if ( ! possibleFiles . length ) {
1127
1077
throw new Error (
1128
- `Package subpath '${ relativeId } ' is not defined by "exports" in ` +
1078
+ `Package subpath '${ file } ' is not defined by "exports" in ` +
1129
1079
`${ path . join ( dir , 'package.json' ) } .`
1130
1080
)
1131
1081
}
1132
1082
} else if ( targetWeb && options . browserField && isObject ( browserField ) ) {
1133
- // resolve without postfix (see #7098)
1134
- const { file, postfix } = splitFileAndPostfix ( relativeId )
1135
1083
const mapped = mapWithBrowserField ( file , browserField )
1136
1084
if ( mapped ) {
1137
- relativeId = mapped + postfix
1085
+ possibleFiles = [ mapped ]
1138
1086
} else if ( mapped === false ) {
1139
1087
return ( webResolvedImports [ id ] = browserExternalId )
1140
1088
}
1141
1089
}
1142
1090
1143
- if ( relativeId ) {
1144
- const resolved = tryFsResolve (
1145
- path . join ( dir , relativeId ) ,
1146
- options ,
1147
- ! exportsField , // try index only if no exports field
1148
- targetWeb
1091
+ possibleFiles ||= [ id ]
1092
+ if ( possibleFiles [ 0 ] ) {
1093
+ let resolved : string | undefined
1094
+ possibleFiles . some (
1095
+ ( file ) =>
1096
+ ( resolved = tryFsResolve (
1097
+ path . join ( dir , file ) ,
1098
+ options ,
1099
+ ! exportsField , // try index only if no exports field
1100
+ targetWeb
1101
+ ) )
1149
1102
)
1150
1103
if ( resolved ) {
1104
+ resolved += postfix
1151
1105
isDebug &&
1152
1106
debug (
1153
1107
`[node/deep-import] ${ colors . cyan ( id ) } -> ${ colors . dim ( resolved ) } `
0 commit comments