You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by an...@apache.org on 2014/03/27 15:22:20 UTC

[11/34] js commit: CB-6181 android: Always execute exec() callbacks async.

CB-6181 android: Always execute exec() callbacks async.


Project: http://git-wip-us.apache.org/repos/asf/cordova-js/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-js/commit/7b681f2a
Tree: http://git-wip-us.apache.org/repos/asf/cordova-js/tree/7b681f2a
Diff: http://git-wip-us.apache.org/repos/asf/cordova-js/diff/7b681f2a

Branch: refs/heads/browserify
Commit: 7b681f2acc894c010342e9de3cfd2000be7e9360
Parents: fb16e9a
Author: Andrew Grieve <ag...@chromium.org>
Authored: Thu Mar 6 12:14:43 2014 -0500
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Thu Mar 6 12:14:43 2014 -0500

----------------------------------------------------------------------
 src/android/exec.js       | 64 ++++++++++++++++++++++++++----------------
 test/android/test.exec.js | 16 ++++++++++-
 2 files changed, 55 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-js/blob/7b681f2a/src/android/exec.js
----------------------------------------------------------------------
diff --git a/src/android/exec.js b/src/android/exec.js
index 0d35ff1..e6a53d6 100644
--- a/src/android/exec.js
+++ b/src/android/exec.js
@@ -98,7 +98,7 @@ function androidExec(success, fail, service, action, args) {
             androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
             return;
         } else {
-            androidExec.processMessages(messages);
+            androidExec.processMessages(messages, true);
         }
     }
 }
@@ -207,46 +207,62 @@ function processMessage(message) {
             }
             cordova.callbackFromNative(callbackId, success, status, [payload], keepCallback);
         } else {
-            console.log("processMessage failed: invalid message:" + message);
+            console.log("processMessage failed: invalid message: " + JSON.stringify(message));
         }
     } catch (e) {
-        console.log("processMessage failed: Message: " + message);
         console.log("processMessage failed: Error: " + e);
         console.log("processMessage failed: Stack: " + e.stack);
+        console.log("processMessage failed: Message: " + message);
     }
 }
 
+var isProcessing = false;
+
 // This is called from the NativeToJsMessageQueue.java.
-androidExec.processMessages = function(messages) {
+androidExec.processMessages = function(messages, opt_useTimeout) {
     if (messages) {
         messagesFromNative.push(messages);
-        // Check for the reentrant case, and enqueue the message if that's the case.
-        if (messagesFromNative.length > 1) {
-            return;
-        }
+    }
+    // Check for the reentrant case.
+    if (isProcessing) {
+        return;
+    }
+    if (opt_useTimeout) {
+        window.setTimeout(androidExec.processMessages, 0);
+        return;
+    }
+    isProcessing = true;
+    try {
+        // TODO: add setImmediate polyfill and process only one message at a time.
         while (messagesFromNative.length) {
-            // Don't unshift until the end so that reentrancy can be detected.
-            messages = messagesFromNative[0];
+            var msg = popMessageFromQueue();
             // The Java side can send a * message to indicate that it
             // still has messages waiting to be retrieved.
-            if (messages == '*') {
-                messagesFromNative.shift();
-                window.setTimeout(pollOnce, 0);
+            if (msg == '*' && messagesFromNative.length === 0) {
+                setTimeout(pollOnce, 0);
                 return;
             }
-
-            var spaceIdx = messages.indexOf(' ');
-            var msgLen = +messages.slice(0, spaceIdx);
-            var message = messages.substr(spaceIdx + 1, msgLen);
-            messages = messages.slice(spaceIdx + msgLen + 1);
-            processMessage(message);
-            if (messages) {
-                messagesFromNative[0] = messages;
-            } else {
-                messagesFromNative.shift();
-            }
+            processMessage(msg);
         }
+    } finally {
+        isProcessing = false;
     }
 };
 
+function popMessageFromQueue() {
+    var messageBatch = messagesFromNative.shift();
+    if (messageBatch == '*') {
+        return '*';
+    }
+
+    var spaceIdx = messageBatch.indexOf(' ');
+    var msgLen = +messageBatch.slice(0, spaceIdx);
+    var message = messageBatch.substr(spaceIdx + 1, msgLen);
+    messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
+    if (messageBatch) {
+        messagesFromNative.unshift(messageBatch);
+    }
+    return message;
+}
+
 module.exports = androidExec;

http://git-wip-us.apache.org/repos/asf/cordova-js/blob/7b681f2a/test/android/test.exec.js
----------------------------------------------------------------------
diff --git a/test/android/test.exec.js b/test/android/test.exec.js
index 5271d81..736db04 100644
--- a/test/android/test.exec.js
+++ b/test/android/test.exec.js
@@ -89,7 +89,21 @@ describe('exec.processMessages', function () {
 
             exec(win1, null, 'Service', 'action', []);
             exec(win2, null, 'Service', 'action', []);
-            expect(winSpy3).toHaveBeenCalledWith('three');
+            waitsFor(function() { return winSpy3.wasCalled }, 200);
+            runs(function() {
+                expect(winSpy3).toHaveBeenCalledWith('three');
+            });
+        });
+        it('should process messages asynchronously', function() {
+            nativeApi.exec.andCallFake(function(service, action, callbackId, argsJson) {
+                return createCallbackMessage(true, false, 1, callbackId, 'stwo');
+            });
+
+            var winSpy = jasmine.createSpy('win');
+
+            exec(winSpy, null, 'Service', 'action', []);
+            expect(winSpy).not.toHaveBeenCalled();
+            waitsFor(function() { return winSpy.wasCalled }, 200);
         });
     });