44
55import buildDebug from "debug" ;
66import path from "path" ;
7- import type { Handler } from "gensync" ;
8- import loadCjsOrMjsDefault from "./module-types" ;
7+ import gensync , { type Gensync , type Handler } from "gensync" ;
98import { 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" ;
1013
1114import { createRequire } from "module" ;
1215const require = createRequire ( import . meta. url ) ;
@@ -24,22 +27,19 @@ const OTHER_PRESET_ORG_RE =
2427 / ^ ( @ (? ! b a b e l \/ ) [ ^ / ] + \/ ) (? ! [ ^ / ] * b a b e l - p r e s e t (?: - | \/ | $ ) | [ ^ / ] + \/ ) / ;
2528const OTHER_ORG_DEFAULT_RE = / ^ ( @ (? ! b a b e l $ ) [ ^ / ] + ) $ / ;
2629
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 ) ;
2932}
3033
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 ) ;
3336}
3437
3538export function * loadPlugin (
3639 name : string ,
3740 dirname : string ,
3841) : 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 ) ;
4343
4444 const value = yield * requireModule ( "plugin" , filepath ) ;
4545 debug ( "Loaded plugin %o from %o." , name , dirname ) ;
@@ -51,10 +51,7 @@ export function* loadPreset(
5151 name : string ,
5252 dirname : string ,
5353) : 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 ) ;
5855
5956 const value = yield * requireModule ( "preset" , filepath ) ;
6057
@@ -93,62 +90,111 @@ function standardizeName(type: "plugin" | "preset", name: string) {
9390 ) ;
9491}
9592
96- function resolveStandardizedName (
93+ type Result < T > = { error : Error ; value : null } | { error : null ; value : T } ;
94+
95+ function * resolveAlternativesHelper (
9796 type : "plugin" | "preset" ,
9897 name : string ,
99- dirname : string = process . cwd ( ) ,
100- ) {
98+ ) : Iterator < string , string , Result < string > > {
10199 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 ;
102105
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 > {
103126 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+ }
123132
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 ) ;
134183 }
135184
136- let resolvedOppositeType = false ;
137- const oppositeType = type === "preset" ? "plugin" : "preset" ;
138185 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+ }
147195 }
148-
149- throw e ;
150- }
151- }
196+ } ,
197+ } ) ;
152198
153199if ( ! process . env . BABEL_8_BREAKING ) {
154200 // eslint-disable-next-line no-var
0 commit comments