ContextDependency.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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 ? 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. }
  83. /**
  84. * Returns warnings
  85. * @param {ModuleGraph} moduleGraph module graph
  86. * @returns {WebpackError[] | null | undefined} warnings
  87. */
  88. getWarnings(moduleGraph) {
  89. let warnings = super.getWarnings(moduleGraph);
  90. if (this.critical) {
  91. if (!warnings) warnings = [];
  92. const CriticalDependencyWarning = getCriticalDependencyWarning();
  93. warnings.push(new CriticalDependencyWarning(this.critical));
  94. }
  95. if (this.hadGlobalOrStickyRegExp) {
  96. if (!warnings) warnings = [];
  97. const CriticalDependencyWarning = getCriticalDependencyWarning();
  98. warnings.push(
  99. new CriticalDependencyWarning(
  100. "Contexts can't use RegExps with the 'g' or 'y' flags."
  101. )
  102. );
  103. }
  104. return warnings;
  105. }
  106. /**
  107. * @param {ObjectSerializerContext} context context
  108. */
  109. serialize(context) {
  110. const { write } = context;
  111. write(this.options);
  112. write(this.userRequest);
  113. write(this.critical);
  114. write(this.hadGlobalOrStickyRegExp);
  115. write(this.request);
  116. write(this._requestContext);
  117. write(this.range);
  118. write(this.valueRange);
  119. write(this.prepend);
  120. write(this.replaces);
  121. super.serialize(context);
  122. }
  123. /**
  124. * @param {ObjectDeserializerContext} context context
  125. */
  126. deserialize(context) {
  127. const { read } = context;
  128. this.options = read();
  129. this.userRequest = read();
  130. this.critical = read();
  131. this.hadGlobalOrStickyRegExp = read();
  132. this.request = read();
  133. this._requestContext = read();
  134. this.range = read();
  135. this.valueRange = read();
  136. this.prepend = read();
  137. this.replaces = read();
  138. super.deserialize(context);
  139. }
  140. }
  141. makeSerializable(
  142. ContextDependency,
  143. "webpack/lib/dependencies/ContextDependency"
  144. );
  145. ContextDependency.Template = DependencyTemplate;
  146. module.exports = ContextDependency;