diff --git a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
index b7925ada895..949c9946d9f 100644
--- a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
+++ b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
@@ -62,6 +62,24 @@ return { fn }
})"
`;
+exports[`SFC compile
- `)
- assertCode(content)
- expect(content).toMatch(`const a = 1;`) // test correct removal
- expect(content).toMatch(`props: ['item'],`)
- expect(content).toMatch(`emits: ['a'],`)
- })
-
- // #6757
- test('defineProps/defineEmits in multi-variable declaration fix #6757 ', () => {
- const { content } = compile(`
-
- `)
- assertCode(content)
- expect(content).toMatch(`const a = 1;`) // test correct removal
- expect(content).toMatch(`props: ['item'],`)
- expect(content).toMatch(`emits: ['a'],`)
- })
-
- // #7422
- test('defineProps/defineEmits in multi-variable declaration fix #7422', () => {
- const { content } = compile(`
-
- `)
- assertCode(content)
- expect(content).toMatch(`props: ['item'],`)
- expect(content).toMatch(`emits: ['foo'],`)
- expect(content).toMatch(`const a = 0,`)
- expect(content).toMatch(`b = 0;`)
- })
-
- test('defineProps/defineEmits in multi-variable declaration (full removal)', () => {
- const { content } = compile(`
-
- `)
- assertCode(content)
- expect(content).toMatch(`props: ['item'],`)
- expect(content).toMatch(`emits: ['a'],`)
- })
-
describe('
+ `)
+ assertCode(content)
+
+ expect(content).toMatch(`console.log('test')`)
+ expect(content).toMatch(`const props = __props;`)
+ expect(content).toMatch(`const emit = __emit;`)
+ expect(content).toMatch(`(function () {})()`)
+ })
+
test('script setup first, named default export', () => {
const { content } = compile(`
+ `)
+ assertCode(content)
+ expect(content).toMatch(`const a = 1;`)
+ expect(content).toMatch(`props: ['item'],`)
+ })
+
+ // #6757
+ test('multi-variable declaration fix #6757 ', () => {
+ const { content } = compile(`
+
+ `)
+ assertCode(content)
+ expect(content).toMatch(`const a = 1;`)
+ expect(content).toMatch(`props: ['item'],`)
+ })
+
+ // #7422
+ test('multi-variable declaration fix #7422', () => {
+ const { content } = compile(`
+
+ `)
+ assertCode(content)
+ expect(content).toMatch(`const a = 0,`)
+ expect(content).toMatch(`b = 0;`)
+ expect(content).toMatch(`props: ['item'],`)
+ })
+
+ test('defineProps/defineEmits in multi-variable declaration (full removal)', () => {
+ const { content } = compile(`
+
+ `)
+ assertCode(content)
+ expect(content).toMatch(`props: ['item'],`)
+ expect(content).toMatch(`emits: ['a'],`)
+ })
+
describe('errors', () => {
test('should error on deep destructure', () => {
expect(() =>
diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts
index 046797cfbe5..cfcc607c72d 100644
--- a/packages/compiler-sfc/src/compileScript.ts
+++ b/packages/compiler-sfc/src/compileScript.ts
@@ -552,7 +552,11 @@ export function compileScript(
(processDefineSlots(ctx, init, decl.id) ||
processDefineModel(ctx, init, decl.id))
- if (isDefineProps || isDefineEmits) {
+ if (
+ isDefineProps &&
+ !ctx.propsDestructureRestId &&
+ ctx.propsDestructureDecl
+ ) {
if (left === 1) {
ctx.s.remove(node.start! + startOffset, node.end! + startOffset)
} else {
@@ -570,6 +574,12 @@ export function compileScript(
ctx.s.remove(start, end)
left--
}
+ } else if (isDefineEmits) {
+ ctx.s.overwrite(
+ startOffset + init.start!,
+ startOffset + init.end!,
+ '__emit'
+ )
} else {
lastNonRemoved = i
}
@@ -781,22 +791,29 @@ export function compileScript(
// inject user assignment of props
// we use a default __props so that template expressions referencing props
// can use it directly
- if (ctx.propsIdentifier) {
- ctx.s.prependLeft(
- startOffset,
- `\nconst ${ctx.propsIdentifier} = __props;\n`
- )
- }
- if (ctx.propsDestructureRestId) {
- ctx.s.prependLeft(
- startOffset,
- `\nconst ${ctx.propsDestructureRestId} = ${ctx.helper(
- `createPropsRestProxy`
- )}(__props, ${JSON.stringify(
- Object.keys(ctx.propsDestructuredBindings)
- )});\n`
- )
+ if (ctx.propsDecl) {
+ if (ctx.propsDestructureRestId) {
+ ctx.s.overwrite(
+ startOffset + ctx.propsCall!.start!,
+ startOffset + ctx.propsCall!.end!,
+ `${ctx.helper(`createPropsRestProxy`)}(__props, ${JSON.stringify(
+ Object.keys(ctx.propsDestructuredBindings)
+ )})`
+ )
+ ctx.s.overwrite(
+ startOffset + ctx.propsDestructureDecl!.start!,
+ startOffset + ctx.propsDestructureDecl!.end!,
+ ctx.propsDestructureRestId
+ )
+ } else if (!ctx.propsDestructureDecl) {
+ ctx.s.overwrite(
+ startOffset + ctx.propsCall!.start!,
+ startOffset + ctx.propsCall!.end!,
+ '__props'
+ )
+ }
}
+
// inject temp variables for async context preservation
if (hasAwait) {
const any = ctx.isTS ? `: any` : ``
@@ -807,10 +824,8 @@ export function compileScript(
ctx.hasDefineExposeCall || !options.inlineTemplate
? [`expose: __expose`]
: []
- if (ctx.emitIdentifier) {
- destructureElements.push(
- ctx.emitIdentifier === `emit` ? `emit` : `emit: ${ctx.emitIdentifier}`
- )
+ if (ctx.emitDecl) {
+ destructureElements.push(`emit: __emit`)
}
if (destructureElements.length) {
args += `, { ${destructureElements.join(', ')} }`
diff --git a/packages/compiler-sfc/src/script/context.ts b/packages/compiler-sfc/src/script/context.ts
index af2dee16568..5fe09d28a42 100644
--- a/packages/compiler-sfc/src/script/context.ts
+++ b/packages/compiler-sfc/src/script/context.ts
@@ -1,4 +1,4 @@
-import { Node, ObjectPattern, Program } from '@babel/types'
+import { CallExpression, Node, ObjectPattern, Program } from '@babel/types'
import { SFCDescriptor } from '../parse'
import { generateCodeFrame } from '@vue/shared'
import { parse as babelParse, ParserPlugin } from '@babel/parser'
@@ -38,7 +38,8 @@ export class ScriptCompileContext {
hasDefineModelCall = false
// defineProps
- propsIdentifier: string | undefined
+ propsCall: CallExpression | undefined
+ propsDecl: Node | undefined
propsRuntimeDecl: Node | undefined
propsTypeDecl: Node | undefined
propsDestructureDecl: ObjectPattern | undefined
@@ -49,7 +50,7 @@ export class ScriptCompileContext {
// defineEmits
emitsRuntimeDecl: Node | undefined
emitsTypeDecl: Node | undefined
- emitIdentifier: string | undefined
+ emitDecl: Node | undefined
// defineModel
modelDecls: Record = {}
diff --git a/packages/compiler-sfc/src/script/defineEmits.ts b/packages/compiler-sfc/src/script/defineEmits.ts
index a50cf91fc4a..02014d1b276 100644
--- a/packages/compiler-sfc/src/script/defineEmits.ts
+++ b/packages/compiler-sfc/src/script/defineEmits.ts
@@ -29,10 +29,7 @@ export function processDefineEmits(
ctx.emitsTypeDecl = node.typeParameters.params[0]
}
- if (declId) {
- ctx.emitIdentifier =
- declId.type === 'Identifier' ? declId.name : ctx.getString(declId)
- }
+ ctx.emitDecl = declId
return true
}
diff --git a/packages/compiler-sfc/src/script/defineProps.ts b/packages/compiler-sfc/src/script/defineProps.ts
index 1ae5a16e3d6..5004e314da1 100644
--- a/packages/compiler-sfc/src/script/defineProps.ts
+++ b/packages/compiler-sfc/src/script/defineProps.ts
@@ -77,15 +77,14 @@ export function processDefineProps(
ctx.propsTypeDecl = node.typeParameters.params[0]
}
- if (declId) {
- // handle props destructure
- if (declId.type === 'ObjectPattern') {
- processPropsDestructure(ctx, declId)
- } else {
- ctx.propsIdentifier = ctx.getString(declId)
- }
+ // handle props destructure
+ if (declId && declId.type === 'ObjectPattern') {
+ processPropsDestructure(ctx, declId)
}
+ ctx.propsCall = node
+ ctx.propsDecl = declId
+
return true
}
@@ -97,31 +96,33 @@ function processWithDefaults(
if (!isCallOf(node, WITH_DEFAULTS)) {
return false
}
- if (processDefineProps(ctx, node.arguments[0], declId)) {
- if (ctx.propsRuntimeDecl) {
- ctx.error(
- `${WITH_DEFAULTS} can only be used with type-based ` +
- `${DEFINE_PROPS} declaration.`,
- node
- )
- }
- if (ctx.propsDestructureDecl) {
- ctx.error(
- `${WITH_DEFAULTS}() is unnecessary when using destructure with ${DEFINE_PROPS}().\n` +
- `Prefer using destructure default values, e.g. const { foo = 1 } = defineProps(...).`,
- node.callee
- )
- }
- ctx.propsRuntimeDefaults = node.arguments[1]
- if (!ctx.propsRuntimeDefaults) {
- ctx.error(`The 2nd argument of ${WITH_DEFAULTS} is required.`, node)
- }
- } else {
+ if (!processDefineProps(ctx, node.arguments[0], declId)) {
ctx.error(
`${WITH_DEFAULTS}' first argument must be a ${DEFINE_PROPS} call.`,
node.arguments[0] || node
)
}
+
+ if (ctx.propsRuntimeDecl) {
+ ctx.error(
+ `${WITH_DEFAULTS} can only be used with type-based ` +
+ `${DEFINE_PROPS} declaration.`,
+ node
+ )
+ }
+ if (ctx.propsDestructureDecl) {
+ ctx.error(
+ `${WITH_DEFAULTS}() is unnecessary when using destructure with ${DEFINE_PROPS}().\n` +
+ `Prefer using destructure default values, e.g. const { foo = 1 } = defineProps(...).`,
+ node.callee
+ )
+ }
+ ctx.propsRuntimeDefaults = node.arguments[1]
+ if (!ctx.propsRuntimeDefaults) {
+ ctx.error(`The 2nd argument of ${WITH_DEFAULTS} is required.`, node)
+ }
+ ctx.propsCall = node
+
return true
}
diff --git a/packages/compiler-sfc/src/script/definePropsDestructure.ts b/packages/compiler-sfc/src/script/definePropsDestructure.ts
index 5965262f3c3..5aa895bc7fe 100644
--- a/packages/compiler-sfc/src/script/definePropsDestructure.ts
+++ b/packages/compiler-sfc/src/script/definePropsDestructure.ts
@@ -28,7 +28,6 @@ export function processPropsDestructure(
declId: ObjectPattern
) {
if (!ctx.options.propsDestructure && !ctx.options.reactivityTransform) {
- ctx.propsIdentifier = ctx.getString(declId)
return
}