TopLevelAwaitDependency.js 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. */
  4. "use strict";
  5. const isGeneratorLowered = require("../async-modules/isGeneratorLowered");
  6. const makeSerializable = require("../util/makeSerializable");
  7. const NullDependency = require("./NullDependency");
  8. /** @import { ReplaceSource } from "webpack-sources" */
  9. /** @import Dependency from "../Dependency" */
  10. /** @import { DependencyTemplateContext } from "../DependencyTemplate" */
  11. /** @import Module from "../Module" */
  12. /** @import { Range } from "../javascript/JavascriptParser" */
  13. /**
  14. * @import {
  15. * ObjectDeserializerContext,
  16. * ObjectSerializerContext
  17. * } from "../serialization/ObjectMiddleware"
  18. */
  19. /**
  20. * Marks a top-level `await` expression so it can be rewritten to `(yield …)`
  21. * when the module is lowered to a generator (target without `async`/`await`).
  22. */
  23. class TopLevelAwaitDependency extends NullDependency {
  24. /**
  25. * @param {Range} range range of the whole `await` expression
  26. * @param {Range} argumentRange range of the awaited argument
  27. */
  28. constructor(range, argumentRange) {
  29. super();
  30. /** @type {Range} */
  31. this.range = range;
  32. /** @type {Range} */
  33. this.argumentRange = argumentRange;
  34. }
  35. /**
  36. * Serializes this instance into the provided serializer context.
  37. * @param {ObjectSerializerContext} context context
  38. */
  39. serialize(context) {
  40. const { write } = context;
  41. write(this.range);
  42. write(this.argumentRange);
  43. super.serialize(context);
  44. }
  45. /**
  46. * Restores this instance from the provided deserializer context.
  47. * @param {ObjectDeserializerContext} context context
  48. */
  49. deserialize(context) {
  50. const { read } = context;
  51. this.range = read();
  52. this.argumentRange = read();
  53. super.deserialize(context);
  54. }
  55. }
  56. makeSerializable(
  57. TopLevelAwaitDependency,
  58. "webpack/lib/dependencies/TopLevelAwaitDependency"
  59. );
  60. TopLevelAwaitDependency.Template = class TopLevelAwaitDependencyTemplate extends (
  61. NullDependency.Template
  62. ) {
  63. /**
  64. * Applies the plugin by registering its hooks on the compiler.
  65. * @param {Dependency} dependency the dependency for which the template should be applied
  66. * @param {ReplaceSource} source the current replace source which can be modified
  67. * @param {DependencyTemplateContext} templateContext the context object
  68. * @returns {void}
  69. */
  70. apply(dependency, source, { module, moduleGraph, runtimeTemplate }) {
  71. // Only rewrite when the body is a generator (no `async`/`await`, but
  72. // generators). `await` and `yield` differ in precedence, so wrap the
  73. // whole expression: `await X` -> `(yield X)`.
  74. if (
  75. !isGeneratorLowered(
  76. /** @type {Module} */ (module),
  77. moduleGraph,
  78. runtimeTemplate
  79. )
  80. ) {
  81. return;
  82. }
  83. const dep = /** @type {TopLevelAwaitDependency} */ (dependency);
  84. source.replace(dep.range[0], dep.argumentRange[0] - 1, "(yield ");
  85. source.insert(dep.argumentRange[1], ")");
  86. }
  87. };
  88. module.exports = TopLevelAwaitDependency;