Improved window.postMessage implementation

Summary:
Adds a queue to postMessage so that messages sent close together are not lost.

Setting location="a";location="b" results in only "b" reaching shouldStartLoadWithRequest. Making the second update asynchronous with setTimeout does not fix the issue unless a delay is added.

With this update, postMessage queues "b" until it gets a "message:received" event that confirms "a" has already been processed.

The included test sends two messages from a webview and checks that both are received. It fails against the preexisting code with the first message being dropped.
Closes https://github.com/facebook/react-native/pull/11304

Differential Revision: D5481385

Pulled By: hramos

fbshipit-source-id: 9b6af195eeff8f20c820e2fcdac997c90763e840
This commit is contained in:
Tom Clarkson
2017-07-28 11:32:00 -07:00
committed by Facebook Github Bot
parent bca825ee50
commit 42f7b9e717
4 changed files with 91 additions and 4 deletions

View File

@@ -250,6 +250,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
[event addEntriesFromDictionary: @{
@"data": data,
}];
NSString *source = @"document.dispatchEvent(new MessageEvent('message:received'));";
[_webView stringByEvaluatingJavaScriptFromString:source];
_onMessage(event);
}
@@ -301,10 +306,28 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
}
#endif
NSString *source = [NSString stringWithFormat:
@"window.originalPostMessage = window.postMessage;"
"window.postMessage = function(data) {"
"window.location = '%@://%@?' + encodeURIComponent(String(data));"
"};", RCTJSNavigationScheme, kPostMessageHost
@"(function() {"
"window.originalPostMessage = window.postMessage;"
"var messageQueue = [];"
"var messagePending = false;"
"function processQueue() {"
"if (!messageQueue.length || messagePending) return;"
"messagePending = true;"
"window.location = '%@://%@?' + encodeURIComponent(messageQueue.shift());"
"}"
"window.postMessage = function(data) {"
"messageQueue.push(String(data));"
"processQueue();"
"};"
"document.addEventListener('message:received', function(e) {"
"messagePending = false;"
"processQueue();"
"});"
"})();", RCTJSNavigationScheme, kPostMessageHost
];
[webView stringByEvaluatingJavaScriptFromString:source];
}