diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap index 0c8e061f9ef..7c8837dd6b3 100644 --- a/packages/compiler-core/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap +++ b/packages/compiler-core/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap @@ -215,6 +215,34 @@ return function render(_ctx, _cache) { }" `; +exports[`compiler: transform component slots > template named v-if/else and whitespace preserve 1`] = ` +"const { toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, resolveComponent: _resolveComponent, withCtx: _withCtx, createSlots: _createSlots, openBlock: _openBlock, createBlock: _createBlock } = Vue + +return function render(_ctx, _cache) { + const _component_Comp = _resolveComponent(\\"Comp\\") + + return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 2 /* DYNAMIC */ }, [ + true + ? { + name: \\"one\\", + fn: _withCtx(() => [ + _createTextVNode(_toDisplayString(_ctx.foo) + _toDisplayString(_ctx.bar), 1 /* TEXT */) + ]), + key: \\"0\\" + } + : true + ? { + name: \\"one\\", + fn: _withCtx(() => [ + _createTextVNode(_toDisplayString(_ctx.foo) + _toDisplayString(_ctx.bar), 1 /* TEXT */) + ]), + key: \\"1\\" + } + : undefined + ]), 1024 /* DYNAMIC_SLOTS */)) +}" +`; + exports[`compiler: transform component slots > with whitespace: 'preserve' > implicit default slot 1`] = ` "const { createElementVNode: _createElementVNode, resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue diff --git a/packages/compiler-core/__tests__/transforms/vSlot.spec.ts b/packages/compiler-core/__tests__/transforms/vSlot.spec.ts index bb3d9d2cfa3..f9cc50dd6cf 100644 --- a/packages/compiler-core/__tests__/transforms/vSlot.spec.ts +++ b/packages/compiler-core/__tests__/transforms/vSlot.spec.ts @@ -28,8 +28,14 @@ import { createObjectMatcher, genFlagText } from '../testUtils' import { PatchFlags } from '@vue/shared' import { transformFor } from '../../src/transforms/vFor' import { transformIf } from '../../src/transforms/vIf' +import { transformText } from '../../src/transforms/transformText' -function parseWithSlots(template: string, options: CompilerOptions = {}) { +function parseWithSlots( + template: string, + options: CompilerOptions & { + appendNodeTransforms?: CompilerOptions['nodeTransforms'] + } = {} +) { const ast = parse(template, { whitespace: options.whitespace }) @@ -42,7 +48,8 @@ function parseWithSlots(template: string, options: CompilerOptions = {}) { : []), transformSlotOutlet, transformElement, - trackSlotScopes + trackSlotScopes, + ...(options.appendNodeTransforms ?? []) ], directiveTransforms: { on: transformOn, @@ -234,6 +241,27 @@ describe('compiler: transform component slots', () => { expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot() }) + // #6063 should not throw error + test('template named v-if/else and whitespace preserve', () => { + const { root } = parseWithSlots( + ` + + + `, + { + whitespace: 'preserve', + prefixIdentifiers: true, + appendNodeTransforms: [transformText] + } + ) + + expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot() + }) + test('on component dynamically named slot', () => { const { root, slots } = parseWithSlots( `{{ foo }}{{ bar }}`, diff --git a/packages/compiler-core/src/transforms/vSlot.ts b/packages/compiler-core/src/transforms/vSlot.ts index c4416dd45f7..ce71c8ff148 100644 --- a/packages/compiler-core/src/transforms/vSlot.ts +++ b/packages/compiler-core/src/transforms/vSlot.ts @@ -223,6 +223,13 @@ export function buildSlots( let prev while (j--) { prev = children[j] + if ( + prev.type === NodeTypes.TEXT_CALL && + prev.content.type === NodeTypes.TEXT && + prev.content.content === ' ' + ) { + continue + } if (prev.type !== NodeTypes.COMMENT) { break }