Skip to content

【错误报告】列表页下拉到一定程度后无限转圈,分页数据不再加载(LDS 1.5.35) #385

Description

@cjfbbb

字段 1:你使用的浏览器版本 + 扩展版本号

Cent Browser 5.2.1168.83(内核 Chromium 134.0.6998.136)/ 扩展 1.5.35
(另在 Edge 同版本内核下不出现,见"对比"一节)

字段 2:问题描述

现象

在 linux.do 列表页(如 /latest)向下滚动到一定程度后开始无限转圈,后续分页数据不再渲染;刷新页面后前几页正常,继续下拉又会在相近位置卡住。停用本扩展后立即恢复正常。

复现步骤

  1. 启用 LinuxDo Scripts 1.5.35
  2. 打开 https://linux.do/latest(或任意列表页)
  3. 向下滚动,持续加载下一页(无限滚动)
  4. 滚到大约第 3~5 页时开始一直转圈,新话题不再出现
  5. 停用扩展后重复步骤 2-3 → 正常,可一直滚到底

控制台报错

NotFoundError: Failed to execute 'removeChild' on 'Node':
The node to be removed is not a child of this node.

调用栈指向 Discourse 自身的懒加载渲染块(注意:报错不在扩展代码里):

assets/chunk-d5aq5i5v.digested.js:4:40762   ← 抛出点
→ 经 Vue/Ember 渲染链上抛:
  vue_execute → renderRoots(#app) → invoke → flush → e.progress
  → patchBlockChildren → unmount → handleException

同时伴随一条与渲染无关但同屏出现的消息(供参考):

MESSAGE DISM FAIL: callback /presence/chat/online ... disallowed

分析:为什么本扩展会触发它

  • 本扩展通过 createShadowRootUi 把 Vue UI 挂到 Shadow DOM,宿主元素挂在 document.body(见 entrypoints/content.js)。
  • Discourse 的列表页使用虚拟化渲染(virtual list),会频繁挂载/卸载帖子节点。
  • 一旦本扩展在渲染周期中移动/替换/回收了 Discourse 虚拟列表所持有的节点,Discourse 那段移除逻辑就会拿到一个"父节点已经不是它"的节点而抛 NotFoundError。
  • 该异常沿异步渲染链上抛后会中断后续渲染流程 → 分页数据拿到了但渲染不出来 → 表现为一直转圈(网络面板里 /latest.json?page=N 是成功的,这是"渲染中断"而非"请求失败"的典型特征)。
  • 对照实验:同一台机器、同一网络、同一时间,Edge(未装本扩展)完全正常 → 差异在浏览器侧的扩展行为,而非网络/缓存。

已做过的关键验证(供参考,证明不是网络或缓存问题)

在主世界对 Node.prototype.removeChild / insertBefore 做容错包裹(当 child.parentNode !== this 时不抛错,改为尽力移除或退化为 appendChild),保持本扩展启用:

场景 结果
无容错(当前扩展行为) 一直转圈(复现)
有容错 ✅ 下拉滚动恢复正常,可一直加载
对照:主世界对 removeChild 直接调用(父节点不匹配) THREW:NotFoundError —— 成功复刻了上面的报错

也就是说:只需要"不让这个异常中断渲染链",问题即消失。

建议的修复方向(任选)

  1. 收敛对 Discourse 节点树的直接操作:本扩展挂在 body 上的 Shadow DOM 宿主元素,以及后续对宿主/帖子节点的挂载与回收,建议改为不做破坏性移除(不调用 .remove() / removeChild 移除可能被框架持有的节点),改用隐藏(display:none)或移动到独立容器;回收逻辑加 if (el.parentNode) el.parentNode.removeChild(el) 形式的守卫。
  2. 加一层防御性容错:在扩展的 content script 里(或在主世界注入极小的一段守卫)包裹 Node.prototype.removeChild / insertBefore,父节点不匹配时降级处理而不抛错。实测可完全解决本问题,代价是掩盖真实 DOM 错误(可加开关)。
  3. 排查与虚拟列表的交互时机:确认是否有逻辑在 MutationObserver 回调里移动被 Discourse 虚拟列表回收的节点,或对 #main-outlet / .topic-list 容器内的节点做了重排。

补充说明:崩溃点的 removeChild 调用本身也未校验父节点(该 chunk 内注释写着 "NOT use removeChild to remove the node",但实际仍走了 removeChild),所以根治也需要 Discourse 侧加守卫。本条 issue 主要诉求是:本扩展可否避免触发它,或增加上述容错选项。

环境

项 值
浏览器 Cent Browser 5.2.1168.83(Chromium 134.0.6998.136)
扩展 LinuxDo Scripts 1.5.35(仓库最新 tag 亦为 1.5.35)
系统 Windows 11 build 10.0.26200
网络 系统代理(Clash,127.0.0.1:7897);站点在 Cloudflare 之后
对照浏览器 Microsoft Edge(同机同网络,未装本扩展)→ 正常

用户侧临时绕过(已验证有效)

在浏览器里额外装一个"主世界容错"的最小扩展(world: "MAIN", run_at: document_start,包裹 removeChild/insertBefore)即可,扩展功能不受影响。方案细节见上述"建议的修复方向 2"。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions