CssIcssSymbolDependency.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Alexander Akait @alexander-akait
  4. */
  5. "use strict";
  6. const { CSS_TYPE } = require("../ModuleSourceTypeConstants");
  7. const makeSerializable = require("../util/makeSerializable");
  8. const CssIcssExportDependency = require("./CssIcssExportDependency");
  9. const NullDependency = require("./NullDependency");
  10. /** @import { ReplaceSource } from "webpack-sources" */
  11. /** @import Dependency, { UpdateHashContext } from "../Dependency" */
  12. /**
  13. * @import {
  14. * CssDependencyTemplateContext as DependencyTemplateContext
  15. * } from "../DependencyTemplate"
  16. */
  17. /** @import { Range } from "../css/CssParser" */
  18. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext<[string, Range, string | undefined, string | undefined, string | undefined]>} ObjectDeserializerContext */
  19. /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext<[string, Range, string | undefined, string | undefined, string | undefined]>} ObjectSerializerContext */
  20. /** @import Hash from "../util/Hash" */
  21. class CssIcssSymbolDependency extends NullDependency {
  22. /**
  23. * Creates an instance of CssIcssSymbolDependency.
  24. * @param {string} localName local name
  25. * @param {Range} range range
  26. * @param {string=} value value when it was defined in this module
  27. * @param {string=} importName import name when it was imported from other module
  28. * @param {string=} request request of the `@value` import that was active when this reference was parsed — used to disambiguate when the same local name is imported from multiple modules
  29. */
  30. constructor(localName, range, value, importName, request) {
  31. super();
  32. /** @type {string} */
  33. this.localName = localName;
  34. this.range = range;
  35. /** @type {string | undefined} */
  36. this.value = value;
  37. /** @type {string | undefined} */
  38. this.importName = importName;
  39. /** @type {string | undefined} */
  40. this.request = request;
  41. /** @type {undefined | string} */
  42. this._hashUpdate = undefined;
  43. }
  44. get type() {
  45. return "css symbol identifier";
  46. }
  47. /**
  48. * Updates the hash with the data contributed by this instance.
  49. * @param {Hash} hash hash to be updated
  50. * @param {UpdateHashContext} context context
  51. * @returns {void}
  52. */
  53. updateHash(hash, context) {
  54. if (this._hashUpdate === undefined) {
  55. // Concatenate with explicit field separators so adjacent fields
  56. // can't alias each other (e.g. range `[1,11]` + localName `"foo"`
  57. // vs range `[1,1]` + localName `"1foo"`).
  58. this._hashUpdate = `range|${JSON.stringify(this.range)}|localName|${this.localName}|value|${this.value || ""}|importName|${this.importName || ""}|request|${this.request || ""}`;
  59. }
  60. hash.update(this._hashUpdate);
  61. }
  62. /**
  63. * Serializes this instance into the provided serializer context.
  64. * @param {ObjectSerializerContext} context context
  65. */
  66. serialize(context) {
  67. context
  68. .write(this.localName)
  69. .write(this.range)
  70. .write(this.value)
  71. .write(this.importName)
  72. .write(this.request);
  73. super.serialize(context);
  74. }
  75. /**
  76. * Restores this instance from the provided deserializer context.
  77. * @param {ObjectDeserializerContext} context context
  78. */
  79. deserialize(context) {
  80. this.localName = context.read();
  81. const c1 = context.rest;
  82. this.range = c1.read();
  83. const c2 = c1.rest;
  84. this.value = c2.read();
  85. const c3 = c2.rest;
  86. this.importName = c3.read();
  87. const c4 = c3.rest;
  88. this.request = c4.read();
  89. super.deserialize(c4.rest);
  90. }
  91. }
  92. CssIcssSymbolDependency.Template = class CssIcssSymbolDependencyTemplate extends (
  93. NullDependency.Template
  94. ) {
  95. /**
  96. * Applies the plugin by registering its hooks on the compiler.
  97. * @param {Dependency} dependency the dependency for which the template should be applied
  98. * @param {ReplaceSource} source the current replace source which can be modified
  99. * @param {DependencyTemplateContext} templateContext the context object
  100. * @returns {void}
  101. */
  102. apply(dependency, source, templateContext) {
  103. if (templateContext.type === CSS_TYPE) {
  104. const dep = /** @type {CssIcssSymbolDependency} */ (dependency);
  105. /** @type {string | undefined} */
  106. const value = dep.importName
  107. ? CssIcssExportDependency.Template.resolve(
  108. dep.localName,
  109. dep.importName,
  110. templateContext,
  111. dep.request
  112. )
  113. : dep.value;
  114. if (!value) {
  115. return;
  116. }
  117. source.replace(dep.range[0], dep.range[1] - 1, value);
  118. }
  119. }
  120. };
  121. makeSerializable(
  122. CssIcssSymbolDependency,
  123. "webpack/lib/dependencies/CssIcssSymbolDependency"
  124. );
  125. module.exports = CssIcssSymbolDependency;