Skip to content

Commit 8d1f526

Browse files
committed
fix(compiler-sfc): fix binding analysis for aliased late import
1 parent 4a00fdd commit 8d1f526

File tree

2 files changed

+60
-33
lines changed

2 files changed

+60
-33
lines changed

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

+13
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,19 @@ defineExpose({ foo: 123 })
391391
bar: BindingTypes.SETUP_REACTIVE_CONST
392392
})
393393
})
394+
395+
test('aliased usage before import site', () => {
396+
const { bindings } = compile(`
397+
<script setup>
398+
const bar = x(1)
399+
import { reactive as x } from 'vue'
400+
</script>
401+
`)
402+
expect(bindings).toStrictEqual({
403+
bar: BindingTypes.SETUP_REACTIVE_CONST,
404+
x: BindingTypes.SETUP_CONST
405+
})
406+
})
394407
})
395408
})
396409

packages/compiler-sfc/src/compileScript.ts

+47-33
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,25 @@ export function compileScript(
354354
)
355355
}
356356

357+
function hoistNode(node: Statement) {
358+
const start = node.start! + startOffset
359+
let end = node.end! + startOffset
360+
// locate comment
361+
if (node.trailingComments && node.trailingComments.length > 0) {
362+
const lastCommentNode =
363+
node.trailingComments[node.trailingComments.length - 1]
364+
end = lastCommentNode.end + startOffset
365+
}
366+
// locate the end of whitespace between this statement and the next
367+
while (end <= source.length) {
368+
if (!/\s/.test(source.charAt(end))) {
369+
break
370+
}
371+
end++
372+
}
373+
s.move(start, end, 0)
374+
}
375+
357376
function registerUserImport(
358377
source: string,
359378
local: string,
@@ -891,6 +910,7 @@ export function compileScript(
891910
scriptStartOffset!
892911
)
893912

913+
// walk import declarations first
894914
for (const node of scriptAst.body) {
895915
if (node.type === 'ImportDeclaration') {
896916
// record imports for dedupe
@@ -910,7 +930,11 @@ export function compileScript(
910930
!options.inlineTemplate
911931
)
912932
}
913-
} else if (node.type === 'ExportDefaultDeclaration') {
933+
}
934+
}
935+
936+
for (const node of scriptAst.body) {
937+
if (node.type === 'ExportDefaultDeclaration') {
914938
// export default
915939
defaultExport = node
916940

@@ -1040,39 +1064,9 @@ export function compileScript(
10401064
)
10411065

10421066
for (const node of scriptSetupAst.body) {
1043-
const start = node.start! + startOffset
1044-
let end = node.end! + startOffset
1045-
// locate comment
1046-
if (node.trailingComments && node.trailingComments.length > 0) {
1047-
const lastCommentNode =
1048-
node.trailingComments[node.trailingComments.length - 1]
1049-
end = lastCommentNode.end + startOffset
1050-
}
1051-
// locate the end of whitespace between this statement and the next
1052-
while (end <= source.length) {
1053-
if (!/\s/.test(source.charAt(end))) {
1054-
break
1055-
}
1056-
end++
1057-
}
1058-
1059-
// (Dropped) `ref: x` bindings
1060-
if (
1061-
node.type === 'LabeledStatement' &&
1062-
node.label.name === 'ref' &&
1063-
node.body.type === 'ExpressionStatement'
1064-
) {
1065-
error(
1066-
`ref sugar using the label syntax was an experimental proposal and ` +
1067-
`has been dropped based on community feedback. Please check out ` +
1068-
`the new proposal at https://github.com/vuejs/rfcs/discussions/369`,
1069-
node
1070-
)
1071-
}
1072-
10731067
if (node.type === 'ImportDeclaration') {
10741068
// import declarations are moved to top
1075-
s.move(start, end, 0)
1069+
hoistNode(node)
10761070

10771071
// dedupe imports
10781072
let removed = 0
@@ -1137,6 +1131,26 @@ export function compileScript(
11371131
s.remove(node.start! + startOffset, node.end! + startOffset)
11381132
}
11391133
}
1134+
}
1135+
1136+
for (const node of scriptSetupAst.body) {
1137+
// already processed
1138+
if (node.type === 'ImportDeclaration') continue
1139+
1140+
// (Dropped) `ref: x` bindings
1141+
// TODO remove when out of experimental
1142+
if (
1143+
node.type === 'LabeledStatement' &&
1144+
node.label.name === 'ref' &&
1145+
node.body.type === 'ExpressionStatement'
1146+
) {
1147+
error(
1148+
`ref sugar using the label syntax was an experimental proposal and ` +
1149+
`has been dropped based on community feedback. Please check out ` +
1150+
`the new proposal at https://github.com/vuejs/rfcs/discussions/369`,
1151+
node
1152+
)
1153+
}
11401154

11411155
if (node.type === 'ExpressionStatement') {
11421156
// process `defineProps` and `defineEmit(s)` calls
@@ -1268,7 +1282,7 @@ export function compileScript(
12681282
(node.type === 'VariableDeclaration' && node.declare)
12691283
) {
12701284
recordType(node, declaredTypes)
1271-
s.move(start, end, 0)
1285+
hoistNode(node)
12721286
}
12731287
}
12741288
}

0 commit comments

Comments
 (0)