Skip to content

Commit

Permalink
fix(compiler-sfc): preserve old behavior when using withDefaults with…
Browse files Browse the repository at this point in the history
… desutructure

close #11930
  • Loading branch information
yyx990803 committed Sep 16, 2024
1 parent fbae210 commit 8492c3c
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -378,14 +378,15 @@ describe('sfc reactive props destructure', () => {
).toThrow(`destructure cannot use computed key`)
})

test('should error when used with withDefaults', () => {
expect(() =>
compile(
`<script setup lang="ts">
const { foo } = withDefaults(defineProps<{ foo: string }>(), { foo: 'foo' })
</script>`,
),
).toThrow(`withDefaults() is unnecessary when using destructure`)
test('should warn when used with withDefaults', () => {
compile(
`<script setup lang="ts">
const { foo } = withDefaults(defineProps<{ foo: string }>(), { foo: 'foo' })
</script>`,
)
expect(
`withDefaults() is unnecessary when using destructure`,
).toHaveBeenWarned()
})

test('should error if destructure reference local vars', () => {
Expand Down
28 changes: 20 additions & 8 deletions packages/compiler-sfc/src/script/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { ModelDecl } from './defineModel'
import type { BindingMetadata } from '../../../compiler-core/src'
import MagicString from 'magic-string'
import type { TypeScope } from './resolveType'
import { warn } from '../warn'

export class ScriptCompileContext {
isJS: boolean
Expand Down Expand Up @@ -145,20 +146,31 @@ export class ScriptCompileContext {
return block.content.slice(node.start!, node.end!)
}

warn(msg: string, node: Node, scope?: TypeScope): void {
warn(generateError(msg, node, this, scope))
}

error(msg: string, node: Node, scope?: TypeScope): never {
const offset = scope ? scope.offset : this.startOffset!
throw new Error(
`[@vue/compiler-sfc] ${msg}\n\n${
(scope || this.descriptor).filename
}\n${generateCodeFrame(
(scope || this.descriptor).source,
node.start! + offset,
node.end! + offset,
)}`,
`[@vue/compiler-sfc] ${generateError(msg, node, this, scope)}`,
)
}
}

function generateError(
msg: string,
node: Node,
ctx: ScriptCompileContext,
scope?: TypeScope,
) {
const offset = scope ? scope.offset : ctx.startOffset!
return `${msg}\n\n${(scope || ctx.descriptor).filename}\n${generateCodeFrame(
(scope || ctx.descriptor).source,
node.start! + offset,
node.end! + offset,
)}`
}

export function resolveParserPlugins(
lang: string,
userPlugins?: ParserPlugin[],
Expand Down
19 changes: 14 additions & 5 deletions packages/compiler-sfc/src/script/defineProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export function processDefineProps(
ctx: ScriptCompileContext,
node: Node,
declId?: LVal,
isWithDefaults = false,
): boolean {
if (!isCallOf(node, DEFINE_PROPS)) {
return processWithDefaults(ctx, node, declId)
Expand Down Expand Up @@ -81,7 +82,7 @@ export function processDefineProps(
}

// handle props destructure
if (declId && declId.type === 'ObjectPattern') {
if (!isWithDefaults && declId && declId.type === 'ObjectPattern') {
processPropsDestructure(ctx, declId)
}

Expand All @@ -99,7 +100,14 @@ function processWithDefaults(
if (!isCallOf(node, WITH_DEFAULTS)) {
return false
}
if (!processDefineProps(ctx, node.arguments[0], declId)) {
if (
!processDefineProps(
ctx,
node.arguments[0],
declId,
true /* isWithDefaults */,
)
) {
ctx.error(
`${WITH_DEFAULTS}' first argument must be a ${DEFINE_PROPS} call.`,
node.arguments[0] || node,
Expand All @@ -113,10 +121,11 @@ function processWithDefaults(
node,
)
}
if (ctx.propsDestructureDecl) {
ctx.error(
if (declId && declId.type === 'ObjectPattern') {
ctx.warn(
`${WITH_DEFAULTS}() is unnecessary when using destructure with ${DEFINE_PROPS}().\n` +
`Prefer using destructure default values, e.g. const { foo = 1 } = defineProps(...).`,
`Reactive destructure will be disabled when using withDefaults().\n` +
`Prefer using destructure default values, e.g. const { foo = 1 } = defineProps(...). `,
node.callee,
)
}
Expand Down

0 comments on commit 8492c3c

Please sign in to comment.