espree.cjs 30 KB

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