ContextDependency.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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. /** @typedef {import("../ContextModule").ContextOptions} ContextOptions */
  11. /** @typedef {import("../Dependency").TRANSITIVE} TRANSITIVE */
  12. /** @typedef {import("../ModuleGraph")} ModuleGraph */
  13. /** @typedef {import("../WebpackError")} WebpackError */
  14. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
  15. /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
  16. const getCriticalDependencyWarning = memoize(() =>
  17. require("./CriticalDependencyWarning")
  18. );
  19. /** @typedef {ContextOptions & { request: string }} ContextDependencyOptions */
  20. /**
  21. * @param {RegExp | null | undefined} r regexp
  22. * @returns {string} stringified regexp
  23. */
  24. const regExpToString = r => (r ? String(r) : "");
  25. class ContextDependency extends Dependency {
  26. /**
  27. * @param {ContextDependencyOptions} options options for the context module
  28. * @param {string=} context request context
  29. */
  30. constructor(options, context) {
  31. super();
  32. this.options = options;
  33. this.userRequest = this.options && this.options.request;
  34. /** @type {false | undefined | string} */
  35. this.critical = false;
  36. this.hadGlobalOrStickyRegExp = false;
  37. if (
  38. this.options &&
  39. (this.options.regExp.global || this.options.regExp.sticky)
  40. ) {
  41. this.options = { ...this.options, regExp: null };
  42. this.hadGlobalOrStickyRegExp = true;
  43. }
  44. this.request = undefined;
  45. this.range = undefined;
  46. this.valueRange = undefined;
  47. /** @type {boolean | string | undefined} */
  48. this.inShorthand = undefined;
  49. // TODO refactor this
  50. this.replaces = undefined;
  51. this._requestContext = context;
  52. }
  53. /**
  54. * @returns {string | undefined} a request context
  55. */
  56. getContext() {
  57. return this._requestContext;
  58. }
  59. get category() {
  60. return "commonjs";
  61. }
  62. /**
  63. * @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
  64. */
  65. couldAffectReferencingModule() {
  66. return true;
  67. }
  68. /**
  69. * @returns {string | null} an identifier to merge equal requests
  70. */
  71. getResourceIdentifier() {
  72. return (
  73. `context${this._requestContext || ""}|ctx request${
  74. this.options.request
  75. } ${this.options.recursive} ` +
  76. `${regExpToString(this.options.regExp)} ${regExpToString(
  77. this.options.include
  78. )} ${regExpToString(this.options.exclude)} ` +
  79. `${this.options.mode} ${this.options.chunkName} ` +
  80. `${JSON.stringify(this.options.groupOptions)}` +
  81. `${
  82. this.options.referencedExports
  83. ? ` ${JSON.stringify(this.options.referencedExports)}`
  84. : ""
  85. }`
  86. );
  87. }
  88. /**
  89. * Returns warnings
  90. * @param {ModuleGraph} moduleGraph module graph
  91. * @returns {WebpackError[] | null | undefined} warnings
  92. */
  93. getWarnings(moduleGraph) {
  94. let warnings = super.getWarnings(moduleGraph);
  95. if (this.critical) {
  96. if (!warnings) warnings = [];
  97. const CriticalDependencyWarning = getCriticalDependencyWarning();
  98. warnings.push(new CriticalDependencyWarning(this.critical));
  99. }
  100. if (this.hadGlobalOrStickyRegExp) {
  101. if (!warnings) warnings = [];
  102. const CriticalDependencyWarning = getCriticalDependencyWarning();
  103. warnings.push(
  104. new CriticalDependencyWarning(
  105. "Contexts can't use RegExps with the 'g' or 'y' flags."
  106. )
  107. );
  108. }
  109. return warnings;
  110. }
  111. /**
  112. * @param {ObjectSerializerContext} context context
  113. */
  114. serialize(context) {
  115. const { write } = context;
  116. write(this.options);
  117. write(this.userRequest);
  118. write(this.critical);
  119. write(this.hadGlobalOrStickyRegExp);
  120. write(this.request);
  121. write(this._requestContext);
  122. write(this.range);
  123. write(this.valueRange);
  124. write(this.prepend);
  125. write(this.replaces);
  126. super.serialize(context);
  127. }
  128. /**
  129. * @param {ObjectDeserializerContext} context context
  130. */
  131. deserialize(context) {
  132. const { read } = context;
  133. this.options = read();
  134. this.userRequest = read();
  135. this.critical = read();
  136. this.hadGlobalOrStickyRegExp = read();
  137. this.request = read();
  138. this._requestContext = read();
  139. this.range = read();
  140. this.valueRange = read();
  141. this.prepend = read();
  142. this.replaces = read();
  143. super.deserialize(context);
  144. }
  145. }
  146. makeSerializable(
  147. ContextDependency,
  148. "webpack/lib/dependencies/ContextDependency"
  149. );
  150. ContextDependency.Template = DependencyTemplate;
  151. module.exports = ContextDependency;