RawSource.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const Source = require("./Source");
  7. const streamChunksOfRawSource = require("./helpers/streamChunksOfRawSource");
  8. const {
  9. internString,
  10. isDualStringBufferCachingEnabled,
  11. } = require("./helpers/stringBufferUtils");
  12. /** @typedef {import("./Source").HashLike} HashLike */
  13. /** @typedef {import("./Source").MapOptions} MapOptions */
  14. /** @typedef {import("./Source").RawSourceMap} RawSourceMap */
  15. /** @typedef {import("./Source").SourceValue} SourceValue */
  16. /** @typedef {import("./helpers/getGeneratedSourceInfo").GeneratedSourceInfo} GeneratedSourceInfo */
  17. /** @typedef {import("./helpers/streamChunks").OnChunk} OnChunk */
  18. /** @typedef {import("./helpers/streamChunks").OnName} OnName */
  19. /** @typedef {import("./helpers/streamChunks").OnSource} OnSource */
  20. /** @typedef {import("./helpers/streamChunks").Options} Options */
  21. class RawSource extends Source {
  22. /**
  23. * @param {string | Buffer} value value
  24. * @param {boolean=} convertToString convert to string
  25. */
  26. constructor(value, convertToString = false) {
  27. super();
  28. const isBuffer = Buffer.isBuffer(value);
  29. if (isBuffer) {
  30. /**
  31. * @private
  32. * @type {boolean}
  33. */
  34. this._valueIsBuffer = !convertToString;
  35. /**
  36. * @private
  37. * @type {undefined | string | Buffer}
  38. */
  39. this._value = convertToString ? undefined : value;
  40. /**
  41. * @private
  42. * @type {undefined | Buffer}
  43. */
  44. this._valueAsBuffer = value;
  45. /**
  46. * @private
  47. * @type {undefined | string}
  48. */
  49. this._valueAsString = undefined;
  50. } else if (typeof value === "string") {
  51. const interned = internString(value);
  52. this._valueIsBuffer = false;
  53. this._value = interned;
  54. this._valueAsBuffer = undefined;
  55. this._valueAsString = interned;
  56. } else {
  57. throw new TypeError("argument 'value' must be either string or Buffer");
  58. }
  59. }
  60. isBuffer() {
  61. return this._valueIsBuffer;
  62. }
  63. /**
  64. * @returns {SourceValue} source
  65. */
  66. source() {
  67. if (this._value === undefined) {
  68. const value =
  69. /** @type {Buffer} */
  70. (this._valueAsBuffer).toString("utf8");
  71. if (isDualStringBufferCachingEnabled()) {
  72. this._value = internString(value);
  73. }
  74. return value;
  75. }
  76. return this._value;
  77. }
  78. /**
  79. * @returns {Buffer} buffer
  80. */
  81. buffer() {
  82. if (this._valueAsBuffer === undefined) {
  83. const value = Buffer.from(/** @type {string} */ (this._value), "utf8");
  84. if (isDualStringBufferCachingEnabled()) {
  85. this._valueAsBuffer = value;
  86. }
  87. return value;
  88. }
  89. return this._valueAsBuffer;
  90. }
  91. /**
  92. * @returns {number} size
  93. */
  94. size() {
  95. if (this._cachedSize !== undefined) return this._cachedSize;
  96. if (this._valueAsBuffer !== undefined) {
  97. return (this._cachedSize = this._valueAsBuffer.length);
  98. }
  99. return (this._cachedSize = Buffer.byteLength(
  100. /** @type {string} */ (this._valueAsString),
  101. "utf8",
  102. ));
  103. }
  104. /**
  105. * @param {MapOptions=} options map options
  106. * @returns {RawSourceMap | null} map
  107. */
  108. // eslint-disable-next-line no-unused-vars
  109. map(options) {
  110. return null;
  111. }
  112. /**
  113. * @param {Options} options options
  114. * @param {OnChunk} onChunk called for each chunk of code
  115. * @param {OnSource} onSource called for each source
  116. * @param {OnName} onName called for each name
  117. * @returns {GeneratedSourceInfo} generated source info
  118. */
  119. streamChunks(options, onChunk, onSource, onName) {
  120. let strValue = this._valueAsString;
  121. if (strValue === undefined) {
  122. const value = this.source();
  123. strValue = typeof value === "string" ? value : value.toString("utf8");
  124. if (isDualStringBufferCachingEnabled()) {
  125. this._valueAsString = internString(strValue);
  126. }
  127. }
  128. return streamChunksOfRawSource(
  129. strValue,
  130. onChunk,
  131. onSource,
  132. onName,
  133. Boolean(options && options.finalSource),
  134. );
  135. }
  136. /**
  137. * @param {HashLike} hash hash
  138. * @returns {void}
  139. */
  140. updateHash(hash) {
  141. hash.update("RawSource");
  142. hash.update(this.buffer());
  143. }
  144. }
  145. module.exports = RawSource;