mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-12 23:36:15 -08:00
206 lines
13 KiB
Markdown
206 lines
13 KiB
Markdown
# Thumbnail tool maintenance map
|
|
|
|
The runtime responsibilities were separated under PKG-TOOL-THUMB-03 and are now
|
|
strict TypeScript under PKG-TOOL-THUMB-04. Public declarations and isolated installed
|
|
entrypoints now have checks; final integration/release gates remain open.
|
|
|
|
The user approved the
|
|
[compatibility decision](../../refactor/thumbnail-compatibility-decision.md) on 2026-09-15:
|
|
recovered 3.5.31 defaults versus opt-in workspace 4.4.0 behavior, including the
|
|
class-level DEFAULTS boundary. The root constructor now defaults to the published
|
|
policy; `compatibility: 'workspace-4.4'` selects the previous workspace behavior.
|
|
|
|
| File | Responsibility |
|
|
| --- | --- |
|
|
| src/index.ts | Public class, historical method names, construction and destruction entry |
|
|
| src/lifecycle.ts | Private state, source/input generations, cancellation and resource release |
|
|
| src/source.ts | File loading, native metadata/error listeners and source/thumbnail Blob URLs |
|
|
| src/extraction.ts | Owned metadata wait and serial frame job, callback/error completion and cancellation |
|
|
| src/input.ts | Option validation/clamps, file-input wrapper creation, listener registration/replacement and release |
|
|
| src/policy.ts | Approved mode selection and numeric normalization; no DOM or timer ownership |
|
|
| src/sheet.ts | Midpoint grid, canvas/footer geometry, temporary download anchor |
|
|
| src/emitter.ts | Typed local adaptation of tiny-emitter; preserves on/once/emit/off behavior |
|
|
| src/utils.ts | Pure clamp and filename helpers; unused sleep/serial helpers removed |
|
|
| src/types.ts | Internal option, frame, event tuple, job and lifecycle contracts; no runtime output |
|
|
| types/artplayer-tool-thumbnail.d.ts | Public class/namespace; d.cts/d.mts wrappers share its identity |
|
|
|
|
The entry delegates to input/source/extraction/sheet. Helpers import its type only;
|
|
the imports are erased and do not create a runtime dependency on the entry.
|
|
Input/source use lifecycle state, extraction uses lifecycle/source, and sheet uses
|
|
only filename calculation. types.ts contains no imports or executable state.
|
|
Input records live in a private WeakMap, so callers replacing `option` cannot
|
|
lose ownership of generated inputs/listeners. Normal construction preserves the
|
|
existing instance-field order and bound inputChange/ondrop methods. Public method
|
|
spelling and return values stay unchanged. DEFAULTS includes published delay: 300.
|
|
|
|
Input setup validates options before changing DOM or committed options. A wrapper
|
|
receives one owned input; repeated setup with that wrapper reuses it. Replacement
|
|
installs the new listeners before releasing the old input. A failed new listener
|
|
installation rolls back its partial listeners/DOM. Explicit caller-provided file
|
|
inputs are never removed. Generated inputs are removed and the wrapper's previous
|
|
position is restored only if its current position still matches the tool's write.
|
|
The existing bound ondrop method is now registered correctly.
|
|
|
|
Destroy is idempotent and attempts input, video, current URL and destroy-event
|
|
cleanup even when one step throws; the first cleanup error escapes afterward.
|
|
Setup/file-input/drop/load calls cannot recreate input/source resources after
|
|
destruction. The emitter is not globally cleared. Destruction closes the instance
|
|
before cleanup, cancels its job and releases private URLs even if public URL fields
|
|
were overwritten. Current public URLs are also revoked, preserving historical
|
|
destroy behavior. The video is paused, its src removed, load resets its decoder
|
|
state, and its node is removed. Registration checks for reentrant closure/replacement.
|
|
|
|
Cleanup records whether an exception occurred separately from its value. It attempts
|
|
all remaining cleanup callbacks and then rethrows the first value unchanged, including
|
|
undefined, null, false, zero, an empty string or NaN. In particular, a destroy listener
|
|
must not have its exception swallowed just because it is falsy. The instance remains
|
|
closed after a failed destroy; a repeated destroy is a no-op. This is distinct from
|
|
emitter dispatch: an exception still stops the remaining listeners in that dispatch.
|
|
`test/thumbnail-cleanup-errors.test.js` compares recovered 3.5.31 and frozen workspace
|
|
behavior, checks first-error identity across nested cleanup and verifies resource release.
|
|
`test/browser/thumbnail-emitter.spec.js` repeats the listener contract with real DOM.
|
|
|
|
## Extraction and event ordering
|
|
|
|
Loading emits file before assigning video.src, then video after the configured
|
|
delay in the default published policy, or synchronously in workspace mode.
|
|
A source generation prevents an older file callback or URL creation
|
|
hook from overwriting a nested newer load. Successful replacement revokes old
|
|
source URLs. Native errors report once for their source; stale listeners cannot
|
|
fail the latest job. Existing sheet URLs stay available until the next sheet frame
|
|
or destruction, matching the previous public behavior.
|
|
|
|
start creates one owned job. Metadata waits use native events plus the existing
|
|
one-second polling fallback. Waiting before the first file adopts that selection;
|
|
replacing an existing source cancels its old job. Duplicate starts are rejected.
|
|
Preflight stays synchronous when metadata is ready. Canvas precedes processing=true;
|
|
updates observe true, done observes false and may start another job without old
|
|
completion clearing the new state.
|
|
|
|
Published mode keeps configured height (clamped to 10-1000), waits delay after each
|
|
seek and delay * 2 after the last update before done. Delay defaults to 300 and is
|
|
clamped to 10-1000. Workspace mode derives height from video aspect ratio, ignores
|
|
delay and resets the selected input value; published mode retains that value.
|
|
Source notifications and extraction waits own their timers separately, so replacement,
|
|
error and destroy cancel both without late events. A null policy delay means no
|
|
timer; NaN retains the historical asynchronous browser timer behavior.
|
|
|
|
Frames wait for readiness/seek as well as any policy delay, accept readiness/Blob callbacks once and restore
|
|
oncanplay only while still owning it. Seek/draw/encoding failures, null Blob and
|
|
throwing callbacks settle the promise and detach job resources. Source replacement
|
|
or destruction rejects with AbortError without an error event. The public promise
|
|
still rejects for awaiting consumers; an internal handler owns ignored cancellation.
|
|
Late callbacks cannot create URLs, emit updates or schedule frames. There is no
|
|
arbitrary new metadata deadline; waiting can be cancelled by destroy/replacement.
|
|
|
|
Sheet extraction preserves fractional coordinates, historical `creat*` names,
|
|
the 30-pixel footer and the filename algorithm. The temporary download anchor is
|
|
removed even if click throws. Aspect-derived height and synchronous video events
|
|
apply only to explicit workspace-4.4 mode; the default preserves recovered
|
|
3.5.31 fixed height and delays. See the frozen
|
|
[contract](../../refactor/baselines/thumbnail-contract.md) before changing defaults.
|
|
|
|
## Validation and continuation
|
|
|
|
Use Yarn and the repository scripts:
|
|
|
|
```sh
|
|
yarn test:thumbnail
|
|
yarn typecheck
|
|
yarn build artplayer-tool-thumbnail
|
|
yarn test:browser test/browser/thumbnail-tool.spec.js test/browser/thumbnail-native.spec.js test/browser/thumbnail-input.spec.js
|
|
```
|
|
|
|
`test/thumbnail-input.test.js` contains candidate input/export regressions; set
|
|
ARTPLAYER_THUMBNAIL_BASELINE=1 to reproduce failures against frozen workspace
|
|
main. ARTPLAYER_THUMBNAIL_ARTIFACT selects an actual built artifact for Node and
|
|
browser candidate checks. `test/thumbnail.test.js` remains immutable-behavior
|
|
evidence against old implementations, including intentionally reproduced bugs.
|
|
|
|
Browser records distinguish actual extraction from native Blob-unavailable
|
|
controls. Windows WebKit can load tested MP4 files over HTTP but returns error 4
|
|
for native Blob URLs; this is not successful file extraction. Actual input/DOM
|
|
cleanup runs on all three engines, while extraction acceptance needs supported
|
|
Safari/WebKit evidence in 05. The independent tool example is
|
|
`docs/assets/example/tool.thumbnail.js`, not the external thumbnail plugin example.
|
|
|
|
`test/thumbnail-lifecycle.test.js` covers jobs, source cancellation, native errors,
|
|
callback failures, reentrancy and private resources. Browser tests hold real PNG
|
|
callbacks and replace a selected file during encoding; only the latest job may
|
|
complete. Preserve old tests and the approved delay/height boundary. The new
|
|
`test/thumbnail-policy.test.js` covers both modes, owned delays and cancellation;
|
|
browser extraction checks both policies against the frozen historical bundles.
|
|
The [public type guide](types/README.md)
|
|
documents declaration ownership, module entries, events and installed consumers.
|
|
See [task plan](../../refactor/plan.md) and [risk ledger](../../refactor/risks.json).
|
|
|
|
## Generated sheets consumed by ArtPlayer
|
|
|
|
The tool owns both `videoUrl` and `thumbnailUrl`. Destroy the player borrowing
|
|
those URLs before generating a replacement sheet or destroying the tool. Pass
|
|
the same `number`, `column`, `width` and `height` to the player's thumbnails
|
|
option; the PNG includes a 30px attribution footer, so do not infer cell height
|
|
from the full image height. The integration suite uses `scale: 1`.
|
|
|
|
Run `yarn test:browser:source thumbnail-core.spec.js --workers=1` for native file
|
|
extraction, two generated sheets, real mouse hover, screenshot pixels and URL
|
|
ownership against associated core 3.5.31, published 5.4.0 and the candidate core.
|
|
`ARTPLAYER_THUMBNAIL_ARTIFACT` selects the installed tool main. Historical cores'
|
|
first-cell/row-boundary defects have explicit expectations; the candidate must
|
|
use the correct cell. The old tool uses its original 300ms delay, while the
|
|
candidate still exercises 20ms. Recovered 3.5.31 at 20ms produced black cells in
|
|
Firefox because it draws after a timer without awaiting seek completion.
|
|
|
|
Windows WebKit Blob controls do not validate extraction. See the
|
|
[combination checkpoint](../../refactor/changes/2026-09-16-PKG-TOOL-THUMB-05-core-combinations.md)
|
|
for exact passing scopes and remaining Safari/device/archive evidence.
|
|
|
|
## Type and provenance boundaries
|
|
|
|
All nine executable source modules and the shared type module are checked with
|
|
strict, noUncheckedIndexedAccess, noImplicitOverride, skipLibCheck=false and no
|
|
ambient Node/test globals. Public fields use declare so TypeScript does not add
|
|
early undefined properties or change constructor property order. File/URL/density
|
|
fields retain their absence until the corresponding operation publishes them.
|
|
Unknown option fields remain unknown. Custom string/number/symbol events infer
|
|
caller-defined callback tuples; built-in events have precise tuples. Their
|
|
heterogeneous registry erases tuple types at storage and applies a local assertion
|
|
when dispatching. Public and source constructors are checked in both directions.
|
|
Error payloads remain unknown because callbacks can throw arbitrary message
|
|
values. This does not change runtime error delivery.
|
|
|
|
Assertions are limited to existing runtime boundaries: a temporary empty option
|
|
object before setup validation; the input/wrapper conversion; event target and
|
|
dataTransfer/files supplied by native input/drop events; private records inserted
|
|
before lookup; nonempty/dense frame arrays; a successful 2D canvas context; and
|
|
the old property read of message on arbitrary thrown values. These assertions
|
|
preserve existing runtime validation/errors rather than adding new coercions.
|
|
The constructor and destroy rollback paths also intentionally tolerate fields
|
|
that have not yet been assigned. DOM listener casts connect known event names to
|
|
the matching bound callbacks. Keep new assertions equally local and documented.
|
|
|
|
The emitter structurally corresponds to tiny-emitter 2.1.0, which the recovered
|
|
3.5.31 manifest declared as ^2.1.0. The exact original copied revision is unknown.
|
|
The pinned [reference files](../../refactor/baselines/thumbnail-vendor/sources.json)
|
|
and [MIT notice](THIRD_PARTY_NOTICES) retain upstream attribution. The repository
|
|
build includes the complete notice in main, legacy and ESM bundle headers.
|
|
Current packed contents include the complete notice and no implementation source;
|
|
new release candidates must repeat the installed check. Do not replace this local
|
|
emitter with the core emitter as part of a type-only change: dispatch semantics
|
|
need their own behavior review. The subsequent emitter fix checks only own
|
|
registry keys, defines new slots as ordinary enumerable/writable/configurable
|
|
data properties and leaves the registry prototype unchanged. Inherited getters
|
|
and setters cannot intercept event registration or dispatch. Each once wrapper
|
|
is consumed before removal/invocation so nested snapshots cannot invoke it twice,
|
|
including after a callback throws. New registrations of the same callback remain
|
|
independent. Normal snapshot order and off(originalCallback) are preserved.
|
|
|
|
`test/thumbnail-runtime.test.js` compares upstream, recovered/historical bundles
|
|
and the selected candidate for dispatch behavior, and checks candidate public
|
|
descriptors and validation. `test/thumbnail-vendor.test.js` verifies fixed source
|
|
bytes, complete notices and dist/docs equality. `test/types/thumbnail-runtime.ts`
|
|
checks source consumers with positive cases and six rejected invalid uses.
|
|
`test/thumbnail-emitter.test.js` reproduces the old key-collision/nested-once
|
|
failures and checks the candidate; `test/browser/thumbnail-emitter.spec.js` repeats
|
|
the behavior with the real browser class and native DOM cleanup.
|