AsyncModuleRuntimeModule.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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. constructor() {
  11. super("async module");
  12. }
  13. /**
  14. * @returns {string | null} runtime code
  15. */
  16. generate() {
  17. const compilation = /** @type {Compilation} */ (this.compilation);
  18. const { runtimeTemplate } = compilation;
  19. const fn = RuntimeGlobals.asyncModule;
  20. return Template.asString([
  21. 'var webpackQueues = typeof Symbol === "function" ? Symbol("webpack queues") : "__webpack_queues__";',
  22. `var webpackExports = typeof Symbol === "function" ? Symbol("webpack exports") : "${RuntimeGlobals.exports}";`,
  23. 'var webpackError = typeof Symbol === "function" ? Symbol("webpack error") : "__webpack_error__";',
  24. `var resolveQueue = ${runtimeTemplate.basicFunction("queue", [
  25. "if(queue && queue.d < 1) {",
  26. Template.indent([
  27. "queue.d = 1;",
  28. `queue.forEach(${runtimeTemplate.expressionFunction(
  29. "fn.r--",
  30. "fn"
  31. )});`,
  32. `queue.forEach(${runtimeTemplate.expressionFunction(
  33. "fn.r-- ? fn.r++ : fn()",
  34. "fn"
  35. )});`
  36. ]),
  37. "}"
  38. ])}`,
  39. `var wrapDeps = ${runtimeTemplate.returningFunction(
  40. `deps.map(${runtimeTemplate.basicFunction("dep", [
  41. 'if(dep !== null && typeof dep === "object") {',
  42. Template.indent([
  43. "if(dep[webpackQueues]) return dep;",
  44. "if(dep.then) {",
  45. Template.indent([
  46. "var queue = [];",
  47. "queue.d = 0;",
  48. `dep.then(${runtimeTemplate.basicFunction("r", [
  49. "obj[webpackExports] = r;",
  50. "resolveQueue(queue);"
  51. ])}, ${runtimeTemplate.basicFunction("e", [
  52. "obj[webpackError] = e;",
  53. "resolveQueue(queue);"
  54. ])});`,
  55. "var obj = {};",
  56. `obj[webpackQueues] = ${runtimeTemplate.expressionFunction(
  57. `fn(queue)`,
  58. "fn"
  59. )};`,
  60. "return obj;"
  61. ]),
  62. "}"
  63. ]),
  64. "}",
  65. "var ret = {};",
  66. `ret[webpackQueues] = ${runtimeTemplate.emptyFunction()};`,
  67. "ret[webpackExports] = dep;",
  68. "return ret;"
  69. ])})`,
  70. "deps"
  71. )};`,
  72. `${fn} = ${runtimeTemplate.basicFunction("module, body, hasAwait", [
  73. "var queue;",
  74. "hasAwait && ((queue = []).d = -1);",
  75. "var depQueues = new Set();",
  76. "var exports = module.exports;",
  77. "var currentDeps;",
  78. "var outerResolve;",
  79. "var reject;",
  80. `var promise = new Promise(${runtimeTemplate.basicFunction(
  81. "resolve, rej",
  82. ["reject = rej;", "outerResolve = resolve;"]
  83. )});`,
  84. "promise[webpackExports] = exports;",
  85. `promise[webpackQueues] = ${runtimeTemplate.expressionFunction(
  86. `queue && fn(queue), depQueues.forEach(fn), promise["catch"](${runtimeTemplate.emptyFunction()})`,
  87. "fn"
  88. )};`,
  89. "module.exports = promise;",
  90. `body(${runtimeTemplate.basicFunction("deps", [
  91. "currentDeps = wrapDeps(deps);",
  92. "var fn;",
  93. `var getResult = ${runtimeTemplate.returningFunction(
  94. `currentDeps.map(${runtimeTemplate.basicFunction("d", [
  95. "if(d[webpackError]) throw d[webpackError];",
  96. "return d[webpackExports];"
  97. ])})`
  98. )}`,
  99. `var promise = new Promise(${runtimeTemplate.basicFunction(
  100. "resolve",
  101. [
  102. `fn = ${runtimeTemplate.expressionFunction(
  103. "resolve(getResult)",
  104. ""
  105. )};`,
  106. "fn.r = 0;",
  107. `var fnQueue = ${runtimeTemplate.expressionFunction(
  108. "q !== queue && !depQueues.has(q) && (depQueues.add(q), q && !q.d && (fn.r++, q.push(fn)))",
  109. "q"
  110. )};`,
  111. `currentDeps.map(${runtimeTemplate.expressionFunction(
  112. "dep[webpackQueues](fnQueue)",
  113. "dep"
  114. )});`
  115. ]
  116. )});`,
  117. "return fn.r ? promise : getResult();"
  118. ])}, ${runtimeTemplate.expressionFunction(
  119. "(err ? reject(promise[webpackError] = err) : outerResolve(exports)), resolveQueue(queue)",
  120. "err"
  121. )});`,
  122. "queue && queue.d < 0 && (queue.d = 0);"
  123. ])};`
  124. ]);
  125. }
  126. }
  127. module.exports = AsyncModuleRuntimeModule;