ConditionalInitFragment.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { ConcatSource, PrefixSource } = require("webpack-sources");
  7. const InitFragment = require("./InitFragment");
  8. const Template = require("./Template");
  9. const { mergeRuntime } = require("./util/runtime");
  10. /** @typedef {import("webpack-sources").Source} Source */
  11. /** @typedef {import("./Generator").GenerateContext} GenerateContext */
  12. /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
  13. /**
  14. * Returns wrapped source.
  15. * @param {string} condition condition
  16. * @param {string | Source} source source
  17. * @returns {string | Source} wrapped source
  18. */
  19. const wrapInCondition = (condition, source) => {
  20. if (typeof source === "string") {
  21. return Template.asString([
  22. `if (${condition}) {`,
  23. Template.indent(source),
  24. "}",
  25. ""
  26. ]);
  27. }
  28. return new ConcatSource(
  29. `if (${condition}) {\n`,
  30. new PrefixSource("\t", source),
  31. "}\n"
  32. );
  33. };
  34. /**
  35. * Represents ConditionalInitFragment.
  36. * @extends {InitFragment<GenerateContext>}
  37. */
  38. class ConditionalInitFragment extends InitFragment {
  39. /**
  40. * Creates an instance of ConditionalInitFragment.
  41. * @param {string | Source | undefined} content the source code that will be included as initialization code
  42. * @param {number} stage category of initialization code (contribute to order)
  43. * @param {number} position position in the category (contribute to order)
  44. * @param {string | undefined} key unique key to avoid emitting the same initialization code twice
  45. * @param {RuntimeSpec | boolean} runtimeCondition in which runtime this fragment should be executed
  46. * @param {string | Source=} endContent the source code that will be included at the end of the module
  47. */
  48. constructor(
  49. content,
  50. stage,
  51. position,
  52. key,
  53. runtimeCondition = true,
  54. endContent = undefined
  55. ) {
  56. super(content, stage, position, key, endContent);
  57. this.runtimeCondition = runtimeCondition;
  58. }
  59. /**
  60. * Returns the source code that will be included as initialization code.
  61. * @param {GenerateContext} context context
  62. * @returns {string | Source | undefined} the source code that will be included as initialization code
  63. */
  64. getContent(context) {
  65. if (this.runtimeCondition === false || !this.content) return "";
  66. if (this.runtimeCondition === true) return this.content;
  67. const expr = context.runtimeTemplate.runtimeConditionExpression({
  68. chunkGraph: context.chunkGraph,
  69. runtimeRequirements: context.runtimeRequirements,
  70. runtime: context.runtime,
  71. runtimeCondition: this.runtimeCondition
  72. });
  73. if (expr === "true") return this.content;
  74. return wrapInCondition(expr, this.content);
  75. }
  76. /**
  77. * Returns the source code that will be included at the end of the module.
  78. * @param {GenerateContext} context context
  79. * @returns {string | Source | undefined} the source code that will be included at the end of the module
  80. */
  81. getEndContent(context) {
  82. if (this.runtimeCondition === false || !this.endContent) return "";
  83. if (this.runtimeCondition === true) return this.endContent;
  84. const expr = context.runtimeTemplate.runtimeConditionExpression({
  85. chunkGraph: context.chunkGraph,
  86. runtimeRequirements: context.runtimeRequirements,
  87. runtime: context.runtime,
  88. runtimeCondition: this.runtimeCondition
  89. });
  90. if (expr === "true") return this.endContent;
  91. return wrapInCondition(expr, this.endContent);
  92. }
  93. /**
  94. * Returns merged fragment.
  95. * @param {ConditionalInitFragment} other fragment to merge with
  96. * @returns {ConditionalInitFragment} merged fragment
  97. */
  98. merge(other) {
  99. if (this.runtimeCondition === true) return this;
  100. if (other.runtimeCondition === true) return other;
  101. if (this.runtimeCondition === false) return other;
  102. if (other.runtimeCondition === false) return this;
  103. const runtimeCondition = mergeRuntime(
  104. this.runtimeCondition,
  105. other.runtimeCondition
  106. );
  107. return new ConditionalInitFragment(
  108. this.content,
  109. this.stage,
  110. this.position,
  111. this.key,
  112. runtimeCondition,
  113. this.endContent
  114. );
  115. }
  116. }
  117. module.exports = ConditionalInitFragment;