You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by br...@apache.org on 2013/03/20 18:36:50 UTC

js commit: Add scripts/plugin_loader.js, which runs after bootstrap.

Updated Branches:
  refs/heads/master bbb9d7940 -> f97bd694d


Add scripts/plugin_loader.js, which runs after bootstrap.

This code does an XHR for cordova_plugins.json. If it finds the file, it
will load the plugins specified in it. If the response is empty or the
XHR fails, it does nothing.

This creates a new onPluginsReady event that fires either when the
plugins are all loaded or there are no plugins to load. The bootstrap is
waiting on this now, as well as onDOMContentLoaded and onNativeReady.


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

Branch: refs/heads/master
Commit: f97bd694da3364664776d79c5bbf5e914e8e4f5a
Parents: bbb9d79
Author: Braden Shepherdson <br...@gmail.com>
Authored: Wed Mar 20 11:14:31 2013 -0400
Committer: Braden Shepherdson <br...@gmail.com>
Committed: Wed Mar 20 13:29:38 2013 -0400

----------------------------------------------------------------------
 build/packager.js            |   10 +++
 lib/common/channel.js        |    1 -
 lib/scripts/bootstrap.js     |   11 +---
 lib/scripts/plugin_loader.js |  118 +++++++++++++++++++++++++++++++++++++
 4 files changed, 129 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-js/blob/f97bd694/build/packager.js
----------------------------------------------------------------------
diff --git a/build/packager.js b/build/packager.js
index c5f1636..d73c789 100644
--- a/build/packager.js
+++ b/build/packager.js
@@ -111,6 +111,16 @@ packager.bundle = function(platform, debug, commitId ) {
         writeScript(output, scripts[bootstrapPlatform], debug)
     }
 
+    // Include the plugin loading code.
+    if (platform !== 'test') {
+        // NB: This should probably run last of all, and definitely after the bootstrap.
+        if (!scripts['plugin_loader']) {
+            throw new Error("didn't find a script for 'plugin_loader'");
+        }
+
+        writeScript(output, scripts['plugin_loader'], debug);
+    }
+
     // write trailer
     output.push('\n})();')
 

http://git-wip-us.apache.org/repos/asf/cordova-js/blob/f97bd694/lib/common/channel.js
----------------------------------------------------------------------
diff --git a/lib/common/channel.js b/lib/common/channel.js
index 38daedf..d22e57d 100644
--- a/lib/common/channel.js
+++ b/lib/common/channel.js
@@ -243,7 +243,6 @@ channel.createSticky('onCordovaInfoReady');
 channel.createSticky('onCordovaConnectionReady');
 
 // Event to indicate that all automatically loaded JS plugins are loaded and ready.
-// This is used in conjunction with the automatic plugin JS loading CLI prototype.
 channel.createSticky('onPluginsReady');
 
 // Event to indicate that Cordova is ready

http://git-wip-us.apache.org/repos/asf/cordova-js/blob/f97bd694/lib/scripts/bootstrap.js
----------------------------------------------------------------------
diff --git a/lib/scripts/bootstrap.js b/lib/scripts/bootstrap.js
index 6213165..e187798 100644
--- a/lib/scripts/bootstrap.js
+++ b/lib/scripts/bootstrap.js
@@ -53,15 +53,6 @@
     /**
      * Create all cordova objects once page has fully loaded and native side is ready.
      */
-    var joinEvents = [ channel.onDOMContentLoaded, channel.onNativeReady ];
-
-    // If this property is set to something truthy, join on onPluginsReady too.
-    // This property is set by the automatic JS installation prototype in cordova-cli,
-    // and will be removed when the prototype either becomes mainline or is dropped.
-    if (window.__onPluginsLoadedHack) {
-        joinEvents.push(channel.onPluginsReady);
-    }
-
     channel.join(function() {
         var builder = require('cordova/builder'),
             platform = require('cordova/platform');
@@ -82,6 +73,6 @@
             require('cordova').fireDocumentEvent('deviceready');
         }, channel.deviceReadyChannelsArray);
 
