Skip to content

Commit 6d762a8

Browse files
authored
fix(compiler-sfc): removeSpecifier issue when removing initial imports (script-setup) (#2729)
1 parent 22b382a commit 6d762a8

File tree

3 files changed

+43
-8
lines changed

3 files changed

+43
-8
lines changed

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

+19
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,25 @@ return { x }
164164
}"
165165
`;
166166
167+
exports[`SFC compile <script setup> imports should allow defineProps/Emit at the start of imports 1`] = `
168+
"import { ref } from 'vue'
169+
170+
export default {
171+
expose: [],
172+
props: ['foo'],
173+
emits: ['bar'],
174+
setup(__props) {
175+
176+
177+
178+
const r = ref(0)
179+
180+
return { r, ref }
181+
}
182+
183+
}"
184+
`;
185+
167186
exports[`SFC compile <script setup> imports should extract comment for import or type declarations 1`] = `
168187
"import a from 'a' // comment
169188
import b from 'b'

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

+12
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,18 @@ const myEmit = defineEmit(['foo', 'bar'])
141141
)
142142
})
143143

144+
// #2740
145+
test('should allow defineProps/Emit at the start of imports', () => {
146+
assertCode(
147+
compile(`<script setup>
148+
import { defineProps, defineEmit, ref } from 'vue'
149+
defineProps(['foo'])
150+
defineEmit(['bar'])
151+
const r = ref(0)
152+
</script>`).content
153+
)
154+
})
155+
144156
test('dedupe between user & helper', () => {
145157
const { content } = compile(`
146158
<script setup>

packages/compiler-sfc/src/compileScript.ts

+12-8
Original file line numberDiff line numberDiff line change
@@ -597,19 +597,23 @@ export function compileScript(
597597

598598
// dedupe imports
599599
let removed = 0
600-
let prev: Node | undefined, next: Node | undefined
601-
const removeSpecifier = (node: Node) => {
600+
const removeSpecifier = (i: number) => {
601+
const removeLeft = i > removed
602602
removed++
603+
const current = node.specifiers[i]
604+
const next = node.specifiers[i + 1]
603605
s.remove(
604-
prev ? prev.end! + startOffset : node.start! + startOffset,
605-
next && !prev ? next.start! + startOffset : node.end! + startOffset
606+
removeLeft
607+
? node.specifiers[i - 1].end! + startOffset
608+
: current.start! + startOffset,
609+
next && !removeLeft
610+
? next.start! + startOffset
611+
: current.end! + startOffset
606612
)
607613
}
608614

609615
for (let i = 0; i < node.specifiers.length; i++) {
610616
const specifier = node.specifiers[i]
611-
prev = node.specifiers[i - 1]
612-
next = node.specifiers[i + 1]
613617
const local = specifier.local.name
614618
const imported =
615619
specifier.type === 'ImportSpecifier' &&
@@ -621,11 +625,11 @@ export function compileScript(
621625
source === 'vue' &&
622626
(imported === DEFINE_PROPS || imported === DEFINE_EMIT)
623627
) {
624-
removeSpecifier(specifier)
628+
removeSpecifier(i)
625629
} else if (existing) {
626630
if (existing.source === source && existing.imported === imported) {
627631
// already imported in <script setup>, dedupe
628-
removeSpecifier(specifier)
632+
removeSpecifier(i)
629633
} else {
630634
error(`different imports aliased to same local name.`, specifier)
631635
}

0 commit comments

Comments
 (0)