Skip to content

Commit ccf1a89

Browse files
authoredAug 1, 2024··
fix(runtime): hydrate shadow dom first (#5911)
* fix(runtime): hydrate shadow dom first * prettier * hydrate shadow first * remove any * don't remove vnodes that are about to be hydrated * prettier
1 parent 5dd4f7f commit ccf1a89

File tree

3 files changed

+29
-20
lines changed

3 files changed

+29
-20
lines changed
 

‎src/runtime/client-hydrate.ts

+18-18
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,6 @@ const clientHydrate = (
154154
}
155155
}
156156

157-
// recursively drill down, end to start so we can remove nodes
158-
for (i = node.childNodes.length - 1; i >= 0; i--) {
159-
clientHydrate(
160-
parentVNode,
161-
childRenderNodes,
162-
slotNodes,
163-
shadowRootNodes,
164-
hostElm,
165-
node.childNodes[i] as any,
166-
hostId,
167-
);
168-
}
169-
170157
if (node.shadowRoot) {
171158
// keep drilling down through the shadow root nodes
172159
for (i = node.shadowRoot.childNodes.length - 1; i >= 0; i--) {
@@ -181,6 +168,19 @@ const clientHydrate = (
181168
);
182169
}
183170
}
171+
172+
// recursively drill down, end to start so we can remove nodes
173+
for (i = node.childNodes.length - 1; i >= 0; i--) {
174+
clientHydrate(
175+
parentVNode,
176+
childRenderNodes,
177+
slotNodes,
178+
shadowRootNodes,
179+
hostElm,
180+
node.childNodes[i] as any,
181+
hostId,
182+
);
183+
}
184184
} else if (node.nodeType === NODE_TYPE.CommentNode) {
185185
// `${COMMENT_TYPE}.${hostId}.${nodeId}.${depth}.${index}`
186186
childIdSplt = node.nodeValue.split('.');
@@ -293,14 +293,14 @@ const clientHydrate = (
293293
export const initializeDocumentHydrate = (node: d.RenderNode, orgLocNodes: d.PlatformRuntime['$orgLocNodes$']) => {
294294
if (node.nodeType === NODE_TYPE.ElementNode) {
295295
let i = 0;
296-
for (; i < node.childNodes.length; i++) {
297-
initializeDocumentHydrate(node.childNodes[i] as any, orgLocNodes);
298-
}
299296
if (node.shadowRoot) {
300-
for (i = 0; i < node.shadowRoot.childNodes.length; i++) {
301-
initializeDocumentHydrate(node.shadowRoot.childNodes[i] as any, orgLocNodes);
297+
for (; i < node.shadowRoot.childNodes.length; i++) {
298+
initializeDocumentHydrate(node.shadowRoot.childNodes[i] as d.RenderNode, orgLocNodes);
302299
}
303300
}
301+
for (i = 0; i < node.childNodes.length; i++) {
302+
initializeDocumentHydrate(node.childNodes[i] as d.RenderNode, orgLocNodes);
303+
}
304304
} else if (node.nodeType === NODE_TYPE.CommentNode) {
305305
const childIdSplt = node.nodeValue.split('.');
306306
if (childIdSplt[0] === ORG_LOCATION_ID) {

‎src/runtime/vdom/vdom-render.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,12 @@ export const patch = (oldVNode: d.VNode, newVNode: d.VNode, isInitialRender = fa
704704
}
705705
// add the new vnode children
706706
addVnodes(elm, null, newVNode, newChildren, 0, newChildren.length - 1);
707-
} else if (BUILD.updatable && oldChildren !== null) {
707+
} else if (
708+
// don't do this on initial render as it can cause non-hydrated content to be removed
709+
!isInitialRender &&
710+
BUILD.updatable &&
711+
oldChildren !== null
712+
) {
708713
// no new child vnodes, but there are old child vnodes to remove
709714
removeVnodes(oldChildren, 0, oldChildren.length - 1);
710715
}

‎test/end-to-end/src/declarative-shadow-dom/test.e2e.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ describe('renderToString', () => {
218218
`,
219219
{
220220
serializeShadowRoot: true,
221-
fullDocument: false,
221+
fullDocument: true,
222222
},
223223
);
224224

@@ -255,6 +255,10 @@ describe('renderToString', () => {
255255
expect(html).toContain(
256256
`<car-detail custom-hydrate-flag=\"\" c-id=\"2.4.2.0\" s-id=\"4\"><!--r.4--><section c-id=\"4.0.0.0\"><!--t.4.1.1.0-->2023 VW Beetle</section></car-detail>`,
257257
);
258+
259+
const page = await newE2EPage({ html, url: 'https://stencil.com' });
260+
const cars = await page.findAll('>>>car-detail');
261+
expect(cars.map((car) => car.textContent)).toEqual(['2024 VW Vento', '2023 VW Beetle']);
258262
});
259263

260264
it('calls beforeHydrate and afterHydrate function hooks', async () => {

0 commit comments

Comments
 (0)
Please sign in to comment.