Skip to content

Commit c354b27

Browse files
committed
test: add hydration test, fix unrendering styles
1 parent 1642679 commit c354b27

File tree

20 files changed

+195
-12
lines changed

20 files changed

+195
-12
lines changed

packages/@lwc/engine-dom/src/renderer.ts

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ const supportsMutableAdoptedStyleSheets =
4444
const styleElements: { [content: string]: HTMLStyleElement } = create(null);
4545
const styleSheets: { [content: string]: CSSStyleSheet } = create(null);
4646
const shadowRootsToStyleSheets = new WeakMap<ShadowRoot, { [content: string]: HTMLStyleElement }>();
47-
const stylesToUsageCount = new WeakMap<HTMLStyleElement | CSSStyleSheet, number>();
47+
const stylesToUsageCount = new WeakMap<
48+
HTMLStyleElement | CSSStyleSheet,
49+
WeakMap<ShadowRoot | Document, number>
50+
>();
4851

4952
export let getCustomElement: any;
5053
export let defineCustomElement: any;
@@ -73,16 +76,32 @@ function isCustomElementRegistryAvailable() {
7376
}
7477
}
7578

76-
function incrementOrDecrementUsageCount(elm: HTMLStyleElement | CSSStyleSheet, delta: number) {
77-
let count = stylesToUsageCount.get(elm);
79+
function incrementOrDecrementUsageCount(
80+
style: HTMLStyleElement | CSSStyleSheet,
81+
root: ShadowRoot | Document,
82+
delta: number
83+
) {
84+
let rootsToCounts = stylesToUsageCount.get(style);
85+
if (isUndefined(rootsToCounts)) {
86+
rootsToCounts = new WeakMap();
87+
stylesToUsageCount.set(style, rootsToCounts);
88+
}
89+
let count = rootsToCounts.get(root);
7890
if (isUndefined(count)) {
7991
count = 0;
8092
}
8193
count += delta;
82-
stylesToUsageCount.set(elm, count);
94+
rootsToCounts.set(root, count);
8395
return count;
8496
}
8597

98+
function incrementOrDecrementGlobalUsageCount(
99+
elm: HTMLStyleElement | CSSStyleSheet,
100+
delta: number
101+
) {
102+
return incrementOrDecrementUsageCount(elm, document, delta);
103+
}
104+
86105
function insertConstructableStyleSheet(content: string, target: ShadowRoot) {
87106
// It's important for CSSStyleSheets to be unique based on their content, so that
88107
// `shadowRoot.adoptedStyleSheets.includes(sheet)` works.
@@ -92,7 +111,7 @@ function insertConstructableStyleSheet(content: string, target: ShadowRoot) {
92111
styleSheet.replaceSync(content);
93112
styleSheets[content] = styleSheet;
94113
}
95-
incrementOrDecrementUsageCount(styleSheet, 1);
114+
incrementOrDecrementUsageCount(styleSheet, target, 1);
96115
const { adoptedStyleSheets } = target;
97116
if (!adoptedStyleSheets.includes(styleSheet)) {
98117
if (supportsMutableAdoptedStyleSheets) {
@@ -111,7 +130,7 @@ function removeConstructableStyleSheet(content: string, target: ShadowRoot) {
111130
if (isUndefined(styleSheet)) {
112131
return;
113132
}
114-
const count = incrementOrDecrementUsageCount(styleSheet, -1);
133+
const count = incrementOrDecrementUsageCount(styleSheet, target, -1);
115134
if (count === 0) {
116135
const { adoptedStyleSheets } = target;
117136
if (adoptedStyleSheets.includes(styleSheet)) {
@@ -133,7 +152,7 @@ function insertStyleElement(content: string, target: ShadowRoot) {
133152
}
134153
const existingElement = sheets![content];
135154
if (!isUndefined(existingElement)) {
136-
incrementOrDecrementUsageCount(existingElement, 1);
155+
incrementOrDecrementUsageCount(existingElement, target, 1);
137156
return;
138157
}
139158

@@ -150,7 +169,7 @@ function insertStyleElement(content: string, target: ShadowRoot) {
150169
}
151170
sheets![content] = elm;
152171
target.appendChild(elm);
153-
incrementOrDecrementUsageCount(elm, 1);
172+
incrementOrDecrementUsageCount(elm, target, 1);
154173
}
155174

156175
function removeStyleElement(content: string, target: ShadowRoot) {
@@ -162,7 +181,7 @@ function removeStyleElement(content: string, target: ShadowRoot) {
162181
if (isUndefined(elm)) {
163182
return;
164183
}
165-
const count = incrementOrDecrementUsageCount(elm, -1);
184+
const count = incrementOrDecrementUsageCount(elm, target, -1);
166185
if (count === 0) {
167186
if (elm.parentNode === target) {
168187
target.removeChild(elm);
@@ -404,7 +423,7 @@ export function isConnected(node: Node): boolean {
404423
export function insertGlobalStylesheet(content: string): void {
405424
const existingElement = globalStylesheets[content];
406425
if (!isUndefined(existingElement)) {
407-
incrementOrDecrementUsageCount(existingElement, 1);
426+
incrementOrDecrementGlobalUsageCount(existingElement, 1);
408427
return;
409428
}
410429

@@ -414,15 +433,15 @@ export function insertGlobalStylesheet(content: string): void {
414433

415434
globalStylesheets[content] = elm;
416435
globalStylesheetsParentElement.appendChild(elm);
417-
incrementOrDecrementUsageCount(elm, 1);
436+
incrementOrDecrementGlobalUsageCount(elm, 1);
418437
}
419438

420439
export function removeGlobalStylesheet(content: string): void {
421440
const elm = globalStylesheets[content];
422441
if (isUndefined(elm)) {
423442
return;
424443
}
425-
const count = incrementOrDecrementUsageCount(elm, -1);
444+
const count = incrementOrDecrementGlobalUsageCount(elm, -1);
426445
if (count === 0) {
427446
if (elm.parentNode === globalStylesheetsParentElement) {
428447
globalStylesheetsParentElement.removeChild(elm);
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
const parentTags = [
2+
'x-light-parent-light-child',
3+
'x-light-parent-shadow-child',
4+
'x-shadow-parent-light-child',
5+
];
6+
7+
export default {
8+
test(rootElement) {
9+
let promise = Promise.resolve();
10+
for (const parentTag of parentTags) {
11+
promise = promise.then(() => {
12+
const parent = rootElement.querySelector(parentTag);
13+
const child = (parent.shadowRoot || parent).querySelector('x-light,x-shadow');
14+
15+
function getDivColor() {
16+
return getComputedStyle((child.shadowRoot || child).querySelector('div')).color;
17+
}
18+
19+
expect(getDivColor()).toEqual('rgb(255, 0, 0)');
20+
child.next();
21+
return Promise.resolve()
22+
.then(() => {
23+
expect(getDivColor()).toEqual('rgb(0, 0, 255)');
24+
child.next();
25+
})
26+
.then(() => {
27+
expect(getDivColor()).toEqual('rgb(255, 0, 0)');
28+
child.next();
29+
})
30+
.then(() => {
31+
expect(getDivColor()).toEqual('rgb(0, 0, 255)');
32+
child.next();
33+
})
34+
.then(() => {
35+
expect(getDivColor()).toEqual('rgb(255, 0, 0)');
36+
});
37+
});
38+
}
39+
return promise;
40+
},
41+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
div {
2+
color: red;
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<template lwc:render-mode="light">
2+
<div>a</div>
3+
</template>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
div {
2+
color: blue;
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<template lwc:render-mode="light">
2+
<div>b</div>
3+
</template>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { LightningElement, api } from 'lwc';
2+
import A from './a.html';
3+
import B from './b.html';
4+
5+
export default class extends LightningElement {
6+
static renderMode = 'light';
7+
current = A;
8+
9+
@api
10+
next() {
11+
this.current = this.current === A ? B : A;
12+
}
13+
14+
render() {
15+
return this.current;
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<template lwc:render-mode="light">
2+
<template for:each={items} for:item="item">
3+
<x-light key={item}></x-light>
4+
</template>
5+
</template>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { LightningElement, api, track } from 'lwc';
2+
3+
export default class extends LightningElement {
4+
static renderMode = 'light';
5+
@track items = [0];
6+
7+
@api add() {
8+
this.items.push(this.items.length);
9+
}
10+
11+
@api remove() {
12+
this.items.pop();
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<template lwc:render-mode="light">
2+
<template for:each={items} for:item="item">
3+
<x-shadow key={item}></x-shadow>
4+
</template>
5+
</template>

0 commit comments

Comments
 (0)