AsyncModuleRuntimeModule.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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. class AsyncModuleRuntimeModule extends HelperRuntimeModule {
  9. constructor() {
  10. super("async module");
  11. }
  12. /**
  13. * @returns {string} runtime code
  14. */
  15. generate() {
  16. const { runtimeTemplate } = this.compilation;
  17. const fn = RuntimeGlobals.asyncModule;
  18. return Template.asString([
  19. 'var webpackThen = typeof Symbol === "function" ? Symbol("webpack then") : "__webpack_then__";',
  20. 'var webpackExports = typeof Symbol === "function" ? Symbol("webpack exports") : "__webpack_exports__";',
  21. 'var webpackError = typeof Symbol === "function" ? Symbol("webpack error") : "__webpack_error__";',
  22. `var completeQueue = ${runtimeTemplate.basicFunction("queue", [
  23. "if(queue) {",
  24. Template.indent([
  25. `queue.forEach(${runtimeTemplate.expressionFunction(
  26. "fn.r--",
  27. "fn"
  28. )});`,
  29. `queue.forEach(${runtimeTemplate.expressionFunction(
  30. "fn.r-- ? fn.r++ : fn()",
  31. "fn"
  32. )});`
  33. ]),
  34. "}"
  35. ])}`,
  36. `var completeFunction = ${runtimeTemplate.expressionFunction(
  37. "!--fn.r && fn()",
  38. "fn"
  39. )};`,
  40. `var queueFunction = ${runtimeTemplate.expressionFunction(
  41. "queue ? queue.push(fn) : completeFunction(fn)",
  42. "queue, fn"
  43. )};`,
  44. `var wrapDeps = ${runtimeTemplate.returningFunction(
  45. `deps.map(${runtimeTemplate.basicFunction("dep", [
  46. 'if(dep !== null && typeof dep === "object") {',
  47. Template.indent([
  48. "if(dep[webpackThen]) return dep;",
  49. "if(dep.then) {",
  50. Template.indent([
  51. "var queue = [];",
  52. `dep.then(${runtimeTemplate.basicFunction("r", [
  53. "obj[webpackExports] = r;",
  54. "completeQueue(queue);",
  55. "queue = 0;"
  56. ])}, ${runtimeTemplate.basicFunction("e", [
  57. "obj[webpackError] = e;",
  58. "completeQueue(queue);",
  59. "queue = 0;"
  60. ])});`,
  61. "var obj = {};",
  62. `obj[webpackThen] = ${runtimeTemplate.expressionFunction(
  63. "queueFunction(queue, fn), dep['catch'](reject)",
  64. "fn, reject"
  65. )};`,
  66. "return obj;"
  67. ]),
  68. "}"
  69. ]),
  70. "}",
  71. "var ret = {};",
  72. `ret[webpackThen] = ${runtimeTemplate.expressionFunction(
  73. "completeFunction(fn)",
  74. "fn"
  75. )};`,
  76. "ret[webpackExports] = dep;",
  77. "return ret;"
  78. ])})`,
  79. "deps"
  80. )};`,
  81. `${fn} = ${runtimeTemplate.basicFunction("module, body, hasAwait", [
  82. "var queue = hasAwait && [];",
  83. "var exports = module.exports;",
  84. "var currentDeps;",
  85. "var outerResolve;",
  86. "var reject;",
  87. "var isEvaluating = true;",
  88. "var nested = false;",
  89. `var whenAll = ${runtimeTemplate.basicFunction(
  90. "deps, onResolve, onReject",
  91. [
  92. "if (nested) return;",
  93. "nested = true;",
  94. "onResolve.r += deps.length;",
  95. `deps.map(${runtimeTemplate.expressionFunction(
  96. "dep[webpackThen](onResolve, onReject)",
  97. "dep, i"
  98. )});`,
  99. "nested = false;"
  100. ]
  101. )};`,
  102. `var promise = new Promise(${runtimeTemplate.basicFunction(
  103. "resolve, rej",
  104. [
  105. "reject = rej;",
  106. `outerResolve = ${runtimeTemplate.expressionFunction(
  107. "resolve(exports), completeQueue(queue), queue = 0"
  108. )};`
  109. ]
  110. )});`,
  111. "promise[webpackExports] = exports;",
  112. `promise[webpackThen] = ${runtimeTemplate.basicFunction(
  113. "fn, rejectFn",
  114. [
  115. "if (isEvaluating) { return completeFunction(fn); }",
  116. "if (currentDeps) whenAll(currentDeps, fn, rejectFn);",
  117. "queueFunction(queue, fn);",
  118. "promise['catch'](rejectFn);"
  119. ]
  120. )};`,
  121. "module.exports = promise;",
  122. `body(${runtimeTemplate.basicFunction("deps", [
  123. "currentDeps = wrapDeps(deps);",
  124. "var fn;",
  125. `var getResult = ${runtimeTemplate.returningFunction(
  126. `currentDeps.map(${runtimeTemplate.basicFunction("d", [
  127. "if(d[webpackError]) throw d[webpackError];",
  128. "return d[webpackExports];"
  129. ])})`
  130. )}`,
  131. `var promise = new Promise(${runtimeTemplate.basicFunction(
  132. "resolve, reject",
  133. [
  134. `fn = ${runtimeTemplate.expressionFunction(
  135. "resolve(getResult)"
  136. )};`,
  137. "fn.r = 0;",
  138. "whenAll(currentDeps, fn, reject);"
  139. ]
  140. )});`,
  141. "return fn.r ? promise : getResult();"
  142. ])}, ${runtimeTemplate.expressionFunction(
  143. "err && reject(promise[webpackError] = err), outerResolve()",
  144. "err"
  145. )});`,
  146. "isEvaluating = false;"
  147. ])};`
  148. ]);
  149. }
  150. }
  151. module.exports = AsyncModuleRuntimeModule;