PureExpressionDependency.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { UsageState } = require("../ExportsInfo");
  7. const makeSerializable = require("../util/makeSerializable");
  8. const { filterRuntime, runtimeToString } = require("../util/runtime");
  9. const NullDependency = require("./NullDependency");
  10. /** @import { ReplaceSource } from "webpack-sources" */
  11. /** @import Dependency, { UpdateHashContext } from "../Dependency" */
  12. /** @import { DependencyTemplateContext } from "../DependencyTemplate" */
  13. /** @import Module from "../Module" */
  14. /** @import ModuleGraph from "../ModuleGraph" */
  15. /** @import { ConnectionState } from "../ModuleGraphConnection" */
  16. /** @import { Range } from "../javascript/JavascriptParser" */
  17. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext<[Range, Set<string> | false]>} ObjectDeserializerContext */
  18. /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext<[Range, Set<string> | false]>} ObjectSerializerContext */
  19. /** @import Hash from "../util/Hash" */
  20. /** @import { RuntimeSpec } from "../util/runtime" */
  21. class PureExpressionDependency extends NullDependency {
  22. /**
  23. * Creates an instance of PureExpressionDependency.
  24. * @param {Range} range the source range
  25. */
  26. constructor(range) {
  27. super();
  28. this.range = range;
  29. /** @type {Set<string> | false} */
  30. this.usedByExports = false;
  31. }
  32. /**
  33. * Get runtime condition.
  34. * @param {ModuleGraph} moduleGraph module graph
  35. * @param {RuntimeSpec} runtime current runtimes
  36. * @returns {boolean | RuntimeSpec} runtime condition
  37. */
  38. _getRuntimeCondition(moduleGraph, runtime) {
  39. const usedByExports = this.usedByExports;
  40. if (usedByExports !== false) {
  41. const selfModule =
  42. /** @type {Module} */
  43. (moduleGraph.getParentModule(this));
  44. const exportsInfo = moduleGraph.getExportsInfo(selfModule);
  45. const runtimeCondition = filterRuntime(runtime, (runtime) => {
  46. for (const exportName of usedByExports) {
  47. if (exportsInfo.getUsed(exportName, runtime) !== UsageState.Unused) {
  48. return true;
  49. }
  50. }
  51. return false;
  52. });
  53. return runtimeCondition;
  54. }
  55. return false;
  56. }
  57. /**
  58. * Updates the hash with the data contributed by this instance.
  59. * @param {Hash} hash hash to be updated
  60. * @param {UpdateHashContext} context context
  61. * @returns {void}
  62. */
  63. updateHash(hash, context) {
  64. const runtimeCondition = this._getRuntimeCondition(
  65. context.chunkGraph.moduleGraph,
  66. context.runtime
  67. );
  68. if (runtimeCondition === true) {
  69. return;
  70. } else if (runtimeCondition === false) {
  71. hash.update("null");
  72. } else {
  73. hash.update(
  74. `${runtimeToString(runtimeCondition)}|${runtimeToString(
  75. context.runtime
  76. )}`
  77. );
  78. }
  79. hash.update(String(this.range));
  80. }
  81. /**
  82. * Gets module evaluation side effects state.
  83. * @param {ModuleGraph} moduleGraph the module graph
  84. * @returns {ConnectionState} how this dependency connects the module to referencing modules
  85. */
  86. getModuleEvaluationSideEffectsState(moduleGraph) {
  87. return false;
  88. }
  89. /**
  90. * Serializes this instance into the provided serializer context.
  91. * @param {ObjectSerializerContext} context context
  92. */
  93. serialize(context) {
  94. context.write(this.range).write(this.usedByExports);
  95. super.serialize(context);
  96. }
  97. /**
  98. * Restores this instance from the provided deserializer context.
  99. * @param {ObjectDeserializerContext} context context
  100. */
  101. deserialize(context) {
  102. this.range = context.read();
  103. const c1 = context.rest;
  104. this.usedByExports = c1.read();
  105. super.deserialize(c1.rest);
  106. }
  107. }
  108. makeSerializable(
  109. PureExpressionDependency,
  110. "webpack/lib/dependencies/PureExpressionDependency"
  111. );
  112. PureExpressionDependency.Template = class PureExpressionDependencyTemplate extends (
  113. NullDependency.Template
  114. ) {
  115. /**
  116. * Applies the plugin by registering its hooks on the compiler.
  117. * @param {Dependency} dependency the dependency for which the template should be applied
  118. * @param {ReplaceSource} source the current replace source which can be modified
  119. * @param {DependencyTemplateContext} templateContext the context object
  120. * @returns {void}
  121. */
  122. apply(
  123. dependency,
  124. source,
  125. { chunkGraph, moduleGraph, runtime, runtimeTemplate, runtimeRequirements }
  126. ) {
  127. const dep = /** @type {PureExpressionDependency} */ (dependency);
  128. const runtimeCondition = dep._getRuntimeCondition(moduleGraph, runtime);
  129. if (runtimeCondition === true) {
  130. // Do nothing
  131. } else if (runtimeCondition === false) {
  132. source.insert(
  133. dep.range[0],
  134. "(/* unused pure expression or super */ null && ("
  135. );
  136. source.insert(dep.range[1], "))");
  137. } else {
  138. const condition = runtimeTemplate.runtimeConditionExpression({
  139. chunkGraph,
  140. runtime,
  141. runtimeCondition,
  142. runtimeRequirements
  143. });
  144. source.insert(
  145. dep.range[0],
  146. `(/* runtime-dependent pure expression or super */ ${condition} ? (`
  147. );
  148. source.insert(dep.range[1], ") : null)");
  149. }
  150. }
  151. };
  152. module.exports = PureExpressionDependency;