test(danmuku): [PKG-DANMUKU-02] establish failure browser and load baselines

This commit is contained in:
Harvey Zhao committed 2026-09-13 18:03:21 +08:00
1 parent ccf3d6ed14
commit d3c91af92c
14 files changed
+8508 -15

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -0,0 +1,301 @@
{
"schemaVersion": 1,
"task": "PKG-DANMUKU-02",
"scope": "Controlled historical failure subtask only; parent browser/clock/track/load baseline remains required",
"wholeTaskComplete": false,
"capturedAt": "2026-09-13T09:46:29.424Z",
"sourceCommit": "b0cfbfe3a09a84a295a257e45e4577847588d1cb",
"environment": {
"node": "v24.21.0",
"platform": "win32",
"architecture": "x64",
"executable": "refactor/.cache/toolchains/node-v24.21.0-win-x64/node.exe"
},
"inputs": {
"test/helpers/danmuku.js": {
"sha256LF": "4e4420d6fe7198bd91c7a444f3f82740991181c3a1b2cb8b91b1db6fc759046a"
},
"test/danmuku-failures.test.js": {
"sha256LF": "1d7a4fc988f75239bc33453fe4334c17ab34420b58ae26a33d7fc7471be8bf8f"
},
"refactor/baselines/danmuku-release.json": {
"sha256LF": "82a0ab2e87f108cbb1d09ce1b6647cfefc896d974da1cb60b2668fded18a4b2f"
},
"refactor/scripts/danmuku-contract.mjs": {
"sha256LF": "8ca0996605cfbcd732030708bd67ecedff5018d2b7436fa7247de7bbb39d7573"
},
"refactor/changes/2026-09-13-PKG-DANMUKU-02-controlled-failures.md": {
"sha256LF": "e4373ee55bcd1f96987d6a647663bef9d646e7caa30ba9abf5416202b3873169"
}
},
"tests": {
"command": "node --test test/danmuku-failures.test.js",
"exitCode": 0,
"passed": 42,
"failed": 0,
"skipped": 0,
"log": "refactor/.cache/danmuku02-controlled.log",
"logSha256": "5e17966b1cd19f045b1d74d2ac065271ddbaeec44b7c5b533d625f3bd5b05670",
"implementationCount": 3,
"scenariosPerImplementation": 14
},
"lint": {
"command": "node node_modules/eslint/bin/eslint.js test/helpers/danmuku.js test/danmuku-failures.test.js",
"exitCode": 0,
"log": "refactor/.cache/danmuku02-controlled-lint.log",
"logSha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"execution": {
"source": "Immutable Git modules bundled only in memory; Worker import transport controlled, parser actual generated Blob executed in a VM",
"main": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f",
"legacy": "62db96685c48b8573f0480cead6ac934b1d0382b9fdd0046d17d15d2549c56dc",
"validator": "Actual frozen published Artplayer 5.4.0 static validator",
"domAndClock": "Controlled, not a browser/layout/playback claim"
},
"isolatedProcesses": {
"directory": "refactor/.cache/danmuku02-controlled/run-9m9V8f",
"count": 15,
"rejectionProcesses": 9,
"rejectionFlags": "--unhandled-rejections=strict",
"observation": "uncaughtExceptionMonitor only; errors remain fatal with exit 1 and origin unhandledRejection",
"heatmapProcesses": 6,
"vmTimeoutMilliseconds": 100,
"processTimeoutMilliseconds": 3000,
"timeoutScope": "Expected VM timeout only for default sampling at width99; explicit sampling1 completes; outer process timeout fails the test",
"reports": [
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/frozen-source-beforeVisible-reject.json",
"sha256": "41748d818ad4b20b916140bec42b58687943dec7f1f7faa42e01ef7d57f76b42",
"implementation": "frozen-source",
"scenario": "beforeVisible-reject",
"status": 1,
"signal": null,
"errorCode": null,
"stdout": "{\"stage\":\"fatal\",\"origin\":\"unhandledRejection\",\"error\":\"beforeVisible-original\",\"settled\":false,\"errors\":0}\n"
},
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/frozen-source-fetch-reject.json",
"sha256": "8f05b57fe32605ff3233394304d7851760ed8335e7cb2cd4314e3399e54f6efa",
"implementation": "frozen-source",
"scenario": "fetch-reject",
"status": 1,
"signal": null,
"errorCode": null,
"stdout": "{\"stage\":\"fatal\",\"origin\":\"unhandledRejection\",\"error\":\"fetch-original\",\"settled\":false,\"errors\":0}\n"
},
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/frozen-source-heatmap-positive.json",
"sha256": "faf1edb2e96a800a7605db93e1266d3cb7304672609843f061ee09484251e841",
"implementation": "frozen-source",
"scenario": "heatmap-positive",
"status": 0,
"signal": null,
"errorCode": null,
"stdout": "heatmap-ready\n{\"stage\":\"complete\"}\n"
},
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/frozen-source-heatmap-zero.json",
"sha256": "5d3f166e103cccd2e6ba6b81e6cbcf95454f11c2f15427b41763a73ff4099dd8",
"implementation": "frozen-source",
"scenario": "heatmap-zero",
"status": 0,
"signal": null,
"errorCode": null,
"stdout": "heatmap-ready\n{\"stage\":\"bounded-timeout\",\"code\":\"ERR_SCRIPT_EXECUTION_TIMEOUT\"}\n"
},
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/frozen-source-text-reject.json",
"sha256": "261c3206b5180ff0e093b21a842e1bcd1dbcbccea637574c2a15416a75a706ba",
"implementation": "frozen-source",
"scenario": "text-reject",
"status": 1,
"signal": null,
"errorCode": null,
"stdout": "{\"stage\":\"fatal\",\"origin\":\"unhandledRejection\",\"error\":\"text-original\",\"settled\":false,\"errors\":0}\n"
},
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/published-5.3.0-legacy-beforeVisible-reject.json",
"sha256": "6f2c59251bcb37d029eac4e1edd68fb0bedd6499781f045a384e40e0bf2810ef",
"implementation": "published-5.3.0-legacy",
"scenario": "beforeVisible-reject",
"status": 1,
"signal": null,
"errorCode": null,
"stdout": "{\"stage\":\"fatal\",\"origin\":\"unhandledRejection\",\"error\":\"beforeVisible-original\",\"settled\":false,\"errors\":0}\n"
},
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/published-5.3.0-legacy-fetch-reject.json",
"sha256": "76e39a61d50e7a2722ae8fef16672764b91e28d6b8496b7bbd13cdf908418e13",
"implementation": "published-5.3.0-legacy",
"scenario": "fetch-reject",
"status": 1,
"signal": null,
"errorCode": null,
"stdout": "{\"stage\":\"fatal\",\"origin\":\"unhandledRejection\",\"error\":\"fetch-original\",\"settled\":false,\"errors\":0}\n"
},
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/published-5.3.0-legacy-heatmap-positive.json",
"sha256": "3b672dbb6af585b5f260ab3cf2ff294cf52026de192f64dcaa4202b4ae914dd3",
"implementation": "published-5.3.0-legacy",
"scenario": "heatmap-positive",
"status": 0,
"signal": null,
"errorCode": null,
"stdout": "heatmap-ready\n{\"stage\":\"complete\"}\n"
},
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/published-5.3.0-legacy-heatmap-zero.json",
"sha256": "817e3f4f61eb3c5f19096e9a6cc7fe01d5fb4be6756e52ab305de2e51fef7485",
"implementation": "published-5.3.0-legacy",
"scenario": "heatmap-zero",
"status": 0,
"signal": null,
"errorCode": null,
"stdout": "heatmap-ready\n{\"stage\":\"bounded-timeout\",\"code\":\"ERR_SCRIPT_EXECUTION_TIMEOUT\"}\n"
},
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/published-5.3.0-legacy-text-reject.json",
"sha256": "63c38503aad6fc9c0eafecc59e906c441827333d7fa102cae370511aadcd077b",
"implementation": "published-5.3.0-legacy",
"scenario": "text-reject",
"status": 1,
"signal": null,
"errorCode": null,
"stdout": "{\"stage\":\"fatal\",\"origin\":\"unhandledRejection\",\"error\":\"text-original\",\"settled\":false,\"errors\":0}\n"
},
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/published-5.3.0-main-beforeVisible-reject.json",
"sha256": "338d99844c2e05ac121beef206550a0f590c11e6b4caf3f702cce62c68d3c79d",
"implementation": "published-5.3.0-main",
"scenario": "beforeVisible-reject",
"status": 1,
"signal": null,
"errorCode": null,
"stdout": "{\"stage\":\"fatal\",\"origin\":\"unhandledRejection\",\"error\":\"beforeVisible-original\",\"settled\":false,\"errors\":0}\n"
},
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/published-5.3.0-main-fetch-reject.json",
"sha256": "97428c512f7eb613a1102532170b92a395f6845b83e03d4242084ffd69617a45",
"implementation": "published-5.3.0-main",
"scenario": "fetch-reject",
"status": 1,
"signal": null,
"errorCode": null,
"stdout": "{\"stage\":\"fatal\",\"origin\":\"unhandledRejection\",\"error\":\"fetch-original\",\"settled\":false,\"errors\":0}\n"
},
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/published-5.3.0-main-heatmap-positive.json",
"sha256": "a44cbec41648ea681eb4745561e704596aa0c2e4bc4c4024084701434a0a0fe1",
"implementation": "published-5.3.0-main",
"scenario": "heatmap-positive",
"status": 0,
"signal": null,
"errorCode": null,
"stdout": "heatmap-ready\n{\"stage\":\"complete\"}\n"
},
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/published-5.3.0-main-heatmap-zero.json",
"sha256": "5677249e3b1d26932b27ff8f2a8749c1c6e2d1e409ff090e6d3722ff0660255a",
"implementation": "published-5.3.0-main",
"scenario": "heatmap-zero",
"status": 0,
"signal": null,
"errorCode": null,
"stdout": "heatmap-ready\n{\"stage\":\"bounded-timeout\",\"code\":\"ERR_SCRIPT_EXECUTION_TIMEOUT\"}\n"
},
{
"file": "refactor/.cache/danmuku02-controlled/run-9m9V8f/published-5.3.0-main-text-reject.json",
"sha256": "f56b3c1f0d07f269f92a23d7751fc18c6b0b881c5458ddf98a33cdfe1c2c5401",
"implementation": "published-5.3.0-main",
"scenario": "text-reject",
"status": 1,
"signal": null,
"errorCode": null,
"stdout": "{\"stage\":\"fatal\",\"origin\":\"unhandledRejection\",\"error\":\"text-original\",\"settled\":false,\"errors\":0}\n"
}
]
},
"reproduced": [
{
"id": "DMK-FAIL-01",
"issue": "fetch rejection leaves public load pending and skips error event",
"next": "PKG-DANMUKU-03"
},
{
"id": "DMK-FAIL-02",
"issue": "response.text rejection leaves public load pending and skips error event",
"next": "PKG-DANMUKU-03"
},
{
"id": "DMK-FAIL-03",
"issue": "beforeVisible rejection becomes an ignored animation callback rejection",
"next": "PKG-DANMUKU-04"
},
{
"id": "DMK-FAIL-04",
"issue": "width99 default sampling0 does not advance heatmap loop; positive control succeeds",
"next": "PKG-DANMUKU-05"
},
{
"id": "DMK-FAIL-05",
"issue": "parser Worker error has no handler/settlement or destruction cleanup",
"next": "PKG-DANMUKU-03"
},
{
"id": "DMK-FAIL-06",
"issue": "actual generated parser ignores empty XML and load remains pending",
"next": "PKG-DANMUKU-03"
},
{
"id": "DMK-FAIL-07",
"issue": "successful parser does not revoke its Blob URL",
"next": "PKG-DANMUKU-05"
},
{
"id": "DMK-FAIL-08",
"issue": "parser completion can populate queue and emit loaded after destroy",
"next": "PKG-DANMUKU-03"
},
{
"id": "DMK-FAIL-09",
"issue": "old replacement load overwrites the newer completed queue",
"next": "PKG-DANMUKU-03"
},
{
"id": "DMK-FAIL-10",
"issue": "function input resolves and emits loaded after destroy",
"next": "PKG-DANMUKU-03"
},
{
"id": "DMK-FAIL-11",
"issue": "beforeVisible continuation allocates DOM and attempts terminated-worker post after destroy",
"next": "PKG-DANMUKU-04"
},
{
"id": "DMK-FAIL-12",
"issue": "already delivered Worker response continuation changes state after destroy",
"next": "PKG-DANMUKU-04"
},
{
"id": "DMK-FAIL-13",
"issue": "play/playing duplicate loops overwrite response handlers and strand an earlier Promise",
"next": "PKG-DANMUKU-04"
},
{
"id": "DMK-FAIL-14",
"issue": "pause/destroy leaves a previously scheduled duplicate frame",
"next": "PKG-DANMUKU-04"
}
],
"limitations": [
"Historical defect observations must not become candidate normal expectations",
"No native browser or server started",
"No actual Bilibili/media request, native Worker/CSP, video clock or layout tested",
"Late Worker continuation test delivers before terminate and resumes after it; no post-terminate native event guarantee assumed",
"Real track/clock/load/performance and visual/browser evidence required for whole task",
"No production source/declaration/artifact edits and no publication readiness conclusion"
],
"productionChanged": false,
"browserValidated": false,
"releaseReady": false
}
@@ -0,0 +1,77 @@
# PKG-DANMUKU-02 浏览器与负载基线
本记录整合先前的[受控失败子项](2026-09-13-PKG-DANMUKU-02-controlled-failures.md):
42项旧失败观察及父代理复跑通过,新增真实浏览器的行为、布局和负载记录。
这里完成的是重构前基线,生产代码、类型及dist均未修改;没有把已复现缺陷当作
候选必须保持的行为,也不代表弹幕能力或整包已经达到发布条件。
## 实际浏览器范围
使用真实npm Danmuku 5.3.0 main/legacy归档字节,每次核验SHA;真实已发布核心
5.4.0及当前候选5.4.1。Chromium 153.0.8010.12、Firefox 155.0、Windows WebKit26.6,
后者不是Safari真机。页面运行本地八秒视频、原生Blob Worker、实际DOM/设置操作。
Worker子类只记录创建/消息/终止,不替换回复、算法、RAF或媒体时钟。外网被拒绝,
同源Blob可用。共2核心×2插件格式×4场景×3引擎,48项通过、无跳过或未处理页面错误。
- 三种弹幕模式、同步filter与异步beforeVisible,真实居中/边界布局与Worker工作。
- 六条同时固定弹幕的顺序、严格非重叠几何与暂停状态。
- 原生play/pause/seek、两倍播放及四秒CSS运动时长,reset节点复用和load替换/追加。
- 实际设置面板、异步发送去重和锁定、外挂输入框在网页全屏时移入并回位,双实例
销毁隔离;旧版外部设置DOM残留如实记录为后续清理问题。
截图、原始几何、事件/Worker记录和运行输入在
[机器报告](../baselines/danmuku-browser-validation.json)引用的不可变归档中。
## 初轮失败及处置
首轮Chromium为7通过、9失败,原spec、报告、截图和trace完整保留。
八项来自两个错误测试假设:网页全屏会把播放器移到body,原容器选择器失效;
旧版可能复用一个节点后又生成额外节点,不能要求最终可见节点必须是原节点。
测试改为验证实际控件引用归属,以及原节点确实被再次使用,同时记录额外/隐藏节点。
没有修改生产行为来满足测试。
另一次是**实际轨道重叠**:dense0和dense1的y都为10,宽70、高22.5,并观察到
两次start及重复Worker消息id。截图也显示两条文字重叠。DANMUKU-TRACK-01保持开放,
与已受控复现的双RAF/请求覆盖问题一同由04/05/07修复验收。严格非重叠断言仍保留;
后次48通过只能说明那一轮没有触发,不能说明竞态已修复,后续运行仍可能再次报红。
负载首轮六项也保留:读取不存在的art.paused导致等待失败。改为原生
art.template.$video.paused后重跑通过;这属于测试错误,不记录成生产缺陷。
## 300条弹幕负载观察
两种实际插件格式、已发布核心、三个引擎,共六个配置;各载入300个独立ID混合模式
弹幕,确认完整队列、真实播放到至少四秒、可见输出、Worker工作和销毁。保存原始
帧时间戳/间隔、实际DOM池与几何、可见ID及各阶段performance.memory。独立RAF
观察者不更改插件时钟,但其自身也有测量开销。
初次三worker运行全部通过。WebKit帧间隔较长,因此再以单worker串行复测六个配置,
减少并行测试争用;两份报告均保留,不能混为相同条件或增加六种功能覆盖。
初次并行样本的可见唯一ID为51–129,DOM节点53–131;300载入成功不代表300条都
在短窗口显示。真实排队/轨道与显示窗口仍受当前调度器影响。
串行六项也通过。该主机上的帧间隔中位数:Chromium两格式约16.7ms,Firefox约
16.66ms,Windows WebKit为78/80ms;WebKit的p95为101/104ms。其样本可见51个ID、
DOM53个节点;记录保留这个差异,不因测试通过就称流畅,也不外推为Safari设备结论。
实际暂停时间约4.61–5.06秒,原始时间戳保留,后续比较须使用相同输入/观察方式。
Chromium提供堆读数,Firefox/WebKit为空;没有强制GC、跨引擎堆值比较、短样本
泄漏结论或凭空设置性能阈值。串行结果是后续同条件对照,07仍需更长负载、重复
装卸和资源稳定性验收。真实设备/CSP、Bilibili网络、Mask模型和最终新旧组合仍归后续。
## 重放、提交与下一步
```sh
yarn test:danmuku
yarn exec playwright test test/browser/danmuku-baseline.spec.js --workers=3
yarn exec playwright test test/browser/danmuku-load-baseline.spec.js --workers=1
```
固定Node24.21.0/Yarn1.22.22。受控测试接入test:unit,契约由test:baseline收集,
浏览器文件由既有Playwright发现。没有安装依赖、修改锁文件或使用全局吞错处理。
lint及任务/风险/契约索引校验随本次提交;本任务独立commit,无推送、标签或npm发布。
03接着整理加载、解析与config,保留数组同步初始化顺序、内部链式返回身份、
追加/替换区别、逐条await emit以及live option回调接收者;优先修复网络拒绝悬挂、
空XML、解析Worker/Blob释放、过期替换、time0和函数配置更新。轨道Worker/RAF、
设置/heatmap和完整TS公开类型分别由04/05/06接续。
@@ -0,0 +1,88 @@
# PKG-DANMUKU-02 受控失败基线子项
本记录只交付 02 的受控测试部分,**不代表 PKG-DANMUKU-02 整体完成**。
真实浏览器的时钟、轨道、密集/稀疏负载和可视结果由主任务另行验收。
没有修改生产源码、声明、构建产物、共享元数据或 root scripts;没有启动服务或浏览器。
## 冻结输入与测试方法
复用 [01 发布基线](../baselines/danmuku-release.json) 与
[不可变校验器](../scripts/danmuku-contract.mjs),执行三个实际实现:
- Git `b0cfbfe3a09a84a295a257e45e4577847588d1cb` 的冻结源码,只在内存打包。
- 真正 npm artplayer-plugin-danmuku@5.3.0 main 字节。
- 同一发布版的 legacy 字节。
[test/helpers/danmuku.js](../../test/helpers/danmuku.js) 提供受控 DOM、时钟、rAF、
timer、fetch 和 Worker transport;配置验证使用实际发布核心 5.4.0 的 validator。
[`danmukuHistorical()`](../../test/helpers/danmuku.js) 返回 `{name,code,coreCode}` 数组;
`danmukuEnvironment(implementation, settings)` 控制请求、帧、回应和资源观察。
其捕获的 Bilibili Blob 内容在独立 VM 中实际执行,XML 的空输入和正常解析不是手写替身。
框架只模拟传输/布局,不把它说成原生 Worker 或真实 DOM/播放验证。
[test/danmuku-failures.test.js](../../test/danmuku-failures.test.js) 每个实现有 14 个场景,
共 42 项历史观察全部通过。测试中的“失败”指真实历史缺陷;这些断言不能用于要求候选
保留缺陷。候选修复必须在后续任务中另加正确行为断言。
## 已复现观察
| 测试场景 | 精确结果 | 后续责任 |
| --- | --- | --- |
| DMK-FAIL-01 fetch rejection | fetch 原拒绝成为未处理拒绝;公开 load 不 settle,未发 :error | 03 |
| DMK-FAIL-02 text rejection | response.text 原拒绝同样脱离公开 load/error 路径 | 03 |
| DMK-FAIL-03 beforeVisible rejection | 异步 rAF 回调 Promise 被忽略,原错成为未处理拒绝;无 :error | 04 |
| DMK-FAIL-04 narrow heatmap | offsetWidth=99 的默认 sampling=0 耗尽 VM 时间预算;显式 sampling=1 正常完成 | 05 |
| DMK-FAIL-05 parser worker error | 未装错误处理;错误投递后 load 不 settle,destroy 也未终止这个 parser worker | 03/05 |
| DMK-FAIL-06 empty XML | 实际 Blob parser 忽略空 XML 而不回消息;load 一直等待,parser worker 活着 | 03 |
| DMK-FAIL-07 Blob URL | 真实 parser 成功后 worker terminate,但对应 URL 没有 revoke | 03/05 |
| DMK-FAIL-08 late parser | destroy 时 parser worker 未终止;之后实际 parser 完成仍向 queue 添加并发 :loaded | 03/05 |
| DMK-FAIL-09 out-of-order load | 两次无参数替换 load,第二次先完成,第一次晚完成将新队列覆盖为旧数据 | 03 |
| DMK-FAIL-10 late function input | destroy 后异步输入继续入队并触发 :loaded | 03 |
| DMK-FAIL-11 late beforeVisible | destroy 后用户 Promise 成功继续创建弹幕 DOM,尝试向已 terminate worker postMessage | 04/05 |
| DMK-FAIL-12 late continuation | worker 消息在 destroy 前送达,await continuation 在 destroy 后将 wait 改成 ready | 04/05 |
| DMK-FAIL-13 competing loops | play + playing 建两条循环;不同 id 的第二请求覆盖 onmessage,第一请求永不 settle | 04 |
| DMK-FAIL-14 remaining frame | 双 start 后 pause/destroy 只取消最后一帧,另一已排定帧仍存在 | 04 |
DMK-FAIL-12 不依赖浏览器在 terminate 后再派发 Worker 消息:测试先完成消息投递,
同步 destroy,再让 Promise continuation 恢复;不会夸大原生 Worker 终止语义。
DMK-FAIL-11 的证据是 DOM 分配与 postMessage 调用尝试,不宣称原生 worker 已终止后
仍执行代码或真的显示弹幕。测试也确认 late worker 分支没有发新的 :visible。
03 需要明确异步取消如何 settle 公开 load Promise、如何保持原错误通知/返回关系;
04/05 需要单一帧循环、每请求关联、generation/销毁防护和 parser/Blob/设置的资源所有权。
这只是后续设计边界,不在本任务提前实现或改变接口。
## 进程隔离与可重复证据
三类未处理拒绝各实现分别运行独立 Node 子进程,共 9 次,固定
`--unhandled-rejections=strict`。只用 `uncaughtExceptionMonitor` 记录原错误、origin、
公开 Promise settled 标记和 :error 数量,不注册吞掉错误的 unhandledRejection 或
uncaughtException 处理器。实际进程 exit 1,monitor 记录 origin=unhandledRejection;
不是把未处理拒绝隐藏到通过结果中。
热力图另有 6 次独立进程:三个 sampling=0,三个 sampling=1 对照。内部 VM 100ms
执行预算明确产生 `ERR_SCRIPT_EXECUTION_TIMEOUT`;对照完成且没有超时。外层进程
还有 3000ms 最终保护,外层超时本身会使测试失败,不能被算作正常观察。
整个重放不会把零步长循环交给真实浏览器页面。
每次测试写独立 `refactor/.cache/danmuku02-controlled/run-*/`,保留 15 个子进程
stdout/stderr/status JSON。最终目录、文件 SHA、脚本 SHA、命令与汇总见
[danmuku-failures-validation.json](../baselines/danmuku-failures-validation.json)。
```text
node --test test/danmuku-failures.test.js
node node_modules/eslint/bin/eslint.js test/helpers/danmuku.js test/danmuku-failures.test.js
```
实际 Node 24.21.0 / Windows,42 passed / 0 failed / 0 skipped;专属 lint 通过。
没有新依赖、没有修改 Yarn lock。缺少归档缓存时,01 verifier 只向冻结 npm URL 请求,
测试本身不会请求 Bilibili、媒体或任何识别服务。
## 未完成范围与回退
尚未覆盖原生 Worker/CSP、真实媒体时钟和 seek/倍率、实际测量的防重叠/轨道顺序、
长时间负载、内存、设置触摸/旋转、mask/fullscreen/PiP/外部挂载、浏览器错误表现。
这些内容仍是 PKG-DANMUKU-02 及后续组合验收的门槛。本报告不标包重构完成或 npm 可发布。
此批只有历史测试与证据,可独立撤销,不影响发布包。整合代理将本子项与 02 的其他
必要证据一起管理状态;不要仅依据这 42 个观察把整个任务标为 done。
+4 -3
View File
@@ -4,7 +4,7 @@
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 228 项,范围 22 个包及工作区/示例。
状态:todo 73 / doing 15 / blocked 0 / done 140 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
状态:todo 72 / doing 15 / blocked 0 / done 141 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
@@ -310,8 +310,8 @@
| ID | 范围 / 步骤 | 前置依赖 | 交付物 | 验收条件 | 风险 | 状态 |
| --- | --- | --- | --- | --- | --- | --- |
| PKG-DANMUKU-01 | artplayer-plugin-danmuku<br>核对弹幕全部公开契约 | BASE-05 | emit/load/config/hide/show/reset/mount、option/isHide/isStop/icons 与事件清单 | 源码、声明、发布包、Bilibili 输入和设置入口对照 | H | done |
| PKG-DANMUKU-02 | artplayer-plugin-danmuku<br>建立弹幕算法与浏览器基线 | PKG-DANMUKU-01, ENG-05, ENG-08 | 密集/稀疏弹幕、过滤/异步输入、seek/倍率/重载测试 | 轨道选择、发射顺序、事件、内存和可视结果可重跑 | H | doing |
| PKG-DANMUKU-03 | artplayer-plugin-danmuku<br>整理加载、解析与配置 | PKG-DANMUKU-02, CORE-08 | bilibili/input/parser/config 的分层与取消 | 旧格式、回调、过滤、追加/替换语义保持 | M | todo |
| PKG-DANMUKU-02 | artplayer-plugin-danmuku<br>建立弹幕算法与浏览器基线 | PKG-DANMUKU-01, ENG-05, ENG-08 | 密集/稀疏弹幕、过滤/异步输入、seek/倍率/重载测试 | 轨道选择、发射顺序、事件、内存和可视结果可重跑 | H | done |
| PKG-DANMUKU-03 | artplayer-plugin-danmuku<br>整理加载、解析与配置 | PKG-DANMUKU-02, CORE-08 | bilibili/input/parser/config 的分层与取消 | 旧格式、回调、过滤、追加/替换语义保持 | M | doing |
| PKG-DANMUKU-04 | artplayer-plugin-danmuku<br>整理时钟、队列与轨道调度 | PKG-DANMUKU-03, CORE-10 | danmuku 调度器和确定性时钟测试 | seek/暂停/倍率/长时间运行无顺序和碰撞回归 | H | todo |
| PKG-DANMUKU-05 | artplayer-plugin-danmuku<br>整理 DOM 渲染、设置、热力图与 worker | PKG-DANMUKU-04, CORE-14, CORE-18 | renderer/setting/heatmap/worker 职责及资源归属 | mount/icons/设置和 worker 协议保持,销毁无后台工作 | H | todo |
| PKG-DANMUKU-06 | artplayer-plugin-danmuku<br>迁移 TS 与公开声明 | PKG-DANMUKU-05, ENG-04, ENG-06 | 自有模块、worker 消息、option/item/result 类型 | 旧参数、扩展字段和事件消费通过,vendored 边界清楚 | H | todo |
@@ -554,6 +554,7 @@
- PKG-DPIP-04: [记录](changes/2026-09-12-PKG-DPIP-04-types.md) [记录](baselines/dpip-types-validation.json) [记录](dpip-validation.md)
- PKG-DPIP-05: [记录](changes/2026-09-12-PKG-DPIP-05-native-checkpoint.md) [记录](baselines/dpip-native-validation.json)
- PKG-DANMUKU-01: [记录](baselines/danmuku-release.json) [记录](baselines/danmuku-contract.md) [记录](baselines/danmuku-contract-validation.json) [记录](changes/2026-09-13-PKG-DANMUKU-01-contracts.md)
- PKG-DANMUKU-02: [记录](changes/2026-09-13-PKG-DANMUKU-02-controlled-failures.md) [记录](baselines/danmuku-failures-validation.json) [记录](changes/2026-09-13-PKG-DANMUKU-02-browser-baseline.md) [记录](baselines/danmuku-browser-validation.json)
- PKG-CANVAS-01: [记录](changes/2026-09-12-PKG-CANVAS-01-contract.md) [记录](baselines/canvas-contract.md) [记录](baselines/canvas-release.json) [记录](canvas-validation.md) [记录](baselines/canvas-contract-validation.json)
- PKG-CANVAS-02: [记录](changes/2026-09-12-PKG-CANVAS-02-tests.md) [记录](baselines/canvas-behavior-validation.json) [记录](canvas-validation.md)
- PKG-CANVAS-03: [记录](changes/2026-09-12-PKG-CANVAS-03-lifecycle.md) [记录](baselines/canvas-lifecycle-validation.json) [记录](canvas-validation.md)
+11
View File
@@ -1,5 +1,16 @@
# 进度与证据
## PKG-DANMUKU-02 历史错误和真实浏览器基线完成
42项受控旧缺陷、48项原生Worker/视频/布局/设置及6项300弹幕负载观察通过;所有
初轮失败留档。纠正两个测试假设,保留严格非重叠断言;首次测到的实际轨道重叠
仍为DANMUKU-TRACK-01开放问题,后次48通过不能替代修复。短时heap/帧间隔不是
长期内存或性能验收。见[变更](changes/2026-09-13-PKG-DANMUKU-02-browser-baseline.md)与[机器证据](baselines/danmuku-browser-validation.json)。
根test:unit接入受控测试,浏览器文件由已有Playwright流程收集。
228项:141 done、15 doing、72 todo。03开始输入/解析/config
实施;04调度/05DOM和07负载稳定性继续。无推送或发布。
## PKG-MASK-02 生命周期与错误基线完成
54项冻结历史测试及父代理复核通过,覆盖源码和两旧版本三格式的关键生命周期;
+3 -2
View File
@@ -232,6 +232,7 @@
| DANMUKU-CONFIG-01 | open / 已复现 | Danmuku JSON configuration comparison ignores a replacement filter function | PKG-DANMUKU-02, PKG-DANMUKU-03 |
| DANMUKU-CLEANUP-01 | open / 已复现 | Danmuku removes a different resize callback and retains the settings lock timer on destroy | PKG-DANMUKU-02, PKG-DANMUKU-05 |
| DANMUKU-TYPE-02 | open / 源码/产物事实 | Danmuku id, icons, Slider steps, heatmap points and partial configuration drift from declarations | PKG-DANMUKU-05, PKG-DANMUKU-06 |
| DANMUKU-ASYNC-01 | open / 源码/产物事实 | Danmuku asynchronous input, worker replies and pending visibility have unverified failure and cancellation paths | PKG-DANMUKU-02, PKG-DANMUKU-03, PKG-DANMUKU-04, PKG-DANMUKU-05 |
| DANMUKU-HEATMAP-01 | open / 源码/产物事实 | Danmuku heatmap sampling can become zero and points/instance ownership need browser validation | PKG-DANMUKU-02, PKG-DANMUKU-05 |
| DANMUKU-ASYNC-01 | open / 已复现 | Danmuku asynchronous input, worker replies and pending visibility have unverified failure and cancellation paths | PKG-DANMUKU-02, PKG-DANMUKU-03, PKG-DANMUKU-04, PKG-DANMUKU-05 |
| DANMUKU-HEATMAP-01 | open / 已复现 | Danmuku heatmap sampling can become zero and points/instance ownership need browser validation | PKG-DANMUKU-02, PKG-DANMUKU-05 |
| DANMUKU-SOURCE-01 | open / 已复现 | Danmuku registry Git associations differ from releases and static icon provenance remains incomplete | PKG-DANMUKU-09 |
| DANMUKU-TRACK-01 | open / 已复现 | Native simultaneous fixed Danmuku comments can overlap with duplicate start loops and repeated Worker IDs | PKG-DANMUKU-04, PKG-DANMUKU-05, PKG-DANMUKU-07 |
+34 -5
View File
@@ -5082,7 +5082,9 @@
"evidence": [
"refactor/baselines/danmuku-contract.md",
"refactor/baselines/danmuku-contract-validation.json",
"refactor/baselines/danmuku-release.json"
"refactor/baselines/danmuku-release.json",
"refactor/changes/2026-09-13-PKG-DANMUKU-02-browser-baseline.md",
"refactor/baselines/danmuku-browser-validation.json"
],
"compatibleResolution": "Track and release exact subscription and timer ownership across settings, renderer and instances.",
"closureCriteria": "Repeated lifecycle and pending settings actions leave no owned subscriptions, timers or late DOM writes."
@@ -5107,7 +5109,7 @@
{
"id": "DANMUKU-ASYNC-01",
"title": "Danmuku asynchronous input, worker replies and pending visibility have unverified failure and cancellation paths",
"confirmation": "source-observed",
"confirmation": "reproduced",
"status": "open",
"owners": [
"PKG-DANMUKU-02",
@@ -5118,7 +5120,11 @@
"evidence": [
"refactor/baselines/danmuku-contract.md",
"refactor/baselines/danmuku-contract-validation.json",
"refactor/baselines/danmuku-release.json"
"refactor/baselines/danmuku-release.json",
"refactor/baselines/danmuku-failures-validation.json",
"test/danmuku-failures.test.js",
"refactor/changes/2026-09-13-PKG-DANMUKU-02-browser-baseline.md",
"refactor/baselines/danmuku-browser-validation.json"
],
"compatibleResolution": "Reproduce load ordering, Bilibili rejection and late worker/visibility paths before defining operation ownership.",
"closureCriteria": "Failures settle, obsolete results cannot alter new queues or destroyed instances, and worker resources are released with browser evidence."
@@ -5126,7 +5132,7 @@
{
"id": "DANMUKU-HEATMAP-01",
"title": "Danmuku heatmap sampling can become zero and points/instance ownership need browser validation",
"confirmation": "source-observed",
"confirmation": "reproduced",
"status": "open",
"owners": [
"PKG-DANMUKU-02",
@@ -5135,7 +5141,11 @@
"evidence": [
"refactor/baselines/danmuku-contract.md",
"refactor/baselines/danmuku-contract-validation.json",
"refactor/baselines/danmuku-release.json"
"refactor/baselines/danmuku-release.json",
"refactor/baselines/danmuku-failures-validation.json",
"test/danmuku-failures.test.js",
"refactor/changes/2026-09-13-PKG-DANMUKU-02-browser-baseline.md",
"refactor/baselines/danmuku-browser-validation.json"
],
"compatibleResolution": "Use isolated timeout-protected reproduction for narrow dimensions, then define finite sampling and per-instance rendering.",
"closureCriteria": "Narrow widths terminate, points/config behavior is explicit and multiple SVG/control instances remain independent."
@@ -5155,6 +5165,25 @@
],
"compatibleResolution": "Use actual archive identity, preserve missing historical Git information and audit icon source/notice obligations.",
"closureCriteria": "Candidate tarball paths, complete module forms and icon/source provenance are explicitly reviewed; unresolved history is not invented."
},
{
"id": "DANMUKU-TRACK-01",
"title": "Native simultaneous fixed Danmuku comments can overlap with duplicate start loops and repeated Worker IDs",
"confirmation": "reproduced",
"status": "open",
"owners": [
"PKG-DANMUKU-04",
"PKG-DANMUKU-05",
"PKG-DANMUKU-07"
],
"evidence": [
"refactor/changes/2026-09-13-PKG-DANMUKU-02-browser-baseline.md",
"refactor/baselines/danmuku-browser-validation.json",
"test/browser/danmuku-baseline.spec.js",
"test/danmuku-failures.test.js"
],
"compatibleResolution": "Enforce one owned scheduler loop and request correlation before claiming simultaneous native anti-overlap stability; keep strict track geometry tests.",
"closureCriteria": "Deterministic duplicate-loop/worker regressions and repeated candidate native simultaneous-load geometry pass without extra nodes or stale state; a later passing old snapshot alone does not close the race."
}
]
}
+8 -3
View File
@@ -3278,11 +3278,16 @@
"ENG-05",
"ENG-08"
],
"status": "doing",
"status": "done",
"risk": "H",
"deliverable": "密集/稀疏弹幕、过滤/异步输入、seek/倍率/重载测试",
"acceptance": "轨道选择、发射顺序、事件、内存和可视结果可重跑",
"evidence": []
"evidence": [
"changes/2026-09-13-PKG-DANMUKU-02-controlled-failures.md",
"baselines/danmuku-failures-validation.json",
"changes/2026-09-13-PKG-DANMUKU-02-browser-baseline.md",
"baselines/danmuku-browser-validation.json"
]
},
{
"id": "PKG-DANMUKU-03",
@@ -3295,7 +3300,7 @@
"PKG-DANMUKU-02",
"CORE-08"
],
"status": "todo",
"status": "doing",
"risk": "M",
"deliverable": "bilibili/input/parser/config 的分层与取消",
"acceptance": "旧格式、回调、过滤、追加/替换语义保持",