Skip to content

fix(engine-dom): innerHTML 本地视图产物物化真 handle 树,修 nano 播放器 volume/progress 小部件脚本中断 - #130

Merged
leizongmin merged 2 commits into
mainfrom
t8r-local-artifact-interface
Oct 10, 2026
Merged

leizongmin merged 2 commits into
mainfrom
t8r-local-artifact-interface

Conversation

@leizongmin

@leizongmin leizongmin commented Oct 10, 2026 •

Copy link
Copy Markdown
Owner

fix(engine-dom): innerHTML 本地视图产物物化为真 handle 树,修 nano 播放器 volume/progress 小部件脚本中断

问题

t8q(PR #129)修通 adoptNode 主链后,bilibili 视频页 nano 播放器初始化推进到小部件层,console 报 5 条同形态错误:volume 小部件 TypeError: Cannot set properties of undefined (setting 'webkitTransform')×2(npd.586 n.move)、progress 小部件 Cannot set properties of undefined (setting 'transform')×3(npd.911 updateCurrentSchedule/updateBufferSchedule)——查询返回了节点但 .style 为 undefined,mobx Reaction 链中断,players=0。

站点链路(bundle 静态解剖):volume 小部件 this.area = document.createElement('div')(handle ✓)→ area.innerHTML = tpl() → elements.bar = area.querySelector('.bar-normal') → bar.style.webkitTransform = …;progress 小部件 mainScheduleWrap.innerHTML = i → mainScheduleWrap.querySelectorAll('.schedule-current')[o].style.transform。

根因

innerHTML setter 的 handle 路径(detached createElement 容器)把 _zwFragmentAdded 产出的 _zwMEl 解析代理直接存入本地子视图 _handleChildren(part04.js)。相对查询从该视图扫描返回 truthy 节点,但 _zwMEl 是解析快照代理——无 .style/.classList 等 HTMLElement 接口,站点脚本第一条样式赋值即 TypeError,小部件构造中断。

这与 createElement+appendChild 路径(存真 handle wrapper,全接口)不一致:同样「JS 构造的子树」,注入方式不同产物接口不同,违反 HTML Standard §dom-innerhtml 产物应为完整元素节点的语义。

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

  • js_dom_shim/part04.js(innerHTML setter 存储出口):_handleChildren[handle] = _ihAdded 改为逐顶层元素子经既有 _wcRebuildAsHandle(t8q 重建器)物化为真 handle 树(属性/深层子递归),文本/注释子保持原样(cloneNode 复制分支读 .data 兼容);物化失败回退代理原样。顶层子补 _zwNodeParent 父反链(appendChild 家族同款),保持 R136 的宿主 parentNode 语义。
  • js_dom_shim/part04.js(focus 迁移):旧焦点为 handle/proxy 域时沿父反链上行判 shadow 归属,命中 _shadowHandleMeta 即以 host 为 relatedTarget(与 R148 解析节点臂同源 retargeting)。

第二处是第一处的语义外溢修复:shadow root 复用 fragment handle 容器,root.innerHTML 产物同被物化后,shadow 内元素 focus 从解析节点域(_zwMElFocused)切到 handle 域,暴露 handle 域焦点迁移无 shadow retargeting 的既有缺口——WPT shadow-relatedTarget 断言 e.relatedTarget === host 会退化。沿反链上行复用 _shadowHandleMeta 判定,非 shadow 上行 miss 回落既有语义(rtForNew = oldProxy),零行为变化。

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

  • CE 构造去重(审查② N1):物化经 createElement 已对 registry 命中的自定义元素跑过 ctor,而后续 __zwCeAttachForAdded(_ihAdded, …) 仍对原解析代理整表 upgrade——_ceUpgradeNode 无幂等门(_ceRunCtor 无条件执行),且 createElement 构造亦无幂等印记,重复 ctor 副作用翻倍、connectedCallback 派发到被丢弃的孤儿代理上。修法:物化循环收集回退代理(_wcRebuildAsHandle catch 返原 node 的顶层元素子=未构造);attach 点按物化是否生效分流——生效时回退代理仍走 upgrade(必要),成功 wrapper 只补连接态派发(pc 双源判定 + _ceApplyConn 递归派发,无 ctor);未物化路径原调用逐字不变。新钉 t8r_inner_html_materialized_custom_element_ctor_once 断言 ctor 恰 1 次(红态变异实证 ctor:2 精确复现审查探针读数,ctor 段独占判别)。
  • 钉测补强(审查① Bump actions/github-script from 7 to 9 #1/Bump actions/download-artifact from 4 to 8 #2):变体钉追加混合 markup+文本顶层注入臂('<b>x</b>tail':尾文本子保持代理 .data 可读、元素子物化全接口)与物化成员跨查询 identity 断言(两次 querySelector 同一对象 + 与 firstElementChild 一致)。
  • 注释校正(审查① Bump softprops/action-gh-release from 2 to 3 #3):_zwNodeParent 反链注释改按实际承重面表述(焦点注册/retargeting 上行链与事件冒泡;parentNode 读另有 _parentNodeFor R155 fallback 兜底)。
  • 格式修正(审查① Bump actions/checkout from 4 to 7 #4):t8q 既有主钉的 assert_eq! 缩进 6→4 空格(本轮测试编辑的顺手扰动复原)。

审查记录不修项:MO addedNodes 代理(PR 已披露,t8r-2 同域)、cloneNode deep 既有缺口(t8r-3 池项)、已 apply 容器二次 innerHTML stale 反链(BASE 同型既有)、window named access 注册对象 identity 分叉(既有越权,独立语义决策转池)。

不引入新机制:重建器、父反链、shadow meta、attach pc 判定均为既有设施的最小接线。

已知限制(如实披露)

物化 wrapper 是 detached 新建 handle,与宿主树 innerHTML 产物的 handle 不同源——对查询产物的样式/属性写不穿透渲染(volume/progress 条 transform 视觉暂不更新)。本切片消除的是「.style 抛 TypeError 脚本中断」面(小部件构造从失败恢复为可继续);视图-宿主写穿透对齐记入问题池(t8r-2)。MutationObserver addedNodes 仍持 setter 时快照的代理原件(R3031 既有钉测纯 introspect,零回归)。

验证

  • 红→绿钉测(js_dom_bridge_tests/part18.rs 新增 3 测):主钉复刻真站链(detached 容器 innerHTML → 相对查询 → style 写读回 → 深查 → 多顶层子 → parentNode),断言 style:object|styleSet:function|styleWrite:ok|styleRead:0.5|tag:DIV|class:ok|nested:ok|tip:ok|parent:ok;变体钉覆盖纯文本分支/清空/二次重物化/混合容器(物化成员+appendChild 成员共存)/introspection 保真/混合 markup+文本顶层注入/跨查询 identity。红态实跑与推演逐字一致(style:undefined|styleWrite:throw:TypeError|nested:bad|tip:bad + reIh:bad;护栏臂红态绿不误报),修复后双绿。N1 钉红态变异实证 ctor:2(与双审查探针读数一致)、修复后 ctor:1|isInst:ok。
  • zero-engine lib 全量:2962 passed / 0 failed(2959 基线 + 3 新钉;RUST_MIN_STACK=33554432 深嵌套既有要求)。中途红一轮:R148 shadow-relatedTarget 钉 related:other(上述外溢根因),补 handle 域 retargeting 臂后全绿。
  • WPT dom 套全量对照:主修复轮 55,083 Pass / 199 Fail,与 t8q r3 基线逐数一致;返修轮 55,084 Pass / 198 Fail,与主轮基线 Fail 集合唯一差异为同文件 GamepadEvent subtest Fail→Pass(同族时间戳分辨率断言的时序 flaky 正向翻转,与 DOM 结构无语义交集)——两轮均零实质退化。
  • 真站复跑(bilibili 视频页,headless 探针 r5,release 重建 + 执行体核验 renderer _ihMat=3/_r148Up=5):
    • r4 的 volume webkitTransform×2 + progress transform×3 五条 TypeError 全部消除;
    • census mountHTML 推进:出现 bpx-docker bpx-docker-major(data-injector=nano)层与 container 的 data-revision/data-locale 属性(r4 无);
    • widget 安装链推进暴露新层:4 条 error 来自 npd.314.700a18c2.js(r4 未出现的 chunk)——Cannot read properties of null (reading 'style'/'ownerDocument'/'classList'),bundle 解剖定谳为 widget 模板元素注册表(this.template.info/online 等)选择器查询 miss(null≠undefined,非接口缺失面),已记池(t8r-4,下一任务候选);
    • players 仍 0(widget 链在 npd.314 处中断)、videos=1 不变、未起播,不虚报;jinkela 簇与 mobx pageError 与 r4 逐字一致。

截图

无适用画面:本修复改的是 DOM 接口语义(注入产物接口完整性)与焦点 retargeting,非视觉呈现面;验证经 headless CDP 探针采集,无 GUI 窗口可截。挂载状态证据以探针 census 序列化文本为准(上节 r4→r5 对比)。

测试计划

  • cargo test -p zero-engine(lib 全量 2962P/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

innerHTML setter 的 handle 路径(detached createElement 容器)此前把 _zwMEl
解析代理存入 _handleChildren——相对查询返回 truthy 节点但无 .style/.classList
接口,bilibili nano 播放器 volume(npd.586 webkitTransform×2)/progress
(npd.911 transform×3)小部件构造即中断,players=0。

改为逐顶层元素子经既有 _wcRebuildAsHandle 物化为真 handle 树(appendChild
路径同构成员类型),顶层子补 _zwNodeParent 反链保持 R136 parentNode 语义;
物化失败回退代理原样。shadow root 复用 fragment 容器同被物化后,focus 从
解析节点域切到 handle 域,暴露 handle 域焦点迁移无 shadow retargeting 缺口——
沿父反链上行判 shadow 归属,命中 _shadowHandleMeta 以 host 为 relatedTarget
(与 R148 解析节点臂同源),非 shadow 上行 miss 回落既有语义。

验证:红→绿钉测×2(红态读数与真站崩型一致);lib 2961P/0F;WPT dom 套
55,083P/199F 与基线 Fail 集合精确 diff 零实质差异;真站 r5 探针五条
TypeError 全消、mount 推进到 bpx-docker 层(新暴露 npd.314 查询 null 簇
记池);fmt/clippy 双腿/make test 全绿。

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: 49ed65d1-94bb-43cb-8e0b-9d30f5466a25)

审查② N1:物化经 createElement 已对 registry 命中的 CE 跑过 ctor,
__zwCeAttachForAdded 再对原解析代理整表 upgrade(_ceUpgradeNode 无幂等门)
→ ctor ×2、connectedCallback 落孤儿代理。修法:物化循环收集回退代理
(_wcRebuildAsHandle catch 返原 node),attach 点按物化是否生效分流——
生效时回退代理仍走 upgrade,成功 wrapper 只补连接态派发(pc 双源判定 +
_ceApplyConn 递归派发,无 ctor);未物化路径原调用逐字不变。

附带双审查采纳项:变体钉补混合 markup+文本顶层注入臂与物化成员跨查询
identity 断言(①#1/#2)、_zwNodeParent 反链注释按实际承重面校正(①#3)、
t8q 主钉缩进 6→4(①#4)、N1 新钉断言 ctor 恰 1 次(红态变异实证 ctor:2
与审查探针读数一致)。

验证:t8r 三钉绿 + N1 红态 ctor:2 → 修复后 ctor:1;lib 全量 2962P/0F;
make test exit 0;WPT dom 套 55,084P/198F 与基线唯一差异为 GamepadEvent
时间戳 flaky 正向翻转(Fail→Pass,同族已记录时序 flaky,零实质退化);
fmt CLEAN + clippy 双腿(默认 v8 + quickjs no-default)-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: 8486f720-3ce3-49e4-bd89-607c78e3aa4c)

@leizongmin
leizongmin merged commit 11499f2 into main Oct 10, 2026
2 checks passed
@leizongmin
leizongmin deleted the t8r-local-artifact-interface branch October 10, 2026 11:22
leizongmin added a commit that referenced this pull request Oct 10, 2026
- README/ROADMAP/architecture 渲染口径更新至 R5051(15,265/16,594 ≈ 91.99%,fail 1,329),近期修复族换为 aspect-ratio transferred / min-content / ::placeholder(R5029–R5051);navigation-compat 更新至 M2 收口(S1~S9 三十三片,navigation-api 93.3%、全量 85.7%,408/476,DC-3 用户门控挂起)
- CHANGELOG 补 2026-10-10/11 四条:导航 M2-S4R–S9 收口、渲染 R5024–R5051、engine DOM 物化面修复(PR #128–#130,nano 播放器面)、script-sandbox register_callback 槽位所有权 + test-guard 负进程组定界
- rendering-compat master 头部引子由上游流自更新至 R5051,本批不再代写(rebase 冲突按取上游版解决);本轮无新增 crate、无依赖变动、crate README 无过时项;zero-web master R 记录仍 10 条未触发迁移阈值
- 取数与推送窗口内兄弟流持续推进(R5047→R5051、S8→S9 收口),数字以 rebase 后上游控制面为准
- 验证:git diff --check 干净;lei-pre-commit-guard PASS(隔离子代理重扫 4 文件 +10/−6 零发现);纯文档变更,不触发浏览器全量门禁

Co-Authored-By: Claude <noreply@anthropic.com>
leizongmin added a commit that referenced this pull request Oct 11, 2026
…口(85.7%);wpt-suites 两行更新;首页 commit 计数刷新至 12,500+

- website/updates.json:新增 2026-10-11 中英双语周报(uievents-compat
  10-07 尾簇 41 收口 Done:corpus 230 基线→1,794P/170F/96TO、+1,575 累计、
  173F+96TO 按 14 类编目挂账、四项转归档后用户决策;navigation-compat
  M2 收口 S1–S9 三十三片:20.9%→85.7%(408/476),分域 97.7/98.2/93.3/
  93.3,DC-3 用户门控挂起;渲染 R5024–R5054 aspect-ratio/min-content
  战役 + ::placeholder/::selection 三轮,fail 1,368→1,323、R5051 口径
  15,265/16,594 ≈ 91.99% 同步 README/ROADMAP;七新 goal 立项编号 16–25
  满编;innerHTML 物化修 bilibili nano 播放器(PR #128–#130)、
  register_callback 槽位所有权修复、CSV 列错位修复;weekly WPT 92.3%),
  文案经 /lei-humanizer 处理,21 项事实/数字程序化核对未改动
  (修正一处错误星期表述与标题推算百分比,改用来源原值)
- docs/compat/trends/wpt-suites.csv:①rendering-compat 追加 2026-10-11
  行(R5051 轮口径 15,265/16,594 ≈ 91.99%,note 注明 R5052-R5054 后
  fail 1,323,evidence 指 docs/goal/rendering-compat.md);②uievents-compat
  追加 2026-10-07 行(收口 1,794/2,060,170F+96TO 编目挂账注记,status
  completed,evidence 指 docs/goal/uievents-compat.md);navigation-compat
  已由目标流行维护至 10-11 无需变动
- website/index.html:统计卡 commit 总数 12,000+ → 12,500+
  (git rev-list --count HEAD = 12562,按百位向下取整)
- 门禁:git diff --check 干净;cargo fmt --all --check 干净;
  cargo clippy --workspace --all-targets -- -D warnings 零告警

Co-Authored-By: Claude <noreply@anthropic.com>
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