refactor(types): CORE-07 reconcile public declarations and preserve legacy consumers

This commit is contained in:
Harvey Zhao committed 2026-09-11 01:42:32 +08:00
1 parent ee859e4804
commit f9707bad71
34 files changed
+2806 -85

No files matched your search

+64 -5
View File
@@ -44,20 +44,29 @@ export interface Utils {
errorHandle: <T extends boolean>(condition: T, msg: string) => T extends true ? T : never
silencePromise: <T>(value: T) => T extends Promise<infer R> ? Promise<R | undefined> : T
def: (obj: object, name: string, value: unknown) => void
def: {
/** Historical string-key signature; runtime returns obj. */
(obj: object, name: string, value: unknown): void
<T>(obj: T, name: PropertyKey, value: PropertyDescriptor & ThisType<T>): T
}
has: (obj: object, name: PropertyKey) => boolean
get: (obj: object, name: PropertyKey) => PropertyDescriptor | undefined
mergeDeep: <T extends object[]>(...args: T) => T[number]
sleep: (ms: number) => Promise<void>
sleep: (ms?: number) => Promise<void>
/** Historical return type; runtime discards the callback result and ignores context. */
debounce: <F extends (...args: any[]) => any>(func: F, wait: number, context?: object) => (...args: Parameters<F>) => ReturnType<F>
/** Historical return type; runtime discards the callback result. */
throttle: <F extends (...args: any[]) => any>(func: F, wait: number) => (...args: Parameters<F>) => ReturnType<F>
clamp: (num: number, a: number, b: number) => number
secondToTime: (second: number) => string
escape: (str: string) => string
unescape: (str: string) => string
capitalize: (str: string) => string
ArtPlayerError: new (message?: string, context?: ((...args: never[]) => unknown) | (abstract new (...args: never[]) => object)) => Error
getIcon: (key?: string, html?: string | HTMLElement) => HTMLElement
getComposedPath: (event: Event) => EventTarget[]
supportsFlex: () => boolean
@@ -330,6 +339,7 @@ export declare class Player {
pause(): void
play(): Promise<void>
/** Legacy signature; runtime preserves pause's synchronous result or play's Promise. */
toggle(): void
attr(key: string, value?: unknown): unknown
@@ -389,6 +399,14 @@ export interface Thumbnails {
scale?: number
}
/** Constructor input; Option retains its historical required URL/read types. */
export interface OptionInput extends Omit<Option, 'url' | 'controls' | 'layers' | 'contextmenu'> {
url?: string
controls?: ComponentInput[]
layers?: ComponentInput[]
contextmenu?: ComponentInput[]
}
export interface Option {
/**
* The player id
@@ -752,6 +770,12 @@ export type I18n = Partial<Record<I18nKeys, Partial<I18nValue>>>
export type Bar = 'loaded' | 'played' | 'hover'
/** Actual built-in subtitle update payloads; legacy Events keeps its scalar types. */
export interface SubtitleUpdateEvents {
subtitleBeforeUpdate: [cues: VTTCue[]]
subtitleAfterUpdate: [cues: VTTCue[]]
}
export interface Events {
'document:click': [event: Event]
'document:mouseup': [event: Event]
@@ -807,7 +831,9 @@ export interface Events {
'destroy': []
'subtitleOffset': [offset: number]
/** Legacy contextual type; annotate listeners with VTTCue[] for the runtime payload. */
'subtitleBeforeUpdate': [cue: VTTCue]
/** Legacy contextual type; annotate listeners with VTTCue[] for the runtime payload. */
'subtitleAfterUpdate': [cue: VTTCue]
'subtitleLoad': [cues: VTTCue[], option: Subtitle]
@@ -845,6 +871,15 @@ export interface Events {
'keydown': [event: KeyboardEvent]
}
/** The event bus exposed by Artplayer.Emitter; no new runtime export. */
export interface Emitter<Events extends { [Name in keyof Events]: readonly unknown[] } = Record<PropertyKey, unknown[]>> {
e?: { [Name in keyof Events]?: { fn: (...args: [...Events[Name]]) => unknown, ctx: unknown }[] }
on: <Name extends keyof Events, Context>(name: Name, fn: (this: Context, ...args: [...Events[Name]]) => unknown, ctx?: Context) => this
once: <Name extends keyof Events, Context>(name: Name, fn: (this: Context, ...args: [...Events[Name]]) => unknown, ctx?: Context) => this
emit: <Name extends keyof Events>(name: Name, ...args: [...Events[Name]]) => this
off: <Name extends keyof Events>(name: Name, fn?: (...args: [...Events[Name]]) => unknown) => this
}
export interface CssVar {
'--art-theme': string
'--art-font-color': string
@@ -973,6 +1008,11 @@ export interface Config {
]
}
/** Input accepted by the existing HTML renderer, including numeric content. */
export interface ComponentInput extends Omit<ComponentOption, 'html'> {
html?: string | HTMLElement | number
}
export interface Selector {
/**
* Whether the default is selected
@@ -1029,7 +1069,10 @@ export interface Component {
/**
* Dynamic add a component
*/
add: (option: ComponentOption | ((art: Artplayer) => ComponentOption)) => HTMLElement | undefined
add: {
(option: ComponentOption | ((art: Artplayer) => ComponentOption)): HTMLElement | undefined
(option: ComponentInput | ((art: Artplayer) => ComponentInput)): HTMLElement | undefined
}
/**
* Dynamic remove a component by name
@@ -1039,7 +1082,10 @@ export interface Component {
/**
* Dynamic update a component
*/
update: (option: ComponentOption) => HTMLElement | undefined
update: {
(option: ComponentOption): HTMLElement | undefined
(option: ComponentInput): HTMLElement | undefined
}
}
export interface ComponentOption {
@@ -1106,20 +1152,24 @@ export interface ComponentOption {
export type {
Config,
Emitter,
Events,
I18n,
Icons,
Option,
OptionInput,
Player,
Setting,
SettingOption,
Subtitle,
SubtitleUpdateEvents,
Template,
Utils,
}
export default class Artplayer extends Player {
constructor(option: Option, readyCallback?: (this: Artplayer, art: Artplayer) => unknown)
constructor(option: OptionInput, readyCallback?: (this: Artplayer, art: Artplayer) => unknown)
static readonly instances: Artplayer[]
static readonly version: string
@@ -1128,7 +1178,7 @@ export default class Artplayer extends Player {
static readonly config: Config
static readonly utils: Utils
static readonly scheme: Record<keyof Option, unknown>
static readonly Emitter: new (...args: unknown[]) => unknown
static readonly Emitter: new <Events extends { [Name in keyof Events]: readonly unknown[] } = Record<PropertyKey, unknown[]>>(...args: unknown[]) => Emitter<Events>
static readonly validator: <T extends object>(option: T, scheme: object) => T
static readonly kindOf: (item: unknown) => string
static readonly html: Artplayer['template']['html']
@@ -1186,15 +1236,19 @@ export default class Artplayer extends Player {
torrent?: unknown
on<T extends keyof Events>(name: T, fn: (...args: Events[T]) => unknown, ctx?: object): this
on<T extends keyof SubtitleUpdateEvents>(name: T, fn: (...args: SubtitleUpdateEvents[T]) => unknown, ctx?: object): this
on(name: string, fn: (...args: unknown[]) => unknown, ctx?: object): this
once<T extends keyof Events>(name: T, fn: (...args: Events[T]) => unknown, ctx?: object): this
once<T extends keyof SubtitleUpdateEvents>(name: T, fn: (...args: SubtitleUpdateEvents[T]) => unknown, ctx?: object): this
once(name: string, fn: (...args: unknown[]) => unknown, ctx?: object): this
emit<T extends keyof Events>(name: T, ...args: Events[T]): this
emit<T extends keyof SubtitleUpdateEvents>(name: T, ...args: SubtitleUpdateEvents[T]): this
emit(name: string, ...args: unknown[]): this
off<T extends keyof Events>(name: T, callback?: (...args: Events[T]) => unknown): this
off<T extends keyof SubtitleUpdateEvents>(name: T, callback?: (...args: SubtitleUpdateEvents[T]) => unknown): this
off(name: string, callback?: (...args: unknown[]) => unknown): this
query: Artplayer['template']['query']
@@ -1280,13 +1334,18 @@ export default class Artplayer extends Player {
readonly setting: {
option: SettingOption[]
updateStyle: (width?: number) => void
/** Legacy return signature; a missing runtime entry is null. */
find: (name: string) => SettingOption | undefined
/** Legacy return signature; runtime returns the formatted input item. */
add: (setting: Setting) => Artplayer['setting']
/** Legacy return signature; runtime returns the updated or added item. */
update: (settings: Setting) => Artplayer['setting']
/** Legacy return signature; runtime returns undefined. */
remove: (name: string) => Artplayer['setting']
} & Component
readonly plugins: {
/** Legacy signature: synchronous factories return this registry directly; Promise factories return a Promise of it. */
add: (
plugin: (this: Artplayer, art: Artplayer) => unknown | Promise<unknown>,
) => Promise<Artplayer['plugins']>
+12 -11
View File
@@ -13,7 +13,7 @@ The entry passes Artplayer.option to `option/resolve.ts`, which performs the exi
deep merge, restores input.container by reference and invokes the same option-validator
function. Allocation of the instance id still precedes validation; DOM mounting follows it.
`option/types.ts` reuses the public Option as the typed input contract. ResolvedOption
`option/types.ts` reuses the public OptionInput as the typed input contract. ResolvedOption
requires top-level defaults and subtitle/thumbnail defaults, while explicitly allowing
proxy to remain undefined. ResolvedInput preserves extra typed application fields without
adding a global any index signature. The one assertion after validation connects the
@@ -30,12 +30,14 @@ The public Artplayer.validator and scheme references remain available as before.
Merge behavior includes unknown own keys, collection item references, two reads of an
enumerable input container getter, and restoration of an inherited container. Explicit
undefined can still fail the existing schema instead of being silently defaulted. This
task changes neither validation rules nor public consumer declarations.
undefined can still fail the existing schema instead of being silently defaulted.
Runtime validation is unchanged; public input expansions are described below.
Two verified declaration gaps are tracked as BASE-TYPE-06 for CORE-07: existing JS can
omit url and use numeric control HTML, while the current public types reject those forms.
The historical rejection fixtures must become positive consumer checks when reconciled.
CORE-07 adds OptionInput for omitted URL and numeric component HTML. Historical Option
keeps its required URL/read types; the constructor accepts both via overloads. Source
fixtures now accept the expanded inputs, and declaration-legacy.ts protects old reads.
The additive declarations and remaining return conflicts are tracked in
[types/COMPATIBILITY.md](./types/COMPATIBILITY.md).
Other permissive validator cases are not blanket guarantees that later DOM/media code
can consume every accepted value. Preserve failure stages while migrating those consumers.
@@ -257,11 +259,10 @@ documented cast to the pre-existing generic return contract. No file-wide any or
type-check suppression was added. The main public declarations remain a separate
compatibility surface; see [types/README.md](./types/README.md).
Existing declaration discrepancies are still tracked for CORE-07: Utils lacks some
runtime exports, def is declared void, debounce/throttle declare the callback return
instead of void, and debounce's old optional context argument is ignored at runtime.
Sleep's declaration also requires a delay while runtime defaults to zero. These were
not silently tightened during source migration; use the actual source types internally.
Public return discrepancies remain after CORE-07. It adds unescape/ArtPlayerError,
optional sleep and a symbol/PropertyKey def overload; old string def and debounce/throttle return declarations
remain for source compatibility. The old debounce context argument is ignored at runtime.
BASE-TYPE-05 remains open through CORE-21; use the actual source types internally.
Lifecycle-owned timer cancellation is part of CORE-04/17 and the existing BASE-PERF-01
finding, not a claim that a standalone debounce can know when its owner is destroyed.
+2 -2
View File
@@ -1,9 +1,9 @@
import type { Option, ResolvedInput, ResolvedOption } from './types'
import type { OptionInput, ResolvedInput, ResolvedOption } from './types'
import validator from 'option-validator'
import scheme from '../scheme'
import { mergeDeep } from '../utils/property'
export default function resolveOption<Input extends Option>(input: Input, defaults: ResolvedOption): ResolvedInput<Input> {
export default function resolveOption<Input extends OptionInput>(input: Input, defaults: ResolvedOption): ResolvedInput<Input> {
const merged = mergeDeep(defaults, input)
merged.container = input.container
// Keep the existing runtime validator. It checks the known schema, not extension data.
+5 -5
View File
@@ -1,13 +1,13 @@
import type { Option, Thumbnails } from '../../types/option'
import type { OptionInput, Thumbnails } from '../../types/option'
import type { Subtitle } from '../../types/subtitle'
export type { Option } from '../../types/option'
export type { Option, OptionInput } from '../../types/option'
// A successfully merged typed input, not a general guard for arbitrary JS objects.
export interface ResolvedOption extends Omit<Required<Option>, 'proxy' | 'subtitle' | 'thumbnails'> {
proxy: Option['proxy']
export interface ResolvedOption extends Omit<Required<OptionInput>, 'proxy' | 'subtitle' | 'thumbnails'> {
proxy: OptionInput['proxy']
subtitle: Required<Subtitle>
thumbnails: Required<Thumbnails>
}
export type ResolvedInput<Input extends Option> = ResolvedOption & Omit<Input, keyof Option>
export type ResolvedInput<Input extends OptionInput> = ResolvedOption & Omit<Input, keyof OptionInput>
+72
View File
@@ -0,0 +1,72 @@
# Public type compatibility boundaries
The declarations preserve legal historical TypeScript consumers as well as runtime
calls. Some old return and callback declarations were inaccurate. Changing a
return from Promise to a union, or an inferred callback parameter from cue to cue
array, can break old source even when runtime behavior is unchanged. Do not hide
that conflict with `any`, an impossible intersection, or a runtime Promise wrapper.
## Additive declarations
- Option retains its required string URL and existing component read types.
OptionInput accepts omitted URL and numeric component HTML. Constructor overloads
accept both; Component.add/update also accept ComponentInput. Use OptionInput for
new configurations that require these forms. Instance/static option read types
retain their old surface; internal ResolvedOption models the expanded input.
- Artplayer.Emitter now returns the named Emitter interface. It supports optional
typed event maps, correlated payloads, explicit callback context, symbols and
chaining. Constructor arguments remain accepted and ignored at runtime.
- SubtitleUpdateEvents describes the real before/after update cue arrays. Extra
on/once/off/emit overloads accept explicit array callbacks. Historical Events
and the first overload retain old contextual inference for compatibility:
```ts
art.on('subtitleBeforeUpdate', (cues: VTTCue[]) => {
cues.forEach(cue => console.log(cue.text))
})
```
- Utils includes existing unescape and ArtPlayerError exports and optional sleep
delay. A PropertyKey/identity def overload supports symbol keys while the old
string-key signature remains first. These are type additions, not new runtime
functions or exports.
## Retained conflicts and owners
| Surface | Actual runtime | Retained historical declaration | Follow-up |
| ------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------- | ------------------------ |
| plugins.add | Registry for a synchronous factory; Promise of registry for a Promise factory | Always Promise | CORE-08/21, BASE-TYPE-04 |
| toggle | Pause result or original play Promise, including rejection | void | CORE-10/21, BASE-TYPE-04 |
| debounce/throttle | Wrapper returns undefined; debounce ignores its old context argument | Callback return type | CORE-21, BASE-TYPE-05 |
| def with string key | Native defineProperty returns the target | void, arbitrary descriptor input accepted | CORE-21, BASE-TYPE-05 |
| setting.find | Item or null | Item or undefined | CORE-14/21, BASE-TYPE-07 |
| setting.add/update/remove | Item/item/undefined | Setting registry | CORE-14/21, BASE-TYPE-07 |
| subtitle update events | VTTCue array | Scalar contextual inference unless explicitly annotated | CORE-15/21, BASE-TYPE-07 |
| notice.show getter | Boolean visibility | Historical message/false union | CORE-18/21, BASE-TYPE-07 |
These remain open declaration work, not release waivers. CORE-21 must resolve the
public/generated facade strategy against both actual returns and historical source
consumers. Migrated implementation modules must use their accurate internal types.
For existing application code, awaiting plugins.add or toggle works for synchronous
and Promise results; ignore timer results, guard setting.find with a truthiness
check, and explicitly annotate cue-array listeners. Do not rely on the inaccurate
return types to call Promise methods on synchronous results or chain settings.
## Evidence and maintenance
declaration-legacy.ts is a compile-only regression fixture, not recommended runtime
usage. It retains the historical assignments that make direct return tightening
incompatible. declaration-inputs.ts covers the additions with old and current TS,
Node10/NodeNext/Bundler, and actual installed packages. emitter-source.ts also checks
the public Emitter shape against the real implementation.
Browser declarations.spec.js compares published/candidate plugin registration,
rejection identity, actual toggle playback, settings return identity, notice state,
static Emitter context and native subtitle cue events. The generated VTT is test
content; explicit Blob URL teardown there does not certify subtitle resource cleanup
(CORE-15). options.spec.js verifies numeric content and omitted URL in the real DOM.
Run yarn typecheck, yarn ci:check, yarn build:ts and yarn test:package:release, then
the installed-artifact browser suite. Keep the exact historical TS 4.3.5 notice
getter/setter error isolated to the frozen 5.4.0 package. Current declarations must
remain free of diagnostics in every supported compiler mode.
+16 -8
View File
@@ -26,16 +26,24 @@ When changing types, run `yarn typecheck`, `yarn test:baseline` and
chapter/legacy factories, language data, invalid inputs, NodeNext/Bundler and old
TS 4.3.5 consumers. Run `yarn build:ts` to refresh editor declarations. Full editor
behavior and other core declaration/runtime mismatches have CORE-07/SITE tasks.
## Configuration migration boundary
CORE-05 keeps the public Option unchanged. Internal src/option/types.ts distinguishes
typed input from defaults-filled ResolvedOption; it is not a new public export. The
existing public url requirement and exclusion of numeric control HTML differ from
verified JS behavior (BASE-TYPE-06, CORE-07). test/types/options-source.ts records the
current rejection; replace those two negative cases with positive consumer coverage
when expanding the public declarations. Do not change runtime validation to match a
narrower historical declaration. Other optional fields and callback signatures remain
subject to the existing public compatibility contract.
Option retains its historical required URL and component read types. OptionInput is
an additive constructor input: URL is optional and numeric component HTML is accepted.
The constructor keeps its old overload and adds OptionInput; Component.add/update
similarly retain their old signatures and add ComponentInput. Internal ResolvedOption
uses the expanded input with defaults filled. It is not a new public runtime export.
This preserves assignments such as `const url: string = option.url` for existing
Option consumers while matching the verified JS input forms (BASE-TYPE-06).
Use OptionInput for newly typed configurations that omit URL or use numeric HTML.
test/types/options-source.ts and declaration-inputs.ts cover those forms positively;
declaration-legacy.ts preserves old reads and historically legal return assumptions.
Do not change runtime validation to match a narrower declaration. The additions,
retained conflicts and follow-up owners are detailed in [COMPATIBILITY.md](./COMPATIBILITY.md).
CORE-07 coordinates the differences; it does not close every conflicting old return
signature. CORE-21 remains responsible for the generated/public declaration strategy.
## Internal media migration
+5
View File
@@ -1,18 +1,23 @@
import type * as Definition from './artplayer.js'
declare const Artplayer: typeof Definition.default
// eslint-disable-next-line ts/no-redeclare -- CJS constructor value and instance type share the export.
type Artplayer = Definition.default
// eslint-disable-next-line ts/no-redeclare -- Namespace merging carries named types on export =.
declare namespace Artplayer {
type Config = Definition.Config
type Emitter<Events extends { [Name in keyof Events]: readonly unknown[] } = Record<PropertyKey, unknown[]>> = Definition.Emitter<Events>
type Events = Definition.Events
type I18n = Definition.I18n
type Icons = Definition.Icons
type Option = Definition.Option
type OptionInput = Definition.OptionInput
type Player = Definition.Player
type Setting = Definition.Setting
type SettingOption = Definition.SettingOption
type Subtitle = Definition.Subtitle
type SubtitleUpdateEvents = Definition.SubtitleUpdateEvents
type Template = Definition.Template
type Utils = Definition.Utils
}
+1 -1
View File
@@ -1,2 +1,2 @@
export { default } from './artplayer.cjs'
export type { Config, Events, I18n, Icons, Option, Player, Setting, SettingOption, Subtitle, Template, Utils } from './artplayer.js'
export type { Config, Emitter, Events, I18n, Icons, Option, OptionInput, Player, Setting, SettingOption, Subtitle, SubtitleUpdateEvents, Template, Utils } from './artplayer.js'
+17 -3
View File
@@ -1,9 +1,10 @@
import type { Component } from './component'
import type { Config } from './config'
import type { Events } from './events'
import type { Emitter } from './emitter'
import type { Events, SubtitleUpdateEvents } from './events'
import type { I18n } from './i18n'
import type { Icons } from './icons'
import type { Option } from './option'
import type { Option, OptionInput } from './option'
import type { Player } from './player'
import type { Setting, SettingOption } from './setting'
import type { Subtitle } from './subtitle'
@@ -12,20 +13,24 @@ import type { Utils } from './utils'
export type {
Config,
Emitter,
Events,
I18n,
Icons,
Option,
OptionInput,
Player,
Setting,
SettingOption,
Subtitle,
SubtitleUpdateEvents,
Template,
Utils,
}
export default class Artplayer extends Player {
constructor(option: Option, readyCallback?: (this: Artplayer, art: Artplayer) => unknown)
constructor(option: OptionInput, readyCallback?: (this: Artplayer, art: Artplayer) => unknown)
static readonly instances: Artplayer[]
static readonly version: string
@@ -34,7 +39,7 @@ export default class Artplayer extends Player {
static readonly config: Config
static readonly utils: Utils
static readonly scheme: Record<keyof Option, unknown>
static readonly Emitter: new (...args: unknown[]) => unknown
static readonly Emitter: new <Events extends { [Name in keyof Events]: readonly unknown[] } = Record<PropertyKey, unknown[]>>(...args: unknown[]) => Emitter<Events>
static readonly validator: <T extends object>(option: T, scheme: object) => T
static readonly kindOf: (item: unknown) => string
static readonly html: Artplayer['template']['html']
@@ -92,15 +97,19 @@ export default class Artplayer extends Player {
torrent?: unknown
on<T extends keyof Events>(name: T, fn: (...args: Events[T]) => unknown, ctx?: object): this
on<T extends keyof SubtitleUpdateEvents>(name: T, fn: (...args: SubtitleUpdateEvents[T]) => unknown, ctx?: object): this
on(name: string, fn: (...args: unknown[]) => unknown, ctx?: object): this
once<T extends keyof Events>(name: T, fn: (...args: Events[T]) => unknown, ctx?: object): this
once<T extends keyof SubtitleUpdateEvents>(name: T, fn: (...args: SubtitleUpdateEvents[T]) => unknown, ctx?: object): this
once(name: string, fn: (...args: unknown[]) => unknown, ctx?: object): this
emit<T extends keyof Events>(name: T, ...args: Events[T]): this
emit<T extends keyof SubtitleUpdateEvents>(name: T, ...args: SubtitleUpdateEvents[T]): this
emit(name: string, ...args: unknown[]): this
off<T extends keyof Events>(name: T, callback?: (...args: Events[T]) => unknown): this
off<T extends keyof SubtitleUpdateEvents>(name: T, callback?: (...args: SubtitleUpdateEvents[T]) => unknown): this
off(name: string, callback?: (...args: unknown[]) => unknown): this
query: Artplayer['template']['query']
@@ -186,13 +195,18 @@ export default class Artplayer extends Player {
readonly setting: {
option: SettingOption[]
updateStyle: (width?: number) => void
/** Legacy return signature; a missing runtime entry is null. */
find: (name: string) => SettingOption | undefined
/** Legacy return signature; runtime returns the formatted input item. */
add: (setting: Setting) => Artplayer['setting']
/** Legacy return signature; runtime returns the updated or added item. */
update: (settings: Setting) => Artplayer['setting']
/** Legacy return signature; runtime returns undefined. */
remove: (name: string) => Artplayer['setting']
} & Component
readonly plugins: {
/** Legacy signature: synchronous factories return this registry directly; Promise factories return a Promise of it. */
add: (
plugin: (this: Artplayer, art: Artplayer) => unknown | Promise<unknown>,
) => Promise<Artplayer['plugins']>
+13 -2
View File
@@ -1,5 +1,10 @@
import type Artplayer from './artplayer'
/** Input accepted by the existing HTML renderer, including numeric content. */
export interface ComponentInput extends Omit<ComponentOption, 'html'> {
html?: string | HTMLElement | number
}
export interface Selector {
/**
* Whether the default is selected
@@ -56,7 +61,10 @@ export interface Component {
/**
* Dynamic add a component
*/
add: (option: ComponentOption | ((art: Artplayer) => ComponentOption)) => HTMLElement | undefined
add: {
(option: ComponentOption | ((art: Artplayer) => ComponentOption)): HTMLElement | undefined
(option: ComponentInput | ((art: Artplayer) => ComponentInput)): HTMLElement | undefined
}
/**
* Dynamic remove a component by name
@@ -66,7 +74,10 @@ export interface Component {
/**
* Dynamic update a component
*/
update: (option: ComponentOption) => HTMLElement | undefined
update: {
(option: ComponentOption): HTMLElement | undefined
(option: ComponentInput): HTMLElement | undefined
}
}
export interface ComponentOption {
+8
View File
@@ -0,0 +1,8 @@
/** The event bus exposed by Artplayer.Emitter; no new runtime export. */
export interface Emitter<Events extends { [Name in keyof Events]: readonly unknown[] } = Record<PropertyKey, unknown[]>> {
e?: { [Name in keyof Events]?: { fn: (...args: [...Events[Name]]) => unknown, ctx: unknown }[] }
on: <Name extends keyof Events, Context>(name: Name, fn: (this: Context, ...args: [...Events[Name]]) => unknown, ctx?: Context) => this
once: <Name extends keyof Events, Context>(name: Name, fn: (this: Context, ...args: [...Events[Name]]) => unknown, ctx?: Context) => this
emit: <Name extends keyof Events>(name: Name, ...args: [...Events[Name]]) => this
off: <Name extends keyof Events>(name: Name, fn?: (...args: [...Events[Name]]) => unknown) => this
}
+8
View File
@@ -3,6 +3,12 @@ import type { Subtitle } from './subtitle'
export type Bar = 'loaded' | 'played' | 'hover'
/** Actual built-in subtitle update payloads; legacy Events keeps its scalar types. */
export interface SubtitleUpdateEvents {
subtitleBeforeUpdate: [cues: VTTCue[]]
subtitleAfterUpdate: [cues: VTTCue[]]
}
export interface Events {
'document:click': [event: Event]
'document:mouseup': [event: Event]
@@ -58,7 +64,9 @@ export interface Events {
'destroy': []
'subtitleOffset': [offset: number]
/** Legacy contextual type; annotate listeners with VTTCue[] for the runtime payload. */
'subtitleBeforeUpdate': [cue: VTTCue]
/** Legacy contextual type; annotate listeners with VTTCue[] for the runtime payload. */
'subtitleAfterUpdate': [cue: VTTCue]
'subtitleLoad': [cues: VTTCue[], option: Subtitle]
+9 -1
View File
@@ -1,5 +1,5 @@
import type Artplayer from './artplayer'
import type { ComponentOption } from './component'
import type { ComponentInput, ComponentOption } from './component'
import type { CssVar } from './cssVar'
import type { I18n } from './i18n'
import type { Icons } from './icons'
@@ -48,6 +48,14 @@ export interface Thumbnails {
scale?: number
}
/** Constructor input; Option retains its historical required URL/read types. */
export interface OptionInput extends Omit<Option, 'url' | 'controls' | 'layers' | 'contextmenu'> {
url?: string
controls?: ComponentInput[]
layers?: ComponentInput[]
contextmenu?: ComponentInput[]
}
export interface Option {
/**
* The player id
+1
View File
@@ -93,6 +93,7 @@ export declare class Player {
pause(): void
play(): Promise<void>
/** Legacy signature; runtime preserves pause's synchronous result or play's Promise. */
toggle(): void
attr(key: string, value?: unknown): unknown
+11 -2
View File
@@ -44,20 +44,29 @@ export interface Utils {
errorHandle: <T extends boolean>(condition: T, msg: string) => T extends true ? T : never
silencePromise: <T>(value: T) => T extends Promise<infer R> ? Promise<R | undefined> : T
def: (obj: object, name: string, value: unknown) => void
def: {
/** Historical string-key signature; runtime returns obj. */
(obj: object, name: string, value: unknown): void
<T>(obj: T, name: PropertyKey, value: PropertyDescriptor & ThisType<T>): T
}
has: (obj: object, name: PropertyKey) => boolean
get: (obj: object, name: PropertyKey) => PropertyDescriptor | undefined
mergeDeep: <T extends object[]>(...args: T) => T[number]
sleep: (ms: number) => Promise<void>
sleep: (ms?: number) => Promise<void>
/** Historical return type; runtime discards the callback result and ignores context. */
debounce: <F extends (...args: any[]) => any>(func: F, wait: number, context?: object) => (...args: Parameters<F>) => ReturnType<F>
/** Historical return type; runtime discards the callback result. */
throttle: <F extends (...args: any[]) => any>(func: F, wait: number) => (...args: Parameters<F>) => ReturnType<F>
clamp: (num: number, a: number, b: number) => number
secondToTime: (second: number) => string
escape: (str: string) => string
unescape: (str: string) => string
capitalize: (str: string) => string
ArtPlayerError: new (message?: string, context?: ((...args: never[]) => unknown) | (abstract new (...args: never[]) => object)) => Error
getIcon: (key?: string, html?: string | HTMLElement) => HTMLElement
getComposedPath: (event: Event) => EventTarget[]
supportsFlex: () => boolean
@@ -0,0 +1,576 @@
{
"task": "CORE-07",
"status": "partial",
"validatedScope": "additive option inputs, missing utilities, historical return consumers",
"node": "v24.21.0",
"types": {
"packages/artplayer/types/artplayer.d.cts": "949be8471bc369f4be21654f20c32eb8319944241b5389d1ba91f0d92b2d0195",
"packages/artplayer/types/artplayer.d.mts": "52bd9520a975f9b69d0169b2ef362dca8f8a3101127041930d3d81d8c7a6c51a",
"packages/artplayer/types/artplayer.d.ts": "e09779cdbc55fbab50928d01a12f737206b6bb0221f158e9733289a60f23fbe9",
"packages/artplayer/types/component.d.ts": "aa1c43be67322781b4b355b143bc69d9f29d22e578e4974d6a13e957a7c0334f",
"packages/artplayer/types/config.d.ts": "c4fd8681bf32b10c743e3e561c532520c8f32e43fd765524850b15e55cb91c72",
"packages/artplayer/types/cssVar.d.ts": "e027d82fb4f01c9ce7559cf679b2d5ee1962d3f7e5b4dd64ca21f472b933efb6",
"packages/artplayer/types/events.d.ts": "98c74aebb82455accc0b3523af5a1145bc9119da58c884200adc36e70a164b02",
"packages/artplayer/types/i18n.d.ts": "3e14759caf71f97f01650839248c8737c42d2c2979dabc43ad92b724da648708",
"packages/artplayer/types/icons.d.ts": "0d8e8e52e52130dd4a29bab551dd7a2a954797e42e92a6e068c85d583e23e6a4",
"packages/artplayer/types/language.d.cts": "1c9e0c47fae3c2d68c3e144d95a55071318a03bb31554dd049109efd3d0f95a4",
"packages/artplayer/types/language.d.mts": "c391e863012c77769e661afbf8fa949e9373aa88d17f58cbba7f5696edb8077f",
"packages/artplayer/types/option.d.ts": "2407f08755cfe854821a65fb8c74b7ea5078d5b8f9cd9bdd3e67904529840585",
"packages/artplayer/types/player.d.ts": "986382bb6b4e82746fd2405092e69d0ef413988887a557a0fd4db85d64b78d54",
"packages/artplayer/types/quality.d.ts": "7ed6ed78cea52991b2f6ddd2bd3b7bd8c5146fdfff7486fe8b814c3e632f1567",
"packages/artplayer/types/setting.d.ts": "d12a75b656fff70cbb30be4bffec46d9c4273636e8722bce971a4d2b188712a1",
"packages/artplayer/types/subtitle.d.ts": "d25b470e47d6a9bd696d9c1ad8adb58e56a208f05695186d513bc8c43c2e8acf",
"packages/artplayer/types/template.d.ts": "68aed9e97d006d6be4fabb8504ca84dafab770b0925f4d6e7319e67c82f21b0d",
"packages/artplayer/types/utils.d.ts": "3957fa840e472b4da260a3179878550dd3b99ecd2ef27e85821abf446fa4d95e"
},
"ci": {
"total": 112,
"unit": 83,
"engineering": 4,
"baseline": 25,
"logSha256": "0002c9e307dfbf18f5e2a5f0f6b3b84b52c5ebe8be3ed61fa90b36ff5845f73a"
},
"packages": [
{
"name": "artplayer",
"version": "5.4.1",
"archive": "artplayer.tgz",
"sha256": "7596ef220b89295bf641d924aa556ea03ba1e854b275ed89db7a3e358747f2a3",
"files": {
"package/ARCHITECTURE.md": "47faff9250a85ce2a1ce8452628d5c81e26db7ff16a78134d83536104707d68a",
"package/README.md": "1e185e65f67fc2081b4182bbc6c4558ea05b6e3fa3acc5dd0c3ac7df1d542b09",
"package/dist/artplayer.js": "ce632f30f93eb81b856191082fccdfb2cab81aa39277eee4b89b6dfebb0ccd49",
"package/dist/artplayer.legacy.js": "9b5d7c77785f556c667a77ecbae70fdc562c8362dd0476c55310859b4f0b1dc7",
"package/dist/artplayer.mjs": "1fec67e1029191869da1e4895c0d6fecfe72811f0fb26e3159a9403a6f8d107c",
"package/dist/i18n/ar.js": "61c43469ee95a00dc624583f418653e3dcbf48b24ae6a4c203ad986234852365",
"package/dist/i18n/ar.mjs": "68922fdc9f80d3321ea0654c8ff8f5875b6715103d2b14ffcf17f93738b39cf9",
"package/dist/i18n/cs.js": "ad7bbf8853204a6955ef84bfbd932cab3f141a7e73a8145f28ba7a5b2b83b7c0",
"package/dist/i18n/cs.mjs": "29a489be767fda9d46b59c9adbaad323f17a5e67daf7f7aa78b7ce8fb5b4d63c",
"package/dist/i18n/es.js": "aaa95cc9645b734c58fba06fdbcdda962c4cb3a0e7eb6206f06d6168208cd86b",
"package/dist/i18n/es.mjs": "331d2ef74da2eec8f3304fec0b5340c795d9c1eec24e08167c9a7b66bf30973b",
"package/dist/i18n/fa.js": "c998467261cbdfd2c3fb16c0ae4b2c48c409f42f41aea35ed94766f1e12819d5",
"package/dist/i18n/fa.mjs": "b4c98894b46975cebf5ea9088bcf0b5bdfd408bc3c82f4e2e9128133c7de2d4d",
"package/dist/i18n/fr.js": "6b06e16b1fb01c8695fb5c10b32a00421399180de5dc5d845ce17010f2fd3e66",
"package/dist/i18n/fr.mjs": "abe8e3548fa7304f302e2c74818a6176edee8c3b65e33cb6f62e96d130749ee5",
"package/dist/i18n/id.js": "a5832c4bfc03c7f16418bf4b324d9773895541dc823ece9114741794737aad74",
"package/dist/i18n/id.mjs": "a40a433be6ca1ac1ee1810fe805ee60784d349e59b9ad82ea80201d660db4e68",
"package/dist/i18n/pl.js": "2491487062bdfc91d60f17c6e9a83ee196c991216d15f525fe3536b98873da2c",
"package/dist/i18n/pl.mjs": "ad8ea2c03785edbfe1f35761bec21b8a04213f9fa88a794d850bb3973564930f",
"package/dist/i18n/ru.js": "2d3a9ee6533cb6fa961f0a24a25ce63cc76992fca17e1769b6fa75104f8a1529",
"package/dist/i18n/ru.mjs": "a89b8c36cfd7c181c2b31aa823deda3d7c37b56b2b81746338c52ea1c1d93352",
"package/dist/i18n/tr.js": "438b06a4c3f479a2901b0085eaa7bdba8eaef87bdb07ff3faa559c85403fe433",
"package/dist/i18n/tr.mjs": "cc96f9cbb9c1587d5cd8f25b0b9800678ad76e93de089ae42c38dee16e6fe8fa",
"package/dist/i18n/vi.js": "1ffbd62843a902ea2967eab46432d3fc548f5633e53eed104314b523cacc46a8",
"package/dist/i18n/vi.mjs": "7872ded84622bcda20e8c1d70c597c2ba071b50701900efa47cc4683ee17f1a2",
"package/dist/i18n/zh-tw.js": "2d43577f98456488196921e1ec721695a95e1b8c827077286b02ce3fb987e8ff",
"package/dist/i18n/zh-tw.mjs": "7ec638b4babe59d3ab1d3e64abdd74a96fefb260a50e2cd7240f8d50a1340925",
"package/package.json": "b343df9955df9ac0ea71ea775bd0743c6b26c06d3bb7699128f7eac484fa769f",
"package/types/README.md": "4cc8175527081ef03cc5ff4616463da356159444be156dd7972a558eab5fc2f6",
"package/types/artplayer.d.cts": "949be8471bc369f4be21654f20c32eb8319944241b5389d1ba91f0d92b2d0195",
"package/types/artplayer.d.mts": "52bd9520a975f9b69d0169b2ef362dca8f8a3101127041930d3d81d8c7a6c51a",
"package/types/artplayer.d.ts": "e09779cdbc55fbab50928d01a12f737206b6bb0221f158e9733289a60f23fbe9",
"package/types/component.d.ts": "aa1c43be67322781b4b355b143bc69d9f29d22e578e4974d6a13e957a7c0334f",
"package/types/config.d.ts": "c4fd8681bf32b10c743e3e561c532520c8f32e43fd765524850b15e55cb91c72",
"package/types/cssVar.d.ts": "e027d82fb4f01c9ce7559cf679b2d5ee1962d3f7e5b4dd64ca21f472b933efb6",
"package/types/events.d.ts": "98c74aebb82455accc0b3523af5a1145bc9119da58c884200adc36e70a164b02",
"package/types/i18n.d.ts": "3e14759caf71f97f01650839248c8737c42d2c2979dabc43ad92b724da648708",
"package/types/icons.d.ts": "0d8e8e52e52130dd4a29bab551dd7a2a954797e42e92a6e068c85d583e23e6a4",
"package/types/language.d.cts": "1c9e0c47fae3c2d68c3e144d95a55071318a03bb31554dd049109efd3d0f95a4",
"package/types/language.d.mts": "c391e863012c77769e661afbf8fa949e9373aa88d17f58cbba7f5696edb8077f",
"package/types/legacy/language.d.ts": "c452ffd764ff9b29b819b3475c42395d2ea7a33560d8c186ef5df3844b9524c3",
"package/types/option.d.ts": "2407f08755cfe854821a65fb8c74b7ea5078d5b8f9cd9bdd3e67904529840585",
"package/types/player.d.ts": "986382bb6b4e82746fd2405092e69d0ef413988887a557a0fd4db85d64b78d54",
"package/types/quality.d.ts": "7ed6ed78cea52991b2f6ddd2bd3b7bd8c5146fdfff7486fe8b814c3e632f1567",
"package/types/setting.d.ts": "d12a75b656fff70cbb30be4bffec46d9c4273636e8722bce971a4d2b188712a1",
"package/types/subtitle.d.ts": "d25b470e47d6a9bd696d9c1ad8adb58e56a208f05695186d513bc8c43c2e8acf",
"package/types/template.d.ts": "68aed9e97d006d6be4fabb8504ca84dafab770b0925f4d6e7319e67c82f21b0d",
"package/types/utils.d.ts": "3957fa840e472b4da260a3179878550dd3b99ecd2ef27e85821abf446fa4d95e"
}
},
{
"name": "artplayer-plugin-chapter",
"version": "1.1.0",
"archive": "artplayer-plugin-chapter.tgz",
"sha256": "dbb3077746b1270d55b2add8ca0b28759732b87dcfe2ae3d0599abafbe9eb33e",
"files": {
"package/ARCHITECTURE.md": "20743bad87a174b0450e0d876b6aa6b2a9f47df296d479511ce7cc9298fdb57c",
"package/README.md": "b95400ff3d525621a15268bb56a2d353aacaaadefde7e735d7abd91a34edd96f",
"package/dist/artplayer-plugin-chapter.js": "6ac3dfe28f46084ac7caedd571b1a97dcee3cf9d708112f1b8bbd6566e1dc5c5",
"package/dist/artplayer-plugin-chapter.legacy.js": "6d9bff885412169e701670961aa00c2e46c4b42c9b9647ff4e6d198777d2a359",
"package/dist/artplayer-plugin-chapter.mjs": "26415cecab2c0198c566cef0232e20123413782d5bad7534a32939b3298617af",
"package/package.json": "24eec6907b3218439189adab6af3f932c1497c47c2d41209311c01042b07fd4f",
"package/types/artplayer-plugin-chapter.d.cts": "4f07514b37453cd6cea8e5aa28fa018ff31738e0d423c11a3b5eccd50ed30bcc",
"package/types/artplayer-plugin-chapter.d.mts": "610179754db36276e161a07bccf4eaba8b4480f053e716a2bcc5a1574871a171",
"package/types/artplayer-plugin-chapter.d.ts": "581aa2862e709601c87a23585f54a969ebd350be56a7469a31ff53f1311b578d"
}
}
],
"packageRuntimeChecks": 27,
"typeModes": [
{
"compiler": "5.9.3",
"mode": "node10-commonjs",
"diagnostics": [],
"declarations": [
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.decorators.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.decorators.legacy.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.dom.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.collection.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.core.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.generator.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.iterable.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.proxy.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.reflect.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.symbol.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2016.array.include.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2016.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2016.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.date.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.object.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.regexp.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.array.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.object.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.symbol.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.bigint.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.date.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.number.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es5.d.ts",
"node_modules/artplayer-plugin-chapter/types/artplayer-plugin-chapter.d.ts",
"node_modules/artplayer/types/artplayer.d.ts",
"node_modules/artplayer/types/component.d.ts",
"node_modules/artplayer/types/config.d.ts",
"node_modules/artplayer/types/cssVar.d.ts",
"node_modules/artplayer/types/events.d.ts",
"node_modules/artplayer/types/i18n.d.ts",
"node_modules/artplayer/types/icons.d.ts",
"node_modules/artplayer/types/legacy/language.d.ts",
"node_modules/artplayer/types/option.d.ts",
"node_modules/artplayer/types/player.d.ts",
"node_modules/artplayer/types/quality.d.ts",
"node_modules/artplayer/types/setting.d.ts",
"node_modules/artplayer/types/subtitle.d.ts",
"node_modules/artplayer/types/template.d.ts",
"node_modules/artplayer/types/utils.d.ts"
]
},
{
"compiler": "5.9.3",
"mode": "nodenext-cjs",
"diagnostics": [],
"declarations": [
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.decorators.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.decorators.legacy.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.dom.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.collection.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.core.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.generator.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.iterable.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.proxy.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.reflect.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.symbol.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2016.array.include.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2016.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2016.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.date.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.object.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.regexp.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.array.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.object.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.symbol.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.bigint.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.date.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.number.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es5.d.ts",
"node_modules/artplayer-plugin-chapter/types/artplayer-plugin-chapter.d.cts",
"node_modules/artplayer-plugin-chapter/types/artplayer-plugin-chapter.d.ts",
"node_modules/artplayer/types/artplayer.d.cts",
"node_modules/artplayer/types/artplayer.d.ts",
"node_modules/artplayer/types/component.d.ts",
"node_modules/artplayer/types/config.d.ts",
"node_modules/artplayer/types/cssVar.d.ts",
"node_modules/artplayer/types/events.d.ts",
"node_modules/artplayer/types/i18n.d.ts",
"node_modules/artplayer/types/icons.d.ts",
"node_modules/artplayer/types/language.d.cts",
"node_modules/artplayer/types/option.d.ts",
"node_modules/artplayer/types/player.d.ts",
"node_modules/artplayer/types/quality.d.ts",
"node_modules/artplayer/types/setting.d.ts",
"node_modules/artplayer/types/subtitle.d.ts",
"node_modules/artplayer/types/template.d.ts",
"node_modules/artplayer/types/utils.d.ts"
]
},
{
"compiler": "5.9.3",
"mode": "bundler-esm",
"diagnostics": [],
"declarations": [
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.decorators.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.decorators.legacy.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.dom.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.collection.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.core.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.generator.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.iterable.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.proxy.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.reflect.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.symbol.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2016.array.include.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2016.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2016.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.date.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.object.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.regexp.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.array.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.object.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.symbol.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.bigint.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.date.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.number.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es5.d.ts",
"node_modules/artplayer-plugin-chapter/types/artplayer-plugin-chapter.d.cts",
"node_modules/artplayer-plugin-chapter/types/artplayer-plugin-chapter.d.mts",
"node_modules/artplayer-plugin-chapter/types/artplayer-plugin-chapter.d.ts",
"node_modules/artplayer/types/artplayer.d.cts",
"node_modules/artplayer/types/artplayer.d.mts",
"node_modules/artplayer/types/artplayer.d.ts",
"node_modules/artplayer/types/component.d.ts",
"node_modules/artplayer/types/config.d.ts",
"node_modules/artplayer/types/cssVar.d.ts",
"node_modules/artplayer/types/events.d.ts",
"node_modules/artplayer/types/i18n.d.ts",
"node_modules/artplayer/types/icons.d.ts",
"node_modules/artplayer/types/language.d.cts",
"node_modules/artplayer/types/language.d.mts",
"node_modules/artplayer/types/option.d.ts",
"node_modules/artplayer/types/player.d.ts",
"node_modules/artplayer/types/quality.d.ts",
"node_modules/artplayer/types/setting.d.ts",
"node_modules/artplayer/types/subtitle.d.ts",
"node_modules/artplayer/types/template.d.ts",
"node_modules/artplayer/types/utils.d.ts"
]
},
{
"compiler": "4.3.5",
"mode": "node10-commonjs",
"diagnostics": [],
"declarations": [
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.dom.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2015.collection.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2015.core.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2015.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2015.generator.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2015.iterable.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2015.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2015.proxy.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2015.reflect.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2015.symbol.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2015.symbol.wellknown.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2016.array.include.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2016.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2017.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2017.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2017.object.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2017.sharedmemory.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2017.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2017.typedarrays.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2018.asyncgenerator.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2018.asynciterable.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2018.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2018.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2018.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2018.regexp.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2019.array.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2019.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2019.object.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2019.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2019.symbol.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2020.bigint.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2020.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2020.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2020.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2020.sharedmemory.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2020.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es2020.symbol.wellknown.d.ts",
"D:/github/ArtPlayer/node_modules/typescript-compat/lib/lib.es5.d.ts",
"node_modules/artplayer-plugin-chapter/types/artplayer-plugin-chapter.d.ts",
"node_modules/artplayer/types/artplayer.d.ts",
"node_modules/artplayer/types/component.d.ts",
"node_modules/artplayer/types/config.d.ts",
"node_modules/artplayer/types/cssVar.d.ts",
"node_modules/artplayer/types/events.d.ts",
"node_modules/artplayer/types/i18n.d.ts",
"node_modules/artplayer/types/icons.d.ts",
"node_modules/artplayer/types/legacy/language.d.ts",
"node_modules/artplayer/types/option.d.ts",
"node_modules/artplayer/types/player.d.ts",
"node_modules/artplayer/types/quality.d.ts",
"node_modules/artplayer/types/setting.d.ts",
"node_modules/artplayer/types/subtitle.d.ts",
"node_modules/artplayer/types/template.d.ts",
"node_modules/artplayer/types/utils.d.ts"
]
},
{
"compiler": "5.9.3",
"mode": "nodenext-esm",
"diagnostics": [],
"declarations": [
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.decorators.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.decorators.legacy.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.dom.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.collection.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.core.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.generator.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.iterable.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.proxy.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.reflect.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.symbol.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2016.array.include.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2016.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2016.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.date.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.object.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2018.regexp.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.array.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.object.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2019.symbol.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.bigint.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.date.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.intl.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.number.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.promise.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.string.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts",
"D:/github/ArtPlayer/node_modules/typescript/lib/lib.es5.d.ts",
"node_modules/artplayer-plugin-chapter/types/artplayer-plugin-chapter.d.cts",
"node_modules/artplayer-plugin-chapter/types/artplayer-plugin-chapter.d.mts",
"node_modules/artplayer-plugin-chapter/types/artplayer-plugin-chapter.d.ts",
"node_modules/artplayer/types/artplayer.d.cts",
"node_modules/artplayer/types/artplayer.d.mts",
"node_modules/artplayer/types/artplayer.d.ts",
"node_modules/artplayer/types/component.d.ts",
"node_modules/artplayer/types/config.d.ts",
"node_modules/artplayer/types/cssVar.d.ts",
"node_modules/artplayer/types/events.d.ts",
"node_modules/artplayer/types/i18n.d.ts",
"node_modules/artplayer/types/icons.d.ts",
"node_modules/artplayer/types/language.d.cts",
"node_modules/artplayer/types/language.d.mts",
"node_modules/artplayer/types/option.d.ts",
"node_modules/artplayer/types/player.d.ts",
"node_modules/artplayer/types/quality.d.ts",
"node_modules/artplayer/types/setting.d.ts",
"node_modules/artplayer/types/subtitle.d.ts",
"node_modules/artplayer/types/template.d.ts",
"node_modules/artplayer/types/utils.d.ts"
]
}
],
"browser": {
"stats": {
"startTime": "2026-09-10T17:27:57.881Z",
"duration": 7643.864,
"expected": 18,
"skipped": 0,
"unexpected": 0,
"flaky": 0
},
"cases": [
{
"title": "published: expanded option input preserves historical JS forms",
"engine": "chromium",
"browser": "153.0.8010.12"
},
{
"title": "published: configuration errors occur before mounting and preserve allocation timing",
"engine": "chromium",
"browser": "153.0.8010.12"
},
{
"title": "published: container identity, partial defaults, custom fields and normal callbacks",
"engine": "chromium",
"browser": "153.0.8010.12"
},
{
"title": "candidate: expanded option input preserves historical JS forms",
"engine": "chromium",
"browser": "153.0.8010.12"
},
{
"title": "candidate: configuration errors occur before mounting and preserve allocation timing",
"engine": "chromium",
"browser": "153.0.8010.12"
},
{
"title": "candidate: container identity, partial defaults, custom fields and normal callbacks",
"engine": "chromium",
"browser": "153.0.8010.12"
},
{
"title": "published: expanded option input preserves historical JS forms",
"engine": "firefox",
"browser": "155.0"
},
{
"title": "published: configuration errors occur before mounting and preserve allocation timing",
"engine": "firefox",
"browser": "155.0"
},
{
"title": "published: container identity, partial defaults, custom fields and normal callbacks",
"engine": "firefox",
"browser": "155.0"
},
{
"title": "candidate: expanded option input preserves historical JS forms",
"engine": "firefox",
"browser": "155.0"
},
{
"title": "candidate: configuration errors occur before mounting and preserve allocation timing",
"engine": "firefox",
"browser": "155.0"
},
{
"title": "candidate: container identity, partial defaults, custom fields and normal callbacks",
"engine": "firefox",
"browser": "155.0"
},
{
"title": "published: expanded option input preserves historical JS forms",
"engine": "webkit",
"browser": "26.6"
},
{
"title": "published: configuration errors occur before mounting and preserve allocation timing",
"engine": "webkit",
"browser": "26.6"
},
{
"title": "published: container identity, partial defaults, custom fields and normal callbacks",
"engine": "webkit",
"browser": "26.6"
},
{
"title": "candidate: expanded option input preserves historical JS forms",
"engine": "webkit",
"browser": "26.6"
},
{
"title": "candidate: configuration errors occur before mounting and preserve allocation timing",
"engine": "webkit",
"browser": "26.6"
},
{
"title": "candidate: container identity, partial defaults, custom fields and normal callbacks",
"engine": "webkit",
"browser": "26.6"
}
]
},
"historicalTypeDiagnostic": {
"version": "4.3.5",
"package": "artplayer@5.4.0",
"file": "types/artplayer.d.ts",
"line": 155,
"code": 2380,
"scope": "frozen published notice getter/setter only; candidate requires zero diagnostics"
},
"remaining": [
"plugins/toggle/timer return compatibility",
"setting returns and cue event shapes",
"static Emitter type",
"final complete task audit and commit"
]
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,66 @@
# CORE-07:公开声明逐项协调
本任务完成兼容扩展与逐项处置,不宣称所有历史返回类型已准确。BASE-TYPE-06 关闭;
BASE-TYPE-04/05/07 保持开放,并已接入后续模块任务及 CORE-21 声明出口。任务原验收允许
每项形成兼容扩展或待决结论;这些待决项没有作为发布豁免,不能在最终重构验收中算已解决。
## 已实施的兼容扩展
新增 OptionInput 和 ComponentInput。保留 Option.url 的必填字符串与 ComponentOption.html
的历史读取类型,构造函数和组件 add/update 用额外重载接受省略 URL、数字 HTML。
直接把 Option.url 改为可选会破坏旧的 `const url: string = option.url`,所以将新的输入形式
与旧命名类型分开。内部 ResolvedOption 基于 OptionInput 补齐默认值,不改变运行时配置。
原两项配置缺口负例已转为正例;旧 Option 读取另有正例保留。
Utils 新增已有运行时导出 unescape、ArtPlayerError,sleep 的 delay 改为可选;def 保留
历史 string-key/void 签名,再补充 PropertyKey/对象 identity 重载。string-key 调用的旧
void 类型仍优先,不将它描述为已全面精确化。没有返回类型交叉伪装或修改运行时来迎合声明。
declaration-inputs.ts 与 declaration-legacy.ts 已接入工作区及仓库外安装消费者。后者只编译,
记录历史合法但运行时不准确的用法,不作为推荐示例,也不实际执行错误的返回值假设。
## 逐项结论与接续条件
| 边界 | 源码事实 | 当前处理/剩余工作 |
| --- | --- | --- |
| plugins.add | 同步注册返回 registry,Promise 插件返回 Promise registry | 旧一律 Promise 与精确 union 无法同时满足旧赋值;保留旧签名,CORE-08/21 接续 BASE-TYPE-04 |
| toggle | pause 分支同步,play 分支返回原 Promise | 旧 void 赋值与 union 冲突;保留旧签名,CORE-10/21 接续 BASE-TYPE-04,拒绝不吞掉 |
| debounce/throttle | 回调结果被丢弃,debounce 第三参数不使用 | 旧 callback 返回赋值与 void 冲突;内部已精确,公开保留并注明实际行为,CORE-21 接续 BASE-TYPE-05 |
| def | Object.defineProperty 原函数,返回输入对象 | symbol/PropertyKey 入口补齐;string-key/void 优先级保留,CORE-21 接续 BASE-TYPE-05 |
| setting | find miss 为 null;add/update 返回 item;remove 为 undefined | 真实浏览器复现,旧返回赋值保留;CORE-14/21 接续 BASE-TYPE-07 |
| subtitle events | Before/AfterUpdate 发送 activeCues 数组 | 新增 SubtitleUpdateEvents 及显式数组监听重载;旧隐式 scalar 推断保持,CORE-15/21 接续 BASE-TYPE-07 |
| notice.show | getter 返回 boolean 显示状态 | 旧读取联合类型缺少 true;浏览器复现,CORE-18/21 接续 BASE-TYPE-07 |
| static Emitter | 可构造事件总线 | 新增类型 Emitter,支持 event map、payload/ctx、symbols、链式调用;保留构造参数接受范围 |
不能使用 `Registry & Promise<Registry>` 或 `Item & SettingRegistry` 来假装两个返回声明都
正确,也不能把同步调用改为 async 以满足旧声明。保留的声明处已经标注真实运行时含义;
新的内部模块使用精确 source 类型。旧名字、重载顺序、方法运行时和错误传播保持。
新的 Emitter 公开结构与真实 source 实例之间有直接可赋值检查,避免复制出漂移的空接口。
包内 [类型兼容说明](../../packages/artplayer/types/COMPATIBILITY.md) 是后续维护入口,记录
旧/实际类型、可执行用法、责任任务与验证命令。没有增加新的运行时导出或依赖。
## 当前验证证据
五组工作区与仓库外安装类型模式通过,安装包 27 项运行时检查通过;完整安装 UMD 三浏览器
144 项与 legacy 声明/配置 30 项通过,无重试/跳过。新增 12 项运行时对照验证原生字幕 cue、
插件同步/异步注册、拒绝 identity、真实 toggle 播放/暂停、设置返回 identity/null/void、
notice 可见值与静态事件 ctx。字幕 fixture 的 Blob URL 由测试额外回收,不证明生产资源清理。
yarn ci:check 共 112 项通过(83 单元、4 工程、25 冻结基线),28 个生产 TS 文件严格检查;
编辑器声明由 build:ts 生成,完整编辑器交互仍属 SITE/EX。本任务运行时 JS 产物与 CORE-06
相同,所有最终类型及包内文档已核对 tarball 指纹,文档格式变化后重新打包。
详见 [最终验证报告](../baselines/declarations-validation.json);
[前一批部分验证](../baselines/declaration-inputs-validation.json) 保留为实施过程,已由最终证据接续。
新增构造重载使错误 URL 的诊断由 TS2322 变为 TS2769;已核对两个编译器均拒绝两个重载,
测试检查准确的新错误代码和 number/string 原因,没有放宽有效性断言。
隔离的已发布 artplayer 5.4.0 在 TS 4.3.5 下于 types/artplayer.d.ts:155 报 TS2380:
notice.show 的 boolean getter 无法赋给旧 setter 类型。该错误发生在包声明,不在新增的
历史消费样例。测试冻结此文件/行/代码/消息;TS 5.9.3 旧消费零诊断,候选声明在两版 TS
均必须零诊断。未更改冻结 tarball 或基线文件,也没有用 skipLibCheck 绕过错误。
本任务独立提交;回退该提交可恢复声明、消费者、生成编辑器类型、文档及任务状态。
没有推送、发布、真机或远端 CI 通过结论。下一任务 CORE-08 插件管理器 TS 与扩展类型;
CORE-21 必须处理上表仍开放的声明方案,不能把本次协调完成当成它的验收证据。
+9 -8
View File
@@ -4,7 +4,7 @@
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 214 项,范围 22 个包及工作区/示例。
状态:todo 172 / doing 0 / blocked 0 / done 42 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
状态:todo 171 / doing 0 / blocked 0 / done 43 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
@@ -110,21 +110,21 @@
| CORE-04 | artplayer<br>修复初始化与销毁生命周期 | CORE-03, ENG-05, BASE-07 | 构造失败回收、重复/重入 destroy、instances 修复 | 事件顺序、removeHtml、多实例和销毁中异步有真实回归;处理 baselines/lifecycle-coverage.md 的 BASE-LIFE-04/05 并增加候选正向回归;协调 BASE-PERF-01 销毁后定时器与回调归属 | H | done |
| CORE-05 | artplayer<br>区分输入配置和内部配置 | CORE-01, ENG-04 | Option/ResolvedOption、默认值与校验整理 | 配置合并/错误时机不变,JS 输入仍运行时校验 | M | done |
| 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 | todo |
| CORE-08 | artplayer<br>整理插件管理器与扩展类型 | CORE-03, CORE-07 | 注册流程、同步/异步结果、插件/事件扩展接口 | 旧插件同步可见性、重名与命名、销毁中异步插件保持明确语义;处理 baselines/lifecycle-coverage.md 的 BASE-LIFE-03 并增加候选正向回归 | H | todo |
| 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 | 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 | todo |
| CORE-10 | artplayer<br>迁移播放与时间/状态属性 | CORE-09 | play/pause/toggle/seek/volume/rate/duration 等模块 | 旧返回值、拒绝、mutex、位置恢复、属性描述符与事件通过 | H | todo |
| 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 |
| CORE-13 | artplayer<br>迁移组件注册与控件 | CORE-12, CORE-08 | Component/control/layer/contextmenu 的资源与 TS 边界 | add/update/remove、name、selector、mounted/beforeUnmount 通过;处理 BASE-DOM-02 窄容器控件裁切,保留 controls.update 的旧 undefined 返回值 | H | todo |
| CORE-14 | artplayer<br>拆分设置树、渲染和布局 | CORE-13 | setting model/selection/render/layout 的分批实现 | 不强行统一控件返回值,嵌套选择、默认高亮、更新清理通过;结合 BASE-DOM-02 验证窄容器设置定位 | H | todo |
| CORE-15 | artplayer<br>迁移字幕获取、解析和渲染 | CORE-11, CORE-13 | subtitle 请求/track/DOM/URL 生命周期与类型 | 过期结果、偏移、cue 数组、原生全屏及错误路径通过 | H | todo |
| CORE-14 | artplayer<br>拆分设置树、渲染和布局 | CORE-13 | setting model/selection/render/layout 的分批实现 | 不强行统一控件返回值,嵌套选择、默认高亮、更新清理通过;结合 BASE-DOM-02 验证窄容器设置定位;接续 BASE-TYPE-07 的 find null、add/update item、remove undefined 声明冲突 | H | todo |
| CORE-15 | artplayer<br>迁移字幕获取、解析和渲染 | CORE-11, CORE-13 | subtitle 请求/track/DOM/URL 生命周期与类型 | 过期结果、偏移、cue 数组、原生全屏及错误路径通过;接续 BASE-TYPE-07 的真实 cue 数组与旧隐式 scalar 回调声明兼容 | H | todo |
| CORE-16 | artplayer<br>迁移全屏、PiP、mini 与尺寸模式 | CORE-11, CORE-12 | 显示模式服务和原公开属性门面 | 模式互斥/恢复位置、手势权限、移动方向和退出失败通过 | H | todo |
| CORE-17 | artplayer<br>迁移键盘、手势、焦点和全局事件 | CORE-13, CORE-16 | events/hotkey 的明确 document 与资源归属 | 跨 document 重绑、触摸/键盘、快捷键及销毁无重复响应;修复 BASE-PERF-01 pending resize debounce 销毁后执行,并验证正常 resize 不变 | H | todo |
| CORE-18 | artplayer<br>迁移内置插件和提示模块 | CORE-14, CORE-16, CORE-17 | autoPlayback/autoOrientation/fastForward/lock/miniProgressBar 及 info/notice/loading/mask | 默认启用条件、storage 格式、定时器/动画清理通过;结合 BASE-PERF-01 防止销毁后重新安排 notice timer | M | todo |
| CORE-18 | artplayer<br>迁移内置插件和提示模块 | CORE-14, CORE-16, CORE-17 | autoPlayback/autoOrientation/fastForward/lock/miniProgressBar 及 info/notice/loading/mask | 默认启用条件、storage 格式、定时器/动画清理通过;结合 BASE-PERF-01 防止销毁后重新安排 notice timer;接续 BASE-TYPE-07 的 notice.show boolean getter 与历史读类型冲突 | M | todo |
| CORE-19 | artplayer<br>整理进度、质量、缩略图和截图 | CORE-10, CORE-13, CORE-16 | 相关 player/control 功能与纯计算分离 | 截图跨域失败、缩略图布局、quality/进度边界保持 | M | todo |
| CORE-20 | artplayer<br>收敛核心入口与依赖方向 | CORE-14, CORE-15, CORE-18, CORE-19 | Artplayer 门面、初始化依赖与最终目录 | 所有核心自有源码迁移,公开描述符/静态接口/事件差分通过 | H | todo |
| CORE-21 | artplayer<br>生成核心声明并校验包内容 | CORE-20, ENG-07 | 由 TS 生成的既有入口声明与三种发布产物 | 内部类型不泄漏,旧 JS/TS 消费者与 i18n 通过 | H | todo |
| CORE-21 | artplayer<br>生成核心声明并校验包内容 | CORE-20, ENG-07 | 由 TS 生成的既有入口声明与三种发布产物 | 内部类型不泄漏,旧 JS/TS 消费者与 i18n 通过;逐项完成 CORE-07 留下的 BASE-TYPE-04/05/07 声明方案,旧合法消费者与实际返回分别留证;不能以虚假的交叉返回类型或改变运行时来掩盖冲突,未决项阻止核心声明出口 | H | todo |
| CORE-23 | artplayer<br>检查并补齐键盘、焦点与可访问名称 | CORE-13, CORE-14, CORE-17, ENG-05, BASE-04 | 主要控件/设置/模式退出的键盘与焦点回归、名称和字幕可用性检查及必要兼容修正 | 保持旧快捷键和 DOM/CSS 钩子;真实浏览器验证,不以静态属性检查代替交互;处理 BASE-DOM-01 的主要控件 Tab 不可达,保留既有名称与快捷键 | H | todo |
| CORE-22 | artplayer<br>核心阶段完整验收 | CORE-21, CORE-23, PILOT-01, ENG-08, ENG-10 | 核心与旧插件的可自动化完整回归、资源/性能及明确外部验证缺口 | 核心自动化和公开差异处置通过;真实环境缺口链接包集成/REL 门槛,阶段完成不代表可公开发布 | H | todo |
@@ -441,6 +441,7 @@
- CORE-04: [记录](changes/2026-09-11-CORE-04-instance-lifecycle.md) [记录](baselines/instance-lifecycle-validation.json)
- CORE-05: [记录](changes/2026-09-11-CORE-05-resolved-options.md) [记录](baselines/options-validation.json)
- 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)
- 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)
+8
View File
@@ -1,5 +1,13 @@
# 进度与证据
## 当前实施:CORE-07 公开声明逐项协调完成
OptionInput、数字组件输入、Utils 缺失项、静态 Emitter 和显式 cue 数组重载已补充,旧合法返回赋值样例保留。112 项 Node/基线、安装 UMD 三浏览器 144 项及 legacy 声明/配置 30 项通过;严格打包 27 项运行时与五组类型零诊断。见 [交付](changes/2026-09-11-CORE-07-declarations.md)。关闭 BASE-TYPE-06;BASE-TYPE-04/05/07 的返回/隐式推断冲突保持开放,已接入模块任务与 CORE-21 出口,不代表全部公开类型已精确化。当前 214 项,43 完成、171 待办;下一项 CORE-08 插件管理器与扩展类型。
## 当前实施:CORE-07 公开声明协调进行中
已补充 OptionInput/ComponentInput 和兼容重载,保留旧 Option 读取类型;补齐部分 Utils 声明,新增历史返回值消费样例。112 项 Node/基线、五组安装包类型及 18 项配置浏览器测试通过,见 [当前记录](changes/2026-09-11-CORE-07-declarations.md)。plugins/toggle/timer/setting/cue/static 仍需逐项协调,本任务保持 doing,尚未提交。当前 214 项,42 完成、1 实施、171 待办;上个完成任务 CORE-06 提交 ee859e48。
## 当前实施:CORE-06 媒体与宿主类型完成
建立原生 video/canvas 媒体及最小宿主类型,五个播放/布局 mixin 迁移 TS,保持公开 art.video 身份、描述符和返回时序。111 项 Node/基线、安装 UMD 三浏览器 132 项及 legacy 播放/生命周期/代理 48 项通过;严格打包 27 项运行时、五组类型零诊断。见 [交付](changes/2026-09-11-CORE-06-media-hosts.md)。当前 214 项,42 完成、172 待办;核心二十三个 TS 文件、chapter 五个。代理完整迁移和主入口静态集成尚未完成;下一项 CORE-07 逐项协调公开声明差异。
+4 -3
View File
@@ -16,7 +16,7 @@
| BASE-TYPE-01 | resolved / 已复现 | NodeNext ESM 默认导出与声明互操作失配 | ENG-04, CORE-07, PKG-CHAPTER-04 |
| BASE-TYPE-02 | resolved / 已复现 | chapter 可选运行时参数被声明为必填 | PKG-CHAPTER-02 |
| BASE-TYPE-03 | resolved / 已复现 | chapter legacy 缺旧模块解析的声明回退 | ENG-04, PKG-CHAPTER-04 |
| BASE-TYPE-04 | open / 源码/产物事实 | plugins.add / toggle 的旧声明返回值与运行时不同 | CORE-07 |
| BASE-TYPE-04 | open / 已复现 | plugins.add / toggle 的旧声明返回值与运行时不同 | CORE-07, CORE-08, CORE-10, CORE-21 |
| BASE-DIST-01 | open / 源码/产物事实 | thumbnail tool 分发入口与类型文件缺失 | PKG-TOOL-THUMB-01, PKG-TOOL-THUMB-04 |
| BASE-PERF-01 | resolved / 已复现 | 销毁后的 resize 防抖重新创建 notice timer | CORE-17, CORE-04, CORE-18 |
| BASE-SOURCE-01 | open / 源码/产物事实 | 工作区 5.4.1 与采集时真实发布 5.4.0 不同 | BASE-08, REL-01 |
@@ -46,7 +46,8 @@
| BUILD-AMD-01 | resolved / 已复现 | AMD 全局导出补丁误将固定参数 t 当作全局对象 | ENG-06 |
| UTIL-MERGE-01 | resolved / 已复现 | mergeDeep lets a JSON __proto__ key replace the result prototype | CORE-01 |
| UTIL-DOWNLOAD-01 | resolved / 源码/产物事实 | Temporary download anchor remains if click throws | CORE-01 |
| BASE-TYPE-05 | open / 源码/产物事实 | Public Utils declarations omit exports and misstate timer/descriptor signatures | CORE-07 |
| BASE-TYPE-05 | open / 源码/产物事实 | Public Utils declarations omit exports and misstate timer/descriptor signatures | CORE-07, CORE-21 |
| EVENT-NAME-01 | resolved / 已复现 | Emitter event names collide with Object.prototype | CORE-02 |
| EVENT-ONCE-01 | resolved / 已复现 | Nested dispatch snapshots invoke the same once registration twice | CORE-02 |
| BASE-TYPE-06 | open / 已复现 | Public Option requires url and excludes numeric control HTML accepted by existing JS | CORE-07 |
| BASE-TYPE-06 | resolved / 已复现 | Public Option requires url and excludes numeric control HTML accepted by existing JS | CORE-07 |
| BASE-TYPE-07 | open / 已复现 | Setting returns, subtitle contextual payloads and notice getter conflict with historical declarations | CORE-07, CORE-14, CORE-15, CORE-18, CORE-21 |
+50 -9
View File
@@ -232,19 +232,25 @@
{
"id": "BASE-TYPE-04",
"title": "plugins.add / toggle 的旧声明返回值与运行时不同",
"confirmation": "source-observed",
"confirmation": "reproduced",
"status": "open",
"owners": [
"CORE-07"
"CORE-07",
"CORE-08",
"CORE-10",
"CORE-21"
],
"evidence": [
"refactor/baselines/consumers.json",
"refactor/baselines/public-api.json",
"refactor/baselines/lifecycle.json"
"refactor/baselines/lifecycle.json",
"test/types/declaration-legacy.ts",
"refactor/changes/2026-09-11-CORE-07-declarations.md",
"refactor/baselines/declarations-validation.json"
],
"compatibleResolution": "保留旧声明接受范围并协调精确重载/扩展,不静默把同步注册改成 async。",
"closureCriteria": "返回值类型与运行时差异逐项说明,旧合法消费和拒绝传播回归通过。",
"scopeNote": "plugins.add synchronous result is browser-reproduced; toggle return comparison also relies on current source/playback tests. Do not claim every declaration mismatch was independently browser-reproduced."
"scopeNote": "CORE-07 retains historical legal return assignments and records actual runtime separately; incompatible return tightening remains open through CORE-21. No release waiver."
},
{
"id": "BASE-DIST-01",
@@ -726,16 +732,21 @@
"confirmation": "source-observed",
"status": "open",
"owners": [
"CORE-07"
"CORE-07",
"CORE-21"
],
"evidence": [
"packages/artplayer/types/utils.d.ts",
"test/utils.test.js",
"test/types/utils-source.ts",
"refactor/changes/2026-09-10-CORE-01-typed-utils.md"
"refactor/changes/2026-09-10-CORE-01-typed-utils.md",
"test/types/declaration-legacy.ts",
"refactor/changes/2026-09-11-CORE-07-declarations.md",
"refactor/baselines/declarations-validation.json"
],
"compatibleResolution": "Coordinate compatible public overloads/exports separately; use accurate strict types in migrated source.",
"closureCriteria": "Cover missing unescape/ArtPlayerError, def identity/property keys, optional sleep, timer void returns and ignored debounce context; retain legal old consumers in new/old compilers."
"closureCriteria": "Cover missing unescape/ArtPlayerError, def identity/property keys, optional sleep, timer void returns and ignored debounce context; retain legal old consumers in new/old compilers.",
"scopeNote": "CORE-07 retains historical legal return assignments and records actual runtime separately; incompatible return tightening remains open through CORE-21. No release waiver."
},
{
"id": "EVENT-NAME-01",
@@ -787,7 +798,7 @@
"id": "BASE-TYPE-06",
"title": "Public Option requires url and excludes numeric control HTML accepted by existing JS",
"confirmation": "reproduced",
"status": "open",
"status": "resolved",
"owners": [
"CORE-07"
],
@@ -798,7 +809,37 @@
"refactor/changes/2026-09-11-CORE-05-resolved-options.md"
],
"compatibleResolution": "Expand public declarations for the verified legal JS forms; preserve existing typed inputs and runtime defaults.",
"closureCriteria": "Replace the two historical negative fixtures with positive public consumers and verify old/new TypeScript plus installed package modes."
"closureCriteria": "Replace the two historical negative fixtures with positive public consumers and verify old/new TypeScript plus installed package modes.",
"resolutionEvidence": [
"refactor/changes/2026-09-11-CORE-07-declarations.md",
"refactor/baselines/declarations-validation.json",
"test/types/declaration-inputs.ts",
"test/browser/options.spec.js"
],
"resolutionRationale": "Additive OptionInput/ComponentInput and constructor/component overloads accept omitted URL and numeric HTML while preserving historical Option reads. Five installed compiler modes and old/new core browser input cases pass."
},
{
"id": "BASE-TYPE-07",
"title": "Setting returns, subtitle contextual payloads and notice getter conflict with historical declarations",
"confirmation": "reproduced",
"status": "open",
"owners": [
"CORE-07",
"CORE-14",
"CORE-15",
"CORE-18",
"CORE-21"
],
"evidence": [
"test/browser/declarations.spec.js",
"test/types/declaration-legacy.ts",
"packages/artplayer/types/artplayer.d.ts",
"packages/artplayer/types/events.d.ts",
"refactor/baselines/declarations-validation.json"
],
"compatibleResolution": "Keep legacy consumers; add explicit cue-array listener overloads, type internal implementations accurately, and resolve remaining generated/public facade contracts at CORE-21 without false intersections.",
"closureCriteria": "Actual setting/null/void and notice boolean returns, cue array callbacks and old legal type consumers all have an explicit compatible declaration strategy and package tests.",
"scopeNote": "CORE-07 provides runtime evidence and explicit cue-array overloads; old inferred scalar event callbacks and return signatures are not claimed corrected."
}
]
}
+38 -2
View File
@@ -5,19 +5,55 @@ import test from 'node:test'
import ts from 'typescript'
import compat from 'typescript-compat'
import { checkConsumer, checkProject } from '../../scripts/typecheck.mjs'
import { refactorDir } from './releases.mjs'
import { ensureArchive, hash, readMember, refactorDir } from './releases.mjs'
test('Current and compatibility compilers reject invalid old public calls and unused error assertions', () => {
const original = fs.readFileSync(path.join(refactorDir, '../test/types/public.ts'), 'utf8')
for (const compiler of [ts, compat]) {
assert.deepEqual(checkConsumer(compiler, 'node10-commonjs'), [])
const invalid = "import Artplayer from 'artplayer'; new Artplayer({ container: '#player', url: 42 });"
assert(checkConsumer(compiler, 'node10-commonjs', invalid).some(d => d.code === 2322))
const diagnostics = checkConsumer(compiler, 'node10-commonjs', invalid)
assert.deepEqual(diagnostics.map(d => d.code), [2769], 'Both constructor overloads must reject the numeric URL')
assert.match(diagnostics[0].message, /Type 'number' is not assignable to type 'string/)
const unused = original.replace('url: 42', "url: 'valid.mp4'")
assert(checkConsumer(compiler, 'node10-commonjs', unused).some(d => d.code === 2578))
}
})
test('Historical return assignments retain exact published diagnostics and current acceptance', async () => {
const release = JSON.parse(fs.readFileSync(path.join(refactorDir, 'baselines/releases.json'), 'utf8')).releases.find(item => item.name === 'artplayer')
const archive = await ensureArchive(release)
const parent = path.join(refactorDir, '.cache')
const dir = fs.mkdtempSync(path.join(parent, 'legacy-types-'))
try {
for (const [member, digest] of Object.entries(release.files)) {
if (member !== 'package/package.json' && !member.startsWith('package/types/')) continue
const bytes = readMember(archive, member)
assert.equal(hash(bytes), digest)
const target = path.resolve(dir, 'node_modules/artplayer', member.slice('package/'.length))
assert(target.startsWith(path.join(dir, 'node_modules/artplayer') + path.sep))
fs.mkdirSync(path.dirname(target), { recursive: true })
fs.writeFileSync(target, bytes)
}
const filename = path.join(dir, 'legacy.ts')
fs.copyFileSync(path.join(refactorDir, '../test/types/declaration-legacy.ts'), filename)
for (const compiler of [ts, compat]) {
const program = compiler.createProgram([filename], { strict: true, noEmit: true, skipLibCheck: false, types: [], esModuleInterop: true, target: compiler.ScriptTarget.ES2020, module: compiler.ModuleKind.CommonJS, moduleResolution: compiler.ModuleResolutionKind.NodeJs, lib: ['lib.es2020.d.ts', 'lib.dom.d.ts'] })
const declarations = program.getSourceFiles().filter(file => file.fileName.replaceAll('\\', '/').includes('/artplayer/types/'))
assert(declarations.length > 0)
assert(declarations.every(file => path.resolve(file.fileName).startsWith(path.join(dir, 'node_modules/artplayer') + path.sep)))
const expected = compiler === compat ? [{ file: 'node_modules/artplayer/types/artplayer.d.ts', line: 155, code: 2380, message: "The return type of a 'get' accessor must be assignable to its 'set' accessor type" }] : []
assert.deepEqual(compiler.getPreEmitDiagnostics(program).map(d => ({ file: d.file && path.relative(dir, d.file.fileName).replaceAll('\\', '/'), line: d.file && d.file.getLineAndCharacterOfPosition(d.start).line + 1, code: d.code, message: compiler.flattenDiagnosticMessageText(d.messageText, '\n') })), expected, `TS ${compiler.version} historical consumer`)
assert.deepEqual(checkConsumer(compiler, 'node10-commonjs', fs.readFileSync(filename, 'utf8')), [], 'Current declarations must have zero diagnostics, including TS 4.3.5')
}
}
finally {
const resolved = fs.realpathSync(dir)
assert(path.dirname(resolved) === fs.realpathSync(parent) && path.basename(resolved).startsWith('legacy-types-'))
fs.rmSync(resolved, { recursive: true, force: true })
}
})
test('Browser implementation configuration catches source errors without emitting JavaScript', () => {
const parent = path.join(refactorDir, '.cache')
fs.mkdirSync(parent, { recursive: true })
+11 -8
View File
@@ -870,11 +870,14 @@
"CORE-06",
"BASE-07"
],
"status": "todo",
"status": "done",
"risk": "H",
"deliverable": "plugins/toggle/cue/setting/static 的旧新类型对照",
"acceptance": "每项有兼容重载/扩展或待决结论,不能删除旧类型样例;处理 BASE-TYPE-01/04,分别保留旧合法声明消费并验证真实返回;协调 BASE-TYPE-05 的 Utils 导出、descriptor 和 timer 旧声明差异",
"evidence": []
"evidence": [
"changes/2026-09-11-CORE-07-declarations.md",
"baselines/declarations-validation.json"
]
},
{
"id": "CORE-08",
@@ -890,7 +893,7 @@
"status": "todo",
"risk": "H",
"deliverable": "注册流程、同步/异步结果、插件/事件扩展接口",
"acceptance": "旧插件同步可见性、重名与命名、销毁中异步插件保持明确语义;处理 baselines/lifecycle-coverage.md 的 BASE-LIFE-03 并增加候选正向回归",
"acceptance": "旧插件同步可见性、重名与命名、销毁中异步插件保持明确语义;处理 baselines/lifecycle-coverage.md 的 BASE-LIFE-03 并增加候选正向回归;接续 CORE-07 / BASE-TYPE-04 的同步/异步注册返回声明冲突,内部返回类型精确,保留历史消费者",
"evidence": []
},
{
@@ -924,7 +927,7 @@
"status": "todo",
"risk": "H",
"deliverable": "play/pause/toggle/seek/volume/rate/duration 等模块",
"acceptance": "旧返回值、拒绝、mutex、位置恢复、属性描述符与事件通过",
"acceptance": "旧返回值、拒绝、mutex、位置恢复、属性描述符与事件通过;接续 CORE-07 / BASE-TYPE-04 的 toggle void 与实际 Promise 分支冲突,不吞拒绝",
"evidence": []
},
{
@@ -991,7 +994,7 @@
"status": "todo",
"risk": "H",
"deliverable": "setting model/selection/render/layout 的分批实现",
"acceptance": "不强行统一控件返回值,嵌套选择、默认高亮、更新清理通过;结合 BASE-DOM-02 验证窄容器设置定位",
"acceptance": "不强行统一控件返回值,嵌套选择、默认高亮、更新清理通过;结合 BASE-DOM-02 验证窄容器设置定位;接续 BASE-TYPE-07 的 find null、add/update item、remove undefined 声明冲突",
"evidence": []
},
{
@@ -1008,7 +1011,7 @@
"status": "todo",
"risk": "H",
"deliverable": "subtitle 请求/track/DOM/URL 生命周期与类型",
"acceptance": "过期结果、偏移、cue 数组、原生全屏及错误路径通过",
"acceptance": "过期结果、偏移、cue 数组、原生全屏及错误路径通过;接续 BASE-TYPE-07 的真实 cue 数组与旧隐式 scalar 回调声明兼容",
"evidence": []
},
{
@@ -1060,7 +1063,7 @@
"status": "todo",
"risk": "M",
"deliverable": "autoPlayback/autoOrientation/fastForward/lock/miniProgressBar 及 info/notice/loading/mask",
"acceptance": "默认启用条件、storage 格式、定时器/动画清理通过;结合 BASE-PERF-01 防止销毁后重新安排 notice timer",
"acceptance": "默认启用条件、storage 格式、定时器/动画清理通过;结合 BASE-PERF-01 防止销毁后重新安排 notice timer;接续 BASE-TYPE-07 的 notice.show boolean getter 与历史读类型冲突",
"evidence": []
},
{
@@ -1114,7 +1117,7 @@
"status": "todo",
"risk": "H",
"deliverable": "由 TS 生成的既有入口声明与三种发布产物",
"acceptance": "内部类型不泄漏,旧 JS/TS 消费者与 i18n 通过",
"acceptance": "内部类型不泄漏,旧 JS/TS 消费者与 i18n 通过;逐项完成 CORE-07 留下的 BASE-TYPE-04/05/07 声明方案,旧合法消费者与实际返回分别留证;不能以虚假的交叉返回类型或改变运行时来掩盖冲突,未决项阻止核心声明出口",
"evidence": []
},
{
+1 -1
View File
@@ -38,7 +38,7 @@ export function typeConsumers(dir) {
for (const [compiler, mode] of [[ts, 'node10-commonjs'], [ts, 'nodenext-cjs'], [ts, 'bundler-esm'], [compat, 'node10-commonjs'], [ts, 'nodenext-esm']]) {
const next = mode.startsWith('nodenext')
const extension = next ? (mode.endsWith('-cjs') ? 'cts' : 'mts') : 'ts'
const inputs = ['public', 'chapter-options', 'chapter-exports', 'language-value', 'language', 'legacy-plugin']
const inputs = ['public', 'declaration-inputs', 'declaration-legacy', 'chapter-options', 'chapter-exports', 'language-value', 'language', 'legacy-plugin']
if (mode === 'nodenext-cjs')
inputs.push('commonjs')
const files = inputs.map((name) => {
+1 -1
View File
@@ -71,7 +71,7 @@ export function runTypechecks() {
console.log(`Strict project passed: ${relative(config)} (${result.files.length} root files)`)
}
for (const [compiler, mode] of [[ts, 'node10-commonjs'], [ts, 'nodenext-cjs'], [ts, 'bundler-esm'], [ts, 'nodenext-esm'], [compat, 'node10-commonjs']]) {
for (const fixture of ['test/types/public.ts', 'test/types/chapter-options.ts', 'test/types/chapter-exports.ts', 'test/types/language-value.ts', 'refactor/fixtures/consumers/language.ts', 'refactor/fixtures/consumers/legacy-plugin.ts']) {
for (const fixture of ['test/types/public.ts', 'test/types/declaration-inputs.ts', 'test/types/declaration-legacy.ts', 'test/types/chapter-options.ts', 'test/types/chapter-exports.ts', 'test/types/language-value.ts', 'refactor/fixtures/consumers/language.ts', 'refactor/fixtures/consumers/legacy-plugin.ts']) {
assert.deepEqual(checkConsumer(compiler, mode, fs.readFileSync(path.join(root, fixture), 'utf8')), [], `Consumer failed: TS ${compiler.version} ${mode} ${fixture}`)
}
if (mode === 'nodenext-cjs')
+97
View File
@@ -0,0 +1,97 @@
import { expect, test } from './fixtures.js'
for (const core of ['published', 'candidate']) {
test(`${core}: plugin, toggle, setting and static runtime return contracts`, async ({ page }) => {
await page.goto(`/test/player.html?core=${core}&chapter=published`)
await page.evaluate(() => {
const container = document.createElement('div')
Object.assign(container.style, { width: '640px', height: '360px' })
document.body.append(container)
window.art = new window.Artplayer({ container, url: '/test/pattern.mp4', muted: true, setting: true })
})
await expect.poll(() => page.evaluate(() => window.art.isReady)).toBe(true)
const values = await page.evaluate(async () => {
const art = window.art
const sync = art.plugins.add(() => ({ name: 'syncContract' }))
const promise = art.plugins.add(async () => ({ name: 'asyncContract' }))
const before = art.plugins.asyncContract === undefined
const asyncResult = await promise
const failure = new Error('plugin rejection contract')
const rejected = await art.plugins.add(() => Promise.reject(failure)).catch(error => error === failure)
const item = { name: 'returnContract', html: 'Initial' }
const added = art.setting.add(item)
const updated = art.setting.update({ name: 'returnContract', html: 'Updated' })
const identity = art.setting.find('returnContract') === item
const html = item.$html.textContent
const removed = art.setting.remove('returnContract')
const missing = art.setting.find('returnContract')
art.notice.show = 'Visible notice'
const notice = art.notice.show
const emitter = new art.constructor.Emitter('ignored')
let received
const ctx = { value: 2 }
const chained = emitter.on('contract', function (payload) {
received = this.value + payload
}, ctx).emit('contract', 3) === emitter
return {
syncRegistry: sync === art.plugins,
syncThen: typeof sync.then,
asyncPromise: promise instanceof Promise,
asyncPending: before,
asyncRegistry: asyncResult === art.plugins,
rejected,
addedItem: added === item,
updatedItem: updated === item,
foundItem: identity,
html,
removedType: typeof removed,
missing,
notice,
chained,
received,
}
})
expect(values).toEqual({ syncRegistry: true, syncThen: 'undefined', asyncPromise: true, asyncPending: true, asyncRegistry: true, rejected: true, addedItem: true, updatedItem: true, foundItem: true, html: 'Updated', removedType: 'undefined', missing: null, notice: true, chained: true, received: 5 })
expect(await page.evaluate(async () => {
const result = window.art.toggle()
const promise = result instanceof Promise
await result
return promise
})).toBe(true)
await expect.poll(() => page.evaluate(() => window.art.playing)).toBe(true)
expect(await page.evaluate(() => typeof window.art.toggle())).toBe('undefined')
expect(await page.evaluate(() => window.art.playing)).toBe(false)
await page.evaluate(() => window.art.destroy())
})
test(`${core}: native subtitle update events carry cue arrays`, async ({ page }) => {
await page.goto(`/test/player.html?core=${core}&chapter=published`)
await page.evaluate(() => {
const container = document.createElement('div')
Object.assign(container.style, { width: '640px', height: '360px' })
document.body.append(container)
const art = window.art = new window.Artplayer({ container, url: '/test/pattern.mp4', muted: true, subtitle: { url: '/test/declaration-cues.vtt' } })
window.cueEvents = []
for (const name of ['subtitleBeforeUpdate', 'subtitleAfterUpdate']) {
art.on(name, (cues) => {
window.cueEvents.push({ name, array: Array.isArray(cues), length: cues.length, native: cues[0] instanceof VTTCue, same: cues[0] === art.subtitle.textTrack.cues[0], text: cues[0]?.text })
})
}
})
await expect.poll(() => page.evaluate(() => window.art.isReady && window.art.subtitle.cues.length === 1)).toBe(true)
await page.evaluate(() => {
window.art.seek = 1
})
await expect.poll(() => page.evaluate(() => window.cueEvents.some(event => event.name === 'subtitleAfterUpdate'))).toBe(true)
const events = await page.evaluate(() => window.cueEvents)
for (const name of ['subtitleBeforeUpdate', 'subtitleAfterUpdate'])
expect(events.find(event => event.name === name)).toEqual({ name, array: true, length: 1, native: true, same: true, text: 'Declaration cue' })
expect(await page.evaluate(() => window.art.template.$subtitle.textContent.trim())).toBe('Declaration cue')
await page.evaluate(() => {
const url = window.art.template.$track.src
window.art.destroy()
// Explicit test teardown; subtitle URL ownership is still tracked by CORE-15.
URL.revokeObjectURL(url)
})
})
}
+4
View File
@@ -0,0 +1,4 @@
WEBVTT
00:00:00.000 --> 00:00:04.000
Declaration cue
+12 -4
View File
@@ -1,17 +1,25 @@
import { expect, test } from './fixtures.js'
for (const core of ['published', 'candidate']) {
test(`${core}: historical JS option forms remain accepted despite declaration gaps`, async ({ page }) => {
test(`${core}: expanded option input preserves historical JS forms`, async ({ page }) => {
await page.goto(`/test/player.html?core=${core}&chapter=published`)
const result = await page.evaluate(() => {
const container = document.createElement('div')
document.body.append(container)
const art = new window.Artplayer({ container, controls: [{ name: 'numeric', html: 42, position: 'left' }] })
const result = { url: art.option.url, html: art.controls.numeric.textContent }
const art = new window.Artplayer({
container,
controls: [{ name: 'numeric', html: 42, position: 'left' }],
layers: [{ name: 'numeric', html: 43 }],
contextmenu: [{ name: 'numeric', html: 44 }],
})
const result = { url: art.option.url, html: art.controls.numeric.textContent, layer: art.layers.numeric.textContent, menu: art.contextmenu.numeric.textContent }
art.controls.update({ name: 'numeric', html: 45, position: 'left' })
result.updated = art.controls.numeric.textContent
result.added = art.layers.add({ name: 'added', html: 46 }).textContent
art.destroy()
return result
})
expect(result).toEqual({ url: '', html: '42' })
expect(result).toEqual({ url: '', html: '42', layer: '43', menu: '44', updated: '45', added: '46' })
})
test(`${core}: configuration errors occur before mounting and preserve allocation timing`, async ({ page }) => {
+1
View File
@@ -60,6 +60,7 @@ for (const extension of ['mp4', 'webm']) {
}
const mime = { '.html': 'text/html', '.js': 'text/javascript', '.mjs': 'text/javascript', '.json': 'application/json', '.css': 'text/css', '.mp4': 'video/mp4', '.webm': 'video/webm', '.vtt': 'text/vtt', '.svg': 'image/svg+xml', '.png': 'image/png', '.jpg': 'image/jpeg' }
add('/test/declaration-cues.vtt', fs.readFileSync(path.join(workspace, 'test/browser/media/declaration-cues.vtt')), { kind: 'test-subtitles', file: 'test/browser/media/declaration-cues.vtt' })
function send(req, res, bytes, filename) {
res.setHeader('Content-Type', mime[path.extname(filename)] || 'application/octet-stream')
res.setHeader('Cache-Control', 'no-store')
+52
View File
@@ -0,0 +1,52 @@
import type { Emitter, Option, OptionInput, SubtitleUpdateEvents } from 'artplayer'
import Artplayer from 'artplayer'
const historical: Option = { container: '#player', url: '' }
const requiredUrl: string = historical.url
const art = new Artplayer(historical)
const instanceUrl: string = art.option.url
const defaultUrl: string = Artplayer.option.url
const input: OptionInput = {
container: '#player',
controls: [{ html: 42, position: 'left' }],
layers: [{ html: 43 }],
contextmenu: [{ html: 44 }],
}
void new Artplayer(input, function (instance) {
const receiverId: number = this.id
const argument: Artplayer = instance
void [receiverId, argument]
})
void new Artplayer({ container: '#player' })
art.controls.update({ name: 'numeric', html: 45, position: 'left' })
art.layers.add(() => ({ html: 46 }))
// @ts-expect-error URL must still be a string when provided.
void new Artplayer({ container: '#player', url: 42 })
// @ts-expect-error Numeric HTML does not relax other component fields.
void new Artplayer({ container: '#player', controls: [{ html: 42, position: 42 }] })
// @ts-expect-error An arbitrary object is not renderable HTML.
void new Artplayer({ container: '#player', layers: [{ html: {} }] })
const unescaped: string = Artplayer.utils.unescape('&amp;')
const error: Error = new Artplayer.utils.ArtPlayerError('message')
const timer: Promise<void> = Artplayer.utils.sleep()
const target = { value: 1 }
const identity: typeof target = Artplayer.utils.def(target, Symbol('key'), { value: 2 })
// Existing string-key return assignments remain valid during reconciliation.
const oldDef: void = Artplayer.utils.def(target, 'key', { value: 2 })
void [requiredUrl, instanceUrl, defaultUrl, unescaped, error, timer, identity, oldDef]
const emitter: Emitter<{ ready: [number] }> = new Artplayer.Emitter<{ ready: [number] }>('historically-ignored')
emitter.on('ready', function (value) {
const id: number = this.id
const payload: number = value
void [id, payload]
}, { id: 1 }).once('ready', () => {}).emit('ready', 1).off('ready')
// @ts-expect-error Typed event maps reject wrong payloads.
emitter.emit('ready', 'bad')
// @ts-expect-error Typed event maps reject unknown names.
emitter.on('missing', () => {})
const open = new Artplayer.Emitter()
open.on(Symbol.for('event'), (...values) => values.length).emit(Symbol.for('event'), 1, 'two')
const before = (cues: SubtitleUpdateEvents['subtitleBeforeUpdate'][0]) => cues.map(cue => cue.text)
art.on('subtitleBeforeUpdate', before).once('subtitleAfterUpdate', before)
art.emit('subtitleBeforeUpdate', []).off('subtitleBeforeUpdate', before)
+20
View File
@@ -0,0 +1,20 @@
import type { Option } from 'artplayer'
import Artplayer from 'artplayer'
// These legal historical declarations expose known runtime mismatches.
// Keep them compiling until a compatible, reviewed resolution exists.
const option: Option = { container: '#player', url: '' }
const requiredUrl: string = option.url
const art = new Artplayer(option)
const registration: Promise<Artplayer['plugins']> = art.plugins.add(() => ({ name: 'legacy' }))
const toggle: void = art.toggle()
const debounced: number = Artplayer.utils.debounce(() => 1, 10, {})()
const throttled: number = Artplayer.utils.throttle(() => 1, 10)()
const descriptor: void = Artplayer.utils.def({}, 'value', { value: 1 })
const updated: Artplayer['setting'] = art.setting.update({ name: 'entry', html: 'Entry' })
const removed: Artplayer['setting'] = art.setting.remove('entry')
art.on('subtitleBeforeUpdate', (cue) => {
const historicalCue: VTTCue = cue
void historicalCue
})
void [requiredUrl, registration, toggle, debounced, throttled, descriptor, updated, removed]
+3 -2
View File
@@ -1,4 +1,4 @@
import type { Events } from 'artplayer'
import type { Events, Emitter as PublicEmitter } from 'artplayer'
import Emitter from '../../packages/artplayer/src/utils/emitter'
const symbol = Symbol('message')
@@ -12,6 +12,7 @@ class TypedEmitter extends Emitter<Messages> {
count = 0
}
const events = new TypedEmitter()
const publicShape: PublicEmitter<Messages> = events
const context = { total: 0 }
const chain: TypedEmitter = events.on('value', function (count, label) {
this.total += count
@@ -39,4 +40,4 @@ events.on('ready', contextListener, { total: 'zero' })
function contextListener(this: { total: number }) {
return this.total
}
void chain
void [chain, publicShape]
+6 -7
View File
@@ -1,4 +1,4 @@
import type { Option, ResolvedOption } from '../../packages/artplayer/src/option/types'
import type { Option, OptionInput, ResolvedOption } from '../../packages/artplayer/src/option/types'
import createDefaults from '../../packages/artplayer/src/option/defaults'
import resolveOption from '../../packages/artplayer/src/option/resolve'
@@ -25,9 +25,8 @@ resolved.subtitle.onVttLoad = () => 42
// @ts-expect-error Application fields retain their own type.
extended.application.token = 'invalid'
// Historical public declaration gaps; CORE-07 must replace these with positive checks.
// @ts-expect-error Runtime accepts an omitted URL, but the current public Option requires it.
const omittedUrl: Option = { container: '#player' }
// @ts-expect-error Runtime accepts numeric control HTML, but the current public type excludes it.
const numericHtml: NonNullable<Option['controls']>[number] = { html: 42, position: 'left' }
void [omittedUrl, numericHtml]
const omittedUrl: OptionInput = { container: '#player' }
const numericHtml: NonNullable<OptionInput['controls']>[number] = { html: 42, position: 'left' }
const expanded = resolveOption({ ...omittedUrl, controls: [numericHtml] }, createDefaults())
const defaultUrl: string = expanded.url
void [omittedUrl, numericHtml, defaultUrl]