mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-10 12:46:15 -08:00
240 lines
16 KiB
Markdown
240 lines
16 KiB
Markdown
# Iframe maintenance map
|
|
|
|
Package-name rollback must restore the application imports and saved dependency
|
|
lock together. The old plugin package exposes a CommonJS namespace with `.default`
|
|
and distinct helper files; installing its tarball under the current tool dependency
|
|
key does not preserve the current constructor or `/legacy` imports. The isolated
|
|
build/install/type rehearsal is `yarn test:rollback:iframe`; see
|
|
[rollback maintenance](../../refactor/rollback-rehearsal.md). This does not replace
|
|
the package's cross-window, playback or device acceptance.
|
|
|
|
`src/index.ts` owns the existing class, constructor validation, bound parent
|
|
message listener, child injection/execution protocol and public callbacks.
|
|
`src/requests.ts` owns request IDs, pending promises, injection polling and
|
|
settlement/cancellation. Its host interface uses only the iframe, registry and
|
|
two lifecycle flags; it does not depend on ArtPlayer or import the entry class.
|
|
`src/connection.ts` owns listener acquisition/release and ensures request
|
|
cancellation runs even if listener removal throws. `src/protocol.ts` checks the
|
|
selected window peer and packet shape before either public receiver processes it.
|
|
`src/navigation.ts` owns parent document state, source observation and suspended
|
|
request snapshots. `src/child-session.ts` owns the child document marker and its
|
|
acknowledged pagehide/pageshow/hashchange notifications. Requests accept an
|
|
internal boundary hook rather than importing the connection or navigation modules;
|
|
there is no runtime dependency cycle or dependency on a particular core version.
|
|
|
|
The entry initializes the same seven enumerable, writable fields in the same
|
|
order. Internal request ownership lives in a module WeakMap, keeping instance
|
|
reflection unchanged. `promises` remains the same ordinary object, exposing the
|
|
historical `resove` spelling and `reject`. Do not rename `resove` or replace this
|
|
public object with a Map. The wire envelope remains `{ type, data, id }`, with
|
|
numeric IDs and wildcard target origin. Non-error responses with a matching ID
|
|
are still accepted; `message` receives `{ type, data }` with the instance as `this`.
|
|
|
|
## Request lifecycle
|
|
|
|
Every call owns its promise immediately. Before injection it polls every 200ms,
|
|
as before; injection does not flush the queue synchronously. On send it allocates
|
|
a numeric ID from the greater of the current timestamp and the previous ID + 1.
|
|
The counter is shared by instances in this module so two instances pointing at
|
|
one child do not settle each other's requests. It also avoids reuse after clock
|
|
rollback. Independently loaded copies of the library do not share this counter.
|
|
|
|
The request is recorded before native postMessage. Success, remote error, native
|
|
send failure or an explicit public callback settle once and remove ownership,
|
|
timer and registry entry. Native failures retain their original Error object,
|
|
including failures reached from polling. `destroy()` first marks the instance
|
|
destroyed, removes its listener, then immediately rejects both sent and waiting
|
|
requests with `The instance has been destroyed`. Saved listener/timer callbacks
|
|
become inert. Repeated destroy is harmless. There is no implicit request timeout.
|
|
If constructor setup fails, it marks the partial instance destroyed, releases
|
|
the acquired listener and cancels reentrant requests, preserving the original
|
|
setup error even if cleanup also fails. The listener receiver and owning window
|
|
are captured on acquisition; connection ownership is removed before releasing it.
|
|
|
|
These are deliberate defect corrections: callers holding a promise during
|
|
destroy must handle rejection; previously sent requests remained pending forever.
|
|
The public ID is a correlation number, and is no longer always equal to Date.now.
|
|
Public callback invocation now removes its completed registry entry immediately.
|
|
The own-property guard prevents inherited names such as `toString` being treated
|
|
as requests. These differences are recorded under PKG-IFRAME-03.
|
|
Internal cancellation holds the native rejection separately from public callback
|
|
properties. Replacing/deleting a public entry does not make its owned Promise
|
|
unreachable during destroy or document departure; ordinary response dispatch
|
|
continues to respect the public callbacks.
|
|
|
|
## Document ownership
|
|
|
|
New inject packets advertise optional `__artplayerIframe` metadata. A cooperating
|
|
parent acknowledges it through tagged `artplayer-tool-iframe:session` traffic;
|
|
the public message callback still receives only its original type/data packet.
|
|
Ordinary child messages stay unmarked when the parent has not acknowledged the
|
|
extension. The document ID correlates work and is not an authentication token.
|
|
See [ADR-026](../../refactor/iframe-document-protocol.md) for the complete wire boundary.
|
|
|
|
Parent source attribute changes begin a provisional navigation: capture the old
|
|
pending set and pause new sends. Confirmed pagehide or a different document's
|
|
inject cancels the captured set, preserving work queued for the new document.
|
|
A hashchange report matching the actual target src completes a same-document
|
|
transition without cancellation. This also handles relative/absolute src spelling
|
|
and setting an old fragment after the child changed its own hash. Raw attribute
|
|
tracking prevents a changed base URL resolution alone from inventing navigation.
|
|
|
|
Repeated inject for the active document keeps requests; an old inject cannot
|
|
reactivate a document while its replacement is pending. Marked replies and
|
|
notifications from other documents are discarded; marked old commands are not
|
|
executed by a new child. No load-event reset is used, so inject-before-load works.
|
|
Connection cleanup disposes the observer and request hook, then cancels all owned
|
|
requests. Child listeners belong to the child document, are installed once, and
|
|
are rolled back on partial acquisition failure. A destroyed parent ignores late
|
|
private notifications. The existing API adds no static child destroy method.
|
|
|
|
## Compatibility still under review
|
|
|
|
Child `commit` still extracts the function body and evaluates it with the old
|
|
`resolve(...)` convention. Simple commits post a response synchronously inside
|
|
the async handler; resolver commits await the result. Execution errors still
|
|
send an error packet and reject the handler. Expression arrow functions, closure
|
|
capture and CSP restrictions have not been replaced with a new RPC protocol.
|
|
|
|
Both receivers ignore malformed payloads (a non-null object with a string `type`
|
|
is required, including an empty string). The parent accepts native messages only
|
|
from the configured iframe's contentWindow; the child accepts them only from
|
|
window.parent. Public direct onMessage calls with a missing/null source remain
|
|
available to local callers. Same-page script or privileged injection is not
|
|
isolated by this check. Generic response types and commit payload error handling
|
|
are unchanged after the peer/envelope check.
|
|
|
|
The initial URL's origin is deliberately not pinned: redirects and sandboxed
|
|
opaque-origin children still communicate with their selected parent. The peer's
|
|
content and the embedding parent must be trusted; executable commit is not a
|
|
sandbox or a parent-origin allowlist. Upgrading one side does not secure the
|
|
unchanged historical receiver on the other side. See the independent decision in
|
|
[iframe-message-boundary.md](../../refactor/iframe-message-boundary.md).
|
|
|
|
Legacy peers keep the ordinary envelope and support observed changes to different
|
|
source addresses; their same-address reloads/internal navigation cannot provide
|
|
document identity without upgrading the child. No claim is made that a normal
|
|
history reload is BFCache: actual persisted restoration, full-player integration,
|
|
devices and externally interrupted navigation remain PKG-IFRAME-05/release gates.
|
|
IFRAME-LIFE-01 and IFRAME-TRUST-01 remain open for those integration/review scopes.
|
|
|
|
Public declarations are maintained in `types/artplayer-tool-iframe.d.ts`.
|
|
The `.d.cts` bridge describes the actual CommonJS constructor and its named types;
|
|
`.d.mts` routes native ESM to the same class. Keep the root `types` field and
|
|
legacy `typesVersions` entry for TS 4.3 consumers. The runtime has no self-default
|
|
property. Ordinary default imports use interop in CommonJS consumers; modern
|
|
TypeScript can use direct `import Iframe = require(...)` without interop.
|
|
|
|
The default class intentionally retains required Message.data, void static
|
|
onMessage, readonly instance fields, non-null callback and legacy commit inference.
|
|
RuntimeConstructor/RuntimeInstance expose optional outgoing data, async static
|
|
receiver, nullable callback and application-supplied response types. ResolverInstance
|
|
offers an explicit result parameter for the old serialized resolve(...) protocol.
|
|
These are erased type views, not new runtime methods or payload validators. The
|
|
source class satisfies RuntimeConstructor; its nullable callback intentionally
|
|
does not satisfy the old non-null class declaration, and tests pin that difference.
|
|
|
|
Old npm plugin-iframe used Function callbacks and a CommonJS default namespace;
|
|
those differ from the frozen workspace before this refactor. Installed tests
|
|
preserve that evidence and the separate helper's static destroy protocol. They
|
|
do not claim the renamed tool supplies the old package name or helper entrypoints.
|
|
PKG-IFRAME-06 still owns those distribution decisions and compatibility facades.
|
|
No version bump or publication is implied by declaration validation.
|
|
|
|
## Verification
|
|
|
|
- `yarn test:iframe`: frozen historical contract/defect assertions and candidate
|
|
lifecycle assertions. Historical failures are not candidate acceptance.
|
|
- `yarn typecheck`: strict source and existing consumers, including old extraction
|
|
and new typed views in TS 5.9 and TS 4.3.
|
|
- `yarn test:iframe-types-package`: install the real old npm archive, frozen
|
|
workspace pack and candidate outside the workspace with offline/frozen Yarn.
|
|
Check declaration resolution, exact bytes, exports and positive/negative uses.
|
|
- `yarn build:ts artplayer-tool-iframe`: regenerate only this package's standalone
|
|
editor declaration (plus the shared core declaration). The generator uses the
|
|
actual uppercase class global and exports named types without external imports.
|
|
- `yarn build artplayer-tool-iframe`: normal main/legacy/ESM production output and
|
|
generated docs copies. Never hand-edit those files.
|
|
- `yarn test:browser test/browser/iframe.spec.js`: real same/cross-origin windows
|
|
in Chromium, Firefox and WebKit. This tool-only fixture creates no player.
|
|
- `yarn test:browser test/browser/iframe-boundaries.spec.js`: native peer rejection,
|
|
malformed packets, actual HTTP redirects, opaque sandbox and normal new/old
|
|
parent-child wire combinations. `ARTPLAYER_IFRAME_BOUNDARIES_ONLY=1` omits the
|
|
mixed-version controls when reproducing a candidate boundary failure.
|
|
- `yarn test:browser test/browser/iframe-navigation.spec.js`: source/srcdoc, rapid
|
|
navigation, self-navigation, load ordering, fragment identity, stale packets,
|
|
legacy children and history with actual persisted-state reporting. There is no
|
|
implicit request timeout. Handle rejection when a document leaves or is destroyed.
|
|
- Set `ARTPLAYER_IFRAME_LIFECYCLE_ONLY=1` for candidate lifecycle browser rows;
|
|
`ARTPLAYER_IFRAME_ARTIFACT` selects an actual built file. For an unchanged
|
|
candidate test against the old workspace, set `ARTPLAYER_IFRAME_BASELINE=1`.
|
|
Expected historical failures must be archived, not suppressed.
|
|
|
|
The existing local demo remains at
|
|
`http://localhost:8082/?libs=./uncompiled/artplayer-tool-iframe/index.js&example=iframe`.
|
|
`iframe-player.spec.js` runs the real parent example, child HTML and stylesheet
|
|
with core 4.5.9, frozen 5.4.0 and the candidate, all four new/old bridge pairings,
|
|
and same/cross-origin documents. Historical global-name aliases are test-only.
|
|
It exercises actual media playback, seek/rate, source switch, fullscreenWeb
|
|
controls and independent core/tool destruction. Hover the player before clicking
|
|
controls, as a user does; old cores hide their controls during playback.
|
|
|
|
`iframe-editor.spec.js` opens the actual docs index and local Monaco, clicks Run
|
|
repeatedly, and switches from an iframe example to two parent players and then
|
|
an empty example. The editor loads the core before Monaco's AMD loader so the
|
|
UMD core exposes its script global. Before each Run it dispatches the docs-only
|
|
`artplayer:example:cleanup` event, then destroys a snapshot of parent instances.
|
|
The iframe example subscribes once to destroy its tool and remove its frame;
|
|
its initial commit handles cancellation during cleanup. This is an editor
|
|
convention, not automatic DOM-removal behavior or a new player API. Standalone
|
|
integrations remain responsible for calling destroy themselves.
|
|
|
|
`yarn test:iframe-history` runs the separate cacheable HTTP fixture and full
|
|
Chromium channel, removing Playwright's BFCache-disabling default argument. It
|
|
checks actual whole-page restoration through native persisted events, parent/child
|
|
witnesses, media and the real commit protocol. Firefox/WebKit reload controls are
|
|
reported separately and never counted as cached restoration. Do not replace this
|
|
configuration with the default headless shell or simulated lifecycle events.
|
|
|
|
An entire cached page also freezes the parent. If the private leave message did
|
|
not reach it, the original request can remain pending and settle after restoration.
|
|
If leave was delivered, that request remains rejected; a late result cannot change
|
|
its outcome. Resume retains the same document ID and emits no duplicate public
|
|
inject. The test checks actual delivered phases against settlement.
|
|
|
|
The same command tests native stop, HTTP 204 and a truncated document response.
|
|
After a failed navigation, new work still waits for actual injection into the
|
|
target document; it is not sent to the unrelated old document. Navigate the frame
|
|
to a valid source or destroy the tool to finish/cancel that work. There is no
|
|
implicit timeout or automatic fallback to an old source.
|
|
|
|
Physical devices, native Firefox/WebKit cached restoration and final distribution
|
|
remain separate gates. Desktop evidence does not establish the old helper or
|
|
package-name migration. See ADR-026 and the task 05 history checkpoint for the
|
|
exact fixture, automation limitations and source/main/legacy evidence.
|
|
|
|
## Installed browser checks
|
|
|
|
`yarn test:package --browser` includes this tool in the shared installed roster.
|
|
The pack checker verifies the real `artplayer-plugin-iframe@1.0.0` archive and
|
|
the frozen workspace independently. The tool's required dist/type filenames
|
|
come from its verified workspace manifest and files; the old plugin/helper
|
|
names are not silently treated as releases of the tool. Publishing or restoring
|
|
the predecessor package remains a separate distribution decision.
|
|
|
|
The five `test/browser/iframe*.spec.js` files use `iframeBrowserCandidate()` from
|
|
`test/helpers/iframe.js`. With an installed map it must load the verified tool
|
|
UMD, reject an explicit artifact or frozen-workspace override, and record the
|
|
package/file/archive/source identity for each candidate parent and child.
|
|
Without a map the same tests retain their source and historical controls.
|
|
`iframeCandidate()` keeps its existing unit/history semantics: history may
|
|
inherit a core-only map, which does not select a tool build. Do not merge these
|
|
two fixture entrypoints or claim the separate BFCache suite used an installed
|
|
tool when it used a source/explicit tool. Browser scope configuration rejects
|
|
diagnostic flags that would remove historical Iframe rows.
|
|
|
|
The installed tests cover protocol, peer/document boundaries, native navigation,
|
|
old/new player combinations and the real docs editor. They do not replace the
|
|
special `test:iframe-history` browser channel or physical-device evidence. See
|
|
`../../refactor/changes/2026-09-15-CI-01-iframe-installed.md` for measured results.
|