123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- // Copyright 2008 The Closure Library Authors. All Rights Reserved.
- //
- // Licensed 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.
- /**
- * @fileoverview Defines the goog.module.ModuleInfo class.
- *
- */
- goog.provide('goog.module.ModuleInfo');
- goog.require('goog.Disposable');
- goog.require('goog.async.throwException');
- goog.require('goog.functions');
- /** @suppress {extraRequire} */
- goog.require('goog.module');
- goog.require('goog.module.BaseModule');
- goog.require('goog.module.ModuleLoadCallback');
- // TODO(johnlenz): goog.module.ModuleManager.FailureType into its own file.
- goog.forwardDeclare('goog.module.ModuleManager.FailureType');
- /**
- * A ModuleInfo object is used by the ModuleManager to hold information about a
- * module of js code that may or may not yet be loaded into the environment.
- *
- * @param {Array<string>} deps Ids of the modules that must be loaded before
- * this one. The ids must be in dependency order (i.e. if the ith module
- * depends on the jth module, then i > j).
- * @param {string} id The module's ID.
- * @constructor
- * @extends {goog.Disposable}
- * @final
- */
- goog.module.ModuleInfo = function(deps, id) {
- goog.Disposable.call(this);
- /**
- * A list of the ids of the modules that must be loaded before this module.
- * @type {Array<string>}
- * @private
- */
- this.deps_ = deps;
- /**
- * The module's ID.
- * @type {string}
- * @private
- */
- this.id_ = id;
- /**
- * Callbacks to execute once this module is loaded.
- * @type {Array<goog.module.ModuleLoadCallback>}
- * @private
- */
- this.onloadCallbacks_ = [];
- /**
- * Callbacks to execute if the module load errors.
- * @type {Array<goog.module.ModuleLoadCallback>}
- * @private
- */
- this.onErrorCallbacks_ = [];
- /**
- * Early callbacks to execute once this module is loaded. Called after
- * module initialization but before regular onload callbacks.
- * @type {Array<goog.module.ModuleLoadCallback>}
- * @private
- */
- this.earlyOnloadCallbacks_ = [];
- };
- goog.inherits(goog.module.ModuleInfo, goog.Disposable);
- /**
- * The uris that can be used to retrieve this module's code.
- * @type {Array<string>?}
- * @private
- */
- goog.module.ModuleInfo.prototype.uris_ = null;
- /**
- * The constructor to use to instantiate the module object after the module
- * code is loaded. This must be either goog.module.BaseModule or a subclass of
- * it.
- * @type {Function}
- * @private
- */
- goog.module.ModuleInfo.prototype.moduleConstructor_ = goog.module.BaseModule;
- /**
- * The module object. This will be null until the module is loaded.
- * @type {goog.module.BaseModule?}
- * @private
- */
- goog.module.ModuleInfo.prototype.module_ = null;
- /**
- * Gets the dependencies of this module.
- * @return {Array<string>} The ids of the modules that this module depends on.
- */
- goog.module.ModuleInfo.prototype.getDependencies = function() {
- return this.deps_;
- };
- /**
- * Gets the ID of this module.
- * @return {string} The ID.
- */
- goog.module.ModuleInfo.prototype.getId = function() {
- return this.id_;
- };
- /**
- * Sets the uris of this module.
- * @param {Array<string>} uris Uris for this module's code.
- */
- goog.module.ModuleInfo.prototype.setUris = function(uris) {
- this.uris_ = uris;
- };
- /**
- * Gets the uris of this module.
- * @return {Array<string>?} Uris for this module's code.
- */
- goog.module.ModuleInfo.prototype.getUris = function() {
- return this.uris_;
- };
- /**
- * Sets the constructor to use to instantiate the module object after the
- * module code is loaded.
- * @param {Function} constructor The constructor of a goog.module.BaseModule
- * subclass.
- */
- goog.module.ModuleInfo.prototype.setModuleConstructor = function(constructor) {
- if (this.moduleConstructor_ === goog.module.BaseModule) {
- this.moduleConstructor_ = constructor;
- } else {
- throw Error('Cannot set module constructor more than once.');
- }
- };
- /**
- * Registers a function that should be called after the module is loaded. These
- * early callbacks are called after {@link Module#initialize} is called but
- * before the other callbacks are called.
- * @param {Function} fn A callback function that takes a single argument which
- * is the module context.
- * @param {Object=} opt_handler Optional handler under whose scope to execute
- * the callback.
- * @return {!goog.module.ModuleLoadCallback} Reference to the callback
- * object.
- */
- goog.module.ModuleInfo.prototype.registerEarlyCallback = function(
- fn, opt_handler) {
- return this.registerCallback_(this.earlyOnloadCallbacks_, fn, opt_handler);
- };
- /**
- * Registers a function that should be called after the module is loaded.
- * @param {Function} fn A callback function that takes a single argument which
- * is the module context.
- * @param {Object=} opt_handler Optional handler under whose scope to execute
- * the callback.
- * @return {!goog.module.ModuleLoadCallback} Reference to the callback
- * object.
- */
- goog.module.ModuleInfo.prototype.registerCallback = function(fn, opt_handler) {
- return this.registerCallback_(this.onloadCallbacks_, fn, opt_handler);
- };
- /**
- * Registers a function that should be called if the module load fails.
- * @param {Function} fn A callback function that takes a single argument which
- * is the failure type.
- * @param {Object=} opt_handler Optional handler under whose scope to execute
- * the callback.
- * @return {!goog.module.ModuleLoadCallback} Reference to the callback
- * object.
- */
- goog.module.ModuleInfo.prototype.registerErrback = function(fn, opt_handler) {
- return this.registerCallback_(this.onErrorCallbacks_, fn, opt_handler);
- };
- /**
- * Registers a function that should be called after the module is loaded.
- * @param {Array<goog.module.ModuleLoadCallback>} callbacks The array to
- * add the callback to.
- * @param {Function} fn A callback function that takes a single argument which
- * is the module context.
- * @param {Object=} opt_handler Optional handler under whose scope to execute
- * the callback.
- * @return {!goog.module.ModuleLoadCallback} Reference to the callback
- * object.
- * @private
- */
- goog.module.ModuleInfo.prototype.registerCallback_ = function(
- callbacks, fn, opt_handler) {
- var callback = new goog.module.ModuleLoadCallback(fn, opt_handler);
- callbacks.push(callback);
- return callback;
- };
- /**
- * Determines whether the module has been loaded.
- * @return {boolean} Whether the module has been loaded.
- */
- goog.module.ModuleInfo.prototype.isLoaded = function() {
- return !!this.module_;
- };
- /**
- * Gets the module.
- * @return {goog.module.BaseModule?} The module if it has been loaded.
- * Otherwise, null.
- */
- goog.module.ModuleInfo.prototype.getModule = function() {
- return this.module_;
- };
- /**
- * Sets this module as loaded.
- * @param {function() : Object} contextProvider A function that provides the
- * module context.
- * @return {boolean} Whether any errors occurred while executing the onload
- * callbacks.
- */
- goog.module.ModuleInfo.prototype.onLoad = function(contextProvider) {
- // Instantiate and initialize the module object.
- var module = new this.moduleConstructor_;
- module.initialize(contextProvider());
- // Keep an internal reference to the module.
- this.module_ = module;
- // Fire any early callbacks that were waiting for the module to be loaded.
- var errors =
- !!this.callCallbacks_(this.earlyOnloadCallbacks_, contextProvider());
- // Fire any callbacks that were waiting for the module to be loaded.
- errors =
- errors || !!this.callCallbacks_(this.onloadCallbacks_, contextProvider());
- if (!errors) {
- // Clear the errbacks.
- this.onErrorCallbacks_.length = 0;
- }
- return errors;
- };
- /**
- * Calls the error callbacks for the module.
- * @param {goog.module.ModuleManager.FailureType} cause What caused the error.
- */
- goog.module.ModuleInfo.prototype.onError = function(cause) {
- var result = this.callCallbacks_(this.onErrorCallbacks_, cause);
- if (result) {
- // Throw an exception asynchronously. Do not let the exception leak
- // up to the caller, or it will blow up the module loading framework.
- window.setTimeout(
- goog.functions.error('Module errback failures: ' + result), 0);
- }
- this.earlyOnloadCallbacks_.length = 0;
- this.onloadCallbacks_.length = 0;
- };
- /**
- * Helper to call the callbacks after module load.
- * @param {Array<goog.module.ModuleLoadCallback>} callbacks The callbacks
- * to call and then clear.
- * @param {*} context The module context.
- * @return {Array<*>} Any errors encountered while calling the callbacks,
- * or null if there were no errors.
- * @private
- */
- goog.module.ModuleInfo.prototype.callCallbacks_ = function(callbacks, context) {
- // NOTE(nicksantos):
- // In practice, there are two error-handling scenarios:
- // 1) The callback does some mandatory initialization of the module.
- // 2) The callback is for completion of some optional UI event.
- // There's no good way to handle both scenarios.
- //
- // Our strategy here is to protect module manager from exceptions, so that
- // the failure of one module doesn't affect the loading of other modules.
- // Errors are thrown outside of the current stack frame, so they still
- // get reported but don't interrupt execution.
- // Call each callback in the order they were registered
- var errors = [];
- for (var i = 0; i < callbacks.length; i++) {
- try {
- callbacks[i].execute(context);
- } catch (e) {
- goog.async.throwException(e);
- errors.push(e);
- }
- }
- // Clear the list of callbacks.
- callbacks.length = 0;
- return errors.length ? errors : null;
- };
- /** @override */
- goog.module.ModuleInfo.prototype.disposeInternal = function() {
- goog.module.ModuleInfo.superClass_.disposeInternal.call(this);
- goog.dispose(this.module_);
- };
|