You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ag...@apache.org on 2014/11/25 19:41:42 UTC
[1/2] js commit: CB-8002 CB-7735 ios: Properly address iframe bridge
failing when
Repository: cordova-js
Updated Branches:
refs/heads/master 5f4848f64 -> 227d83a12
CB-8002 CB-7735 ios: Properly address iframe bridge failing when <iframe> is removed from DOM.
Project: http://git-wip-us.apache.org/repos/asf/cordova-js/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-js/commit/227d83a1
Tree: http://git-wip-us.apache.org/repos/asf/cordova-js/tree/227d83a1
Diff: http://git-wip-us.apache.org/repos/asf/cordova-js/diff/227d83a1
Branch: refs/heads/master
Commit: 227d83a122733fdf0300ffe75507a221bcef2b06
Parents: d638080
Author: Andrew Grieve <ag...@chromium.org>
Authored: Tue Nov 25 13:39:47 2014 -0500
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Tue Nov 25 13:40:46 2014 -0500
----------------------------------------------------------------------
src/ios/exec.js | 105 +++++++++++++++++++++++++--------------------------
1 file changed, 51 insertions(+), 54 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-js/blob/227d83a1/src/ios/exec.js
----------------------------------------------------------------------
diff --git a/src/ios/exec.js b/src/ios/exec.js
index 5c7cc98..9e2e2e4 100644
--- a/src/ios/exec.js
+++ b/src/ios/exec.js
@@ -33,14 +33,13 @@ var cordova = require('cordova'),
// IFRAME_NAV is the fastest.
// IFRAME_HASH could be made to enable synchronous bridge calls if we wanted this feature.
jsToNativeModes = {
- IFRAME_NAV: 0,
- XHR_NO_PAYLOAD: 1,
- XHR_WITH_PAYLOAD: 2,
- XHR_OPTIONAL_PAYLOAD: 3,
- IFRAME_HASH_NO_PAYLOAD: 4,
- // Bundling the payload turns out to be slower. Probably since it has to be URI encoded / decoded.
- IFRAME_HASH_WITH_PAYLOAD: 5,
- WK_WEBVIEW_BINDING: 6
+ IFRAME_NAV: 0, // Default. Uses a new iframe for each poke.
+ XHR_NO_PAYLOAD: 1, // About the same speed as IFRAME_NAV. Performance not about the same as IFRAME_NAV, but more variable.
+ XHR_WITH_PAYLOAD: 2, // Flakey, and not as performant
+ XHR_OPTIONAL_PAYLOAD: 3, // Flakey, and not as performant
+ IFRAME_HASH_NO_PAYLOAD: 4, // Not fully baked. A bit faster than IFRAME_NAV, but risks jank since poke happens synchronously.
+ IFRAME_HASH_WITH_PAYLOAD: 5, // Slower than no payload. Maybe since it has to be URI encoded / decoded.
+ WK_WEBVIEW_BINDING: 6 // Only way that works for WKWebView :)
},
bridgeMode,
execIframe,
@@ -50,26 +49,8 @@ var cordova = require('cordova'),
requestCount = 0,
vcHeaderValue = null,
commandQueue = [], // Contains pending JS->Native messages.
- isInContextOfEvalJs = 0;
-
-function createExecIframe(src, unloadListener) {
- var iframe = document.createElement("iframe");
- iframe.style.display = 'none';
- // Both the unload listener and the src must be set before adding the iframe
- // to the document in order to avoid race conditions. Callbacks from native
- // can happen within the appendChild() call!
- iframe.onunload = unloadListener;
- iframe.src = src;
- document.body.appendChild(iframe);
- return iframe;
-}
-
-function createHashIframe() {
- var ret = createExecIframe('about:blank');
- // Hash changes don't work on about:blank, so switch it to file:///.
- ret.contentWindow.history.replaceState(null, null, 'file:///#');
- return ret;
-}
+ isInContextOfEvalJs = 0,
+ failSafeTimerId = 0;
function shouldBundleCommandJson() {
if (bridgeMode === jsToNativeModes.XHR_WITH_PAYLOAD) {
@@ -202,19 +183,23 @@ function iOSExec() {
// Also, if there is already a command in the queue, then we've already
// poked the native side, so there is no reason to do so again.
if (!isInContextOfEvalJs && commandQueue.length == 1) {
- switch (bridgeMode) {
- case jsToNativeModes.XHR_NO_PAYLOAD:
- case jsToNativeModes.XHR_WITH_PAYLOAD:
- case jsToNativeModes.XHR_OPTIONAL_PAYLOAD:
- pokeNativeViaXhr();
- break;
- default: // iframe-based.
- pokeNativeViaIframe();
- }
+ pokeNative();
}
}
}
+function pokeNative() {
+ switch (bridgeMode) {
+ case jsToNativeModes.XHR_NO_PAYLOAD:
+ case jsToNativeModes.XHR_WITH_PAYLOAD:
+ case jsToNativeModes.XHR_OPTIONAL_PAYLOAD:
+ pokeNativeViaXhr();
+ break;
+ default: // iframe-based.
+ pokeNativeViaIframe();
+ }
+}
+
function pokeNativeViaXhr() {
// This prevents sending an XHR when there is already one being sent.
// This should happen only in rare circumstances (refer to unit tests).
@@ -238,11 +223,6 @@ function pokeNativeViaXhr() {
execXhr.send(null);
}
-function onIframeUnload() {
- execIframe = null;
- setTimeout(pokeNativeViaIframe, 0);
-}
-
function pokeNativeViaIframe() {
// CB-5488 - Don't attempt to create iframe before document.body is available.
if (!document.body) {
@@ -251,10 +231,12 @@ function pokeNativeViaIframe() {
}
if (bridgeMode === jsToNativeModes.IFRAME_HASH_NO_PAYLOAD || bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) {
// TODO: This bridge mode doesn't properly support being removed from the DOM (CB-7735)
- execHashIframe = execHashIframe || createHashIframe();
- // Check if they've removed it from the DOM, and put it back if so.
- if (!execHashIframe.contentWindow) {
- execHashIframe = createHashIframe();
+ if (!execHashIframe) {
+ execHashIframe = document.createElement('iframe');
+ execHashIframe.style.display = 'none';
+ document.body.appendChild(execHashIframe);
+ // Hash changes don't work on about:blank, so switch it to file:///.
+ execHashIframe.contentWindow.history.replaceState(null, null, 'file:///#');
}
// The delegate method is called only when the hash changes, so toggle it back and forth.
hashToggle = hashToggle ^ 3;
@@ -266,13 +248,25 @@ function pokeNativeViaIframe() {
} else {
// Check if they've removed it from the DOM, and put it back if so.
if (execIframe && execIframe.contentWindow) {
- // Listen for unload, since it can happen (CB-7735) that the iframe gets
- // removed from the DOM before it gets a chance to poke the native side.
- execIframe.contentWindow.onunload = onIframeUnload;
- execIframe.src = 'gap://ready';
+ execIframe.contentWindow.location = 'gap://ready';
} else {
- execIframe = createExecIframe('gap://ready', onIframeUnload);
+ execIframe = document.createElement('iframe');
+ execIframe.style.display = 'none';
+ execIframe.src = 'gap://ready';
+ document.body.appendChild(execIframe);
}
+ // Use a timer to protect against iframe being unloaded during the poke (CB-7735).
+ // This makes the bridge ~ 7% slower, but works around the poke getting lost
+ // when the iframe is removed from the DOM.
+ // An onunload listener could be used in the case where the iframe has just been
+ // created, but since unload events fire only once, it doesn't work in the normal
+ // case of iframe reuse (where unload will have already fired due to the attempted
+ // navigation of the page).
+ failSafeTimerId = setTimeout(function() {
+ if (commandQueue.length) {
+ pokeNative();
+ }
+ }, 50); // Making this > 0 improves performance (marginally) in the normal case (where it doesn't fire).
}
}
@@ -283,7 +277,9 @@ iOSExec.setJsToNativeBridgeMode = function(mode) {
// can trigger browser bugs.
// https://issues.apache.org/jira/browse/CB-593
if (execIframe) {
- execIframe.parentNode.removeChild(execIframe);
+ if (execIframe.parentNode) {
+ execIframe.parentNode.removeChild(execIframe);
+ }
execIframe = null;
}
bridgeMode = mode;
@@ -291,8 +287,9 @@ iOSExec.setJsToNativeBridgeMode = function(mode) {
iOSExec.nativeFetchMessages = function() {
// Stop listing for window detatch once native side confirms poke.
- if (execIframe && execIframe.contentWindow) {
- execIframe.contentWindow.onunload = null;
+ if (failSafeTimerId) {
+ clearTimeout(failSafeTimerId);
+ failSafeTimerId = 0;
}
// Each entry in commandQueue is a JSON string already.
if (!commandQueue.length) {
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org
[2/2] js commit: Fix whitespace to unbreak grunt
Posted by ag...@apache.org.
Fix whitespace to unbreak grunt
Project: http://git-wip-us.apache.org/repos/asf/cordova-js/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-js/commit/d6380809
Tree: http://git-wip-us.apache.org/repos/asf/cordova-js/tree/d6380809
Diff: http://git-wip-us.apache.org/repos/asf/cordova-js/diff/d6380809
Branch: refs/heads/master
Commit: d63808092b27227016b2fce63e47106446ea161f
Parents: 5f4848f
Author: Andrew Grieve <ag...@chromium.org>
Authored: Tue Nov 25 13:37:06 2014 -0500
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Tue Nov 25 13:40:46 2014 -0500
----------------------------------------------------------------------
src/common/init.js | 2 +-
src/common/init_b.js | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-js/blob/d6380809/src/common/init.js
----------------------------------------------------------------------
diff --git a/src/common/init.js b/src/common/init.js
index 46cca2e..4ae0dfd 100644
--- a/src/common/init.js
+++ b/src/common/init.js
@@ -56,7 +56,7 @@ function replaceNavigator(origNavigator) {
for (var key in origNavigator) {
if (typeof origNavigator[key] == 'function') {
newNavigator[key] = origNavigator[key].bind(origNavigator);
- }
+ }
else {
(function(k) {
utils.defineGetterSetter(newNavigator,key,function() {
http://git-wip-us.apache.org/repos/asf/cordova-js/blob/d6380809/src/common/init_b.js
----------------------------------------------------------------------
diff --git a/src/common/init_b.js b/src/common/init_b.js
index 207cc3c..bce769b 100644
--- a/src/common/init_b.js
+++ b/src/common/init_b.js
@@ -57,7 +57,7 @@ function replaceNavigator(origNavigator) {
for (var key in origNavigator) {
if (typeof origNavigator[key] == 'function') {
newNavigator[key] = origNavigator[key].bind(origNavigator);
- }
+ }
else {
(function(k) {
utils.defineGetterSetter(newNavigator,key,function() {
@@ -112,7 +112,7 @@ platform.bootstrap && platform.bootstrap();
* Create all cordova objects once native side is ready.
*/
channel.join(function() {
-
+
platform.initialize && platform.initialize();
// Fire event to notify that all objects are created
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org