Files
ArtPlayer/refactor/changes/2026-09-11-CORE-14-setting.md
T

19 KiB
Raw Blame History

CORE-14 设置树、渲染与布局

状态:完成。设置目录的 TS 拆分、生命周期、失败恢复、布局和交互已通过最终安装包验收。以下各批记录保留当时的进度与失败原因,当前结论以末尾最终交付证据为准。

已接入的源码

setting/model.ts 管理树遍历、查找、结构预检、自动名称及父级绑定。setting/index.ts 的 traverse/format/find 委托该模型;仍保留按选项数组缓存面板的专用管理器,不把它强行套进 Control 返回类型。add/update 返回原条目、remove 返回 undefined、find 缺失返回 null;当前公开 d.ts 保持不变,BASE-TYPE-07 的兼容视图出口仍需 CORE-21 完成。

父级、所在数组、父级数组和事件列表保留非枚举、不可配置 getter;WeakMap 允许同一条目从旧父级移除后重新绑定,getter 函数及事件数组身份保持。遍历保留前序和回调期间添加子节点的可见性。正常显式名称和自动计数规则保留;自动名称遇到整树显式名称时跳过冲突 ID。重复名称、循环/重复条目或不可重定义的外来绑定先预检,不先给前面的条目写入元数据。外部任意 setter/Proxy 抛错的事务边界,以及同时跨活动实例共享同一条目对象,仍需随管理器和资源阶段核对,当前不宣称已覆盖。

setting/layout.ts 将尺寸计算与 DOM 测量分开,面板宽度不超过播放器扣除 padding 后的空间,高度限制在实际控件上方,可滚动访问嵌套内容。padding 从 bottom 的已计算样式读取,支持 CSS 单位解析;控件中心按播放器缩放换算。正常右侧溢出时保持旧 CSS right 锚点,移动端/旋转分支保留原定位策略。动态尺寸观察、长文本、旋转/移动端和完整旧新组合仍需继续验证。

首批验证与待办

新增 7 项模型与 3 项布局单元测试;类型正反例覆盖保留自定义字段、数字计数器和 nullable 查找。浏览器新旧对照覆盖条目返回/绑定、移动条目、名称冲突、320x180 的超宽嵌套面板及真实点击最后一项。初轮 24 项三浏览器通过并已检查旧新截图:旧面板裁切在容器外,候选可滚动选择。最终锚点兼容调整后,24 项专项复跑通过;yarn ci:check 共 187 项通过(158 单元、4 工程、25 基线),112 个生产 TS 文件严格检查。见 阶段证据。尚未完成整个 CORE-14 或安装包回归。

首批结束时计划迁移 manager/types、selection、render 与内置设置(第二批完成情况见下文),建立条目/面板作用域,处理删除子树、缓存面板更新、过期异步回调和 mounted 定时器。补充失败与重入、默认高亮、长文本、实际窄尺寸变化、旧插件交互,之后构建并验证安装 UMD/legacy、公开类型消费和最终文档。BASE-DOM-02 此时仍 open。

package.json 将 setting-model.test.js 与 setting-layout.test.js 纳入 test:unit;无新增依赖、锁文件或版本变更。任务未完成,尚不提交本任务,不推送或发布。

第二批:渲染、回调与条目资源

render.ts 保留 div/类名、item 的动态 html/icon/tooltip/switch/range 描述符、数据写入和条目身份;管理器入口继续转发 createHeader/createItem/render。selection.ts 保留原 callback this、item、DOM 与 Event,range 的同步值写入和选择 default 标志;按实际写入对象隔离异步结果,兄弟 selector 共用父项代次,更新/删除关闭旧条目作用域。原始失败用 console.warn 报告,不吞掉原异常身份。没有取消用户自己的异步 SDK 工作。

resources.ts 管理条目作用域、DOM 事件与内置 Emitter 订阅。删除/更新父项时递归释放子项并移除其 selector 数组对应的缓存面板;清理失败仍尝试其余事件。注册中重入销毁会释放刚返回的监听器。延迟 mounted 绑定本次条目与 DOM,移除/更新取消旧定时器;mounted 的同步失败或返回 Promise 拒绝会报告,不把其返回值当 disposer。

playbackRate/aspectRatio/flip/subtitleOffset 四个内置设置已迁移 TS;订阅随条目关闭。数值/字符串断言仅对应内置工厂自己创建的 selector 值,不改变运行时转换。6 项资源单元用例与新旧浏览器用例覆盖乱序、更新后写入、拒绝身份、子树缓存/监听器、延迟 mounted、订阅重复及移除。最终同步导航异常保护已通过单元及专项复验;设置专项 60 项三浏览器通过,CI 193 项通过(164 单元、4 工程、25 基线),120 个生产 TS 文件严格检查。见 第二批阶段证据,该记录明确为 partial。

