AwaitDependenciesInitFragment.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const InitFragment = require("../InitFragment");
  7. const RuntimeGlobals = require("../RuntimeGlobals");
  8. const Template = require("../Template");
  9. /** @import { Source } from "webpack-sources" */
  10. /** @import { GenerateContext } from "../Generator" */
  11. /** @typedef {Map<string, string>} Dependencies */
  12. /**
  13. * Represents AwaitDependenciesInitFragment.
  14. * @extends {InitFragment<GenerateContext>}
  15. */
  16. class AwaitDependenciesInitFragment extends InitFragment {
  17. /**
  18. * Creates an instance of AwaitDependenciesInitFragment.
  19. * @param {Dependencies} dependencies maps an import var to an async module that needs to be awaited
  20. * @param {boolean=} generatorLowered module is emitted as a generator, so use `yield` instead of `await`
  21. */
  22. constructor(dependencies, generatorLowered = false) {
  23. super(
  24. undefined,
  25. InitFragment.STAGE_ASYNC_DEPENDENCIES,
  26. 0,
  27. "await-dependencies"
  28. );
  29. /** @type {Dependencies} */
  30. this.dependencies = dependencies;
  31. /** @type {boolean} */
  32. this.generatorLowered = generatorLowered;
  33. }
  34. /**
  35. * Merges another await-dependencies fragment into this fragment.
  36. * @param {AwaitDependenciesInitFragment} other other AwaitDependenciesInitFragment
  37. * @returns {AwaitDependenciesInitFragment} AwaitDependenciesInitFragment
  38. */
  39. merge(other) {
  40. const dependencies = new Map(other.dependencies);
  41. for (const [key, value] of this.dependencies) {
  42. dependencies.set(key, value);
  43. }
  44. return new AwaitDependenciesInitFragment(
  45. dependencies,
  46. this.generatorLowered || other.generatorLowered
  47. );
  48. }
  49. /**
  50. * Returns the source code that will be included as initialization code.
  51. * @param {GenerateContext} context context
  52. * @returns {string | Source | undefined} the source code that will be included as initialization code
  53. */
  54. getContent({ runtimeRequirements, runtimeTemplate }) {
  55. runtimeRequirements.add(RuntimeGlobals.module);
  56. if (this.dependencies.size === 0) {
  57. return "";
  58. }
  59. const importVars = [...this.dependencies.keys()];
  60. const asyncModuleValues = [...this.dependencies.values()].join(", ");
  61. // In a generator-lowered module (no `async`/`await`, but generators) the
  62. // dependency `await` becomes `yield`; the body stays a single scope.
  63. const suspend = this.generatorLowered ? "yield" : "await";
  64. const templateInput = [
  65. `var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([${asyncModuleValues}]);`
  66. ];
  67. if (
  68. this.dependencies.size === 1 ||
  69. !runtimeTemplate.supportsDestructuring()
  70. ) {
  71. templateInput.push(
  72. `var __webpack_async_dependencies_result__ = (__webpack_async_dependencies__.then ? (${suspend} __webpack_async_dependencies__)() : __webpack_async_dependencies__);`
  73. );
  74. for (const [index, importVar] of importVars.entries()) {
  75. templateInput.push(
  76. `${importVar} = __webpack_async_dependencies_result__[${index}];`
  77. );
  78. }
  79. } else {
  80. const importVarsStr = importVars.join(", ");
  81. templateInput.push(
  82. `([${importVarsStr}] = __webpack_async_dependencies__.then ? (${suspend} __webpack_async_dependencies__)() : __webpack_async_dependencies__);`
  83. );
  84. }
  85. templateInput.push("");
  86. return Template.asString(templateInput);
  87. }
  88. }
  89. module.exports = AwaitDependenciesInitFragment;