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:17 UTC
[08/34] js commit: CB-5671 Don't fail plugin loading if plugin
modules are already loaded.
CB-5671 Don't fail plugin loading if plugin modules are already loaded.
This can happen when a build step concats all your JS.
Project: http://git-wip-us.apache.org/repos/asf/cordova-js/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-js/commit/5f811bbf
Tree: http://git-wip-us.apache.org/repos/asf/cordova-js/tree/5f811bbf
Diff: http://git-wip-us.apache.org/repos/asf/cordova-js/diff/5f811bbf
Branch: refs/heads/browserify
Commit: 5f811bbf2be9f6b18ee1575ab7fa506866291573
Parents: ddf13aa
Author: Andrew Grieve <ag...@chromium.org>
Authored: Mon Feb 24 15:59:26 2014 -0500
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Mon Feb 24 15:59:26 2014 -0500
----------------------------------------------------------------------
src/common/pluginloader.js | 79 ++++++++++++--------------
test/test.pluginloader.js | 123 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 160 insertions(+), 42 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-js/blob/5f811bbf/src/common/pluginloader.js
----------------------------------------------------------------------
diff --git a/src/common/pluginloader.js b/src/common/pluginloader.js
index 92cbaed..f72bfda 100644
--- a/src/common/pluginloader.js
+++ b/src/common/pluginloader.js
@@ -23,43 +23,51 @@ var modulemapper = require('cordova/modulemapper');
var urlutil = require('cordova/urlutil');
// Helper function to inject a <script> tag.
-function injectScript(url, onload, onerror) {
+// Exported for testing.
+exports.injectScript = function(url, onload, onerror) {
var script = document.createElement("script");
// onload fires even when script fails loads with an error.
script.onload = onload;
- script.onerror = onerror || onload;
+ // onerror fires for malformed URLs.
+ script.onerror = onerror;
script.src = url;
document.head.appendChild(script);
+};
+
+function injectIfNecessary(id, url, onload, onerror) {
+ onerror = onerror || onload;
+ if (id in define.moduleMap) {
+ onload();
+ } else {
+ exports.injectScript(url, function() {
+ if (id in define.moduleMap) {
+ onload();
+ } else {
+ onerror();
+ }
+ }, onerror);
+ }
}
function onScriptLoadingComplete(moduleList, finishPluginLoading) {
// Loop through all the plugins and then through their clobbers and merges.
for (var i = 0, module; module = moduleList[i]; i++) {
- if (module) {
- try {
- if (module.clobbers && module.clobbers.length) {
- for (var j = 0; j < module.clobbers.length; j++) {
- modulemapper.clobbers(module.id, module.clobbers[j]);
- }
- }
-
- if (module.merges && module.merges.length) {
- for (var k = 0; k < module.merges.length; k++) {
- modulemapper.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)) {
- modulemapper.runs(module.id);
- }
+ if (module.clobbers && module.clobbers.length) {
+ for (var j = 0; j < module.clobbers.length; j++) {
+ modulemapper.clobbers(module.id, module.clobbers[j]);
}
- catch(err) {
- // error with module, most likely clobbers, should we continue?
+ }
+
+ if (module.merges && module.merges.length) {
+ for (var k = 0; k < module.merges.length; k++) {
+ modulemapper.merges(module.id, module.merges[k]);
}
}
+
+ // Finally, if runs is truthy we want to simply require() the module.
+ if (module.runs) {
+ modulemapper.runs(module.id);
+ }
}
finishPluginLoading();
@@ -84,26 +92,10 @@ function handlePluginsObject(path, moduleList, finishPluginLoading) {
}
for (var i = 0; i < moduleList.length; i++) {
- injectScript(path + moduleList[i].file, scriptLoadedCallback);
+ injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
}
}
-function injectPluginScript(pathPrefix, finishPluginLoading) {
- var pluginPath = pathPrefix + 'cordova_plugins.js';
-
- injectScript(pluginPath, function() {
- try {
- var moduleList = require("cordova/plugin_list");
- handlePluginsObject(pathPrefix, moduleList, finishPluginLoading);
- }
- catch (e) {
- // Error loading cordova_plugins.js, file not found or something
- // this is an acceptable error, pre-3.0.0, so we just move on.
- finishPluginLoading();
- }
- }, finishPluginLoading); // also, add script load error handler for file not found
-}
-
function findCordovaPath() {
var path = null;
var scripts = document.getElementsByTagName('script');
@@ -127,6 +119,9 @@ exports.load = function(callback) {
console.log('Could not find cordova.js script tag. Plugin loading may fail.');
pathPrefix = '';
}
- injectPluginScript(pathPrefix, callback);
+ injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function() {
+ var moduleList = require("cordova/plugin_list");
+ handlePluginsObject(pathPrefix, moduleList, callback);
+ }, callback);
};
http://git-wip-us.apache.org/repos/asf/cordova-js/blob/5f811bbf/test/test.pluginloader.js
----------------------------------------------------------------------
diff --git a/test/test.pluginloader.js b/test/test.pluginloader.js
new file mode 100644
index 0000000..bb36f13
--- /dev/null
+++ b/test/test.pluginloader.js
@@ -0,0 +1,123 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+describe('pluginloader', function() {
+ var pluginloader = require('cordova/pluginloader');
+ var injectScript;
+ var cdvScript;
+ var done;
+ var success;
+ beforeEach(function() {
+ injectScript = spyOn(pluginloader, 'injectScript');
+ var el = document.createElement('script');
+ el.setAttribute('type', 'foo');
+ el.src = 'foo/cordova.js?bar';
+ document.body.appendChild(el);
+ cdvScript = el;
+ done = false;
+ success = false;
+ });
+ afterEach(function() {
+ if (cdvScript) {
+ cdvScript.parentNode.removeChild(cdvScript);
+ cdvScript = null;
+ }
+ define.remove('cordova/plugin_list');
+ define.remove('some.id');
+ });
+
+ function setDone() {
+ done = true;
+ }
+
+ it('should inject cordova_plugins.js when it is not already there', function() {
+ injectScript.andCallFake(function(url, onload, onerror) {
+ // jsdom deficiencies:
+ if (typeof location != 'undefined') {
+ expect(url).toBe(window.location.href.replace(/\/[^\/]*?$/, '/foo/cordova_plugins.js'));
+ } else {
+ expect(url).toBe('foo/cordova_plugins.js');
+ }
+ define('cordova/plugin_list', function(require, exports, module) {
+ module.exports = [];
+ });
+ success = true;
+ onload();
+ });
+
+ pluginloader.load(setDone);
+ waitsFor(function() { return done });
+ runs(function() {
+ expect(success).toBe(true);
+ });
+ });
+
+ it('should not inject cordova_plugins.js when it is already there', function() {
+ define('cordova/plugin_list', function(require, exports, module) {
+ module.exports = [];
+ });
+ pluginloader.load(setDone);
+ waitsFor(function() { return done });
+ runs(function() {
+ expect(injectScript).not.toHaveBeenCalled();
+ });
+ });
+
+ it('should inject plugin scripts when they are not already there', function() {
+ define('cordova/plugin_list', function(require, exports, module) {
+ module.exports = [
+ { "file": "some/path.js", "id": "some.id" }
+ ];
+ });
+ injectScript.andCallFake(function(url, onload, onerror) {
+ // jsdom deficiencies:
+ if (typeof location != 'undefined') {
+ expect(url).toBe(window.location.href.replace(/\/[^\/]*?$/, '/foo/some/path.js'));
+ } else {
+ expect(url).toBe('foo/some/path.js');
+ }
+ define('some.id', function(require, exports, module) {
+ });
+ success = true;
+ onload();
+ });
+ pluginloader.load(setDone);
+ waitsFor(function() { return done });
+ runs(function() {
+ expect(success).toBe(true);
+ });
+ });
+
+ it('should not inject plugin scripts when they are already there', function() {
+ define('cordova/plugin_list', function(require, exports, module) {
+ module.exports = [
+ { "file": "some/path.js", "id": "some.id" }
+ ];
+ });
+ define('some.id', function(require, exports, module) {
+ });
+ pluginloader.load(setDone);
+ waitsFor(function() { return done });
+ runs(function() {
+ expect(injectScript).not.toHaveBeenCalled();
+ });
+ });
+});