尚待:管理器转 TS 与专用继承类型边界;add/update/渲染失败时的对象、DOM、面板和监听器回滚;子面板 header 的独立失败清理;跨实例共享/复用和非扩展对象预检;动态尺寸观察、长文本、switch/range 与重入/销毁专项;完整核心/旧插件与最终 UMD/legacy 安装产物。不能用当前已通过专项替代这些剩余验收。

第三批:管理器、根事件与失败处理

index.ts 保留实际 Component 原型继承,用最小构造类型视图表达 Setting 自己的数组缓存及返回约定,没有通过双重断言伪装成通用组件。新增管理器类型正反例,验证 add 保留输入自定义字段、find 可为 null、remove 为 void。

events.ts 接管 blur/focus/resize 和尺寸观察,实例关闭后解绑。ResizeObserver 观察播放器与控件;MutationObserver 观察播放器 class/style,并在缺少 ResizeObserver 时补充控件变化。没有 ResizeObserver 的环境仍依赖已有 window/core resize 信号发现外部容器尺寸变化,不能宣称自动发现所有祖先 CSS 修改。

最初动态布局测试三浏览器均失败:宽度已收缩到 300px,但面板高度仍为 124px,目标为 78px。补上 style 观察后仍失败,证实只增加观察不够;设置面板 transition: all 使 getComputedStyle(bottom) 在回调时返回过渡起点。现在额外监听面板自身 bottom 的 transitionend,过渡结束后重算,保持现有动画。6 项原生观察/回退专项通过,随后完整设置专项 72 项通过;销毁后晚到观察与 resize 均不调用管理器。

第三批 yarn ci:check 194 项通过(165 单元、4 工程、25 基线),122 个生产 TS 文件严格检查;设置专项 72 项为当前工作区构建,三浏览器无重试、跳过或未处理异常。源码、报告、候选构建及失败记录指纹见 第三批阶段证据,仍明确为 partial。

formatTree 新增非扩展对象和不可写自动名称预检,重复名称保持原 ArtPlayerError。add 失败移除本次追加位置;格式化成功后才释放新条目的部分渲染资源,避免无效共享子树触及已有监听器。remove 即使清理失败也继续移除原 DOM 并恢复根面板,再汇总异常。资源树释放有已访问集合,避免外部后续构造循环导致无限递归。

浏览器失败注入覆盖重复名称、同一对象/共享子项、不可扩展对象、html getter 抛错、渲染阶段抛错后的 mounted 取消、再次添加和旧条目可用性。移除失败测试的首版直接向 $events 塞入任意函数,但真实 Events.remove 只处理登记过的监听器,导致三项断言失败;现改为真实 art.proxy 登记与 event-removal 钩子注入,验证原错误身份、后续清理、DOM 删除和兄弟条目均正常。保留失败日志,不以假函数改变生产事件约定。

仍未解决的边界:update 的原对象/描述符/监听器事务恢复、面板创建失败后的缓存与 header 独立清理、重入时的归属以及跨活动实例共享条目。任意 getter/setter/Proxy 的外部副作用不能承诺通用回滚;失败后的新输入可能保留已安装的隐藏元数据。长文本、switch/range、移动端/旋转、完整旧插件组合和最终安装包仍需验收。前两批阶段记录保留当时源码路径与指纹,不改写为最新完成证据。

第四批:面板作用域与新面板渲染恢复

panels.ts 管理按选项数组缓存的面板作用域,条目作用域挂到所属面板;返回按钮由面板持有,并仍登记在父项的公开 $events 数组中。失败、删除子树或销毁时释放其监听器、延迟 mounted、缓存和 DOM。清理返回按钮时从原事件数组移除对应登记,不影响父项其他监听器,也不重复移除已被父项释放的监听器。

checkpoint.ts 不调用用户 getter,保存条目的原属性描述符及直接传入 html/icon/tooltip 的节点位置。新面板创建若在 header、条目或 resize 阶段抛错,释放部分面板,恢复原输入节点和描述符、之前活动面板以及 height/width/left/right,调用者仍收到原始错误。归属检查避免恢复已经由别的面板接管的条目;创建 header 时重入删除父项或销毁实例,后续条目不会继续创建。该阶段没有把这些保证扩展为所有 update 或任意用户重入均已解决。

