-
Notifications
You must be signed in to change notification settings - Fork 439
Expand file tree
/
Copy pathslot.ts
More file actions
94 lines (84 loc) · 4.13 KB
/
slot.ts
File metadata and controls
94 lines (84 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
* Copyright (c) 2024, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
import { is, builders as b } from 'estree-toolkit';
import { esTemplateWithYield } from '../../estemplate';
import { irChildrenToEs } from '../ir-to-es';
import { bAttributeValue, getScopedExpression } from '../shared';
import { isNullableOf } from '../../estree/validators';
import { Element } from './element';
import type { Slot as IrSlot } from '@lwc/template-compiler';
import type {
Statement as EsStatement,
IfStatement as EsIfStatement,
Expression as EsExpression,
} from 'estree';
import type { Transformer } from '../types';
const bConditionalSlot = esTemplateWithYield`
if (isLightDom) {
const isScopedSlot = ${/* isScopedSlot */ is.literal};
const isSlotted = ${/* isSlotted */ is.literal};
const slotName = ${/* slotName */ is.expression};
const lightGenerators = lightSlottedContent?.[slotName ?? ""];
const scopedGenerators = scopedSlottedContent?.[slotName ?? ""];
const mismatchedSlots = isScopedSlot ? lightGenerators : scopedGenerators;
const generators = isScopedSlot ? scopedGenerators : lightGenerators;
// start bookend HTML comment for light DOM slot vfragment
if (!isSlotted) {
yield '<!---->';
// If there is slot data, scoped slot factory has its own vfragment hence its own bookend
if (isScopedSlot && generators) {
yield '<!---->';
}
}
if (generators) {
for (let i = 0; i < generators.length; i++) {
yield* generators[i](contextfulParent, ${/* scoped slot data */ isNullableOf(is.expression)});
// Scoped slotted data is separated by bookends. Final bookends are added outside of the loop below.
if (isScopedSlot && i < generators.length - 1) {
yield '<!---->';
yield '<!---->';
}
}
/*
If there were mismatched slots, do not fallback to the default. This is required for parity with
engine-core which resets children to an empty array when there are children (mismatched or not).
Because the child nodes are reset, the default slotted content is not rendered in the mismatched slot case.
See https://github.com/salesforce/lwc/blob/master/packages/%40lwc/engine-core/src/framework/api.ts#L238
*/
} else if (!mismatchedSlots) {
// If we're in this else block, then the generator _must_ have yielded
// something. It's impossible for a slottedContent["foo"] to exist
// without the generator yielding at least a text node / element.
// FIXME: how does this work with comments and lwc:preserve-comments?
// TODO: default/fallback slot content
${/* slot fallback content */ is.statement}
}
// end bookend HTML comment for light DOM slot vfragment
if (!isSlotted) {
yield '<!---->';
// If there is slot data, scoped slot factory has its own vfragment hence its own bookend
if (isScopedSlot && generators) {
yield '<!---->';
}
}
} else {
${/* slot element AST */ is.statement}
}
`<EsIfStatement>;
export const Slot: Transformer<IrSlot> = function Slot(node, ctx): EsStatement[] {
const slotBindDirective = node.directives.find((dir) => dir.name === 'SlotBind');
const slotBound = slotBindDirective?.value
? getScopedExpression(slotBindDirective.value as EsExpression, ctx)
: null;
const slotName = bAttributeValue(node, 'name');
// FIXME: avoid serializing the slot's children twice
const slotAst = Element(node, ctx);
const slotChildren = irChildrenToEs(node.children, ctx);
const isScopedSlot = b.literal(Boolean(slotBound));
const isSlotted = b.literal(Boolean(ctx.isSlotted));
return [bConditionalSlot(isScopedSlot, isSlotted, slotName, slotBound, slotChildren, slotAst)];
};