Skip to content

Commit a752178

Browse files
crisbetothePunderWoman
authored andcommitted
fix(core): hydration error in some let declaration setups (angular#57173)
Fixes that we were throwing an assertion error during hydration if a `@let` declaration is used before and immediately inside of a container. Fixes angular#57160. PR Close angular#57173
1 parent 4988451 commit a752178

File tree

2 files changed

+73
-1
lines changed

2 files changed

+73
-1
lines changed

packages/core/src/render3/node_manipulation.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,11 @@ export function getFirstNativeNode(lView: LView, tNode: TNode | null): RNode | n
864864
ngDevMode &&
865865
assertTNodeType(
866866
tNode,
867-
TNodeType.AnyRNode | TNodeType.AnyContainer | TNodeType.Icu | TNodeType.Projection,
867+
TNodeType.AnyRNode |
868+
TNodeType.AnyContainer |
869+
TNodeType.Icu |
870+
TNodeType.Projection |
871+
TNodeType.LetDeclaration,
868872
);
869873

870874
const tNodeType = tNode.type;
@@ -884,6 +888,8 @@ export function getFirstNativeNode(lView: LView, tNode: TNode | null): RNode | n
884888
return unwrapRNode(rNodeOrLContainer);
885889
}
886890
}
891+
} else if (tNodeType & TNodeType.LetDeclaration) {
892+
return getFirstNativeNode(lView, tNode.next);
887893
} else if (tNodeType & TNodeType.Icu) {
888894
let nextRNode = icuContainerIterate(tNode as TIcuContainerNode, lView);
889895
let rNode: RNode | null = nextRNode();

packages/platform-server/test/hydration_spec.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7643,6 +7643,72 @@ describe('platform-server hydration integration', () => {
76437643
verifyClientAndSSRContentsMatch(ssrContents, clientRootNode);
76447644
expect(clientRootNode.innerHTML).toContain(`<inner>${expectedContent}</inner>`);
76457645
});
7646+
7647+
it('should handle let declaration before and directly inside of an embedded view', async () => {
7648+
@Component({
7649+
standalone: true,
7650+
selector: 'app',
7651+
template: `
7652+
@let before = 'before';
7653+
@if (true) {
7654+
@let inside = 'inside';
7655+
{{before}}|{{inside}}
7656+
}
7657+
`,
7658+
})
7659+
class SimpleComponent {}
7660+
7661+
const html = await ssr(SimpleComponent);
7662+
const ssrContents = getAppContents(html);
7663+
7664+
expect(ssrContents).toContain('<app ngh');
7665+
expect(ssrContents).toContain('before|inside');
7666+
7667+
resetTViewsFor(SimpleComponent);
7668+
7669+
const appRef = await renderAndHydrate(doc, html, SimpleComponent);
7670+
const compRef = getComponentRef<SimpleComponent>(appRef);
7671+
appRef.tick();
7672+
7673+
const clientRootNode = compRef.location.nativeElement;
7674+
verifyAllNodesClaimedForHydration(clientRootNode);
7675+
verifyClientAndSSRContentsMatch(ssrContents, clientRootNode);
7676+
expect(clientRootNode.textContent).toContain('before|inside');
7677+
});
7678+
7679+
it('should handle let declaration before, directly inside of and after an embedded view', async () => {
7680+
@Component({
7681+
standalone: true,
7682+
selector: 'app',
7683+
template: `
7684+
@let before = 'before';
7685+
@if (true) {
7686+
@let inside = 'inside';
7687+
{{inside}}
7688+
}
7689+
@let after = 'after';
7690+
{{before}}|{{after}}
7691+
`,
7692+
})
7693+
class SimpleComponent {}
7694+
7695+
const html = await ssr(SimpleComponent);
7696+
const ssrContents = getAppContents(html);
7697+
7698+
expect(ssrContents).toContain('<app ngh');
7699+
expect(ssrContents).toContain('inside <!--container--> before|after');
7700+
7701+
resetTViewsFor(SimpleComponent);
7702+
7703+
const appRef = await renderAndHydrate(doc, html, SimpleComponent);
7704+
const compRef = getComponentRef<SimpleComponent>(appRef);
7705+
appRef.tick();
7706+
7707+
const clientRootNode = compRef.location.nativeElement;
7708+
verifyAllNodesClaimedForHydration(clientRootNode);
7709+
verifyClientAndSSRContentsMatch(ssrContents, clientRootNode);
7710+
expect(clientRootNode.textContent).toContain('inside before|after');
7711+
});
76467712
});
76477713

76487714
describe('Router', () => {

0 commit comments

Comments
 (0)