AsyncModuleRuntimeModule.js 6.3 KB

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