OriginalSource.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { getMap, getSourceAndMap } = require("./helpers/getFromStreamChunks");
  7. const splitIntoLines = require("./helpers/splitIntoLines");
  8. const getGeneratedSourceInfo = require("./helpers/getGeneratedSourceInfo");
  9. const Source = require("./Source");
  10. const splitIntoPotentialTokens = require("./helpers/splitIntoPotentialTokens");
  11. class OriginalSource extends Source {
  12. constructor(value, name) {
  13. super();
  14. const isBuffer = Buffer.isBuffer(value);
  15. this._value = isBuffer ? undefined : value;
  16. this._valueAsBuffer = isBuffer ? value : undefined;
  17. this._name = name;
  18. }
  19. getName() {
  20. return this._name;
  21. }
  22. source() {
  23. if (this._value === undefined) {
  24. this._value = this._valueAsBuffer.toString("utf-8");
  25. }
  26. return this._value;
  27. }
  28. buffer() {
  29. if (this._valueAsBuffer === undefined) {
  30. this._valueAsBuffer = Buffer.from(this._value, "utf-8");
  31. }
  32. return this._valueAsBuffer;
  33. }
  34. map(options) {
  35. return getMap(this, options);
  36. }
  37. sourceAndMap(options) {
  38. return getSourceAndMap(this, options);
  39. }
  40. /**
  41. * @param {object} options options
  42. * @param {function(string, number, number, number, number, number, number): void} onChunk called for each chunk of code
  43. * @param {function(number, string, string)} onSource called for each source
  44. * @param {function(number, string)} onName called for each name
  45. * @returns {void}
  46. */
  47. streamChunks(options, onChunk, onSource, onName) {
  48. if (this._value === undefined) {
  49. this._value = this._valueAsBuffer.toString("utf-8");
  50. }
  51. onSource(0, this._name, this._value);
  52. const finalSource = !!(options && options.finalSource);
  53. if (!options || options.columns !== false) {
  54. // With column info we need to read all lines and split them
  55. const matches = splitIntoPotentialTokens(this._value);
  56. let line = 1;
  57. let column = 0;
  58. if (matches !== null) {
  59. for (const match of matches) {
  60. const isEndOfLine = match.endsWith("\n");
  61. if (isEndOfLine && match.length === 1) {
  62. if (!finalSource) onChunk(match, line, column, -1, -1, -1, -1);
  63. } else {
  64. const chunk = finalSource ? undefined : match;
  65. onChunk(chunk, line, column, 0, line, column, -1);
  66. }
  67. if (isEndOfLine) {
  68. line++;
  69. column = 0;
  70. } else {
  71. column += match.length;
  72. }
  73. }
  74. }
  75. return {
  76. generatedLine: line,
  77. generatedColumn: column,
  78. source: finalSource ? this._value : undefined
  79. };
  80. } else if (finalSource) {
  81. // Without column info and with final source we only
  82. // need meta info to generate mapping
  83. const result = getGeneratedSourceInfo(this._value);
  84. const { generatedLine, generatedColumn } = result;
  85. if (generatedColumn === 0) {
  86. for (let line = 1; line < generatedLine; line++)
  87. onChunk(undefined, line, 0, 0, line, 0, -1);
  88. } else {
  89. for (let line = 1; line <= generatedLine; line++)
  90. onChunk(undefined, line, 0, 0, line, 0, -1);
  91. }
  92. return result;
  93. } else {
  94. // Without column info, but also without final source
  95. // we need to split source by lines
  96. let line = 1;
  97. const matches = splitIntoLines(this._value);
  98. let match;
  99. for (match of matches) {
  100. onChunk(finalSource ? undefined : match, line, 0, 0, line, 0, -1);
  101. line++;
  102. }
  103. return matches.length === 0 || match.endsWith("\n")
  104. ? {
  105. generatedLine: matches.length + 1,
  106. generatedColumn: 0,
  107. source: finalSource ? this._value : undefined
  108. }
  109. : {
  110. generatedLine: matches.length,
  111. generatedColumn: match.length,
  112. source: finalSource ? this._value : undefined
  113. };
  114. }
  115. }
  116. updateHash(hash) {
  117. if (this._valueAsBuffer === undefined) {
  118. this._valueAsBuffer = Buffer.from(this._value, "utf-8");
  119. }
  120. hash.update("OriginalSource");
  121. hash.update(this._valueAsBuffer);
  122. hash.update(this._name || "");
  123. }
  124. }
  125. module.exports = OriginalSource;