From 3fafb43698691f37fab6620e1f19de594c10fbe1 Mon Sep 17 00:00:00 2001 From: arturovt Date: Thu, 4 Dec 2025 19:00:20 +0200 Subject: [PATCH] fix(cdk/scrolling): handle null document.body in ViewportRuler We've been encountering runtime errors in our production monitoring system: `TypeError: Cannot read properties of null (reading 'scrollTop')` The error originates from `ViewportRuler.getViewportScrollPosition` when accessing `document.body.scrollTop` and `document.body.scrollLeft`. Creating a minimal reproduction is impractical, as the issue occurs during edge cases in page navigation/unload cycles in a large application. According to the WHATWG HTML specification, `document.body` can be `null` when the document element is not `` or has no ``/`` child element. This typically occurs during page navigation or document unload when the DOM structure is being torn down. Spec: https://html.spec.whatwg.org/multipage/dom.html#dom-document-body TypeScript's `lib.dom.d.ts` incorrectly types `document.body` as non-nullable `HTMLElement`, which masks this issue at compile time but allows the runtime error to occur. Related TypeScript issues: - https://github.com/microsoft/TypeScript/issues/50078 (documentElement nullability) - https://github.com/microsoft/TypeScript/issues/22868 (body type issue) Added optional chaining (`?.`) when accessing `document.body.scrollTop` and `document.body.scrollLeft` to safely handle the null case. Note: This PR focuses on fixing the immediate issue in `ViewportRuler`. If accepted, similar patterns elsewhere in the codebase can be addressed in follow-up PRs. --- src/cdk/scrolling/viewport-ruler.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/cdk/scrolling/viewport-ruler.ts b/src/cdk/scrolling/viewport-ruler.ts index 66ea77dd9f79..47eb3bdc4f68 100644 --- a/src/cdk/scrolling/viewport-ruler.ts +++ b/src/cdk/scrolling/viewport-ruler.ts @@ -125,14 +125,17 @@ export class ViewportRuler implements OnDestroy { const top = -documentRect.top || - document.body.scrollTop || + // `document.body` can be `null` per WHATWG spec when document element is not `` + // or has no body/frameset child: https://html.spec.whatwg.org/multipage/dom.html#dom-document-body + // Note: TypeScript incorrectly types this as non-nullable, but it can be `null` in practice. + document.body?.scrollTop || window.scrollY || documentElement.scrollTop || 0; const left = -documentRect.left || - document.body.scrollLeft || + document.body?.scrollLeft || window.scrollX || documentElement.scrollLeft || 0;