refactor(iframe): [PKG-IFRAME-03] scope requests to active documents

This commit is contained in:
Harvey Zhao committed 2026-09-13 01:07:37 +08:00
1 parent b8cdafedd1
commit 1342de94ef
27 files changed
+10860 -69

No files matched your search

+34 -5
View File
@@ -20,11 +20,24 @@ interface Pending {
id?: number
timer?: ReturnType<typeof setTimeout>
callbacks: Callbacks
cancel: (reason: unknown) => void
}
const requests = new WeakMap<RequestHost, Set<Pending>>()
interface RequestBoundary {
prepare: () => void
envelope: (packet: Packet) => Packet
}
const boundaries = new WeakMap<RequestHost, RequestBoundary>()
let lastId = 0
export function setRequestBoundary(host: RequestHost, boundary: RequestBoundary | undefined): void {
if (boundary)
boundaries.set(host, boundary)
else
boundaries.delete(host)
}
export function postRequest(host: RequestHost, { type, data }: Packet): Promise<any> {
return new Promise((resolve, reject) => {
if (host.destroyed) {
@@ -55,6 +68,10 @@ export function postRequest(host: RequestHost, { type, data }: Packet): Promise<
reject(error)
},
},
cancel(error) {
if (finish(request))
reject(error)
},
}
pending.add(request)
const loop = () => {
@@ -62,33 +79,45 @@ export function postRequest(host: RequestHost, { type, data }: Packet): Promise<
if (!pending.has(request))
return
if (host.destroyed) {
request.callbacks.reject(new Error('The instance has been destroyed'))
request.cancel(new Error('The instance has been destroyed'))
return
}
try {
boundaries.get(host)?.prepare()
if (!pending.has(request))
return
if (host.injected) {
const id = Math.max(Date.now(), lastId + 1)
lastId = id
request.id = id
host.promises[id] = request.callbacks
host.$iframe.contentWindow!.postMessage({ type, data, id }, '*')
const packet = { type, data, id }
host.$iframe.contentWindow!.postMessage(boundaries.get(host)?.envelope(packet) || packet, '*')
}
else {
request.timer = setTimeout(loop, 200)
}
}
catch (error) {
request.callbacks.reject(error)
request.cancel(error)
}
}
loop()
})
}
export function cancelRequests(host: RequestHost): void {
export function cancelRequests(host: RequestHost, reason = new Error('The instance has been destroyed')): void {
const pending = requests.get(host)
if (!pending)
return
for (const request of [...pending])
request.callbacks.reject(new Error('The instance has been destroyed'))
request.cancel(reason)
}
export function captureRequests(host: RequestHost): (reason: unknown) => void {
const captured = [...(requests.get(host) || [])]
return (reason) => {
for (const request of captured)
request.cancel(reason)
}
}