refactor(multiple-subtitles): [PKG-MULTI-SUB-03] own requests and subtitle resources

This commit is contained in:
Harvey Zhao committed 2026-09-13 11:01:47 +08:00
1 parent 36cd151095
commit beaa93d6cc
25 files changed
+7908 -250

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -0,0 +1,73 @@
# PKG-MULTI-SUB-03 模块边界与资源修复
本次修改生产源码,保持工厂名称/必需参数、async 注册结果、name/tracks/reset、同步 void
选择方法和原分发入口。自有 JS 先按职责拆清,严格 TS 与公开声明仍由 04 完成。
原始 parser、许可和公开类型未改,没有新增依赖或改变包版本。
## 结构变化
| 文件 | 实际职责 |
| --- | --- |
| index.js | 注册编排、名称选择、活跃状态检查和公开返回对象 |
| request.js | 每轨请求、原生状态检查、字节解码与既有核心格式转换 |
| merge.js | 解析元数据和按选择顺序序列化;通过复制 cue 包装文本,原树不变 |
| lifetime.js | 本次注册的 destroy 监听、请求取消、Promise 提前结束与清理登记 |
| render.js | Blob 所有权、新旧 URL 替换、重入保护及宿主 init 失败处理 |
| parser.js | 保持原始 vendor 边界,不因本次拆分改写算法 |
模块依赖由入口向请求/纯解析/安装流动;仅入口和宿主安装/生命周期需要 art,纯 merge
不依赖 DOM、fetch 或播放器。没有引入要求用户升级核心的共享运行时依赖。
## 独立缺陷修正
- 销毁中 fetch/body 通过取消信号和关闭 Promise 结束;无 AbortController 的旧环境仍
能及时结束注册并忽略迟到结果。返回相同形状的失活结果,不新增 destroy 拒绝。
- 单轨失败保留原传输/解码异常身份,关闭整个注册并取消兄弟请求;HTTP ok=false 明确
拒绝且取消未消费的响应,不再把错误页面当作有效字幕。
- 最后 Blob URL 在 destroy 时释放。保留的 tracks/reset 此后返回 undefined,不再
读取名称、分配 URL 或触发宿主。重复 destroy 不重复释放。
- 分配新 URL 成功后才尝试替换;分配失败保留旧 URL。同步 init 失败释放新 URL,
保留先前资源并回滚该次 escape 写入;首次注册失败同时移除监听。
- 观察宿主真实 Promise 的 rejection,释放失败安装对应的 URL,并在活跃时以 console.warn
保留诊断。正常注册仍不等待宿主加载;tracks/reset 仍为 void。宿主核心可能自行显示
notice,这里不引入新公开事件,也不假装异步错误会从旧 void 方法同步抛出。
- 老 init 的迟到错误不释放后来成功替换的资源;同步重入选择、配置读取失败,以及
用户 getter/init 中触发 destroy 都有明确归属检查。
异步 init 失败发生时,宿主可能已经更新自身状态;插件不能通用回滚第三方宿主的副作用。
此时释放失败资源,保留旧异步接口时序并记录错误;调用方可在仍活跃时重新 reset。
正常 destroy 不恢复共享 subtitle.escape,避免覆盖后续插件/用户的配置。
## 保留的兼容边界
1. 采用已发布 1.2.0 的逐轨连接语义;没有恢复 1.0.0 按下标丢 cue 的缺陷。
2. 轨内 parser 排序、轨间选择顺序、同名取第一个、重复选择、未知名 TypeError、空轨、
onParser 未执行,以及坏 header 仍可保留可用 cue 的容错均保留。
3. option.type 优先、当前核心 SRT/ASS 转换、encoding 默认与原生解码行为保持。
轨元数据在下载结束后读取;restart 不重新下载字幕,配置在每次安装时读取。
4. 不再调用无实际资源的 revokeObjectURL('')。历史测试仍断言旧调用记录,候选正常
测试仅对这一项无资源清理差异作明确区分,不放宽真实 URL 的释放断言。
5. 合并不再原地标记 updated/改 cue;冻结树重复序列化测试和九种真实旧产物逐字对照
证明输出保持,另对实际核心转换和 Windows-1252/UTF-16LE 字节逐字比较。
## 验证与限制
命令及准确运行结果、输入指纹、原生浏览器观察见
[验证记录](../baselines/multiple-subtitles-resources.json)。新生命周期/merge 文件接入
test:unit 与 test:multiple-subtitles,生产三入口由正常 yarn build 生成。
浏览器矩阵使用发布/候选核心、Chromium/Firefox/Windows WebKit 和源码/现代/legacy
插件,覆盖 SRT 显示/选择、挂起请求销毁、原生 Blob 不可访问、HTTP 失败及真实视频切源。
其中资源/错误场景直接执行公开注册函数,显示与切源场景使用真实 plugins.add。
最终本包 241 项通过;源码/main/legacy 各 31 项通过(其中冻结树纯函数用例固定读取源码,
其余正常/生命周期/转换对照通过选定入口)。三入口原生浏览器各 30 项,共 90 项通过。
完整 CI 2311 项通过:1963 单元、14 工程、334 基线;严格生产 TS 仍 346 文件。
状态更新后 9 项风险/契约元数据测试通过。显式 lint 无错误或警告;全量 lint 仍有既有
生成声明 unused-disable 警告。实际 ESM 只验证导出形状和工厂,不冒充完整安装消费者。
这不是全部历史核心、实体 Safari/移动设备、ASS 原生显示、样式/编辑器或 npm 发布准入。
HOST/HTTP 在本次边界回归后关闭;LIFE/MERGE 的完整支持范围组合仍由 05 补齐。
每项状态以 tasks/risks 与验证记录为准;后续 04 迁移 TS 时重跑相同生产入口用例。
独立本地任务提交,不推送、不发布。回退本提交恢复旧单文件和生成产物,同时重新引入
02 已复现的泄漏/失败行为;02 历史基线及浏览器证据保留。
+3 -2
View File
@@ -4,7 +4,7 @@
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 222 项,范围 22 个包及工作区/示例。
状态:todo 90 / doing 13 / blocked 0 / done 119 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
状态:todo 89 / doing 13 / blocked 0 / done 120 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
@@ -218,7 +218,7 @@
| --- | --- | --- | --- | --- | --- | --- |
| PKG-MULTI-SUB-01 | artplayer-plugin-multiple-subtitles<br>核对包契约与历史用法 | BASE-05 | subtitles/onParser、multipleSubtitles 名称及实际返回方法 | 源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结;接续 VENDOR-03,定位 WebVTT parser 来源/修订及 CC0 头,保留解析/序列化行为 | H | done |
| PKG-MULTI-SUB-02 | artplayer-plugin-multiple-subtitles<br>建立特有行为与错误测试 | PKG-MULTI-SUB-01, ENG-03, ENG-05 | VTT/SRT/ASS、编码/重叠 cue/排序/空轨/失败与切换 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | done |
| PKG-MULTI-SUB-03 | artplayer-plugin-multiple-subtitles<br>整理内部职责与资源 | PKG-MULTI-SUB-02, CORE-15 | 解析与合并/获取/渲染分离,过期请求及对象 URL 清理 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | todo |
| PKG-MULTI-SUB-03 | artplayer-plugin-multiple-subtitles<br>整理内部职责与资源 | PKG-MULTI-SUB-02, CORE-15 | 解析与合并/获取/渲染分离,过期请求及对象 URL 清理 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | done |
| PKG-MULTI-SUB-04 | artplayer-plugin-multiple-subtitles<br>迁移自有源码和公开类型 | PKG-MULTI-SUB-03, ENG-04, ENG-06, CORE-07 | 准确 parser/cue/tree/result 类型与真实异步形状 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | todo |
| PKG-MULTI-SUB-05 | artplayer-plugin-multiple-subtitles<br>验证新旧核心和组合 | PKG-MULTI-SUB-04, CORE-22 | 与核心字幕/偏移/全屏组合,旧名称调用不变 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | todo |
| PKG-MULTI-SUB-06 | artplayer-plugin-multiple-subtitles<br>验证分发并同步文档 | PKG-MULTI-SUB-05, ENG-07 | multiple.subtitles.js、parser 来源许可及打包边界 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | H | todo |
@@ -513,6 +513,7 @@
- PKG-DASH-05: [记录](changes/2026-09-12-PKG-DASH-05-sdk-checkpoint.md) [记录](baselines/dash-sdk.json) [记录](baselines/dash-sdk-checkpoint.json) [记录](dash-validation.md) [记录](changes/2026-09-12-PKG-DASH-05-sdk-types.md) [记录](baselines/dash-sdk-types-validation.json) [记录](changes/2026-09-12-PKG-DASH-05-sdk-events.md) [记录](baselines/dash-sdk-events-validation.json) [记录](changes/2026-09-12-PKG-DASH-05-seek-diagnosis.md) [记录](baselines/dash-seek-diagnosis.json)
- PKG-MULTI-SUB-01: [记录](baselines/multiple-subtitles-release.json) [记录](baselines/multiple-subtitles-contract.md) [记录](baselines/multiple-subtitles-contract-validation.json) [记录](changes/2026-09-13-PKG-MULTI-SUB-01-contract.md)
- PKG-MULTI-SUB-02: [记录](baselines/multiple-subtitles-failures.json) [记录](changes/2026-09-13-PKG-MULTI-SUB-02-failures.md)
- PKG-MULTI-SUB-03: [记录](baselines/multiple-subtitles-resources.json) [记录](changes/2026-09-13-PKG-MULTI-SUB-03-resources.md)
- PKG-ADS-01: [记录](baselines/ads-release.json) [记录](baselines/ads-contract.md) [记录](baselines/ads-contract-validation.json) [记录](changes/2026-09-12-PKG-ADS-01-contract.md) [记录](scripts/ads-contract.test.mjs)
- PKG-ADS-02: [记录](changes/2026-09-12-PKG-ADS-02-tests.md) [记录](ads-validation.md) [记录](baselines/ads-validation.json)
- PKG-ADS-03: [记录](changes/2026-09-12-PKG-ADS-03-lifecycle.md) [记录](ads-validation.md) [记录](baselines/ads-lifecycle-validation.json)
+17
View File
@@ -1,5 +1,22 @@
# 进度与证据
## PKG-MULTI-SUB-03 模块与资源修复完成
生产源码拆为入口、请求、纯解析合并、生命周期和宿主安装五个模块,vendor parser 不变。
修复 HTTP 失败、兄弟请求取消、fetch/body 销毁中结算、Blob 泄漏、分配失败替换顺序、
同步/异步安装失败与重入归属;保留 async 注册与 void tracks/reset、轨序、元数据和容错。
九种 markup/timing/空轨输入及真实转换/编码逐字对照已发布 1.2.0,冻结树重复序列化通过。
源码/main/legacy 各 31 项通过;本包 241 项通过,两新增文件已接入主 test:unit。
三入口配发布/候选核心,在 Chromium/Firefox/Windows WebKit 共 90 项通过:真实 SRT、
选择/清空/reset、请求销毁、Blob 不可访问、HTTP 失败和真实视频切源无重复字幕下载。
完整 CI 2311 项通过(1963 单元、14 工程、334 基线);严格生产 TS 仍 346,04 继续 TS。
正常生产构建及实际 ESM 导入通过,三个 dist 与 docs/compiled 对应字节一致。
HTTP/HOST 风险关闭;LIFE/MERGE 完整支持范围组合仍待 05。见
[变更](changes/2026-09-13-PKG-MULTI-SUB-03-resources.md)和[验证](baselines/multiple-subtitles-resources.json)。
222 项:120 done、13 doing、89 todo;196 项风险。独立本地提交,不推送、不发布。
下一步 MULTI-SUB-04 自有模块严格 TS 与旧消费者公开类型;VTT 类型取舍继续待决。
## PKG-MULTI-SUB-02 错误与生命周期复现完成
9 份历史实现各 18 类异常/边界,共 162 项;本包命令及主 test:unit 已接入,
+2 -2
View File
@@ -198,5 +198,5 @@
| MULTI-SUB-MERGE-01 | open / 已复现 | 1.0.0 merges cues by index while later versions concatenate independently timed track cues | PKG-MULTI-SUB-02, PKG-MULTI-SUB-03, PKG-MULTI-SUB-05 |
| MULTI-SUB-LIFE-01 | open / 已复现 | Pending downloads and final object URL have no destroy owner | PKG-MULTI-SUB-02, PKG-MULTI-SUB-03, PKG-MULTI-SUB-05 |
| MULTI-SUB-EXPORT-01 | open / 已复现 | Older CommonJS default objects conflict with export-assignment declarations; latest exports a direct factory | PKG-MULTI-SUB-04, PKG-MULTI-SUB-06 |
| MULTI-SUB-HTTP-01 | open / 已复现 | HTTP error responses with parseable bodies are installed as subtitles | PKG-MULTI-SUB-03, PKG-MULTI-SUB-05 |
| MULTI-SUB-HOST-01 | open / 已复现 | Subtitle init rejections are ignored and failed installation or URL replacement leaks or invalidates resources | PKG-MULTI-SUB-03, PKG-MULTI-SUB-05 |
| MULTI-SUB-HTTP-01 | resolved / 已复现 | HTTP error responses with parseable bodies are installed as subtitles | PKG-MULTI-SUB-03, PKG-MULTI-SUB-05 |
| MULTI-SUB-HOST-01 | resolved / 已复现 | Subtitle init rejections are ignored and failed installation or URL replacement leaks or invalidates resources | PKG-MULTI-SUB-03, PKG-MULTI-SUB-05 |
+48 -10
View File
@@ -4279,10 +4279,16 @@
"test/multiple-subtitles-failures.test.js",
"test/browser/multiple-subtitles-history.spec.js",
"refactor/baselines/multiple-subtitles-failures.json",
"refactor/changes/2026-09-13-PKG-MULTI-SUB-02-failures.md"
"refactor/changes/2026-09-13-PKG-MULTI-SUB-02-failures.md",
"refactor/baselines/multiple-subtitles-resources.json",
"refactor/changes/2026-09-13-PKG-MULTI-SUB-03-resources.md",
"test/multiple-subtitles-lifecycle.test.js",
"test/multiple-subtitles-merge.test.js",
"test/browser/multiple-subtitles-lifecycle.spec.js"
],
"compatibleResolution": "Keep historical merge profiles explicit and test real overlap/timing before choosing compatibility behavior.",
"closureCriteria": "Unaligned lengths, overlap, sorting, names and real subtitle display across supported cores are verified."
"closureCriteria": "Unaligned lengths, overlap, sorting, names and real subtitle display across supported cores are verified.",
"workspaceState": "Candidate resource fixes and serialization parity are verified in task 03. This risk remains open for the complete supported-core/device coverage owned by task 05."
},
{
"id": "MULTI-SUB-LIFE-01",
@@ -4302,10 +4308,16 @@
"test/multiple-subtitles-failures.test.js",
"test/browser/multiple-subtitles-history.spec.js",
"refactor/baselines/multiple-subtitles-failures.json",
"refactor/changes/2026-09-13-PKG-MULTI-SUB-02-failures.md"
"refactor/changes/2026-09-13-PKG-MULTI-SUB-02-failures.md",
"refactor/baselines/multiple-subtitles-resources.json",
"refactor/changes/2026-09-13-PKG-MULTI-SUB-03-resources.md",
"test/multiple-subtitles-lifecycle.test.js",
"test/multiple-subtitles-merge.test.js",
"test/browser/multiple-subtitles-lifecycle.spec.js"
],
"compatibleResolution": "Reproduce stale completion and own requests and URLs without changing public selection methods.",
"closureCriteria": "Cancellation, failures, source changes, repeated selection and destroy are verified with native core coverage."
"closureCriteria": "Cancellation, failures, source changes, repeated selection and destroy are verified with native core coverage.",
"workspaceState": "Candidate resource fixes and serialization parity are verified in task 03. This risk remains open for the complete supported-core/device coverage owned by task 05."
},
{
"id": "MULTI-SUB-EXPORT-01",
@@ -4331,7 +4343,7 @@
"compatibleResolution": "Reject actual HTTP failures with explicit diagnostics while preserving successful conversion and original transport errors.",
"closureCriteria": "Native HTTP errors, transport/body failures, sibling cancellation and successful requests have candidate regressions.",
"confirmation": "reproduced",
"status": "open",
"status": "resolved",
"owners": [
"PKG-MULTI-SUB-03",
"PKG-MULTI-SUB-05"
@@ -4340,8 +4352,21 @@
"test/multiple-subtitles-failures.test.js",
"test/browser/multiple-subtitles-history.spec.js",
"refactor/baselines/multiple-subtitles-failures.json",
"refactor/changes/2026-09-13-PKG-MULTI-SUB-02-failures.md"
]
"refactor/changes/2026-09-13-PKG-MULTI-SUB-02-failures.md",
"refactor/baselines/multiple-subtitles-resources.json",
"refactor/changes/2026-09-13-PKG-MULTI-SUB-03-resources.md",
"test/multiple-subtitles-lifecycle.test.js",
"test/multiple-subtitles-merge.test.js",
"test/browser/multiple-subtitles-lifecycle.spec.js"
],
"resolutionEvidence": [
"refactor/baselines/multiple-subtitles-resources.json",
"refactor/changes/2026-09-13-PKG-MULTI-SUB-03-resources.md",
"test/multiple-subtitles-lifecycle.test.js",
"test/multiple-subtitles-merge.test.js",
"test/browser/multiple-subtitles-lifecycle.spec.js"
],
"resolutionRationale": "HTTP failures reject before body consumption and abort their requests. Exact transport/body errors, sibling cancellation, conversion success and native 404 rejection pass candidate regressions; source/main/legacy run with both core fixtures."
},
{
"id": "MULTI-SUB-HOST-01",
@@ -4349,7 +4374,7 @@
"compatibleResolution": "Own installation results and URL rollback while preserving void selection methods and normal registration timing.",
"closureCriteria": "Synchronous and asynchronous host failures, stale rejection, allocation failure and destroy leave no plugin-owned live resources.",
"confirmation": "reproduced",
"status": "open",
"status": "resolved",
"owners": [
"PKG-MULTI-SUB-03",
"PKG-MULTI-SUB-05"
@@ -4358,8 +4383,21 @@
"test/multiple-subtitles-failures.test.js",
"test/browser/multiple-subtitles-history.spec.js",
"refactor/baselines/multiple-subtitles-failures.json",
"refactor/changes/2026-09-13-PKG-MULTI-SUB-02-failures.md"
]
"refactor/changes/2026-09-13-PKG-MULTI-SUB-02-failures.md",
"refactor/baselines/multiple-subtitles-resources.json",
"refactor/changes/2026-09-13-PKG-MULTI-SUB-03-resources.md",
"test/multiple-subtitles-lifecycle.test.js",
"test/multiple-subtitles-merge.test.js",
"test/browser/multiple-subtitles-lifecycle.spec.js"
],
"resolutionEvidence": [
"refactor/baselines/multiple-subtitles-resources.json",
"refactor/changes/2026-09-13-PKG-MULTI-SUB-03-resources.md",
"test/multiple-subtitles-lifecycle.test.js",
"test/multiple-subtitles-merge.test.js",
"test/browser/multiple-subtitles-lifecycle.spec.js"
],
"resolutionRationale": "Owned installations retain prior URLs on synchronous failure, observe async rejections, release the failed active URL without affecting newer installs, and clean up on destroy. Controlled sync/async/reentrant/getter failures and native Blob revocation pass; void methods and registration timing are preserved."
}
]
}
+5 -2
View File
@@ -2297,11 +2297,14 @@
"PKG-MULTI-SUB-02",
"CORE-15"
],
"status": "todo",
"status": "done",
"risk": "H",
"deliverable": "解析与合并/获取/渲染分离,过期请求及对象 URL 清理",
"acceptance": "结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过",
"evidence": []
"evidence": [
"baselines/multiple-subtitles-resources.json",
"changes/2026-09-13-PKG-MULTI-SUB-03-resources.md"
]
},
{
"id": "PKG-MULTI-SUB-04",