Skip to content

Commit 9826382

Browse files
authored
fix(compiler-sfc): fix <script> and <script setup> co-usage ordering edge case (vuejs#4419)
Fix: vuejs#4395 Fix: vuejs#4376
1 parent a46b0a9 commit 9826382

File tree

3 files changed

+60
-9
lines changed

3 files changed

+60
-9
lines changed

packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap

+21
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,27 @@ return { x }
3333
export const n = 1"
3434
`;
3535
36+
exports[`SFC compile <script setup> <script> and <script setup> co-usage script setup first, lang="ts", script block content export default 1`] = `
37+
"import { defineComponent as _defineComponent } from 'vue'
38+
import { x } from './x'
39+
40+
function setup(__props, { expose }) {
41+
42+
x()
43+
44+
return { x }
45+
}
46+
47+
48+
const __default__ = {
49+
name: \\"test\\"
50+
}
51+
52+
export default _defineComponent({
53+
...__default__,
54+
setup})"
55+
`;
56+
3657
exports[`SFC compile <script setup> <script> and <script setup> co-usage spaces in ExportDefaultDeclaration node with many spaces and newline 1`] = `
3758
"import { x } from './x'
3859

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

+18
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,24 @@ defineExpose({ foo: 123 })
202202
`)
203203
assertCode(content)
204204
})
205+
206+
// #4395
207+
test('script setup first, lang="ts", script block content export default', () => {
208+
const { content } = compile(`
209+
<script setup lang="ts">
210+
import { x } from './x'
211+
x()
212+
</script>
213+
<script lang="ts">
214+
export default {
215+
name: "test"
216+
}
217+
</script>
218+
`)
219+
// ensure __default__ is declared before used
220+
expect(content).toMatch(/const __default__[\S\s]*\.\.\.__default__/m)
221+
assertCode(content)
222+
})
205223
})
206224

207225
describe('imports', () => {

packages/compiler-sfc/src/compileScript.ts

+21-9
Original file line numberDiff line numberDiff line change
@@ -1150,15 +1150,27 @@ export function compileScript(
11501150
// wrap setup code with function.
11511151
// export the content of <script setup> as a named export, `setup`.
11521152
// this allows `import { setup } from '*.vue'` for testing purposes.
1153-
s.prependLeft(
1154-
startOffset,
1155-
`\nexport default ${helper(
1156-
`defineComponent`
1157-
)}({${def}${runtimeOptions}\n ${
1158-
hasAwait ? `async ` : ``
1159-
}setup(${args}) {\n${exposeCall}`
1160-
)
1161-
s.appendRight(endOffset, `})`)
1153+
if (defaultExport) {
1154+
s.prependLeft(
1155+
startOffset,
1156+
`\n${hasAwait ? `async ` : ``}function setup(${args}) {\n`
1157+
)
1158+
s.append(
1159+
`\nexport default ${helper(
1160+
`defineComponent`
1161+
)}({${def}${runtimeOptions}\n setup})`
1162+
)
1163+
} else {
1164+
s.prependLeft(
1165+
startOffset,
1166+
`\nexport default ${helper(
1167+
`defineComponent`
1168+
)}({${def}${runtimeOptions}\n ${
1169+
hasAwait ? `async ` : ``
1170+
}setup(${args}) {\n${exposeCall}`
1171+
)
1172+
s.appendRight(endOffset, `})`)
1173+
}
11621174
} else {
11631175
if (defaultExport) {
11641176
// can't rely on spread operator in non ts mode

0 commit comments

Comments
 (0)