From d017f435731ce7742f896268963ac1009b190bd5 Mon Sep 17 00:00:00 2001 From: roymondchen Date: Mon, 19 Oct 2026 17:08:02 +0800 Subject: [PATCH] =?UTF-8?q?fix(stage):=20iframe=20=E6=9C=AA=E5=B0=B1?= =?UTF-8?q?=E7=BB=AA=E6=97=B6=E8=B7=B3=E8=BF=87=E6=B3=A8=E5=85=A5=20magic?= =?UTF-8?q?=EF=BC=8C=E9=81=BF=E5=85=8D=20contentWindow=20=E4=B8=BA?= =?UTF-8?q?=E7=A9=BA=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/stage/src/StageRender.ts | 5 ++++- packages/stage/tests/unit/StageRender.spec.ts | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/stage/src/StageRender.ts b/packages/stage/src/StageRender.ts index 92fa06e5..9b24abad 100644 --- a/packages/stage/src/StageRender.ts +++ b/packages/stage/src/StageRender.ts @@ -194,7 +194,10 @@ export default class StageRender extends EventEmitter { } public postTmagicRuntimeReady() { - this.contentWindow = this.iframe?.contentWindow as RuntimeWindow; + this.contentWindow = (this.iframe?.contentWindow as RuntimeWindow | null) ?? null; + + // iframe 尚未就绪时 contentWindow 为空,等 load 后再注入 magic + if (!this.contentWindow) return; this.contentWindow.magic = this.getMagicApi(); diff --git a/packages/stage/tests/unit/StageRender.spec.ts b/packages/stage/tests/unit/StageRender.spec.ts index 722702ee..2a31e4bd 100644 --- a/packages/stage/tests/unit/StageRender.spec.ts +++ b/packages/stage/tests/unit/StageRender.spec.ts @@ -154,6 +154,24 @@ describe('StageRender - NATIVE', () => { renderer.destroy(); }); + test('contentWindow 未就绪时 mount 不抛错,就绪后注入 magic', async () => { + const host = globalThis.document.createElement('div'); + globalThis.document.body.appendChild(host); + const renderer = new StageRender({ renderType: RenderType.IFRAME, runtimeUrl: '' }); + await expect(renderer.mount(host)).resolves.toBeUndefined(); + expect(renderer.contentWindow).toBeNull(); + + const postMessage = vi.fn(); + Object.defineProperty(renderer.iframe!, 'contentWindow', { + configurable: true, + value: { postMessage, document: globalThis.document }, + }); + renderer.postTmagicRuntimeReady(); + expect(postMessage).toHaveBeenCalledWith({ tmagicRuntimeReady: true }, '*'); + expect(renderer.contentWindow?.magic).toBeDefined(); + renderer.destroy(); + }); + test('IFRAME getElementsFromPoint 考虑 iframe 偏移', async () => { const host = globalThis.document.createElement('div'); globalThis.document.body.appendChild(host);