require.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. //
  2. // This file is part of //\ Tarp.
  3. //
  4. // Copyright (C) 2013-2018 Torben Haase <https://pixelsvsbytes.com>
  5. //
  6. // Tarp is free software: you can redistribute it and/or modify it under the
  7. // terms of the GNU Lesser General Public License as published by the Free
  8. // Software Foundation, either version 3 of the License, or (at your option) any
  9. // later version.
  10. //
  11. // Tarp is distributed in the hope that it will be useful, but WITHOUT ANY
  12. // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  13. // A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  14. // details.You should have received a copy of the GNU Lesser General Public
  15. // License along with Tarp. If not, see <http://www.gnu.org/licenses/>.
  16. //
  17. ////////////////////////////////////////////////////////////////////////////////
  18. // NOTE The load parameter points to the function, which prepares the
  19. // environment for each module and runs its code. Scroll down to the end of
  20. // the file to see the function definition.
  21. (function () {
  22. "use strict";
  23. var cache, root;
  24. cache = Object.create(null);
  25. function getRoot() {
  26. var config = (self.Tarp && self.Tarp.require && self.Tarp.require.config) || {};
  27. root = {
  28. children: [],
  29. paths: config.paths || [(new URL("./node_modules/", location.href)).href],
  30. uri: config.uri || location.href
  31. };
  32. return root;
  33. }
  34. function load(id, pwd, asyn) {
  35. var matches, href, cached, request;
  36. // NOTE resolve href from id
  37. matches = id.match(/^((\.)?.*\/|)(.[^.]*|)(\..*|)$/);
  38. href = (new URL(
  39. matches[1] + matches[3] + (matches[3] && (matches[4] || ".js")),
  40. matches[2] ? pwd : root.paths[0] // TODO Can we get rid of this check with more intelligent pwd setting in the engine?
  41. )).href;
  42. // NOTE create cache item if required
  43. cached = cache[href] = cache[href] || {
  44. e: undefined, // error
  45. m: undefined, // module
  46. p: undefined, // promise
  47. r: undefined, // request
  48. s: undefined, // source
  49. t: undefined, // type
  50. u: href, // url
  51. };
  52. if (!cached.p) {
  53. cached.p = new Promise(function (res, rej) {
  54. request = cached.r = new XMLHttpRequest();
  55. request.onload = request.onerror = request.ontimeout = function () {
  56. var tmp, done, pattern, match, loading = 0;
  57. // `request` might have been changed by line 60ff
  58. if (request = cached.r) {
  59. cached.r = null;
  60. if ((request.status > 99) && ((href = request.responseURL) != cached.u)) {
  61. if (cache[href]) {
  62. cached = cache[cached.u] = cache[href];
  63. cached.p.then(res, rej);
  64. // NOTE Replace pending request of actual module with the already completed request and abort the
  65. // pending request.
  66. if (cached.r) {
  67. tmp = cached.r;
  68. cached.r = request;
  69. tmp.abort();
  70. tmp.onload();
  71. }
  72. return;
  73. }
  74. else {
  75. cache[href] = cached;
  76. }
  77. }
  78. if ((request.status > 99) && (request.status < 400)) {
  79. cached.s = request.responseText;
  80. cached.t = request.getResponseHeader("Content-Type");
  81. done = function () {
  82. if (--loading < 0) res(cached);
  83. };
  84. // NOTE Pre-load submodules if the request is asynchronous (timeout > 0).
  85. if (request.timeout) {
  86. // TODO Write a real parser that returns all modules that are preloadable
  87. pattern = /require(?:\.resolve)?\((?:"((?:[^"\\]|\\.)+)"|'((?:[^'\\]|\\.)+)')\)/g;
  88. while ((match = pattern.exec(cached.s)) !== null) {
  89. // NOTE Only add modules to the loading-queue that are still pending
  90. if ((tmp = load(match[1] || match[2], href, true)).r) {
  91. loading++;
  92. tmp.p.then(done, done);
  93. }
  94. }
  95. }
  96. done();
  97. }
  98. else {
  99. rej(cached.e = new Error(href + " " + request.status));
  100. }
  101. }
  102. };
  103. });
  104. }
  105. // NOTE `request` is only defined if the module is requested for the first time.
  106. if (request = request || (!asyn && cached.r)) {
  107. try {
  108. request.abort();
  109. request.timeout = asyn ? 10000 : 0;
  110. request.open("GET", href, asyn);
  111. request.send();
  112. }
  113. catch (e) {
  114. request.onerror();
  115. }
  116. }
  117. if (cached.e)
  118. throw cached.e;
  119. return cached;
  120. }
  121. function evaluate(cached, parent) {
  122. var module;
  123. if (!cached.m) {
  124. module = cached.m = {
  125. children: new Array(),
  126. exports: Object.create(null),
  127. filename: cached.u,
  128. id: cached.u,
  129. loaded: false,
  130. parent: parent,
  131. paths: parent.paths.slice(),
  132. require: undefined,
  133. uri: cached.u
  134. },
  135. module.require = factory(module);
  136. parent.children.push(module);
  137. if (cached.t == "application/json")
  138. module.exports = JSON.parse(cached.s);
  139. else
  140. (new Function(
  141. "exports,require,module,__filename,__dirname",
  142. cached.s + "\n//# sourceURL=" + module.uri
  143. ))(module.exports, module.require, module, module.uri, module.uri.match(/.*\//)[0]);
  144. module.loaded = true;
  145. }
  146. return cached.m;
  147. }
  148. function factory(parent) {
  149. function requireEngine(mode, id, asyn) {
  150. parent = parent === -1 ? getRoot() : parent;
  151. function afterLoad(cached) {
  152. var regex = /package\.json$/;
  153. if (regex.test(cached.u) && !regex.test(id)) {
  154. parent = evaluate(cached, parent);
  155. return requireEngine(mode, parent.exports.main, asyn);
  156. }
  157. else if (mode === 1)
  158. return cached.u;
  159. else if (mode === 2)
  160. return [id[0] === "." ? parent.uri.match(/.*\//)[0] : root.uri]; // TODO Can this be cleaned up?
  161. else
  162. return evaluate(cached, parent).exports;
  163. }
  164. return asyn ?
  165. new Promise(function (res, rej) {
  166. load(id, parent.uri, asyn).p.then(afterLoad).then(res, rej);
  167. }) :
  168. afterLoad(load(id, parent.uri, asyn));
  169. }
  170. var require = requireEngine.bind(undefined, 0);
  171. require.resolve = requireEngine.bind(require, 1);
  172. require.resolve.paths = requireEngine.bind(require.resolve, 2);
  173. return require;
  174. }
  175. (self.Tarp = self.Tarp || {}).require = factory(-1);
  176. })();