fix(iframe): [PKG-IFRAME-03] release failed setup and bind message peers

This commit is contained in:
Harvey Zhao committed 2026-09-13 00:03:37 +08:00
1 parent b8d03e7366
commit b8cdafedd1
23 files changed
+7940 -32

No files matched your search

@@ -0,0 +1,28 @@
import type { Packet, RequestHost } from './requests'
import { cancelRequests } from './requests'
interface ConnectionHost extends RequestHost {
url: string
onMessage: (event: MessageEvent<Packet>) => void
}
const connections = new WeakMap<ConnectionHost, () => void>()
export function connect(host: ConnectionHost): void {
const owner = window
const receiver = host.onMessage
connections.set(host, () => owner.removeEventListener('message', receiver))
owner.addEventListener('message', receiver)
host.$iframe.src = host.url
}
export function releaseConnection(host: ConnectionHost): void {
const disconnect = connections.get(host)
connections.delete(host)
try {
disconnect?.()
}
finally {
cancelRequests(host)
}
}
+21 -6
View File
@@ -1,5 +1,7 @@
import type { Callbacks, Packet } from './requests'
import { cancelRequests, postRequest } from './requests'
import { connect, releaseConnection } from './connection'
import { acceptsMessage } from './protocol'
import { postRequest } from './requests'
export default class ArtplayerToolIframe {
declare url: string
@@ -33,6 +35,9 @@ export default class ArtplayerToolIframe {
throw new Error('The "ArtplayerToolIframe.onMessage" method can only be used in iframe')
}
if (!acceptsMessage(event, window.parent))
return
const { type, data, id } = event.data
switch (type) {
case 'commit':
@@ -84,12 +89,23 @@ export default class ArtplayerToolIframe {
this.destroyed = false
this.messageCallback = () => null
this.onMessage = this.onMessage.bind(this)
window.addEventListener('message', this.onMessage)
this.$iframe.src = this.url
try {
connect(this)
}
catch (error) {
this.destroyed = true
try {
releaseConnection(this)
}
catch {
// Preserve the original setup failure if cleanup also fails.
}
throw error
}
}
onMessage(event: MessageEvent<Packet>) {
if (this.destroyed)
if (this.destroyed || !acceptsMessage(event, this.$iframe.contentWindow))
return
const { type, data, id } = event.data
@@ -139,7 +155,6 @@ export default class ArtplayerToolIframe {
destroy() {
this.destroyed = true
window.removeEventListener('message', this.onMessage)
cancelRequests(this)
releaseConnection(this)
}
}
@@ -0,0 +1,8 @@
import type { Packet } from './requests'
export function acceptsMessage(event: MessageEvent<unknown>, peer: Window | null): event is MessageEvent<Packet> {
if (event.source !== undefined && event.source !== null && event.source !== peer)
return false
const data = event.data
return typeof data === 'object' && data !== null && 'type' in data && typeof data.type === 'string'
}