10
0

ConditionalInitFragment.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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. * @param {string} condition condition
  15. * @param {string | Source} source source
  16. * @returns {string | Source} wrapped source
  17. */
  18. const wrapInCondition = (condition, source) => {
  19. if (typeof source === "string") {
  20. return Template.asString([
  21. `if (${condition}) {`,
  22. Template.indent(source),
  23. "}",
  24. ""
  25. ]);
  26. }
  27. return new ConcatSource(
  28. `if (${condition}) {\n`,
  29. new PrefixSource("\t", source),
  30. "}\n"
  31. );
  32. };
  33. /**
  34. * @extends {InitFragment<GenerateContext>}
  35. */
  36. class ConditionalInitFragment extends InitFragment {
  37. /**
  38. * @param {string | Source | undefined} content the source code that will be included as initialization code
  39. * @param {number} stage category of initialization code (contribute to order)
  40. * @param {number} position position in the category (contribute to order)
  41. * @param {string | undefined} key unique key to avoid emitting the same initialization code twice
  42. * @param {RuntimeSpec | boolean} runtimeCondition in which runtime this fragment should be executed
  43. * @param {string | Source=} endContent the source code that will be included at the end of the module
  44. */
  45. constructor(
  46. content,
  47. stage,
  48. position,
  49. key,
  50. runtimeCondition = true,
  51. endContent = undefined
  52. ) {
  53. super(content, stage, position, key, endContent);
  54. this.runtimeCondition = runtimeCondition;
  55. }
  56. /**
  57. * @param {GenerateContext} context context
  58. * @returns {string | Source | undefined} the source code that will be included as initialization code
  59. */
  60. getContent(context) {
  61. if (this.runtimeCondition === false || !this.content) return "";
  62. if (this.runtimeCondition === true) return this.content;
  63. const expr = context.runtimeTemplate.runtimeConditionExpression({
  64. chunkGraph: context.chunkGraph,
  65. runtimeRequirements: context.runtimeRequirements,
  66. runtime: context.runtime,
  67. runtimeCondition: this.runtimeCondition
  68. });
  69. if (expr === "true") return this.content;
  70. return wrapInCondition(expr, this.content);
  71. }
  72. /**
  73. * @param {GenerateContext} context context
  74. * @returns {string|Source=} the source code that will be included at the end of the module
  75. */
  76. getEndContent(context) {
  77. if (this.runtimeCondition === false || !this.endContent) return "";
  78. if (this.runtimeCondition === true) return this.endContent;
  79. const expr = context.runtimeTemplate.runtimeConditionExpression({
  80. chunkGraph: context.chunkGraph,
  81. runtimeRequirements: context.runtimeRequirements,
  82. runtime: context.runtime,
  83. runtimeCondition: this.runtimeCondition
  84. });
  85. if (expr === "true") return this.endContent;
  86. return wrapInCondition(expr, this.endContent);
  87. }
  88. /**
  89. * @param {ConditionalInitFragment} other fragment to merge with
  90. * @returns {ConditionalInitFragment} merged fragment
  91. */
  92. merge(other) {
  93. if (this.runtimeCondition === true) return this;
  94. if (other.runtimeCondition === true) return other;
  95. if (this.runtimeCondition === false) return other;
  96. if (other.runtimeCondition === false) return this;
  97. const runtimeCondition = mergeRuntime(
  98. this.runtimeCondition,
  99. other.runtimeCondition
  100. );
  101. return new ConditionalInitFragment(
  102. this.content,
  103. this.stage,
  104. this.position,
  105. this.key,
  106. runtimeCondition,
  107. this.endContent
  108. );
  109. }
  110. }
  111. module.exports = ConditionalInitFragment;