Skip to content

Instantly share code, notes, and snippets.

@samba
Last active February 11, 2024 22:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samba/6711258 to your computer and use it in GitHub Desktop.
Save samba/6711258 to your computer and use it in GitHub Desktop.
Simplified AMD-style module framework
/* A lightweight module framework intended to provide (simplified)
* AMD-style module support.
*
* Currently its minified form yields 987 bytes, 577 after gzip compression.
*
* It DOES NOT parse module identifiers as paths (e.g. "/a/b" or "../a").
* It assumes that all module IDs are simple strings, and seeks an exact
* match, without attempting to navigate any hierarchy.
*
* It DOES NOT parse incoming modules as string for require() statements.
* The require() method is completely synchronous; exceptions are thrown when
* modules are require()'d but don't exist.
*
* It DOES NOT support any kind of loading module. It assumes you'll load the
* scripts you need, when you need them. This framework's purpose is simply
* to ensure that modules are run only when their dependencies are registered.
*
*
* It DOES support AMD-style module definition, evaluating depend-
* encies with exact matching of module names, and running the module
* factories when all dependencies have registered.
*
* Without loading support, it's expected that components are concatenated
* via some sort of build script, or loaded independently in your site. It
* also effectively requires the use of module names given in their definition,
* as it doesn't relate filenames as module names.
*
* Suggested format:
*
* define('modname', [ 'dep1', 'dep2' ], function(dep1, dep2, exports){
*
* exports.method = function(){...}
*
* // any return value here will be used instead of exports
* return exports
*
* });
*
*
* See also:
* https://github.com/amdjs/amdjs-api/wiki/AMD
*/
(function(global, undefined){
var counter = 0;
var modules = {};
var queue = [];
var RE_AUTO_MODULES = /^(require|exports|module)$/;
/* Find something in an array (like String.indexOf) */
function _indexOf(elem){
for(var i = 0; i < this.length; i++){
if(this[i] === elem) return i;
}
return -1;
}
function require (name, callback){
if(name in modules){
return modules[ name ];
} else
throw new Error('Unrecognized module: ' + name);
}
function resolve(name, factory, dependencies, cache){
// Module-scope objects
var exports = {}, module = {};
// Scoped names for each module (i.e. auto-populated)
var scope = {'exports': exports, 'module': module, 'require': require};
var deps = [], i = dependencies && dependencies.length;
if(name in modules){
throw new Error('Module already exists: ' + name);
}
while(i--){ // Resolve dependency sequence from cache
if(dependencies[i] in scope)
deps[i] = scope[ dependencies[i] ];
else
deps[i] = cache[ dependencies[i] ];
}
if(!dependencies) // Common-JS style (no dependencies declared)
deps = [ require, exports, module ];
else
deps.push(exports, module);
// Evaulate the module's factory.
var resolved_name = name || counter++;
var result = factory.apply(cache, deps);
if(result === undefined) result = exports;
// Store the result
modules[ resolved_name ] = result;
// Notify waiting modules
setTimeout(function(){
for(var i = 0; i < queue.length; i++){
if(queue[i] && queue[i].call){
queue[i].call(modules, resolved_name, result);
}
}
}, 1);
}
/* Prepare the cache and queue for a new module */
function _module(name, dependencies, factory){
var result;
var queue_index;
var cache = {}; // local stash of resolved dependencies
var i = dependencies && dependencies.length,
required = Number(i) || 0;
while(i--){ /* Collect existing dependencies */
if(RE_AUTO_MODULES.test(dependencies[i])){
required--; // these are automatically populated
}
else if(dependencies[ i ] in modules){
cache[ dependencies[i] ] = modules[ dependencies[i] ];
required--;
}
}
/* No remaining dependencies; resolve now */
if(required === 0){
return resolve(name, factory, dependencies, cache);
}
/* Queued method when waiting for dependencies */
function resolver(depname, value){
/* Ignore modules not required by this one */
if(0 > _indexOf.call(dependencies, depname)){
return false;
}
cache[ depname ] = value;
required--;
if(required === 0){ /* Resolve this module */
resolve(name, factory, dependencies, cache);
queue[ queue_index ] = null; // de-queue
}
};
resolver.module = name; // for debugging, really.
/* Enqueue this method for new module definitions. */
return (queue_index = queue.push(resolver) -1);
}
function define(){ /* the public define() interface */
var i = 0; // argument sentinel for flexible argument structures (as per AMD standard)
var args = arguments;
var id, deps, factory;
if(id = (typeof args[0] === 'string') && args[0]) i++;
if(deps = (args[i] && args[i].length && !args[i].call) && args[i]) i++;
if(factory = (args[i] && args[i].call) && args[i])
_module(id, deps, factory);
}
/* Expose public methods */
global['define'] = define;
global['require'] = require;
}(window, void 0));
// vim: set nowrap tabstop=2 shiftwidth=2 softtabstop=0 expandtab textwidth=0 filetype=javascript foldmethod=indent foldcolumn=4
(function(q,t){function u(b){for(var a=0;a<this.length;a++)if(this[a]===b)return a;return-1}function p(b){if(b in k)return k[b];throw Error("Unrecognized module: "+b);}function r(b,a,c,e){var f={},h={},d={exports:f,module:h,require:p},g=[],m=c&&c.length;if(b in k)throw Error("Module already exists: "+b);for(;m--;)g[m]=c[m]in d?d[c[m]]:e[c[m]];c?g.push(f,h):g=[p,f,h];var s=b||v++,n=a.apply(e,g);n===t&&(n=f);k[s]=n;setTimeout(function(){for(var a=0;a<l.length;a++)l[a]&&l[a].call&&l[a].call(k,s,n)},
1)}function w(b,a,c){function e(d,e){if(0>u.call(a,d))return!1;h[d]=e;g--;0===g&&(r(b,c,a,h),l[f]=null)}for(var f,h={},d=a&&a.length,g=Number(d)||0;d--;)x.test(a[d])?g--:a[d]in k&&(h[a[d]]=k[a[d]],g--);0===g?r(b,c,a,h):(e.a=b,f=l.push(e)-1)}var v=0,k={},l=[],x=/^(require|exports|module)$/;q.define=function(){var b=0,a=arguments,c,e,f;(c="string"===typeof a[0]&&a[0])&&b++;(e=a[b]&&a[b].length&&!a[b].call&&a[b])&&b++;(f=a[b]&&a[b].call&&a[b])&&w(c,e,f)};q.require=p})(window,void 0);
/* Statistics: {"compressedGzipSize": 577, "originalGzipSize": 2170, "compressedSize": 987, "originalSize": 5378, "compileTime": 0} */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment