AsyncModuleRuntimeModule.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. */
  4. "use strict";
  5. const RuntimeGlobals = require("../RuntimeGlobals");
  6. const Template = require("../Template");
  7. const HelperRuntimeModule = require("./HelperRuntimeModule");
  8. /** @typedef {import("../Compilation")} Compilation */
  9. class AsyncModuleRuntimeModule extends HelperRuntimeModule {
  10. /**
  11. * @param {boolean=} deferInterop if defer import is used.
  12. */
  13. constructor(deferInterop = false) {
  14. super("async module");
  15. this._deferInterop = deferInterop;
  16. }
  17. /**
  18. * @returns {string | null} runtime code
  19. */
  20. generate() {
  21. const compilation = /** @type {Compilation} */ (this.compilation);
  22. const { runtimeTemplate } = compilation;
  23. const fn = RuntimeGlobals.asyncModule;
  24. const defer = this._deferInterop;
  25. return Template.asString([
  26. 'var hasSymbol = typeof Symbol === "function";',
  27. 'var webpackQueues = hasSymbol ? Symbol("webpack queues") : "__webpack_queues__";',
  28. `var webpackExports = ${
  29. defer ? `${RuntimeGlobals.asyncModuleExportSymbol}= ` : ""
  30. }hasSymbol ? Symbol("webpack exports") : "${RuntimeGlobals.exports}";`,
  31. 'var webpackError = hasSymbol ? Symbol("webpack error") : "__webpack_error__";',
  32. defer
  33. ? `var webpackDone = ${RuntimeGlobals.asyncModuleDoneSymbol} = hasSymbol ? Symbol("webpack done") : "__webpack_done__";`
  34. : "",
  35. defer
  36. ? `var webpackDefer = ${RuntimeGlobals.makeDeferredNamespaceObjectSymbol} = hasSymbol ? Symbol("webpack defer") : "__webpack_defer__";`
  37. : "",
  38. `var resolveQueue = ${runtimeTemplate.basicFunction("queue", [
  39. "if(queue && queue.d < 1) {",
  40. Template.indent([
  41. "queue.d = 1;",
  42. `queue.forEach(${runtimeTemplate.expressionFunction(
  43. "fn.r--",
  44. "fn"
  45. )});`,
  46. `queue.forEach(${runtimeTemplate.expressionFunction(
  47. "fn.r-- ? fn.r++ : fn()",
  48. "fn"
  49. )});`
  50. ]),
  51. "}"
  52. ])}`,
  53. `var wrapDeps = ${runtimeTemplate.returningFunction(
  54. `deps.map(${runtimeTemplate.basicFunction("dep", [
  55. 'if(dep !== null && typeof dep === "object") {',
  56. Template.indent([
  57. defer
  58. ? Template.asString([
  59. "if(!dep[webpackQueues] && dep[webpackDefer]) {",
  60. Template.indent([
  61. "var asyncDeps = dep[webpackDefer];",
  62. `var hasUnresolvedAsyncSubgraph = asyncDeps.some(${runtimeTemplate.basicFunction(
  63. "id",
  64. [
  65. "var cache = __webpack_module_cache__[id];",
  66. "return !cache || cache[webpackDone] === false;"
  67. ]
  68. )});`,
  69. "if (hasUnresolvedAsyncSubgraph) {",
  70. Template.indent([
  71. "var d = dep;",
  72. "dep = {",
  73. Template.indent([
  74. "then(callback) {",
  75. Template.indent([
  76. "Promise.all(asyncDeps.map(__webpack_require__))",
  77. `.then(${runtimeTemplate.returningFunction(
  78. "callback(d)"
  79. )});`
  80. ]),
  81. "}"
  82. ]),
  83. "};"
  84. ]),
  85. "} else return dep;"
  86. ]),
  87. "}"
  88. ])
  89. : "",
  90. "if(dep[webpackQueues]) return dep;",
  91. "if(dep.then) {",
  92. Template.indent([
  93. "var queue = [];",
  94. "queue.d = 0;",
  95. `dep.then(${runtimeTemplate.basicFunction("r", [
  96. "obj[webpackExports] = r;",
  97. "resolveQueue(queue);"
  98. ])}, ${runtimeTemplate.basicFunction("e", [
  99. "obj[webpackError] = e;",
  100. "resolveQueue(queue);"
  101. ])});`,
  102. "var obj = {};",
  103. defer ? "obj[webpackDefer] = false;" : "",
  104. `obj[webpackQueues] = ${runtimeTemplate.expressionFunction(
  105. "fn(queue)",
  106. "fn"
  107. )};`,
  108. "return obj;"
  109. ]),
  110. "}"
  111. ]),
  112. "}",
  113. "var ret = {};",
  114. `ret[webpackQueues] = ${runtimeTemplate.emptyFunction()};`,
  115. "ret[webpackExports] = dep;",
  116. "return ret;"
  117. ])})`,
  118. "deps"
  119. )};`,
  120. `${fn} = ${runtimeTemplate.basicFunction("module, body, hasAwait", [
  121. "var queue;",
  122. "hasAwait && ((queue = []).d = -1);",
  123. "var depQueues = new Set();",
  124. "var exports = module.exports;",
  125. "var currentDeps;",
  126. "var outerResolve;",
  127. "var reject;",
  128. `var promise = new Promise(${runtimeTemplate.basicFunction(
  129. "resolve, rej",
  130. ["reject = rej;", "outerResolve = resolve;"]
  131. )});`,
  132. "promise[webpackExports] = exports;",
  133. `promise[webpackQueues] = ${runtimeTemplate.expressionFunction(
  134. `queue && fn(queue), depQueues.forEach(fn), promise["catch"](${runtimeTemplate.emptyFunction()})`,
  135. "fn"
  136. )};`,
  137. "module.exports = promise;",
  138. `var handle = ${runtimeTemplate.basicFunction("deps", [
  139. "currentDeps = wrapDeps(deps);",
  140. "var fn;",
  141. `var getResult = ${runtimeTemplate.returningFunction(
  142. `currentDeps.map(${runtimeTemplate.basicFunction("d", [
  143. defer ? "if(d[webpackDefer]) return d;" : "",
  144. "if(d[webpackError]) throw d[webpackError];",
  145. "return d[webpackExports];"
  146. ])})`
  147. )}`,
  148. `var promise = new Promise(${runtimeTemplate.basicFunction(
  149. "resolve",
  150. [
  151. `fn = ${runtimeTemplate.expressionFunction(
  152. "resolve(getResult)",
  153. ""
  154. )};`,
  155. "fn.r = 0;",
  156. `var fnQueue = ${runtimeTemplate.expressionFunction(
  157. "q !== queue && !depQueues.has(q) && (depQueues.add(q), q && !q.d && (fn.r++, q.push(fn)))",
  158. "q"
  159. )};`,
  160. `currentDeps.map(${runtimeTemplate.expressionFunction(
  161. `${
  162. defer ? "dep[webpackDefer]||" : ""
  163. }dep[webpackQueues](fnQueue)`,
  164. "dep"
  165. )});`
  166. ]
  167. )});`,
  168. "return fn.r ? promise : getResult();"
  169. ])}`,
  170. `var done = ${runtimeTemplate.expressionFunction(
  171. `(err ? reject(promise[webpackError] = err) : outerResolve(exports)), resolveQueue(queue)${
  172. defer ? ", promise[webpackDone] = true" : ""
  173. }`,
  174. "err"
  175. )}`,
  176. "body(handle, done);",
  177. "queue && queue.d < 0 && (queue.d = 0);"
  178. ])};`
  179. ]);
  180. }
  181. }
  182. module.exports = AsyncModuleRuntimeModule;