Skip to content

fix(engine-dom): sel 路径 innerHTML 查询时物化解析代理,修 nano widget 模板注册表 null 簇 - #131

Merged
leizongmin merged 3 commits into
mainfrom
t8r4-npd314-template-registry
Oct 10, 2026
Merged

leizongmin merged 3 commits into
mainfrom
t8r4-npd314-template-registry

Conversation

@leizongmin

@leizongmin leizongmin commented Oct 10, 2026 •

Copy link
Copy Markdown
Owner

fix(engine-dom): sel 路径 innerHTML 查询时物化解析代理,修 nano widget 模板注册表 null 簇

问题

t8r(PR #130)修通 detached 容器 innerHTML 产物物化后,bilibili 视频页 nano 播放器 widget 安装链推进到 npd.314.700a18c2.js(此前未到达的 chunk),console 报 4 条同形态错误:Cannot read properties of null (reading 'style'/'ownerDocument'/'classList')——widget 模板元素注册表 this.template.info/online 等成员为 null(构造时按选择器集查询 miss),resize/hideDm/renderOnlineCount 消费崩,players=0。

与 t8r 修复簇(npd.586/911)的差异正是容器域:t8r 是 detached createElement 容器(handle 路径),本簇是树内 sendBar 元素(sel 路径)。

根因

树内容器 innerHTML 注入后,host 侧 apply(多进程 dom_html 换代)异步;立即相对查询 sendBar.querySelector('.bpx-video-info') 走 host 快照 miss → null。R322 host-miss 兜底只扫桶 added 的 handle 子树(!__zwHandle 即跳过),innerHTML sel 路径的产物是 _zwMEl 解析代理(无 handle)——查询面完全不可见。真浏览器 spec innerHTML 同步替换子节点、后续查询立即可见(HTML Standard §dom-innerhtml)。

行为面三角化(本地 V8Sandbox 探针):同链 sel 域查询 → null、detached handle 域查询 → wrapper(t8r 修复生效),假设 a(注入缺元素)/b(选择器面差异)均排除,时序假设定谳。

修复(3 文件,最小通用)

第一版方案(setter 侧物化:顶层元素子物化并替换 _ihAdded)引入 3 个 lib 回归(slice13 apply 后双计 + t7 两个 host-visible 序列化偏差),否决。定案为查询时物化——查询可见性由查询面承担,setter/apply 记账面零扰动:

  • js_dom_shim/part04.js(R322 host-miss 兜底臂扩扫):桶 added 的解析顶层代理(R304 挂父槽、无 handle 无 sel、parentSel 匹配容器)经既有 _matchCompoundOf 匹配,命中现场 _wcRebuildAsHandle(t8r 重建器)物化为 detached 真 handle 树(全接口),原位替换桶成员/全局 pending 表/addedSet/by-id 索引,写 sel 域父反链(overlay/childNodes 融合与查询同一 wrapper,R309 identity 双源教训),打 _zwMatParsed 标记。物化失败回退代理原样(可见性保持既有 R3254-K3 代理匹配语义)。
  • js_dom_shim/part05.js(K3 apply 代际清除扩展):__zw_apply_generation_bump 的解析补偿定点清除加 _zwMatParsed wrapper 臂——apply 后快照已含该子,桶内 wrapper + 父反链残留会让 overlay 重复并入(vue_mount_lands 双份 <p class="msg"> 同型);清除时桶定位走父反链(物化 wrapper 无槽),反链与标记同批清。与切片 C 解析补偿清除同构。
  • setter 记账面(mutation 队列 addedNodes、CE attach、_mo_notify 桶展平)保持解析代理原样零变化。

已 upgrade 的自定义元素代理不物化——createElement 会二次 ctor(t8r N1 查询面变体);经 _ceRunCtor 既有的 prototype 印记(Object.getPrototypeOf(proxy) === ctor.prototype)判定后按代理返回(原型已挂,instanceof 语义成立)。

返修(双审查统一返修轮)

  • noWire 豁免(审查② F1,blocking):R97 fragment 视图/createContextualFragment 形态的 noWire 解析子从未 wire 进 host 快照,物化打标会被 K3 在 apply 代际边界作废而整体消失(审查探针实证 base post:1 → 修复初版 post:0)。匹配命中按代理返回(可见性与代理匹配面一致),不物化不打标——与 K3 slice-C 旧臂/t8i 豁免同源语义。
  • CE 子树印记检测(审查② F2,blocking):setter 期 __zwCeAttachForAdded 已递归 upgrade 全子树,物化根会经 createElement 对已 upgrade 的 CE 后代重复 ctor(审查探针实证 ctor 1→2)。物化前展平代理子树逐元素反查 registry + prototype 印记,根或任一后代已 upgrade 即整条目回退代理语义(ctor 保真优先)。
  • K3 作废臂钉测(审查① blocking):扩扫臂的 apply 代际清除半区原无测试触达(审查变异实证禁用后全库零护栏)。补 host apply 序列钉(innerHTML → 查询物化 → apply+bump → re-register → 断言无重复并入),红态变异实证禁用后 3≠2。
  • 写前校验(审查② F6,nit 顺带):物化(CE ctor 可同步执行页面代码)后恢复执行时校验桶槽未被重入改动,防按物化前索引写腐化无关条目。
  • 负控制断言(审查① nit):主钉补不匹配选择器 null 护栏(防过匹配)。

不引入新机制:重建器、compound 匹配、父反链、R304 槽、K3 定点清除、noWire 豁免、prototype 印记均为既有设施的最小接线。

已知限制(如实披露)

  • 物化 wrapper 是 detached 新建 handle,与 host apply 后元素 identity 分叉(apply 后查询走 host 快照命中 sel proxy);对查询产物的样式/属性写不穿透渲染。本切片消除的是「查询 null + .style/.ownerDocument/.classList 消费崩」面;identity 缝合与写穿透对齐记入问题池(t8r-2 同域)。
  • querySelectorAll 成员不物化:qsa 返回的解析代理仍是接口缺失面(框架若以 qsa 建注册表消费 .style 仍会 TypeError),且与单数查询产物对同元素双 identity——出口物化面转问题池(t8r-3 同域)。
  • 子树含已 upgrade CE(含匹配根自身)时按代理返回:查询产物非 null 但 .style 为 undefined——ctor 保真优先于接口完整性的取舍(createElement 无法对已 upgrade 元素跳过 ctor);普通元素(真站 npd.314 全簇)不受影响。
  • globalThis named access 与 MutationObserver addedNodes 持解析代理,与查询产物 wrapper 双 identity(t8r-2 同域既有面)。
  • 物化 wrapper 在 apply 前被移入 handle 域父的触发链上会被 K3 作废(by-id 回落丢失,registry 可见性保留)——低频窗口,记录不修。
  • 深层直查(跳过顶层先查其祖先)暂不经本臂物化——真站注册表查询全是一层相对查询(sendBar.querySelector),顶层代理匹配即覆盖全簇。

验证

  • 红→绿钉测(js_dom_bridge_tests/part18.rs 新增 3 测):主钉复刻真站链(树内容器 innerHTML → 立即相对查询 → 全接口断言 → 相对深查 → querySelectorAll → childNodes/firstChild → parentNode 反链 → style 写读回 → 第二顶层子结构保真 → 负控制 .nope=null),断言 info:wrapper|online:ok|qsa:ok|fc:ok|cc:ok|parent:ok|styleWrite:ok|sib:ok|nope:null;变体钉覆盖纯文本零回归/混合 markup+文本顶层/清空重注/sel 域 CE ctor 恒 1(text:ok|mix:ok|reIh:ok|ctor:1|isInst:ok);返修钉覆盖 K3 作废(host apply 序列)/noWire 豁免/CE 后代单 ctor 三臂(ceAfterSet:1|ceHit:ok|ceAfterQ:1 + nwPre:ok|nwMat:proxy|nwPost:ok|nwFc:yes + apply 后 2 子内容正确)。红态变异实证:禁用扩扫臂 → 主钉 info:null|…|styleWrite:throw:TypeError|sib:bad(精确命中 npd.314 注册表 null 消费崩形态,护栏段红态绿不误报)+ 变体钉 mix:bad|reIh:bad|isInst:bad;禁用 K3 作废臂 → 返修钉 3≠2(物化 wrapper 残留重复并入);禁用 noWire 豁免 → nwMat:wrapper|nwPost:lost|nwFc:null(与审查探针读数逐字符一致);禁用 CE 检测 → ceAfterQ:2(与审查探针一致)。
  • 回归守卫:第一版引入的 3 个失败测试(slice13 apply 代际 removed 补偿 + t7 两个 host-visible)在定案下全部恢复绿——setter 记账面零扰动的直接证据。
  • zero-engine lib 全量:2965 passed / 0 failed(2962 基线 + 3 新钉;RUST_MIN_STACK=33554432)。
  • WPT dom 套全量对照:首轮 55,085 Pass / 198 Fail / 16 Timeout,与 t8r 返修轮基线(55,084P/198F/17T)对照 Fail 集合 diff 零差异;唯一差异为 dom/events/Event-dispatch-click.html 基线整文件 Timeout → 本轮跑完且可见 subtest Pass(文件级超时消失,方向与查询可见性修复一致的时间边界正向翻转)。返修轮 55,085P/198F/16T 与首轮逐数一致(Fail/Pass 集合 diff 均空)——零实质退化。
  • fmt CLEAN + clippy 双腿(默认 v8 + quickjs no-default)-D warnings 全绿。

截图

无适用画面:本修复改的是 DOM 查询可见性语义(异步 apply 窗口内的同步查询),非视觉呈现面;验证经 V8Sandbox 行为钉测采集,无 GUI 窗口可截。真站挂载状态证据以 headless 探针 census 序列化文本为准(集成验收轮)。

测试计划

  • cargo test -p zero-engine(lib 全量 2965P/0F)
  • WPT dom 套全量对照(与基线集合等价,零回归)
  • cargo fmt -p zero-engine -- --check / cargo clippy -p zero-engine --all-targets -- -D warnings(默认 + quickjs 双腿)
  • make test 全量

🤖 Generated with Claude Code


Note

Medium Risk
Touches core DOM query/overlay timing around innerHTML and apply-generation boundaries; behavior is intricate but scoped to pending-query materialization with new regression tests.

Overview
Fixes in-tree innerHTML on selector-backed containers where immediate querySelector returned null before async host apply—matching spec synchronous child replacement (Bilibili nano widget template registry null cluster).

Query-time materialization extends the R322 host-miss fallback: pending parsed top-level proxies (no handle) that compound-match are rebuilt via _wcRebuildAsHandle, swapped into pending buckets/global indexes, parent-linked, and tagged _zwMatParsed. The innerHTML setter path stays on parse proxies for mutations/CE attach; visibility is handled only on query. Exemptions: noWire fragment children stay proxies through apply bumps; subtrees with already-upgraded custom elements skip materialization to avoid double constructors.

K3 apply-generation cleanup in part05.js drops _zwMatParsed wrappers from pending overlay after host apply so child lists do not double-merge.

Adds V8 sandbox regression tests in part18.rs (immediate query, variants, K3/noWire/CE arms).

Reviewed by Cursor Bugbot for commit af4b7a5. Bugbot is set up for automated code reviews on this repo. Configure here.

树内容器 innerHTML 后 host apply 异步,立即相对查询走 host 快照 miss →
null(bilibili nano sendBar widget 注册表 this.template.info/online 等全
null,resize/hideDm/renderOnlineCount 消费崩,npd.314)。R322 host-miss
兜底只扫桶 added 的 handle 子树,sel 路径产物 _zwMEl 解析代理不可见。

修复为查询时物化:R322 兜底臂扩扫桶 added 解析顶层代理(R304 槽、无
handle 无 sel、parentSel 匹配),_matchCompoundOf 命中现场
_wcRebuildAsHandle 物化并原位替换桶成员/全局表/by-id 索引 + 写 sel 域父
反链 + _zwMatParsed 标记;K3 apply 代际清除加 _zwMatParsed wrapper 臂
(反链定位、同批清),消 apply 后 overlay 重复并入。setter 记账面
(mutation 队列/CE attach/_mo_notify)保持解析代理原样零变化。已
upgrade CE 代理按 prototype 印记判后返回代理,防二次 ctor。

第一版 setter 侧物化(_ihAdded 全量替换)引入 slice13 双计 + t7 host
序列化两簇回归,已否决;定案下三测试恢复绿。

验证:t8r-4 双钉红→绿(红态变异实证 info:null + styleWrite throw
TypeError 精确命中 npd.314 消费崩形态);lib 全量 2964P/0F(+2 钉);
WPT dom 套 55,085P/198F/16T vs 基线 55,084P/198F/17T,Fail 集合 diff
零差异(唯一差异 Event-dispatch-click 文件级 Timeout→Pass 正向翻转);
make test exit 0;fmt CLEAN;clippy 双腿 -D warnings 全绿。

Co-Authored-By: Claude Code <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 10, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: 57edb4ed-0b66-49a4-8337-1afb230b6764)

