ContextDependency.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const Dependency = require("../Dependency");
  7. const DependencyTemplate = require("../DependencyTemplate");
  8. const makeSerializable = require("../util/makeSerializable");
  9. const memoize = require("../util/memoize");
  10. const getCriticalDependencyWarning = memoize(() =>
  11. require("./CriticalDependencyWarning")
  12. );
  13. /** @import { Range } from "../javascript/JavascriptParser" */
  14. /** @import { ContextOptions } from "../ContextModule" */
  15. /** @import { TRANSITIVE } from "../Dependency" */
  16. /** @import ModuleGraph from "../ModuleGraph" */
  17. /** @import WebpackError from "../errors/WebpackError" */
  18. /**
  19. * @import {
  20. * ObjectDeserializerContext,
  21. * ObjectSerializerContext
  22. * } from "../serialization/ObjectMiddleware"
  23. */
  24. /** @typedef {ContextOptions & { request: string }} ContextDependencyOptions */
  25. /** @typedef {{ value: string, range: Range }[]} Replaces */
  26. /**
  27. * Returns stringified regexp.
  28. * @param {RegExp | false | null | undefined} r regexp
  29. * @returns {string} stringified regexp
  30. */
  31. const regExpToString = (r) => (r ? String(r) : "");
  32. class ContextDependency extends Dependency {
  33. /**
  34. * Creates an instance of ContextDependency.
  35. * @param {ContextDependencyOptions} options options for the context module
  36. * @param {string=} context request context
  37. */
  38. constructor(options, context) {
  39. super();
  40. /** @type {ContextDependencyOptions} */
  41. this.options = options;
  42. /** @type {string} */
  43. this.userRequest = this.options && this.options.request;
  44. /** @type {false | undefined | string} */
  45. this.critical = false;
  46. /** @type {boolean} */
  47. this.hadGlobalOrStickyRegExp = false;
  48. if (
  49. this.options &&
  50. this.options.regExp &&
  51. (this.options.regExp.global || this.options.regExp.sticky)
  52. ) {
  53. this.options = { ...this.options, regExp: null };
  54. this.hadGlobalOrStickyRegExp = true;
  55. }
  56. /** @type {string | undefined} */
  57. this.request = undefined;
  58. /** @type {Range | undefined} */
  59. this.range = undefined;
  60. /** @type {Range | undefined} */
  61. this.valueRange = undefined;
  62. /** @type {boolean | string | undefined} */
  63. this.inShorthand = undefined;
  64. /** @type {Replaces | undefined} */
  65. this.replaces = undefined;
  66. /** @type {string | undefined} */
  67. this._requestContext = context;
  68. }
  69. /**
  70. * Returns a request context.
  71. * @returns {string | undefined} a request context
  72. */
  73. getContext() {
  74. return this._requestContext;
  75. }
  76. get category() {
  77. return "commonjs";
  78. }
  79. /**
  80. * Could affect referencing module.
  81. * @returns {boolean | TRANSITIVE} true, when changes to the referenced module could affect the referencing module; TRANSITIVE, when changes to the referenced module could affect referencing modules of the referencing module
  82. */
  83. couldAffectReferencingModule() {
  84. return true;
  85. }
  86. /**
  87. * Returns an identifier to merge equal requests.
  88. * @returns {string | null} an identifier to merge equal requests
  89. */
  90. getResourceIdentifier() {
  91. return (
  92. `context${this._requestContext || ""}|ctx request${
  93. this.options.request
  94. } ${this.options.recursive} ` +
  95. `${regExpToString(this.options.regExp)} ${regExpToString(
  96. this.options.include
  97. )} ${regExpToString(this.options.exclude)} ` +
  98. `${this.options.mode} ${this.options.chunkName} ` +
  99. `${JSON.stringify(this.options.groupOptions)}` +
  100. `${
  101. this.options.referencedExports
  102. ? ` ${JSON.stringify(this.options.referencedExports)}`
  103. : ""
  104. }`
  105. );
  106. }
  107. /**
  108. * Returns warnings.
  109. * @param {ModuleGraph} moduleGraph module graph
  110. * @returns {WebpackError[] | null | undefined} warnings
  111. */
  112. getWarnings(moduleGraph) {
  113. let warnings = super.getWarnings(moduleGraph);
  114. if (this.critical) {
  115. if (!warnings) warnings = [];
  116. const CriticalDependencyWarning = getCriticalDependencyWarning();
  117. warnings.push(new CriticalDependencyWarning(this.critical));
  118. }
  119. if (this.hadGlobalOrStickyRegExp) {
  120. if (!warnings) warnings = [];
  121. const CriticalDependencyWarning = getCriticalDependencyWarning();
  122. warnings.push(
  123. new CriticalDependencyWarning(
  124. "Contexts can't use RegExps with the 'g' or 'y' flags."
  125. )
  126. );
  127. }
  128. return warnings;
  129. }
  130. /**
  131. * Serializes this instance into the provided serializer context.
  132. * @param {ObjectSerializerContext} context context
  133. */
  134. serialize(context) {
  135. const { write } = context;
  136. write(this.options);
  137. write(this.userRequest);
  138. write(this.critical);
  139. write(this.hadGlobalOrStickyRegExp);
  140. write(this.request);
  141. write(this._requestContext);
  142. write(this.range);
  143. write(this.valueRange);
  144. write(this.replaces);
  145. super.serialize(context);
  146. }
  147. /**
  148. * Restores this instance from the provided deserializer context.
  149. * @param {ObjectDeserializerContext} context context
  150. */
  151. deserialize(context) {
  152. const { read } = context;
  153. this.options = read();
  154. this.userRequest = read();
  155. this.critical = read();
  156. this.hadGlobalOrStickyRegExp = read();
  157. this.request = read();
  158. this._requestContext = read();
  159. this.range = read();
  160. this.valueRange = read();
  161. this.replaces = read();
  162. super.deserialize(context);
  163. }
  164. }
  165. makeSerializable(
  166. ContextDependency,
  167. "webpack/lib/dependencies/ContextDependency"
  168. );
  169. ContextDependency.Template = DependencyTemplate;
  170. module.exports = ContextDependency;