Skip to content

Commit efa0d4f

Browse files
authored
fix(cdk/scrolling): handle null document.body in ViewportRuler (#32477)
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 `<html>` or has no `<body>`/`<frameset>` 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: - microsoft/TypeScript#50078 (documentElement nullability) - microsoft/TypeScript#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.
1 parent c62c64f commit efa0d4f

1 file changed

Lines changed: 5 additions & 2 deletions

File tree

src/cdk/scrolling/viewport-ruler.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,17 @@ export class ViewportRuler implements OnDestroy {
125125

126126
const top =
127127
-documentRect.top ||
128-
document.body.scrollTop ||
128+
// `document.body` can be `null` per WHATWG spec when document element is not `<html>`
129+
// or has no body/frameset child: https://html.spec.whatwg.org/multipage/dom.html#dom-document-body
130+
// Note: TypeScript incorrectly types this as non-nullable, but it can be `null` in practice.
131+
document.body?.scrollTop ||
129132
window.scrollY ||
130133
documentElement.scrollTop ||
131134
0;
132135

133136
const left =
134137
-documentRect.left ||
135-
document.body.scrollLeft ||
138+
document.body?.scrollLeft ||
136139
window.scrollX ||
137140
documentElement.scrollLeft ||
138141
0;

0 commit comments

Comments
 (0)