diff --git a/packages/compiler-core/src/index.ts b/packages/compiler-core/src/index.ts
index 6ed7aa5b897..6a1f8b63b57 100644
--- a/packages/compiler-core/src/index.ts
+++ b/packages/compiler-core/src/index.ts
@@ -43,7 +43,8 @@ export { processIf } from './transforms/vIf'
export { processFor, createForLoopParams } from './transforms/vFor'
export {
transformExpression,
- processExpression
+ processExpression,
+ stringifyExpression
} from './transforms/transformExpression'
export {
buildSlots,
diff --git a/packages/compiler-core/src/transforms/transformExpression.ts b/packages/compiler-core/src/transforms/transformExpression.ts
index e4311ad4f88..43c69559688 100644
--- a/packages/compiler-core/src/transforms/transformExpression.ts
+++ b/packages/compiler-core/src/transforms/transformExpression.ts
@@ -361,7 +361,7 @@ function canPrefix(id: Identifier) {
return true
}
-function stringifyExpression(exp: ExpressionNode | string): string {
+export function stringifyExpression(exp: ExpressionNode | string): string {
if (isString(exp)) {
return exp
} else if (exp.type === NodeTypes.SIMPLE_EXPRESSION) {
diff --git a/packages/compiler-ssr/__tests__/ssrComponent.spec.ts b/packages/compiler-ssr/__tests__/ssrComponent.spec.ts
index 5d5191ffb44..cd21e48cb9a 100644
--- a/packages/compiler-ssr/__tests__/ssrComponent.spec.ts
+++ b/packages/compiler-ssr/__tests__/ssrComponent.spec.ts
@@ -104,6 +104,11 @@ describe('ssr: components', () => {
`)
})
+ test('empty attribute should not produce syntax error', () => {
+ // previously this would produce syntax error `default: _withCtx((, _push, ...)`
+ expect(compile(`foo`).code).not.toMatch(`(,`)
+ })
+
test('named slots', () => {
expect(
compile(`
diff --git a/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts b/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
index df190c768a8..dc8c6a4ae4f 100644
--- a/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
+++ b/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
@@ -36,7 +36,8 @@ import {
CallExpression,
JSChildNode,
RESOLVE_DYNAMIC_COMPONENT,
- TRANSITION
+ TRANSITION,
+ stringifyExpression
} from '@vue/compiler-dom'
import { SSR_RENDER_COMPONENT, SSR_RENDER_VNODE } from '../runtimeHelpers'
import {
@@ -145,8 +146,9 @@ export const ssrTransformComponent: NodeTransform = (node, context) => {
wipMap.set(node, wipEntries)
const buildSSRSlotFn: SlotFnBuilder = (props, children, loc) => {
+ const param0 = (props && stringifyExpression(props)) || `_`
const fn = createFunctionExpression(
- [props || `_`, `_push`, `_parent`, `_scopeId`],
+ [param0, `_push`, `_parent`, `_scopeId`],
undefined, // no return, assign body later
true, // newline
true, // isSlot