新增 15 项三浏览器测试,覆盖三种失败阶段、失败后正常重试、原 DOM 节点身份与位置、mounted 不重复、父项监听器数量、返回按钮和删除后的迟到点击,以及 header 创建中的 remove/destroy 重入。设置专项共 87 项通过。初次测试在回滚后等待定时器才比较 style,与正常 ResizeObserver 后续布局混在一起,九项失败;分开记录同步回滚和下一轮布局后,证实同步恢复正确。布局失败注入钩子随后也需在同步调用结束后撤销,避免测试自己的异常污染异步观察器。保留两轮失败报告和前后样式附件,未放宽未处理错误检查。

第四批 CI 194 项通过(165 单元、4 工程、25 基线),124 个生产 TS 文件严格检查。完整工作区 UMD 三浏览器 429 项通过,含设置 87 项以及现有播放、切源、章节插件、全屏、生命周期等检查;无重试、跳过或未处理异常。专项与完整运行的候选构建指纹一致,见 第四批阶段证据。这是当前工作区构建证据,不能替代最终安装包和 legacy 验收。

仍需完成:已缓存面板切换及 update 的失败/重入恢复、跨实例条目复用、长文本与 switch/range、移动端/旋转、最终安装 UMD/legacy 回归和包指纹核对。CORE-14 继续 doing,风险尚未关闭,未提交本任务。

第五批:设置项 update 事务与重入

update.ts 保留原条目身份和返回值,在赋值前暂停旧子树,渲染成功后才释放旧资源。resources.ts 让暂停的作用域暂存旧监听器,公开 $events 数组身份不变,新一代登记写入原数组;activity.ts 阻止暂停期间的旧回调及异步写入。回滚恢复原监听器,不重新登记,也不重复执行已经运行的 mounted;成功则释放旧代,新代继续工作,销毁时两代都释放。

checkpoint.ts 保存框架管理的 switch/range 闭包状态,恢复 range 原数组引用、内容和原生 input 的边界、步进及值;DOM 检查点恢复实际旧节点及其属性,不用克隆节点替代原节点。赋值、整树校验、条目渲染或最终 render 失败时恢复这些受管理状态,调用者仍收到原错误。提交后若旧资源清理异常,保留已经成功的新行并报告清理错误,不假装已释放的旧资源还能恢复。

按 Reflect.ownKeys 的顺序读取可枚举自有字段,保留通常的 Object.assign 读写顺序,同时在每个用户读取/写入之后检查当前操作。重入新 update、remove、destroy 或后代 update 会终止旧操作;删除祖先先取消其后代的未完成更新。渲染持有自己的操作/作用域,旧 getter 在新行完成后继续返回或抛错,也不能覆盖新句柄或清理新行。任意自定义 setter/Proxy 的外部副作用,以及任意覆写方法在返回前自行发起的额外操作,不能承诺通用回滚。

4 项新增资源单元检查覆盖恢复原登记、只提交新代、销毁两代及清理异常仍恢复旧监听器。新增独立 setting-update.spec.js,覆盖四个失败阶段的 range/DOM/监听器身份、失败后重试、switch 显示状态、同项和父子重入、祖先删除,以及 icon/switch/range 渲染 getter 的重入。此前 87 项设置专项和第一轮新增 27 项均通过;扩展重入检查后的 123 项也通过。最后补充的控制句柄检查随本轮完整运行验证,以下阶段证据以最终完整运行指纹为准,不把较早专项当作最后源码的证据。

第五批最终 CI 198 项通过(169 单元、4 工程、25 基线),126 个生产 TS 文件严格检查;工作区 UMD 完整三浏览器 471 项通过,其中设置相关 129 项,无重试、跳过或未处理异常。见 第五批阶段证据,包含最终源码/测试/构建和报告指纹。尚未运行本任务最终安装包和 legacy 验收。

仍需完成:直接切换已缓存面板时的失败恢复、跨实例共享/复用、长文本与完整 switch/range 交互、移动端/旋转、最终安装 UMD/legacy 与打包类型验收。当前公开 d.ts 未变,CORE-14 仍 doing,不关闭风险、不提交未完成任务。

第六批:缓存导航恢复与实例归属

render 的缓存分支现在也处理 resize 失败,恢复之前的活动面板及布局属性,保留缓存 DOM 和监听器。每次导航有独立代次;失败前若重入导航、删除面板或销毁实例,外层失败不再覆盖较新的结果。导航专项最初三项失败源于测试假定根面板与子面板尺寸必不相同,实际两者此时均为两行;活动面板和 class 断言证明重入导航正确,尺寸相等不是回滚的证据。修正该断言并保留初轮报告。

