3
3
Identifier ,
4
4
Node ,
5
5
Function ,
6
- ObjectProperty
6
+ ObjectProperty ,
7
+ BlockStatement
7
8
} from '@babel/types'
8
9
import { walk } from 'estree-walker'
9
10
@@ -17,9 +18,10 @@ export function walkIdentifiers(
17
18
isLocal : boolean
18
19
) => void ,
19
20
onNode ?: ( node : Node , parent : Node , parentStack : Node [ ] ) => void | boolean ,
21
+ includeAll = false ,
22
+ analyzeScope = true ,
20
23
parentStack : Node [ ] = [ ] ,
21
- knownIds : Record < string , number > = Object . create ( null ) ,
22
- includeAll = false
24
+ knownIds : Record < string , number > = Object . create ( null )
23
25
) {
24
26
const rootExp =
25
27
root . type === 'Program' &&
@@ -42,62 +44,41 @@ export function walkIdentifiers(
42
44
return this . skip ( )
43
45
}
44
46
if ( node . type === 'Identifier' ) {
45
- const isLocal = ! ! knownIds [ node . name ]
47
+ const isLocal = analyzeScope && ! ! knownIds [ node . name ]
46
48
const isRefed = isReferencedIdentifier ( node , parent ! , parentStack )
47
49
if ( includeAll || ( isRefed && ! isLocal ) ) {
48
50
onIdentifier ( node , parent ! , parentStack , isRefed , isLocal )
49
51
}
50
- } else if ( isFunctionType ( node ) ) {
51
- // walk function expressions and add its arguments to known identifiers
52
- // so that we don't prefix them
53
- for ( const p of node . params ) {
54
- ; ( walk as any ) ( p , {
55
- enter ( child : Node , parent : Node ) {
56
- if (
57
- child . type === 'Identifier' &&
58
- // do not record as scope variable if is a destructured key
59
- ! isStaticPropertyKey ( child , parent ) &&
60
- // do not record if this is a default value
61
- // assignment of a destructured variable
62
- ! (
63
- parent &&
64
- parent . type === 'AssignmentPattern' &&
65
- parent . right === child
66
- )
67
- ) {
68
- markScopeIdentifier ( node , child , knownIds )
69
- }
70
- }
71
- } )
72
- }
73
- } else if ( node . type === 'BlockStatement' ) {
74
- // #3445 record block-level local variables
75
- for ( const stmt of node . body ) {
76
- if ( stmt . type === 'VariableDeclaration' ) {
77
- for ( const decl of stmt . declarations ) {
78
- for ( const id of extractIdentifiers ( decl . id ) ) {
79
- markScopeIdentifier ( node , id , knownIds )
80
- }
81
- }
82
- }
83
- }
84
52
} else if (
85
53
node . type === 'ObjectProperty' &&
86
54
parent ! . type === 'ObjectPattern'
87
55
) {
88
56
// mark property in destructure pattern
89
57
; ( node as any ) . inPattern = true
58
+ } else if ( analyzeScope ) {
59
+ if ( isFunctionType ( node ) ) {
60
+ // walk function expressions and add its arguments to known identifiers
61
+ // so that we don't prefix them
62
+ walkFunctionParams ( node , id =>
63
+ markScopeIdentifier ( node , id , knownIds )
64
+ )
65
+ } else if ( node . type === 'BlockStatement' ) {
66
+ // #3445 record block-level local variables
67
+ walkBlockDeclarations ( node , id =>
68
+ markScopeIdentifier ( node , id , knownIds )
69
+ )
70
+ }
90
71
}
91
72
} ,
92
73
leave ( node : Node & { scopeIds ?: Set < string > } , parent : Node | undefined ) {
93
74
parent && parentStack . pop ( )
94
- if ( node !== rootExp && node . scopeIds ) {
95
- node . scopeIds . forEach ( ( id : string ) => {
75
+ if ( analyzeScope && node !== rootExp && node . scopeIds ) {
76
+ for ( const id of node . scopeIds ) {
96
77
knownIds [ id ] --
97
78
if ( knownIds [ id ] === 0 ) {
98
79
delete knownIds [ id ]
99
80
}
100
- } )
81
+ }
101
82
}
102
83
}
103
84
} )
@@ -156,6 +137,47 @@ export function isInDestructureAssignment(
156
137
return false
157
138
}
158
139
140
+ export function walkFunctionParams (
141
+ node : Function ,
142
+ onIdent : ( id : Identifier ) => void
143
+ ) {
144
+ for ( const p of node . params ) {
145
+ ; ( walk as any ) ( p , {
146
+ enter ( child : Node , parent : Node ) {
147
+ if (
148
+ child . type === 'Identifier' &&
149
+ // do not record as scope variable if is a destructured key
150
+ ! isStaticPropertyKey ( child , parent ) &&
151
+ // do not record if this is a default value
152
+ // assignment of a destructured variable
153
+ ! (
154
+ parent &&
155
+ parent . type === 'AssignmentPattern' &&
156
+ parent . right === child
157
+ )
158
+ ) {
159
+ onIdent ( child )
160
+ }
161
+ }
162
+ } )
163
+ }
164
+ }
165
+
166
+ export function walkBlockDeclarations (
167
+ block : BlockStatement ,
168
+ onIdent : ( node : Identifier ) => void
169
+ ) {
170
+ for ( const stmt of block . body ) {
171
+ if ( stmt . type === 'VariableDeclaration' ) {
172
+ for ( const decl of stmt . declarations ) {
173
+ for ( const id of extractIdentifiers ( decl . id ) ) {
174
+ onIdent ( id )
175
+ }
176
+ }
177
+ }
178
+ }
179
+ }
180
+
159
181
function extractIdentifiers (
160
182
param : Node ,
161
183
nodes : Identifier [ ] = [ ]
0 commit comments