sourcemap-codec.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import { comma, decodeInteger, encodeInteger, hasMoreVlq, semicolon } from './vlq';
  2. import { StringWriter, StringReader } from './strings';
  3. export {
  4. decodeOriginalScopes,
  5. encodeOriginalScopes,
  6. decodeGeneratedRanges,
  7. encodeGeneratedRanges,
  8. } from './scopes';
  9. export type { OriginalScope, GeneratedRange, CallSite, BindingExpressionRange } from './scopes';
  10. export type SourceMapSegment =
  11. | [number]
  12. | [number, number, number, number]
  13. | [number, number, number, number, number];
  14. export type SourceMapLine = SourceMapSegment[];
  15. export type SourceMapMappings = SourceMapLine[];
  16. export function decode(mappings: string): SourceMapMappings {
  17. const { length } = mappings;
  18. const reader = new StringReader(mappings);
  19. const decoded: SourceMapMappings = [];
  20. let genColumn = 0;
  21. let sourcesIndex = 0;
  22. let sourceLine = 0;
  23. let sourceColumn = 0;
  24. let namesIndex = 0;
  25. do {
  26. const semi = reader.indexOf(';');
  27. const line: SourceMapLine = [];
  28. let sorted = true;
  29. let lastCol = 0;
  30. genColumn = 0;
  31. while (reader.pos < semi) {
  32. let seg: SourceMapSegment;
  33. genColumn = decodeInteger(reader, genColumn);
  34. if (genColumn < lastCol) sorted = false;
  35. lastCol = genColumn;
  36. if (hasMoreVlq(reader, semi)) {
  37. sourcesIndex = decodeInteger(reader, sourcesIndex);
  38. sourceLine = decodeInteger(reader, sourceLine);
  39. sourceColumn = decodeInteger(reader, sourceColumn);
  40. if (hasMoreVlq(reader, semi)) {
  41. namesIndex = decodeInteger(reader, namesIndex);
  42. seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];
  43. } else {
  44. seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];
  45. }
  46. } else {
  47. seg = [genColumn];
  48. }
  49. line.push(seg);
  50. reader.pos++;
  51. }
  52. if (!sorted) sort(line);
  53. decoded.push(line);
  54. reader.pos = semi + 1;
  55. } while (reader.pos <= length);
  56. return decoded;
  57. }
  58. function sort(line: SourceMapSegment[]) {
  59. line.sort(sortComparator);
  60. }
  61. function sortComparator(a: SourceMapSegment, b: SourceMapSegment): number {
  62. return a[0] - b[0];
  63. }
  64. export function encode(decoded: SourceMapMappings): string;
  65. export function encode(decoded: Readonly<SourceMapMappings>): string;
  66. export function encode(decoded: Readonly<SourceMapMappings>): string {
  67. const writer = new StringWriter();
  68. let sourcesIndex = 0;
  69. let sourceLine = 0;
  70. let sourceColumn = 0;
  71. let namesIndex = 0;
  72. for (let i = 0; i < decoded.length; i++) {
  73. const line = decoded[i];
  74. if (i > 0) writer.write(semicolon);
  75. if (line.length === 0) continue;
  76. let genColumn = 0;
  77. for (let j = 0; j < line.length; j++) {
  78. const segment = line[j];
  79. if (j > 0) writer.write(comma);
  80. genColumn = encodeInteger(writer, segment[0], genColumn);
  81. if (segment.length === 1) continue;
  82. sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex);
  83. sourceLine = encodeInteger(writer, segment[2], sourceLine);
  84. sourceColumn = encodeInteger(writer, segment[3], sourceColumn);
  85. if (segment.length === 4) continue;
  86. namesIndex = encodeInteger(writer, segment[4], namesIndex);
  87. }
  88. }
  89. return writer.flush();
  90. }