diff --git a/docs/assets/ts/artplayer-plugin-jassub.d.ts b/docs/assets/ts/artplayer-plugin-jassub.d.ts index 27e10fe86..71b742ebe 100644 --- a/docs/assets/ts/artplayer-plugin-jassub.d.ts +++ b/docs/assets/ts/artplayer-plugin-jassub.d.ts @@ -1,38 +1,41 @@ -export interface JassubOption { - workerUrl: string - wasmUrl: string - modernWasmUrl: string - subUrl?: string - subContent?: string - timeOffset?: number - debug?: boolean - prescaleFactor?: number - prescaleHeightLimit?: number - maxRenderHeight?: number - fonts?: string[] | Uint8Array[] - availableFonts?: Record - fallbackFont?: string - useLocalFonts?: boolean - libassMemoryLimit?: number - libassGlyphLimit?: number - [key: string]: any +// Generated from the package public declaration by yarn build:ts. Do not edit. +/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */ +declare namespace artplayerPluginJassubDefinitions { + export interface JassubOption { + workerUrl: string + wasmUrl: string + modernWasmUrl: string + subUrl?: string + subContent?: string + timeOffset?: number + debug?: boolean + prescaleFactor?: number + prescaleHeightLimit?: number + maxRenderHeight?: number + fonts?: string[] | Uint8Array[] + availableFonts?: Record + fallbackFont?: string + useLocalFonts?: boolean + libassMemoryLimit?: number + libassGlyphLimit?: number + [key: string]: any + } + export interface JassubInstance { + resize: (force?: boolean, width?: number, height?: number, top?: number, left?: number) => Promise + setVideo: (video: HTMLVideoElement) => Promise + destroy: () => Promise + [key: string]: any + } + export interface Result { + name: 'artplayerPluginJassub' + instance: JassubInstance + } + export const artplayerPluginJassub: (option: JassubOption) => (art: Artplayer) => Result } - -export interface JassubInstance { - resize: (force?: boolean, width?: number, height?: number, top?: number, left?: number) => Promise - setVideo: (video: HTMLVideoElement) => Promise - destroy: () => Promise - [key: string]: any +declare const artplayerPluginJassub: typeof artplayerPluginJassubDefinitions.artplayerPluginJassub +declare namespace artplayerPluginJassub { + export type JassubOption = artplayerPluginJassubDefinitions.JassubOption + export type JassubInstance = artplayerPluginJassubDefinitions.JassubInstance } - -interface Result { - name: 'artplayerPluginJassub' - instance: JassubInstance -} - -declare const artplayerPluginJassub: (option: JassubOption) => (art: Artplayer) => Result - -export default artplayerPluginJassub - export = artplayerPluginJassub export as namespace artplayerPluginJassub; diff --git a/package.json b/package.json index 861603ef5..d74d6774f 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "ci:build": "yarn build:types && yarn build all && yarn build:i18n && yarn build:ts && yarn build:docs && yarn test:imports", "test:imports": "node --test test/esm.test.js test/i18n.test.js test/ssr.test.js test/asr-distribution.test.js", "typecheck": "node scripts/typecheck.mjs", - "test:unit": "node --test test/danmuku-setting.test.js test/danmuku-heatmap.test.js test/danmuku-renderer.test.js test/danmuku-scheduler.test.js test/danmuku-worker-client.test.js test/danmuku-input.test.js test/danmuku-parser.test.js test/danmuku-failures.test.js test/danmuku-mask-failures.test.js test/danmuku-mask-lifecycle.test.js test/asr-encoding.test.js test/asr-lifecycle.test.js test/asr-audio.test.js test/asr.test.js test/jassub.test.js test/jassub-registration.test.js test/multiple-subtitles-merge.test.js test/multiple-subtitles-lifecycle.test.js test/multiple-subtitles-failures.test.js test/multiple-subtitles.test.js test/multiple-subtitles-vendor.test.js test/vtt-thumbnail-parser.test.js test/vtt-thumbnail-lifecycle.test.js test/vtt-thumbnail.test.js test/auto-thumbnail-frames.test.js test/auto-thumbnail-lifecycle.test.js test/auto-thumbnail.test.js test/thumbnail-emitter.test.js test/thumbnail-runtime.test.js test/thumbnail-vendor.test.js test/thumbnail-lifecycle.test.js test/thumbnail-input.test.js test/thumbnail.test.js test/iframe-navigation.test.js test/iframe-boundaries.test.js test/iframe-lifecycle.test.js test/iframe.test.js test/mediabunny.test.js test/mediabunny-shim.test.js test/mediabunny-coordination.test.js test/mediabunny-video.test.js test/mediabunny-audio.test.js test/mediabunny-hls.test.js test/mediabunny-entry.test.js test/mediabunny-capability.test.js test/mediabunny-load.test.js test/mediabunny-input.test.js test/dpip.test.js test/dpip-lifecycle.test.js test/canvas.test.js test/canvas-lifecycle.test.js test/ambilight.test.js test/ambilight-lifecycle.test.js test/ambilight-proxy.test.js test/vast.test.js test/vast-lifecycle.test.js test/ads.test.js test/ads-lifecycle.test.js test/playback.test.js test/dash-control.test.js test/dash-contract.test.js test/dash-lifecycle.test.js test/dash-events.test.js test/hls-control.test.js test/audio-track.test.js test/public-behavior.test.js test/helpers.test.js test/chapter.test.js test/utils.test.js test/resource-scope.test.js test/instance-lifecycle.test.js test/options.test.js test/media-hosts.test.js test/plugins.test.js test/source.test.js test/playback-properties.test.js test/media-events.test.js test/template-resources.test.js test/core-vendor.test.js test/component-resources.test.js test/setting-model.test.js test/setting-layout.test.js test/setting-resources.test.js test/subtitle.test.js test/display-native.test.js test/display-video-fullscreen.test.js test/display-pip.test.js test/display-mini.test.js test/display-sizing.test.js test/display-orientation.test.js test/hotkey.test.js test/listener-registry.test.js test/global-events.test.js test/pointer-events.test.js test/gesture.test.js test/event-scheduling.test.js test/notice.test.js test/fast-forward.test.js test/auto-playback.test.js test/builtin-layers.test.js test/prompt-components.test.js test/screenshot.test.js test/thumbnails.test.js test/progress.test.js test/environment.test.js test/storage.test.js test/facade-properties.test.js test/dom-boundaries.test.js test/initialization.test.js test/entry.test.js test/accessibility-button.test.js test/accessibility-focus.test.js test/accessibility-slider.test.js test/asr-fallback-routing.test.js test/asr-local-example.test.js test/asr-explicit-capture.test.js test/chromecast.test.js test/chromecast-failures.test.js test/chromecast-runtime.test.js", + "test:unit": "node --test test/danmuku-setting.test.js test/danmuku-heatmap.test.js test/danmuku-renderer.test.js test/danmuku-scheduler.test.js test/danmuku-worker-client.test.js test/danmuku-input.test.js test/danmuku-parser.test.js test/danmuku-failures.test.js test/danmuku-mask-failures.test.js test/danmuku-mask-lifecycle.test.js test/asr-encoding.test.js test/asr-lifecycle.test.js test/asr-audio.test.js test/asr.test.js test/jassub.test.js test/jassub-registration.test.js test/jassub-runtime.test.js test/multiple-subtitles-merge.test.js test/multiple-subtitles-lifecycle.test.js test/multiple-subtitles-failures.test.js test/multiple-subtitles.test.js test/multiple-subtitles-vendor.test.js test/vtt-thumbnail-parser.test.js test/vtt-thumbnail-lifecycle.test.js test/vtt-thumbnail.test.js test/auto-thumbnail-frames.test.js test/auto-thumbnail-lifecycle.test.js test/auto-thumbnail.test.js test/thumbnail-emitter.test.js test/thumbnail-runtime.test.js test/thumbnail-vendor.test.js test/thumbnail-lifecycle.test.js test/thumbnail-input.test.js test/thumbnail.test.js test/iframe-navigation.test.js test/iframe-boundaries.test.js test/iframe-lifecycle.test.js test/iframe.test.js test/mediabunny.test.js test/mediabunny-shim.test.js test/mediabunny-coordination.test.js test/mediabunny-video.test.js test/mediabunny-audio.test.js test/mediabunny-hls.test.js test/mediabunny-entry.test.js test/mediabunny-capability.test.js test/mediabunny-load.test.js test/mediabunny-input.test.js test/dpip.test.js test/dpip-lifecycle.test.js test/canvas.test.js test/canvas-lifecycle.test.js test/ambilight.test.js test/ambilight-lifecycle.test.js test/ambilight-proxy.test.js test/vast.test.js test/vast-lifecycle.test.js test/ads.test.js test/ads-lifecycle.test.js test/playback.test.js test/dash-control.test.js test/dash-contract.test.js test/dash-lifecycle.test.js test/dash-events.test.js test/hls-control.test.js test/audio-track.test.js test/public-behavior.test.js test/helpers.test.js test/chapter.test.js test/utils.test.js test/resource-scope.test.js test/instance-lifecycle.test.js test/options.test.js test/media-hosts.test.js test/plugins.test.js test/source.test.js test/playback-properties.test.js test/media-events.test.js test/template-resources.test.js test/core-vendor.test.js test/component-resources.test.js test/setting-model.test.js test/setting-layout.test.js test/setting-resources.test.js test/subtitle.test.js test/display-native.test.js test/display-video-fullscreen.test.js test/display-pip.test.js test/display-mini.test.js test/display-sizing.test.js test/display-orientation.test.js test/hotkey.test.js test/listener-registry.test.js test/global-events.test.js test/pointer-events.test.js test/gesture.test.js test/event-scheduling.test.js test/notice.test.js test/fast-forward.test.js test/auto-playback.test.js test/builtin-layers.test.js test/prompt-components.test.js test/screenshot.test.js test/thumbnails.test.js test/progress.test.js test/environment.test.js test/storage.test.js test/facade-properties.test.js test/dom-boundaries.test.js test/initialization.test.js test/entry.test.js test/accessibility-button.test.js test/accessibility-focus.test.js test/accessibility-slider.test.js test/asr-fallback-routing.test.js test/asr-local-example.test.js test/asr-explicit-capture.test.js test/chromecast.test.js test/chromecast-failures.test.js test/chromecast-runtime.test.js", "test:coverage": "node --test test/coverage.test.js && node scripts/coverage.mjs", "test": "yarn test:node && yarn test:baseline", "test:browser": "playwright test", @@ -90,7 +90,9 @@ "test:vtt-thumbnail-types-package": "node refactor/scripts/vtt-thumbnail-package-types.mjs", "test:multiple-subtitles": "node --test test/multiple-subtitles-merge.test.js test/multiple-subtitles-lifecycle.test.js test/multiple-subtitles-failures.test.js test/multiple-subtitles.test.js test/multiple-subtitles-vendor.test.js refactor/scripts/multiple-subtitles-contract.test.mjs refactor/scripts/multiple-subtitles-runtime-types.test.mjs refactor/scripts/multiple-subtitles-types.test.mjs", "test:multiple-subtitles-types-package": "node refactor/scripts/multiple-subtitles-package-types.mjs", - "test:jassub": "node --test test/jassub.test.js test/jassub-registration.test.js refactor/scripts/jassub-contract.test.mjs refactor/scripts/jassub-provenance.test.mjs refactor/scripts/jassub-failures.test.mjs", + "test:jassub": "node --test test/jassub.test.js test/jassub-registration.test.js test/jassub-runtime.test.js refactor/scripts/jassub-contract.test.mjs refactor/scripts/jassub-provenance.test.mjs refactor/scripts/jassub-failures.test.mjs refactor/scripts/jassub-types.test.mjs", + "test:jassub-types": "node --test refactor/scripts/jassub-types.test.mjs", + "test:jassub-types-package": "node refactor/scripts/jassub-package-types.mjs", "check:ci": "node refactor/scripts/ci-workflow.mjs", "test:ci": "node --test test/ci-summary.test.js refactor/scripts/ci-workflow.test.mjs refactor/scripts/impact.test.mjs test/package-runtime.test.js", "test:package:runtime": "node scripts/package-runtime.mjs --canonical", diff --git a/packages/artplayer-plugin-jassub/.npmignore b/packages/artplayer-plugin-jassub/.npmignore index 4439c6874..2b272d565 100644 --- a/packages/artplayer-plugin-jassub/.npmignore +++ b/packages/artplayer-plugin-jassub/.npmignore @@ -2,4 +2,5 @@ node_modules .DS_Store yarn.lock package-lock.json -src \ No newline at end of file +src +tsconfig.json diff --git a/packages/artplayer-plugin-jassub/ARCHITECTURE.md b/packages/artplayer-plugin-jassub/ARCHITECTURE.md index 5c48d77ce..cb9156934 100644 --- a/packages/artplayer-plugin-jassub/ARCHITECTURE.md +++ b/packages/artplayer-plugin-jassub/ARCHITECTURE.md @@ -1,7 +1,7 @@ # JASSUB maintenance -`src/index.js` preserves the lazy factory and delegates registration to -`src/registration.js`. The registration module constructs the actual vendor object +`src/index.ts` preserves the lazy factory and delegates registration to +`src/registration.ts`. The registration module constructs the actual vendor object with `{ video: art.video, ...option }`, styles only a vendor-created canvas parent, binds host cleanup and synchronously returns `{ name: 'artplayerPluginJassub', instance }`. Options remain live until registration; a supplied video wins. This small split keeps @@ -27,11 +27,27 @@ messages. Keep this third-party file separate from the adapter's TypeScript migr files. The local demo explicitly hosts its resources under `docs/assets/jassub/` and selects fonts in `docs/assets/example/jassub.js`. Do not move or rename those URLs as an internal cleanup. -`types/artplayer-plugin-jassub.d.ts` currently requires three resource URLs and describes -resize/setVideo/destroy as Promise-returning. Actual historical methods are synchronous, and -resize is width/height/top/left/force. Keep the existing declarations until the dedicated public -type compatibility work has assessed extraction, callbacks and replacement consumers. -Both option and instance expose extension indexes; they are existing compatibility boundaries. +`types/artplayer-plugin-jassub.d.ts` preserves the actual npm 1.0.0/1.1.0 declarations, +including three required resource URLs, Promise-returning resize/setVideo/destroy and +the historical force-first resize signature. Both option and instance retain their existing +extension indexes. Do not correct this root file by narrowing fields or adding overloads: +complete factory assignment and Parameters/ReturnType are compatibility boundaries. + +`types/runtime-api.d.ts` separately describes the actual optional options, synchronous +registration and methods, width/height/top/left/force resize, EventTarget events and +Worker query/mutation data. `types/runtime.d.ts`, `.d.cts` and `.d.mts` expose it through +the optional `/runtime` entry; it resolves to the same main/ESM JavaScript as the root. +There is no second implementation and no new factory.default property. Root/legacy +types remain unchanged; exact typesVersions mappings support old Node module resolution. +See [type migration notes](types/README.md) before changing either surface. + +`src/jassub.es.d.ts` is a private bridge for the frozen vendor JS, not a public export. +It adds only the adapter's `_destroyed` read and `_canvasParent.style.zIndex` write to the +accurate instance. The minimal style contract permits the historical numeric 20, which +the native DOM setter converts to a string. The owned TS modules depend on RuntimeOption +and RuntimeResult, while JassubHost needs only video/on/off. The implementation fixture +checks actual Artplayer assignability. No broad any index, allowJs or ts-nocheck hides +owned code; the isolated third-party JS remains an explicit provenance/07 exception. The wrapper matches upstream jassub 1.8.8 apart from formatting and the ESLint header; worker JS and default font match that archive byte-for-byte. Local WASM instead matches @@ -48,6 +64,10 @@ Use the pinned Node/Yarn toolchain: ```sh yarn test:jassub +yarn test:jassub-types +yarn test:jassub-types-package +yarn typecheck +yarn build:ts artplayer-plugin-jassub node --test test/jassub-registration.test.js node refactor/scripts/jassub-provenance.test.mjs --network yarn build artplayer-plugin-jassub diff --git a/packages/artplayer-plugin-jassub/README.md b/packages/artplayer-plugin-jassub/README.md index 8b8ba825f..663e589fd 100644 --- a/packages/artplayer-plugin-jassub/README.md +++ b/packages/artplayer-plugin-jassub/README.md @@ -11,6 +11,10 @@ jassub plugin for ArtPlayer See [maintenance notes](ARCHITECTURE.md) for adapter/vendor boundaries, resource paths, historical declaration differences and the current validation scope. +Existing imports keep their historical types. The optional +[`artplayer-plugin-jassub/runtime` entry](types/README.md) provides accurate options, +synchronous instance methods and subtitle query types using the same implementation. + ## License MIT © Harvey Zhao diff --git a/packages/artplayer-plugin-jassub/package.json b/packages/artplayer-plugin-jassub/package.json index 7032f2783..13706a762 100644 --- a/packages/artplayer-plugin-jassub/package.json +++ b/packages/artplayer-plugin-jassub/package.json @@ -27,11 +27,31 @@ "types": "./types/artplayer-plugin-jassub.d.ts", "import": "./dist/artplayer-plugin-jassub.legacy.js", "require": "./dist/artplayer-plugin-jassub.legacy.js" + }, + "./runtime": { + "import": { + "types": "./types/runtime.d.mts", + "default": "./dist/artplayer-plugin-jassub.mjs" + }, + "require": { + "types": "./types/runtime.d.cts", + "default": "./dist/artplayer-plugin-jassub.js" + } } }, "main": "dist/artplayer-plugin-jassub.js", "module": "./dist/artplayer-plugin-jassub.mjs", "types": "types/artplayer-plugin-jassub.d.ts", "legacy": "dist/artplayer-plugin-jassub.legacy.js", - "browserslist": "last 1 Chrome version" + "browserslist": "last 1 Chrome version", + "typesVersions": { + "*": { + "legacy": [ + "types/artplayer-plugin-jassub.d.ts" + ], + "runtime": [ + "types/runtime.d.ts" + ] + } + } } diff --git a/packages/artplayer-plugin-jassub/src/index.js b/packages/artplayer-plugin-jassub/src/index.js deleted file mode 100644 index 9c93ae78a..000000000 --- a/packages/artplayer-plugin-jassub/src/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import { registerJassub } from './registration.js' - -export default function artplayerPluginJassub(option) { - return art => registerJassub(art, option) -} diff --git a/packages/artplayer-plugin-jassub/src/index.ts b/packages/artplayer-plugin-jassub/src/index.ts new file mode 100644 index 000000000..de250f32b --- /dev/null +++ b/packages/artplayer-plugin-jassub/src/index.ts @@ -0,0 +1,7 @@ +import type { RuntimeOption } from '../types/runtime-api.js' +import type { JassubHost } from './registration.js' +import { registerJassub } from './registration.js' + +export default function artplayerPluginJassub(option?: RuntimeOption) { + return (art: JassubHost) => registerJassub(art, option) +} diff --git a/packages/artplayer-plugin-jassub/src/jassub.es.d.ts b/packages/artplayer-plugin-jassub/src/jassub.es.d.ts new file mode 100644 index 000000000..66604dfbd --- /dev/null +++ b/packages/artplayer-plugin-jassub/src/jassub.es.d.ts @@ -0,0 +1,12 @@ +import type { RuntimeInstance, RuntimeOption } from '../types/runtime-api.js' + +interface VendorInstance extends RuntimeInstance { + _destroyed?: boolean + // Minimal write contract: the DOM setter coerces the historical numeric 20. + _canvasParent?: { style: { zIndex: string | number } } +} + +declare const JASSUB: { + new (option: RuntimeOption): VendorInstance +} +export default JASSUB diff --git a/packages/artplayer-plugin-jassub/src/registration.js b/packages/artplayer-plugin-jassub/src/registration.ts similarity index 70% rename from packages/artplayer-plugin-jassub/src/registration.js rename to packages/artplayer-plugin-jassub/src/registration.ts index 0308f4293..0b248f804 100644 --- a/packages/artplayer-plugin-jassub/src/registration.js +++ b/packages/artplayer-plugin-jassub/src/registration.ts @@ -1,6 +1,13 @@ +import type { RuntimeOption, RuntimeResult } from '../types/runtime-api.js' import JASSUB from './jassub.es.js' -export function registerJassub(art, option) { +export interface JassubHost { + video: HTMLVideoElement + on: (name: 'destroy', callback: () => void) => unknown + off: (name: 'destroy', callback: () => void) => unknown +} + +export function registerJassub(art: JassubHost, option?: RuntimeOption): RuntimeResult { const instance = new JASSUB({ video: art.video, ...option }) let disposed = false const dispose = () => { diff --git a/packages/artplayer-plugin-jassub/tsconfig.json b/packages/artplayer-plugin-jassub/tsconfig.json new file mode 100644 index 000000000..0795b52fb --- /dev/null +++ b/packages/artplayer-plugin-jassub/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { "allowJs": false }, + "include": ["src/**/*.ts", "../../refactor/fixtures/implementation/jassub.ts"] +} diff --git a/packages/artplayer-plugin-jassub/types/README.md b/packages/artplayer-plugin-jassub/types/README.md new file mode 100644 index 000000000..ec9892ad9 --- /dev/null +++ b/packages/artplayer-plugin-jassub/types/README.md @@ -0,0 +1,67 @@ +# JASSUB type compatibility + +The root and `/legacy` declarations retain the complete npm 1.0.0 and 1.1.0 type +shape, including known mistakes. Existing TypeScript consumers do not need to +change imports as part of this migration. Both releases used the same declarations. +The generated online-editor global also preserves this historical surface. + +For accurate types, explicitly opt into the additive entry: + +```ts +import jassub from 'artplayer-plugin-jassub/runtime' + +const register = jassub({ + workerUrl: '/assets/jassub-worker.js', + wasmUrl: '/assets/jassub-worker.wasm', + modernWasmUrl: '/assets/jassub-worker-modern.wasm', + subUrl: '/subtitles.ass', +}) +// Add register to the existing Artplayer plugins option. +// When called with an Artplayer, it synchronously returns { name, instance }. +``` + +`/runtime` uses the same JavaScript file as the root entry. It does not change +defaults, wrap instances, download resources differently or introduce a second +implementation. URLs are optional because the vendor has defaults; this does not +mean its default relative URLs will exist on your site. Continue hosting compatible +worker, WASM and font files and supplying the paths your deployment needs. + +| Area | Historical root types | Accurate `/runtime` types and existing JavaScript | +| --- | --- | --- | +| Factory options | Required, with three required URLs | Optional options; optional resource URLs | +| Instance resize | force, width, height, top, left | width, height, top, left, force | +| resize/setVideo/destroy | Promise | Synchronous; no-argument calls return void | +| sendMessage | Unchecked extension | Promise, resolves after posting, not after Worker completion | +| Events/styles | Unchecked extension | Typed callbacks and partial mutation objects | +| ASS event Style | Unchecked extension | Numeric libass style index | +| ASS Start/Duration | Unchecked extension | Milliseconds; setCurrentTime uses seconds | +| Unknown fields/methods | Existing any indexes | Named supported fields; unknown members rejected | + +Switching to `/runtime` intentionally changes type inference. For example, +`instance.resize(640, 360, 0, 0, true)` describes the actual call order. +`await instance.destroy()` remains legal JavaScript, but `.then()` on that result +never worked at runtime. Resource teardown completion is not represented by a Promise. +The callback error channel is `Error | ErrorEvent | null`; an error may omit the data. +The currently frozen vendor has a request timeout/error bug that throws before user +callbacks run. PKG-JASSUB-07 tracks the fix; typing that channel does not fix or guarantee +callback delivery. Query outputs do not contain the upstream npm declaration's `_index`. + +The accurate instance extends EventTarget and preserves its normal listener APIs. +`destroy(error)` returns the original Error, or converts a nonempty string to Error; +an empty string is returned unchanged. Repeated direct destruction and construction/ +video clock failures remain separate vendor lifecycle work, documented in ARCHITECTURE.md. + +NodeNext ESM retains the root declaration's historical CommonJS namespace behavior. +If existing code uses the root namespace's `.default` to satisfy that declaration, +keep that form or opt into `/runtime`, whose conditional `.d.mts` is directly callable. +CommonJS accurate types use `import jassub = require('artplayer-plugin-jassub/runtime')`. +Do not invent `jassub.default`: the current JavaScript factory has no self alias. +Older TypeScript resolves `/legacy` and `/runtime` through exact typesVersions mappings. +Existing direct declaration paths are retained; no wildcard remaps unrelated paths. + +Maintain `runtime-api.d.ts` against the frozen wrapper and worker behavior, not a new +upstream version. Keep CJS/ESM entry aliases synchronized. Run `yarn test:jassub-types`, +`yarn test:jassub-types-package`, `yarn test:jassub`, and `yarn typecheck` after changes. +The package runner installs actual historical archives and the candidate outside the +workspace, checks strict positive/negative consumers, and verifies artifact identity. +This is type/distribution evidence, not browser playback or final release acceptance. diff --git a/packages/artplayer-plugin-jassub/types/runtime-api.d.ts b/packages/artplayer-plugin-jassub/types/runtime-api.d.ts new file mode 100644 index 000000000..1d220fd4d --- /dev/null +++ b/packages/artplayer-plugin-jassub/types/runtime-api.d.ts @@ -0,0 +1,155 @@ +// Core exposes a default constructor in Node10/ESM and export= in NodeNext CJS. +// Extract the same instance without requiring esModuleInterop in consumers. +type CoreModule = typeof import('artplayer') +type Artplayer = CoreModule extends { default: { prototype: infer Instance } } + ? Instance + : CoreModule extends { prototype: infer Instance } ? Instance : never + +export type FontSource = string | Uint8Array + +/** Options are read when the registrar runs; the host supplies video by default. */ +export interface RuntimeOption { + video?: HTMLVideoElement | null + canvas?: HTMLCanvasElement + blendMode?: 'js' | 'wasm' + asyncRender?: boolean + offscreenRender?: boolean + onDemandRender?: boolean + targetFps?: number + timeOffset?: number + debug?: boolean + prescaleFactor?: number + prescaleHeightLimit?: number + maxRenderHeight?: number + dropAllAnimations?: boolean + dropAllBlur?: boolean + workerUrl?: string + wasmUrl?: string + legacyWasmUrl?: string + modernWasmUrl?: string + subUrl?: string + subContent?: string + fonts?: FontSource[] + availableFonts?: Record + fallbackFont?: string + useLocalFonts?: boolean + libassMemoryLimit?: number + libassGlyphLimit?: number +} + +/** Fields actually serialized by the frozen worker's getEvents response. */ +export interface AssEvent { + /** Milliseconds; distinct from setCurrentTime's seconds. */ + Start: number + Duration: number + /** Numeric libass style index, not the ASS text format's style name. */ + Style: number + Name: string + MarginL: number + MarginR: number + MarginV: number + Effect: string + Text: string + ReadOrder: number + Layer: number +} + +/** Fields actually serialized by the frozen worker's getStyles response. */ +export interface AssStyle { + Name: string + FontName: string + FontSize: number + PrimaryColour: number + SecondaryColour: number + OutlineColour: number + BackColour: number + Bold: number + Italic: number + Underline: number + StrikeOut: number + ScaleX: number + ScaleY: number + Spacing: number + Angle: number + BorderStyle: number + Outline: number + Shadow: number + Alignment: number + MarginL: number + MarginR: number + MarginV: number + Encoding: number + treat_fontname_as_pattern: number + Blur: number + Justify: number +} + +/** Worker mutation handlers assign supplied keys; unspecified fields are not sent. */ +export type AssEventInput = Partial +export type AssStyleInput = Partial + +/** Timeout errors and native Worker error events are separate channels. */ +export type WorkerRequestError = Error | ErrorEvent +/** + * Success supplies null plus an array. Error payloads are absent. + * The frozen vendor currently throws before notifying this callback on request + * errors/timeouts; PKG-JASSUB-07 owns that defect. These types do not guarantee + * callback delivery or claim that the error path has been repaired. + */ +export type EventsCallback = (error: WorkerRequestError | null, events?: AssEvent[]) => void +export type StylesCallback = (error: WorkerRequestError | null, styles?: AssStyle[]) => void + +export interface RuntimeEventMap { + ready: CustomEvent + error: ErrorEvent +} + +/** The actual vendor EventTarget instance, rather than an adapter copy. */ +export interface RuntimeInstance extends EventTarget { + timeOffset: number + debug: boolean + prescaleFactor: number + prescaleHeightLimit: number + maxRenderHeight: number + /** Present when the selected rendering path uses demand/busy state. */ + busy?: boolean + /** These two fields were explicitly exposed by npm jassub 1.8.8. */ + _canvas: HTMLCanvasElement + _ctx: CanvasRenderingContext2D | false | null + + resize: (width?: number, height?: number, top?: number, left?: number, force?: boolean) => void + setVideo: (video: HTMLVideoElement) => void + runBenchmark: () => void + setTrackByUrl: (url: string) => void + setTrack: (content: string) => void + freeTrack: () => void + setIsPaused: (isPaused: boolean) => void + setRate: (rate: number) => void + /** Current time is measured in seconds. */ + setCurrentTime: (isPaused?: boolean, currentTime?: number, rate?: number) => void + createEvent: (event: AssEventInput) => void + setEvent: (event: AssEventInput, index: number) => void + removeEvent: (index: number) => void + getEvents: (callback: EventsCallback) => void + createStyle: (style: AssStyleInput) => void + setStyle: (style: AssStyleInput, index: number) => void + removeStyle: (index: number) => void + getStyles: (callback: StylesCallback) => void + styleOverride: (style: AssStyleInput) => void + disableStyleOverride: () => void + setDefaultFont: (font: string) => void + addFont: (font: FontSource) => void + /** Resolves after posting the message; it is not a Worker-operation acknowledgement. */ + sendMessage: (target: string, data?: Record | null, transferable?: Transferable[]) => Promise + destroy: (() => void) & ((error: Error) => Error) & ((error: string) => Error | '') & ((error: Error | string | undefined) => Error | '' | undefined) + + addEventListener: ((type: Name, listener: (this: RuntimeInstance, event: RuntimeEventMap[Name]) => void, options?: boolean | AddEventListenerOptions) => void) & ((type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions) => void) + removeEventListener: ((type: Name, listener: (this: RuntimeInstance, event: RuntimeEventMap[Name]) => void, options?: boolean | EventListenerOptions) => void) & ((type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | EventListenerOptions) => void) +} + +export interface RuntimeResult { + name: 'artplayerPluginJassub' + instance: RuntimeInstance +} + +export type RuntimeFactory = (option?: RuntimeOption) => (art: Artplayer) => RuntimeResult diff --git a/packages/artplayer-plugin-jassub/types/runtime.d.cts b/packages/artplayer-plugin-jassub/types/runtime.d.cts new file mode 100644 index 000000000..08ddd7d4f --- /dev/null +++ b/packages/artplayer-plugin-jassub/types/runtime.d.cts @@ -0,0 +1,20 @@ +import type { RuntimeFactory } from './runtime-api.js' + +declare const artplayerPluginJassub: RuntimeFactory +// eslint-disable-next-line ts/no-redeclare -- Ambient merge exposes types on the CommonJS factory. +declare namespace artplayerPluginJassub { + type FontSource = import('./runtime-api.js').FontSource + type RuntimeOption = import('./runtime-api.js').RuntimeOption + type AssEvent = import('./runtime-api.js').AssEvent + type AssStyle = import('./runtime-api.js').AssStyle + type AssEventInput = import('./runtime-api.js').AssEventInput + type AssStyleInput = import('./runtime-api.js').AssStyleInput + type WorkerRequestError = import('./runtime-api.js').WorkerRequestError + type EventsCallback = import('./runtime-api.js').EventsCallback + type StylesCallback = import('./runtime-api.js').StylesCallback + type RuntimeEventMap = import('./runtime-api.js').RuntimeEventMap + type RuntimeInstance = import('./runtime-api.js').RuntimeInstance + type RuntimeResult = import('./runtime-api.js').RuntimeResult + type RuntimeFactory = import('./runtime-api.js').RuntimeFactory +} +export = artplayerPluginJassub diff --git a/packages/artplayer-plugin-jassub/types/runtime.d.mts b/packages/artplayer-plugin-jassub/types/runtime.d.mts new file mode 100644 index 000000000..01167b219 --- /dev/null +++ b/packages/artplayer-plugin-jassub/types/runtime.d.mts @@ -0,0 +1,5 @@ +import type { RuntimeFactory } from './runtime-api.js' + +declare const artplayerPluginJassub: RuntimeFactory +export default artplayerPluginJassub +export type { AssEvent, AssEventInput, AssStyle, AssStyleInput, EventsCallback, FontSource, RuntimeEventMap, RuntimeFactory, RuntimeInstance, RuntimeOption, RuntimeResult, StylesCallback, WorkerRequestError } from './runtime-api.js' diff --git a/packages/artplayer-plugin-jassub/types/runtime.d.ts b/packages/artplayer-plugin-jassub/types/runtime.d.ts new file mode 100644 index 000000000..08ddd7d4f --- /dev/null +++ b/packages/artplayer-plugin-jassub/types/runtime.d.ts @@ -0,0 +1,20 @@ +import type { RuntimeFactory } from './runtime-api.js' + +declare const artplayerPluginJassub: RuntimeFactory +// eslint-disable-next-line ts/no-redeclare -- Ambient merge exposes types on the CommonJS factory. +declare namespace artplayerPluginJassub { + type FontSource = import('./runtime-api.js').FontSource + type RuntimeOption = import('./runtime-api.js').RuntimeOption + type AssEvent = import('./runtime-api.js').AssEvent + type AssStyle = import('./runtime-api.js').AssStyle + type AssEventInput = import('./runtime-api.js').AssEventInput + type AssStyleInput = import('./runtime-api.js').AssStyleInput + type WorkerRequestError = import('./runtime-api.js').WorkerRequestError + type EventsCallback = import('./runtime-api.js').EventsCallback + type StylesCallback = import('./runtime-api.js').StylesCallback + type RuntimeEventMap = import('./runtime-api.js').RuntimeEventMap + type RuntimeInstance = import('./runtime-api.js').RuntimeInstance + type RuntimeResult = import('./runtime-api.js').RuntimeResult + type RuntimeFactory = import('./runtime-api.js').RuntimeFactory +} +export = artplayerPluginJassub diff --git a/refactor/baselines/jassub-types-validation.json b/refactor/baselines/jassub-types-validation.json new file mode 100644 index 000000000..9a272c59e --- /dev/null +++ b/refactor/baselines/jassub-types-validation.json @@ -0,0 +1,2445 @@ +{ + "task": "PKG-JASSUB-04", + "node": "v24.21.0", + "platform": "win32", + "recordedAt": "2026-09-13T17:40:16.016Z", + "compatibility": "Actual npm 1.0.0/1.1.0 root declaration bytes preserved after LF normalization; optional runtime alias points to the same JS and exposes no invented default self alias.", + "files": { + "packages/artplayer-plugin-jassub/src/index.ts": "3e210671548168ee919812091186edb43c9ae0f8f5ddb9b610379080d7c4388f", + "packages/artplayer-plugin-jassub/src/registration.ts": "cc45b907d9e2a84e68246ccdf8a11ef03d3ca69bf5f8a3182efddcd766283f72", + "packages/artplayer-plugin-jassub/src/jassub.es.d.ts": "6f5ac9310757525d81da2b2c3c9b8f1f397eb5e42d22f925cbf514df0af99d58", + "packages/artplayer-plugin-jassub/types/runtime-api.d.ts": "702a783fbc96b7b5c47a905d886c444c5ed45d7ffb5651a07891b01aee06c0a3", + "test/types/jassub-public.ts": "2ade876801a478121c4e726fc79efa268758d51e807f1b93122bf9d96fe8b02f", + "test/types/jassub-runtime.ts": "e215591ae1c164b9bf05ea1228341d2770203149ea6931c86f47f203c13c4779", + "test/jassub-runtime.test.js": "c29d46e651248c4dfd8231fe8d2b6d2baeb86be9aaf162aac91c3e35904ecc4c", + "refactor/scripts/jassub-types.test.mjs": "3c6c6a878d7a1d997b1f59a3156448debe6453e16b9da8118556b05c48aa2239", + "refactor/scripts/jassub-package-types.mjs": "58c7520cf7e05d26d6eabb5354fd3e103588b4e213e50c6405ff2e8b2d1446cd" + }, + "runtimeEquivalence": { + "baselineCommit": "38e7b37878b6630f75de38ee7b353f44abb029c9", + "files": [ + { + "file": "packages/artplayer-plugin-jassub/src/index.ts", + "baselineFile": "packages/artplayer-plugin-jassub/src/index.js", + "normalizedJavaScriptSha256": "66d85554363cc163fb116dfb0942f1a9bf88f774f77d753e3473e0098d312835" + }, + { + "file": "packages/artplayer-plugin-jassub/src/registration.ts", + "baselineFile": "packages/artplayer-plugin-jassub/src/registration.js", + "normalizedJavaScriptSha256": "e62ce28ea7fa3ae56d9a46cfa048658feaccf10198ebbb79342a5cf6c135ae56" + }, + { + "file": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js", + "sha256": "1d2fb75dec766c30edb724b5faceae07369a90560aeea07490373193f4a2a4ba", + "sha256LF": "1d2fb75dec766c30edb724b5faceae07369a90560aeea07490373193f4a2a4ba", + "docs": "docs/compiled/artplayer-plugin-jassub.js" + }, + { + "file": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js", + "sha256": "e186265ddbb7db1de3c8def9bbd9769c9a33f6d69c296aef9a3e252ca6e0e734", + "sha256LF": "e186265ddbb7db1de3c8def9bbd9769c9a33f6d69c296aef9a3e252ca6e0e734", + "docs": "docs/compiled/artplayer-plugin-jassub.legacy.js" + }, + { + "file": "packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.mjs", + "sha256": "5d05fab072b8a1f4a4dcf39c9607f3f3200b51aa1afba9c83a8bf372c6a762b4", + "sha256LF": "5d05fab072b8a1f4a4dcf39c9607f3f3200b51aa1afba9c83a8bf372c6a762b4", + "docs": "docs/compiled/artplayer-plugin-jassub.mjs" + } + ], + "vendorUnchanged": true, + "scope": "Owned modules emit identical JS; normal three-format builds equal the prior task after LF normalization, and docs copies are byte-identical. This is not new browser playback evidence." + }, + "tests": { + "file": "refactor/.cache/jassub04-all-final.log", + "sha256": "ef26010ebffb30e2f5d63da2099b44056a4f50629f6649385c09b3380d765b11", + "passed": 139, + "failed": 0, + "skipped": 0, + "previousSuite": 128, + "newRuntime": 8, + "newTypeAndEditor": 3 + }, + "controlledCandidate": [ + { + "file": "refactor/.cache/jassub04-source.log", + "sha256": "0cbb035c654a95931d846ad9524be926df9a65eeabd4b2bd4643e49464b05679", + "passed": 15 + }, + { + "file": "refactor/.cache/jassub04-main.log", + "sha256": "8e9af2691a2f726af1f504b71051e1d7f5d9807f9bd7fe84a7de8e51eb4c6459", + "passed": 15 + }, + { + "file": "refactor/.cache/jassub04-legacy.log", + "sha256": "a5fca654287647a5e5db7f71c43d5476da3e12fff005df46832741695dd4f6b6", + "passed": 15 + } + ], + "strict": { + "file": "refactor/.cache/jassub04-strict-final.log", + "sha256": "d581527df7e9435f0112b3147bdf226aa70c19c3fe1e4c333454f5142333e452", + "productionFiles": 406, + "skipLibCheck": false, + "allowJs": false + }, + "lint": { + "file": "refactor/.cache/jassub04-lint-final.log", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "editor": { + "file": "refactor/.cache/jassub04-editor.log", + "sha256": "894c1ed2089a28401c3b4fa82524fdd4d00d556c255866d7f3c9c5613e4f0dad" + }, + "build": { + "file": "refactor/.cache/jassub04-build.log", + "sha256": "3ef995c766b4e764d73d1735e490395ebb9493cc1827bde13dd7dc06ff20b1d9" + }, + "installed": { + "file": "refactor/.cache/jassub-package-types-H53r6m/report.json", + "sha256": "e28891c8b183c37318e677fb839a76909c08c111091d267228e648410efd3985", + "task": "PKG-JASSUB-04", + "node": "v24.21.0", + "fixtures": { + "refactor/scripts/jassub-consumer.mjs": "d155926155a5bbf1ef66d55883b171aed8b448a2fbb80619df60645b17091431", + "test/types/jassub-public.ts": "2ade876801a478121c4e726fc79efa268758d51e807f1b93122bf9d96fe8b02f", + "test/types/jassub-runtime.ts": "e215591ae1c164b9bf05ea1228341d2770203149ea6931c86f47f203c13c4779" + }, + "rootDeclarations": [ + { + "version": "1.0.0", + "candidateSha256": "0c00ce8fd60780c7c01d23534c193cedd32898dc79739e7cf13d8700a6ab7676", + "publishedSha256": "b591ab9895eef714e5bf3db17c805a2c5278c3244f6bbd614c7c02c397a0d450", + "bytesEqual": false, + "normalizedLFSha256": "b591ab9895eef714e5bf3db17c805a2c5278c3244f6bbd614c7c02c397a0d450" + }, + { + "version": "1.1.0", + "candidateSha256": "0c00ce8fd60780c7c01d23534c193cedd32898dc79739e7cf13d8700a6ab7676", + "publishedSha256": "b591ab9895eef714e5bf3db17c805a2c5278c3244f6bbd614c7c02c397a0d450", + "bytesEqual": false, + "normalizedLFSha256": "b591ab9895eef714e5bf3db17c805a2c5278c3244f6bbd614c7c02c397a0d450" + } + ], + "packages": [ + { + "name": "artplayer", + "archive": "D:\\github\\ArtPlayer\\refactor\\.cache\\jassub-package-types-H53r6m\\artplayer.tgz", + "manifest": { + "name": "artplayer", + "version": "5.4.1", + "description": "ArtPlayer.js is a modern and full featured HTML5 video player", + "author": "Harvey Zhao ", + "license": "MIT", + "homepage": "https://artplayer.org", + "repository": { + "type": "git", + "url": "git+https://github.com/zhw2590582/ArtPlayer.git" + }, + "bugs": { + "url": "https://github.com/zhw2590582/ArtPlayer/issues" + }, + "keywords": [ + "html5", + "video", + "player" + ], + "exports": { + ".": { + "import": { + "types": "./types/artplayer.d.mts", + "default": "./dist/artplayer.mjs" + }, + "require": { + "types": "./types/artplayer.d.cts", + "default": "./dist/artplayer.js" + } + }, + "./types": { + "types": "./types/artplayer.d.ts" + }, + "./runtime": { + "import": { + "types": "./types/runtime.d.mts", + "default": "./dist/artplayer.mjs" + }, + "require": { + "types": "./types/runtime.d.cts", + "default": "./dist/artplayer.js" + } + }, + "./runtime/types": { + "types": "./types/runtime.d.ts" + }, + "./runtime/legacy": { + "import": { + "types": "./types/runtime.d.cts", + "default": "./dist/artplayer.legacy.js" + }, + "require": { + "types": "./types/runtime.d.cts", + "default": "./dist/artplayer.legacy.js" + } + }, + "./legacy": { + "import": { + "types": "./types/artplayer.d.cts", + "default": "./dist/artplayer.legacy.js" + }, + "require": { + "types": "./types/artplayer.d.cts", + "default": "./dist/artplayer.legacy.js" + } + }, + "./i18n/*": { + "import": { + "types": "./types/language.d.mts", + "default": "./dist/i18n/*.mjs" + }, + "require": { + "types": "./types/language.d.cts", + "default": "./dist/i18n/*.js" + } + } + }, + "main": "./dist/artplayer.js", + "module": "./dist/artplayer.mjs", + "types": "./types/artplayer.d.ts", + "typesVersions": { + "*": { + "types": [ + "types/artplayer.d.ts" + ], + "runtime": [ + "types/runtime.d.ts" + ], + "runtime/types": [ + "types/runtime.d.ts" + ], + "runtime/legacy": [ + "types/runtime.d.ts" + ], + "i18n/*": [ + "types/legacy/language.d.ts" + ], + "legacy": [ + "types/artplayer.d.ts" + ] + } + }, + "legacy": "./dist/artplayer.legacy.js", + "browserslist": "last 1 Chrome version", + "dependencies": { + "option-validator": "^2.0.6" + } + }, + "sha256": "0c0ea52d41575261b836aefac68280733b119c75834ecad6d4bc78edb073f4c1", + "files": { + "package/ARCHITECTURE.md": "bee98fc9d93a3911d58e98ef15f2dbe07e12f2274c444d989094248a22079e46", + "package/README.md": "1e185e65f67fc2081b4182bbc6c4558ea05b6e3fa3acc5dd0c3ac7df1d542b09", + "package/THIRD_PARTY_NOTICES": "b77b5b46b79fa0cda850b0781f78c3b1112c4ed9672fa291956fe8eff53098e7", + "package/dist/artplayer.js": "6dc8ca6d6eb34aa8a056cbc31328efd634530b3c5c60f0014cb7ce719fabc335", + "package/dist/artplayer.legacy.js": "80f74a8a39df4baf64cc00c65d21cd57c011bfcdead0da38eea077fbc67c5c04", + "package/dist/artplayer.mjs": "432e2b0ad92009a09743e020bf7c928c8b8f18a52496622b16259ec9ab20059f", + "package/dist/i18n/ar.js": "bd0bef65f4f7dc3f8ed562904cc6fa9071ff4537fb64c1e0fc3d554141bcd3cb", + "package/dist/i18n/ar.mjs": "59310b7bbeea83bbb7d73aadc5ca82a6ec269c3530d19aa741c94d5c64fc5da8", + "package/dist/i18n/cs.js": "6e2c93daba24c2e48dfa206bcf4f2f2a8a02713b856e404d2e4e4ecd8309ca2f", + "package/dist/i18n/cs.mjs": "c73fba18797d62d7b2581e67fe7340c35fe84510b2250ff1ecaad253d9cabbac", + "package/dist/i18n/es.js": "f4133ac6ea06b69a474b33c4a1809a4066e2376bb9464a3f3aa8330f01f1944a", + "package/dist/i18n/es.mjs": "1390bca3def2be115e811de337df0a0c3f63998e51359f283023246245c552a7", + "package/dist/i18n/fa.js": "8d3ef2e0f0cc0ea480c2167b6fcb87cdf444e90759c3519e8daa139fec576da4", + "package/dist/i18n/fa.mjs": "ab441e8a2d79043b29ceca87c783bf06874bb9d3a149c1604bc167eb481be2a9", + "package/dist/i18n/fr.js": "89dc4194a6c0a962b9ce756b52c90401c1acf3b159f265f3bc0d7d6d7d987f03", + "package/dist/i18n/fr.mjs": "99491878430fb7b6f2b7bf93da0588a831704b412e01116f23ba1d9d45863816", + "package/dist/i18n/id.js": "4c6dc86db741bcc2857df55a9d037e82e91d375fa6fd22e0562809ff621b92db", + "package/dist/i18n/id.mjs": "383e5803a6b6686c6de4e867770241de75b6f517dcca2bdedc6f2004bf6e1fb3", + "package/dist/i18n/pl.js": "3a38828b1c3d719c0aca9906cf6a46c23555a8411f8d57645f0e0ce8147dc664", + "package/dist/i18n/pl.mjs": "079ed96732979035297af387c64a7b99519b5a43107fb86735a654ea4fe8e9b5", + "package/dist/i18n/ru.js": "62fac9dddb302eb16382e6e9301fc4b2c66f5f69d4a358a26b67026a5fa4e787", + "package/dist/i18n/ru.mjs": "a893aeaee1d79409db72e324fbff200e3864f33ed168f04d91d25f7cf2efa765", + "package/dist/i18n/tr.js": "1492c36b069a7d73db4f3913bd18085faff7afd8b3c158138fe264e31600e38c", + "package/dist/i18n/tr.mjs": "a90478cac078836b76c2a98261907610fee07f3e4b28671b8e7dbf533778f918", + "package/dist/i18n/vi.js": "c7216ef7e608a79b7e2c479a07bf310d4ab79577947ac4a62d676faaced0e9cf", + "package/dist/i18n/vi.mjs": "66270fdfa0b5da396322d1769169b7df37a030ba15ac18eb30bd87b3af8074ec", + "package/dist/i18n/zh-tw.js": "11c49857d6d40a5ffd224ffa59c9026e71621b345f63c5a086326db80a22371a", + "package/dist/i18n/zh-tw.mjs": "a38e630cb96de96c15d824686aec750e25cf6c8ada01285a292442a81566314f", + "package/package.json": "82e92699e7c29847f32ac6767ece0401290e7d7a12854722bdbcfd09b90b7954", + "package/types/COMPATIBILITY.md": "a7da9e102a116104b513df4f7451247b7759bc502d3375f30bd5b14a541826e0", + "package/types/README.md": "1bd9868e773610e6312fd48a1c5aa20772d29df0af40c3db66e75b7ab4a1aee0", + "package/types/artplayer.d.cts": "3685065e4263abcfd9d953176e461d5b3eb990b0363b54689a7f55deba770fef", + "package/types/artplayer.d.mts": "b664fec51ee5c5381f2ceab25d99d52aee56feab04a2ee7b4ea5b2145ea5fa0e", + "package/types/artplayer.d.ts": "5d0162adf7ac6d0f2bb9b5cfe361f28657c4d9c540cadbf36eba3cc954ce50f8", + "package/types/component.d.ts": "ae5bc1ddeaa1ee1ebbc62573e32423993727079205c64751a5a314170e588a32", + "package/types/config.d.ts": "36f9a84cd436f17701a0d11d3417fc1fe0414e0c52c80083b94a85dfc329e37e", + "package/types/cssVar.d.ts": "93217860fff2ebf750f606d95ddd22220a58837119e63bdf2f5f78fd7488458b", + "package/types/emitter.d.ts": "7e1f9a2a8ce65feb95734f1ed52d1334e57aa388bbef2a43d8bc53a9b6f6623c", + "package/types/events.d.ts": "f83624c9268a284477e8bd793fe3562a2363b72f2a44d5c64fe8c6a6cede8830", + "package/types/i18n.d.ts": "f4f2f05bdfda73c74fef34767cb18ee8e11b743120b1c4598e9714d7846018e5", + "package/types/icons.d.ts": "326a67ba7bdcf52862c5b2a269e540140aff98d05c7b96196485a77f84fe5960", + "package/types/language.d.cts": "f7928e108cf7b7814c2d75cb0a525333e95873fca6cd6d89a740450656b9c1cd", + "package/types/language.d.mts": "6619a26d604b7cccbe2f596243d87ae37cfaae33b8b52874ec071d9787446f9e", + "package/types/legacy/language.d.ts": "c7abda4d506fd933c350e9030290bf9e64347a921d683a66115da1995ebe0a81", + "package/types/option.d.ts": "ccf2c8ddc537dc65c9682d39f044726e23bff18f476b622512d7e6a4b949b5f6", + "package/types/playback.d.ts": "58705c273df6e76a77a6575e769a9ec6c013785c25080f2551aa22415788d870", + "package/types/player.d.ts": "92b00211b70ac71336e495899df972a0519dd138111846044fe4e0f967966177", + "package/types/plugin.d.ts": "fc3594a41c51d8248713e33c486fb1f6a518ac5c7ce31be6988a6cd8d052c5f3", + "package/types/quality.d.ts": "1ac1a48b4f74ff9ba1ce60443e1463d50d1c6a2e5d87d63dc7d2a8eb7f4c2c34", + "package/types/runtime.d.cts": "7ee988dfea9a0ac71a34a656f96f7b74e78aa92547cfdfab7ff7e1139a77d4a3", + "package/types/runtime.d.mts": "dcb85f59a8b7714918ced0c1d18c2bb24e8b80b56d8c594e019dcbdb5ad88b08", + "package/types/runtime.d.ts": "9c6ccd39a1be293f17ae46dae8ea077053e12635ee79d73a5e3b3a559230fcff", + "package/types/runtime/component.d.ts": "1b4c0cee44568649e80140fe778febfcae88af0ac85515f1cbeff78ab0c6d14f", + "package/types/runtime/construction.d.ts": "7a87bedf6f7ffff0c46078aa5f1551e0077d35574e286516121f5f935e2d9ce4", + "package/types/runtime/events.d.ts": "a1e2f9d387475453eaf95c2a5ee79e228636c0bb859bda3fcc46da46574a0c31", + "package/types/runtime/media.d.ts": "8fc89401be7fe25542c169d07dd5675f10916ed20be8493e19695966cf3864a8", + "package/types/runtime/option.d.ts": "6e334e1a76fdcc40b4665c02523bd31c3994d96078fadeb40e23422aa54c1a1d", + "package/types/runtime/player.d.ts": "8ac6383502e4872e83659838844856903031a81a0adc8e8535feb78453aa042c", + "package/types/runtime/plugin.d.ts": "8528f2b17843149f42f9cc16d6fd70baa238c9dc2c329b67d2c38096799c69bd", + "package/types/runtime/services.d.ts": "604c9f8e4b6c0da818f96576bf9f4b0e96085a9003927b2f7ba30027b1ba237e", + "package/types/runtime/setting.d.ts": "349c1fcb205ad312916bd3ee55e6bf241ea8a569fb2ab6c80822e69fc518f7d7", + "package/types/runtime/subtitle.d.ts": "269ff84678d327b3a9dc2f5bc6cc0d731d1e081b85422e474621d5d792efb153", + "package/types/runtime/template.d.ts": "7a62f968a38b4bf9109a4439557c02074eb1d62ba1f6e21a8eb194e91f0badfe", + "package/types/runtime/utils.d.ts": "6bf731705d86853e066dbaf3b8d4003b6548423fe615b7412b722bd0d3a6e48b", + "package/types/setting.d.ts": "08305a75dff96f06490430e099338b463df471b550c1d0dac3abc8995b39eb09", + "package/types/subtitle.d.ts": "b18314e2d64efdb6045830b6e12f615ae2ed585416130e562329ad3ea337f6ce", + "package/types/template.d.ts": "4792bc0c2cbcb7966e4375118bd34b326166e0831862e94ace4cf6b1bbe6a8c8", + "package/types/utils.d.ts": "fca0d3d814df94a25f9eb067c86fa0cf272e2791bac793b91229d57680797712" + } + }, + { + "name": "artplayer-plugin-jassub", + "archive": "D:\\github\\ArtPlayer\\refactor\\.cache\\jassub-package-types-H53r6m\\artplayer-plugin-jassub.tgz", + "manifest": { + "name": "artplayer-plugin-jassub", + "version": "1.1.0", + "description": "jassub plugin for ArtPlayer", + "author": "Harvey Zhao ", + "license": "MIT", + "homepage": "https://artplayer.org", + "repository": { + "type": "git", + "url": "git+https://github.com/zhw2590582/ArtPlayer.git" + }, + "bugs": { + "url": "https://github.com/zhw2590582/ArtPlayer/issues" + }, + "keywords": [ + "html5", + "video", + "player" + ], + "exports": { + ".": { + "types": "./types/artplayer-plugin-jassub.d.ts", + "import": "./dist/artplayer-plugin-jassub.mjs", + "require": "./dist/artplayer-plugin-jassub.js" + }, + "./legacy": { + "types": "./types/artplayer-plugin-jassub.d.ts", + "import": "./dist/artplayer-plugin-jassub.legacy.js", + "require": "./dist/artplayer-plugin-jassub.legacy.js" + }, + "./runtime": { + "import": { + "types": "./types/runtime.d.mts", + "default": "./dist/artplayer-plugin-jassub.mjs" + }, + "require": { + "types": "./types/runtime.d.cts", + "default": "./dist/artplayer-plugin-jassub.js" + } + } + }, + "main": "dist/artplayer-plugin-jassub.js", + "module": "./dist/artplayer-plugin-jassub.mjs", + "types": "types/artplayer-plugin-jassub.d.ts", + "legacy": "dist/artplayer-plugin-jassub.legacy.js", + "browserslist": "last 1 Chrome version", + "typesVersions": { + "*": { + "legacy": [ + "types/artplayer-plugin-jassub.d.ts" + ], + "runtime": [ + "types/runtime.d.ts" + ] + } + } + }, + "sha256": "131037887bc9daeb38990106554da12d09e0168c1bc6224a1de01d58e8ebe463", + "files": { + "package/ARCHITECTURE.md": "4adddb2939be3db3428ea31efa675008a4e834f20e02b9a2c9337336396e9c3a", + "package/README.md": "06ec53e11a1aed27c978987a126781874e569e6f211d712ee7021f776d7ea10b", + "package/dist/artplayer-plugin-jassub.js": "1d2fb75dec766c30edb724b5faceae07369a90560aeea07490373193f4a2a4ba", + "package/dist/artplayer-plugin-jassub.legacy.js": "e186265ddbb7db1de3c8def9bbd9769c9a33f6d69c296aef9a3e252ca6e0e734", + "package/dist/artplayer-plugin-jassub.mjs": "5d05fab072b8a1f4a4dcf39c9607f3f3200b51aa1afba9c83a8bf372c6a762b4", + "package/package.json": "e5098c03fb59c920ba28318348ffa5573e162d38293d0ac39c4fd74f9ee70c9b", + "package/types/README.md": "addb15e5ca68a04ea1f4613eb013aeff10834752f7ac1eafec3793efe5b3c942", + "package/types/artplayer-plugin-jassub.d.ts": "0c00ce8fd60780c7c01d23534c193cedd32898dc79739e7cf13d8700a6ab7676", + "package/types/runtime-api.d.ts": "702a783fbc96b7b5c47a905d886c444c5ed45d7ffb5651a07891b01aee06c0a3", + "package/types/runtime.d.cts": "b4557e2016dd21b6ef34206ed3116e8879afe16a59ed85eaf1618846539b24bd", + "package/types/runtime.d.mts": "6ca863aed785caa1f2707ddfc4cb8456bed2465dbb0a2a1bc12e949a2ffccadc", + "package/types/runtime.d.ts": "b4557e2016dd21b6ef34206ed3116e8879afe16a59ed85eaf1618846539b24bd", + "package/worker/jassub-worker-modern.wasm": "8a8b37463713d1f2ddbc1fbb8a35889d9565e5a6670851758b46b2216d8e513c", + "package/worker/jassub-worker.js": "0fb9a83f96fc39426e733a94f3e7fe4e37099324c08328450ba032b653e85707", + "package/worker/jassub-worker.wasm": "73880d99ba9260ac39fc4476491cf254ca784c76f3af2fb03f3f9be8065ad3c0" + } + } + ], + "published": [ + { + "label": "published-1.0.0", + "archive": "D:\\github\\ArtPlayer\\refactor\\.cache\\releases\\artplayer-plugin-jassub-1.0.0.tgz", + "sha256": "3b46d3ea149af65150cdc42f9ca5eee5fef2893a87bb9ee108050e73849811dc" + }, + { + "label": "published-1.1.0", + "archive": "D:\\github\\ArtPlayer\\refactor\\.cache\\releases\\artplayer-plugin-jassub-1.1.0.tgz", + "sha256": "00713b4eee4b90e7dc13d1f2c88bc785f9b62f3903b00be6f7bec738fbb78c57" + } + ], + "matrix": [ + { + "plugin": "published-1.0.0", + "compiler": "5.9.3", + "mode": "node10-commonjs", + "raw": [ + { + "code": 2307, + "file": "consumer.ts", + "line": 4, + "message": "Cannot find module 'artplayer-plugin-jassub/legacy' or its corresponding type declarations.\n There are types at '/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub.d.ts', but this result could not be resolved under your current 'moduleResolution' setting. Consider updating to 'node16', 'nodenext', or 'bundler'." + } + ], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.0.0", + "compiler": "5.9.3", + "mode": "nodenext-cjs", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.cts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.0.0", + "compiler": "5.9.3", + "mode": "nodenext-esm", + "raw": [ + { + "code": 2344, + "file": "consumer.mts", + "line": 10, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 11, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 11, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 12, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 12, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 18, + "message": "Type '(_option: JassubOption) => (_art: Artplayer) => { name: string; instance: JassubInstance; }' is not assignable to type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 19, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' is not assignable to type 'OldFactory'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(option: JassubOption): (art: Artplayer) => OldResult'." + }, + { + "code": 2349, + "file": "consumer.mts", + "line": 21, + "message": "This expression is not callable.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' has no call signatures." + }, + { + "code": 2349, + "file": "consumer.mts", + "line": 22, + "message": "This expression is not callable.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' has no call signatures." + } + ], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.mts", + "line": 32, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 33, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 34, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 35, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 36, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 37, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 38, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.0.0", + "compiler": "5.9.3", + "mode": "bundler-esm", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.0.0", + "compiler": "4.3.5", + "mode": "node10-commonjs", + "raw": [ + { + "code": 2307, + "file": "consumer.ts", + "line": 4, + "message": "Cannot find module 'artplayer-plugin-jassub/legacy' or its corresponding type declarations." + } + ], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.1.0", + "compiler": "5.9.3", + "mode": "node10-commonjs", + "raw": [ + { + "code": 2307, + "file": "consumer.ts", + "line": 4, + "message": "Cannot find module 'artplayer-plugin-jassub/legacy' or its corresponding type declarations.\n There are types at '/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub.d.ts', but this result could not be resolved under your current 'moduleResolution' setting. Consider updating to 'node16', 'nodenext', or 'bundler'." + } + ], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.1.0", + "compiler": "5.9.3", + "mode": "nodenext-cjs", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.cts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.1.0", + "compiler": "5.9.3", + "mode": "nodenext-esm", + "raw": [ + { + "code": 2344, + "file": "consumer.mts", + "line": 10, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 11, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 11, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 12, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 12, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 18, + "message": "Type '(_option: JassubOption) => (_art: Artplayer) => { name: string; instance: JassubInstance; }' is not assignable to type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 19, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' is not assignable to type 'OldFactory'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(option: JassubOption): (art: Artplayer) => OldResult'." + }, + { + "code": 2349, + "file": "consumer.mts", + "line": 21, + "message": "This expression is not callable.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' has no call signatures." + }, + { + "code": 2349, + "file": "consumer.mts", + "line": 22, + "message": "This expression is not callable.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' has no call signatures." + } + ], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.mts", + "line": 32, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 33, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 34, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 35, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 36, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 37, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 38, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.1.0", + "compiler": "5.9.3", + "mode": "bundler-esm", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "published-1.1.0", + "compiler": "4.3.5", + "mode": "node10-commonjs", + "raw": [ + { + "code": 2307, + "file": "consumer.ts", + "line": 4, + "message": "Cannot find module 'artplayer-plugin-jassub/legacy' or its corresponding type declarations." + } + ], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": null + }, + { + "plugin": "candidate", + "compiler": "5.9.3", + "mode": "node10-commonjs", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": { + "diagnostics": [], + "negative": [ + { + "line": 74, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 74, + "message": "Type 'number' is not assignable to type 'string'." + } + ] + }, + { + "line": 76, + "diagnostics": [ + { + "code": 2353, + "file": "consumer.ts", + "line": 76, + "message": "Object literal may only specify known properties, and 'typoOption' does not exist in type 'RuntimeOption'." + } + ] + }, + { + "line": 78, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.ts", + "line": 78, + "message": "Argument of type 'boolean' is not assignable to parameter of type 'number'." + } + ] + }, + { + "line": 80, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 80, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 82, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 82, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 84, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 84, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 86, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 86, + "message": "Property 'then' does not exist on type 'RuntimeResult'." + } + ] + }, + { + "line": 88, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 88, + "message": "Type 'Promise' is not assignable to type 'void'." + } + ] + }, + { + "line": 90, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 90, + "message": "Type 'string' is not assignable to type 'number'." + } + ] + }, + { + "line": 92, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 92, + "message": "Property '_index' does not exist on type 'AssEvent'." + } + ] + }, + { + "line": 94, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 94, + "message": "Type 'AssEvent[] | undefined' is not assignable to type 'AssEvent[]'.\n Type 'undefined' is not assignable to type 'AssEvent[]'." + } + ] + }, + { + "line": 96, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.ts", + "line": 96, + "message": "Argument of type 'number' is not assignable to parameter of type 'FontSource'." + } + ] + }, + { + "line": 98, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 98, + "message": "Property 'nonexistentMethod' does not exist on type 'RuntimeInstance'." + } + ] + }, + { + "line": 100, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 100, + "message": "Type '\"gpu\"' is not assignable to type '\"js\" | \"wasm\" | undefined'." + } + ] + } + ], + "declarations": [ + "consumer.ts", + "node_modules/artplayer-plugin-jassub/types/runtime-api.d.ts", + "node_modules/artplayer-plugin-jassub/types/runtime.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/emitter.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/option.d.ts", + "node_modules/artplayer/types/playback.d.ts", + "node_modules/artplayer/types/player.d.ts", + "node_modules/artplayer/types/plugin.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" + ], + "sourceSha256": "e215591ae1c164b9bf05ea1228341d2770203149ea6931c86f47f203c13c4779" + } + }, + { + "plugin": "candidate", + "compiler": "5.9.3", + "mode": "nodenext-cjs", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.cts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.cts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.cts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": { + "diagnostics": [], + "negative": [ + { + "line": 74, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 74, + "message": "Type 'number' is not assignable to type 'string'." + } + ] + }, + { + "line": 76, + "diagnostics": [ + { + "code": 2353, + "file": "consumer.cts", + "line": 76, + "message": "Object literal may only specify known properties, and 'typoOption' does not exist in type 'RuntimeOption'." + } + ] + }, + { + "line": 78, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.cts", + "line": 78, + "message": "Argument of type 'boolean' is not assignable to parameter of type 'number'." + } + ] + }, + { + "line": 80, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 80, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 82, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 82, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 84, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 84, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 86, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.cts", + "line": 86, + "message": "Property 'then' does not exist on type 'RuntimeResult'." + } + ] + }, + { + "line": 88, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 88, + "message": "Type 'Promise' is not assignable to type 'void'." + } + ] + }, + { + "line": 90, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 90, + "message": "Type 'string' is not assignable to type 'number'." + } + ] + }, + { + "line": 92, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.cts", + "line": 92, + "message": "Property '_index' does not exist on type 'AssEvent'." + } + ] + }, + { + "line": 94, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 94, + "message": "Type 'AssEvent[] | undefined' is not assignable to type 'AssEvent[]'.\n Type 'undefined' is not assignable to type 'AssEvent[]'." + } + ] + }, + { + "line": 96, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.cts", + "line": 96, + "message": "Argument of type 'number' is not assignable to parameter of type 'FontSource'." + } + ] + }, + { + "line": 98, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.cts", + "line": 98, + "message": "Property 'nonexistentMethod' does not exist on type 'RuntimeInstance'." + } + ] + }, + { + "line": 100, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.cts", + "line": 100, + "message": "Type '\"gpu\"' is not assignable to type '\"js\" | \"wasm\" | undefined'." + } + ] + } + ], + "declarations": [ + "consumer.cts", + "node_modules/artplayer-plugin-jassub/types/runtime-api.d.ts", + "node_modules/artplayer-plugin-jassub/types/runtime.d.cts", + "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/emitter.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/option.d.ts", + "node_modules/artplayer/types/playback.d.ts", + "node_modules/artplayer/types/player.d.ts", + "node_modules/artplayer/types/plugin.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" + ], + "sourceSha256": "e215591ae1c164b9bf05ea1228341d2770203149ea6931c86f47f203c13c4779", + "commonjs": { + "esModuleInterop": false, + "diagnostics": [], + "declarations": [ + "consumer.cts", + "node_modules/artplayer-plugin-jassub/types/runtime-api.d.ts", + "node_modules/artplayer-plugin-jassub/types/runtime.d.cts", + "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/emitter.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/option.d.ts", + "node_modules/artplayer/types/playback.d.ts", + "node_modules/artplayer/types/player.d.ts", + "node_modules/artplayer/types/plugin.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" + ], + "sourceSha256": "2c2dcef802ac8479469944812dce1115f98ee422ee4f8e2445c5f0d0a791ff3f" + } + } + }, + { + "plugin": "candidate", + "compiler": "5.9.3", + "mode": "nodenext-esm", + "raw": [ + { + "code": 2344, + "file": "consumer.mts", + "line": 10, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 11, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 11, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 12, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "file": "consumer.mts", + "line": 12, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 18, + "message": "Type '(_option: JassubOption) => (_art: Artplayer) => { name: string; instance: JassubInstance; }' is not assignable to type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 19, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' is not assignable to type 'OldFactory'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' provides no match for the signature '(option: JassubOption): (art: Artplayer) => OldResult'." + }, + { + "code": 2349, + "file": "consumer.mts", + "line": 21, + "message": "This expression is not callable.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' has no call signatures." + }, + { + "code": 2349, + "file": "consumer.mts", + "line": 22, + "message": "This expression is not callable.\n Type 'typeof import(\"/node_modules/artplayer-plugin-jassub/types/artplayer-plugin-jassub\")' has no call signatures." + } + ], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.mts", + "line": 32, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 33, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 34, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 35, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.mts", + "line": 36, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 37, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.mts", + "line": 38, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": { + "diagnostics": [], + "negative": [ + { + "line": 74, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 74, + "message": "Type 'number' is not assignable to type 'string'." + } + ] + }, + { + "line": 76, + "diagnostics": [ + { + "code": 2353, + "file": "consumer.mts", + "line": 76, + "message": "Object literal may only specify known properties, and 'typoOption' does not exist in type 'RuntimeOption'." + } + ] + }, + { + "line": 78, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.mts", + "line": 78, + "message": "Argument of type 'boolean' is not assignable to parameter of type 'number'." + } + ] + }, + { + "line": 80, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 80, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 82, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 82, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 84, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 84, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 86, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.mts", + "line": 86, + "message": "Property 'then' does not exist on type 'RuntimeResult'." + } + ] + }, + { + "line": 88, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 88, + "message": "Type 'Promise' is not assignable to type 'void'." + } + ] + }, + { + "line": 90, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 90, + "message": "Type 'string' is not assignable to type 'number'." + } + ] + }, + { + "line": 92, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.mts", + "line": 92, + "message": "Property '_index' does not exist on type 'AssEvent'." + } + ] + }, + { + "line": 94, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 94, + "message": "Type 'AssEvent[] | undefined' is not assignable to type 'AssEvent[]'.\n Type 'undefined' is not assignable to type 'AssEvent[]'." + } + ] + }, + { + "line": 96, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.mts", + "line": 96, + "message": "Argument of type 'number' is not assignable to parameter of type 'FontSource'." + } + ] + }, + { + "line": 98, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.mts", + "line": 98, + "message": "Property 'nonexistentMethod' does not exist on type 'RuntimeInstance'." + } + ] + }, + { + "line": 100, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.mts", + "line": 100, + "message": "Type '\"gpu\"' is not assignable to type '\"js\" | \"wasm\" | undefined'." + } + ] + } + ], + "declarations": [ + "consumer.mts", + "node_modules/artplayer-plugin-jassub/types/runtime-api.d.ts", + "node_modules/artplayer-plugin-jassub/types/runtime.d.mts", + "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/emitter.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/option.d.ts", + "node_modules/artplayer/types/playback.d.ts", + "node_modules/artplayer/types/player.d.ts", + "node_modules/artplayer/types/plugin.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" + ], + "sourceSha256": "e215591ae1c164b9bf05ea1228341d2770203149ea6931c86f47f203c13c4779" + } + }, + { + "plugin": "candidate", + "compiler": "5.9.3", + "mode": "bundler-esm", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": { + "diagnostics": [], + "negative": [ + { + "line": 74, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 74, + "message": "Type 'number' is not assignable to type 'string'." + } + ] + }, + { + "line": 76, + "diagnostics": [ + { + "code": 2353, + "file": "consumer.ts", + "line": 76, + "message": "Object literal may only specify known properties, and 'typoOption' does not exist in type 'RuntimeOption'." + } + ] + }, + { + "line": 78, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.ts", + "line": 78, + "message": "Argument of type 'boolean' is not assignable to parameter of type 'number'." + } + ] + }, + { + "line": 80, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 80, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 82, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 82, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 84, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 84, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 86, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 86, + "message": "Property 'then' does not exist on type 'RuntimeResult'." + } + ] + }, + { + "line": 88, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 88, + "message": "Type 'Promise' is not assignable to type 'void'." + } + ] + }, + { + "line": 90, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 90, + "message": "Type 'string' is not assignable to type 'number'." + } + ] + }, + { + "line": 92, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 92, + "message": "Property '_index' does not exist on type 'AssEvent'." + } + ] + }, + { + "line": 94, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 94, + "message": "Type 'AssEvent[] | undefined' is not assignable to type 'AssEvent[]'.\n Type 'undefined' is not assignable to type 'AssEvent[]'." + } + ] + }, + { + "line": 96, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.ts", + "line": 96, + "message": "Argument of type 'number' is not assignable to parameter of type 'FontSource'." + } + ] + }, + { + "line": 98, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 98, + "message": "Property 'nonexistentMethod' does not exist on type 'RuntimeInstance'." + } + ] + }, + { + "line": 100, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 100, + "message": "Type '\"gpu\"' is not assignable to type '\"js\" | \"wasm\" | undefined'." + } + ] + } + ], + "declarations": [ + "consumer.ts", + "node_modules/artplayer-plugin-jassub/types/runtime-api.d.ts", + "node_modules/artplayer-plugin-jassub/types/runtime.d.mts", + "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/emitter.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/option.d.ts", + "node_modules/artplayer/types/playback.d.ts", + "node_modules/artplayer/types/player.d.ts", + "node_modules/artplayer/types/plugin.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" + ], + "sourceSha256": "e215591ae1c164b9bf05ea1228341d2770203149ea6931c86f47f203c13c4779" + } + }, + { + "plugin": "candidate", + "compiler": "4.3.5", + "mode": "node10-commonjs", + "raw": [], + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "file": "consumer.ts", + "line": 30, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 31, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'JassubOption'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 32, + "message": "Argument of type '{ workerUrl: string; wasmUrl: string; }' is not assignable to parameter of type 'JassubOption'.\n Property 'modernWasmUrl' is missing in type '{ workerUrl: string; wasmUrl: string; }' but required in type 'JassubOption'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 33, + "message": "Type 'number' is not assignable to type 'string'." + }, + { + "code": 2345, + "file": "consumer.ts", + "line": 34, + "message": "Argument of type '640' is not assignable to parameter of type 'boolean | undefined'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 35, + "message": "Type 'Promise' is not assignable to type 'void'." + }, + { + "code": 2322, + "file": "consumer.ts", + "line": 36, + "message": "Type '\"artplayerPluginJassub\"' is not assignable to type '\"other\"'." + } + ], + "runtime": { + "diagnostics": [], + "negative": [ + { + "line": 74, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 74, + "message": "Type 'number' is not assignable to type 'string | undefined'." + } + ] + }, + { + "line": 76, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.ts", + "line": 76, + "message": "Argument of type '{ typoOption: boolean; }' is not assignable to parameter of type 'RuntimeOption'.\n Object literal may only specify known properties, and 'typoOption' does not exist in type 'RuntimeOption'." + } + ] + }, + { + "line": 78, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.ts", + "line": 78, + "message": "Argument of type 'true' is not assignable to parameter of type 'number | undefined'." + } + ] + }, + { + "line": 80, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 80, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 82, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 82, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 84, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 84, + "message": "Type 'void' is not assignable to type 'Promise'." + } + ] + }, + { + "line": 86, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 86, + "message": "Property 'then' does not exist on type 'RuntimeResult'." + } + ] + }, + { + "line": 88, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 88, + "message": "Type 'Promise' is not assignable to type 'void'." + } + ] + }, + { + "line": 90, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 90, + "message": "Type 'string' is not assignable to type 'number | undefined'." + } + ] + }, + { + "line": 92, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 92, + "message": "Property '_index' does not exist on type 'AssEvent'." + } + ] + }, + { + "line": 94, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 94, + "message": "Type 'AssEvent[] | undefined' is not assignable to type 'AssEvent[]'.\n Type 'undefined' is not assignable to type 'AssEvent[]'." + } + ] + }, + { + "line": 96, + "diagnostics": [ + { + "code": 2345, + "file": "consumer.ts", + "line": 96, + "message": "Argument of type 'number' is not assignable to parameter of type 'FontSource'." + } + ] + }, + { + "line": 98, + "diagnostics": [ + { + "code": 2339, + "file": "consumer.ts", + "line": 98, + "message": "Property 'nonexistentMethod' does not exist on type 'RuntimeInstance'." + } + ] + }, + { + "line": 100, + "diagnostics": [ + { + "code": 2322, + "file": "consumer.ts", + "line": 100, + "message": "Type '\"gpu\"' is not assignable to type '\"js\" | \"wasm\" | undefined'." + } + ] + } + ], + "declarations": [ + "consumer.ts", + "node_modules/artplayer-plugin-jassub/types/runtime-api.d.ts", + "node_modules/artplayer-plugin-jassub/types/runtime.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/emitter.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/option.d.ts", + "node_modules/artplayer/types/playback.d.ts", + "node_modules/artplayer/types/player.d.ts", + "node_modules/artplayer/types/plugin.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" + ], + "sourceSha256": "e215591ae1c164b9bf05ea1228341d2770203149ea6931c86f47f203c13c4779", + "commonjs": { + "esModuleInterop": false, + "diagnostics": [], + "declarations": [ + "consumer.ts", + "node_modules/artplayer-plugin-jassub/types/runtime-api.d.ts", + "node_modules/artplayer-plugin-jassub/types/runtime.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/emitter.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/option.d.ts", + "node_modules/artplayer/types/playback.d.ts", + "node_modules/artplayer/types/player.d.ts", + "node_modules/artplayer/types/plugin.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" + ], + "sourceSha256": "2c2dcef802ac8479469944812dce1115f98ee422ee4f8e2445c5f0d0a791ff3f" + } + } + } + ], + "scope": "Actual npm 1.0.0/1.1.0 and Yarn-packed candidate/core installed outside workspace; offline installation and forced frozen reinstall with unchanged lock, strictly verified installed member hashes and non-link checks; root declaration text unchanged after CRLF normalization with both raw hashes recorded, exact old diagnostics, conditional accurate runtime declarations and Node lazy factory/legacy identity. Registrars are never invoked in Node; this is not browser Worker/WASM/font rendering or publication acceptance." + }, + "runtimeApiAudit": { + "facts": "Actual complete Worker JS and local WASM parsed ASS and queried/updated events/styles through controlled structured-clone transport. Numeric Style, no _index, milliseconds, success null callback, sync resize and Promise sendMessage verified. No browser Worker, native font painting or new playback evidence.", + "sourceEvidence": { + "files": { + "packages/artplayer-plugin-jassub/types/artplayer-plugin-jassub.d.ts": "0c00ce8fd60780c7c01d23534c193cedd32898dc79739e7cf13d8700a6ab7676", + "packages/artplayer-plugin-jassub/src/jassub.es.js": "b973508ade00b5b9cea2f299d49f4943003372729be7350b6938e44fddb32038", + "packages/artplayer-plugin-jassub/worker/jassub-worker.js": "0fb9a83f96fc39426e733a94f3e7fe4e37099324c08328450ba032b653e85707", + "refactor/.cache/jassub04-npm-1.8.8.d.ts": "56802e69e7c689af6f78c1ecd663a64c03d8b28f52995699e4c759a25870b91b", + "refactor/.cache/jassub04-pinned-JASSUB.cpp": "c28d53f5afad2833717889db981b3b1c4c09154e8dc5797f033cac42895ad9dc", + "refactor/.cache/jassub04-pinned-ass_types.h": "b3ac4ad4d655f4d90e5e8d05cc2868ce17e5ff89ef1fe76cabcc8f3093e6134b", + "refactor/.cache/jassub04-runtime/runtime-api.d.ts": "ad4d067edd521fa4064a24b82f9a5f77b1f1df8ff99c7a0b443f77073c135385", + "test/jassub-runtime.test.js": "c29d46e651248c4dfd8231fe8d2b6d2baeb86be9aaf162aac91c3e35904ecc4c" + }, + "runtimeOnly": true, + "rootModified": false, + "callbackFixOwner": "PKG-JASSUB-07", + "packedEntrypointsVerified": false, + "authorizedFormalTest": "test/jassub-runtime.test.js", + "runtimeTests": { + "passed": 8, + "lintPassed": true, + "actualWasmQueries": true, + "nativeBrowserWorker": false + } + }, + "callbackDefects": [ + { + "method": "getEvents", + "mode": "success", + "userCallbacks": 1, + "listenersRetained": 0, + "pendingTimers": 0 + }, + { + "method": "getEvents", + "mode": "timeout", + "userCallbacks": 0, + "thrown": { + "name": "TypeError", + "message": "Cannot destructure property 'events' of 'undefined' as it is undefined." + }, + "listenersRetained": 2, + "pendingTimers": 0 + }, + { + "method": "getEvents", + "mode": "worker-error", + "userCallbacks": 0, + "thrown": { + "name": "TypeError", + "message": "Cannot destructure property 'events' of 'undefined' as it is undefined." + }, + "listenersRetained": 2, + "pendingTimers": 1 + }, + { + "method": "getStyles", + "mode": "success", + "userCallbacks": 1, + "listenersRetained": 0, + "pendingTimers": 0 + }, + { + "method": "getStyles", + "mode": "timeout", + "userCallbacks": 0, + "thrown": { + "name": "TypeError", + "message": "Cannot destructure property 'styles' of 'undefined' as it is undefined." + }, + "listenersRetained": 2, + "pendingTimers": 0 + }, + { + "method": "getStyles", + "mode": "worker-error", + "userCallbacks": 0, + "thrown": { + "name": "TypeError", + "message": "Cannot destructure property 'styles' of 'undefined' as it is undefined." + }, + "listenersRetained": 2, + "pendingTimers": 1 + } + ] + }, + "intermediateFailures": [ + { + "report": "refactor/.cache/jassub-package-types-qvVnvj/failure.json", + "reason": "No-interop consumer exposed TS1259 in default Artplayer type import; fixed only in new runtime API." + }, + { + "report": "refactor/.cache/jassub-package-types-UMAzT7/failure.json", + "reason": "Simple import-type=require alternative failed Node10 TS2709; replaced by conditional constructor prototype type, with exact host equality checked." + } + ], + "remaining": [ + "PKG-JASSUB-07 vendor lifecycle/clock/query error fixes", + "PKG-JASSUB-05 native combinations/default offscreen/WebKit/devices", + "PKG-JASSUB-06 and SITE-01 distribution/notices/font permissions", + "No push, publication or completion of global release reviews" + ] +} diff --git a/refactor/changes/2026-09-14-PKG-JASSUB-04-types.md b/refactor/changes/2026-09-14-PKG-JASSUB-04-types.md new file mode 100644 index 000000000..27d38a581 --- /dev/null +++ b/refactor/changes/2026-09-14-PKG-JASSUB-04-types.md @@ -0,0 +1,67 @@ +# PKG-JASSUB-04 自有 TS 与兼容类型 + +## 结构与运行时边界 + +自有 index/registration 迁为严格 TS,职责延续 03 的工厂与资源注册分离。 +JassubHost 只需要 video/on/off,真实 Artplayer fixture 验证结构兼容;内部返回 +RuntimeResult,不使用已知不准确的旧根声明来约束实现。私有 jassub.es.d.ts +桥接 vendor,只补 adapter 使用的 _destroyed 与最小样式写入契约,保留数值 20 +经 DOM setter 转字符串的历史行为。allowJs=false,不用 any/ts-nocheck 隐藏自有实现。 + +vendor JS 是明确的第三方例外,本次完全不改字节和算法。Worker/WASM/font 来源 +和 07 修复责任继续保留。两个自有模块经 esbuild 去类型后与 38e7b378 的 JS 完全 +相同;正常构建 main/legacy/ESM 与该提交一致(仅归一化 LF),docs 副本逐字节一致。 +因此不以这次类型迁移声称新增浏览器播放验收,03 的原生验证范围和限制仍适用。 + +## API-09/11 兼容策略 + +实际 npm 1.0.0/1.1.0 根声明相同,本次逐字保留(忽略换行):资源 URL 必填、 +force-first resize、三个 Promise 返回值和两个扩展索引都没有收窄。工厂完整 +双向赋值、Parameters/ReturnType 和原有非法调用的错误位置继续验证。 + +新增可选 /runtime 与根入口复用同一 JavaScript,准确声明可选 options、同步 +registration/resize/setVideo/destroy、width/height/top/left/force 顺序,以及 +EventTarget、字幕/样式/字体方法。sendMessage 实际是 Promise,完成仅代表 +发出消息;不声称 Worker 已处理。ASS Style 是 libass 数值索引,Start/Duration +是毫秒,查询结果没有上游 npm 类型误写的 _index。旧入口消费者不需要迁移, +选择准确入口时的推导差异和调用示例写在包内 types/README.md。 + +精确 typesVersions 修复旧 Node10 下 /legacy 找不到声明;实际两旧包保留原 2307 +证据,候选仅允许消除该 import 行的错误。NodeNext ESM 旧根 namespace 行为及 +直接调用失败保持一致;/runtime 使用 conditional .d.mts/.d.cts 与旧编译器 .d.ts。 +不添加不存在的 factory.default。在线编辑器旧生成方式同时包含 default/export= +而报 2309,两个编译器已复现;接入已有语义生成器并验证生成文件及正反例。 + +## 类型审查发现的真实缺陷 + +JASSUB-QUERY-01:getEvents/getStyles 的 timeout 和 Worker-error 路径缺少第二个 +参数,公开 wrapper 先解构 undefined 抛 TypeError,用户回调为零次,两个请求 +监听器保留;Worker-error 路径还保留定时器。冻结实现的四个失败测试保留此行为。 +该问题纳入 PKG-JASSUB-07 的独立 vendor 修复,不在 04 中混改,不标为已修复。 +准确回调类型允许 Error/ErrorEvent 与缺失数组,不能代表错误回调已经可靠送达。 + +## 验证、命令与限制 + +完整证据与最终安装报告摘要见 [类型验证](../baselines/jassub-types-validation.json)。 +验证包括:严格 TS 自有项目及全仓流程,实际旧声明正反例、生成编辑器,源码和 +main/legacy 注册回归,完整 vendor Worker JS/本地 WASM 的字幕查询及部分字段更新。 +WASM 测试控制消息传输与 fetch,不声称浏览器 Worker、绘制或完整字体加载验收。 + +仓库外实际安装两个历史 npm 归档与 Yarn pack 候选,逐文件核对 hash 和非链接, +离线安装后强制 frozen 重装并检查锁文件。TS 5.9.3 Node10/NodeNext CJS/ESM/Bundler +及 TS 4.3.5 Node10 共 15 组;旧入口七项非法调用、准确入口十四项非法调用逐条 +验证。CJS/ESM 根/legacy 工厂和 root/runtime 同一对象从实际安装包执行,不启动 +vendor 或模拟一次浏览器播放。历史 raw 错误与正确 namespace 消费均单独记录。 + +复跑:yarn test:jassub、yarn test:jassub-types、yarn test:jassub-types-package、 +yarn typecheck、yarn build:ts artplayer-plugin-jassub、yarn build artplayer-plugin-jassub。 +新增脚本复用既有依赖,无新增依赖或锁变更;类型测试进入既有 baseline glob, +运行测试进入 test:unit/test:jassub。隔离安装脚本是可复跑的分包验证,尚不声称 +全部生态安装矩阵已经接入远程 CI 或运行通过。 + +## 剩余任务与回退 + +07 继续 vendor 生命周期、时钟和查询错误清理;05 继续新旧核心/浏览器/真实设备 +组合;06 继续完整分发和许可通知,VENDOR-04/05 保留。版本仍由各包独立 major +任务统一落地。本任务没有发布、推送或减少最终三轮复盘要求。 +回退本任务并正常重建即可恢复旧 JS 入口/类型生成选择;03 修复仍是独立提交。 diff --git a/refactor/fixtures/implementation/jassub.ts b/refactor/fixtures/implementation/jassub.ts new file mode 100644 index 000000000..ff8d4f27b --- /dev/null +++ b/refactor/fixtures/implementation/jassub.ts @@ -0,0 +1,8 @@ +import type Artplayer from 'artplayer' +import type { RuntimeFactory, RuntimeResult } from '../../../packages/artplayer-plugin-jassub/types/runtime-api.js' +import factory from '../../../packages/artplayer-plugin-jassub/src' + +declare const art: Artplayer +const registration: RuntimeResult = factory()(art) +const publicFactory: RuntimeFactory = factory +export { publicFactory, registration } diff --git a/refactor/plan.md b/refactor/plan.md index c3d0f665b..5dde78a03 100644 --- a/refactor/plan.md +++ b/refactor/plan.md @@ -4,7 +4,7 @@ 基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 232 项,范围 22 个包及工作区/示例。 -状态:todo 64 / doing 14 / blocked 0 / done 154 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 +状态:todo 63 / doing 14 / blocked 0 / done 155 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。 @@ -232,10 +232,10 @@ | PKG-JASSUB-01 | artplayer-plugin-jassub
核对包契约与历史用法 | BASE-05 | 选项透传、result.instance、vendor 来源、worker/WASM/font 路径 | 源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结;接续 VENDOR-04/05,核对 wrapper/worker/WASM/font 的独立来源与通知,保持资源路径和选项透传 | H | done | | PKG-JASSUB-02 | artplayer-plugin-jassub
建立特有行为与错误测试 | PKG-JASSUB-01, ENG-03, ENG-05 | ASS 字体、时钟/seek/倍率/resize、加载失败和销毁 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | done | | PKG-JASSUB-03 | artplayer-plugin-jassub
整理内部职责与资源 | PKG-JASSUB-02, CORE-15, CORE-16 | 仅整理自有 adapter/销毁;保留第三方文件及来源 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | done | -| PKG-JASSUB-04 | artplayer-plugin-jassub
迁移自有源码和公开类型 | PKG-JASSUB-03, ENG-04, ENG-06, CORE-07 | JASSUB option/instance 的兼容类型包装,vendor JS 例外记录 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | todo | +| PKG-JASSUB-04 | artplayer-plugin-jassub
迁移自有源码和公开类型 | PKG-JASSUB-03, ENG-04, ENG-06, CORE-07 | JASSUB option/instance 的兼容类型包装,vendor JS 例外记录 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | done | | PKG-JASSUB-05 | artplayer-plugin-jassub
验证新旧核心和组合 | PKG-JASSUB-04, CORE-22, PKG-JASSUB-07 | 真实 worker/WASM 字幕渲染与全屏、旧核心测试 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | todo | | PKG-JASSUB-06 | artplayer-plugin-jassub
验证分发并同步文档 | PKG-JASSUB-05, ENG-07 | jassub.js、外部资源路径、许可和离线失败记录;接续 VENDOR-04/05 完整组件/字体通知、LGPL 源码分发核对及六份未明确字体的分发处置 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录;来源身份已由01冻结,完整通知和未明确字体的发布处理必须闭环,不能以来源相同替代许可结论 | H | todo | -| PKG-JASSUB-07 | artplayer-plugin-jassub
修复 vendor 生命周期与字幕时钟 | PKG-JASSUB-03, PKG-JASSUB-02 | 独立记录 vendor 适配差异;幂等销毁、跨容器 setVideo、构造回滚、逐帧归属和倍率/能力边界 | 保持公开真实 instance、同步方法与资源路径;保留原 vendor 来源指纹并记录每项实际补丁;候选修复正例和真实字幕/失败/时钟验证通过,未证实设备不得冒充通过 | H | todo | +| PKG-JASSUB-07 | artplayer-plugin-jassub
修复 vendor 生命周期与字幕时钟 | PKG-JASSUB-03, PKG-JASSUB-02 | 独立记录 vendor 适配差异;幂等销毁、跨容器 setVideo、构造回滚、逐帧归属和倍率/能力边界;查询 timeout/Worker error 的缺失数据回调及每请求监听器/定时器清理(JASSUB-QUERY-01) | 保持公开真实 instance、同步方法与资源路径;保留原 vendor 来源指纹并记录每项实际补丁;候选修复正例和真实字幕/失败/时钟验证通过,未证实设备不得冒充通过 | H | todo | ## 5 包迁移:artplayer-plugin-danmuku-mask @@ -535,6 +535,7 @@ - PKG-JASSUB-01: [记录](baselines/jassub-release.json) [记录](baselines/jassub-vendor.json) [记录](baselines/jassub-font-metadata.json) [记录](baselines/jassub-contract.md) [记录](baselines/jassub-contract-validation.json) [记录](changes/2026-09-13-PKG-JASSUB-01-baseline.md) [记录](baselines/jassub-provenance.json) [记录](baselines/jassub-provenance-validation.json) [记录](changes/2026-09-14-PKG-JASSUB-01-provenance.md) - PKG-JASSUB-02: [记录](changes/2026-09-14-PKG-JASSUB-02-failure-baseline.md) [记录](baselines/jassub-failures-validation.json) - PKG-JASSUB-03: [记录](changes/2026-09-14-PKG-JASSUB-03-registration.md) [记录](baselines/jassub-registration-validation.json) +- PKG-JASSUB-04: [记录](changes/2026-09-14-PKG-JASSUB-04-types.md) [记录](baselines/jassub-types-validation.json) - PKG-MASK-01: [记录](baselines/danmuku-mask-release.json) [记录](baselines/danmuku-mask-registry.json) [记录](baselines/danmuku-mask-contract.md) [记录](baselines/danmuku-mask-contract-validation.json) [记录](changes/2026-09-13-PKG-MASK-01-contract.md) - PKG-MASK-02: [记录](changes/2026-09-13-PKG-MASK-02-failures.md) [记录](baselines/danmuku-mask-failures-validation.json) - PKG-MASK-03: [记录](changes/2026-09-13-PKG-MASK-03-lifecycle.md) [记录](baselines/danmuku-mask-lifecycle-validation.json) diff --git a/refactor/progress.md b/refactor/progress.md index b726d6630..a5d2befaa 100644 --- a/refactor/progress.md +++ b/refactor/progress.md @@ -1,5 +1,18 @@ # 进度与证据 +## PKG-JASSUB-04 自有 TS 与准确类型入口完成 + +两个自有模块已迁为严格 TS,编译后的 JS 和三种正常构建产物保持上一任务行为。 +实际 npm 两版旧根声明完整保留,新增 /runtime 描述真实同步方法/可选参数, +修复旧 Node10 legacy 解析与编辑器导出冲突;无 interop 的 CJS 类型引用也通过。 +联合 139 项、源码/main/legacy 各 15 项、406 生产 TS 全仓检查通过;实际两旧包及 +候选的仓库外安装 15 编译器组合通过,新增真实 WASM 查询/修改测试。 +[变更记录](changes/2026-09-14-PKG-JASSUB-04-types.md)和 +[安装与类型证据](baselines/jassub-types-validation.json)保留中间失败及最终候选。 +新增 JASSUB-QUERY-01 有冻结错误复现,交由下一项 07 修复;没有宣称新浏览器 +播放或发布验收。下一步继续 vendor 生命周期/时钟/查询清理,05/06 仍未完成。 + + ## PKG-JASSUB-03 自有注册/清理改造完成 入口与 registration 分离;自定义 canvas、直接实例销毁后的宿主清理、重入与 diff --git a/refactor/risk-table.md b/refactor/risk-table.md index 075d339e5..d3f5b2b64 100644 --- a/refactor/risk-table.md +++ b/refactor/risk-table.md @@ -248,3 +248,4 @@ | JASSUB-VIDEO-FRAME-01 | open / 已复现 | Old video frame callbacks can drive replacement subtitle time and duplicate chains | PKG-JASSUB-02, PKG-JASSUB-07 | | JASSUB-RATE-01 | open / 已复现 | Fallback ratechange sends an Event instead of numeric playbackRate | PKG-JASSUB-02, PKG-JASSUB-07 | | JASSUB-NATIVE-FRAME-01 | open / 已复现 | Windows WebKit default frame-clock path does not produce subtitle demands in actual playback | PKG-JASSUB-02, PKG-JASSUB-07, PKG-JASSUB-05 | +| JASSUB-QUERY-01 | open / 已复现 | Subtitle query errors throw before calling the consumer and leave request listeners attached | PKG-JASSUB-07, PKG-JASSUB-05 | diff --git a/refactor/risks.json b/refactor/risks.json index f689d5c4f..32f418db1 100644 --- a/refactor/risks.json +++ b/refactor/risks.json @@ -2,7 +2,7 @@ "schemaVersion": 1, "task": "BASE-07", "sourceCommit": "e01f39ff", - "updatedAt": "2026-09-13", + "updatedAt": "2026-09-14", "note": "Open means closure evidence is outstanding; source-observed and unverified are not reproduced runtime bugs. A source issue already mitigated in the workspace still requires candidate regression evidence. No accepted-with-scope item is implied by baseline task completion.", "items": [ { @@ -779,7 +779,7 @@ "PKG-JASSUB-05" ], "evidence": [ - "packages/artplayer-plugin-jassub/src/index.js", + "packages/artplayer-plugin-jassub/src/index.ts", "docs/assets/example/jassub.js" ], "compatibleResolution": "Preserve options pass-through, result.instance and worker/wasm/font URLs. Wrapper, worker and WASM must be a verified compatible set.", @@ -5535,6 +5535,22 @@ ], "compatibleResolution": "Investigate native frame delivery and establish a compatible capability response; explicit event-clock success is diagnostic only.", "closureCriteria": "Default native behavior is verified or an explicit reviewed environment limitation is recorded; no silent global fallback or substitution of diagnostic mode for default acceptance." + }, + { + "id": "JASSUB-QUERY-01", + "title": "Subtitle query errors throw before calling the consumer and leave request listeners attached", + "confirmation": "reproduced", + "status": "open", + "owners": [ + "PKG-JASSUB-07", + "PKG-JASSUB-05" + ], + "evidence": [ + "refactor/changes/2026-09-14-PKG-JASSUB-04-types.md", + "test/jassub-runtime.test.js" + ], + "compatibleResolution": "Handle absent worker error payloads, release per-request listeners and timers before invoking user callbacks, and preserve successful synchronous query registration and callback data.", + "closureCriteria": "Actual vendor timeout and Worker-error paths invoke the consumer exactly once with the original error, leave no request listeners/timers, and successful real-WASM events/styles remain unchanged. Browser error/recovery acceptance remains PKG-JASSUB-05." } ] } diff --git a/refactor/scripts/jassub-consumer.mjs b/refactor/scripts/jassub-consumer.mjs new file mode 100644 index 000000000..171d4279f --- /dev/null +++ b/refactor/scripts/jassub-consumer.mjs @@ -0,0 +1,30 @@ +import fs from 'node:fs' + +export const jassubInvalidStatements = [ + 'jassub()', + 'jassub(undefined)', + 'jassub({ workerUrl: "/worker.js", wasmUrl: "/worker.wasm" })', + 'jassub({ workerUrl: 1, wasmUrl: "/worker.wasm", modernWasmUrl: "/modern.wasm" })', + 'instance.resize(640)', + 'const synchronousDestroy: void = instance.destroy()', + 'const wrongName: "other" = result.name', +] + +export function jassubConsumerSource(mode, raw = false) { + let source = fs.readFileSync(new URL('../../test/types/jassub-public.ts', import.meta.url), 'utf8') + if (mode === 'nodenext-esm' && !raw) { + source = source + .replace('import jassub from \'artplayer-plugin-jassub\'', 'import jassubModule from \'artplayer-plugin-jassub\'\nconst jassub = jassubModule.default') + .replace('import legacy from \'artplayer-plugin-jassub/legacy\'', 'import legacyModule from \'artplayer-plugin-jassub/legacy\'\nconst legacy = legacyModule.default') + } + return source +} + +export function jassubRuntimeSource(mode) { + const source = fs.readFileSync(new URL('../../test/types/jassub-runtime.ts', import.meta.url), 'utf8') + return mode.endsWith('-no-interop') + ? source + .replace('import runtime from \'artplayer-plugin-jassub/runtime\'', 'import runtime = require(\'artplayer-plugin-jassub/runtime\')') + .replace('import type Artplayer from \'artplayer\'', 'type Core = typeof import(\'artplayer\'); type Artplayer = Core extends { default: { prototype: infer I } } ? I : Core extends { prototype: infer I } ? I : never') + : source +} diff --git a/refactor/scripts/jassub-package-types.mjs b/refactor/scripts/jassub-package-types.mjs new file mode 100644 index 000000000..9faec4baf --- /dev/null +++ b/refactor/scripts/jassub-package-types.mjs @@ -0,0 +1,204 @@ +import assert from 'node:assert/strict' +import fs from 'node:fs' +import path from 'node:path' +import process from 'node:process' +import ts from 'typescript' +import compat from 'typescript-compat' +import { checkFiles, packedFiles } from '../../scripts/package-check.mjs' +import { consumerDirectory, removeConsumer, run, workspace, writeJson } from '../../scripts/package-consumer.mjs' +import { jassubConsumerSource, jassubInvalidStatements, jassubRuntimeSource } from './jassub-consumer.mjs' +import { verifyJassubContract } from './jassub-contract.mjs' +import { hash, readMember } from './releases.mjs' + +const name = 'artplayer-plugin-jassub' +const declaration = `package/types/${name}.d.ts` +const shape = diagnostics => diagnostics.map(({ code, file, line }) => ({ code, file, line })) +let evidenceOutput + +function installedBytes(consumer, packages) { + for (const pkg of packages) { + const root = path.join(consumer, 'node_modules', pkg.name) + assert.equal(fs.realpathSync(root), root, 'Installed package must not be a workspace link') + assert(!fs.lstatSync(root).isSymbolicLink(), 'Installed package root is a link') + for (const [member, expected] of Object.entries(pkg.files)) { + const file = path.join(root, member.slice(8)) + assert.equal(fs.realpathSync(file), file, `Installed member resolves through a link: ${member}`) + assert(fs.lstatSync(file).isFile(), `Installed member is not a regular file: ${member}`) + assert.equal(hash(fs.readFileSync(file)), expected, `Installed bytes differ: ${member}`) + } + } +} + +function runtimeProbe(candidate, old) { + return `const assert = require('node:assert/strict'); +global.self = global; +const names = ${JSON.stringify([name, `${name}/legacy`, ...(candidate ? [`${name}/runtime`] : [])])}; +const old = ${old}; +const commonjs = names.map(name => require(name)); +for (const value of commonjs) { + assert.equal(typeof value, old ? 'object' : 'function'); + assert.equal(typeof value.default, old ? 'function' : 'undefined'); + const factory = old ? value.default : value; + assert.equal(typeof factory(), 'function'); + assert.equal(typeof factory({workerUrl: '/worker.js', wasmUrl: '/wasm.wasm', modernWasmUrl: '/modern.wasm'}), 'function'); +} +${candidate ? 'assert.equal(commonjs[2], commonjs[0]); assert.equal(require.resolve(names[2]), require.resolve(names[0]));' : ''} +Promise.all(names.map(name => import(name))).then(modules => { + assert.equal(typeof modules[0].default, 'function'); + assert.equal(typeof modules[0].default(), 'function'); + assert.equal(modules[1].default, commonjs[1]); + const legacy = old ? modules[1].default.default : modules[1].default; + assert.equal(typeof legacy(), 'function'); + ${candidate ? 'assert.equal(modules[2].default, modules[0].default); assert.equal(typeof modules[2].default(), \'function\');' : ''} + console.log('Installed CJS/ESM root/legacy lazy factories and conditional runtime identity passed. Registrars were not invoked; no vendor initialization.'); +}).catch(error => { console.error(error); process.exitCode = 1; }); +` +} + +async function main() { + assert.equal(process.version.slice(1), fs.readFileSync(path.join(workspace, '.node-version'), 'utf8').trim(), 'Use the repository Node version') + assert.equal(process.env.npm_config_user_agent?.split(' ')[0], 'yarn/1.22.22', 'Use yarn test:jassub-types-package') + const yarn = process.env.npm_execpath + assert(yarn && fs.existsSync(yarn)) + const output = fs.mkdtempSync(path.join(workspace, 'refactor/.cache/jassub-package-types-')) + evidenceOutput = output + console.log(`JASSUB isolated installed consumer evidence: ${output}`) + const fixtureHashes = () => Object.fromEntries(['refactor/scripts/jassub-consumer.mjs', 'test/types/jassub-public.ts', 'test/types/jassub-runtime.ts'].map(file => [file, hash(fs.readFileSync(path.join(workspace, file)))])) + const fixtures = fixtureHashes() + const contract = await verifyJassubContract() + const releases = [...contract.baseline.previous, contract.baseline.release] + assert.deepEqual(releases.map(release => release.version), ['1.0.0', '1.1.0']) + const packages = [] + for (const packageName of ['artplayer', name]) { + const archive = path.join(output, `${packageName}.tgz`) + fs.writeFileSync(path.join(output, `${packageName}-pack.log`), run([yarn, 'pack', '--filename', archive], path.join(workspace, 'packages', packageName))) + const manifest = JSON.parse(readMember(archive, 'package/package.json')) + const files = packedFiles(archive) + checkFiles(manifest, files, packageName === name ? Object.keys(contract.baseline.release.files) : []) + packages.push({ name: packageName, archive, manifest, sha256: hash(fs.readFileSync(archive)), files: Object.fromEntries(files.map(member => [member, hash(readMember(archive, member))])) }) + } + const [core, candidate] = packages + const rootDeclarations = releases.map((release) => { + const current = readMember(candidate.archive, declaration) + const previous = readMember(contract.archives.get(release.version), declaration) + const normalize = bytes => bytes.toString('utf8').replaceAll('\r\n', '\n') + assert.equal(normalize(current), normalize(previous), `Preserve npm ${release.version} root declaration; only checkout CRLF may differ`) + return { version: release.version, candidateSha256: hash(current), publishedSha256: hash(previous), bytesEqual: current.equals(previous), normalizedLFSha256: hash(normalize(current)) } + }) + const exports = candidate.manifest.exports + assert.equal(exports['./runtime'].import.types, './types/runtime.d.mts') + assert.equal(exports['./runtime'].require.types, './types/runtime.d.cts') + assert.equal(exports['./runtime'].import.default, exports['.'].import) + assert.equal(exports['./runtime'].require.default, exports['.'].require) + assert.deepEqual(candidate.manifest.typesVersions['*'].runtime, ['types/runtime.d.ts']) + assert.deepEqual(candidate.manifest.typesVersions['*'].legacy, [`types/${name}.d.ts`]) + const plugins = [ + ...releases.map(release => ({ ...release, archive: contract.archives.get(release.version), label: `published-${release.version}` })), + { ...candidate, label: 'candidate' }, + ] + const matrix = [] + const historical = new Map() + for (const plugin of plugins) { + const consumer = consumerDirectory() + try { + writeJson(path.join(consumer, 'package.json'), { name: 'jassub-isolated-consumer', private: true, dependencies: Object.fromEntries([core, plugin].map(pkg => [pkg.name, `file:${pkg.archive.replaceAll('\\', '/')}`])) }) + fs.copyFileSync(path.join(workspace, 'yarn.lock'), path.join(consumer, 'yarn.lock')) + fs.writeFileSync(path.join(output, `${plugin.label}-install.log`), run([yarn, 'install', '--offline', '--ignore-scripts', '--non-interactive'], consumer)) + installedBytes(consumer, [core, plugin]) + const lock = fs.readFileSync(path.join(consumer, 'yarn.lock')) + fs.writeFileSync(path.join(output, `${plugin.label}-frozen-install.log`), run([yarn, 'install', '--offline', '--frozen-lockfile', '--force', '--ignore-scripts', '--non-interactive'], consumer)) + assert.deepEqual(fs.readFileSync(path.join(consumer, 'yarn.lock')), lock, 'Frozen reinstall changed consumer lock') + installedBytes(consumer, [core, plugin]) + fs.writeFileSync(path.join(output, `${plugin.label}-yarn.lock`), lock) + const runtimeFile = path.join(consumer, 'exports.cjs') + fs.writeFileSync(runtimeFile, runtimeProbe(plugin.label === 'candidate', plugin.version === '1.0.0')) + fs.writeFileSync(path.join(output, `${plugin.label}-runtime.log`), run([runtimeFile], consumer)) + for (const [compiler, mode] of [[ts, 'node10-commonjs'], [ts, 'nodenext-cjs'], [ts, 'nodenext-esm'], [ts, 'bundler-esm'], [compat, 'node10-commonjs']]) { + const next = mode.startsWith('nodenext') + const filename = path.join(consumer, `consumer.${next ? mode.endsWith('-cjs') ? 'cts' : 'mts' : 'ts'}`) + const options = { strict: true, noEmit: true, skipLibCheck: false, types: [], esModuleInterop: true, target: compiler.ScriptTarget.ES2020, lib: ['lib.es2020.d.ts', 'lib.dom.d.ts'], module: next ? compiler.ModuleKind.NodeNext : mode === 'bundler-esm' ? compiler.ModuleKind.ESNext : compiler.ModuleKind.CommonJS, moduleResolution: next ? compiler.ModuleResolutionKind.NodeNext : mode === 'bundler-esm' ? compiler.ModuleResolutionKind.Bundler : compiler.ModuleResolutionKind.NodeJs } + let declarations = [] + const compile = (source, esModuleInterop = options.esModuleInterop) => { + fs.writeFileSync(filename, source) + const program = compiler.createProgram([filename], { ...options, esModuleInterop }) + for (const file of program.getSourceFiles()) { + const actual = fs.realpathSync(file.fileName) + assert(actual.startsWith(fs.realpathSync(consumer) + path.sep) || (program.isSourceFileDefaultLibrary(file) && path.dirname(actual) === fs.realpathSync(path.dirname(compiler.sys.getExecutingFilePath()))), `Type escaped consumer: ${actual}`) + } + declarations = program.getSourceFiles().filter(file => !program.isSourceFileDefaultLibrary(file)).map(file => path.relative(consumer, file.fileName).replaceAll('\\', '/')).sort() + return compiler.getPreEmitDiagnostics(program).map(diagnostic => ({ code: diagnostic.code, file: diagnostic.file ? path.relative(consumer, diagnostic.file.fileName).replaceAll('\\', '/') : null, line: diagnostic.file && diagnostic.start !== undefined ? diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start).line + 1 : null, message: compiler.flattenDiagnosticMessageText(diagnostic.messageText, '\n').replaceAll(consumer.replaceAll('\\', '/'), '').replaceAll(consumer, '') })) + } + const rawSource = jassubConsumerSource(mode, true) + const raw = compile(rawSource) + const key = `${compiler.version}:${mode}` + const entry = { plugin: plugin.label, compiler: compiler.version, mode, raw, diagnostics: null, invalid: null, runtime: null } + matrix.push(entry) + writeJson(path.join(output, 'matrix-progress.json'), matrix) + const legacyLines = rawSource.split('\n').flatMap((line, index) => /from ['"]artplayer-plugin-jassub\/legacy['"]/.test(line) ? [index + 1] : []) + assert.equal(legacyLines.length, 1, 'The raw consumer must contain one identifiable legacy import') + const legacyFailure = { code: 2307, file: path.basename(filename), line: legacyLines[0] } + if (plugin.label === 'published-1.0.0') { + if (mode === 'node10-commonjs') + assert.deepEqual(shape(raw), [legacyFailure], 'Preserve the exact old Node10 legacy resolution error') + if (mode === 'nodenext-esm') + assert(raw.length > 0, 'Keep raw historical NodeNext namespace failures visible') + historical.set(key, { raw: shape(raw) }) + } + else { + const expected = historical.get(key).raw + assert.deepEqual(shape(raw), plugin.label === 'candidate' && mode === 'node10-commonjs' ? expected.filter(item => item.code !== legacyFailure.code || item.file !== legacyFailure.file || item.line !== legacyFailure.line) : expected, 'Only the exact recorded old Node10 legacy resolution failure may be corrected') + } + let source = jassubConsumerSource(mode) + if (plugin.label !== 'candidate' && mode === 'node10-commonjs') + source = source.replace(/(['"])artplayer-plugin-jassub\/legacy\1/g, `'artplayer-plugin-jassub/types/artplayer-plugin-jassub'`) + entry.diagnostics = compile(source) + assert.deepEqual(entry.diagnostics, [], `${plugin.label} ${compiler.version} ${mode}: explicit historical namespace consumer`) + entry.invalid = compile(`${source}\n${jassubInvalidStatements.join('\n')}\n`) + assert.equal(jassubInvalidStatements.length, 7, 'Retain all seven historical negative consumers') + assert.equal(entry.invalid.length, jassubInvalidStatements.length) + assert.deepEqual(entry.invalid.map(item => item.line), jassubInvalidStatements.map((_, index) => source.split('\n').length + 1 + index), 'Every old-entry negative statement must fail at its exact line') + if (plugin.label === 'published-1.0.0') + historical.get(key).invalid = shape(entry.invalid) + else assert.deepEqual(shape(entry.invalid), historical.get(key).invalid, 'Both published packages and candidate preserve exact invalid diagnostic codes and lines') + if (plugin.label === 'candidate') { + const runtimeSource = jassubRuntimeSource(mode) + const diagnostics = compile(runtimeSource) + const runtimeDeclarations = declarations + assert.deepEqual(diagnostics, [], `Accurate runtime consumer: ${compiler.version} ${mode}`) + const lines = runtimeSource.split('\n') + const negative = [] + for (let index = 0; index < lines.length; index++) { + if (!/^[ \t]*\/\/ @ts-expect-error/.test(lines[index])) + continue + assert(lines[index + 1]?.trim() && !lines[index + 1].trim().startsWith('//'), 'Each runtime directive must precede one negative statement') + const invalid = compile(lines.map((line, offset) => offset === index ? '' : line).join('\n')) + assert(invalid.length > 0 && invalid.every(item => item.file === path.basename(filename) && item.line === index + 2), `Runtime negative statement ${index + 2} must independently fail on its own line`) + negative.push({ line: index + 2, diagnostics: invalid }) + } + assert.equal(negative.length, 14, 'Retain all fourteen runtime negative consumers') + entry.runtime = { diagnostics, negative, declarations: runtimeDeclarations, sourceSha256: hash(runtimeSource) } + if ((compiler === ts && mode === 'nodenext-cjs') || (compiler === compat && mode === 'node10-commonjs')) { + const commonjsSource = jassubRuntimeSource(`${mode}-no-interop`) + assert(commonjsSource.includes('import runtime = require(\'artplayer-plugin-jassub/runtime\')'), 'Exercise the promised CommonJS import assignment') + const commonjsDiagnostics = compile(commonjsSource, false) + entry.runtime.commonjs = { esModuleInterop: false, diagnostics: commonjsDiagnostics, declarations, sourceSha256: hash(commonjsSource) } + writeJson(path.join(output, 'matrix-progress.json'), matrix) + assert.deepEqual(commonjsDiagnostics, [], `Runtime import=require without interop: ${compiler.version} ${mode}`) + } + } + writeJson(path.join(output, 'matrix-progress.json'), matrix) + } + } + finally { removeConsumer(consumer) } + } + assert.deepEqual(fixtureHashes(), fixtures, 'Consumer fixtures changed during the installed matrix; rerun with final inputs') + writeJson(path.join(output, 'report.json'), { task: 'PKG-JASSUB-04', node: process.version, fixtures, rootDeclarations, packages, published: plugins.slice(0, 2).map(plugin => ({ label: plugin.label, archive: plugin.archive, sha256: hash(fs.readFileSync(plugin.archive)) })), matrix, scope: 'Actual npm 1.0.0/1.1.0 and Yarn-packed candidate/core installed outside workspace; offline installation and forced frozen reinstall with unchanged lock, strictly verified installed member hashes and non-link checks; root declaration text unchanged after CRLF normalization with both raw hashes recorded, exact old diagnostics, conditional accurate runtime declarations and Node lazy factory/legacy identity. Registrars are never invoked in Node; this is not browser Worker/WASM/font rendering or publication acceptance.' }) + console.log(`JASSUB isolated installed consumers passed ${matrix.length} compiler modes: ${output}`) +} + +main().catch((error) => { + if (evidenceOutput) + writeJson(path.join(evidenceOutput, 'failure.json'), { message: error.message, stack: error.stack }) + console.error(error) + process.exitCode = 1 +}) diff --git a/refactor/scripts/jassub-types.test.mjs b/refactor/scripts/jassub-types.test.mjs new file mode 100644 index 000000000..2bcf31e1a --- /dev/null +++ b/refactor/scripts/jassub-types.test.mjs @@ -0,0 +1,74 @@ +import assert from 'node:assert/strict' +import fs from 'node:fs' +// eslint-disable-next-line test/no-import-node-test -- Repository baseline runner. +import test from 'node:test' +import { ESLint } from 'eslint' +import ts from 'typescript' +import compat from 'typescript-compat' +import { checkPluginEditorDeclaration, generatePluginEditorDeclaration } from '../../scripts/plugin-editor-types.mjs' +import { checkConsumer } from '../../scripts/typecheck.mjs' +import { jassubConsumerSource, jassubInvalidStatements, jassubRuntimeSource } from './jassub-consumer.mjs' +import { verifyJassubContract } from './jassub-contract.mjs' +import { readMember } from './releases.mjs' + +const modes = [[ts, 'node10-commonjs'], [ts, 'nodenext-cjs'], [ts, 'nodenext-esm'], [ts, 'bundler-esm'], [compat, 'node10-commonjs']] + +test('JASSUB keeps both actual published root declarations without changing historical extraction or replacement types', async () => { + const contract = await verifyJassubContract() + const candidate = fs.readFileSync('packages/artplayer-plugin-jassub/types/artplayer-plugin-jassub.d.ts', 'utf8').replaceAll('\r\n', '\n') + for (const archive of contract.archives.values()) + assert.equal(candidate, readMember(archive, 'package/types/artplayer-plugin-jassub.d.ts').toString().replaceAll('\r\n', '\n')) + for (const [compiler, mode] of modes) { + const source = jassubConsumerSource(mode) + assert.deepEqual(checkConsumer(compiler, mode, source), [], `${compiler.version} ${mode}`) + const errors = checkConsumer(compiler, mode, `${source}\n${jassubInvalidStatements.join('\n')}\n`) + assert.deepEqual(errors.map(item => item.line), jassubInvalidStatements.map((_, index) => source.split('\n').length + 1 + index)) + } +}) + +test('JASSUB runtime entry checks optional options, sync instances, worker messages, callbacks and invalid consumers', () => { + for (const [compiler, mode] of modes) { + const source = jassubRuntimeSource(mode) + assert.deepEqual(checkConsumer(compiler, mode, source), [], `${compiler.version} ${mode}`) + const invalid = checkConsumer(compiler, mode, source.replaceAll(/\/\/ @ts-expect-error[^\n]*\n/g, '')) + const expected = [] + let line = 1 + for (const text of source.split('\n')) { + if (text.startsWith('// @ts-expect-error')) + expected.push(line) + else line++ + } + assert.equal(expected.length, 14) + assert.deepEqual(invalid.map(item => item.line), expected, `${compiler.version} ${mode}: each negative statement must fail independently`) + } + assert.deepEqual(checkConsumer(ts, 'nodenext-cjs', `import root = require('artplayer-plugin-jassub'); import legacy = require('artplayer-plugin-jassub/legacy'); import runtime = require('artplayer-plugin-jassub/runtime'); +const option: root.JassubOption = {workerUrl: '/worker.js', wasmUrl: '/worker.wasm', modernWasmUrl: '/modern.wasm'}; +root.default(option); legacy.default(option); runtime(); const value: runtime.RuntimeOption = {}; runtime(value);`), []) +}) + +test('JASSUB generated editor declaration preserves the old global API and is valid in both compilers', async () => { + const source = fs.readFileSync('packages/artplayer-plugin-jassub/types/artplayer-plugin-jassub.d.ts', 'utf8') + const generated = generatePluginEditorDeclaration(source, 'artplayerPluginJassub') + const file = 'docs/assets/ts/artplayer-plugin-jassub.d.ts' + const [formatted] = await new ESLint({ fix: true, fixTypes: ['layout'] }).lintText(generated, { filePath: file }) + assert.equal(formatted.errorCount, 0) + assert.equal(fs.readFileSync(file, 'utf8').replaceAll('\r\n', '\n'), formatted.output || generated) + const core = fs.readFileSync('docs/assets/ts/artplayer.d.ts', 'utf8') + const consumer = `declare const art: Artplayer; +const option: artplayerPluginJassub.JassubOption = {workerUrl: '/worker.js', wasmUrl: '/worker.wasm', modernWasmUrl: '/modern.wasm'}; +const result = artplayerPluginJassub(option)(art); +const promise: Promise = result.instance.resize(true, 640, 360); +const replacement: typeof artplayerPluginJassub = (_option) => (_art) => result; +// @ts-expect-error Keep the historical required options argument. +artplayerPluginJassub(); +// @ts-expect-error Keep the historical required resource URLs. +artplayerPluginJassub({}); +// @ts-expect-error Global editor uses the historical force-first resize signature. +result.instance.resize(640);` + for (const compiler of [ts, compat]) { + assert.deepEqual(checkPluginEditorDeclaration(generated, core, consumer, compiler), []) + assert.equal(checkPluginEditorDeclaration(generated, core, consumer.replaceAll(/\/\/ @ts-expect-error[^\n]*\n/g, ''), compiler).length, 3) + const oldEditor = `${source.replace(/^import.*$/gim, '')}\nexport = artplayerPluginJassub;\nexport as namespace artplayerPluginJassub;\n` + assert(checkPluginEditorDeclaration(oldEditor, core, '', compiler).some(item => item.code === 2309), 'Reproduce the former conflicting export assignment before claiming the editor fix') + } +}) diff --git a/refactor/tasks.json b/refactor/tasks.json index 53f95b6e5..fa02e2960 100644 --- a/refactor/tasks.json +++ b/refactor/tasks.json @@ -2477,11 +2477,14 @@ "ENG-06", "CORE-07" ], - "status": "todo", + "status": "done", "risk": "H", "deliverable": "JASSUB option/instance 的兼容类型包装,vendor JS 例外记录", "acceptance": "严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容", - "evidence": [] + "evidence": [ + "changes/2026-09-14-PKG-JASSUB-04-types.md", + "baselines/jassub-types-validation.json" + ] }, { "id": "PKG-JASSUB-05", @@ -2531,7 +2534,7 @@ ], "status": "todo", "risk": "H", - "deliverable": "独立记录 vendor 适配差异;幂等销毁、跨容器 setVideo、构造回滚、逐帧归属和倍率/能力边界", + "deliverable": "独立记录 vendor 适配差异;幂等销毁、跨容器 setVideo、构造回滚、逐帧归属和倍率/能力边界;查询 timeout/Worker error 的缺失数据回调及每请求监听器/定时器清理(JASSUB-QUERY-01)", "acceptance": "保持公开真实 instance、同步方法与资源路径;保留原 vendor 来源指纹并记录每项实际补丁;候选修复正例和真实字幕/失败/时钟验证通过,未证实设备不得冒充通过", "evidence": [] }, diff --git a/refactor/third-party.json b/refactor/third-party.json index 85ddb4fe8..bd7f6d172 100644 --- a/refactor/third-party.json +++ b/refactor/third-party.json @@ -1258,7 +1258,7 @@ "PKG-JASSUB-05" ], "sourceFiles": [ - "packages/artplayer-plugin-jassub/src/index.js", + "packages/artplayer-plugin-jassub/src/index.ts", "docs/assets/example/jassub.js" ], "contract": "Preserve options pass-through, result.instance and worker/wasm/font URLs. Wrapper, worker and WASM must be a verified compatible set.", diff --git a/refactor/type-compatibility-policy.md b/refactor/type-compatibility-policy.md index 755cbafe1..8011c1976 100644 --- a/refactor/type-compatibility-policy.md +++ b/refactor/type-compatibility-policy.md @@ -35,3 +35,8 @@ Danmuku的PKG-DANMUKU-06保留实际npm 5.3.0根声明的完整类型形状与 points、静态icons和回调receiver;根/legacy/runtime复用原分发实现,不添加不存在 的factory.default。旧入口用户不需要因本次类型迁移修改代码。切换/runtime是可选 的准确类型入口,历史声明与运行时的区别见包README;这里没有新增旧类型破坏授权。 + +JASSUB 的 PKG-JASSUB-04 保留实际 npm 1.0.0/1.1.0 相同的根声明(忽略换行), +不改变必填资源 URL、旧 resize 参数顺序、Promise 返回声明和扩展索引。新增 +/runtime 描述真实可选参数、同步方法及 Worker 数据,并复用同一运行产物。 +这项实施没有新增旧类型破坏,不声称用户另行批准过 JASSUB 专属类型冲突。 diff --git a/scripts/build-ts.js b/scripts/build-ts.js index 20a3fea1a..f2a5134d7 100644 --- a/scripts/build-ts.js +++ b/scripts/build-ts.js @@ -53,7 +53,7 @@ console.log(`✨ Built ${artplayerTSoutput}`); const type = pluginsTS[index] const { name, file } = parsePluginInfo(type) const source = String(fs.readFileSync(type)) - const semanticPlugin = ['artplayerPluginDanmukuMask', 'artplayerPluginDanmuku', 'artplayerPluginChromecast', 'artplayerPluginAsr', 'artplayerPluginMultipleSubtitles', 'artplayerPluginVttThumbnail', 'artplayerPluginHlsControl', 'artplayerPluginAudioTrack', 'artplayerPluginDashControl', 'artplayerPluginAds', 'artplayerPluginAmbilight', 'artplayerProxyCanvas', 'artplayerProxyMediabunny', 'artplayerPluginDocumentPip', 'ArtplayerToolIframe', 'ArtplayerToolThumbnail'].includes(name) + const semanticPlugin = ['artplayerPluginJassub', 'artplayerPluginDanmukuMask', 'artplayerPluginDanmuku', 'artplayerPluginChromecast', 'artplayerPluginAsr', 'artplayerPluginMultipleSubtitles', 'artplayerPluginVttThumbnail', 'artplayerPluginHlsControl', 'artplayerPluginAudioTrack', 'artplayerPluginDashControl', 'artplayerPluginAds', 'artplayerPluginAmbilight', 'artplayerProxyCanvas', 'artplayerProxyMediabunny', 'artplayerPluginDocumentPip', 'ArtplayerToolIframe', 'ArtplayerToolThumbnail'].includes(name) const localTypes = name === 'artplayerProxyMediabunny' ? { './media': fs.readFileSync(path.join(path.dirname(type), 'media.d.ts'), 'utf8') } : {} const code = semanticPlugin ? generatePluginEditorDeclaration(source, name, localTypes) diff --git a/test/jassub-runtime.test.js b/test/jassub-runtime.test.js new file mode 100644 index 000000000..e40abb0e8 --- /dev/null +++ b/test/jassub-runtime.test.js @@ -0,0 +1,236 @@ +import assert from 'node:assert/strict' +import fs from 'node:fs' +// eslint-disable-next-line test/no-import-node-test -- Accurate runtime contracts use the repository runner. +import test from 'node:test' +import { isPromise } from 'node:util/types' +import vm from 'node:vm' +import { jassubCandidate, jassubEnvironment, jassubHistorical } from './helpers/jassub.js' + +const candidate = await jassubCandidate() +const frozen = (await jassubHistorical()).find(item => item.name === 'frozen-workspace-source') + +function environment(implementation) { + const code = `${implementation.code}\nObject.defineProperty(module.exports.default || module.exports, '__runtimePlatform', { value: { ErrorEvent, setGlobal: (name, value) => { globalThis[name] = value } } });` + const env = jassubEnvironment({ ...implementation, code }) + env.platform = env.factory.__runtimePlatform + return env +} + +function requestListeners(worker) { + const listeners = new Map() + worker.addEventListener = (type, callback) => { + if (!listeners.has(type)) + listeners.set(type, new Set()) + listeners.get(type).add(callback) + } + worker.removeEventListener = (type, callback) => listeners.get(type)?.delete(callback) + return { + size: () => [...listeners.values()].reduce((sum, entries) => sum + entries.size, 0), + emit(type, event) { + for (const callback of [...listeners.get(type) || []]) callback(event) + }, + } +} + +test('JASSUB accurate runtime resize uses width/height/top/left/force and lifecycle methods return synchronously', async () => { + const env = environment(candidate) + const { instance } = env.factory()(env.art) + await env.ready() + assert.equal(instance.resize(320, 180, 4, 7, false), undefined) + assert.equal(instance._canvas.style.top, '4px') + assert.equal(instance._canvas.style.left, '7px') + await env.flush() + const resize = env.workers[0].messages.at(-1) + assert.equal(resize.target, 'canvas') + assert.equal(resize.width, 320) + assert.equal(resize.height, 180) + assert.equal(resize.force, false) + const video = env.createVideo() + assert.equal(instance.setVideo(video), undefined) + assert.equal(instance._video, video) + assert.equal(instance.destroy(), undefined) + assert.equal(env.workers[0].terminated, 1) + assert.equal(env.parent.children.some(child => child.className === 'JASSUB'), false) +}) + +test('JASSUB accurate sendMessage returns a Promise waiting for ready and resolving after the actual post', async () => { + const env = environment(candidate) + const { instance } = env.factory()(env.art) + const payload = { value: 42 } + const pending = instance.sendMessage('runtime-probe', payload) + assert(isPromise(pending)) + let settled = false + pending.then(() => { + settled = true + }) + await env.flush() + assert.equal(settled, false) + assert.deepEqual(env.workers[0].messages.map(message => message.target), ['init']) + await env.ready() + assert.equal(await pending, undefined) + assert.equal(settled, true) + assert.equal(env.workers[0].messages.at(-1).target, 'runtime-probe') + assert.equal(env.workers[0].messages.at(-1).value, 42) + instance.destroy() +}) + +test('JASSUB accurate font options preserve mixed sources and font methods return synchronously', async () => { + const env = environment(candidate) + const bytes = new Uint8Array([1, 2, 3]) + const fonts = ['fixture.woff2', bytes] + const availableFonts = { fixture: bytes, fallback: 'fallback.woff2' } + const { instance } = env.factory({ fonts, availableFonts })(env.art) + await env.ready() + const init = env.workers[0].messages[0] + assert.equal(init.fonts, fonts) + assert.equal(init.fonts[1], bytes) + assert.equal(init.availableFonts, availableFonts) + assert.equal(instance.addFont(bytes), undefined) + assert.equal(instance.setDefaultFont('fixture'), undefined) + await env.flush() + const added = env.workers[0].messages.find(message => message.target === 'addFont') + assert.equal(added.font, bytes) + assert.equal(env.workers[0].messages.at(-1).target, 'defaultFont') + assert.equal(env.workers[0].messages.at(-1).font, 'fixture') + instance.destroy() +}) + +const subtitles = `[Script Info] +ScriptType: v4.00+ +PlayResX: 640 +PlayResY: 360 +[V4+ Styles] +Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding +Style: Default,Arial,24,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,0,2,10,10,10,1 +[Events] +Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text +Dialogue: 0,0:00:01.00,0:00:03.00,Default,,0,0,0,,Runtime fixture` + +test('JASSUB real Worker JS/WASM queries return numeric style indices and full event/style data through controlled transport', { timeout: 10000 }, async (context) => { + const env = environment(candidate) + env.platform.setGlobal('setTimeout', setTimeout) + env.platform.setGlobal('clearTimeout', clearTimeout) + const { instance } = env.factory({ subContent: subtitles, availableFonts: {}, fallbackFont: 'fixture', wasmUrl: '/runtime-fixture.wasm', onDemandRender: false, offscreenRender: false, asyncRender: false })(env.art) + const worker = env.workers[0] + const listeners = requestListeners(worker) + const wasm = fs.readFileSync('packages/artplayer-plugin-jassub/worker/jassub-worker.wasm') + const source = fs.readFileSync('packages/artplayer-plugin-jassub/worker/jassub-worker.js', 'utf8') + const requests = [] + const messages = [] + let initialized = false + let stopped = false + const workerContext = { + WebAssembly, + TextDecoder, + TextEncoder, + console, + onmessage: null, + async fetch(url) { + assert.equal(url, '/runtime-fixture.wasm') + requests.push(url) + return new Response(wasm, { headers: { 'Content-Type': 'application/wasm' } }) + }, + postMessage(message) { + const data = structuredClone(message) + messages.push(data) + if (data.target === 'ready') + initialized = true + queueMicrotask(() => { + if (stopped) + return + worker.onmessage({ data }) + listeners.emit('message', { data }) + }) + }, + } + workerContext.self = workerContext + vm.createContext(workerContext) + // Execute complete production Worker JS and actual WASM. Only transport and fetch are controlled. + vm.runInContext(source, workerContext, { timeout: 5000 }) + const post = worker.postMessage + worker.postMessage = function (message) { + post.call(this, message) + if (!stopped) + workerContext.onmessage({ data: structuredClone(message) }) + } + const terminate = worker.terminate + worker.terminate = function () { + if (initialized && !stopped) + workerContext.onmessage({ data: { target: 'destroy' } }) + stopped = true + terminate.call(this) + } + context.after(() => instance.destroy()) + let readyEvents = 0 + instance.addEventListener('ready', (event) => { + readyEvents++ + assert.equal(event.detail, null) + assert.equal(event.target, instance) + }) + assert(instance instanceof EventTarget) + await new Promise(resolve => instance.addEventListener('ready', resolve, { once: true })) + assert.equal(readyEvents, 1) + assert.deepEqual(requests, ['/runtime-fixture.wasm']) + const query = method => new Promise((resolve, reject) => { + assert.equal(instance[method]((error, rows) => { + if (error !== null) { + reject(error ?? new Error('Successful queries must pass null as their error argument')) + return + } + resolve(rows) + }), undefined) + }) + const events = await query('getEvents') + const styles = await query('getStyles') + assert.equal(events.length, 1) + assert.equal(events[0].Start, 1000) + assert.equal(events[0].Duration, 2000) + assert.equal(events[0].Text, 'Runtime fixture') + assert.equal(typeof events[0].Style, 'number') + assert.equal(Object.hasOwn(events[0], '_index'), false) + assert.equal(styles[events[0].Style].FontName, 'Arial') + assert.equal(styles[events[0].Style].FontSize, 24) + assert.equal(typeof styles[events[0].Style].PrimaryColour, 'number') + assert.equal(listeners.size(), 0) + assert.deepEqual(messages.find(message => message.target === 'getEvents').events, events) + assert.deepEqual(messages.find(message => message.target === 'getStyles').styles, styles) + assert.equal(instance.setEvent({ Text: 'Updated through Worker', Style: events[0].Style }, 0), undefined) + await env.flush() + assert.equal((await query('getEvents'))[0].Text, 'Updated through Worker') + assert.equal(instance.setStyle({ FontSize: 32 }, events[0].Style), undefined) + await env.flush() + assert.equal((await query('getStyles'))[events[0].Style].FontSize, 32) +}) + +for (const method of ['getEvents', 'getStyles']) { + for (const mode of ['timeout', 'worker-error']) { + test(`JASSUB frozen PKG-JASSUB-07 defect: ${method} ${mode} throws before the public error callback`, async () => { + const env = environment(frozen) + const timers = new Map() + let next = 0 + env.platform.setGlobal('setTimeout', (callback) => { + timers.set(++next, callback) + return next + }) + env.platform.setGlobal('clearTimeout', id => timers.delete(id)) + const { instance } = env.factory()(env.art) + await env.ready() + const listeners = requestListeners(env.workers[0]) + let calls = 0 + instance[method](() => calls++) + assert.equal(listeners.size(), 2) + const trigger = mode === 'timeout' + ? () => { + const [id, callback] = [...timers][0] + timers.delete(id) + callback() + } + : () => listeners.emit('error', new env.platform.ErrorEvent('error', { error: new Error('controlled Worker error') })) + assert.throws(trigger, { name: 'TypeError', message: /Cannot destructure property/ }) + assert.equal(calls, 0) + assert.equal(listeners.size(), 2) + assert.equal(timers.size, mode === 'timeout' ? 0 : 1) + instance.destroy() + }) + } +} diff --git a/test/types/jassub-public.ts b/test/types/jassub-public.ts new file mode 100644 index 000000000..0647294b0 --- /dev/null +++ b/test/types/jassub-public.ts @@ -0,0 +1,28 @@ +import type Artplayer from 'artplayer' +import type { JassubInstance, JassubOption } from 'artplayer-plugin-jassub' +import jassub from 'artplayer-plugin-jassub' +import legacy from 'artplayer-plugin-jassub/legacy' + +type Equal = (() => T extends A ? 1 : 2) extends (() => T extends B ? 1 : 2) ? true : false +type Assert = T +interface OldResult { name: 'artplayerPluginJassub', instance: JassubInstance } +type OldFactory = (option: JassubOption) => (art: Artplayer) => OldResult +type FactoryCheck = Assert> +type ArgumentCheck = Assert, [option: JassubOption]>> +type ReturnCheck = Assert>, OldResult>> +type ResizeCheck = Assert, [force?: boolean, width?: number, height?: number, top?: number, left?: number]>> + +declare const art: Artplayer +declare const instance: JassubInstance +const option: JassubOption = { workerUrl: '/worker.js', wasmUrl: '/worker.wasm', modernWasmUrl: '/modern.wasm', futureOption: true } +const replacement: typeof jassub = (_option: JassubOption) => (_art: Artplayer) => ({ name: 'artplayerPluginJassub', instance }) +const reverse: OldFactory = jassub +const legacyReplacement: typeof legacy = replacement +const result: OldResult = jassub(option)(art) +legacy(option)(art) +const resize: Promise = result.instance.resize(true, 640, 360, 0, 0) +const video: Promise = result.instance.setVideo(art.video) +const destroy: Promise = result.instance.destroy() +const extension: string = result.instance.futureMethod(option.futureOption) +export type { ArgumentCheck, FactoryCheck, ResizeCheck, ReturnCheck } +export { destroy, extension, legacyReplacement, replacement, resize, reverse, video } diff --git a/test/types/jassub-runtime.ts b/test/types/jassub-runtime.ts new file mode 100644 index 000000000..56281c975 --- /dev/null +++ b/test/types/jassub-runtime.ts @@ -0,0 +1,101 @@ +import type Artplayer from 'artplayer' +import type { AssEvent, AssStyle, RuntimeFactory, RuntimeInstance, RuntimeOption, RuntimeResult } from 'artplayer-plugin-jassub/runtime' +import runtime from 'artplayer-plugin-jassub/runtime' + +type Equal = (() => T extends A ? 1 : 2) extends (() => T extends B ? 1 : 2) ? true : false +type Assert = T +export type HostCheck = Assert>, [art: Artplayer]>> + +declare const art: Artplayer +declare const canvas: HTMLCanvasElement +const option: RuntimeOption = { canvas, fonts: ['/font.woff2', new Uint8Array([0])], availableFonts: { fallback: new Uint8Array([0]) }, onDemandRender: false } +const factory: RuntimeFactory = runtime +const result: RuntimeResult = runtime(option)(art) +const replacement: typeof runtime = (_option?: RuntimeOption) => (_art: Artplayer) => result +const defaults: RuntimeResult = runtime()(art) +runtime(undefined)(art) +runtime({ video: null, canvas })(art) +const instance: RuntimeInstance = result.instance +const target: EventTarget = instance +const resize: void = instance.resize(640, 360, 0, 0, true) +const video: void = instance.setVideo(art.video) +const destroyed: void = instance.destroy() +const error: Error = instance.destroy(new Error('test')) +const errorOrEmpty: Error | '' = instance.destroy('failure') +const sent: Promise = instance.sendMessage('custom', { payload: new Uint8Array([1]) }, []) +instance.setCurrentTime(false, 10, 2) +instance.setTrackByUrl('/sub.ass') +instance.setTrack('[Script Info]') +instance.freeTrack() +instance.setIsPaused(true) +instance.setRate(2) +instance.createEvent({ Start: 1000, Duration: 2000, Style: 0, Text: 'Subtitle' }) +instance.setEvent({ Text: 'Replacement' }, 0) +instance.removeEvent(0) +instance.createStyle({ Name: 'Default', FontSize: 24 }) +instance.setStyle({ Bold: 1 }, 0) +instance.removeStyle(0) +instance.styleOverride({ FontSize: 30 }) +instance.disableStyleOverride() +instance.addFont(new Uint8Array([0])) +instance.setDefaultFont('fallback') +instance.runBenchmark() +instance.getEvents((failure, events) => { + const caught: Error | ErrorEvent | null = failure + const values: AssEvent[] | undefined = events + if (events) { + for (const event of events) { + const style: number = event.Style + const start: number = event.Start + void [style, start] + } + } + void [caught, values] +}) +instance.getStyles((_failure, styles) => { + const values: AssStyle[] | undefined = styles + void values +}) +instance.addEventListener('ready', function (event) { + function acceptsInstance(_instance: RuntimeInstance) {} + acceptsInstance(this) + const detail: null = event.detail + void detail +}) +instance.addEventListener('error', (event) => { + const message: string = event.message + void message +}) +instance.addEventListener('custom', { handleEvent(event) { + const type: string = event.type + void type +} }) +// @ts-expect-error Runtime URL fields are optional strings, not numbers. +runtime({ workerUrl: 42 }) +// @ts-expect-error Accurate entry does not silently accept unknown options. +runtime({ typoOption: true }) +// @ts-expect-error Resize starts with width; force is the fifth parameter. +instance.resize(true) +// @ts-expect-error Actual destroy is synchronous. +const asyncDestroy: Promise = instance.destroy() +// @ts-expect-error Actual setVideo is synchronous. +const asyncVideo: Promise = instance.setVideo(art.video) +// @ts-expect-error Actual resize is synchronous. +const asyncResize: Promise = instance.resize() +// @ts-expect-error Registration is synchronous. +runtime()(art).then(() => {}) +// @ts-expect-error sendMessage waits for initialization and returns a Promise. +const syncMessage: void = instance.sendMessage('custom') +// @ts-expect-error Style is the numeric libass index. +instance.createEvent({ Style: 'Default' }) +// @ts-expect-error Worker responses do not contain _index. +const index: number = ({} as AssEvent)._index +// @ts-expect-error Callback errors may omit the event list. +instance.getEvents((_error, events) => { const required: AssEvent[] = events; void required }) // eslint-disable-line style/max-statements-per-line -- Keep this rejected callback on one diagnostic line. +// @ts-expect-error Font data must be a URL or bytes. +instance.addFont(1) +// @ts-expect-error Unknown instance methods are not hidden by an any index. +instance.nonexistentMethod() +// @ts-expect-error Only two blend modes are supported. +runtime({ blendMode: 'gpu' }) +void [asyncDestroy, asyncVideo, asyncResize, defaults, destroyed, error, errorOrEmpty, factory, index, replacement, resize, sent, syncMessage, target, video]