4
4
5
5
import buildDebug from "debug" ;
6
6
import path from "path" ;
7
- import type { Handler } from "gensync" ;
8
- import loadCjsOrMjsDefault from "./module-types" ;
7
+ import gensync , { type Gensync , type Handler } from "gensync" ;
9
8
import { isAsync } from "../../gensync-utils/async" ;
9
+ import loadCjsOrMjsDefault , { supportsESM } from "./module-types" ;
10
+ import { fileURLToPath , pathToFileURL } from "url" ;
11
+
12
+ import getImportMetaResolve from "./import-meta-resolve" ;
10
13
11
14
import { createRequire } from "module" ;
12
15
const require = createRequire ( import . meta. url ) ;
@@ -24,22 +27,19 @@ const OTHER_PRESET_ORG_RE =
24
27
/ ^ ( @ (? ! b a b e l \/ ) [ ^ / ] + \/ ) (? ! [ ^ / ] * b a b e l - p r e s e t (?: - | \/ | $ ) | [ ^ / ] + \/ ) / ;
25
28
const OTHER_ORG_DEFAULT_RE = / ^ ( @ (? ! b a b e l $ ) [ ^ / ] + ) $ / ;
26
29
27
- export function resolvePlugin ( name : string , dirname : string ) : string | null {
28
- return resolveStandardizedName ( "plugin" , name , dirname ) ;
30
+ export function * resolvePlugin ( name : string , dirname : string ) : Handler < string > {
31
+ return yield * resolveStandardizedName ( "plugin" , name , dirname ) ;
29
32
}
30
33
31
- export function resolvePreset ( name : string , dirname : string ) : string | null {
32
- return resolveStandardizedName ( "preset" , name , dirname ) ;
34
+ export function * resolvePreset ( name : string , dirname : string ) : Handler < string > {
35
+ return yield * resolveStandardizedName ( "preset" , name , dirname ) ;
33
36
}
34
37
35
38
export function * loadPlugin (
36
39
name : string ,
37
40
dirname : string ,
38
41
) : Handler < { filepath : string ; value : unknown } > {
39
- const filepath = resolvePlugin ( name , dirname ) ;
40
- if ( ! filepath ) {
41
- throw new Error ( `Plugin ${ name } not found relative to ${ dirname } ` ) ;
42
- }
42
+ const filepath = yield * resolvePlugin ( name , dirname ) ;
43
43
44
44
const value = yield * requireModule ( "plugin" , filepath ) ;
45
45
debug ( "Loaded plugin %o from %o." , name , dirname ) ;
@@ -51,10 +51,7 @@ export function* loadPreset(
51
51
name : string ,
52
52
dirname : string ,
53
53
) : Handler < { filepath : string ; value : unknown } > {
54
- const filepath = resolvePreset ( name , dirname ) ;
55
- if ( ! filepath ) {
56
- throw new Error ( `Preset ${ name } not found relative to ${ dirname } ` ) ;
57
- }
54
+ const filepath = yield * resolvePreset ( name , dirname ) ;
58
55
59
56
const value = yield * requireModule ( "preset" , filepath ) ;
60
57
@@ -93,62 +90,111 @@ function standardizeName(type: "plugin" | "preset", name: string) {
93
90
) ;
94
91
}
95
92
96
- function resolveStandardizedName (
93
+ type Result < T > = { error : Error ; value : null } | { error : null ; value : T } ;
94
+
95
+ function * resolveAlternativesHelper (
97
96
type : "plugin" | "preset" ,
98
97
name : string ,
99
- dirname : string = process . cwd ( ) ,
100
- ) {
98
+ ) : Iterator < string , string , Result < string > > {
101
99
const standardizedName = standardizeName ( type , name ) ;
100
+ const { error, value } = yield standardizedName ;
101
+ if ( ! error ) return value ;
102
+
103
+ // @ts -ignore
104
+ if ( error . code !== "MODULE_NOT_FOUND" ) throw error ;
102
105
106
+ if ( standardizedName !== name && ! ( yield name ) . error ) {
107
+ error . message += `\n- If you want to resolve "${ name } ", use "module:${ name } "` ;
108
+ }
109
+
110
+ if ( ! ( yield standardizeName ( type , "@babel/" + name ) ) . error ) {
111
+ error . message += `\n- Did you mean "@babel/${ name } "?` ;
112
+ }
113
+
114
+ const oppositeType = type === "preset" ? "plugin" : "preset" ;
115
+ if ( ! ( yield standardizeName ( oppositeType , name ) ) . error ) {
116
+ error . message += `\n- Did you accidentally pass a ${ oppositeType } as a ${ type } ?` ;
117
+ }
118
+
119
+ throw error ;
120
+ }
121
+
122
+ function tryRequireResolve (
123
+ id : Parameters < RequireResolve > [ 0 ] ,
124
+ { paths : [ dirname ] } : Parameters < RequireResolve > [ 1 ] ,
125
+ ) : Result < string > {
103
126
try {
104
- return require . resolve ( standardizedName , {
105
- paths : [ dirname ] ,
106
- } ) ;
107
- } catch ( e ) {
108
- if ( e . code !== "MODULE_NOT_FOUND" ) throw e ;
109
-
110
- if ( standardizedName !== name ) {
111
- let resolvedOriginal = false ;
112
- try {
113
- require . resolve ( name , {
114
- paths : [ dirname ] ,
115
- } ) ;
116
- resolvedOriginal = true ;
117
- } catch { }
118
-
119
- if ( resolvedOriginal ) {
120
- e . message += `\n- If you want to resolve "${ name } ", use "module:${ name } "` ;
121
- }
122
- }
127
+ return { error : null , value : require . resolve ( id , { paths : [ dirname ] } ) } ;
128
+ } catch ( error ) {
129
+ return { error, value : null } ;
130
+ }
131
+ }
123
132
124
- let resolvedBabel = false ;
125
- try {
126
- require . resolve ( standardizeName ( type , "@babel/" + name ) , {
127
- paths : [ dirname ] ,
128
- } ) ;
129
- resolvedBabel = true ;
130
- } catch { }
131
-
132
- if ( resolvedBabel ) {
133
- e . message += `\n- Did you mean "@babel/${ name } "?` ;
133
+ async function tryImportMetaResolve (
134
+ id : Parameters < ImportMeta [ "resolve" ] > [ 0 ] ,
135
+ options : Parameters < ImportMeta [ "resolve" ] > [ 1 ] ,
136
+ ) : Promise < Result < string > > {
137
+ const importMetaResolve = await getImportMetaResolve ( ) ;
138
+ try {
139
+ return { error : null , value : await importMetaResolve ( id , options ) } ;
140
+ } catch ( error ) {
141
+ return { error, value : null } ;
142
+ }
143
+ }
144
+
145
+ function resolveStandardizedNameForRequrie (
146
+ type : "plugin" | "preset" ,
147
+ name : string ,
148
+ dirname : string ,
149
+ ) {
150
+ const it = resolveAlternativesHelper ( type , name ) ;
151
+ let res = it . next ( ) ;
152
+ while ( ! res . done ) {
153
+ res = it . next ( tryRequireResolve ( res . value , { paths : [ dirname ] } ) ) ;
154
+ }
155
+ return res . value ;
156
+ }
157
+ async function resolveStandardizedNameForImport (
158
+ type : "plugin" | "preset" ,
159
+ name : string ,
160
+ dirname : string ,
161
+ ) {
162
+ const parentUrl = pathToFileURL (
163
+ path . join ( dirname , "./babel-virtual-resolve-base.js" ) ,
164
+ ) . href ;
165
+
166
+ const it = resolveAlternativesHelper ( type , name ) ;
167
+ let res = it . next ( ) ;
168
+ while ( ! res . done ) {
169
+ res = it . next ( await tryImportMetaResolve ( res . value , parentUrl ) ) ;
170
+ }
171
+ return fileURLToPath ( res . value ) ;
172
+ }
173
+
174
+ const resolveStandardizedName : Gensync <
175
+ ( type : "plugin" | "preset" , name : string , dirname ?: string ) => string
176
+ > = gensync ( {
177
+ sync ( type , name , dirname = process . cwd ( ) ) {
178
+ return resolveStandardizedNameForRequrie ( type , name , dirname ) ;
179
+ } ,
180
+ async async ( type , name , dirname = process . cwd ( ) ) {
181
+ if ( ! supportsESM ) {
182
+ return resolveStandardizedNameForRequrie ( type , name , dirname ) ;
134
183
}
135
184
136
- let resolvedOppositeType = false ;
137
- const oppositeType = type === "preset" ? "plugin" : "preset" ;
138
185
try {
139
- require . resolve ( standardizeName ( oppositeType , name ) , {
140
- paths : [ dirname ] ,
141
- } ) ;
142
- resolvedOppositeType = true ;
143
- } catch { }
144
-
145
- if ( resolvedOppositeType ) {
146
- e . message += `\n- Did you accidentally pass a ${ oppositeType } as a ${ type } ?` ;
186
+ return await resolveStandardizedNameForImport ( type , name , dirname ) ;
187
+ } catch ( e ) {
188
+ try {
189
+ return resolveStandardizedNameForRequrie ( type , name , dirname ) ;
190
+ } catch ( e2 ) {
191
+ if ( e . type === "MODULE_NOT_FOUND" ) throw e ;
192
+ if ( e2 . type === "MODULE_NOT_FOUND" ) throw e2 ;
193
+ throw e ;
194
+ }
147
195
}
148
-
149
- throw e ;
150
- }
151
- }
196
+ } ,
197
+ } ) ;
152
198
153
199
if ( ! process . env . BABEL_8_BREAKING ) {
154
200
// eslint-disable-next-line no-var
0 commit comments