fix(paginator): guard getVisibleRange against not-yet-loaded documents

Second member of the 50f56ee guard family: the scroll-anchor tick
(#afterScroll) can run before the iframe document is parsed, throwing
'createTreeWalker' on null body. getVisibleRange now returns null for
that tick and #afterScroll preserves the previous visibility state.
Observed live in the Android app on PalmDOC open.
This commit is contained in:
John O'Keefe committed 2026-10-03 22:35:28 -04:00
1 parent 111898ee0e
commit b7597d6159
2 files changed
+8 -1

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "foliate-js",
"version": "0.5.1",
"version": "0.5.2",
"description": "Render e-books in the browser",
"repository": {
"type": "git",
+7
View File
@@ -92,6 +92,10 @@ const getBoundingClientRect = target => {
}
const getVisibleRange = (doc, start, end, mapRect) => {
// Same teardown race as expand(): a scroll-anchor tick can run
// against a not-yet-parsed iframe document (no body / documentElement
// yet) — return a null range so the caller skips visibility math.
if (!doc || !doc.body || !doc.documentElement) return null
// first get all visible nodes
const acceptNode = node => {
const name = node.localName?.toLowerCase()
@@ -1107,6 +1111,9 @@ export class Paginator extends HTMLElement {
}
#afterScroll(reason) {
const range = this.#getVisibleRange()
// Torn-down/not-yet-loaded document tick — preserve the previous
// visibility state instead of anchoring on a null range.
if (!range) return
this.#lastVisibleRange = range
// don't set new anchor if relocation was to scroll to anchor
if (reason !== 'selection' && reason !== 'navigation' && reason !== 'anchor')