实际旧/新对照复现 BASE-DOM-08:同一条目给两台活动播放器使用,旧发布版的第二台没有条目,但第一台仍可点击;归属保护前的候选会重新绑定到第二台并释放第一台监听器。现在整树预检拒绝仍由另一活动树持有的条目,抛出 ArtPlayerError,两个树及先前监听器都不修改。没有静默克隆条目,因为那会改变 add/update 返回原对象及回调引用约定。此前这种共享本身不能正常显示两台播放器,因此登记为旧缺陷修正;同时显示时使用各自的条目对象,回调函数仍可共用。

owner 状态不直接保存播放器或 manager 对象,销毁时清空树和作用域引用,避免绑定保留旧实例。关闭中的作用域也视为非活动;旧树 remove 或实例 destroy 后,原条目/子树可交给另一实例使用,父级绑定随之更新,隐藏 getter 与 $events 数组身份保留,原实例晚到清理不会影响新实例。新增两项模型单元和 24 项归属/导航三浏览器检查,均通过;包含冲突 add 不改旧树、原对象移交、旧节点迟到点击及新回调 this。

第六批最终 CI 200 项通过(171 单元、4 工程、25 基线),126 个生产 TS 文件严格检查;工作区 UMD 完整三浏览器 495 项通过,其中设置相关 153 项,无重试、跳过或未处理异常。见 第六批阶段证据,保留旧/新共享对象的初始诊断和最终构建指纹。

仍需完成长文本、完整 switch/range 原生交互、移动端/旋转,以及 CORE-14 最终安装 UMD/legacy、类型消费和文件指纹验收。BASE-DOM-08 与其他 CORE-14 风险保持 open,任务保持 doing。

第七批:原生交互、长文本与旋转

setting-interaction.spec.js 使用真实键盘与指针事件核对 range 的 input/change 次序、每次同步值、回调 this/条目/DOM 与最终 tooltip,并用真实点击切换 switch。移动 UA/视口与触摸事件结合本地视频和实际内置 autoOrientation,验证正常与旋转状态的嵌套菜单滚动和最后一项选择;没有把这些测试标成实体手机验收。

长文本初轮在三个引擎复现控件被挤出行内,旧版与候选都存在。setting.less 让标签与提示缩短显示,给原生控件及图标保留宽度,并保留左右内容间隔;文本仍完整保留在 DOM。已检查旧/新长文本和旋转截图,新版 range/switch 可见且可通过键盘/指针操作。交互专项 18 项通过;额外 add 重入检查合入后,交互与更新两组共 66 项通过。

收尾审查补上 registration.ts:外层 add 的 getter 在内层成功 add/update 同一对象后抛错时,旧操作不能移除新行。记录新的注册归属,remove/update 使旧注册失效;保留外层原始异常及内层成功结果。最终打包验收将覆盖最新源码,不以此前局部运行替代它。

本任务的完整浏览器矩阵指仓库现有核心、历史核心及章节插件组合和契约套件;全部生态包/SDK 的专项迁移与最终发布矩阵仍由对应后续任务负责。BASE-TYPE-07 保持开放至 CORE-21 的兼容公开类型出口,CORE-14 不伪造运行时返回值来迁就旧声明。

最终交付证据

  • yarn ci:check:200 项通过(171 单元、4 工程、25 基线),127 个生产 TS 文件严格检查;核心 122、chapter 5。
  • 核心构建与 i18n 生成成功。核心/chapter 实际 tarball 仓库外安装:27 项运行时、五组类型零诊断。
  • 实际安装 UMD 与 legacy 各 519 项三浏览器通过,其中各含 177 项设置相关检查;无重试、跳过、flaky 或未处理页面异常。
  • 最终验证记录 核对全部核心源码与构建快照、三个分发格式与 tarball/docs/compiled、公开声明、包内架构文档、22 个语言文件和独立分发许可。阶段失败与原始旧行为记录仍保留。
  • legacy 首次启动时,临时映射中的包路径被重复拼接,服务尚未启动即失败;已改为 Resolve-Path 得到的绝对产物路径,保留启动失败日志。最终验收核对实际映射的包内字节,不把启动失败计作通过或测试重试。
  • 关闭 BASE-DOM-02/06/07/08 与 BASE-LIFE-12/13/14。BASE-TYPE-07 保留给 CORE-15/18/21 等公开类型后续责任;本任务不改变旧公开声明来掩盖实际 item/null/void 返回。
  • 移动端检查采用真实引擎、触摸事件、模拟 UA/视口和实际 autoOrientation,未宣称实体设备、全部外部 SDK、远端 CI 或完整生态发布验收。

本任务独立本地提交,不推送或发布。当前 214 项中 50 完成、164 待办;下一项 CORE-15 字幕获取、解析和渲染。