Skip to content

Commit cb92511

Browse files
authored
fix(compiler-vapor): don't generate default slot for whitespace when preserved (#13009)
1 parent 6f8ea35 commit cb92511

File tree

4 files changed

+146
-7
lines changed

4 files changed

+146
-7
lines changed

packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,3 +274,68 @@ export function render(_ctx) {
274274
return n6
275275
}"
276276
`;
277+
278+
exports[`compiler: transform slot > with whitespace: 'preserve' > implicit default slot 1`] = `
279+
"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
280+
const t0 = _template(" Header ")
281+
const t1 = _template(" ")
282+
const t2 = _template("<p></p>")
283+
284+
export function render(_ctx) {
285+
const _component_Comp = _resolveComponent("Comp")
286+
const n4 = _createComponentWithFallback(_component_Comp, null, {
287+
"header": () => {
288+
const n0 = t0()
289+
return n0
290+
},
291+
"default": () => {
292+
const n2 = t1()
293+
const n3 = t2()
294+
return [n2, n3]
295+
}
296+
}, true)
297+
return n4
298+
}"
299+
`;
300+
301+
exports[`compiler: transform slot > with whitespace: 'preserve' > named default slot + implicit whitespace content 1`] = `
302+
"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
303+
const t0 = _template(" Header ")
304+
const t1 = _template(" Default ")
305+
306+
export function render(_ctx) {
307+
const _component_Comp = _resolveComponent("Comp")
308+
const n5 = _createComponentWithFallback(_component_Comp, null, {
309+
"header": () => {
310+
const n0 = t0()
311+
return n0
312+
},
313+
"default": () => {
314+
const n3 = t1()
315+
return n3
316+
}
317+
}, true)
318+
return n5
319+
}"
320+
`;
321+
322+
exports[`compiler: transform slot > with whitespace: 'preserve' > should not generate whitespace only default slot 1`] = `
323+
"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
324+
const t0 = _template(" Header ")
325+
const t1 = _template(" Footer ")
326+
327+
export function render(_ctx) {
328+
const _component_Comp = _resolveComponent("Comp")
329+
const n5 = _createComponentWithFallback(_component_Comp, null, {
330+
"header": () => {
331+
const n0 = t0()
332+
return n0
333+
},
334+
"footer": () => {
335+
const n3 = t1()
336+
return n3
337+
}
338+
}, true)
339+
return n5
340+
}"
341+
`;

packages/compiler-vapor/__tests__/transforms/vSlot.spec.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,4 +509,60 @@ describe('compiler: transform slot', () => {
509509
})
510510
})
511511
})
512+
513+
describe(`with whitespace: 'preserve'`, () => {
514+
test('named default slot + implicit whitespace content', () => {
515+
const source = `
516+
<Comp>
517+
<template #header> Header </template>
518+
<template #default> Default </template>
519+
</Comp>
520+
`
521+
const { code } = compileWithSlots(source, {
522+
whitespace: 'preserve',
523+
})
524+
525+
expect(
526+
`Extraneous children found when component already has explicitly named default slot.`,
527+
).not.toHaveBeenWarned()
528+
expect(code).toMatchSnapshot()
529+
})
530+
531+
test('implicit default slot', () => {
532+
const source = `
533+
<Comp>
534+
<template #header> Header </template>
535+
<p/>
536+
</Comp>
537+
`
538+
const { code } = compileWithSlots(source, {
539+
whitespace: 'preserve',
540+
})
541+
542+
expect(
543+
`Extraneous children found when component already has explicitly named default slot.`,
544+
).not.toHaveBeenWarned()
545+
expect(code).toMatchSnapshot()
546+
})
547+
548+
test('should not generate whitespace only default slot', () => {
549+
const source = `
550+
<Comp>
551+
<template #header> Header </template>
552+
<template #footer> Footer </template>
553+
</Comp>
554+
`
555+
const { code, ir } = compileWithSlots(source, {
556+
whitespace: 'preserve',
557+
})
558+
559+
const slots = (ir.block.dynamic.children[0].operation as any).slots[0]
560+
.slots
561+
// should be: header, footer (no default)
562+
expect(Object.keys(slots).length).toBe(2)
563+
expect(!!slots['default']).toBe(false)
564+
565+
expect(code).toMatchSnapshot()
566+
})
567+
})
512568
})

packages/compiler-vapor/src/transforms/transformText.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ const seen = new WeakMap<
2323
WeakSet<TemplateChildNode | RootNode>
2424
>()
2525

26+
export function markNonTemplate(
27+
node: TemplateChildNode,
28+
context: TransformContext,
29+
): void {
30+
seen.get(context.root)!.add(node)
31+
}
32+
2633
export const transformText: NodeTransform = (node, context) => {
2734
if (!seen.has(context.root)) seen.set(context.root, new WeakSet())
2835
if (seen.get(context.root)!.has(node)) {
@@ -68,7 +75,7 @@ export const transformText: NodeTransform = (node, context) => {
6875
prev.type === NodeTypes.TEXT
6976
) {
7077
// mark leading text node for skipping
71-
seen.get(context.root)!.add(prev)
78+
markNonTemplate(prev, context)
7279
}
7380
}
7481
}
@@ -143,7 +150,7 @@ function processTextContainer(
143150
}
144151

145152
function createTextLikeExpression(node: TextLike, context: TransformContext) {
146-
seen.get(context.root)!.add(node)
153+
markNonTemplate(node, context)
147154
if (node.type === NodeTypes.TEXT) {
148155
return createSimpleExpression(node.content, true, node.loc)
149156
} else {

packages/compiler-vapor/src/transforms/vSlot.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
type VaporDirectiveNode,
2525
} from '../ir'
2626
import { findDir, resolveExpression } from '../utils'
27+
import { markNonTemplate } from './transformText'
2728

2829
export const transformVSlot: NodeTransform = (node, context) => {
2930
if (node.type !== NodeTypes.ELEMENT) return
@@ -66,11 +67,21 @@ function transformComponentSlot(
6667
) {
6768
const { children } = node
6869
const arg = dir && dir.arg
69-
const nonSlotTemplateChildren = children.filter(
70-
n =>
71-
isNonWhitespaceContent(node) &&
72-
!(n.type === NodeTypes.ELEMENT && n.props.some(isVSlot)),
73-
)
70+
71+
// whitespace: 'preserve'
72+
const emptyTextNodes: TemplateChildNode[] = []
73+
const nonSlotTemplateChildren = children.filter(n => {
74+
if (isNonWhitespaceContent(n)) {
75+
return !(n.type === NodeTypes.ELEMENT && n.props.some(isVSlot))
76+
} else {
77+
emptyTextNodes.push(n)
78+
}
79+
})
80+
if (!nonSlotTemplateChildren.length) {
81+
emptyTextNodes.forEach(n => {
82+
markNonTemplate(n, context)
83+
})
84+
}
7485

7586
const [block, onExit] = createSlotBlock(node, dir, context)
7687

0 commit comments

Comments
 (0)