Ctrl K
ComunidadGuías…

extensions/web-base/www/amdimpl.js

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/*
 * Asynchronous Module Definition (AMD) API implementation for JLS.
 * The following code creates a 'require' function to load modules.
 * See https://github.com/amdjs/amdjs-api
 */
(function() {
  /* Helper functions */
  function extension(path) {
    var index = path.lastIndexOf('.');
    if (index !== -1) {
      var slashIndex = path.lastIndexOf('/');
      if (index > slashIndex) {
        return path.substring(index + 1);
      }
    }
    return '';
  }
  function basename(path) {
    var index = path.lastIndexOf('/');
    return index === -1 ? path : path.substring(index + 1);
  }
  function dirname(path) {
    var index = path.lastIndexOf('/');
    return index === -1 ? '' : path.substring(0, index);
  }
  function endsWith(value, search) {
    return value.substring(value.length - search.length) === search;
  }
  function startsWith(value, search) {
    return value.substring(0, search.length) === search;
  }
  function concatPath(a, b) {
    var pathItems = b.split('/');
    if ((a !== '.') && ((pathItems[0] === '.') || (pathItems[0] === '..'))) {
      pathItems = a.split('/').concat(pathItems);
    }
    for (var i = 0; i < pathItems.length; i++) {
      var pathItem = pathItems[i];
      if ((pathItem === '.') || (pathItem === '')) {
        pathItems.splice(i, 1);
        i--;
      } else if ((i > 0) && (pathItem === '..')) {
        pathItems.splice(i - 1, 2);
        i -= 2;
      }
    }
    var path = pathItems.join('/');
    if (startsWith(b, '/')) {
      path = '/' + path;
    }
    if (endsWith(b, '/')) {
      path = path + '/';
    }
    return path;
  }
  function basemodule(path) {
    var index = path.indexOf('$');
    return index === -1 ? path : path.substring(0, index);
  }
  function submodule(module, path) {
    if (typeof path !== 'string') {
      return module;
    }
    var index = path.indexOf('$');
    if (index === -1) {
      return module;
    }
    var subpath = path.substring(index + 1);
    // TODO handle sub sub...
    return module[subpath];
  }
  /* Miscellaneous functions */
  var warn, log, debug, loadModule;
  log = debug = warn = function(msg) {};
  var previousDefine = undefined;
  loadModule = function(path, callback, sync, prefix, suffix) {};
  var fullyQualifiedRequire, createRequire, fullyQualifiedDefine;
  /* The cache is a map containing the defined module by absolute path (module identifier) */
  var cache = {};
  /* The AMD specific define entry */
  var amd = {
      multiversion: true
  };
  /*  */
  var CacheEntry = function(path, sync, module) {
    this.path = path || null;
    this.module = module || undefined;
    this.exports = null;
    this.sync = sync || false;
    this.paths = null;
    this.callback = null;
    this.defined = false;
    this.loading = false;
    this.dependencies = [];
    this.count = 0;
    this.waiters = [];
    if (path) {
      cache[path] = this;
    }
    log('CacheEntry("' + path + '", ' + sync + ', ' + module + ')');
  };
  CacheEntry.prototype.declare = function(paths, callback) {
    log('declare([' + paths + '], ...) "' + this.path + '"');
    this.paths = paths || null;
    this.callback = callback || null;
  };
  CacheEntry.prototype.onDefined = function(module) {
    log('onDefined(...) "' + this.path + '"');
    this.module = module || null;
    if ((this.exports !== null) && (typeof this.exports !== 'undefined')) {
      var singleKey = null;
      for (var k in this.exports) {
        if (singleKey === null) {
          singleKey = k;
        } else {
          singleKey = null;
          break;
        }
      }
      if (singleKey === null) {
        this.module = this.exports;
      } else {
        this.module = this.exports[singleKey];
      }
    }
    // Play dependencies
    for (var index = 0; index < this.waiters.length; index++) {
      this.waiters[index].notify(this);
    }
    // TODO Cleanup dependencies...
    this.waiters = [];
  };
  CacheEntry.prototype.onLoaded = function(fnOrContent, err) {
    var t = typeof fnOrContent;
    debug('onLoaded(' + t + ', ' + err + ') "' + this.path + '"');
    var m = null;
    if (err) {
      warn('Exception raised while loading "' + this.path + '": ' + err);
    } else {
      var self = this;
      if (t === 'function') {
        try {
          /* Creates a define function suitable for this module */
          var defined = false;
          var defineFn = function(id, dependencies, factory) {
            if (typeof id === 'function') {
              factory = id;
              dependencies = null;
              id = undefined;
            } else if (typeof dependencies === 'function') {
              factory = dependencies;
              dependencies = id;
              id = undefined;
            }
            fullyQualifiedRequire(self.path, dependencies, factory, self.sync);
            defined = true;
          };
          m = fnOrContent(defineFn);
          if (defined) {
            return;
          }
        } catch (e) {
          warn('Exception raised while evaluating "' + this.path + '": ' + e);
        }
      } else if ((t === 'string') || (t === 'object')) {
        m = fnOrContent;
      } else {
        warn('Invalid argument while loading "' + this.path + '" (' + t + ')');
      }
    }
    if (typeof m === 'object' && typeof m.then === 'function') {
      m.then(function(n) {
        self.onDefined(n);
      }, function(e) {
        warn('Exception raised while loading "' + self.path + '": ' + e);
        self.onDefined(null);
      });
    } else {
      this.onDefined(m);
    }
  };
  CacheEntry.prototype.load = function() {
    debug('load() "' + this.path + '"');
    var self = this;
    var path = this.path;
    var ext = extension(path);
    if (ext === '' && !endsWith(path, '/')) {
      path += '.js';
    }
    this.loading = true;
    loadModule(path, function(fnOrContent, err) {
      self.onLoaded.call(self, fnOrContent, err);
    }, this.sync, '(function() { return function(define) { ', ' }; })();');
  };
  CacheEntry.prototype.notify = function(entry) {
    debug('notify("' + entry.path + '") "' + this.path + '"');
    for (var index = 0; index < this.paths.length; index++) {
      var path = basemodule(this.paths[index]);
      if (path === entry.path) {
        this.setDependency(index, entry.module);
        break;
      }
    }
  };
  CacheEntry.prototype.isDependent = function(entry) {
    debug('isDependent("' + entry.path + '") "' + this.path + '"');
    if (entry.path === null) {
      return false;
    }
    for (var index = 0; index < this.waiters.length; index++) {
      var waiter = this.waiters[index];
      if ((waiter.path !== null) && ((waiter.path === entry.path) || (waiter.isDependent(entry)))) {
        return true;
      }
    }
    return false;
  };
  CacheEntry.prototype.wait = function(entry) {
    debug('wait("' + entry.path + '") "' + this.path + '"');
    if (this.isDependent(entry)) {
      throw 'Cyclic dependency detected between ' + this.path + ' and ' + entry.path;
    }
    entry.waiters.push(this);
  };
  CacheEntry.prototype.isLoading = function() {
    return this.loading;
  };
  CacheEntry.prototype.isLoaded = function() {
    return typeof this.module !== 'undefined';
  };
  CacheEntry.prototype.isModule = function() {
    return this.path !== null;
  };
  CacheEntry.prototype.isDeclared = function() {
    return (this.callback !== null) || this.isLoaded();
  };
  CacheEntry.prototype.setDependency = function(index, value) {
    var path = this.paths[index];
    this.dependencies[index] = submodule(value, path);
    this.count++;
    debug('setDependency(' + index + ', ...) "' + this.path + '" ' + this.count + '/' + this.paths.length);
    this.wakeup();
  };
  CacheEntry.prototype.wakeup = function() {
    if ((this.callback) && ((this.paths === null) || (this.count === this.paths.length))) {
      debug('wakeup() "' + this.path + '"');
      var fn = this.callback;
      var dep = this.dependencies;
      this.paths = null;
      this.callback = null;
      this.dependencies = null;
      var module = fn.apply(null, dep);
      this.onDefined(this.isModule() ? module : null);
    }
  };
  /* Base require/define function that use a fully qualified module id */
  fullyQualifiedRequire = function(moduleId, ids, callback, sync, dl) {
    if (typeof callback !== 'function') {
      throw 'Invalid arguments';
    }
    sync = (typeof sync === 'boolean') ? sync : false;
    dl = (typeof dl === 'boolean') ? dl : false;
    var basepath = dirname(moduleId || '');
    var name = basename(moduleId || '');
    var paths = [];
    if ((ids !== null) && ('length' in ids)) {
      for (var index = 0; index < ids.length; index++) {
        var id = ids[index];
        if (id === '.') {
          id = './main';
        }
        paths.push(concatPath(basepath, id));
      }
    }
    if (name === '?') {
      moduleId = null;
    }
    var entry;
    if (moduleId) {
      if (moduleId in cache) {
        // Check sync ?
        entry = cache[moduleId];
      } else {
        entry = new CacheEntry(moduleId, sync, undefined);
      }
      entry.defined = true;
    } else {
      entry = new CacheEntry(null, sync, undefined);
    }
    entry.declare(paths, callback);
    for (var index = 0; index < paths.length; index++) {
      var path = basemodule(paths[index]);
      var depEntry;
      try {
        if (path === 'require') {
          entry.setDependency(index, createRequire(basepath));
        } else if (path === 'requirePath') {
          entry.setDependency(index, basepath);
        } else if (path === 'exports') {
          entry.setDependency(index, entry.exports = {});
        } else if (path in cache) {
          depEntry = cache[path];
          if (depEntry.isLoaded()) {
            entry.setDependency(index, depEntry.module);
          } else {
            // TODO Check sync
            entry.wait(depEntry);
            if (! (dl || depEntry.isLoading())) {
              depEntry.load();
            }
          }
        } else {
          depEntry = new CacheEntry(path, sync);
          entry.wait(depEntry);
          if (! dl) {
            depEntry.load();
          }
        }
      }
      catch (e) {
        warn('Exception raised: ' + e);
        //debug(e.name + ': ' + e.message);
        entry.setDependency(index, null);
      }
    }
    entry.wakeup();
  };
  /* Returns a require function suitable for a specific path */
  createRequire = function(path) {
    return function(ids, callback) {
      var async = true;
      var rmod = null;
      if (typeof ids === 'string') {
        ids = [ids];
      }
      if (typeof callback === 'undefined') {
        async = false;
        callback = function(module) {
          if ((typeof module === 'undefined') || (module === null)) {
            warn('Fail to require "' + ids[0] + '"');
          }
          rmod = module;
        };
      }
      fullyQualifiedRequire(path + '/?', ids, callback, !async);
      return async ? undefined : rmod;
    };
  };
  /* Define function that use a fully qualified module id */
  fullyQualifiedDefine = function(id, dependencies, factory) {
    log('define(' + id + ')');
    fullyQualifiedRequire(id, dependencies, factory, true, true);
  };
  // Populate default cache values
  new CacheEntry('_AMD', true, {
    cache : cache,
    setLogFunction: function(fn, level) {
      switch(level) {
      default:
      case 'warn': warn = fn; break;
      case 'log': log = fn; break;
      case 'debug': debug = fn; break;
      case 'all': log = debug = warn = fn; break;
      }
    },
    enableDefine: function() {
      log('enableDefine()');
      previousDefine = (typeof define !== 'undefined') ? define : undefined;
      // global define function
      define = fullyQualifiedDefine;
    },
    disableDefine: function() {
      log('disableDefine()');
      define = previousDefine;
    },
    setLoadModuleFunction: function(fn) {
      loadModule = fn;
    },
    setEvalScriptFunction: function(fn) {
      loadModule = fn;
    },
    getModuleId: function(obj) {
      for (var id in cache) {
        if (cache[id].module === obj.constructor) {
          return id;
        }
      }
      return null;
    },
    status: function() {
      log('AMD Cache status:');
      var lm = [], wm = [];
      for (var path in cache) {
        (cache[path].module ? lm : wm).push(path);
      }
      lm.sort(); wm.sort();
      for (var i = 0; i < lm.length; i++) {
        log(' "' + lm[i] + '" loaded');
      }
      for (var i = 0; i < wm.length; i++) {
        var path = wm[i];
        var ce = cache[path];
        var paths = '';
        if (ce.paths !== null) {
          for (var j = 0; j < ce.paths.length; j++) {
            paths += (paths === '' ? '' : ', ') + (ce.dependencies[j] !== null ? '!' : '') + ce.paths[j];
          }
        }
        log(' "' + path + '"(' + paths + ') ' + ce.waiters.length + ' waiting callback(s)');
      }
    },
    lazyRequire : function(ids, callback) {
      if (arguments.length < 2) {
        return;
      }
      fullyQualifiedRequire('/?', ids, callback, true, true);
    },
    dirname : dirname,
    basename : basename,
    concatPath : concatPath,
    createRequire : createRequire,
    fullyQualifiedDefine : fullyQualifiedDefine,
    fullyQualifiedRequire : fullyQualifiedRequire
  });
  // global require function
  require = createRequire('');
})();