fix(compiler-sfc): fix binding type for constants when hoistStatic is disabled (#8029)

This commit is contained in:
三咲智子 Kevin Deng 2023-04-06 17:19:00 +08:00 committed by GitHub
parent cac1512390
commit f7f4624191
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 8 deletions

View File

@ -130,3 +130,15 @@ return () => {}
}"
`;
exports[`sfc hoist static > should not hoist when disabled 1`] = `
"export default {
setup(__props) {
const foo = 'bar'
return () => {}
}
}"
`;

View File

@ -39,7 +39,7 @@ describe('SFC compile <script setup>', () => {
expect(bindings).toStrictEqual({
x: BindingTypes.SETUP_MAYBE_REF,
a: BindingTypes.SETUP_LET,
b: BindingTypes.LITERAL_CONST,
b: BindingTypes.SETUP_CONST,
c: BindingTypes.SETUP_CONST,
d: BindingTypes.SETUP_CONST,
xx: BindingTypes.SETUP_MAYBE_REF,

View File

@ -183,7 +183,22 @@ describe('sfc hoist static', () => {
</script>
`)
expect(bindings).toStrictEqual({
foo: BindingTypes.LITERAL_CONST
foo: BindingTypes.SETUP_CONST
})
assertCode(content)
})
test('should not hoist when disabled', () => {
const { content, bindings } = compile(
`
<script setup>
const foo = 'bar'
</script>
`,
{ hoistStatic: false }
)
expect(bindings).toStrictEqual({
foo: BindingTypes.SETUP_CONST
})
assertCode(content)
})

View File

@ -803,7 +803,7 @@ export function compileScript(
if (!node) return
walkIdentifiers(node, id => {
const binding = setupBindings[id.name]
if (binding && (binding !== BindingTypes.LITERAL_CONST || !hoistStatic)) {
if (binding && binding !== BindingTypes.LITERAL_CONST) {
error(
`\`${method}()\` in <script setup> cannot reference locally ` +
`declared variables because it will be hoisted outside of the ` +
@ -1258,7 +1258,13 @@ export function compileScript(
}
}
if (node.declaration) {
walkDeclaration(node.declaration, scriptBindings, vueImportAliases)
walkDeclaration(
'script',
node.declaration,
scriptBindings,
vueImportAliases,
hoistStatic
)
}
} else if (
(node.type === 'VariableDeclaration' ||
@ -1267,7 +1273,13 @@ export function compileScript(
node.type === 'TSEnumDeclaration') &&
!node.declare
) {
walkDeclaration(node, scriptBindings, vueImportAliases)
walkDeclaration(
'script',
node,
scriptBindings,
vueImportAliases,
hoistStatic
)
}
}
@ -1394,7 +1406,13 @@ export function compileScript(
node.type === 'TSEnumDeclaration') &&
!node.declare
) {
isAllLiteral = walkDeclaration(node, setupBindings, vueImportAliases)
isAllLiteral = walkDeclaration(
'scriptSetup',
node,
setupBindings,
vueImportAliases,
hoistStatic
)
}
// hoist literal constants
@ -1891,9 +1909,11 @@ function registerBinding(
}
function walkDeclaration(
from: 'script' | 'scriptSetup',
node: Declaration,
bindings: Record<string, BindingTypes>,
userImportAliases: Record<string, string>
userImportAliases: Record<string, string>,
hoistStatic: boolean
): boolean {
let isAllLiteral = false
@ -1918,7 +1938,10 @@ function walkDeclaration(
if (id.type === 'Identifier') {
let bindingType
const userReactiveBinding = userImportAliases['reactive']
if (isAllLiteral || (isConst && isStaticNode(init!))) {
if (
(hoistStatic || from === 'script') &&
(isAllLiteral || (isConst && isStaticNode(init!)))
) {
bindingType = BindingTypes.LITERAL_CONST
} else if (isCallOf(init, userReactiveBinding)) {
// treat reactive() calls as let since it's meant to be mutable