…g 全闭合

双审查统一返修(两独立首轮均 REQUEST_CHANGES):
- noWire 豁免(审查② F1):R97/createContextualFragment 的 noWire 解析子
  从未 wire 进 host 快照,物化打标被 K3 apply 代际作废后跨 turn 丢子
  (审查实证 base post:1 → 修复初版 post:0)。匹配命中按代理返回(可见
  性=代理匹配面一致),不物化不打标。
- CE 子树印记检测(审查② F2):setter 期 attach 已递归 upgrade 全子树,
  物化根经 createElement 对已 upgrade CE 后代重复 ctor(实测 1→2)。物
  化前展平子树逐元素反查 registry+prototype 印记,命中整条目回退代理。
- K3 作废臂钉测(审查① blocking):新钉 t8r4_k3_invalidate_nowire_and_
  ce_subtree 三臂(host apply 序列作废/noWire 豁免/CE 后代单 ctor),
  承重半区从零护栏到三变异红态判别(3≠2 / nwPost:lost / ctor:2,后两
  者与审查探针读数逐字符一致)。
- 写前校验(审查② F6):物化(CE ctor 可执行页面代码)后校验桶槽未被
  重入改动,防按物化前索引写腐化。
- 主钉负控制 `.nope`=null(审查① nit,防过匹配)。

验证:定向 6/6 绿;lib 全量 2965P/0F(+1 钉);WPT dom 套返修轮
55,085P/198F/16T 与首轮逐数一致(Fail/Pass diff 均空);make test
exit 0(首跑超时为共用宿主兄弟会话构建负载挤压 900s 墙钟,负载窗口外
复跑零 60s 警告,环境超时非代码卡死);fmt/clippy 双腿全绿。

Co-Authored-By: Claude Code <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 10, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: 3215650e-da46-4fad-8ea7-9ee2edc08b9c)

非作者复核 APPROVE_WITH_NITS N2:钉测内联注释写「K3 新臂禁用变异下
overlay 重复并入 = 4」,变异实测为 3(仅被查询物化的首子残留并入,未
物化的次子被既有解析补偿臂正常清除)。注释对齐实测读数。

Co-Authored-By: Claude Code <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 10, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: 78a59e1d-50fc-4c73-a78c-338baf4b2239)

@leizongmin
leizongmin merged commit 7fd20cb into main Oct 10, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant