createMappingsSerializer.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(
  7. ""
  8. );
  9. const CONTINUATION_BIT = 0x20;
  10. const createMappingsSerializer = options => {
  11. const linesOnly = options && options.columns === false;
  12. return linesOnly
  13. ? createLinesOnlyMappingsSerializer()
  14. : createFullMappingsSerializer();
  15. };
  16. const createFullMappingsSerializer = () => {
  17. let currentLine = 1;
  18. let currentColumn = 0;
  19. let currentSourceIndex = 0;
  20. let currentOriginalLine = 1;
  21. let currentOriginalColumn = 0;
  22. let currentNameIndex = 0;
  23. let activeMapping = false;
  24. let activeName = false;
  25. let initial = true;
  26. return (
  27. generatedLine,
  28. generatedColumn,
  29. sourceIndex,
  30. originalLine,
  31. originalColumn,
  32. nameIndex
  33. ) => {
  34. if (activeMapping && currentLine === generatedLine) {
  35. // A mapping is still active
  36. if (
  37. sourceIndex === currentSourceIndex &&
  38. originalLine === currentOriginalLine &&
  39. originalColumn === currentOriginalColumn &&
  40. !activeName &&
  41. nameIndex < 0
  42. ) {
  43. // avoid repeating the same original mapping
  44. return "";
  45. }
  46. } else {
  47. // No mapping is active
  48. if (sourceIndex < 0) {
  49. // avoid writing unneccessary generated mappings
  50. return "";
  51. }
  52. }
  53. let str;
  54. if (currentLine < generatedLine) {
  55. str = ";".repeat(generatedLine - currentLine);
  56. currentLine = generatedLine;
  57. currentColumn = 0;
  58. initial = false;
  59. } else if (initial) {
  60. str = "";
  61. initial = false;
  62. } else {
  63. str = ",";
  64. }
  65. const writeValue = value => {
  66. const sign = (value >>> 31) & 1;
  67. const mask = value >> 31;
  68. const absValue = (value + mask) ^ mask;
  69. let data = (absValue << 1) | sign;
  70. for (;;) {
  71. const sextet = data & 0x1f;
  72. data >>= 5;
  73. if (data === 0) {
  74. str += ALPHABET[sextet];
  75. break;
  76. } else {
  77. str += ALPHABET[sextet | CONTINUATION_BIT];
  78. }
  79. }
  80. };
  81. writeValue(generatedColumn - currentColumn);
  82. currentColumn = generatedColumn;
  83. if (sourceIndex >= 0) {
  84. activeMapping = true;
  85. if (sourceIndex === currentSourceIndex) {
  86. str += "A";
  87. } else {
  88. writeValue(sourceIndex - currentSourceIndex);
  89. currentSourceIndex = sourceIndex;
  90. }
  91. writeValue(originalLine - currentOriginalLine);
  92. currentOriginalLine = originalLine;
  93. if (originalColumn === currentOriginalColumn) {
  94. str += "A";
  95. } else {
  96. writeValue(originalColumn - currentOriginalColumn);
  97. currentOriginalColumn = originalColumn;
  98. }
  99. if (nameIndex >= 0) {
  100. writeValue(nameIndex - currentNameIndex);
  101. currentNameIndex = nameIndex;
  102. activeName = true;
  103. } else {
  104. activeName = false;
  105. }
  106. } else {
  107. activeMapping = false;
  108. }
  109. return str;
  110. };
  111. };
  112. const createLinesOnlyMappingsSerializer = () => {
  113. let lastWrittenLine = 0;
  114. let currentLine = 1;
  115. let currentSourceIndex = 0;
  116. let currentOriginalLine = 1;
  117. return (
  118. generatedLine,
  119. _generatedColumn,
  120. sourceIndex,
  121. originalLine,
  122. _originalColumn,
  123. _nameIndex
  124. ) => {
  125. if (sourceIndex < 0) {
  126. // avoid writing generated mappings at all
  127. return "";
  128. }
  129. if (lastWrittenLine === generatedLine) {
  130. // avoid writing multiple original mappings per line
  131. return "";
  132. }
  133. let str;
  134. const writeValue = value => {
  135. const sign = (value >>> 31) & 1;
  136. const mask = value >> 31;
  137. const absValue = (value + mask) ^ mask;
  138. let data = (absValue << 1) | sign;
  139. for (;;) {
  140. const sextet = data & 0x1f;
  141. data >>= 5;
  142. if (data === 0) {
  143. str += ALPHABET[sextet];
  144. break;
  145. } else {
  146. str += ALPHABET[sextet | CONTINUATION_BIT];
  147. }
  148. }
  149. };
  150. lastWrittenLine = generatedLine;
  151. if (generatedLine === currentLine + 1) {
  152. currentLine = generatedLine;
  153. if (sourceIndex === currentSourceIndex) {
  154. currentSourceIndex = sourceIndex;
  155. if (originalLine === currentOriginalLine + 1) {
  156. currentOriginalLine = originalLine;
  157. return ";AACA";
  158. } else {
  159. str = ";AA";
  160. writeValue(originalLine - currentOriginalLine);
  161. currentOriginalLine = originalLine;
  162. return str + "A";
  163. }
  164. } else {
  165. str = ";A";
  166. writeValue(sourceIndex - currentSourceIndex);
  167. currentSourceIndex = sourceIndex;
  168. writeValue(originalLine - currentOriginalLine);
  169. currentOriginalLine = originalLine;
  170. return str + "A";
  171. }
  172. } else {
  173. str = ";".repeat(generatedLine - currentLine);
  174. currentLine = generatedLine;
  175. if (sourceIndex === currentSourceIndex) {
  176. currentSourceIndex = sourceIndex;
  177. if (originalLine === currentOriginalLine + 1) {
  178. currentOriginalLine = originalLine;
  179. return str + "AACA";
  180. } else {
  181. str += "AA";
  182. writeValue(originalLine - currentOriginalLine);
  183. currentOriginalLine = originalLine;
  184. return str + "A";
  185. }
  186. } else {
  187. str += "A";
  188. writeValue(sourceIndex - currentSourceIndex);
  189. currentSourceIndex = sourceIndex;
  190. writeValue(originalLine - currentOriginalLine);
  191. currentOriginalLine = originalLine;
  192. return str + "A";
  193. }
  194. }
  195. };
  196. };
  197. module.exports = createMappingsSerializer;