espree.cjs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var acorn = require('acorn');
  4. var jsx = require('acorn-jsx');
  5. var visitorKeys = require('eslint-visitor-keys');
  6. function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
  7. function _interopNamespace(e) {
  8. if (e && e.__esModule) return e;
  9. var n = Object.create(null);
  10. if (e) {
  11. Object.keys(e).forEach(function (k) {
  12. if (k !== 'default') {
  13. var d = Object.getOwnPropertyDescriptor(e, k);
  14. Object.defineProperty(n, k, d.get ? d : {
  15. enumerable: true,
  16. get: function () { return e[k]; }
  17. });
  18. }
  19. });
  20. }
  21. n["default"] = e;
  22. return Object.freeze(n);
  23. }
  24. var acorn__namespace = /*#__PURE__*/_interopNamespace(acorn);
  25. var jsx__default = /*#__PURE__*/_interopDefaultLegacy(jsx);
  26. var visitorKeys__namespace = /*#__PURE__*/_interopNamespace(visitorKeys);
  27. /**
  28. * @fileoverview Translates tokens between Acorn format and Esprima format.
  29. * @author Nicholas C. Zakas
  30. */
  31. /* eslint no-underscore-dangle: 0 */
  32. //------------------------------------------------------------------------------
  33. // Requirements
  34. //------------------------------------------------------------------------------
  35. // none!
  36. //------------------------------------------------------------------------------
  37. // Private
  38. //------------------------------------------------------------------------------
  39. // Esprima Token Types
  40. const Token = {
  41. Boolean: "Boolean",
  42. EOF: "<end>",
  43. Identifier: "Identifier",
  44. PrivateIdentifier: "PrivateIdentifier",
  45. Keyword: "Keyword",
  46. Null: "Null",
  47. Numeric: "Numeric",
  48. Punctuator: "Punctuator",
  49. String: "String",
  50. RegularExpression: "RegularExpression",
  51. Template: "Template",
  52. JSXIdentifier: "JSXIdentifier",
  53. JSXText: "JSXText"
  54. };
  55. /**
  56. * Converts part of a template into an Esprima token.
  57. * @param {AcornToken[]} tokens The Acorn tokens representing the template.
  58. * @param {string} code The source code.
  59. * @returns {EsprimaToken} The Esprima equivalent of the template token.
  60. * @private
  61. */
  62. function convertTemplatePart(tokens, code) {
  63. const firstToken = tokens[0],
  64. lastTemplateToken = tokens[tokens.length - 1];
  65. const token = {
  66. type: Token.Template,
  67. value: code.slice(firstToken.start, lastTemplateToken.end)
  68. };
  69. if (firstToken.loc) {
  70. token.loc = {
  71. start: firstToken.loc.start,
  72. end: lastTemplateToken.loc.end
  73. };
  74. }
  75. if (firstToken.range) {
  76. token.start = firstToken.range[0];
  77. token.end = lastTemplateToken.range[1];
  78. token.range = [token.start, token.end];
  79. }
  80. return token;
  81. }
  82. /**
  83. * Contains logic to translate Acorn tokens into Esprima tokens.
  84. * @param {Object} acornTokTypes The Acorn token types.
  85. * @param {string} code The source code Acorn is parsing. This is necessary
  86. * to correct the "value" property of some tokens.
  87. * @constructor
  88. */
  89. function TokenTranslator(acornTokTypes, code) {
  90. // token types
  91. this._acornTokTypes = acornTokTypes;
  92. // token buffer for templates
  93. this._tokens = [];
  94. // track the last curly brace
  95. this._curlyBrace = null;
  96. // the source code
  97. this._code = code;
  98. }
  99. TokenTranslator.prototype = {
  100. constructor: TokenTranslator,
  101. /**
  102. * Translates a single Esprima token to a single Acorn token. This may be
  103. * inaccurate due to how templates are handled differently in Esprima and
  104. * Acorn, but should be accurate for all other tokens.
  105. * @param {AcornToken} token The Acorn token to translate.
  106. * @param {Object} extra Espree extra object.
  107. * @returns {EsprimaToken} The Esprima version of the token.
  108. */
  109. translate(token, extra) {
  110. const type = token.type,
  111. tt = this._acornTokTypes;
  112. if (type === tt.name) {
  113. token.type = Token.Identifier;
  114. // TODO: See if this is an Acorn bug
  115. if (token.value === "static") {
  116. token.type = Token.Keyword;
  117. }
  118. if (extra.ecmaVersion > 5 && (token.value === "yield" || token.value === "let")) {
  119. token.type = Token.Keyword;
  120. }
  121. } else if (type === tt.privateId) {
  122. token.type = Token.PrivateIdentifier;
  123. } else if (type === tt.semi || type === tt.comma ||
  124. type === tt.parenL || type === tt.parenR ||
  125. type === tt.braceL || type === tt.braceR ||
  126. type === tt.dot || type === tt.bracketL ||
  127. type === tt.colon || type === tt.question ||
  128. type === tt.bracketR || type === tt.ellipsis ||
  129. type === tt.arrow || type === tt.jsxTagStart ||
  130. type === tt.incDec || type === tt.starstar ||
  131. type === tt.jsxTagEnd || type === tt.prefix ||
  132. type === tt.questionDot ||
  133. (type.binop && !type.keyword) ||
  134. type.isAssign) {
  135. token.type = Token.Punctuator;
  136. token.value = this._code.slice(token.start, token.end);
  137. } else if (type === tt.jsxName) {
  138. token.type = Token.JSXIdentifier;
  139. } else if (type.label === "jsxText" || type === tt.jsxAttrValueToken) {
  140. token.type = Token.JSXText;
  141. } else if (type.keyword) {
  142. if (type.keyword === "true" || type.keyword === "false") {
  143. token.type = Token.Boolean;
  144. } else if (type.keyword === "null") {
  145. token.type = Token.Null;
  146. } else {
  147. token.type = Token.Keyword;
  148. }
  149. } else if (type === tt.num) {
  150. token.type = Token.Numeric;
  151. token.value = this._code.slice(token.start, token.end);
  152. } else if (type === tt.string) {
  153. if (extra.jsxAttrValueToken) {
  154. extra.jsxAttrValueToken = false;
  155. token.type = Token.JSXText;
  156. } else {
  157. token.type = Token.String;
  158. }
  159. token.value = this._code.slice(token.start, token.end);
  160. } else if (type === tt.regexp) {
  161. token.type = Token.RegularExpression;
  162. const value = token.value;
  163. token.regex = {
  164. flags: value.flags,
  165. pattern: value.pattern
  166. };
  167. token.value = `/${value.pattern}/${value.flags}`;
  168. }
  169. return token;
  170. },
  171. /**
  172. * Function to call during Acorn's onToken handler.
  173. * @param {AcornToken} token The Acorn token.
  174. * @param {Object} extra The Espree extra object.
  175. * @returns {void}
  176. */
  177. onToken(token, extra) {
  178. const that = this,
  179. tt = this._acornTokTypes,
  180. tokens = extra.tokens,
  181. templateTokens = this._tokens;
  182. /**
  183. * Flushes the buffered template tokens and resets the template
  184. * tracking.
  185. * @returns {void}
  186. * @private
  187. */
  188. function translateTemplateTokens() {
  189. tokens.push(convertTemplatePart(that._tokens, that._code));
  190. that._tokens = [];
  191. }
  192. if (token.type === tt.eof) {
  193. // might be one last curlyBrace
  194. if (this._curlyBrace) {
  195. tokens.push(this.translate(this._curlyBrace, extra));
  196. }
  197. return;
  198. }
  199. if (token.type === tt.backQuote) {
  200. // if there's already a curly, it's not part of the template
  201. if (this._curlyBrace) {
  202. tokens.push(this.translate(this._curlyBrace, extra));
  203. this._curlyBrace = null;
  204. }
  205. templateTokens.push(token);
  206. // it's the end
  207. if (templateTokens.length > 1) {
  208. translateTemplateTokens();
  209. }
  210. return;
  211. }
  212. if (token.type === tt.dollarBraceL) {
  213. templateTokens.push(token);
  214. translateTemplateTokens();
  215. return;
  216. }
  217. if (token.type === tt.braceR) {
  218. // if there's already a curly, it's not part of the template
  219. if (this._curlyBrace) {
  220. tokens.push(this.translate(this._curlyBrace, extra));
  221. }
  222. // store new curly for later
  223. this._curlyBrace = token;
  224. return;
  225. }
  226. if (token.type === tt.template || token.type === tt.invalidTemplate) {
  227. if (this._curlyBrace) {
  228. templateTokens.push(this._curlyBrace);
  229. this._curlyBrace = null;
  230. }
  231. templateTokens.push(token);
  232. return;
  233. }
  234. if (this._curlyBrace) {
  235. tokens.push(this.translate(this._curlyBrace, extra));
  236. this._curlyBrace = null;
  237. }
  238. tokens.push(this.translate(token, extra));
  239. }
  240. };
  241. /**
  242. * @fileoverview A collection of methods for processing Espree's options.
  243. * @author Kai Cataldo
  244. */
  245. //------------------------------------------------------------------------------
  246. // Helpers
  247. //------------------------------------------------------------------------------
  248. const SUPPORTED_VERSIONS = [
  249. 3,
  250. 5,
  251. 6,
  252. 7,
  253. 8,
  254. 9,
  255. 10,
  256. 11,
  257. 12,
  258. 13
  259. ];
  260. /**
  261. * Get the latest ECMAScript version supported by Espree.
  262. * @returns {number} The latest ECMAScript version.
  263. */
  264. function getLatestEcmaVersion() {
  265. return SUPPORTED_VERSIONS[SUPPORTED_VERSIONS.length - 1];
  266. }
  267. /**
  268. * Get the list of ECMAScript versions supported by Espree.
  269. * @returns {number[]} An array containing the supported ECMAScript versions.
  270. */
  271. function getSupportedEcmaVersions() {
  272. return [...SUPPORTED_VERSIONS];
  273. }
  274. /**
  275. * Normalize ECMAScript version from the initial config
  276. * @param {(number|"latest")} ecmaVersion ECMAScript version from the initial config
  277. * @throws {Error} throws an error if the ecmaVersion is invalid.
  278. * @returns {number} normalized ECMAScript version
  279. */
  280. function normalizeEcmaVersion(ecmaVersion = 5) {
  281. let version = ecmaVersion === "latest" ? getLatestEcmaVersion() : ecmaVersion;
  282. if (typeof version !== "number") {
  283. throw new Error(`ecmaVersion must be a number or "latest". Received value of type ${typeof ecmaVersion} instead.`);
  284. }
  285. // Calculate ECMAScript edition number from official year version starting with
  286. // ES2015, which corresponds with ES6 (or a difference of 2009).
  287. if (version >= 2015) {
  288. version -= 2009;
  289. }
  290. if (!SUPPORTED_VERSIONS.includes(version)) {
  291. throw new Error("Invalid ecmaVersion.");
  292. }
  293. return version;
  294. }
  295. /**
  296. * Normalize sourceType from the initial config
  297. * @param {string} sourceType to normalize
  298. * @throws {Error} throw an error if sourceType is invalid
  299. * @returns {string} normalized sourceType
  300. */
  301. function normalizeSourceType(sourceType = "script") {
  302. if (sourceType === "script" || sourceType === "module") {
  303. return sourceType;
  304. }
  305. if (sourceType === "commonjs") {
  306. return "script";
  307. }
  308. throw new Error("Invalid sourceType.");
  309. }
  310. /**
  311. * Normalize parserOptions
  312. * @param {Object} options the parser options to normalize
  313. * @throws {Error} throw an error if found invalid option.
  314. * @returns {Object} normalized options
  315. */
  316. function normalizeOptions(options) {
  317. const ecmaVersion = normalizeEcmaVersion(options.ecmaVersion);
  318. const sourceType = normalizeSourceType(options.sourceType);
  319. const ranges = options.range === true;
  320. const locations = options.loc === true;
  321. if (ecmaVersion !== 3 && options.allowReserved) {
  322. // a value of `false` is intentionally allowed here, so a shared config can overwrite it when needed
  323. throw new Error("`allowReserved` is only supported when ecmaVersion is 3");
  324. }
  325. if (typeof options.allowReserved !== "undefined" && typeof options.allowReserved !== "boolean") {
  326. throw new Error("`allowReserved`, when present, must be `true` or `false`");
  327. }
  328. const allowReserved = ecmaVersion === 3 ? (options.allowReserved || "never") : false;
  329. const ecmaFeatures = options.ecmaFeatures || {};
  330. const allowReturnOutsideFunction = options.sourceType === "commonjs" ||
  331. Boolean(ecmaFeatures.globalReturn);
  332. if (sourceType === "module" && ecmaVersion < 6) {
  333. throw new Error("sourceType 'module' is not supported when ecmaVersion < 2015. Consider adding `{ ecmaVersion: 2015 }` to the parser options.");
  334. }
  335. return Object.assign({}, options, {
  336. ecmaVersion,
  337. sourceType,
  338. ranges,
  339. locations,
  340. allowReserved,
  341. allowReturnOutsideFunction
  342. });
  343. }
  344. /* eslint-disable no-param-reassign*/
  345. const STATE = Symbol("espree's internal state");
  346. const ESPRIMA_FINISH_NODE = Symbol("espree's esprimaFinishNode");
  347. /**
  348. * Converts an Acorn comment to a Esprima comment.
  349. * @param {boolean} block True if it's a block comment, false if not.
  350. * @param {string} text The text of the comment.
  351. * @param {int} start The index at which the comment starts.
  352. * @param {int} end The index at which the comment ends.
  353. * @param {Location} startLoc The location at which the comment starts.
  354. * @param {Location} endLoc The location at which the comment ends.
  355. * @returns {Object} The comment object.
  356. * @private
  357. */
  358. function convertAcornCommentToEsprimaComment(block, text, start, end, startLoc, endLoc) {
  359. const comment = {
  360. type: block ? "Block" : "Line",
  361. value: text
  362. };
  363. if (typeof start === "number") {
  364. comment.start = start;
  365. comment.end = end;
  366. comment.range = [start, end];
  367. }
  368. if (typeof startLoc === "object") {
  369. comment.loc = {
  370. start: startLoc,
  371. end: endLoc
  372. };
  373. }
  374. return comment;
  375. }
  376. var espree = () => Parser => {
  377. const tokTypes = Object.assign({}, Parser.acorn.tokTypes);
  378. if (Parser.acornJsx) {
  379. Object.assign(tokTypes, Parser.acornJsx.tokTypes);
  380. }
  381. return class Espree extends Parser {
  382. constructor(opts, code) {
  383. if (typeof opts !== "object" || opts === null) {
  384. opts = {};
  385. }
  386. if (typeof code !== "string" && !(code instanceof String)) {
  387. code = String(code);
  388. }
  389. // save original source type in case of commonjs
  390. const originalSourceType = opts.sourceType;
  391. const options = normalizeOptions(opts);
  392. const ecmaFeatures = options.ecmaFeatures || {};
  393. const tokenTranslator =
  394. options.tokens === true
  395. ? new TokenTranslator(tokTypes, code)
  396. : null;
  397. // Initialize acorn parser.
  398. super({
  399. // do not use spread, because we don't want to pass any unknown options to acorn
  400. ecmaVersion: options.ecmaVersion,
  401. sourceType: options.sourceType,
  402. ranges: options.ranges,
  403. locations: options.locations,
  404. allowReserved: options.allowReserved,
  405. // Truthy value is true for backward compatibility.
  406. allowReturnOutsideFunction: options.allowReturnOutsideFunction,
  407. // Collect tokens
  408. onToken: token => {
  409. if (tokenTranslator) {
  410. // Use `tokens`, `ecmaVersion`, and `jsxAttrValueToken` in the state.
  411. tokenTranslator.onToken(token, this[STATE]);
  412. }
  413. if (token.type !== tokTypes.eof) {
  414. this[STATE].lastToken = token;
  415. }
  416. },
  417. // Collect comments
  418. onComment: (block, text, start, end, startLoc, endLoc) => {
  419. if (this[STATE].comments) {
  420. const comment = convertAcornCommentToEsprimaComment(block, text, start, end, startLoc, endLoc);
  421. this[STATE].comments.push(comment);
  422. }
  423. }
  424. }, code);
  425. /*
  426. * Data that is unique to Espree and is not represented internally in
  427. * Acorn. We put all of this data into a symbol property as a way to
  428. * avoid potential naming conflicts with future versions of Acorn.
  429. */
  430. this[STATE] = {
  431. originalSourceType: originalSourceType || options.sourceType,
  432. tokens: tokenTranslator ? [] : null,
  433. comments: options.comment === true ? [] : null,
  434. impliedStrict: ecmaFeatures.impliedStrict === true && this.options.ecmaVersion >= 5,
  435. ecmaVersion: this.options.ecmaVersion,
  436. jsxAttrValueToken: false,
  437. lastToken: null,
  438. templateElements: []
  439. };
  440. }
  441. tokenize() {
  442. do {
  443. this.next();
  444. } while (this.type !== tokTypes.eof);
  445. // Consume the final eof token
  446. this.next();
  447. const extra = this[STATE];
  448. const tokens = extra.tokens;
  449. if (extra.comments) {
  450. tokens.comments = extra.comments;
  451. }
  452. return tokens;
  453. }
  454. finishNode(...args) {
  455. const result = super.finishNode(...args);
  456. return this[ESPRIMA_FINISH_NODE](result);
  457. }
  458. finishNodeAt(...args) {
  459. const result = super.finishNodeAt(...args);
  460. return this[ESPRIMA_FINISH_NODE](result);
  461. }
  462. parse() {
  463. const extra = this[STATE];
  464. const program = super.parse();
  465. program.sourceType = extra.originalSourceType;
  466. if (extra.comments) {
  467. program.comments = extra.comments;
  468. }
  469. if (extra.tokens) {
  470. program.tokens = extra.tokens;
  471. }
  472. /*
  473. * Adjust opening and closing position of program to match Esprima.
  474. * Acorn always starts programs at range 0 whereas Esprima starts at the
  475. * first AST node's start (the only real difference is when there's leading
  476. * whitespace or leading comments). Acorn also counts trailing whitespace
  477. * as part of the program whereas Esprima only counts up to the last token.
  478. */
  479. if (program.body.length) {
  480. const [firstNode] = program.body;
  481. if (program.range) {
  482. program.range[0] = firstNode.range[0];
  483. }
  484. if (program.loc) {
  485. program.loc.start = firstNode.loc.start;
  486. }
  487. program.start = firstNode.start;
  488. }
  489. if (extra.lastToken) {
  490. if (program.range) {
  491. program.range[1] = extra.lastToken.range[1];
  492. }
  493. if (program.loc) {
  494. program.loc.end = extra.lastToken.loc.end;
  495. }
  496. program.end = extra.lastToken.end;
  497. }
  498. /*
  499. * https://github.com/eslint/espree/issues/349
  500. * Ensure that template elements have correct range information.
  501. * This is one location where Acorn produces a different value
  502. * for its start and end properties vs. the values present in the
  503. * range property. In order to avoid confusion, we set the start
  504. * and end properties to the values that are present in range.
  505. * This is done here, instead of in finishNode(), because Acorn
  506. * uses the values of start and end internally while parsing, making
  507. * it dangerous to change those values while parsing is ongoing.
  508. * By waiting until the end of parsing, we can safely change these
  509. * values without affect any other part of the process.
  510. */
  511. this[STATE].templateElements.forEach(templateElement => {
  512. const startOffset = -1;
  513. const endOffset = templateElement.tail ? 1 : 2;
  514. templateElement.start += startOffset;
  515. templateElement.end += endOffset;
  516. if (templateElement.range) {
  517. templateElement.range[0] += startOffset;
  518. templateElement.range[1] += endOffset;
  519. }
  520. if (templateElement.loc) {
  521. templateElement.loc.start.column += startOffset;
  522. templateElement.loc.end.column += endOffset;
  523. }
  524. });
  525. return program;
  526. }
  527. parseTopLevel(node) {
  528. if (this[STATE].impliedStrict) {
  529. this.strict = true;
  530. }
  531. return super.parseTopLevel(node);
  532. }
  533. /**
  534. * Overwrites the default raise method to throw Esprima-style errors.
  535. * @param {int} pos The position of the error.
  536. * @param {string} message The error message.
  537. * @throws {SyntaxError} A syntax error.
  538. * @returns {void}
  539. */
  540. raise(pos, message) {
  541. const loc = Parser.acorn.getLineInfo(this.input, pos);
  542. const err = new SyntaxError(message);
  543. err.index = pos;
  544. err.lineNumber = loc.line;
  545. err.column = loc.column + 1; // acorn uses 0-based columns
  546. throw err;
  547. }
  548. /**
  549. * Overwrites the default raise method to throw Esprima-style errors.
  550. * @param {int} pos The position of the error.
  551. * @param {string} message The error message.
  552. * @throws {SyntaxError} A syntax error.
  553. * @returns {void}
  554. */
  555. raiseRecoverable(pos, message) {
  556. this.raise(pos, message);
  557. }
  558. /**
  559. * Overwrites the default unexpected method to throw Esprima-style errors.
  560. * @param {int} pos The position of the error.
  561. * @throws {SyntaxError} A syntax error.
  562. * @returns {void}
  563. */
  564. unexpected(pos) {
  565. let message = "Unexpected token";
  566. if (pos !== null && pos !== void 0) {
  567. this.pos = pos;
  568. if (this.options.locations) {
  569. while (this.pos < this.lineStart) {
  570. this.lineStart = this.input.lastIndexOf("\n", this.lineStart - 2) + 1;
  571. --this.curLine;
  572. }
  573. }
  574. this.nextToken();
  575. }
  576. if (this.end > this.start) {
  577. message += ` ${this.input.slice(this.start, this.end)}`;
  578. }
  579. this.raise(this.start, message);
  580. }
  581. /*
  582. * Esprima-FB represents JSX strings as tokens called "JSXText", but Acorn-JSX
  583. * uses regular tt.string without any distinction between this and regular JS
  584. * strings. As such, we intercept an attempt to read a JSX string and set a flag
  585. * on extra so that when tokens are converted, the next token will be switched
  586. * to JSXText via onToken.
  587. */
  588. jsx_readString(quote) { // eslint-disable-line camelcase
  589. const result = super.jsx_readString(quote);
  590. if (this.type === tokTypes.string) {
  591. this[STATE].jsxAttrValueToken = true;
  592. }
  593. return result;
  594. }
  595. /**
  596. * Performs last-minute Esprima-specific compatibility checks and fixes.
  597. * @param {ASTNode} result The node to check.
  598. * @returns {ASTNode} The finished node.
  599. */
  600. [ESPRIMA_FINISH_NODE](result) {
  601. // Acorn doesn't count the opening and closing backticks as part of templates
  602. // so we have to adjust ranges/locations appropriately.
  603. if (result.type === "TemplateElement") {
  604. // save template element references to fix start/end later
  605. this[STATE].templateElements.push(result);
  606. }
  607. if (result.type.includes("Function") && !result.generator) {
  608. result.generator = false;
  609. }
  610. return result;
  611. }
  612. };
  613. };
  614. const version$1 = "9.3.1";
  615. /**
  616. * @fileoverview Main Espree file that converts Acorn into Esprima output.
  617. *
  618. * This file contains code from the following MIT-licensed projects:
  619. * 1. Acorn
  620. * 2. Babylon
  621. * 3. Babel-ESLint
  622. *
  623. * This file also contains code from Esprima, which is BSD licensed.
  624. *
  625. * Acorn is Copyright 2012-2015 Acorn Contributors (https://github.com/marijnh/acorn/blob/master/AUTHORS)
  626. * Babylon is Copyright 2014-2015 various contributors (https://github.com/babel/babel/blob/master/packages/babylon/AUTHORS)
  627. * Babel-ESLint is Copyright 2014-2015 Sebastian McKenzie <sebmck@gmail.com>
  628. *
  629. * Redistribution and use in source and binary forms, with or without
  630. * modification, are permitted provided that the following conditions are met:
  631. *
  632. * * Redistributions of source code must retain the above copyright
  633. * notice, this list of conditions and the following disclaimer.
  634. * * Redistributions in binary form must reproduce the above copyright
  635. * notice, this list of conditions and the following disclaimer in the
  636. * documentation and/or other materials provided with the distribution.
  637. *
  638. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  639. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  640. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  641. * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  642. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  643. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  644. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  645. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  646. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  647. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  648. *
  649. * Esprima is Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved.
  650. *
  651. * Redistribution and use in source and binary forms, with or without
  652. * modification, are permitted provided that the following conditions are met:
  653. *
  654. * * Redistributions of source code must retain the above copyright
  655. * notice, this list of conditions and the following disclaimer.
  656. * * Redistributions in binary form must reproduce the above copyright
  657. * notice, this list of conditions and the following disclaimer in the
  658. * documentation and/or other materials provided with the distribution.
  659. *
  660. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  661. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  662. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  663. * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  664. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  665. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  666. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  667. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  668. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  669. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  670. */
  671. // To initialize lazily.
  672. const parsers = {
  673. _regular: null,
  674. _jsx: null,
  675. get regular() {
  676. if (this._regular === null) {
  677. this._regular = acorn__namespace.Parser.extend(espree());
  678. }
  679. return this._regular;
  680. },
  681. get jsx() {
  682. if (this._jsx === null) {
  683. this._jsx = acorn__namespace.Parser.extend(jsx__default["default"](), espree());
  684. }
  685. return this._jsx;
  686. },
  687. get(options) {
  688. const useJsx = Boolean(
  689. options &&
  690. options.ecmaFeatures &&
  691. options.ecmaFeatures.jsx
  692. );
  693. return useJsx ? this.jsx : this.regular;
  694. }
  695. };
  696. //------------------------------------------------------------------------------
  697. // Tokenizer
  698. //------------------------------------------------------------------------------
  699. /**
  700. * Tokenizes the given code.
  701. * @param {string} code The code to tokenize.
  702. * @param {Object} options Options defining how to tokenize.
  703. * @returns {Token[]} An array of tokens.
  704. * @throws {SyntaxError} If the input code is invalid.
  705. * @private
  706. */
  707. function tokenize(code, options) {
  708. const Parser = parsers.get(options);
  709. // Ensure to collect tokens.
  710. if (!options || options.tokens !== true) {
  711. options = Object.assign({}, options, { tokens: true }); // eslint-disable-line no-param-reassign
  712. }
  713. return new Parser(options, code).tokenize();
  714. }
  715. //------------------------------------------------------------------------------
  716. // Parser
  717. //------------------------------------------------------------------------------
  718. /**
  719. * Parses the given code.
  720. * @param {string} code The code to tokenize.
  721. * @param {Object} options Options defining how to tokenize.
  722. * @returns {ASTNode} The "Program" AST node.
  723. * @throws {SyntaxError} If the input code is invalid.
  724. */
  725. function parse(code, options) {
  726. const Parser = parsers.get(options);
  727. return new Parser(options, code).parse();
  728. }
  729. //------------------------------------------------------------------------------
  730. // Public
  731. //------------------------------------------------------------------------------
  732. const version = version$1;
  733. /* istanbul ignore next */
  734. const VisitorKeys = (function() {
  735. return visitorKeys__namespace.KEYS;
  736. }());
  737. // Derive node types from VisitorKeys
  738. /* istanbul ignore next */
  739. const Syntax = (function() {
  740. let name,
  741. types = {};
  742. if (typeof Object.create === "function") {
  743. types = Object.create(null);
  744. }
  745. for (name in VisitorKeys) {
  746. if (Object.hasOwnProperty.call(VisitorKeys, name)) {
  747. types[name] = name;
  748. }
  749. }
  750. if (typeof Object.freeze === "function") {
  751. Object.freeze(types);
  752. }
  753. return types;
  754. }());
  755. const latestEcmaVersion = getLatestEcmaVersion();
  756. const supportedEcmaVersions = getSupportedEcmaVersions();
  757. exports.Syntax = Syntax;
  758. exports.VisitorKeys = VisitorKeys;
  759. exports.latestEcmaVersion = latestEcmaVersion;
  760. exports.parse = parse;
  761. exports.supportedEcmaVersions = supportedEcmaVersions;
  762. exports.tokenize = tokenize;
  763. exports.version = version;
  764. //# sourceMappingURL=espree.cjs.map