mirror of
https://github.com/lrsjng/h5ai.git
synced 2025-05-25 20:44:53 -04:00
247 lines
4.8 KiB
JavaScript
247 lines
4.8 KiB
JavaScript
/*! modulejs 0.2 - //larsjung.de/modulejs - MIT License */
|
|
|
|
(function (global, name) {
|
|
'use strict';
|
|
|
|
|
|
var objProto = Object.prototype,
|
|
arrayForEach = Array.prototype.forEach,
|
|
isType = function (arg, type) {
|
|
|
|
return objProto.toString.call(arg) === '[object ' + type + ']';
|
|
},
|
|
isString = function (arg) {
|
|
|
|
return isType(arg, 'String');
|
|
},
|
|
isFunction = function (arg) {
|
|
|
|
return isType(arg, 'Function');
|
|
},
|
|
isArray = Array.isArray || function (arg) {
|
|
|
|
return isType(arg, 'Array');
|
|
},
|
|
isObject = function (arg) {
|
|
|
|
return arg === new Object(arg);
|
|
},
|
|
has = function (arg, id) {
|
|
|
|
return objProto.hasOwnProperty.call(arg, id);
|
|
},
|
|
each = function (obj, iterator, context) {
|
|
|
|
if (arrayForEach && obj.forEach === arrayForEach) {
|
|
obj.forEach(iterator, context);
|
|
} else if (obj.length === +obj.length) {
|
|
for (var i = 0, l = obj.length; i < l; i += 1) {
|
|
iterator.call(context, obj[i], i, obj);
|
|
}
|
|
} else {
|
|
for (var key in obj) {
|
|
if (has(obj, key)) {
|
|
iterator.call(context, obj[key], key, obj);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
contains = function (array, item) {
|
|
|
|
for (var i = 0, l = array.length; i < l; i += 1) {
|
|
if (array[i] === item) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
uniq = function (array) {
|
|
|
|
var elements = {},
|
|
result = [];
|
|
|
|
each(array, function (el) {
|
|
|
|
if (!has(elements, el)) {
|
|
result.push(el);
|
|
elements[el] = 1;
|
|
}
|
|
});
|
|
|
|
return result;
|
|
},
|
|
err = function (condition, code, message) {
|
|
|
|
if (condition) {
|
|
throw {
|
|
code: code,
|
|
msg: message,
|
|
toString: function () {
|
|
return name + ' error ' + code + ': ' + message;
|
|
}
|
|
};
|
|
}
|
|
},
|
|
|
|
// Module definitions.
|
|
definitions = {},
|
|
|
|
// Module instances.
|
|
instances = {},
|
|
|
|
resolve = function (id, cold, stack) {
|
|
|
|
err(!isString(id), 31, 'id must be a string "' + id + '"');
|
|
|
|
if (!cold && has(instances, id)) {
|
|
return instances[id];
|
|
}
|
|
|
|
var def = definitions[id];
|
|
err(!def, 32, 'id not defined "' + id + '"');
|
|
|
|
stack = (stack || []).slice(0);
|
|
stack.push(id);
|
|
|
|
var deps = [];
|
|
|
|
each(def.deps, function (depId, idx) {
|
|
|
|
err(contains(stack, depId), 33, 'cyclic dependencies: ' + stack + ' & ' + depId);
|
|
|
|
if (cold) {
|
|
deps = deps.concat(resolve(depId, cold, stack));
|
|
deps.push(depId);
|
|
} else {
|
|
deps[idx] = resolve(depId, cold, stack);
|
|
}
|
|
});
|
|
|
|
if (cold) {
|
|
return uniq(deps);
|
|
}
|
|
|
|
var obj = def.fn.apply(global, deps);
|
|
instances[id] = obj;
|
|
return obj;
|
|
},
|
|
|
|
|
|
|
|
// Public methods
|
|
// --------------
|
|
|
|
// ### define
|
|
// Defines a module for `id: String`, optional `deps: Array[String]`,
|
|
// `arg: Object/function`.
|
|
define = function (id, deps, arg) {
|
|
|
|
// sort arguments
|
|
if (arg === undefined) {
|
|
arg = deps;
|
|
deps = [];
|
|
}
|
|
// check arguments
|
|
err(!isString(id), 11, 'id must be a string "' + id + '"');
|
|
err(definitions[id], 12, 'id already defined "' + id + '"');
|
|
err(!isArray(deps), 13, 'dependencies for "' + id + '" must be an array "' + deps + '"');
|
|
err(!isObject(arg) && !isFunction(arg), 14, 'arg for "' + id + '" must be object or function "' + arg + '"');
|
|
|
|
// accept definition
|
|
definitions[id] = {
|
|
id: id,
|
|
deps: deps,
|
|
fn: isFunction(arg) ? arg : function () { return arg; }
|
|
};
|
|
},
|
|
|
|
// ### require
|
|
// Returns an instance for `id`.
|
|
require = function (id) {
|
|
|
|
return resolve(id);
|
|
},
|
|
|
|
// ### state
|
|
// Returns an object that holds infos about the current definitions and dependencies.
|
|
state = function () {
|
|
|
|
var res = {};
|
|
|
|
each(definitions, function (def, id) {
|
|
|
|
res[id] = {
|
|
|
|
// direct dependencies
|
|
deps: def.deps.slice(0),
|
|
|
|
// transitive dependencies
|
|
reqs: resolve(id, true),
|
|
|
|
// already initiated/required
|
|
init: has(instances, id)
|
|
};
|
|
});
|
|
|
|
each(definitions, function (def, id) {
|
|
|
|
var inv = [];
|
|
each(definitions, function (def2, id2) {
|
|
|
|
if (contains(res[id2].reqs, id)) {
|
|
inv.push(id2);
|
|
}
|
|
});
|
|
|
|
// all inverse dependencies
|
|
res[id].reqd = inv;
|
|
});
|
|
|
|
return res;
|
|
},
|
|
|
|
// ### log
|
|
// Returns a string that displays module dependencies.
|
|
log = function (inv) {
|
|
|
|
var out = '\n';
|
|
|
|
each(state(), function (st, id) {
|
|
|
|
var list = inv ? st.reqd : st.reqs;
|
|
out += (st.init ? '* ' : ' ') + id + ' -> [ ' + list.join(', ') + ' ]\n';
|
|
});
|
|
|
|
return out;
|
|
};
|
|
|
|
|
|
// Register Public API
|
|
// -------------------
|
|
global[name] = {
|
|
define: define,
|
|
require: require,
|
|
state: state,
|
|
log: log
|
|
};
|
|
|
|
// Uncomment to run internal tests.
|
|
/*
|
|
if (global[name.toUpperCase()] === true) {
|
|
global[name.toUpperCase()] = {
|
|
isString: isString,
|
|
isFunction: isFunction,
|
|
isArray: isArray,
|
|
isObject: isObject,
|
|
has: has,
|
|
each: each,
|
|
contains: contains,
|
|
uniq: uniq,
|
|
err: err,
|
|
definitions: definitions,
|
|
instances: instances,
|
|
resolve: resolve
|
|
};
|
|
} // */
|
|
|
|
}(this, 'modulejs'));
|