You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

339 lines
12 KiB

5 years ago
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. var __importStar = (this && this.__importStar) || function (mod) {
  6. if (mod && mod.__esModule) return mod;
  7. var result = {};
  8. if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
  9. result["default"] = mod;
  10. return result;
  11. };
  12. Object.defineProperty(exports, "__esModule", { value: true });
  13. var assert_1 = __importDefault(require("assert"));
  14. var types = __importStar(require("ast-types"));
  15. var n = types.namedTypes;
  16. var source_map_1 = __importDefault(require("source-map"));
  17. var SourceMapConsumer = source_map_1.default.SourceMapConsumer;
  18. var SourceMapGenerator = source_map_1.default.SourceMapGenerator;
  19. var hasOwn = Object.prototype.hasOwnProperty;
  20. function getOption(options, key, defaultValue) {
  21. if (options && hasOwn.call(options, key)) {
  22. return options[key];
  23. }
  24. return defaultValue;
  25. }
  26. exports.getOption = getOption;
  27. function getUnionOfKeys() {
  28. var args = [];
  29. for (var _i = 0; _i < arguments.length; _i++) {
  30. args[_i] = arguments[_i];
  31. }
  32. var result = {};
  33. var argc = args.length;
  34. for (var i = 0; i < argc; ++i) {
  35. var keys = Object.keys(args[i]);
  36. var keyCount = keys.length;
  37. for (var j = 0; j < keyCount; ++j) {
  38. result[keys[j]] = true;
  39. }
  40. }
  41. return result;
  42. }
  43. exports.getUnionOfKeys = getUnionOfKeys;
  44. function comparePos(pos1, pos2) {
  45. return (pos1.line - pos2.line) || (pos1.column - pos2.column);
  46. }
  47. exports.comparePos = comparePos;
  48. function copyPos(pos) {
  49. return {
  50. line: pos.line,
  51. column: pos.column
  52. };
  53. }
  54. exports.copyPos = copyPos;
  55. function composeSourceMaps(formerMap, latterMap) {
  56. if (formerMap) {
  57. if (!latterMap) {
  58. return formerMap;
  59. }
  60. }
  61. else {
  62. return latterMap || null;
  63. }
  64. var smcFormer = new SourceMapConsumer(formerMap);
  65. var smcLatter = new SourceMapConsumer(latterMap);
  66. var smg = new SourceMapGenerator({
  67. file: latterMap.file,
  68. sourceRoot: latterMap.sourceRoot
  69. });
  70. var sourcesToContents = {};
  71. smcLatter.eachMapping(function (mapping) {
  72. var origPos = smcFormer.originalPositionFor({
  73. line: mapping.originalLine,
  74. column: mapping.originalColumn
  75. });
  76. var sourceName = origPos.source;
  77. if (sourceName === null) {
  78. return;
  79. }
  80. smg.addMapping({
  81. source: sourceName,
  82. original: copyPos(origPos),
  83. generated: {
  84. line: mapping.generatedLine,
  85. column: mapping.generatedColumn
  86. },
  87. name: mapping.name
  88. });
  89. var sourceContent = smcFormer.sourceContentFor(sourceName);
  90. if (sourceContent && !hasOwn.call(sourcesToContents, sourceName)) {
  91. sourcesToContents[sourceName] = sourceContent;
  92. smg.setSourceContent(sourceName, sourceContent);
  93. }
  94. });
  95. return smg.toJSON();
  96. }
  97. exports.composeSourceMaps = composeSourceMaps;
  98. ;
  99. function getTrueLoc(node, lines) {
  100. // It's possible that node is newly-created (not parsed by Esprima),
  101. // in which case it probably won't have a .loc property (or an
  102. // .original property for that matter). That's fine; we'll just
  103. // pretty-print it as usual.
  104. if (!node.loc) {
  105. return null;
  106. }
  107. var result = {
  108. start: node.loc.start,
  109. end: node.loc.end
  110. };
  111. function include(node) {
  112. expandLoc(result, node.loc);
  113. }
  114. // If the node is an export declaration and its .declaration has any
  115. // decorators, their locations might contribute to the true start/end
  116. // positions of the export declaration node.
  117. if (node.declaration &&
  118. node.declaration.decorators &&
  119. isExportDeclaration(node)) {
  120. node.declaration.decorators.forEach(include);
  121. }
  122. if (comparePos(result.start, result.end) < 0) {
  123. // Trim leading whitespace.
  124. result.start = copyPos(result.start);
  125. lines.skipSpaces(result.start, false, true);
  126. if (comparePos(result.start, result.end) < 0) {
  127. // Trim trailing whitespace, if the end location is not already the
  128. // same as the start location.
  129. result.end = copyPos(result.end);
  130. lines.skipSpaces(result.end, true, true);
  131. }
  132. }
  133. // If the node has any comments, their locations might contribute to
  134. // the true start/end positions of the node.
  135. if (node.comments) {
  136. node.comments.forEach(include);
  137. }
  138. return result;
  139. }
  140. exports.getTrueLoc = getTrueLoc;
  141. ;
  142. function expandLoc(parentLoc, childLoc) {
  143. if (parentLoc && childLoc) {
  144. if (comparePos(childLoc.start, parentLoc.start) < 0) {
  145. parentLoc.start = childLoc.start;
  146. }
  147. if (comparePos(parentLoc.end, childLoc.end) < 0) {
  148. parentLoc.end = childLoc.end;
  149. }
  150. }
  151. }
  152. function fixFaultyLocations(node, lines) {
  153. var loc = node.loc;
  154. if (loc) {
  155. if (loc.start.line < 1) {
  156. loc.start.line = 1;
  157. }
  158. if (loc.end.line < 1) {
  159. loc.end.line = 1;
  160. }
  161. }
  162. if (node.type === "File") {
  163. // Babylon returns File nodes whose .loc.{start,end} do not include
  164. // leading or trailing whitespace.
  165. loc.start = lines.firstPos();
  166. loc.end = lines.lastPos();
  167. }
  168. fixForLoopHead(node, lines);
  169. fixTemplateLiteral(node, lines);
  170. if (loc && node.decorators) {
  171. // Expand the .loc of the node responsible for printing the decorators
  172. // (here, the decorated node) so that it includes node.decorators.
  173. node.decorators.forEach(function (decorator) {
  174. expandLoc(loc, decorator.loc);
  175. });
  176. }
  177. else if (node.declaration && isExportDeclaration(node)) {
  178. // Nullify .loc information for the child declaration so that we never
  179. // try to reprint it without also reprinting the export declaration.
  180. node.declaration.loc = null;
  181. // Expand the .loc of the node responsible for printing the decorators
  182. // (here, the export declaration) so that it includes node.decorators.
  183. var decorators = node.declaration.decorators;
  184. if (decorators) {
  185. decorators.forEach(function (decorator) {
  186. expandLoc(loc, decorator.loc);
  187. });
  188. }
  189. }
  190. else if ((n.MethodDefinition && n.MethodDefinition.check(node)) ||
  191. (n.Property.check(node) && (node.method || node.shorthand))) {
  192. // If the node is a MethodDefinition or a .method or .shorthand
  193. // Property, then the location information stored in
  194. // node.value.loc is very likely untrustworthy (just the {body}
  195. // part of a method, or nothing in the case of shorthand
  196. // properties), so we null out that information to prevent
  197. // accidental reuse of bogus source code during reprinting.
  198. node.value.loc = null;
  199. if (n.FunctionExpression.check(node.value)) {
  200. // FunctionExpression method values should be anonymous,
  201. // because their .id fields are ignored anyway.
  202. node.value.id = null;
  203. }
  204. }
  205. else if (node.type === "ObjectTypeProperty") {
  206. var loc = node.loc;
  207. var end = loc && loc.end;
  208. if (end) {
  209. end = copyPos(end);
  210. if (lines.prevPos(end) &&
  211. lines.charAt(end) === ",") {
  212. // Some parsers accidentally include trailing commas in the
  213. // .loc.end information for ObjectTypeProperty nodes.
  214. if ((end = lines.skipSpaces(end, true, true))) {
  215. loc.end = end;
  216. }
  217. }
  218. }
  219. }
  220. }
  221. exports.fixFaultyLocations = fixFaultyLocations;
  222. ;
  223. function fixForLoopHead(node, lines) {
  224. if (node.type !== "ForStatement") {
  225. return;
  226. }
  227. function fix(child) {
  228. var loc = child && child.loc;
  229. var start = loc && loc.start;
  230. var end = loc && copyPos(loc.end);
  231. while (start && end && comparePos(start, end) < 0) {
  232. lines.prevPos(end);
  233. if (lines.charAt(end) === ";") {
  234. // Update child.loc.end to *exclude* the ';' character.
  235. loc.end.line = end.line;
  236. loc.end.column = end.column;
  237. }
  238. else {
  239. break;
  240. }
  241. }
  242. }
  243. fix(node.init);
  244. fix(node.test);
  245. fix(node.update);
  246. }
  247. function fixTemplateLiteral(node, lines) {
  248. if (node.type !== "TemplateLiteral") {
  249. return;
  250. }
  251. if (node.quasis.length === 0) {
  252. // If there are no quasi elements, then there is nothing to fix.
  253. return;
  254. }
  255. // node.loc is not present when using export default with a template literal
  256. if (node.loc) {
  257. // First we need to exclude the opening ` from the .loc of the first
  258. // quasi element, in case the parser accidentally decided to include it.
  259. var afterLeftBackTickPos = copyPos(node.loc.start);
  260. assert_1.default.strictEqual(lines.charAt(afterLeftBackTickPos), "`");
  261. assert_1.default.ok(lines.nextPos(afterLeftBackTickPos));
  262. var firstQuasi = node.quasis[0];
  263. if (comparePos(firstQuasi.loc.start, afterLeftBackTickPos) < 0) {
  264. firstQuasi.loc.start = afterLeftBackTickPos;
  265. }
  266. // Next we need to exclude the closing ` from the .loc of the last quasi
  267. // element, in case the parser accidentally decided to include it.
  268. var rightBackTickPos = copyPos(node.loc.end);
  269. assert_1.default.ok(lines.prevPos(rightBackTickPos));
  270. assert_1.default.strictEqual(lines.charAt(rightBackTickPos), "`");
  271. var lastQuasi = node.quasis[node.quasis.length - 1];
  272. if (comparePos(rightBackTickPos, lastQuasi.loc.end) < 0) {
  273. lastQuasi.loc.end = rightBackTickPos;
  274. }
  275. }
  276. // Now we need to exclude ${ and } characters from the .loc's of all
  277. // quasi elements, since some parsers accidentally include them.
  278. node.expressions.forEach(function (expr, i) {
  279. // Rewind from expr.loc.start over any whitespace and the ${ that
  280. // precedes the expression. The position of the $ should be the same
  281. // as the .loc.end of the preceding quasi element, but some parsers
  282. // accidentally include the ${ in the .loc of the quasi element.
  283. var dollarCurlyPos = lines.skipSpaces(expr.loc.start, true, false);
  284. if (lines.prevPos(dollarCurlyPos) &&
  285. lines.charAt(dollarCurlyPos) === "{" &&
  286. lines.prevPos(dollarCurlyPos) &&
  287. lines.charAt(dollarCurlyPos) === "$") {
  288. var quasiBefore = node.quasis[i];
  289. if (comparePos(dollarCurlyPos, quasiBefore.loc.end) < 0) {
  290. quasiBefore.loc.end = dollarCurlyPos;
  291. }
  292. }
  293. // Likewise, some parsers accidentally include the } that follows
  294. // the expression in the .loc of the following quasi element.
  295. var rightCurlyPos = lines.skipSpaces(expr.loc.end, false, false);
  296. if (lines.charAt(rightCurlyPos) === "}") {
  297. assert_1.default.ok(lines.nextPos(rightCurlyPos));
  298. // Now rightCurlyPos is technically the position just after the }.
  299. var quasiAfter = node.quasis[i + 1];
  300. if (comparePos(quasiAfter.loc.start, rightCurlyPos) < 0) {
  301. quasiAfter.loc.start = rightCurlyPos;
  302. }
  303. }
  304. });
  305. }
  306. function isExportDeclaration(node) {
  307. if (node)
  308. switch (node.type) {
  309. case "ExportDeclaration":
  310. case "ExportDefaultDeclaration":
  311. case "ExportDefaultSpecifier":
  312. case "DeclareExportDeclaration":
  313. case "ExportNamedDeclaration":
  314. case "ExportAllDeclaration":
  315. return true;
  316. }
  317. return false;
  318. }
  319. exports.isExportDeclaration = isExportDeclaration;
  320. ;
  321. function getParentExportDeclaration(path) {
  322. var parentNode = path.getParentNode();
  323. if (path.getName() === "declaration" &&
  324. isExportDeclaration(parentNode)) {
  325. return parentNode;
  326. }
  327. return null;
  328. }
  329. exports.getParentExportDeclaration = getParentExportDeclaration;
  330. ;
  331. function isTrailingCommaEnabled(options, context) {
  332. var trailingComma = options.trailingComma;
  333. if (typeof trailingComma === "object") {
  334. return !!trailingComma[context];
  335. }
  336. return !!trailingComma;
  337. }
  338. exports.isTrailingCommaEnabled = isTrailingCommaEnabled;
  339. ;