feat(compiler-sfc): `withDefaults` supports the use of local variables
This commit is contained in:
parent
a95e612b25
commit
43e0e26dd4
|
@ -338,6 +338,27 @@ return { props, get defaults() { return defaults } }
|
|||
})"
|
||||
`;
|
||||
|
||||
exports[`defineProps > withDefaults (locally variable) 1`] = `
|
||||
"import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from 'vue'
|
||||
const defaults = { baz: false }
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
props: _mergeDefaults({
|
||||
baz: { type: Boolean, required: true }
|
||||
}, defaults),
|
||||
setup(__props: any, { expose: __expose }) {
|
||||
__expose();
|
||||
|
||||
const props = __props;
|
||||
|
||||
|
||||
|
||||
return { defaults, props }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`defineProps > withDefaults (reference) 1`] = `
|
||||
"import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from 'vue'
|
||||
import { defaults } from './foo'
|
||||
|
|
|
@ -470,6 +470,26 @@ const props = defineProps({ foo: String })
|
|||
)
|
||||
})
|
||||
|
||||
test('withDefaults (locally variable)', () => {
|
||||
const { content } = compile(`
|
||||
<script setup lang="ts">
|
||||
const defaults = { baz: false }
|
||||
const props = withDefaults(defineProps<{
|
||||
baz: boolean
|
||||
}>(), defaults)
|
||||
</script>
|
||||
`)
|
||||
|
||||
assertCode(content)
|
||||
expect(content).toMatch(`import { mergeDefaults as _mergeDefaults`)
|
||||
expect(content).toMatch(
|
||||
`
|
||||
_mergeDefaults({
|
||||
baz: { type: Boolean, required: true }
|
||||
}, defaults)`.trim()
|
||||
)
|
||||
})
|
||||
|
||||
// #7111
|
||||
test('withDefaults (dynamic) w/ production mode', () => {
|
||||
const { content } = compile(
|
||||
|
|
|
@ -193,6 +193,7 @@ export function compileScript(
|
|||
// const ctx.bindingMetadata: BindingMetadata = {}
|
||||
const scriptBindings: Record<string, BindingTypes> = Object.create(null)
|
||||
const setupBindings: Record<string, BindingTypes> = Object.create(null)
|
||||
const withDefaultsVariables: Record<string, Statement> = {}
|
||||
|
||||
let defaultExport: Node | undefined
|
||||
let hasAwait = false
|
||||
|
@ -258,7 +259,11 @@ export function compileScript(
|
|||
if (!node) return
|
||||
walkIdentifiers(node, id => {
|
||||
const binding = setupBindings[id.name]
|
||||
if (binding && binding !== BindingTypes.LITERAL_CONST) {
|
||||
if (
|
||||
binding &&
|
||||
binding !== BindingTypes.LITERAL_CONST &&
|
||||
!withDefaultsVariables[id.name]
|
||||
) {
|
||||
ctx.error(
|
||||
`\`${method}()\` in <script setup> cannot reference locally ` +
|
||||
`declared variables because it will be hoisted outside of the ` +
|
||||
|
@ -636,6 +641,20 @@ export function compileScript(
|
|||
parent.type === 'ExpressionStatement'
|
||||
)
|
||||
}
|
||||
|
||||
if (child.type === 'Identifier') {
|
||||
if (parent.type === 'VariableDeclarator') {
|
||||
withDefaultsVariables[child.name] = node
|
||||
} else if (
|
||||
parent.type === 'CallExpression' &&
|
||||
parent.callee.type === 'Identifier' &&
|
||||
parent.callee.name === WITH_DEFAULTS &&
|
||||
withDefaultsVariables[child.name]
|
||||
) {
|
||||
const node = withDefaultsVariables[child.name]
|
||||
hoistNode(node)
|
||||
}
|
||||
}
|
||||
},
|
||||
exit(node: Node) {
|
||||
if (node.type === 'BlockStatement') scope.pop()
|
||||
|
|
Loading…
Reference in New Issue