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({ expect(bindings).toStrictEqual({
x: BindingTypes.SETUP_MAYBE_REF, x: BindingTypes.SETUP_MAYBE_REF,
a: BindingTypes.SETUP_LET, a: BindingTypes.SETUP_LET,
b: BindingTypes.LITERAL_CONST, b: BindingTypes.SETUP_CONST,
c: BindingTypes.SETUP_CONST, c: BindingTypes.SETUP_CONST,
d: BindingTypes.SETUP_CONST, d: BindingTypes.SETUP_CONST,
xx: BindingTypes.SETUP_MAYBE_REF, xx: BindingTypes.SETUP_MAYBE_REF,

View File

@ -183,7 +183,22 @@ describe('sfc hoist static', () => {
</script> </script>
`) `)
expect(bindings).toStrictEqual({ 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) assertCode(content)
}) })

View File

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