mimicry/module.js

105 lines
4.0 KiB
JavaScript

"use strict";
(function modulePrivateClosure () {
/**
* A class that represents Mimicry Module
* */
class Module {
/**
* @param {Array<Dependency>} deps - array of files that this module depends on
* @param {Function} body - body function of the module that defines the module itself
* */
constructor (deps, body) {
this._dependencies = deps;
this._body = body;
this._loaded = 0;
this._callbacks = [];
this._value = null;
this._executed = false;
}
/**
* @returns {Boolean} - true if the module have already been executed
* */
get executed () {
return this._executed;
}
/**
* @returns {any} - a value that is returned from the module body function
* */
get value () {
return this._value;
}
/**
* @returns {Boolean} - true if the module has its dependencies resolved
* */
get allDependenciesResolved () {
return this.executed || this._loaded === this._dependencies.length;
}
/**
* This function should be called when one of the dependencies are considered to be satisfied
* If the dependency is not a module this happens when the file is loaded
* If the dependency is a module this happens when the module is executed
*
* @param {Mimicry} mimicry - Mimicry instance that was loading this module,
* it is needed for calling "execute" if the dependencies are resolved
* @param {any} global - a global object for current platform
* */
incrementDependency (mimicry, global) {
++this._loaded
if (this.allDependenciesResolved)
this.execute(mimicry, global);
}
/**
* If the modules is executed - calls the callback immediately
* Otherwise remembers the callback and executes all of them in the same order
* that they were added.
*
* Callback is called with the following arguments:
* first: global object
* second: the value of this module
*
* @param {Function} callback - a callback to call
* @param {any} global - a global object for current platform
* */
addCallback (/*Function*/callback, global) {
if (this._executed)
callback.call(null, global, this._value);
else
this._callbacks.push(callback);
}
/**
* Executes a module, launching its body function
*
* @param {Mimicry} mimicry - an instance of Mimicry that was loading this module
* It is needed to acquire values of dependencies
* @param {any} global - a global object for current platform
* */
execute (mimicry, global) {
if (this.executed)
throw new Error("An attempt to execute a module for the second time");
if (this._body instanceof Function) {
const values = [];
for (let i = 0; i < this._dependencies.length; ++i) {
const name = this._dependencies[i].name;
values.push(mimicry.getModule(name) || mimicry.getAsset(name));
}
this._value = this._body.call(null, global, values);
} else {
this._value = null;
}
this._executed = true;
const callbacks = this._callbacks;
delete this._callbacks;
delete this._dependencies;
for (let i = 0; i < callbacks.length; ++i)
callbacks[i].call(null, global, this._value);
}
}
if (typeof module === 'object' && module.exports)
module.exports = Module;
else
window.__MimicryModule__ = Module;
})();