feat(compiler-sfc): support arbitrary expression as withDefaults argument

ref #6459
This commit is contained in:
Evan You 2023-03-31 09:04:27 +08:00
parent 566748c1ed
commit fe619443d2
3 changed files with 58 additions and 12 deletions

View File

@ -1901,6 +1901,33 @@ const props = __props as {
return { props, get defaults() { return defaults } }
}
})"
`;
exports[`SFC compile <script setup> > with TypeScript > withDefaults (reference) 1`] = `
"import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from 'vue'
import { defaults } from './foo'
export default /*#__PURE__*/_defineComponent({
props: _mergeDefaults({
foo: { type: String, required: false },
bar: { type: Number, required: false },
baz: { type: Boolean, required: true }
}, defaults),
setup(__props: any, { expose: __expose }) {
__expose();
const props = __props as {
foo?: string
bar?: number
baz: boolean
};
return { props, get defaults() { return defaults } }
}

View File

@ -1378,6 +1378,29 @@ const emit = defineEmits(['a', 'b'])
)
})
test('withDefaults (reference)', () => {
const { content } = compile(`
<script setup lang="ts">
import { defaults } from './foo'
const props = withDefaults(defineProps<{
foo?: string
bar?: number
baz: boolean
}>(), defaults)
</script>
`)
assertCode(content)
expect(content).toMatch(`import { mergeDefaults as _mergeDefaults`)
expect(content).toMatch(
`
_mergeDefaults({
foo: { type: String, required: false },
bar: { type: Number, required: false },
baz: { type: Boolean, required: true }
}, defaults)`.trim()
)
})
// #7111
test('withDefaults (dynamic) w/ production mode', () => {
const { content } = compile(

View File

@ -313,7 +313,7 @@ export function compileScript(
let hasDefaultExportRender = false
let hasDefineOptionsCall = false
let propsRuntimeDecl: Node | undefined
let propsRuntimeDefaults: ObjectExpression | undefined
let propsRuntimeDefaults: Node | undefined
let propsDestructureDecl: Node | undefined
let propsDestructureRestId: string | undefined
let propsTypeDecl: PropsDeclType | undefined
@ -534,15 +534,9 @@ export function compileScript(
node.callee
)
}
propsRuntimeDefaults = node.arguments[1] as ObjectExpression
if (
!propsRuntimeDefaults ||
propsRuntimeDefaults.type !== 'ObjectExpression'
) {
error(
`The 2nd argument of ${WITH_DEFAULTS} must be an object literal.`,
propsRuntimeDefaults || node
)
propsRuntimeDefaults = node.arguments[1]
if (!propsRuntimeDefaults) {
error(`The 2nd argument of ${WITH_DEFAULTS} is required.`, node)
}
} else {
error(
@ -872,7 +866,9 @@ export function compileScript(
destructured.needSkipFactory ? `, skipFactory: true` : ``
}`
} else if (hasStaticDefaults) {
const prop = propsRuntimeDefaults!.properties.find(node => {
const prop = (
propsRuntimeDefaults as ObjectExpression
).properties.find(node => {
if (node.type === 'SpreadElement') return false
return resolveObjectKey(node.key, node.computed) === key
}) as ObjectProperty | ObjectMethod
@ -1001,7 +997,7 @@ export function compileScript(
m.key.type === 'Identifier'
) {
if (
propsRuntimeDefaults!.properties.some(p => {
(propsRuntimeDefaults as ObjectExpression).properties.some(p => {
if (p.type === 'SpreadElement') return false
return (
resolveObjectKey(p.key, p.computed) ===