@@ -8,7 +8,11 @@ import {
8
8
Program ,
9
9
VariableDeclarator ,
10
10
Expression ,
11
- VariableDeclaration
11
+ VariableDeclaration ,
12
+ ImportDeclaration ,
13
+ ImportSpecifier ,
14
+ ImportDefaultSpecifier ,
15
+ ImportNamespaceSpecifier
12
16
} from '@babel/types'
13
17
import MagicString , { SourceMap } from 'magic-string'
14
18
import { walk } from 'estree-walker'
@@ -25,6 +29,7 @@ import { hasOwn, isArray, isString, genPropsAccessExp } from '@vue/shared'
25
29
26
30
const CONVERT_SYMBOL = '$'
27
31
const ESCAPE_SYMBOL = '$$'
32
+ const IMPORT_SOURCE = 'vue/macros'
28
33
const shorthands = [ 'ref' , 'computed' , 'shallowRef' , 'toRef' , 'customRef' ]
29
34
const transformCheckRE = / [ ^ \w ] \$ (?: \$ | r e f | c o m p u t e d | s h a l l o w R e f ) ? \s * ( \( | \< ) /
30
35
@@ -48,6 +53,13 @@ export interface RefTransformResults {
48
53
importedHelpers : string [ ]
49
54
}
50
55
56
+ export interface ImportBinding {
57
+ local : string
58
+ imported : string
59
+ source : string
60
+ specifier : ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier
61
+ }
62
+
51
63
export function transform (
52
64
src : string ,
53
65
{
@@ -115,39 +127,40 @@ export function transformAST(
115
127
// TODO remove when out of experimental
116
128
warnExperimental ( )
117
129
118
- let convertSymbol = CONVERT_SYMBOL
119
- let escapeSymbol = ESCAPE_SYMBOL
130
+ const userImports : Record < string , ImportBinding > = Object . create ( null )
131
+ for ( const node of ast . body ) {
132
+ if ( node . type !== 'ImportDeclaration' ) continue
133
+ walkImportDeclaration ( node )
134
+ }
120
135
121
136
// macro import handling
122
- for ( const node of ast . body ) {
123
- if (
124
- node . type === 'ImportDeclaration' &&
125
- node . source . value === 'vue/macros'
126
- ) {
127
- // remove macro imports
128
- s . remove ( node . start ! + offset , node . end ! + offset )
129
- // check aliasing
130
- for ( const specifier of node . specifiers ) {
131
- if ( specifier . type === 'ImportSpecifier' ) {
132
- const imported = ( specifier . imported as Identifier ) . name
133
- const local = specifier . local . name
134
- if ( local !== imported ) {
135
- if ( imported === ESCAPE_SYMBOL ) {
136
- escapeSymbol = local
137
- } else if ( imported === CONVERT_SYMBOL ) {
138
- convertSymbol = local
139
- } else {
140
- error (
141
- `macro imports for ref-creating methods do not support aliasing.` ,
142
- specifier
143
- )
144
- }
145
- }
146
- }
137
+ let convertSymbol : string | undefined
138
+ let escapeSymbol : string | undefined
139
+ for ( const { local, imported, source, specifier } of Object . values (
140
+ userImports
141
+ ) ) {
142
+ if ( source === IMPORT_SOURCE ) {
143
+ if ( imported === ESCAPE_SYMBOL ) {
144
+ escapeSymbol = local
145
+ } else if ( imported === CONVERT_SYMBOL ) {
146
+ convertSymbol = local
147
+ } else if ( imported !== local ) {
148
+ error (
149
+ `macro imports for ref-creating methods do not support aliasing.` ,
150
+ specifier
151
+ )
147
152
}
148
153
}
149
154
}
150
155
156
+ // default symbol
157
+ if ( ! convertSymbol && ! userImports [ CONVERT_SYMBOL ] ) {
158
+ convertSymbol = CONVERT_SYMBOL
159
+ }
160
+ if ( ! escapeSymbol && ! userImports [ ESCAPE_SYMBOL ] ) {
161
+ escapeSymbol = ESCAPE_SYMBOL
162
+ }
163
+
151
164
const importedHelpers = new Set < string > ( )
152
165
const rootScope : Scope = { }
153
166
const scopeStack : Scope [ ] = [ rootScope ]
@@ -170,7 +183,32 @@ export function transformAST(
170
183
}
171
184
}
172
185
186
+ function walkImportDeclaration ( node : ImportDeclaration ) {
187
+ const source = node . source . value
188
+ if ( source === IMPORT_SOURCE ) {
189
+ s . remove ( node . start ! + offset , node . end ! + offset )
190
+ }
191
+
192
+ for ( const specifier of node . specifiers ) {
193
+ const local = specifier . local . name
194
+ const imported =
195
+ ( specifier . type === 'ImportSpecifier' &&
196
+ specifier . imported . type === 'Identifier' &&
197
+ specifier . imported . name ) ||
198
+ 'default'
199
+ userImports [ local ] = {
200
+ source,
201
+ local,
202
+ imported,
203
+ specifier
204
+ }
205
+ }
206
+ }
207
+
173
208
function isRefCreationCall ( callee : string ) : string | false {
209
+ if ( ! convertSymbol || currentScope [ convertSymbol ] !== undefined ) {
210
+ return false
211
+ }
174
212
if ( callee === convertSymbol ) {
175
213
return convertSymbol
176
214
}
@@ -628,7 +666,11 @@ export function transformAST(
628
666
)
629
667
}
630
668
631
- if ( callee === escapeSymbol ) {
669
+ if (
670
+ escapeSymbol &&
671
+ currentScope [ escapeSymbol ] === undefined &&
672
+ callee === escapeSymbol
673
+ ) {
632
674
s . remove ( node . callee . start ! + offset , node . callee . end ! + offset )
633
675
escapeScope = node
634
676
}
0 commit comments