Updated Branches: refs/heads/master 08a2641cf -> 5686a320a
Change plugin_loader.js into a regular module that is called from bootstrap Instead of being hardcoded into packager.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/5686a320 Tree: http://git-wip-us.apache.org/repos/asf/cordova-js/tree/5686a320 Diff: http://git-wip-us.apache.org/repos/asf/cordova-js/diff/5686a320 Branch: refs/heads/master Commit: 5686a320aa690e52b2c363cba1f8792112088f52 Parents: 08a2641 Author: Andrew Grieve <[email protected]> Authored: Fri Jul 5 09:53:53 2013 -0400 Committer: Andrew Grieve <[email protected]> Committed: Fri Jul 5 09:53:53 2013 -0400 ---------------------------------------------------------------------- build/packager.js | 10 --- lib/common/pluginloader.js | 164 +++++++++++++++++++++++++++++++++++ lib/scripts/bootstrap.js | 6 ++ lib/scripts/plugin_loader.js | 178 -------------------------------------- 4 files changed, 170 insertions(+), 188 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-js/blob/5686a320/build/packager.js ---------------------------------------------------------------------- diff --git a/build/packager.js b/build/packager.js index d859636..5026fbd 100644 --- a/build/packager.js +++ b/build/packager.js @@ -160,16 +160,6 @@ 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('})();') http://git-wip-us.apache.org/repos/asf/cordova-js/blob/5686a320/lib/common/pluginloader.js ---------------------------------------------------------------------- diff --git a/lib/common/pluginloader.js b/lib/common/pluginloader.js new file mode 100644 index 0000000..764aa90 --- /dev/null +++ b/lib/common/pluginloader.js @@ -0,0 +1,164 @@ +/* + * + * 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. + * +*/ + +var channel = require('cordova/channel'); +var modulemapper = require('cordova/modulemapper'); + +var scriptCounter = 0; +var moduleList = null; + +function scriptLoadedCallback() { + scriptCounter--; + if (scriptCounter === 0) { + onScriptLoadingComplete(); + } +} + +// Helper function to inject a <script> tag. +function injectScript(url, onload) { + scriptCounter++; + var script = document.createElement("script"); + // onload fires even when script fails loads with an error. + script.onload = onload; + script.src = url; + document.head.appendChild(script); +} + +function onScriptLoadingComplete() { + // Loop through all the plugins and then through their clobbers and merges. + for (var i = 0; i < moduleList.length; i++) { + var module = moduleList[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)) { + require(module.id); + } + } + catch(err) { + // error with module, most likely clobbers, should we continue? + } + } + } + + finishPluginLoading(); +} + +// Called when: +// * There are plugins defined and all plugins are finished loading. +// * There are no plugins to load. +function finishPluginLoading() { + channel.onPluginsReady.fire(); +} + +// Handler for the cordova_plugins.js 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 onerror response handler will just call finishPluginLoading(). +function handlePluginsObject(path) { + // Now inject the scripts. + for (var i = 0; i < moduleList.length; i++) { + injectScript(path + moduleList[i].file, scriptLoadedCallback); + } +} + +function injectPluginScript(pathPrefix) { + injectScript(pathPrefix + 'cordova_plugins.js', function(){ + try { + moduleList = require("cordova/plugin_list"); + handlePluginsObject(pathPrefix); + } 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(); + } + }); +} + +function findCordovaPath() { + var path = null; + var scripts = document.getElementsByTagName('script'); + var term = 'cordova.js'; + for (var n = scripts.length-1; n>-1; n--) { + var src = scripts[n].src; + if (src.indexOf(term) == (src.length - term.length)) { + path = src.substring(0, src.length - term.length); + break; + } + } + return path; +} + +// 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. +exports.load = function() { + var pathPrefix = findCordovaPath(); + if (pathPrefix === null) { + console.warn('Could not find cordova.js script tag. Plugin loading may fail.'); + pathPrefix = ''; + } + + // Try to XHR the cordova_plugins.json file asynchronously. + var xhr = new XMLHttpRequest(); + xhr.onload = function() { + // 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. + var obj; + try { + obj = (this.status === 0 || this.status === 200) && this.responseText && JSON.parse(this.responseText); + } catch (err) { + // obj will be undefined. + } + if (Array.isArray(obj) && obj.length > 0) { + moduleList = obj; + handlePluginsObject(pathPrefix); + } else { + finishPluginLoading(); + } + }; + xhr.onerror = function() { + // One some phones (Windows) this xhr.open throws an Access Denied exception + // So lets keep trying, but with a script tag injection technique instead of XHR + injectPluginScript(pathPrefix); + }; + try { + xhr.open('GET', pathPrefix + 'cordova_plugins.json', true); // Async + xhr.send(); + } catch(err){ + injectPluginScript(pathPrefix); + } +}; + http://git-wip-us.apache.org/repos/asf/cordova-js/blob/5686a320/lib/scripts/bootstrap.js ---------------------------------------------------------------------- diff --git a/lib/scripts/bootstrap.js b/lib/scripts/bootstrap.js index 47c3179..27d653c 100644 --- a/lib/scripts/bootstrap.js +++ b/lib/scripts/bootstrap.js @@ -26,6 +26,8 @@ context._cordovaJsLoaded = true; var channel = require('cordova/channel'); + var pluginloader = require('cordova/pluginloader'); + var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady]; function logUnfiredChannels(arr) { @@ -94,4 +96,8 @@ }, platformInitChannelsArray); + // Don't attempt to load when running unit tests. + if (typeof XMLHttpRequest != 'undefined') { + pluginloader.load(); + } }(window)); http://git-wip-us.apache.org/repos/asf/cordova-js/blob/5686a320/lib/scripts/plugin_loader.js ---------------------------------------------------------------------- diff --git a/lib/scripts/plugin_loader.js b/lib/scripts/plugin_loader.js deleted file mode 100644 index d9bea0a..0000000 --- a/lib/scripts/plugin_loader.js +++ /dev/null @@ -1,178 +0,0 @@ -/* - * - * 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(); - } - } - - function scriptErrorCallback(err) { - // Open Question: If a script path specified in cordova_plugins.js does not exist, do we fail for all? - // this is currently just continuing. - 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.onerror = scriptErrorCallback; - 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.js 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 onerror response handler will just call finishPluginLoading(). - function handlePluginsObject(modules, path) { - // 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) { - try { - 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); - } - } - catch(err) { - // error with module, most likely clobbers, should we continue? - } - } - } - - finishPluginLoading(); - }; - - // Now inject the scripts. - for (var i = 0; i < modules.length; i++) { - injectScript(path + modules[i].file); - } - } - - // Find the root of the app - var path = ''; - var scripts = document.getElementsByTagName('script'); - var term = 'cordova.js'; - for (var n = scripts.length-1; n>-1; n--) { - var src = scripts[n].src; - if (src.indexOf(term) == (src.length - term.length)) { - path = src.substring(0, src.length - term.length); - break; - } - } - - var plugins_json = path + 'cordova_plugins.json'; - var plugins_js = path + 'cordova_plugins.js'; - - // One some phones (Windows) this xhr.open throws an Access Denied exception - // So lets keep trying, but with a script tag injection technique instead of XHR - var injectPluginScript = function injectPluginScript() { - try { - var script = document.createElement("script"); - script.onload = function(){ - var list = cordova.require("cordova/plugin_list"); - handlePluginsObject(list,path); - }; - script.onerror = function() { - // 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(); - }; - script.src = plugins_js; - document.head.appendChild(script); - - } catch(err){ - finishPluginLoading(); - } - } - - - // Try to XHR the cordova_plugins.json file asynchronously. - var xhr = new XMLHttpRequest(); - xhr.onload = function() { - // 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. - var obj; - try { - obj = (this.status == 0 || this.status == 200) && this.responseText && JSON.parse(this.responseText); - } catch (err) { - // obj will be undefined. - } - if (Array.isArray(obj) && obj.length > 0) { - handlePluginsObject(obj, path); - } else { - finishPluginLoading(); - } - }; - xhr.onerror = function() { - // In this case, the json file was not present, but XHR was allowed, - // so we should still try the script injection technique with the js file - // in case that is there. - injectPluginScript(); - }; - try { // we commented we were going to try, so let us actually try and catch - xhr.open('GET', plugins_json, true); // Async - xhr.send(); - } catch(err){ - injectPluginScript(); - } -}(window)); -
