mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-28 02:01:20 -08:00
fix(vtt-thumbnail): [PKG-VTT-THUMB-04] preserve historical type shapes
This commit is contained in:
1 parent
c4c7491e16
commit
58d2c95d8e
16 files changed
+235
-57
No files matched your search
@@ -58,21 +58,29 @@ legacy parameter/result/factory extraction, replacement factories and accurate a
|
|||||||
through `/runtime`, including negative cases. The source factory explicitly returns Promise;
|
through `/runtime`, including negative cases. The source factory explicitly returns Promise;
|
||||||
its final assertion only describes the self-reference that Object.assign creates.
|
its final assertion only describes the self-reference that Object.assign creates.
|
||||||
|
|
||||||
Root and legacy use paired `.d.mts`/`.d.cts` default declarations. `/runtime` uses an ESM
|
Root and legacy select the original `.d.ts` shape in every export condition, preserving
|
||||||
default and a CommonJS export assignment, supporting direct and `.default` require calls.
|
latest npm 1.1.0's NodeNext ESM namespace and plain factory replacements. Do not add a
|
||||||
Classic resolution uses `.d.ts` and typesVersions, including TypeScript 4.3. The generated
|
required self alias or silently make the root ESM namespace callable. Previously added
|
||||||
|
root `.d.mts`/`.d.cts` files remain packaged but are not selected by these entrypoints.
|
||||||
|
`/runtime` uses an ESM default and a CommonJS export assignment, supporting direct and
|
||||||
|
`.default` calls. Its Node10 `.d.ts` also uses export=, including raw require without
|
||||||
|
interop on TS 4.3/5.9. Each runtime declaration exports the same four named types.
|
||||||
|
Classic resolution uses typesVersions. The generated
|
||||||
editor global retains the legacy callable type; its RuntimeFactory namespace member is only
|
editor global retains the legacy callable type; its RuntimeFactory namespace member is only
|
||||||
a type, not an additional runtime global. Do not hand-edit generated editor declarations.
|
a type, not an additional runtime global. Do not hand-edit generated editor declarations.
|
||||||
|
|
||||||
The installed-consumer command packs both core and plugin, installs outside the workspace,
|
The installed-consumer command packs both core and plugin, installs outside the workspace,
|
||||||
verifies member hashes, and repeats an offline frozen install. It tests five actual old npm
|
verifies member hashes, and repeats an offline frozen install. It tests five actual old npm
|
||||||
declarations in five modes on TS 4.3/5.9 and seven candidate modes: 32 default-import cells,
|
declarations in five modes on TS 4.3/5.9 and seven candidate modes: 32 default-import cells,
|
||||||
including one expected 1.1.0 NodeNext ESM declaration failure. Candidate ESM passes that cell.
|
including one expected 1.1.0 raw NodeNext ESM declaration failure. Candidate root keeps
|
||||||
|
the old namespace shape and verifies its legal calls and whole-module replacements;
|
||||||
|
accurate direct ESM calls use /runtime. Negative cases are checked at their exact lines.
|
||||||
Another 36 direct/default CommonJS extraction/replacement forms reproduce the opposing 1.0.x
|
Another 36 direct/default CommonJS extraction/replacement forms reproduce the opposing 1.0.x
|
||||||
export-assignment and 1.1.0 default declaration shapes. Candidate preserves the latter.
|
export-assignment and 1.1.0 default declaration shapes. Candidate preserves the latter.
|
||||||
Earlier type-only direct module extraction remains an explicit decision in task 04; a broken
|
Earlier type-only direct module extraction now follows the user's approved rule in
|
||||||
historical JS direct call does not waive that type-only consumer. See the module-forms change
|
../../refactor/type-compatibility-policy.md: keep latest 1.1.0 types and document the
|
||||||
record for the concrete required/optional default-property alternatives and migration proposal.
|
1.0.x export= migration without changing valid JavaScript behavior. Historical failures
|
||||||
|
remain in the installed reports; runtime failures never stand in for type evidence.
|
||||||
|
|
||||||
## Compatibility and intentional fixes
|
## Compatibility and intentional fixes
|
||||||
|
|
||||||
@@ -102,9 +110,9 @@ plugin. Empty or comment-only input remains a valid empty preview.
|
|||||||
|
|
||||||
The exported callable has a writable self `.default` alias, restoring the usable 1.0.x
|
The exported callable has a writable self `.default` alias, restoring the usable 1.0.x
|
||||||
CommonJS default access while retaining direct calls. It does not add a name property to the
|
CommonJS default access while retaining direct calls. It does not add a name property to the
|
||||||
registration Promise. Earlier `thumbnails` control names and remaining historical declaration
|
registration Promise. Earlier `thumbnails` control names are separately frozen and remain
|
||||||
forms are separately frozen and remain compatibility work for tasks 04-06. The full package
|
combination/distribution work for tasks 05-06. The approved declaration migration does not
|
||||||
refactor is not yet finished.
|
complete the remaining package or device acceptance.
|
||||||
|
|
||||||
## Verification and future changes
|
## Verification and future changes
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,33 @@ returned a Promise at runtime. Reading `result.name` requires awaiting registrat
|
|||||||
to `/runtime` opts into that accurate type without changing runtime behavior. The option
|
to `/runtime` opts into that accurate type without changing runtime behavior. The option
|
||||||
object remains required, and its `vtt` and `style` fields remain optional.
|
object remains required, and its `vtt` and `style` fields remain optional.
|
||||||
|
|
||||||
|
The root factory keeps the latest published 1.1.0 type shape, with no required `.default`
|
||||||
|
property. Plain replacement functions remain assignable in both directions. `/runtime`
|
||||||
|
exports `Option`, `Result`, `Factory` and `RuntimeFactory` in all resolution modes; its
|
||||||
|
factory describes the actual writable `.default` self alias and asynchronous registration.
|
||||||
|
|
||||||
|
### Earlier declaration migration
|
||||||
|
|
||||||
|
The 1.0.x declarations used `export =`, while 1.1.0 uses `export default`. Following the
|
||||||
|
approved compatibility policy, the root retains 1.1.0. Older TypeScript code that directly
|
||||||
|
calls or extracts the type of `import vtt = require('artplayer-plugin-vtt-thumbnail')`
|
||||||
|
should use the accurate runtime entry:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import vtt = require('artplayer-plugin-vtt-thumbnail/runtime')
|
||||||
|
|
||||||
|
const register = vtt({ vtt: '/thumbnails/index.vtt' })
|
||||||
|
const result = await register(art)
|
||||||
|
console.log(result.name)
|
||||||
|
```
|
||||||
|
|
||||||
|
This export-assignment form supports Node10 resolution without `esModuleInterop`.
|
||||||
|
Default `/runtime` imports support interoperability and native NodeNext ESM. Root
|
||||||
|
NodeNext ESM intentionally preserves the old declaration namespace shape (the factory
|
||||||
|
is `root.default` after a default import); that historical declaration does not accurately
|
||||||
|
describe the actual ESM export. Use `/runtime` for accurate ESM calls. Valid historical
|
||||||
|
JavaScript default access, the direct factory, and legacy distribution entrypoints remain.
|
||||||
|
|
||||||
See [ARCHITECTURE.md](ARCHITECTURE.md) for module ownership, testing commands and remaining
|
See [ARCHITECTURE.md](ARCHITECTURE.md) for module ownership, testing commands and remaining
|
||||||
compatibility validation.
|
compatibility validation.
|
||||||
|
|
||||||
|
|||||||
@@ -19,24 +19,14 @@
|
|||||||
],
|
],
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
"import": {
|
"types": "./types/artplayer-plugin-vtt-thumbnail.d.ts",
|
||||||
"types": "./types/artplayer-plugin-vtt-thumbnail.d.mts",
|
"import": "./dist/artplayer-plugin-vtt-thumbnail.mjs",
|
||||||
"default": "./dist/artplayer-plugin-vtt-thumbnail.mjs"
|
"require": "./dist/artplayer-plugin-vtt-thumbnail.js"
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"types": "./types/artplayer-plugin-vtt-thumbnail.d.cts",
|
|
||||||
"default": "./dist/artplayer-plugin-vtt-thumbnail.js"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"./legacy": {
|
"./legacy": {
|
||||||
"import": {
|
"types": "./types/artplayer-plugin-vtt-thumbnail.d.ts",
|
||||||
"types": "./types/artplayer-plugin-vtt-thumbnail.d.mts",
|
"import": "./dist/artplayer-plugin-vtt-thumbnail.legacy.js",
|
||||||
"default": "./dist/artplayer-plugin-vtt-thumbnail.legacy.js"
|
"require": "./dist/artplayer-plugin-vtt-thumbnail.legacy.js"
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"types": "./types/artplayer-plugin-vtt-thumbnail.d.cts",
|
|
||||||
"default": "./dist/artplayer-plugin-vtt-thumbnail.legacy.js"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"./runtime": {
|
"./runtime": {
|
||||||
"import": {
|
"import": {
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
import type { RuntimeFactory } from './artplayer-plugin-vtt-thumbnail.js'
|
import type { RuntimeFactory } from './artplayer-plugin-vtt-thumbnail.js'
|
||||||
|
|
||||||
declare const artplayerPluginVttThumbnail: RuntimeFactory
|
declare const artplayerPluginVttThumbnail: RuntimeFactory
|
||||||
|
// eslint-disable-next-line ts/no-redeclare -- Ambient merge exposes types on the CommonJS factory.
|
||||||
|
declare namespace artplayerPluginVttThumbnail {
|
||||||
|
type Option = import('./artplayer-plugin-vtt-thumbnail.js').Option
|
||||||
|
type Result = import('./artplayer-plugin-vtt-thumbnail.js').Result
|
||||||
|
type Factory = import('./artplayer-plugin-vtt-thumbnail.js').Factory
|
||||||
|
type RuntimeFactory = import('./artplayer-plugin-vtt-thumbnail.js').RuntimeFactory
|
||||||
|
}
|
||||||
export = artplayerPluginVttThumbnail
|
export = artplayerPluginVttThumbnail
|
||||||
@@ -2,4 +2,4 @@ import type { RuntimeFactory } from './artplayer-plugin-vtt-thumbnail.js'
|
|||||||
|
|
||||||
declare const artplayerPluginVttThumbnail: RuntimeFactory
|
declare const artplayerPluginVttThumbnail: RuntimeFactory
|
||||||
export default artplayerPluginVttThumbnail
|
export default artplayerPluginVttThumbnail
|
||||||
export type { Option, Result, RuntimeFactory } from './artplayer-plugin-vtt-thumbnail.js'
|
export type { Factory, Option, Result, RuntimeFactory } from './artplayer-plugin-vtt-thumbnail.js'
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
import type { RuntimeFactory } from './artplayer-plugin-vtt-thumbnail.js'
|
import type { RuntimeFactory } from './artplayer-plugin-vtt-thumbnail.js'
|
||||||
|
|
||||||
declare const artplayerPluginVttThumbnail: RuntimeFactory
|
declare const artplayerPluginVttThumbnail: RuntimeFactory
|
||||||
export default artplayerPluginVttThumbnail
|
// eslint-disable-next-line ts/no-redeclare -- Ambient merge exposes types on the CommonJS factory.
|
||||||
export type { Option, Result, RuntimeFactory } from './artplayer-plugin-vtt-thumbnail.js'
|
declare namespace artplayerPluginVttThumbnail {
|
||||||
|
type Option = import('./artplayer-plugin-vtt-thumbnail.js').Option
|
||||||
|
type Result = import('./artplayer-plugin-vtt-thumbnail.js').Result
|
||||||
|
type Factory = import('./artplayer-plugin-vtt-thumbnail.js').Factory
|
||||||
|
type RuntimeFactory = import('./artplayer-plugin-vtt-thumbnail.js').RuntimeFactory
|
||||||
|
}
|
||||||
|
export = artplayerPluginVttThumbnail
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"task": "PKG-VTT-THUMB-04",
|
||||||
|
"status": "done",
|
||||||
|
"capturedAt": "2026-09-13T08:57:34.487Z",
|
||||||
|
"policy": "type-compatibility-policy.md",
|
||||||
|
"baseline": "Latest actual npm 1.1.0 root type shape; earlier 1.0.x conflicts migrated under ADR-025.",
|
||||||
|
"checks": {
|
||||||
|
"isolatedReport": "refactor/.cache/vtt-thumbnail-package-types-JQwPa2/report.json",
|
||||||
|
"reportSha256": "2080b138fa9c9b0e654941b2373862ad2d23ce7caa7b7186cfb2cd6efbe32ead",
|
||||||
|
"candidateArchiveSha256": "8884ad821cee9f1c6792db68bca9cb2f31b092cc8385e0b8fd0299ec726628ad",
|
||||||
|
"configurations": 32,
|
||||||
|
"candidatePositiveConfigurations": 7,
|
||||||
|
"invalidStatementsPerCandidateConfiguration": 12,
|
||||||
|
"log": "refactor/.cache/vtt04-approved-types.log",
|
||||||
|
"logSha256": "3f9283f2387db3db329384e6d59a530b30c6b4aa13c9111714194a7d2971f72a",
|
||||||
|
"focusedTests": 5
|
||||||
|
},
|
||||||
|
"preserves": [
|
||||||
|
"Whole factory replacement in both directions, required arguments and historical sync result.",
|
||||||
|
"Latest published valid NodeNext namespace and plain module replacement, old direct-call diagnostics retained.",
|
||||||
|
"Runtime accurate async result, named types and CommonJS/default identity including old no-interop resolution.",
|
||||||
|
"Isolated actual tarball installation, exact installed bytes, offline frozen reinstall."
|
||||||
|
],
|
||||||
|
"sourceAndDistChanged": false,
|
||||||
|
"browserRerun": false,
|
||||||
|
"limitations": [
|
||||||
|
"Historical thumbnails/vtt-thumbnail control names and complete core/distribution validation remain 05/06.",
|
||||||
|
"Existing runtime/source evidence is linked in the completion note; these checks do not establish devices or final npm release readiness."
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# PKG-VTT-THUMB-04 类型兼容实施完成
|
||||||
|
|
||||||
|
用户已批准ADR-025,之前检查点中的待确认状态由本记录取代。根/legacy保留真实npm
|
||||||
|
1.1.0的必填Option、同步name结果和完整可替换工厂类型;实际异步行为继续通过
|
||||||
|
/runtime表达。修正根入口条件映射,保留旧NodeNext ESM合法namespace及整个模块
|
||||||
|
的双向替换关系,不能只让默认调用通过就声称类型兼容。
|
||||||
|
|
||||||
|
/runtime的Node10声明改为export=并补全Option/Result/Factory/RuntimeFactory命名
|
||||||
|
类型,与NodeNext CommonJS、ESM入口一致。精确异步结果与可写self.default均验证;
|
||||||
|
较早1.0.x的export=冲突、1.1的模块类型及建议迁移已在README和架构文档写明。
|
||||||
|
|
||||||
|
最终真实安装报告包含五个历史版本与候选的32配置,候选7配置全部正例通过,每个
|
||||||
|
配置按语句行拒绝12个反例。保留旧1.1 NodeNext直接调用的7个错误及36组历史/候选
|
||||||
|
CommonJS直接/default对照;1.0.0发布包原始SyntaxError单独记录。最新合法namespace
|
||||||
|
和候选一致,实际JS调用身份单独核验。安装位于工作区外,归档成员逐字核对、离线
|
||||||
|
安装及frozen重装通过。5项专项测试含独立编辑器、历史声明和替代签名验证通过。
|
||||||
|
|
||||||
|
生产TS迁移、模块拆分及先前运行时验证见
|
||||||
|
[运行时检查点](2026-09-13-PKG-VTT-THUMB-04-runtime-types.md)与
|
||||||
|
[公共声明检查点](2026-09-13-PKG-VTT-THUMB-04-public-types.md)。此次源码/dist未变,
|
||||||
|
根公共声明内容未变,生成编辑器一致性已验证,无需重复构建或浏览器播放。
|
||||||
|
|
||||||
|
本任务04完成,VTT-THUMB-TYPE-01关闭;涉及历史控件名称、核心组合和完整分发的
|
||||||
|
VTT-THUMB-EXPORT-01继续交给05/06。没有把类型冲突批准扩大为运行时行为变更,
|
||||||
|
没有新增设备证据,也没有推送或npm发布。详见
|
||||||
|
[最终证据](../baselines/vtt-thumbnail-approved-types.json)。
|
||||||
+3
-3
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 228 项,范围 22 个包及工作区/示例。
|
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 228 项,范围 22 个包及工作区/示例。
|
||||||
|
|
||||||
状态:todo 78 / doing 17 / blocked 0 / done 133 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
|
状态:todo 78 / doing 16 / blocked 0 / done 134 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
|
||||||
|
|
||||||
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
|
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
|
||||||
|
|
||||||
@@ -186,7 +186,7 @@
|
|||||||
| PKG-VTT-THUMB-01 | artplayer-plugin-vtt-thumbnail<br>核对包契约与历史用法 | BASE-05 | vtt/style、异步返回、预览控件名与样式契约 | 源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结 | M | done |
|
| PKG-VTT-THUMB-01 | artplayer-plugin-vtt-thumbnail<br>核对包契约与历史用法 | BASE-05 | vtt/style、异步返回、预览控件名与样式契约 | 源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结 | M | done |
|
||||||
| PKG-VTT-THUMB-02 | artplayer-plugin-vtt-thumbnail<br>建立特有行为与错误测试 | PKG-VTT-THUMB-01, ENG-03, ENG-05 | VTT 解析、xywh、相对 URL、时间边界、请求失败和定位 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | M | done |
|
| PKG-VTT-THUMB-02 | artplayer-plugin-vtt-thumbnail<br>建立特有行为与错误测试 | PKG-VTT-THUMB-01, ENG-03, ENG-05 | VTT 解析、xywh、相对 URL、时间边界、请求失败和定位 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | M | done |
|
||||||
| PKG-VTT-THUMB-03 | artplayer-plugin-vtt-thumbnail<br>整理内部职责与资源 | PKG-VTT-THUMB-02, CORE-09, CORE-19 | 纯解析/区间查找与 DOM、请求/定时器生命周期分离 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | M | done |
|
| PKG-VTT-THUMB-03 | artplayer-plugin-vtt-thumbnail<br>整理内部职责与资源 | PKG-VTT-THUMB-02, CORE-09, CORE-19 | 纯解析/区间查找与 DOM、请求/定时器生命周期分离 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | M | done |
|
||||||
| PKG-VTT-THUMB-04 | artplayer-plugin-vtt-thumbnail<br>迁移自有源码和公开类型 | PKG-VTT-THUMB-03, ENG-04, ENG-06, CORE-07 | cue/rect/result 和参数可选性保持兼容 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | M | doing |
|
| PKG-VTT-THUMB-04 | artplayer-plugin-vtt-thumbnail<br>迁移自有源码和公开类型 | PKG-VTT-THUMB-03, ENG-04, ENG-06, CORE-07 | cue/rect/result 和参数可选性保持兼容 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | M | done |
|
||||||
| PKG-VTT-THUMB-05 | artplayer-plugin-vtt-thumbnail<br>验证新旧核心和组合 | PKG-VTT-THUMB-04, CORE-22 | 鼠标和移动进度、全屏、切源、chapter 组合 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | M | todo |
|
| PKG-VTT-THUMB-05 | artplayer-plugin-vtt-thumbnail<br>验证新旧核心和组合 | PKG-VTT-THUMB-04, CORE-22 | 鼠标和移动进度、全屏、切源、chapter 组合 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | M | todo |
|
||||||
| PKG-VTT-THUMB-06 | artplayer-plugin-vtt-thumbnail<br>验证分发并同步文档 | PKG-VTT-THUMB-05, ENG-07 | vtt.thumbnail.js、VTT/图片资源解析和产物验证 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | M | todo |
|
| PKG-VTT-THUMB-06 | artplayer-plugin-vtt-thumbnail<br>验证分发并同步文档 | PKG-VTT-THUMB-05, ENG-07 | vtt.thumbnail.js、VTT/图片资源解析和产物验证 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | M | todo |
|
||||||
|
|
||||||
@@ -512,7 +512,7 @@
|
|||||||
- PKG-VTT-THUMB-01: [记录](baselines/vtt-thumbnail-release.json) [记录](baselines/vtt-thumbnail-contract.md) [记录](changes/2026-09-13-PKG-VTT-THUMB-01-contract.md)
|
- PKG-VTT-THUMB-01: [记录](baselines/vtt-thumbnail-release.json) [记录](baselines/vtt-thumbnail-contract.md) [记录](changes/2026-09-13-PKG-VTT-THUMB-01-contract.md)
|
||||||
- PKG-VTT-THUMB-02: [记录](baselines/vtt-thumbnail-failures.json) [记录](changes/2026-09-13-PKG-VTT-THUMB-02-failures.md)
|
- PKG-VTT-THUMB-02: [记录](baselines/vtt-thumbnail-failures.json) [记录](changes/2026-09-13-PKG-VTT-THUMB-02-failures.md)
|
||||||
- PKG-VTT-THUMB-03: [记录](changes/2026-09-13-PKG-VTT-THUMB-03-resources.md) [记录](baselines/vtt-thumbnail-resources.json) [记录](changes/2026-09-13-PKG-VTT-THUMB-03-parser.md) [记录](baselines/vtt-thumbnail-parser.json)
|
- PKG-VTT-THUMB-03: [记录](changes/2026-09-13-PKG-VTT-THUMB-03-resources.md) [记录](baselines/vtt-thumbnail-resources.json) [记录](changes/2026-09-13-PKG-VTT-THUMB-03-parser.md) [记录](baselines/vtt-thumbnail-parser.json)
|
||||||
- PKG-VTT-THUMB-04: [记录](changes/2026-09-13-PKG-VTT-THUMB-04-runtime-types.md) [记录](baselines/vtt-thumbnail-runtime-types.json) [记录](changes/2026-09-13-PKG-VTT-THUMB-04-public-types.md) [记录](baselines/vtt-thumbnail-public-types.json) [记录](changes/2026-09-13-PKG-VTT-THUMB-04-module-forms.md) [记录](baselines/vtt-thumbnail-module-forms.json)
|
- PKG-VTT-THUMB-04: [记录](changes/2026-09-13-PKG-VTT-THUMB-04-runtime-types.md) [记录](baselines/vtt-thumbnail-runtime-types.json) [记录](changes/2026-09-13-PKG-VTT-THUMB-04-public-types.md) [记录](baselines/vtt-thumbnail-public-types.json) [记录](changes/2026-09-13-PKG-VTT-THUMB-04-module-forms.md) [记录](baselines/vtt-thumbnail-module-forms.json) [记录](type-compatibility-policy.md) [记录](baselines/vtt-thumbnail-approved-types.json) [记录](changes/2026-09-13-PKG-VTT-THUMB-04-approved-types.md)
|
||||||
- PKG-HLS-01: [记录](baselines/hls-control-contract.md) [记录](baselines/hls-control-release.json) [记录](changes/2026-09-11-PKG-HLS-01-contract.md)
|
- PKG-HLS-01: [记录](baselines/hls-control-contract.md) [记录](baselines/hls-control-release.json) [记录](changes/2026-09-11-PKG-HLS-01-contract.md)
|
||||||
- PKG-HLS-02: [记录](hls-validation.md) [记录](baselines/hls-sdk.json) [记录](baselines/hls-validation.json) [记录](changes/2026-09-11-PKG-HLS-02-tests.md)
|
- PKG-HLS-02: [记录](hls-validation.md) [记录](baselines/hls-sdk.json) [记录](baselines/hls-validation.json) [记录](changes/2026-09-11-PKG-HLS-02-tests.md)
|
||||||
- PKG-HLS-03: [记录](changes/2026-09-12-PKG-HLS-03-modules.md) [记录](baselines/hls-modules-validation.json) [记录](hls-validation.md)
|
- PKG-HLS-03: [记录](changes/2026-09-12-PKG-HLS-03-modules.md) [记录](baselines/hls-modules-validation.json) [记录](hls-validation.md)
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
# 进度与证据
|
# 进度与证据
|
||||||
|
|
||||||
|
## PKG-VTT-THUMB-04 VTT Thumbnail 类型兼容实施完成
|
||||||
|
|
||||||
|
已落实用户批准的最新npm 1.1.0根类型及较早1.0.x迁移规则;/runtime准确
|
||||||
|
描述异步结果和模块形式。32个真实安装配置、7个候选配置正例通过,每配置拒绝
|
||||||
|
12个指定反例,5项专项测试含编辑器通过。见[完成记录](changes/2026-09-13-PKG-VTT-THUMB-04-approved-types.md)及[证据](baselines/vtt-thumbnail-approved-types.json)。
|
||||||
|
VTT-THUMB-TYPE-01关闭,VTT-THUMB-EXPORT-01仍保留组合/完整分发验证。源码与dist未变,
|
||||||
|
不新增浏览器设备通过声明。228项:134 done、16 doing、78 todo;不推送或发布。
|
||||||
|
|
||||||
|
|
||||||
## PKG-FACTORY-01 历史工厂类型修复完成
|
## PKG-FACTORY-01 历史工厂类型修复完成
|
||||||
|
|
||||||
Canvas/Ambilight落实已批准规则:保留真实npm1.1.0根工厂与NodeNext namespace,
|
Canvas/Ambilight落实已批准规则:保留真实npm1.1.0根工厂与NodeNext namespace,
|
||||||
|
|||||||
@@ -192,7 +192,7 @@
|
|||||||
| VTT-THUMB-DIST-01 | open / 已复现 | Historical 1.0.0 main/legacy contain invalid regular expressions and cannot load | PKG-VTT-THUMB-06 |
|
| VTT-THUMB-DIST-01 | open / 已复现 | Historical 1.0.0 main/legacy contain invalid regular expressions and cannot load | PKG-VTT-THUMB-06 |
|
||||||
| VTT-THUMB-PARSE-01 | resolved / 已复现 | Historical compiled arrows differ from shipped source; parsing floors bounds and assumes alternating lines | PKG-VTT-THUMB-02, PKG-VTT-THUMB-03 |
|
| VTT-THUMB-PARSE-01 | resolved / 已复现 | Historical compiled arrows differ from shipped source; parsing floors bounds and assumes alternating lines | PKG-VTT-THUMB-02, PKG-VTT-THUMB-03 |
|
||||||
| VTT-THUMB-LIFE-01 | open / 已复现 | Fetch completion, setBar listeners and mobile timers have no destroy ownership | PKG-VTT-THUMB-02, PKG-VTT-THUMB-03, PKG-VTT-THUMB-05 |
|
| VTT-THUMB-LIFE-01 | open / 已复现 | Fetch completion, setBar listeners and mobile timers have no destroy ownership | PKG-VTT-THUMB-02, PKG-VTT-THUMB-03, PKG-VTT-THUMB-05 |
|
||||||
| VTT-THUMB-TYPE-01 | open / 已复现 | Published declarations falsely describe async registration as a synchronous result | PKG-VTT-THUMB-04 |
|
| VTT-THUMB-TYPE-01 | resolved / 已复现 | Published declarations falsely describe async registration as a synchronous result | PKG-VTT-THUMB-04 |
|
||||||
| VTT-THUMB-EXPORT-01 | open / 已复现 | Older CommonJS default objects and thumbnails control names differ from latest direct export and vtt-thumbnail name | PKG-VTT-THUMB-04, PKG-VTT-THUMB-05, PKG-VTT-THUMB-06 |
|
| VTT-THUMB-EXPORT-01 | open / 已复现 | Older CommonJS default objects and thumbnails control names differ from latest direct export and vtt-thumbnail name | PKG-VTT-THUMB-04, PKG-VTT-THUMB-05, PKG-VTT-THUMB-06 |
|
||||||
| MULTI-SUB-TYPE-01 | open / 已复现 | Declarations omit async registration, tracks/reset and make the subtitles array required | PKG-MULTI-SUB-04 |
|
| MULTI-SUB-TYPE-01 | open / 已复现 | Declarations omit async registration, tracks/reset and make the subtitles array required | PKG-MULTI-SUB-04 |
|
||||||
| 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-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 |
|
||||||
|
|||||||
+13
-5
@@ -4222,7 +4222,7 @@
|
|||||||
"id": "VTT-THUMB-TYPE-01",
|
"id": "VTT-THUMB-TYPE-01",
|
||||||
"title": "Published declarations falsely describe async registration as a synchronous result",
|
"title": "Published declarations falsely describe async registration as a synchronous result",
|
||||||
"confirmation": "reproduced",
|
"confirmation": "reproduced",
|
||||||
"status": "open",
|
"status": "resolved",
|
||||||
"owners": [
|
"owners": [
|
||||||
"PKG-VTT-THUMB-04"
|
"PKG-VTT-THUMB-04"
|
||||||
],
|
],
|
||||||
@@ -4238,8 +4238,14 @@
|
|||||||
"refactor/changes/2026-09-13-PKG-VTT-THUMB-04-module-forms.md",
|
"refactor/changes/2026-09-13-PKG-VTT-THUMB-04-module-forms.md",
|
||||||
"refactor/baselines/vtt-thumbnail-module-forms.json"
|
"refactor/baselines/vtt-thumbnail-module-forms.json"
|
||||||
],
|
],
|
||||||
"compatibleResolution": "Preserve valid consumers and actual async runtime, with explicit decisions for irreconcilable inference changes.",
|
"compatibleResolution": "Approved latest npm 1.1.0 root factory/namespace stays exact; additive runtime supplies accurate asynchronous and module forms. Earlier 1.0.x type conflicts have explicit migration under ADR-025.",
|
||||||
"closureCriteria": "Isolated old/new compiler and installed consumers verify options, styles, callback and result forms."
|
"closureCriteria": "Isolated old/new compiler and installed consumers verify options, styles, callback and result forms.",
|
||||||
|
"resolutionEvidence": [
|
||||||
|
"refactor/baselines/vtt-thumbnail-approved-types.json",
|
||||||
|
"refactor/changes/2026-09-13-PKG-VTT-THUMB-04-approved-types.md",
|
||||||
|
"refactor/type-compatibility-policy.md"
|
||||||
|
],
|
||||||
|
"resolutionRationale": "32 isolated installation configurations, seven zero-diagnostic candidate modes with 12 exact invalid statements each, 5 focused tests. Legal latest namespace and complete factory replacements retained, historical incompatible forms recorded. No production JS changed."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "VTT-THUMB-EXPORT-01",
|
"id": "VTT-THUMB-EXPORT-01",
|
||||||
@@ -4259,9 +4265,11 @@
|
|||||||
"refactor/baselines/vtt-thumbnail-public-types.json",
|
"refactor/baselines/vtt-thumbnail-public-types.json",
|
||||||
"refactor/scripts/vtt-thumbnail-package-types.mjs",
|
"refactor/scripts/vtt-thumbnail-package-types.mjs",
|
||||||
"refactor/changes/2026-09-13-PKG-VTT-THUMB-04-module-forms.md",
|
"refactor/changes/2026-09-13-PKG-VTT-THUMB-04-module-forms.md",
|
||||||
"refactor/baselines/vtt-thumbnail-module-forms.json"
|
"refactor/baselines/vtt-thumbnail-module-forms.json",
|
||||||
|
"refactor/baselines/vtt-thumbnail-approved-types.json",
|
||||||
|
"refactor/changes/2026-09-13-PKG-VTT-THUMB-04-approved-types.md"
|
||||||
],
|
],
|
||||||
"compatibleResolution": "Validate historical import forms and control integrations before selecting compatibility adapters.",
|
"compatibleResolution": "Approved latest npm 1.1.0 root factory/namespace stays exact; additive runtime supplies accurate asynchronous and module forms. Earlier 1.0.x type conflicts have explicit migration under ADR-025. Historical thumbnails/vtt-thumbnail control names and complete core/distribution validation remain 05/06.",
|
||||||
"closureCriteria": "Actual package consumers and old/new cores prove supported forms; unresolved differences stay explicit."
|
"closureCriteria": "Actual package consumers and old/new cores prove supported forms; unresolved differences stay explicit."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import assert from 'node:assert/strict'
|
|||||||
import fs from 'node:fs'
|
import fs from 'node:fs'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import process from 'node:process'
|
import process from 'node:process'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
import ts from 'typescript'
|
import ts from 'typescript'
|
||||||
import compat from 'typescript-compat'
|
import compat from 'typescript-compat'
|
||||||
import { checkFiles, packedFiles } from '../../scripts/package-check.mjs'
|
import { checkFiles, packedFiles } from '../../scripts/package-check.mjs'
|
||||||
@@ -9,7 +10,46 @@ import { consumerDirectory, removeConsumer, run, workspace, writeJson } from '..
|
|||||||
import { hash, readMember } from './releases.mjs'
|
import { hash, readMember } from './releases.mjs'
|
||||||
import { verifyVttThumbnailContract } from './vtt-thumbnail-contract.mjs'
|
import { verifyVttThumbnailContract } from './vtt-thumbnail-contract.mjs'
|
||||||
|
|
||||||
|
export function vttThumbnailConsumerSource(source, mode) {
|
||||||
|
if (mode === 'nodenext-esm') {
|
||||||
|
source = source.replace('import legacy from \'artplayer-plugin-vtt-thumbnail\'', 'import legacyModule from \'artplayer-plugin-vtt-thumbnail\'\nconst legacy = legacyModule.default')
|
||||||
|
.replace('import legacyEntry from \'artplayer-plugin-vtt-thumbnail/legacy\'', 'import legacyEntryModule from \'artplayer-plugin-vtt-thumbnail/legacy\'\nconst legacyEntry = legacyEntryModule.default')
|
||||||
|
.replace('import vtt from \'artplayer-plugin-vtt-thumbnail\'', 'import vttModule from \'artplayer-plugin-vtt-thumbnail\'\nconst vtt = vttModule.default')
|
||||||
|
.replace('namespace.default', 'namespace.default.default')
|
||||||
|
}
|
||||||
|
if (mode.endsWith('-no-interop'))
|
||||||
|
source = source.replace('import runtime from \'artplayer-plugin-vtt-thumbnail/runtime\'', 'import runtime = require(\'artplayer-plugin-vtt-thumbnail/runtime\')')
|
||||||
|
return source
|
||||||
|
}
|
||||||
|
|
||||||
|
export const vttThumbnailNamespaceConsumer = `import type Artplayer from 'artplayer';
|
||||||
|
import vttModule from 'artplayer-plugin-vtt-thumbnail';
|
||||||
|
import * as namespace from 'artplayer-plugin-vtt-thumbnail';
|
||||||
|
import legacyModule from 'artplayer-plugin-vtt-thumbnail/legacy';
|
||||||
|
type Factory = (option: { vtt?: string, style?: Partial<CSSStyleDeclaration> }) => (art: Artplayer) => {name: 'artplayerPluginVttThumbnail'};
|
||||||
|
const replacement: Factory = () => () => ({name: 'artplayerPluginVttThumbnail'});
|
||||||
|
vttModule.default({}); namespace.default.default({}); legacyModule.default({});
|
||||||
|
const fromOld: typeof vttModule = {default: replacement};
|
||||||
|
const toOld: {default: Factory} = vttModule;
|
||||||
|
const namespaceReplacement: typeof namespace.default = {default: replacement};
|
||||||
|
const oldNamespace: {default: Factory} = namespace.default;
|
||||||
|
const option: Parameters<typeof vttModule.default>[0] = {};
|
||||||
|
const result: ReturnType<ReturnType<typeof vttModule.default>> = {name: 'artplayerPluginVttThumbnail'};
|
||||||
|
void [fromOld, toOld, namespaceReplacement, oldNamespace, option, result];`
|
||||||
|
|
||||||
|
export function checkInvalidVttStatements(source, diagnostics) {
|
||||||
|
const expected = []
|
||||||
|
let line = 1
|
||||||
|
for (const text of source.split('\n')) {
|
||||||
|
if (text.startsWith('// @ts-expect-error'))
|
||||||
|
expected.push(line)
|
||||||
|
else line++
|
||||||
|
}
|
||||||
|
assert.deepEqual(diagnostics.map(item => item.line).sort((a, b) => a - b), expected, 'Each invalid VTT statement must fail at its own line')
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
|
assert.equal(process.version.slice(1), fs.readFileSync(path.join(workspace, '.node-version'), 'utf8').trim(), 'Use the repository Node version')
|
||||||
assert.equal(process.env.npm_config_user_agent?.split(' ')[0], 'yarn/1.22.22', 'Use yarn test:vtt-thumbnail-types-package')
|
assert.equal(process.env.npm_config_user_agent?.split(' ')[0], 'yarn/1.22.22', 'Use yarn test:vtt-thumbnail-types-package')
|
||||||
const yarn = process.env.npm_execpath
|
const yarn = process.env.npm_execpath
|
||||||
assert(yarn && fs.existsSync(yarn))
|
assert(yarn && fs.existsSync(yarn))
|
||||||
@@ -66,14 +106,16 @@ Promise.all(['artplayer-plugin-vtt-thumbnail', 'artplayer-plugin-vtt-thumbnail/r
|
|||||||
for (const [compiler, mode] of (plugin.label === 'candidate' ? candidateModes : historicalModes)) {
|
for (const [compiler, mode] of (plugin.label === 'candidate' ? candidateModes : historicalModes)) {
|
||||||
const next = mode.startsWith('nodenext')
|
const next = mode.startsWith('nodenext')
|
||||||
const extension = next ? mode.endsWith('-cjs') ? 'cts' : 'mts' : 'ts'
|
const extension = next ? mode.endsWith('-cjs') ? 'cts' : 'mts' : 'ts'
|
||||||
const source = fs.readFileSync(path.join(workspace, plugin.label === 'candidate' ? 'test/types/vtt-thumbnail-public.ts' : 'refactor/fixtures/consumers/vtt-thumbnail-published.ts'), 'utf8')
|
const fixture = fs.readFileSync(path.join(workspace, plugin.label === 'candidate' ? 'test/types/vtt-thumbnail-public.ts' : 'refactor/fixtures/consumers/vtt-thumbnail-published.ts'), 'utf8')
|
||||||
|
const source = plugin.label === 'candidate' ? vttThumbnailConsumerSource(fixture, mode) : fixture
|
||||||
const filename = path.join(consumer, `consumer.${extension}`)
|
const filename = path.join(consumer, `consumer.${extension}`)
|
||||||
const historical = path.join(consumer, `historical.${extension}`)
|
const historical = path.join(consumer, `historical.${extension}`)
|
||||||
fs.copyFileSync(path.join(workspace, 'refactor/fixtures/consumers/vtt-thumbnail-published.ts'), historical)
|
fs.writeFileSync(historical, vttThumbnailConsumerSource(fs.readFileSync(path.join(workspace, 'refactor/fixtures/consumers/vtt-thumbnail-published.ts'), 'utf8'), mode))
|
||||||
const files = plugin.label === 'candidate' ? [filename, historical] : [filename]
|
const files = plugin.label === 'candidate' ? [filename, historical] : [filename]
|
||||||
if (mode === 'nodenext-cjs' && plugin.label === 'candidate') {
|
if (plugin.label === 'candidate' && mode !== 'nodenext-esm' && mode !== 'bundler-esm') {
|
||||||
const commonjs = path.join(consumer, 'commonjs.cts')
|
const commonjs = path.join(consumer, `commonjs.${extension}`)
|
||||||
fs.writeFileSync(commonjs, `import vtt = require('artplayer-plugin-vtt-thumbnail'); import legacy = require('artplayer-plugin-vtt-thumbnail/legacy'); import runtime = require('artplayer-plugin-vtt-thumbnail/runtime'); vtt.default({}); legacy.default({}); runtime({}); runtime.default({});`)
|
fs.writeFileSync(commonjs, `import vtt = require('artplayer-plugin-vtt-thumbnail'); import legacy = require('artplayer-plugin-vtt-thumbnail/legacy'); import runtime = require('artplayer-plugin-vtt-thumbnail/runtime'); vtt.default({}); legacy.default({}); runtime({}); runtime.default({});
|
||||||
|
const option: runtime.Option = {}; const factory: runtime.RuntimeFactory = runtime; const old: runtime.Factory = () => () => ({name: 'artplayerPluginVttThumbnail'}); const result: runtime.Result = {name: 'artplayerPluginVttThumbnail'}; void [option, factory, old, result];`)
|
||||||
files.push(commonjs)
|
files.push(commonjs)
|
||||||
}
|
}
|
||||||
const options = { strict: true, noEmit: true, skipLibCheck: false, types: [], esModuleInterop: !mode.endsWith('-no-interop'), target: compiler.ScriptTarget.ES2020, lib: ['lib.es2020.d.ts', 'lib.dom.d.ts'], module: next ? compiler.ModuleKind.NodeNext : mode === 'bundler-esm' ? compiler.ModuleKind.ESNext : compiler.ModuleKind.CommonJS, moduleResolution: next ? compiler.ModuleResolutionKind.NodeNext : mode === 'bundler-esm' ? compiler.ModuleResolutionKind.Bundler : compiler.ModuleResolutionKind.NodeJs }
|
const options = { strict: true, noEmit: true, skipLibCheck: false, types: [], esModuleInterop: !mode.endsWith('-no-interop'), target: compiler.ScriptTarget.ES2020, lib: ['lib.es2020.d.ts', 'lib.dom.d.ts'], module: next ? compiler.ModuleKind.NodeNext : mode === 'bundler-esm' ? compiler.ModuleKind.ESNext : compiler.ModuleKind.CommonJS, moduleResolution: next ? compiler.ModuleResolutionKind.NodeNext : mode === 'bundler-esm' ? compiler.ModuleResolutionKind.Bundler : compiler.ModuleResolutionKind.NodeJs }
|
||||||
@@ -84,7 +126,7 @@ Promise.all(['artplayer-plugin-vtt-thumbnail', 'artplayer-plugin-vtt-thumbnail/r
|
|||||||
const actual = fs.realpathSync(file.fileName)
|
const actual = fs.realpathSync(file.fileName)
|
||||||
assert(actual.startsWith(fs.realpathSync(consumer) + path.sep) || (program.isSourceFileDefaultLibrary(file) && path.dirname(actual) === fs.realpathSync(path.dirname(compiler.sys.getExecutingFilePath()))), `Types escaped installed consumer: ${actual}`)
|
assert(actual.startsWith(fs.realpathSync(consumer) + path.sep) || (program.isSourceFileDefaultLibrary(file) && path.dirname(actual) === fs.realpathSync(path.dirname(compiler.sys.getExecutingFilePath()))), `Types escaped installed consumer: ${actual}`)
|
||||||
}
|
}
|
||||||
return compiler.getPreEmitDiagnostics(program).map(item => ({ code: item.code, message: compiler.flattenDiagnosticMessageText(item.messageText, '\n') }))
|
return compiler.getPreEmitDiagnostics(program).map(item => ({ file: item.file && path.relative(consumer, item.file.fileName), line: item.file && item.start !== undefined ? item.file.getLineAndCharacterOfPosition(item.start).line + 1 : null, code: item.code, message: compiler.flattenDiagnosticMessageText(item.messageText, '\n') }))
|
||||||
}
|
}
|
||||||
const diagnostics = compile(source)
|
const diagnostics = compile(source)
|
||||||
const historicalFailure = plugin.version === '1.1.0' && mode === 'nodenext-esm'
|
const historicalFailure = plugin.version === '1.1.0' && mode === 'nodenext-esm'
|
||||||
@@ -93,7 +135,9 @@ Promise.all(['artplayer-plugin-vtt-thumbnail', 'artplayer-plugin-vtt-thumbnail/r
|
|||||||
assert.deepEqual(diagnostics.map(item => item.code), expected, `${plugin.label} ${compiler.version} ${mode}`)
|
assert.deepEqual(diagnostics.map(item => item.code), expected, `${plugin.label} ${compiler.version} ${mode}`)
|
||||||
const invalid = plugin.label === 'candidate' ? compile(source.replaceAll(/\/\/ @ts-expect-error[^\n]*\n/g, '')) : []
|
const invalid = plugin.label === 'candidate' ? compile(source.replaceAll(/\/\/ @ts-expect-error[^\n]*\n/g, '')) : []
|
||||||
if (plugin.label === 'candidate')
|
if (plugin.label === 'candidate')
|
||||||
assert.equal(invalid.length, 10, 'Installed declarations must reject all invalid uses')
|
checkInvalidVttStatements(source, invalid)
|
||||||
|
const namespace = mode === 'nodenext-esm' && (plugin.label === 'candidate' || plugin.version === '1.1.0') ? compile(vttThumbnailNamespaceConsumer) : []
|
||||||
|
assert.deepEqual(namespace, [], 'Latest published and candidate NodeNext namespace replacements must remain valid')
|
||||||
const commonjs = {}
|
const commonjs = {}
|
||||||
if (mode === 'node10-commonjs' || mode === 'nodenext-cjs') {
|
if (mode === 'node10-commonjs' || mode === 'nodenext-cjs') {
|
||||||
const fixture = fs.readFileSync(path.join(workspace, 'refactor/fixtures/consumers/vtt-thumbnail-commonjs.ts'), 'utf8')
|
const fixture = fs.readFileSync(path.join(workspace, 'refactor/fixtures/consumers/vtt-thumbnail-commonjs.ts'), 'utf8')
|
||||||
@@ -108,18 +152,20 @@ Promise.all(['artplayer-plugin-vtt-thumbnail', 'artplayer-plugin-vtt-thumbnail/r
|
|||||||
commonjs[form] = { diagnostics, typeChecks: diagnostics.length === 0 }
|
commonjs[form] = { diagnostics, typeChecks: diagnostics.length === 0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
matrix.push({ plugin: plugin.label, compiler: compiler.version, mode, historicalFailure, diagnostics, invalid, commonjs })
|
matrix.push({ plugin: plugin.label, compiler: compiler.version, mode, historicalFailure, diagnostics, invalid, commonjs, namespace })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
removeConsumer(consumer)
|
removeConsumer(consumer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeJson(path.join(output, 'report.json'), { suite: 'vtt-thumbnail-isolated-package-types', introducedBy: 'PKG-VTT-THUMB-04', scope: 'Five actual published packages in five compiler modes and packed candidate in seven modes, installed outside the workspace with packed core. Offline/frozen reinstall and byte identity are verified. One historical NodeNext ESM declaration failure is expected, not accepted as candidate success. Direct/default import=require extraction and replacement forms reproduce opposing 1.0.x and 1.1.0 declarations; the candidate preserves 1.1.0 forms. The 1.0.x direct module type difference remains unresolved, although old actual CommonJS direct calls already fail. Device and full distribution acceptance remain separate.', packages, published: candidates.slice(0, 5).map(pkg => ({ label: pkg.label, archive: pkg.archive, sha256: hash(fs.readFileSync(pkg.archive)), missingEntrypoints: pkg.missingEntrypoints })), matrix })
|
writeJson(path.join(output, 'report.json'), { suite: 'vtt-thumbnail-isolated-package-types', introducedBy: 'PKG-VTT-THUMB-04', node: process.version, scope: 'Five actual published packages in five compiler modes and packed candidate in seven modes, installed outside the workspace with packed core. Offline/frozen reinstall and byte identity are verified. Root preserves latest 1.1.0 factory and NodeNext ESM namespace, including plain module replacements. Historical raw direct-import diagnostics remain recorded. Direct/default import=require forms retain opposing 1.0.x and 1.1.0 evidence; the candidate follows 1.1.0 under approved type-compatibility-policy.md and documents earlier migration. Runtime describes Promise results, writable self identity and all named types with NodeNext and Node10 including no-interop consumers. Device and full distribution acceptance remain separate.', packages, published: candidates.slice(0, 5).map(pkg => ({ label: pkg.label, archive: pkg.archive, sha256: hash(fs.readFileSync(pkg.archive)), missingEntrypoints: pkg.missingEntrypoints })), matrix })
|
||||||
console.log(`VTT thumbnail installed matrix verified: ${matrix.length} cases, including ${matrix.filter(item => item.historicalFailure).length} expected historical declaration failure; ${output}`)
|
console.log(`VTT thumbnail installed matrix verified: ${matrix.length} cases, including ${matrix.filter(item => item.historicalFailure).length} expected historical declaration failure; ${output}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
main().catch((error) => {
|
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
||||||
console.error(error)
|
main().catch((error) => {
|
||||||
process.exitCode = 1
|
console.error(error)
|
||||||
})
|
process.exitCode = 1
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ import { checkPluginEditorDeclaration, generatePluginEditorDeclaration } from '.
|
|||||||
import { checkConsumer } from '../../scripts/typecheck.mjs'
|
import { checkConsumer } from '../../scripts/typecheck.mjs'
|
||||||
import { readMember } from './releases.mjs'
|
import { readMember } from './releases.mjs'
|
||||||
import { verifyVttThumbnailContract } from './vtt-thumbnail-contract.mjs'
|
import { verifyVttThumbnailContract } from './vtt-thumbnail-contract.mjs'
|
||||||
|
import { checkInvalidVttStatements, vttThumbnailConsumerSource, vttThumbnailNamespaceConsumer } from './vtt-thumbnail-package-types.mjs'
|
||||||
|
|
||||||
const modes = [[ts, 'node10-commonjs'], [ts, 'nodenext-cjs'], [ts, 'nodenext-esm'], [ts, 'bundler-esm'], [compat, 'node10-commonjs']]
|
const modes = [[ts, 'node10-commonjs'], [ts, 'nodenext-cjs'], [ts, 'nodenext-esm'], [ts, 'bundler-esm'], [compat, 'node10-commonjs']]
|
||||||
|
|
||||||
@@ -39,9 +40,11 @@ artplayerPluginVttThumbnail({ vtt: 12 });`
|
|||||||
test('VTT public legacy extraction remains exact while runtime entry gives cast-free Promise types', () => {
|
test('VTT public legacy extraction remains exact while runtime entry gives cast-free Promise types', () => {
|
||||||
const source = fs.readFileSync('test/types/vtt-thumbnail-public.ts', 'utf8')
|
const source = fs.readFileSync('test/types/vtt-thumbnail-public.ts', 'utf8')
|
||||||
for (const [compiler, mode] of modes) {
|
for (const [compiler, mode] of modes) {
|
||||||
assert.deepEqual(checkConsumer(compiler, mode, source), [], `${compiler.version} ${mode}`)
|
const consumer = vttThumbnailConsumerSource(source, mode)
|
||||||
assert.equal(checkConsumer(compiler, mode, source.replaceAll(/\/\/ @ts-expect-error[^\n]*\n/g, '')).length, 10)
|
assert.deepEqual(checkConsumer(compiler, mode, consumer), [], `${compiler.version} ${mode}`)
|
||||||
|
checkInvalidVttStatements(consumer, checkConsumer(compiler, mode, consumer.replaceAll(/\/\/ @ts-expect-error[^\n]*\n/g, '')))
|
||||||
}
|
}
|
||||||
|
assert.deepEqual(checkConsumer(ts, 'nodenext-esm', vttThumbnailNamespaceConsumer), [])
|
||||||
})
|
})
|
||||||
|
|
||||||
test('VTT runtime CommonJS declaration supports direct and default calls without an interop cast', () => {
|
test('VTT runtime CommonJS declaration supports direct and default calls without an interop cast', () => {
|
||||||
|
|||||||
+5
-2
@@ -1927,7 +1927,7 @@
|
|||||||
"ENG-06",
|
"ENG-06",
|
||||||
"CORE-07"
|
"CORE-07"
|
||||||
],
|
],
|
||||||
"status": "doing",
|
"status": "done",
|
||||||
"risk": "M",
|
"risk": "M",
|
||||||
"deliverable": "cue/rect/result 和参数可选性保持兼容",
|
"deliverable": "cue/rect/result 和参数可选性保持兼容",
|
||||||
"acceptance": "严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容",
|
"acceptance": "严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容",
|
||||||
@@ -1937,7 +1937,10 @@
|
|||||||
"changes/2026-09-13-PKG-VTT-THUMB-04-public-types.md",
|
"changes/2026-09-13-PKG-VTT-THUMB-04-public-types.md",
|
||||||
"baselines/vtt-thumbnail-public-types.json",
|
"baselines/vtt-thumbnail-public-types.json",
|
||||||
"changes/2026-09-13-PKG-VTT-THUMB-04-module-forms.md",
|
"changes/2026-09-13-PKG-VTT-THUMB-04-module-forms.md",
|
||||||
"baselines/vtt-thumbnail-module-forms.json"
|
"baselines/vtt-thumbnail-module-forms.json",
|
||||||
|
"type-compatibility-policy.md",
|
||||||
|
"baselines/vtt-thumbnail-approved-types.json",
|
||||||
|
"changes/2026-09-13-PKG-VTT-THUMB-04-approved-types.md"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import type { Factory, Option, Result, RuntimeFactory } from 'artplayer-plugin-vtt-thumbnail'
|
import type { Factory, Option, Result, RuntimeFactory } from 'artplayer-plugin-vtt-thumbnail'
|
||||||
|
import type { Factory as EntryFactory, Option as EntryOption, Result as EntryResult, RuntimeFactory as EntryRuntimeFactory } from 'artplayer-plugin-vtt-thumbnail/runtime'
|
||||||
import Artplayer from 'artplayer'
|
import Artplayer from 'artplayer'
|
||||||
import legacy from 'artplayer-plugin-vtt-thumbnail'
|
import legacy from 'artplayer-plugin-vtt-thumbnail'
|
||||||
|
import * as namespace from 'artplayer-plugin-vtt-thumbnail'
|
||||||
import legacyEntry from 'artplayer-plugin-vtt-thumbnail/legacy'
|
import legacyEntry from 'artplayer-plugin-vtt-thumbnail/legacy'
|
||||||
import runtime from 'artplayer-plugin-vtt-thumbnail/runtime'
|
import runtime from 'artplayer-plugin-vtt-thumbnail/runtime'
|
||||||
|
|
||||||
@@ -10,11 +12,19 @@ type ExactOptions = Assert<Equal<Parameters<typeof legacy>, [option: Option]>>
|
|||||||
type ExactFactory = Assert<Equal<typeof legacy, Factory>>
|
type ExactFactory = Assert<Equal<typeof legacy, Factory>>
|
||||||
type ExactResult = Assert<Equal<ReturnType<ReturnType<typeof legacy>>, Result>>
|
type ExactResult = Assert<Equal<ReturnType<ReturnType<typeof legacy>>, Result>>
|
||||||
type ActualResult = Assert<Equal<ReturnType<ReturnType<typeof runtime>>, Promise<Result>>>
|
type ActualResult = Assert<Equal<ReturnType<ReturnType<typeof runtime>>, Promise<Result>>>
|
||||||
|
type HistoricalFactory = (option: { vtt?: string, style?: Partial<CSSStyleDeclaration> }) => (art: Artplayer) => { name: 'artplayerPluginVttThumbnail' }
|
||||||
|
type ExactHistoricalFactory = Assert<Equal<typeof legacy, HistoricalFactory>>
|
||||||
|
type ExactRuntimeFactory = Assert<Equal<typeof runtime, RuntimeFactory>>
|
||||||
|
type RuntimeEntryTypes = Assert<Equal<[EntryFactory, EntryOption, EntryResult, EntryRuntimeFactory], [Factory, Option, Result, RuntimeFactory]>>
|
||||||
|
|
||||||
const option: Option = { vtt: '/cues.vtt', style: { opacity: '0.8' } }
|
const option: Option = { vtt: '/cues.vtt', style: { opacity: '0.8' } }
|
||||||
const art = new Artplayer({ container: '#player', url: '/video.mp4', plugins: [legacy(option), runtime(option)] })
|
const art = new Artplayer({ container: '#player', url: '/video.mp4', plugins: [legacy(option), runtime(option)] })
|
||||||
const old: Result = legacy(option)(art)
|
const old: Result = legacy(option)(art)
|
||||||
const oldReplacement: typeof legacy = (_option: Option) => (_art: Artplayer) => ({ name: 'artplayerPluginVttThumbnail' })
|
const oldReplacement: typeof legacy = (_option: Option) => (_art: Artplayer) => ({ name: 'artplayerPluginVttThumbnail' })
|
||||||
|
const toOld: HistoricalFactory = legacy
|
||||||
|
const fromOld: typeof legacy = (_option: Parameters<HistoricalFactory>[0]) => (_art: Artplayer) => ({ name: 'artplayerPluginVttThumbnail' })
|
||||||
|
const namespaceFactory: HistoricalFactory = namespace.default
|
||||||
|
const legacyReplacement: typeof legacyEntry = fromOld
|
||||||
legacyEntry(option)
|
legacyEntry(option)
|
||||||
const factory: RuntimeFactory = runtime
|
const factory: RuntimeFactory = runtime
|
||||||
const pending: Promise<Result> = factory(option)(art)
|
const pending: Promise<Result> = factory(option)(art)
|
||||||
@@ -41,5 +51,9 @@ runtime({ unknown: true })
|
|||||||
runtime({})()
|
runtime({})()
|
||||||
// @ts-expect-error The runtime entry cannot be replaced with a synchronous registrar.
|
// @ts-expect-error The runtime entry cannot be replaced with a synchronous registrar.
|
||||||
const wrong: typeof runtime = oldReplacement
|
const wrong: typeof runtime = oldReplacement
|
||||||
void [alias, awaitedName, absent, changed, wrong]
|
// @ts-expect-error The historical root factory has no self default property.
|
||||||
export type { ActualResult, ExactFactory, ExactOptions, ExactResult }
|
legacy.default({})
|
||||||
|
// @ts-expect-error The legacy factory has the same pure function shape.
|
||||||
|
legacyEntry.default({})
|
||||||
|
void [toOld, fromOld, namespaceFactory, legacyReplacement, alias, awaitedName, absent, changed, wrong]
|
||||||
|
export type { ActualResult, ExactFactory, ExactHistoricalFactory, ExactOptions, ExactResult, ExactRuntimeFactory, RuntimeEntryTypes }
|
||||||
Reference in new issue
Block a user