refactor(core): CORE-09 isolate source operations and settle cancelled switches

This commit is contained in:
Harvey Zhao committed 2026-09-11 02:34:26 +08:00
1 parent 874dac9f22
commit 44f4e083a9
29 files changed
+4512 -255

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -0,0 +1,49 @@
# CORE-09 URL 与切源操作
状态:完成;源码、生成产物、安装消费与本地三浏览器检查通过。全项目发布验收仍待后续任务。
## 行为决策
涉及 API-02/03/04/05/07/12。旧 switchUrl/switchQuality 返回 Promise<void>,无取消结果类型。保持方法名、描述符、绑定行为、switch setter 与 switchUrl 的函数身份;保持严格字符串同 URL 快速返回。
每次真实 URL 赋值创建内部操作作用域。新的 switch 或直接 art.url 赋值使旧操作失效,销毁清理所有操作。被替代/销毁的 Promise 以 undefined 正常兑现,不新增 AbortError 拒绝;兑现仅表示该调用已结束,不能证明资源曾成功激活。需要确认当前源的应用仍通过 art.url、媒体事件及当前状态判断。实际媒体错误与 customType 抛出/拒绝保留原错误值;内部恢复播放失败仍正常结束切换,公开 play() 的拒绝不改变。
连续切源时只允许最新操作恢复位置、速率、比例、清理通知和发出 restart。普通原生事件注册顺序保持;源 setter 或 customType 同步发出媒体事件时,暂存到赋值完成后处理,防止先前遗漏。仅清除本操作监听器,不清空用户 Emitter 订阅。空 URL 保持旧 loading 行为且不替换媒体源;对应 switch 调用结束,不无限等待一个没有启动的加载。
## 模块
- player/urlMix.ts:公开 URL 描述符、customType 调用及 restart。
- player/switchMix.ts:公开切源方法门面。
- source/types.ts:最小媒体、宿主、事件和方法类型。
- source/operation.ts:当前操作、URL 赋值令牌、失效与失败。
- source/listen.ts:操作拥有的事件订阅与单次调用。
- source/switch.ts:切源、事件暂存、状态恢复和 Promise 结算。
## 兼容边界与责任
customType 保留真实 video、art、this 和三个参数,不用代理对象替换。其内部已启动的 SDK、请求或用户 Promise 可以继续访问真实对象;核心只能取消尚未调用的回调、忽略过期返回/拒绝并清理自身订阅,不能声称取消任意外部代码。直接 URL 赋值没有可消费的 Promise,当前回调错误通过带原错误值的 console.warn 报告;switch 调用通过自身 Promise 拒绝报告。
媒体事件本身没有操作 ID;customType/proxy 仍负责让自己的事件与当前资源一致。核心的操作身份检查不能鉴别第三方继续向真实 video 或 art 发送的伪装成当前事件的过期回调。
补测真实 playMix 曾复现旧恢复把新通知覆盖成 Play;因此 playMix 也捕获当前源身份,晚到结果仍按原值兑现或拒绝,但不再写通知、发 play 或触发互斥暂停。同步正常路径及公开返回值保持。测试既使用受控覆盖函数,也使用实际 playMix,不能用前者代替后者。
旧 URL 的 revokeObjectURL 行为暂保留;对象 URL 的完整归属审计归 CORE-19。播放模块其余迁移归 CORE-10;过期重连归 CORE-11。不要把本任务的操作监听隔离当作这些模块也已全部处理。
## 验证与交付
证据见 [source-operations-validation.json](../baselines/source-operations-validation.json),记录完整源码/测试/包文件 SHA、安装检查、浏览器版本与逐项结果。
| 验证 | 结果 |
| --- | --- |
| yarn ci:check | 137 项:108 单元、4 工程、25 基线;严格编译 38 个生产 TS 文件 |
| 切源专项 Node | 新增 17 项,覆盖过期、销毁、同 URL、重入、同步事件、错误身份、真实 playMix 和回调身份 |
| 安装包类型 | TS 5.9.3 四组消费模式、TS 4.3.5 一组,均零诊断 |
| 安装包运行时 | 实际 tarball 仓库外安装,27 项通过;范围为核心及 chapter |
| 安装 UMD | Chromium/Firefox/WebKit 共 183 项,通过,无跳过/重试 |
| 安装 legacy | 同一套三浏览器共 183 项,通过,无跳过/重试 |
测试入口:test/source.test.js、test/playback.test.js、test/types/source.ts、test/browser/source.spec.js。BASE-LIFE-01/02/06 已关闭,旧发布基线原样保留。原生 play 的受控拒绝/延迟用于验证 Promise 处理,不作为真实自动播放授权或 codec 支持证明。playMix 补充身份检查前的 180 项 UMD 通过只是阶段证据;最终以包含该修复的 183 项报告及匹配包指纹为准。
未执行远端 GitHub Actions、实体设备或全部生态包发布验收;这些不计为本任务已完成。
不升级版本、不改变依赖和锁文件。本任务完成后单独本地提交。回退按该任务完整提交回退源码、生成产物和文档,不能只恢复 JS 文件而保留调用方的 TS 逻辑。
+3 -2
View File
@@ -4,7 +4,7 @@
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 214 项,范围 22 个包及工作区/示例。
状态:todo 170 / doing 0 / blocked 0 / done 44 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
状态:todo 169 / doing 0 / blocked 0 / done 45 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
@@ -112,7 +112,7 @@
| CORE-06 | artplayer<br>建立内部媒体与宿主类型 | CORE-05 | 原生 video、canvas shim、UI host 类型 | 不更改公开 art.video 用法,不以 HTMLVideoElement 断言掩盖 shim | M | done |
| CORE-07 | artplayer<br>逐项协调公开声明差异 | CORE-02, CORE-06, BASE-07 | plugins/toggle/cue/setting/static 的旧新类型对照 | 每项有兼容重载/扩展或待决结论,不能删除旧类型样例;处理 BASE-TYPE-01/04,分别保留旧合法声明消费并验证真实返回;协调 BASE-TYPE-05 的 Utils 导出、descriptor 和 timer 旧声明差异 | H | done |
| CORE-08 | artplayer<br>整理插件管理器与扩展类型 | CORE-03, CORE-07 | 注册流程、同步/异步结果、插件/事件扩展接口 | 旧插件同步可见性、重名与命名、销毁中异步插件保持明确语义;处理 baselines/lifecycle-coverage.md 的 BASE-LIFE-03 并增加候选正向回归;接续 CORE-07 / BASE-TYPE-04 的同步/异步注册返回声明冲突,内部返回类型精确,保留历史消费者 | H | done |
| CORE-09 | artplayer<br>整理 URL 与切源操作 | CORE-04, CORE-06, CORE-08 | url/switch/customType 的操作身份及取消方案 | 并发切源、错误、同 URL、销毁和 Promise 结算有契约;处理 baselines/lifecycle-coverage.md 的 BASE-LIFE-01/02/06 并增加候选正向回归 | H | todo |
| CORE-09 | artplayer<br>整理 URL 与切源操作 | CORE-04, CORE-06, CORE-08 | url/switch/customType 的操作身份及取消方案 | 并发切源、错误、同 URL、销毁和 Promise 结算有契约;处理 baselines/lifecycle-coverage.md 的 BASE-LIFE-01/02/06 并增加候选正向回归 | H | done |
| CORE-10 | artplayer<br>迁移播放与时间/状态属性 | CORE-09 | play/pause/toggle/seek/volume/rate/duration 等模块 | 旧返回值、拒绝、mutex、位置恢复、属性描述符与事件通过;接续 CORE-07 / BASE-TYPE-04 的 toggle void 与实际 Promise 分支冲突,不吞拒绝 | H | todo |
| CORE-11 | artplayer<br>整理媒体事件、ready 与重连 | CORE-10 | 媒体转发、重连、UI 响应职责分离 | readiness 次数/顺序、过期重连、原错误参数有回归 | H | todo |
| CORE-12 | artplayer<br>迁移模板及公开资源入口 | CORE-06, CORE-04, BASE-04 | template/icons/i18n/style、SSR 与 proxy 挂载 | DOM/CSS/global/样式注入、i18n 子路径及 SSR import 保持;不把 SSR import/useSSR 保持扩大为服务端构造播放器;复跑 BASE-05 的 SSR import/模板、浏览器 useSSR 节点复用和非浏览器构造错误;接续 VENDOR-01/02,核对 screenfull/hint 复制版本、修改与分发通知,保留 DOM/CSS/fullscreen 行为 | H | todo |
@@ -443,6 +443,7 @@
- CORE-06: [记录](changes/2026-09-11-CORE-06-media-hosts.md) [记录](baselines/media-hosts-validation.json)
- CORE-07: [记录](changes/2026-09-11-CORE-07-declarations.md) [记录](baselines/declarations-validation.json)
- CORE-08: [记录](changes/2026-09-11-CORE-08-plugin-manager.md) [记录](baselines/plugins-validation.json)
- CORE-09: [记录](changes/2026-09-11-CORE-09-source-operations.md) [记录](baselines/source-operations-validation.json)
- PKG-CHAPTER-01: [记录](changes/2026-09-10-PKG-CHAPTER-01-contract.md) [记录](baselines/chapter-contract.md)
- PKG-CHAPTER-02: [记录](changes/2026-09-10-PKG-CHAPTER-02-tests.md) [记录](baselines/chapter-validation.json)
- PKG-CHAPTER-03: [记录](changes/2026-09-10-PKG-CHAPTER-03-typescript-modules.md) [记录](baselines/chapter-migration-validation.json)
+4
View File
@@ -1,5 +1,9 @@
# 进度与证据
## 当前实施:CORE-09 URL 与切源操作完成
URL/switch 门面迁移 TS,新增四个 source 模块,统一切源取消、事件清理、同步代理事件和 Promise 结算;真实 playMix 同步接入源身份,避免晚到播放覆盖新状态。137 项 Node/基线、安装 UMD 与 legacy 各 183 项三浏览器检查、打包 27 项运行时和五组类型检查通过。见 [交付](changes/2026-09-11-CORE-09-source-operations.md)。关闭 BASE-LIFE-01/02/06;customType 外部 SDK 清理、对象 URL 归属和过期重连仍由对应后续任务处理。当前 214 项,45 完成、169 待办;核心 33 个 TS 文件、chapter 5 个。下一项 CORE-10 播放与时间/状态属性。
## 当前实施:CORE-08 插件管理器 TS 完成
插件注册、内置装配、命名与内部类型拆成四个 TS 模块;修复销毁后晚到注册,保持 Promise 结算与同步可见性,新增共享类型扩展入口。120 项 Node/基线、安装 UMD 三浏览器 162 项及 legacy 插件/章节/生命周期 90 项通过;严格打包 27 项运行时、五组类型零诊断。见 [交付](changes/2026-09-11-CORE-08-plugin-manager.md)。关闭 BASE-LIFE-03;公开返回声明和各插件自有资源清理仍有后续责任。当前 214 项,44 完成、170 待办;核心 27 个 TS 文件、chapter 5 个。下一项 CORE-09 URL/切源操作。
+3 -3
View File
@@ -4,9 +4,9 @@
| ID | 状态 / 证据等级 | 条目 | 后续任务 |
| --- | --- | --- | --- |
| BASE-LIFE-06 | open / 已复现 | Published switch leaves an unhandled rejection and an unsettled promise when resume fails | CORE-09 |
| BASE-LIFE-01 | open / 已复现 | Superseded switch resolves along with the latest source | CORE-09 |
| BASE-LIFE-02 | open / 已复现 | Switch remains unsettled during the bounded observation after destroy | CORE-09 |
| BASE-LIFE-06 | resolved / 已复现 | Published switch leaves an unhandled rejection and an unsettled promise when resume fails | CORE-09 |
| BASE-LIFE-01 | resolved / 已复现 | Superseded switch resolves along with the latest source | CORE-09 |
| BASE-LIFE-02 | resolved / 已复现 | Switch remains unsettled during the bounded observation after destroy | CORE-09 |
| BASE-LIFE-03 | resolved / 已复现 | Async plugin registers its result after destroy | CORE-08 |
| BASE-LIFE-04 | resolved / 已复现 | Destroying an instance twice unregisters a different live instance | CORE-04 |
| BASE-LIFE-05 | resolved / 已复现 | Failed constructor leaves initialized markup/listeners until explicit probe cleanup | CORE-04 |
+30 -6
View File
@@ -9,7 +9,7 @@
"id": "BASE-LIFE-06",
"title": "Published switch leaves an unhandled rejection and an unsettled promise when resume fails",
"confirmation": "reproduced",
"status": "open",
"status": "resolved",
"owners": [
"CORE-09"
],
@@ -20,13 +20,21 @@
],
"compatibleResolution": "按对应 CORE 任务修复,保持合法旧调用;异步取消需明确结算策略,不把 pending 或重复销毁当正常兼容要求。",
"closureCriteria": "候选正向回归和旧新差异记录通过;有界观察问题不得仅靠延长等待隐藏。",
"workspaceState": "Current switchMix uses silencePromise and test/playback.test.js covers resume rejection. Published baseline still reproduces the old failure; preserve the existing workspace mitigation during migration."
"workspaceState": "Current switchMix uses silencePromise and test/playback.test.js covers resume rejection. Published baseline still reproduces the old failure; preserve the existing workspace mitigation during migration.",
"resolutionEvidence": [
"refactor/changes/2026-09-11-CORE-09-source-operations.md",
"refactor/baselines/source-operations-validation.json",
"test/source.test.js",
"test/playback.test.js",
"test/browser/source.spec.js"
],
"resolutionRationale": "Owned source generations settle superseded/destroyed calls with undefined, prevent stale restart/restoration and actual playMix effects, retain original load failures and best-effort resume settlement. Published baselines remain unchanged; real-media comparisons and controlled native-play tests cover the candidate."
},
{
"id": "BASE-LIFE-01",
"title": "Superseded switch resolves along with the latest source",
"confirmation": "reproduced",
"status": "open",
"status": "resolved",
"owners": [
"CORE-09"
],
@@ -35,13 +43,21 @@
"refactor/baselines/lifecycle-coverage.md"
],
"compatibleResolution": "按对应 CORE 任务修复,保持合法旧调用;异步取消需明确结算策略,不把 pending 或重复销毁当正常兼容要求。",
"closureCriteria": "候选正向回归和旧新差异记录通过;有界观察问题不得仅靠延长等待隐藏。"
"closureCriteria": "候选正向回归和旧新差异记录通过;有界观察问题不得仅靠延长等待隐藏。",
"resolutionEvidence": [
"refactor/changes/2026-09-11-CORE-09-source-operations.md",
"refactor/baselines/source-operations-validation.json",
"test/source.test.js",
"test/playback.test.js",
"test/browser/source.spec.js"
],
"resolutionRationale": "Owned source generations settle superseded/destroyed calls with undefined, prevent stale restart/restoration and actual playMix effects, retain original load failures and best-effort resume settlement. Published baselines remain unchanged; real-media comparisons and controlled native-play tests cover the candidate."
},
{
"id": "BASE-LIFE-02",
"title": "Switch remains unsettled during the bounded observation after destroy",
"confirmation": "reproduced",
"status": "open",
"status": "resolved",
"owners": [
"CORE-09"
],
@@ -50,7 +66,15 @@
"refactor/baselines/lifecycle-coverage.md"
],
"compatibleResolution": "按对应 CORE 任务修复,保持合法旧调用;异步取消需明确结算策略,不把 pending 或重复销毁当正常兼容要求。",
"closureCriteria": "候选正向回归和旧新差异记录通过;有界观察问题不得仅靠延长等待隐藏。"
"closureCriteria": "候选正向回归和旧新差异记录通过;有界观察问题不得仅靠延长等待隐藏。",
"resolutionEvidence": [
"refactor/changes/2026-09-11-CORE-09-source-operations.md",
"refactor/baselines/source-operations-validation.json",
"test/source.test.js",
"test/playback.test.js",
"test/browser/source.spec.js"
],
"resolutionRationale": "Owned source generations settle superseded/destroyed calls with undefined, prevent stale restart/restoration and actual playMix effects, retain original load failures and best-effort resume settlement. Published baselines remain unchanged; real-media comparisons and controlled native-play tests cover the candidate."
},
{
"id": "BASE-LIFE-03",
+5 -2
View File
@@ -911,11 +911,14 @@
"CORE-06",
"CORE-08"
],
"status": "todo",
"status": "done",
"risk": "H",
"deliverable": "url/switch/customType 的操作身份及取消方案",
"acceptance": "并发切源、错误、同 URL、销毁和 Promise 结算有契约;处理 baselines/lifecycle-coverage.md 的 BASE-LIFE-01/02/06 并增加候选正向回归",
"evidence": []
"evidence": [
"changes/2026-09-11-CORE-09-source-operations.md",
"baselines/source-operations-validation.json"
]
},
{
"id": "CORE-10",