mini-require.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /* -*- Mode: js; js-indent-level: 2; -*- */
  2. /*
  3. * Copyright 2011 Mozilla Foundation and contributors
  4. * Licensed under the New BSD license. See LICENSE or:
  5. * http://opensource.org/licenses/BSD-3-Clause
  6. */
  7. /**
  8. * Define a module along with a payload.
  9. * @param {string} moduleName Name for the payload
  10. * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec
  11. * @param {function} payload Function with (require, exports, module) params
  12. */
  13. function define(moduleName, deps, payload) {
  14. if (typeof moduleName != "string") {
  15. throw new TypeError('Expected string, got: ' + moduleName);
  16. }
  17. if (arguments.length == 2) {
  18. payload = deps;
  19. }
  20. if (moduleName in define.modules) {
  21. throw new Error("Module already defined: " + moduleName);
  22. }
  23. define.modules[moduleName] = payload;
  24. };
  25. /**
  26. * The global store of un-instantiated modules
  27. */
  28. define.modules = {};
  29. /**
  30. * We invoke require() in the context of a Domain so we can have multiple
  31. * sets of modules running separate from each other.
  32. * This contrasts with JSMs which are singletons, Domains allows us to
  33. * optionally load a CommonJS module twice with separate data each time.
  34. * Perhaps you want 2 command lines with a different set of commands in each,
  35. * for example.
  36. */
  37. function Domain() {
  38. this.modules = {};
  39. this._currentModule = null;
  40. }
  41. (function () {
  42. /**
  43. * Lookup module names and resolve them by calling the definition function if
  44. * needed.
  45. * There are 2 ways to call this, either with an array of dependencies and a
  46. * callback to call when the dependencies are found (which can happen
  47. * asynchronously in an in-page context) or with a single string an no callback
  48. * where the dependency is resolved synchronously and returned.
  49. * The API is designed to be compatible with the CommonJS AMD spec and
  50. * RequireJS.
  51. * @param {string[]|string} deps A name, or names for the payload
  52. * @param {function|undefined} callback Function to call when the dependencies
  53. * are resolved
  54. * @return {undefined|object} The module required or undefined for
  55. * array/callback method
  56. */
  57. Domain.prototype.require = function(deps, callback) {
  58. if (Array.isArray(deps)) {
  59. var params = deps.map(function(dep) {
  60. return this.lookup(dep);
  61. }, this);
  62. if (callback) {
  63. callback.apply(null, params);
  64. }
  65. return undefined;
  66. }
  67. else {
  68. return this.lookup(deps);
  69. }
  70. };
  71. function normalize(path) {
  72. var bits = path.split('/');
  73. var i = 1;
  74. while (i < bits.length) {
  75. if (bits[i] === '..') {
  76. bits.splice(i-1, 1);
  77. } else if (bits[i] === '.') {
  78. bits.splice(i, 1);
  79. } else {
  80. i++;
  81. }
  82. }
  83. return bits.join('/');
  84. }
  85. function join(a, b) {
  86. a = a.trim();
  87. b = b.trim();
  88. if (/^\//.test(b)) {
  89. return b;
  90. } else {
  91. return a.replace(/\/*$/, '/') + b;
  92. }
  93. }
  94. function dirname(path) {
  95. var bits = path.split('/');
  96. bits.pop();
  97. return bits.join('/');
  98. }
  99. /**
  100. * Lookup module names and resolve them by calling the definition function if
  101. * needed.
  102. * @param {string} moduleName A name for the payload to lookup
  103. * @return {object} The module specified by aModuleName or null if not found.
  104. */
  105. Domain.prototype.lookup = function(moduleName) {
  106. if (/^\./.test(moduleName)) {
  107. moduleName = normalize(join(dirname(this._currentModule), moduleName));
  108. }
  109. if (moduleName in this.modules) {
  110. var module = this.modules[moduleName];
  111. return module;
  112. }
  113. if (!(moduleName in define.modules)) {
  114. throw new Error("Module not defined: " + moduleName);
  115. }
  116. var module = define.modules[moduleName];
  117. if (typeof module == "function") {
  118. var exports = {};
  119. var previousModule = this._currentModule;
  120. this._currentModule = moduleName;
  121. module(this.require.bind(this), exports, { id: moduleName, uri: "" });
  122. this._currentModule = previousModule;
  123. module = exports;
  124. }
  125. // cache the resulting module object for next time
  126. this.modules[moduleName] = module;
  127. return module;
  128. };
  129. }());
  130. define.Domain = Domain;
  131. define.globalDomain = new Domain();
  132. var require = define.globalDomain.require.bind(define.globalDomain);