aboutsummaryrefslogtreecommitdiffstats
path: root/frontend-vanilla/src/main.ts
diff options
context:
space:
mode:
authorClaude <noreply@anthropic.com>2026-02-17 16:35:56 +0000
committerClaude <noreply@anthropic.com>2026-02-17 16:35:56 +0000
commit90177f1645bf886a2e4f84f4db287ba379f01773 (patch)
tree3f19efc1c79acd3143730b9d677fc2d921e22644 /frontend-vanilla/src/main.ts
parent7f0b9ae0f53f26304d26a8d45191f268821425c8 (diff)
downloadneko-90177f1645bf886a2e4f84f4db287ba379f01773.tar.gz
neko-90177f1645bf886a2e4f84f4db287ba379f01773.tar.bz2
neko-90177f1645bf886a2e4f84f4db287ba379f01773.zip
fix: store sentinel IntersectionObserver in module-level variable to prevent GC
The load-more sentinel observer was assigned to a local `const observer` that fell out of scope after renderItems() returned. Without a persistent JS reference, engines can garbage-collect the observer, silently breaking infinite scroll (no more items loaded on scroll). Fix: assign to the existing module-level `itemObserver` variable, which is already disconnected/replaced at the top of each renderItems() call. Add three regression tests in regression.test.ts that use a class-based IntersectionObserver mock to capture the callback and verify: - sentinel visible → loadMore fires - sentinel visible while loading → loadMore suppressed - hasMore=false → no sentinel rendered, no loadMore https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
Diffstat (limited to 'frontend-vanilla/src/main.ts')
-rw-r--r--frontend-vanilla/src/main.ts6
1 files changed, 3 insertions, 3 deletions
diff --git a/frontend-vanilla/src/main.ts b/frontend-vanilla/src/main.ts
index 5f8056c..bdd0e97 100644
--- a/frontend-vanilla/src/main.ts
+++ b/frontend-vanilla/src/main.ts
@@ -270,15 +270,15 @@ export function renderItems() {
// Use the actual scroll container as IntersectionObserver root
const scrollRoot = document.getElementById('main-content');
- // Setup infinite scroll
+ // Setup infinite scroll — stored in itemObserver so it has a GC root and won't be collected
const sentinel = document.getElementById('load-more-sentinel');
if (sentinel) {
- const observer = new IntersectionObserver((entries) => {
+ itemObserver = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && !store.loading && store.hasMore) {
loadMore();
}
}, { root: scrollRoot, threshold: 0.1 });
- observer.observe(sentinel);
+ itemObserver.observe(sentinel);
}
// Scroll listener for reading items