1
1
import * as virtualTypes from "./path/lib/virtual-types" ;
2
+ import type { Node } from "@babel/types" ;
2
3
import {
3
4
DEPRECATED_KEYS ,
4
5
DEPRECATED_ALIASES ,
@@ -7,11 +8,17 @@ import {
7
8
__internal__deprecationWarning as deprecationWarning ,
8
9
} from "@babel/types" ;
9
10
import type { ExplodedVisitor , NodePath , Visitor } from "./index" ;
11
+ import type { ExplVisitNode , VisitNodeFunction , VisitPhase } from "./types" ;
10
12
11
13
type VIRTUAL_TYPES = keyof typeof virtualTypes ;
12
14
function isVirtualType ( type : string ) : type is VIRTUAL_TYPES {
13
15
return type in virtualTypes ;
14
16
}
17
+ export type VisitWrapper < S = any > = (
18
+ stateName : string | undefined ,
19
+ visitorType : VisitPhase ,
20
+ callback : VisitNodeFunction < S , Node > ,
21
+ ) => VisitNodeFunction < S , Node > ;
15
22
16
23
export function isExplodedVisitor (
17
24
visitor : Visitor ,
@@ -29,7 +36,6 @@ export function isExplodedVisitor(
29
36
* * `Identifier() { ... }` -> `Identifier: { enter() { ... } }`
30
37
* * `"Identifier|NumericLiteral": { ... }` -> `Identifier: { ... }, NumericLiteral: { ... }`
31
38
* * Aliases in `@babel/types`: e.g. `Property: { ... }` -> `ObjectProperty: { ... }, ClassProperty: { ... }`
32
- *
33
39
* Other normalizations are:
34
40
* * Visitors of virtual types are wrapped, so that they are only visited when
35
41
* their dynamic check passes
@@ -213,51 +219,67 @@ function validateVisitorMethods(
213
219
}
214
220
}
215
221
216
- export function merge < State > ( visitors : Visitor < State > [ ] ) : Visitor < State > ;
222
+ export function merge < State > (
223
+ visitors : Visitor < State > [ ] ,
224
+ ) : ExplodedVisitor < State > ;
217
225
export function merge (
218
226
visitors : Visitor < unknown > [ ] ,
219
227
states ?: any [ ] ,
220
228
wrapper ?: Function | null ,
221
- ) : Visitor < unknown > ;
229
+ ) : ExplodedVisitor < unknown > ;
222
230
export function merge (
223
231
visitors : any [ ] ,
224
232
states : any [ ] = [ ] ,
225
- wrapper ?: Function | null ,
226
- ) {
227
- const rootVisitor : Visitor = { } ;
233
+ wrapper ?: VisitWrapper | null ,
234
+ ) : ExplodedVisitor {
235
+ // @ts -expect-error don't bother with internal flags so it can work with earlier @babel/core validations
236
+ const mergedVisitor : ExplodedVisitor = { } ;
228
237
229
238
for ( let i = 0 ; i < visitors . length ; i ++ ) {
230
- const visitor = visitors [ i ] ;
239
+ const visitor = explode ( visitors [ i ] ) ;
231
240
const state = states [ i ] ;
232
241
233
- explode ( visitor ) ;
242
+ let topVisitor : ExplVisitNode < unknown , Node > = visitor ;
243
+ if ( state || wrapper ) {
244
+ topVisitor = wrapWithStateOrWrapper ( topVisitor , state , wrapper ) ;
245
+ }
246
+ mergePair ( mergedVisitor , topVisitor ) ;
247
+
248
+ for ( const key of Object . keys ( visitor ) as ( keyof ExplodedVisitor ) [ ] ) {
249
+ if ( shouldIgnoreKey ( key ) ) continue ;
234
250
235
- for ( const type of Object . keys ( visitor ) as ( keyof Visitor ) [ ] ) {
236
- let visitorType = visitor [ type ] ;
251
+ let typeVisitor = visitor [ key ] ;
237
252
238
253
// if we have state or wrapper then overload the callbacks to take it
239
254
if ( state || wrapper ) {
240
- visitorType = wrapWithStateOrWrapper ( visitorType , state , wrapper ) ;
255
+ typeVisitor = wrapWithStateOrWrapper ( typeVisitor , state , wrapper ) ;
241
256
}
242
257
243
- // @ts -expect-error: Expression produces a union type that is too complex to represent.
244
- const nodeVisitor = ( rootVisitor [ type ] ||= { } ) ;
245
- mergePair ( nodeVisitor , visitorType ) ;
258
+ const nodeVisitor = ( mergedVisitor [ key ] ||= { } ) ;
259
+ mergePair ( nodeVisitor , typeVisitor ) ;
246
260
}
247
261
}
248
262
249
- return rootVisitor ;
263
+ if ( process . env . BABEL_8_BREAKING ) {
264
+ return {
265
+ ...mergedVisitor ,
266
+ _exploded : true ,
267
+ _verified : true ,
268
+ } ;
269
+ }
270
+
271
+ return mergedVisitor ;
250
272
}
251
273
252
274
function wrapWithStateOrWrapper < State > (
253
- oldVisitor : Visitor < State > ,
254
- state : State ,
255
- wrapper ?: Function | null ,
256
- ) {
257
- const newVisitor : Visitor = { } ;
275
+ oldVisitor : ExplVisitNode < State , Node > ,
276
+ state : State | null ,
277
+ wrapper ?: VisitWrapper < State > | null ,
278
+ ) : ExplVisitNode < State , Node > {
279
+ const newVisitor : ExplVisitNode < State , Node > = { } ;
258
280
259
- for ( const key of Object . keys ( oldVisitor ) as ( keyof Visitor < State > ) [ ] ) {
260
- let fns = oldVisitor [ key ] ;
281
+ for ( const phase of [ "enter" , "exit" ] as VisitPhase [ ] ) {
282
+ let fns = oldVisitor [ phase ] ;
261
283
262
284
// not an enter/exit array of callbacks
263
285
if ( ! Array . isArray ( fns ) ) continue ;
@@ -272,8 +294,8 @@ function wrapWithStateOrWrapper<State>(
272
294
}
273
295
274
296
if ( wrapper ) {
275
- // @ts -expect-error Fixme: document state .key
276
- newFn = wrapper ( state . key , key , newFn ) ;
297
+ // @ts -expect-error Fixme: actually PluginPass .key (aka pluginAlias)?
298
+ newFn = wrapper ( state ? .key , phase , newFn ) ;
277
299
}
278
300
279
301
// Override toString in case this function is printed, we want to print the wrapped function, same as we do in `wrapCheck`
@@ -284,8 +306,7 @@ function wrapWithStateOrWrapper<State>(
284
306
return newFn ;
285
307
} ) ;
286
308
287
- // @ts -expect-error: Expression produces a union type that is too complex to represent.
288
- newVisitor [ key ] = fns ;
309
+ newVisitor [ phase ] = fns ;
289
310
}
290
311
291
312
return newVisitor ;
@@ -321,6 +342,7 @@ function wrapCheck(nodeType: VIRTUAL_TYPES, fn: Function) {
321
342
function shouldIgnoreKey (
322
343
key : string ,
323
344
) : key is
345
+ | `_${string } `
324
346
| "enter"
325
347
| "exit"
326
348
| "shouldSkip"
@@ -348,8 +370,15 @@ function shouldIgnoreKey(
348
370
return false ;
349
371
}
350
372
373
+ /*
374
+ function mergePair(
375
+ dest: ExplVisitNode<unknown, Node>,
376
+ src: ExplVisitNode<unknown, Node>,
377
+ );
378
+ */
351
379
function mergePair ( dest : any , src : any ) {
352
- for ( const key of Object . keys ( src ) ) {
353
- dest [ key ] = [ ] . concat ( dest [ key ] || [ ] , src [ key ] ) ;
380
+ for ( const phase of [ "enter" , "exit" ] as VisitPhase [ ] ) {
381
+ if ( ! src [ phase ] ) continue ;
382
+ dest [ phase ] = [ ] . concat ( dest [ phase ] || [ ] , src [ phase ] ) ;
354
383
}
355
384
}
0 commit comments