feat(compiler-sfc): enable reactive props destructure by default

Also allow prohibiting usage via config.
RFC: https://github.com/vuejs/rfcs/discussions/502
This commit is contained in:
Evan You 2024-04-29 10:45:48 +08:00
parent 75c8cf63a1
commit d2dac0e359
No known key found for this signature in database
GPG Key ID: B9D421896CA450FB
4 changed files with 26 additions and 14 deletions

View File

@ -597,11 +597,29 @@ const props = defineProps({ foo: String })
foo: Foo foo: Foo
}>() }>()
</script>`, </script>`,
{
propsDestructure: false,
},
) )
expect(content).toMatch(`const { foo } = __props`) expect(content).toMatch(`const { foo } = __props`)
assertCode(content) assertCode(content)
}) })
test('prohibiting reactive destructure', () => {
expect(() =>
compile(
`<script setup lang="ts">
const { foo } = defineProps<{
foo: Foo
}>()
</script>`,
{
propsDestructure: 'error',
},
),
).toThrow()
})
describe('errors', () => { describe('errors', () => {
test('w/ both type and non-type args', () => { test('w/ both type and non-type args', () => {
expect(() => { expect(() => {

View File

@ -6,7 +6,6 @@ describe('sfc reactive props destructure', () => {
function compile(src: string, options?: Partial<SFCScriptCompileOptions>) { function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {
return compileSFCScript(src, { return compileSFCScript(src, {
inlineTemplate: true, inlineTemplate: true,
propsDestructure: true,
...options, ...options,
}) })
} }

View File

@ -106,10 +106,11 @@ export interface SFCScriptCompileOptions {
*/ */
hoistStatic?: boolean hoistStatic?: boolean
/** /**
* (**Experimental**) Enable reactive destructure for `defineProps` * Set to `false` to disable reactive destructure for `defineProps` (pre-3.5
* @default false * behavior), or set to `'error'` to throw hard error on props destructures.
* @default true
*/ */
propsDestructure?: boolean propsDestructure?: boolean | 'error'
/** /**
* File system access methods to be used when resolving types * File system access methods to be used when resolving types
* imported in SFC macros. Defaults to ts.sys in Node.js, can be overwritten * imported in SFC macros. Defaults to ts.sys in Node.js, can be overwritten

View File

@ -22,23 +22,17 @@ import { genPropsAccessExp } from '@vue/shared'
import { isCallOf, resolveObjectKey } from './utils' import { isCallOf, resolveObjectKey } from './utils'
import type { ScriptCompileContext } from './context' import type { ScriptCompileContext } from './context'
import { DEFINE_PROPS } from './defineProps' import { DEFINE_PROPS } from './defineProps'
import { warnOnce } from '../warn'
export function processPropsDestructure( export function processPropsDestructure(
ctx: ScriptCompileContext, ctx: ScriptCompileContext,
declId: ObjectPattern, declId: ObjectPattern,
) { ) {
if (!ctx.options.propsDestructure) { if (ctx.options.propsDestructure === 'error') {
ctx.error(`Props destructure is explicitly prohibited via config.`, declId)
} else if (ctx.options.propsDestructure === false) {
return return
} }
warnOnce(
`This project is using reactive props destructure, which is an experimental ` +
`feature. It may receive breaking changes or be removed in the future, so ` +
`use at your own risk.\n` +
`To stay updated, follow the RFC at https://github.com/vuejs/rfcs/discussions/502.`,
)
ctx.propsDestructureDecl = declId ctx.propsDestructureDecl = declId
const registerBinding = ( const registerBinding = (
@ -104,7 +98,7 @@ export function transformDestructuredProps(
ctx: ScriptCompileContext, ctx: ScriptCompileContext,
vueImportAliases: Record<string, string>, vueImportAliases: Record<string, string>,
) { ) {
if (!ctx.options.propsDestructure) { if (ctx.options.propsDestructure === false) {
return return
} }