-    }, joinEvents);
+    }, [ channel.onDOMContentLoaded, channel.onNativeReady, channel.onPluginsReady ]);
 
 }(window));

http://git-wip-us.apache.org/repos/asf/cordova-js/blob/f97bd694/lib/scripts/plugin_loader.js
----------------------------------------------------------------------
diff --git a/lib/scripts/plugin_loader.js b/lib/scripts/plugin_loader.js
new file mode 100644
index 0000000..ef4f446
--- /dev/null
+++ b/lib/scripts/plugin_loader.js
@@ -0,0 +1,118 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+// Tries to load all plugins' js-modules.
+// This is an async process, but onDeviceReady is blocked on onPluginsReady.
+// onPluginsReady is fired when there are no plugins to load, or they are all done.
+(function (context) {
+    // To be populated with the handler by handlePluginsObject.
+    var onScriptLoadingComplete;
+
+    var scriptCounter = 0;
+    function scriptLoadedCallback() {
+        scriptCounter--;
+        if (scriptCounter === 0) {
+            onScriptLoadingComplete && onScriptLoadingComplete();
+        }
+    }
+
+    // Helper function to inject a <script> tag.
+    function injectScript(path) {
+        scriptCounter++;
+        var script = document.createElement("script");
+        script.onload = scriptLoadedCallback;
+        script.src = path;
+        document.head.appendChild(script);
+    }
+
+    // Called when:
+    // * There are plugins defined and all plugins are finished loading.
+    // * There are no plugins to load.
+    function finishPluginLoading() {
+        context.cordova.require('cordova/channel').onPluginsReady.fire();
+    }
+
+    // Handler for the cordova_plugins.json content.
+    // See plugman's plugin_loader.js for the details of this object.
+    // This function is only called if the really is a plugins array that isn't empty.
+    // Otherwise the XHR response handler will just call finishPluginLoading().
+    function handlePluginsObject(modules) {
+        // First create the callback for when all plugins are loaded.
+        var mapper = context.cordova.require('cordova/modulemapper');
+        onScriptLoadingComplete = function() {
+            // Loop through all the plugins and then through their clobbers and merges.
+            for (var i = 0; i < modules.length; i++) {
+                var module = modules[i];
+                if (!module) continue;
+
+                if (module.clobbers && module.clobbers.length) {
+                    for (var j = 0; j < module.clobbers.length; j++) {
+                        mapper.clobbers(module.id, module.clobbers[j]);
+                    }
+                }
+
+                if (module.merges && module.merges.length) {
+                    for (var k = 0; k < module.merges.length; k++) {
+                        mapper.merges(module.id, module.merges[k]);
+                    }
+                }
+
+                // Finally, if runs is truthy we want to simply require() the module.
+                // This can be skipped if it had any merges or clobbers, though,
+                // since the mapper will already have required the module.
+                if (module.runs && !(module.clobbers && module.clobbers.length) && !(module.merges && module.merges.length)) {
+                    context.cordova.require(module.id);
+                }
+            }
+
+            finishPluginLoading();
+        };
+
+        // Now inject the scripts.
+        for (var i = 0; i < modules.length; i++) {
+            injectScript(modules[i].file);
+        }
+    }
+
+    // Try to XHR the cordova_plugins.json file asynchronously.
+    var xhr = new context.XMLHttpRequest();
+    xhr.onreadystatechange = function() {
+        if (this.readyState != 4) { // not DONE
+            return;
+        }
+
+        // If the response is a JSON string which composes an array, call handlePluginsObject.
+        // If the request fails, or the response is not a JSON array, just call finishPluginLoading.
+        if (this.status == 200) {
+            var obj = JSON.parse(this.responseText);
+            if (obj && obj instanceof Array && obj.length > 0) {
+                handlePluginsObject(obj);
+            } else {
+                finishPluginLoading();
+            }
+        } else {
+            finishPluginLoading();
+        }
+    };
+    xhr.open('GET', 'cordova_plugins.json', true); // Async
+    xhr.send();
+}(window));
+