From 72b0f0f14ff5b81e498159a39b2d570501f7990f Mon Sep 17 00:00:00 2001 From: tuncaulubilge Date: Mon, 24 Sep 2018 14:09:47 +0100 Subject: [PATCH 1/2] Enqueue window post messages until it's ready --- .../utils/webview-event-callback-setup.js | 56 +++++-------------- .../src/utils/webview-event-callback-setup.js | 46 +++++++++++---- 2 files changed, 48 insertions(+), 54 deletions(-) diff --git a/packages/ad/__tests__/utils/webview-event-callback-setup.js b/packages/ad/__tests__/utils/webview-event-callback-setup.js index 7f026bdb5e9..6c293f4c1c5 100644 --- a/packages/ad/__tests__/utils/webview-event-callback-setup.js +++ b/packages/ad/__tests__/utils/webview-event-callback-setup.js @@ -10,9 +10,10 @@ export default () => { beforeEach(() => { jest.useFakeTimers(); window = { - reactBridgePostMessage: jest.fn().mockImplementation((data, origin) => { - window.reactBridgePostMessageDecoded(JSON.parse(data), origin); + postMessage: jest.fn().mockImplementation(data => { + window.reactBridgePostMessageDecoded(JSON.parse(data)); }), + originalPostMessage: {}, reactBridgePostMessageDecoded: jest.fn(), requestAnimationFrame: realWindow.requestAnimationFrame, setTimeout: realWindow.setTimeout, @@ -43,31 +44,6 @@ export default () => { expect(window.eventCallback).toEqual(expect.any(Function)); }); - it("posts a delayed message to the parent when the event callback is called", () => { - webviewEventCallbackSetup({ window }); - window.eventCallback("TYPE", "DETAIL"); - expect(window.reactBridgePostMessageDecoded).not.toHaveBeenCalled(); - jest.runAllTimers(); - expect(window.reactBridgePostMessageDecoded).toHaveBeenCalledWith( - { - isTngMessage: true, - type: "TYPE", - detail: "DETAIL" - }, - "*" - ); - }); - - it("preferrs reactBridgePostMessage if available", () => { - webviewEventCallbackSetup({ window }); - window.postMessage = jest.fn(); - window.reactBridgePostMessage = jest.fn(); - window.eventCallback("TYPE", "DETAIL"); - jest.runAllTimers(); - expect(window.postMessage).toHaveBeenCalledTimes(0); - expect(window.reactBridgePostMessage).toHaveBeenCalledTimes(1); - }); - it("falls abck to postMessage if reactBridgePostMessage if not available", () => { webviewEventCallbackSetup({ window }); window.postMessage = jest.fn(); @@ -81,14 +57,11 @@ export default () => { webviewEventCallbackSetup({ window }); errorHandler(error); jest.runAllTimers(); - expect(window.reactBridgePostMessageDecoded).toHaveBeenCalledWith( - { - isTngMessage: true, - type: "error", - detail: messageDetail - }, - "*" - ); + expect(window.reactBridgePostMessageDecoded).toHaveBeenCalledWith({ + isTngMessage: true, + type: "error", + detail: messageDetail + }); }; it("posts a message to the parent when the global error handler is called", () => { @@ -127,13 +100,10 @@ export default () => { webviewEventCallbackSetup({ window }); window.console.error("a", "b", "c"); jest.runAllTimers(); - expect(window.reactBridgePostMessageDecoded).toHaveBeenCalledWith( - { - isTngMessage: true, - type: "error", - detail: "a\nb\nc" - }, - "*" - ); + expect(window.reactBridgePostMessageDecoded).toHaveBeenCalledWith({ + isTngMessage: true, + type: "error", + detail: "a\nb\nc" + }); }); }; diff --git a/packages/ad/src/utils/webview-event-callback-setup.js b/packages/ad/src/utils/webview-event-callback-setup.js index b75a7e1adac..67a1adf9473 100644 --- a/packages/ad/src/utils/webview-event-callback-setup.js +++ b/packages/ad/src/utils/webview-event-callback-setup.js @@ -5,19 +5,43 @@ const webviewEventCallbackSetup = options => { const { window } = options; + + // Enqueue window messages until it's ready - See https://github.com/facebook/react-native/issues/11594#issuecomment-274689549 for details + let isReactNativePostMessageReady = !!window.originalPostMessage; + const queue = []; + let currentPostMessageFn = function store(message) { + if (queue.length > 100) queue.shift(); + queue.push(message); + }; + + const sendQueue = () => { + while (queue.length > 0) window.postMessage(queue.shift()); + }; + + if (!isReactNativePostMessageReady) { + Object.defineProperty(window, "postMessage", { + configurable: true, + enumerable: true, + get() { + return currentPostMessageFn; + }, + set(fn) { + currentPostMessageFn = fn; + isReactNativePostMessageReady = true; + window.setTimeout(sendQueue, 0); + } + }); + } + window.eventCallback = (type, detail) => { // delay until next frame as React Native message bridge is not set up immediately - window.setTimeout(() => { - const method = window.reactBridgePostMessage || window.postMessage; - method( - JSON.stringify({ - isTngMessage: true, - type, - detail - }), - "*" - ); - }, 300); + window.postMessage( + JSON.stringify({ + isTngMessage: true, + type, + detail + }) + ); }; window.addEventListener("error", ev => { const file = (ev.filename || "").substring(0, 100); From 9d519612935cafe5822365b2d344f175b9e79dc0 Mon Sep 17 00:00:00 2001 From: tuncaulubilge Date: Tue, 25 Sep 2018 10:27:04 +0100 Subject: [PATCH 2/2] Remove comment --- packages/ad/src/utils/webview-event-callback-setup.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ad/src/utils/webview-event-callback-setup.js b/packages/ad/src/utils/webview-event-callback-setup.js index 67a1adf9473..2eb96c3439a 100644 --- a/packages/ad/src/utils/webview-event-callback-setup.js +++ b/packages/ad/src/utils/webview-event-callback-setup.js @@ -34,7 +34,6 @@ const webviewEventCallbackSetup = options => { } window.eventCallback = (type, detail) => { - // delay until next frame as React Native message bridge is not set up immediately window.postMessage( JSON.stringify({ isTngMessage: true,