Skip to content

Commit 701b95f

Browse files
authored
fix(compiler-sfc): rewrite default export with AST analysis instead of regex (#7068)
closes #7038 closes #7041 closes #7078
1 parent 7def8b1 commit 701b95f

File tree

5 files changed

+149
-89
lines changed

5 files changed

+149
-89
lines changed

packages/compiler-sfc/__tests__/rewriteDefault.spec.ts

+81-34
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import { rewriteDefault } from '../src'
22

33
describe('compiler sfc: rewriteDefault', () => {
44
test('without export default', () => {
5-
expect(rewriteDefault(`export a = {}`, 'script')).toMatchInlineSnapshot(`
6-
"export a = {}
5+
expect(rewriteDefault(`export const a = {}`, 'script'))
6+
.toMatchInlineSnapshot(`
7+
"export const a = {}
78
const script = {}"
89
`)
910
})
@@ -14,6 +15,14 @@ describe('compiler sfc: rewriteDefault', () => {
1415
).toMatchInlineSnapshot(`"const script = {}"`)
1516
})
1617

18+
test('rewrite variable value default', () => {
19+
expect(rewriteDefault(`export const foo = 'default'`, 'script'))
20+
.toMatchInlineSnapshot(`
21+
"export const foo = 'default'
22+
const script = {}"
23+
`)
24+
})
25+
1726
test('rewrite export named default', () => {
1827
expect(
1928
rewriteDefault(
@@ -36,6 +45,18 @@ describe('compiler sfc: rewriteDefault', () => {
3645
export { a as b, a as c}
3746
const script = a"
3847
`)
48+
49+
expect(
50+
rewriteDefault(
51+
`const a = 1 \n export { a as b } \n export { a as default, a as c }`,
52+
'script'
53+
)
54+
).toMatchInlineSnapshot(`
55+
"const a = 1
56+
export { a as b }
57+
export { a as c }
58+
const script = a"
59+
`)
3960
})
4061

4162
test('w/ comments', async () => {
@@ -52,7 +73,7 @@ describe('compiler sfc: rewriteDefault', () => {
5273
).toMatchInlineSnapshot(`
5374
"let App = {}
5475
export {
55-
76+
5677
}
5778
const _sfc_main = App"
5879
`)
@@ -96,25 +117,25 @@ describe('compiler sfc: rewriteDefault', () => {
96117
expect(
97118
rewriteDefault(`export { default, foo } from './index.js'`, 'script')
98119
).toMatchInlineSnapshot(`
99-
"import { default as __VUE_DEFAULT__ } from './index.js'
100-
export { foo } from './index.js'
101-
const script = __VUE_DEFAULT__"
120+
"import { default as __VUE_DEFAULT__ } from './index.js'
121+
export { foo } from './index.js'
122+
const script = __VUE_DEFAULT__"
102123
`)
103124

104125
expect(
105126
rewriteDefault(`export { default , foo } from './index.js'`, 'script')
106127
).toMatchInlineSnapshot(`
107-
"import { default as __VUE_DEFAULT__ } from './index.js'
108-
export { foo } from './index.js'
109-
const script = __VUE_DEFAULT__"
128+
"import { default as __VUE_DEFAULT__ } from './index.js'
129+
export { foo } from './index.js'
130+
const script = __VUE_DEFAULT__"
110131
`)
111132

112133
expect(
113134
rewriteDefault(`export { foo, default } from './index.js'`, 'script')
114135
).toMatchInlineSnapshot(`
115-
"import { default as __VUE_DEFAULT__ } from './index.js'
116-
export { foo, } from './index.js'
117-
const script = __VUE_DEFAULT__"
136+
"import { default as __VUE_DEFAULT__ } from './index.js'
137+
export { foo, } from './index.js'
138+
const script = __VUE_DEFAULT__"
118139
`)
119140

120141
expect(
@@ -123,9 +144,9 @@ describe('compiler sfc: rewriteDefault', () => {
123144
'script'
124145
)
125146
).toMatchInlineSnapshot(`
126-
"import { foo } from './index.js'
127-
export { bar } from './index.js'
128-
const script = foo"
147+
"import { foo as __VUE_DEFAULT__ } from './index.js'
148+
export { bar } from './index.js'
149+
const script = __VUE_DEFAULT__"
129150
`)
130151

131152
expect(
@@ -134,9 +155,9 @@ describe('compiler sfc: rewriteDefault', () => {
134155
'script'
135156
)
136157
).toMatchInlineSnapshot(`
137-
"import { foo } from './index.js'
138-
export { bar } from './index.js'
139-
const script = foo"
158+
"import { foo as __VUE_DEFAULT__ } from './index.js'
159+
export { bar } from './index.js'
160+
const script = __VUE_DEFAULT__"
140161
`)
141162

142163
expect(
@@ -145,26 +166,50 @@ describe('compiler sfc: rewriteDefault', () => {
145166
'script'
146167
)
147168
).toMatchInlineSnapshot(`
148-
"import { foo } from './index.js'
149-
export { bar, } from './index.js'
150-
const script = foo"
169+
"import { foo as __VUE_DEFAULT__ } from './index.js'
170+
export { bar, } from './index.js'
171+
const script = __VUE_DEFAULT__"
172+
`)
173+
174+
expect(
175+
rewriteDefault(
176+
`export { foo as default } from './index.js' \n const foo = 1`,
177+
'script'
178+
)
179+
).toMatchInlineSnapshot(`
180+
"import { foo as __VUE_DEFAULT__ } from './index.js'
181+
export { } from './index.js'
182+
const foo = 1
183+
const script = __VUE_DEFAULT__"
184+
`)
185+
186+
expect(
187+
rewriteDefault(
188+
`const a = 1 \nexport { a as default } from 'xxx'`,
189+
'script'
190+
)
191+
).toMatchInlineSnapshot(`
192+
"import { a as __VUE_DEFAULT__ } from 'xxx'
193+
const a = 1
194+
export { } from 'xxx'
195+
const script = __VUE_DEFAULT__"
151196
`)
152197
})
153198

154199
test('export default class', async () => {
155200
expect(rewriteDefault(`export default class Foo {}`, 'script'))
156201
.toMatchInlineSnapshot(`
157-
"class Foo {}
158-
const script = Foo"
159-
`)
202+
" class Foo {}
203+
const script = Foo"
204+
`)
160205
})
161206

162207
test('export default class w/ comments', async () => {
163208
expect(
164209
rewriteDefault(`// export default\nexport default class Foo {}`, 'script')
165210
).toMatchInlineSnapshot(`
166211
"// export default
167-
class Foo {}
212+
class Foo {}
168213
const script = Foo"
169214
`)
170215
})
@@ -190,16 +235,18 @@ describe('compiler sfc: rewriteDefault', () => {
190235
).toMatchInlineSnapshot(`
191236
"/*
192237
export default class Foo {}*/
193-
class Bar {}
238+
class Bar {}
194239
const script = Bar"
195240
`)
196241
})
197242

198243
test('@Component\nexport default class', async () => {
199-
expect(rewriteDefault(`@Component\nexport default class Foo {}`, 'script'))
200-
.toMatchInlineSnapshot(`
201-
"@Component
202-
class Foo {}
244+
expect(
245+
rewriteDefault(`@Component\nexport default class Foo {}`, 'script', [
246+
'decorators-legacy'
247+
])
248+
).toMatchInlineSnapshot(`
249+
"@Component class Foo {}
203250
const script = Foo"
204251
`)
205252
})
@@ -208,12 +255,12 @@ describe('compiler sfc: rewriteDefault', () => {
208255
expect(
209256
rewriteDefault(
210257
`// export default\n@Component\nexport default class Foo {}`,
211-
'script'
258+
'script',
259+
['decorators-legacy']
212260
)
213261
).toMatchInlineSnapshot(`
214262
"// export default
215-
@Component
216-
class Foo {}
263+
@Component class Foo {}
217264
const script = Foo"
218265
`)
219266
})
@@ -242,7 +289,7 @@ describe('compiler sfc: rewriteDefault', () => {
242289
"/*
243290
@Component
244291
export default class Foo {}*/
245-
class Bar {}
292+
class Bar {}
246293
const script = Bar"
247294
`)
248295
})

packages/compiler-sfc/src/compileScript.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ import {
5353
} from './cssVars'
5454
import { compileTemplate, SFCTemplateCompileOptions } from './compileTemplate'
5555
import { warnOnce } from './warn'
56-
import { rewriteDefault } from './rewriteDefault'
56+
import { rewriteDefaultAST } from './rewriteDefault'
5757
import { createCache } from './cache'
5858
import { shouldTransform, transformAST } from '@vue/reactivity-transform'
5959

@@ -231,7 +231,9 @@ export function compileScript(
231231
}
232232
}
233233
if (cssVars.length) {
234-
content = rewriteDefault(content, DEFAULT_VAR, plugins)
234+
const s = new MagicString(content)
235+
rewriteDefaultAST(scriptAst.body, s, DEFAULT_VAR)
236+
content = s.toString()
235237
content += genNormalScriptCssVarsCode(
236238
cssVars,
237239
bindings,
@@ -1759,6 +1761,7 @@ export function compileScript(
17591761

17601762
return {
17611763
...scriptSetup,
1764+
s,
17621765
bindings: bindingMetadata,
17631766
imports: userImports,
17641767
content: s.toString(),

packages/compiler-sfc/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export { parse } from './parse'
33
export { compileTemplate } from './compileTemplate'
44
export { compileStyle, compileStyleAsync } from './compileStyle'
55
export { compileScript } from './compileScript'
6-
export { rewriteDefault } from './rewriteDefault'
6+
export { rewriteDefault, rewriteDefaultAST } from './rewriteDefault'
77
export {
88
shouldTransform as shouldTransformRef,
99
transform as transformRef,

packages/compiler-sfc/src/parse.ts

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { TemplateCompiler } from './compileTemplate'
1212
import { parseCssVars } from './cssVars'
1313
import { createCache } from './cache'
1414
import { hmrShouldReload, ImportBinding } from './compileScript'
15+
import MagicString from 'magic-string'
1516

1617
export const DEFAULT_FILENAME = 'anonymous.vue'
1718

@@ -41,6 +42,7 @@ export interface SFCTemplateBlock extends SFCBlock {
4142

4243
export interface SFCScriptBlock extends SFCBlock {
4344
type: 'script'
45+
s: MagicString
4446
setup?: string | boolean
4547
bindings?: BindingMetadata
4648
imports?: Record<string, ImportBinding>

0 commit comments

Comments
 (0)