You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@cordova.apache.org by "Joel Rubio (JIRA)" <ji...@apache.org> on 2014/04/09 02:11:17 UTC

[jira] [Created] (CB-6423) (iOS) cordova.js: iOSExec() not working after upgrading from Cordova 3.0 to 3.4

Joel Rubio created CB-6423:
------------------------------

             Summary: (iOS) cordova.js: iOSExec() not working after upgrading from Cordova 3.0 to 3.4
                 Key: CB-6423
                 URL: https://issues.apache.org/jira/browse/CB-6423
             Project: Apache Cordova
          Issue Type: Bug
          Components: CordovaJS, iOS
    Affects Versions: 3.4.0
            Reporter: Joel Rubio


Hi there,

I recently upgraded my working PhoneGap app from 3.0 to 3.4. In iOS, the app wouldn't go past the splashscreen. It would get stuck while trying to fetch a local file (in file:/// dir) through an XHR.

I managed to trace the problem to the iOSExec function in cordova.js. Before the upgrade, it would determine bridgeMode the following way:

bridgeMode = navigator.userAgent.indexOf(' 4_') == -1 ? jsToNativeModes.XHR_NO_PAYLOAD : jsToNativeModes.IFRAME_NAV;

In cordova.js 3.4 it is determined the following way:

bridgeMode = navigator.userAgent.indexOf(' 5_') == -1 ? jsToNativeModes.IFRAME_NAV: jsToNativeModes.XHR_NO_PAYLOAD;

Notice the switch in the expressions. 

This led to any iOS device with a version other than 5 not working. Using the jsToNativeModes.IFRAME_NAV bridgeMode would lead to the default case in the subsequent switch statement in which it determines what to do according to the bridgeMode.

switch (bridgeMode) {
        case jsToNativeModes.XHR_NO_PAYLOAD:
        case jsToNativeModes.XHR_WITH_PAYLOAD:
        case jsToNativeModes.XHR_OPTIONAL_PAYLOAD:
            // This prevents sending an XHR when there is already one being sent.
            // This should happen only in rare circumstances (refer to unit tests).
            if (execXhr && execXhr.readyState != 4) {
                execXhr = null;
            }
            // Re-using the XHR improves exec() performance by about 10%.
            execXhr = execXhr || new XMLHttpRequest();
            // Changing this to a GET will make the XHR reach the URIProtocol on 4.2.
            // For some reason it still doesn't work though...
            // Add a timestamp to the query param to prevent caching.
            execXhr.open('HEAD', "/!gap_exec?" + (+new Date()), true);
            if (!vcHeaderValue) {
                vcHeaderValue = /.*\((.*)\)/.exec(navigator.userAgent)[1];
            }
            execXhr.setRequestHeader('vc', vcHeaderValue);
            execXhr.setRequestHeader('rc', ++requestCount);
            if (shouldBundleCommandJson()) {
                execXhr.setRequestHeader('cmds', iOSExec.nativeFetchMessages());
            }
            execXhr.send(null);
            break;
        case jsToNativeModes.IFRAME_HASH_NO_PAYLOAD:
        case jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD:
            execHashIframe = execHashIframe || createHashIframe();
            // Check if they've removed it from the DOM, and put it back if so.
            if (!execHashIframe.contentWindow) {
                execHashIframe = createHashIframe();
            }
            // The delegate method is called only when the hash changes, so toggle it back and forth.
            hashToggle = hashToggle ^ 3;
            var hashValue = '%0' + hashToggle;
            if (bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) {
                hashValue += iOSExec.nativeFetchMessages();
            }
            execHashIframe.contentWindow.location.hash = hashValue;
            break;
        default:
            execIframe = execIframe || createExecIframe();
            // Check if they've removed it from the DOM, and put it back if so.
            if (!execIframe.contentWindow) {
                execIframe = createExecIframe();
            }
            execIframe.src = "gap://ready";
        }

The default case did nothing.

Making it always use jsToNativeModes.XHR_NO_PAYLOAD allows my app to work again with any iOS version but I feel like I'm losing certain advantages from the upgrade. Which are they? Why were the Ternary Operator expressions switched around? Which could be a possible reason why my app, which worked just fine before the upgrade, would stop working because of this change? Is there a better solution than the one I implemented?

Thanks,

-JR.



--
This message was sent by Atlassian JIRA
(v6.2#6252)