espree.cjs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  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. ];
  261. /**
  262. * Get the latest ECMAScript version supported by Espree.
  263. * @returns {number} The latest ECMAScript version.
  264. */
  265. function getLatestEcmaVersion() {
  266. return SUPPORTED_VERSIONS.at(-1);
  267. }
  268. /**
  269. * Get the list of ECMAScript versions supported by Espree.
  270. * @returns {number[]} An array containing the supported ECMAScript versions.
  271. */
  272. function getSupportedEcmaVersions() {
  273. return [...SUPPORTED_VERSIONS];
  274. }
  275. /**
  276. * Normalize ECMAScript version from the initial config
  277. * @param {(number|"latest")} ecmaVersion ECMAScript version from the initial config
  278. * @throws {Error} throws an error if the ecmaVersion is invalid.
  279. * @returns {number} normalized ECMAScript version
  280. */
  281. function normalizeEcmaVersion(ecmaVersion = 5) {
  282. let version = ecmaVersion === "latest" ? getLatestEcmaVersion() : ecmaVersion;
  283. if (typeof version !== "number") {
  284. throw new Error(`ecmaVersion must be a number or "latest". Received value of type ${typeof ecmaVersion} instead.`);
  285. }
  286. // Calculate ECMAScript edition number from official year version starting with
  287. // ES2015, which corresponds with ES6 (or a difference of 2009).
  288. if (version >= 2015) {
  289. version -= 2009;
  290. }
  291. if (!SUPPORTED_VERSIONS.includes(version)) {
  292. throw new Error("Invalid ecmaVersion.");
  293. }
  294. return version;
  295. }
  296. /**
  297. * Normalize sourceType from the initial config
  298. * @param {string} sourceType to normalize
  299. * @throws {Error} throw an error if sourceType is invalid
  300. * @returns {string} normalized sourceType
  301. */
  302. function normalizeSourceType(sourceType = "script") {
  303. if (sourceType === "script" || sourceType === "module") {
  304. return sourceType;
  305. }
  306. if (sourceType === "commonjs") {
  307. return "script";
  308. }
  309. throw new Error("Invalid sourceType.");
  310. }
  311. /**
  312. * Normalize parserOptions
  313. * @param {Object} options the parser options to normalize
  314. * @throws {Error} throw an error if found invalid option.
  315. * @returns {Object} normalized options
  316. */
  317. function normalizeOptions(options) {
  318. const ecmaVersion = normalizeEcmaVersion(options.ecmaVersion);
  319. const sourceType = normalizeSourceType(options.sourceType);
  320. const ranges = options.range === true;
  321. const locations = options.loc === true;
  322. if (ecmaVersion !== 3 && options.allowReserved) {
  323. // a value of `false` is intentionally allowed here, so a shared config can overwrite it when needed
  324. throw new Error("`allowReserved` is only supported when ecmaVersion is 3");
  325. }
  326. if (typeof options.allowReserved !== "undefined" && typeof options.allowReserved !== "boolean") {
  327. throw new Error("`allowReserved`, when present, must be `true` or `false`");
  328. }
  329. const allowReserved = ecmaVersion === 3 ? (options.allowReserved || "never") : false;
  330. const ecmaFeatures = options.ecmaFeatures || {};
  331. const allowReturnOutsideFunction = options.sourceType === "commonjs" ||
  332. Boolean(ecmaFeatures.globalReturn);
  333. if (sourceType === "module" && ecmaVersion < 6) {
  334. throw new Error("sourceType 'module' is not supported when ecmaVersion < 2015. Consider adding `{ ecmaVersion: 2015 }` to the parser options.");
  335. }
  336. return Object.assign({}, options, {
  337. ecmaVersion,
  338. sourceType,
  339. ranges,
  340. locations,
  341. allowReserved,
  342. allowReturnOutsideFunction
  343. });
  344. }
  345. /* eslint no-param-reassign: 0 -- stylistic choice */
  346. const STATE = Symbol("espree's internal state");
  347. const ESPRIMA_FINISH_NODE = Symbol("espree's esprimaFinishNode");
  348. /**
  349. * Converts an Acorn comment to a Esprima comment.
  350. * @param {boolean} block True if it's a block comment, false if not.
  351. * @param {string} text The text of the comment.
  352. * @param {int} start The index at which the comment starts.
  353. * @param {int} end The index at which the comment ends.
  354. * @param {Location} startLoc The location at which the comment starts.
  355. * @param {Location} endLoc The location at which the comment ends.
  356. * @param {string} code The source code being parsed.
  357. * @returns {Object} The comment object.
  358. * @private
  359. */
  360. function convertAcornCommentToEsprimaComment(block, text, start, end, startLoc, endLoc, code) {
  361. let type;
  362. if (block) {
  363. type = "Block";
  364. } else if (code.slice(start, start + 2) === "#!") {
  365. type = "Hashbang";
  366. } else {
  367. type = "Line";
  368. }
  369. const comment = {
  370. type,
  371. value: text
  372. };
  373. if (typeof start === "number") {
  374. comment.start = start;
  375. comment.end = end;
  376. comment.range = [start, end];
  377. }
  378. if (typeof startLoc === "object") {
  379. comment.loc = {
  380. start: startLoc,
  381. end: endLoc
  382. };
  383. }
  384. return comment;
  385. }
  386. var espree = () => Parser => {
  387. const tokTypes = Object.assign({}, Parser.acorn.tokTypes);
  388. if (Parser.acornJsx) {
  389. Object.assign(tokTypes, Parser.acornJsx.tokTypes);
  390. }
  391. return class Espree extends Parser {
  392. constructor(opts, code) {
  393. if (typeof opts !== "object" || opts === null) {
  394. opts = {};
  395. }
  396. if (typeof code !== "string" && !(code instanceof String)) {
  397. code = String(code);
  398. }
  399. // save original source type in case of commonjs
  400. const originalSourceType = opts.sourceType;
  401. const options = normalizeOptions(opts);
  402. const ecmaFeatures = options.ecmaFeatures || {};
  403. const tokenTranslator =
  404. options.tokens === true
  405. ? new TokenTranslator(tokTypes, code)
  406. : null;
  407. /*
  408. * Data that is unique to Espree and is not represented internally
  409. * in Acorn.
  410. *
  411. * For ES2023 hashbangs, Espree will call `onComment()` during the
  412. * constructor, so we must define state before having access to
  413. * `this`.
  414. */
  415. const state = {
  416. originalSourceType: originalSourceType || options.sourceType,
  417. tokens: tokenTranslator ? [] : null,
  418. comments: options.comment === true ? [] : null,
  419. impliedStrict: ecmaFeatures.impliedStrict === true && options.ecmaVersion >= 5,
  420. ecmaVersion: options.ecmaVersion,
  421. jsxAttrValueToken: false,
  422. lastToken: null,
  423. templateElements: []
  424. };
  425. // Initialize acorn parser.
  426. super({
  427. // do not use spread, because we don't want to pass any unknown options to acorn
  428. ecmaVersion: options.ecmaVersion,
  429. sourceType: options.sourceType,
  430. ranges: options.ranges,
  431. locations: options.locations,
  432. allowReserved: options.allowReserved,
  433. // Truthy value is true for backward compatibility.
  434. allowReturnOutsideFunction: options.allowReturnOutsideFunction,
  435. // Collect tokens
  436. onToken(token) {
  437. if (tokenTranslator) {
  438. // Use `tokens`, `ecmaVersion`, and `jsxAttrValueToken` in the state.
  439. tokenTranslator.onToken(token, state);
  440. }
  441. if (token.type !== tokTypes.eof) {
  442. state.lastToken = token;
  443. }
  444. },
  445. // Collect comments
  446. onComment(block, text, start, end, startLoc, endLoc) {
  447. if (state.comments) {
  448. const comment = convertAcornCommentToEsprimaComment(block, text, start, end, startLoc, endLoc, code);
  449. state.comments.push(comment);
  450. }
  451. }
  452. }, code);
  453. /*
  454. * We put all of this data into a symbol property as a way to avoid
  455. * potential naming conflicts with future versions of Acorn.
  456. */
  457. this[STATE] = state;
  458. }
  459. tokenize() {
  460. do {
  461. this.next();
  462. } while (this.type !== tokTypes.eof);
  463. // Consume the final eof token
  464. this.next();
  465. const extra = this[STATE];
  466. const tokens = extra.tokens;
  467. if (extra.comments) {
  468. tokens.comments = extra.comments;
  469. }
  470. return tokens;
  471. }
  472. finishNode(...args) {
  473. const result = super.finishNode(...args);
  474. return this[ESPRIMA_FINISH_NODE](result);
  475. }
  476. finishNodeAt(...args) {
  477. const result = super.finishNodeAt(...args);
  478. return this[ESPRIMA_FINISH_NODE](result);
  479. }
  480. parse() {
  481. const extra = this[STATE];
  482. const program = super.parse();
  483. program.sourceType = extra.originalSourceType;
  484. if (extra.comments) {
  485. program.comments = extra.comments;
  486. }
  487. if (extra.tokens) {
  488. program.tokens = extra.tokens;
  489. }
  490. /*
  491. * Adjust opening and closing position of program to match Esprima.
  492. * Acorn always starts programs at range 0 whereas Esprima starts at the
  493. * first AST node's start (the only real difference is when there's leading
  494. * whitespace or leading comments). Acorn also counts trailing whitespace
  495. * as part of the program whereas Esprima only counts up to the last token.
  496. */
  497. if (program.body.length) {
  498. const [firstNode] = program.body;
  499. if (program.range) {
  500. program.range[0] = firstNode.range[0];
  501. }
  502. if (program.loc) {
  503. program.loc.start = firstNode.loc.start;
  504. }
  505. program.start = firstNode.start;
  506. }
  507. if (extra.lastToken) {
  508. if (program.range) {
  509. program.range[1] = extra.lastToken.range[1];
  510. }
  511. if (program.loc) {
  512. program.loc.end = extra.lastToken.loc.end;
  513. }
  514. program.end = extra.lastToken.end;
  515. }
  516. /*
  517. * https://github.com/eslint/espree/issues/349
  518. * Ensure that template elements have correct range information.
  519. * This is one location where Acorn produces a different value
  520. * for its start and end properties vs. the values present in the
  521. * range property. In order to avoid confusion, we set the start
  522. * and end properties to the values that are present in range.
  523. * This is done here, instead of in finishNode(), because Acorn
  524. * uses the values of start and end internally while parsing, making
  525. * it dangerous to change those values while parsing is ongoing.
  526. * By waiting until the end of parsing, we can safely change these
  527. * values without affect any other part of the process.
  528. */
  529. this[STATE].templateElements.forEach(templateElement => {
  530. const startOffset = -1;
  531. const endOffset = templateElement.tail ? 1 : 2;
  532. templateElement.start += startOffset;
  533. templateElement.end += endOffset;
  534. if (templateElement.range) {
  535. templateElement.range[0] += startOffset;
  536. templateElement.range[1] += endOffset;
  537. }
  538. if (templateElement.loc) {
  539. templateElement.loc.start.column += startOffset;
  540. templateElement.loc.end.column += endOffset;
  541. }
  542. });
  543. return program;
  544. }
  545. parseTopLevel(node) {
  546. if (this[STATE].impliedStrict) {
  547. this.strict = true;
  548. }
  549. return super.parseTopLevel(node);
  550. }
  551. /**
  552. * Overwrites the default raise method to throw Esprima-style errors.
  553. * @param {int} pos The position of the error.
  554. * @param {string} message The error message.
  555. * @throws {SyntaxError} A syntax error.
  556. * @returns {void}
  557. */
  558. raise(pos, message) {
  559. const loc = Parser.acorn.getLineInfo(this.input, pos);
  560. const err = new SyntaxError(message);
  561. err.index = pos;
  562. err.lineNumber = loc.line;
  563. err.column = loc.column + 1; // acorn uses 0-based columns
  564. throw err;
  565. }
  566. /**
  567. * Overwrites the default raise method to throw Esprima-style errors.
  568. * @param {int} pos The position of the error.
  569. * @param {string} message The error message.
  570. * @throws {SyntaxError} A syntax error.
  571. * @returns {void}
  572. */
  573. raiseRecoverable(pos, message) {
  574. this.raise(pos, message);
  575. }
  576. /**
  577. * Overwrites the default unexpected method to throw Esprima-style errors.
  578. * @param {int} pos The position of the error.
  579. * @throws {SyntaxError} A syntax error.
  580. * @returns {void}
  581. */
  582. unexpected(pos) {
  583. let message = "Unexpected token";
  584. if (pos !== null && pos !== void 0) {
  585. this.pos = pos;
  586. if (this.options.locations) {
  587. while (this.pos < this.lineStart) {
  588. this.lineStart = this.input.lastIndexOf("\n", this.lineStart - 2) + 1;
  589. --this.curLine;
  590. }
  591. }
  592. this.nextToken();
  593. }
  594. if (this.end > this.start) {
  595. message += ` ${this.input.slice(this.start, this.end)}`;
  596. }
  597. this.raise(this.start, message);
  598. }
  599. /*
  600. * Esprima-FB represents JSX strings as tokens called "JSXText", but Acorn-JSX
  601. * uses regular tt.string without any distinction between this and regular JS
  602. * strings. As such, we intercept an attempt to read a JSX string and set a flag
  603. * on extra so that when tokens are converted, the next token will be switched
  604. * to JSXText via onToken.
  605. */
  606. jsx_readString(quote) { // eslint-disable-line camelcase -- required by API
  607. const result = super.jsx_readString(quote);
  608. if (this.type === tokTypes.string) {
  609. this[STATE].jsxAttrValueToken = true;
  610. }
  611. return result;
  612. }
  613. /**
  614. * Performs last-minute Esprima-specific compatibility checks and fixes.
  615. * @param {ASTNode} result The node to check.
  616. * @returns {ASTNode} The finished node.
  617. */
  618. [ESPRIMA_FINISH_NODE](result) {
  619. // Acorn doesn't count the opening and closing backticks as part of templates
  620. // so we have to adjust ranges/locations appropriately.
  621. if (result.type === "TemplateElement") {
  622. // save template element references to fix start/end later
  623. this[STATE].templateElements.push(result);
  624. }
  625. if (result.type.includes("Function") && !result.generator) {
  626. result.generator = false;
  627. }
  628. return result;
  629. }
  630. };
  631. };
  632. const version$1 = "10.2.0";
  633. /**
  634. * @fileoverview Main Espree file that converts Acorn into Esprima output.
  635. *
  636. * This file contains code from the following MIT-licensed projects:
  637. * 1. Acorn
  638. * 2. Babylon
  639. * 3. Babel-ESLint
  640. *
  641. * This file also contains code from Esprima, which is BSD licensed.
  642. *
  643. * Acorn is Copyright 2012-2015 Acorn Contributors (https://github.com/marijnh/acorn/blob/master/AUTHORS)
  644. * Babylon is Copyright 2014-2015 various contributors (https://github.com/babel/babel/blob/master/packages/babylon/AUTHORS)
  645. * Babel-ESLint is Copyright 2014-2015 Sebastian McKenzie <sebmck@gmail.com>
  646. *
  647. * Redistribution and use in source and binary forms, with or without
  648. * modification, are permitted provided that the following conditions are met:
  649. *
  650. * * Redistributions of source code must retain the above copyright
  651. * notice, this list of conditions and the following disclaimer.
  652. * * Redistributions in binary form must reproduce the above copyright
  653. * notice, this list of conditions and the following disclaimer in the
  654. * documentation and/or other materials provided with the distribution.
  655. *
  656. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  657. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  658. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  659. * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  660. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  661. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  662. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  663. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  664. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  665. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  666. *
  667. * Esprima is Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved.
  668. *
  669. * Redistribution and use in source and binary forms, with or without
  670. * modification, are permitted provided that the following conditions are met:
  671. *
  672. * * Redistributions of source code must retain the above copyright
  673. * notice, this list of conditions and the following disclaimer.
  674. * * Redistributions in binary form must reproduce the above copyright
  675. * notice, this list of conditions and the following disclaimer in the
  676. * documentation and/or other materials provided with the distribution.
  677. *
  678. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  679. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  680. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  681. * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  682. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  683. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  684. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  685. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  686. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  687. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  688. */
  689. // To initialize lazily.
  690. const parsers = {
  691. _regular: null,
  692. _jsx: null,
  693. get regular() {
  694. if (this._regular === null) {
  695. this._regular = acorn__namespace.Parser.extend(espree());
  696. }
  697. return this._regular;
  698. },
  699. get jsx() {
  700. if (this._jsx === null) {
  701. this._jsx = acorn__namespace.Parser.extend(jsx__default["default"](), espree());
  702. }
  703. return this._jsx;
  704. },
  705. get(options) {
  706. const useJsx = Boolean(
  707. options &&
  708. options.ecmaFeatures &&
  709. options.ecmaFeatures.jsx
  710. );
  711. return useJsx ? this.jsx : this.regular;
  712. }
  713. };
  714. //------------------------------------------------------------------------------
  715. // Tokenizer
  716. //------------------------------------------------------------------------------
  717. /**
  718. * Tokenizes the given code.
  719. * @param {string} code The code to tokenize.
  720. * @param {Object} options Options defining how to tokenize.
  721. * @returns {Token[]} An array of tokens.
  722. * @throws {SyntaxError} If the input code is invalid.
  723. * @private
  724. */
  725. function tokenize(code, options) {
  726. const Parser = parsers.get(options);
  727. // Ensure to collect tokens.
  728. if (!options || options.tokens !== true) {
  729. options = Object.assign({}, options, { tokens: true }); // eslint-disable-line no-param-reassign -- stylistic choice
  730. }
  731. return new Parser(options, code).tokenize();
  732. }
  733. //------------------------------------------------------------------------------
  734. // Parser
  735. //------------------------------------------------------------------------------
  736. /**
  737. * Parses the given code.
  738. * @param {string} code The code to tokenize.
  739. * @param {Object} options Options defining how to tokenize.
  740. * @returns {ASTNode} The "Program" AST node.
  741. * @throws {SyntaxError} If the input code is invalid.
  742. */
  743. function parse(code, options) {
  744. const Parser = parsers.get(options);
  745. return new Parser(options, code).parse();
  746. }
  747. //------------------------------------------------------------------------------
  748. // Public
  749. //------------------------------------------------------------------------------
  750. const version = version$1;
  751. const name = "espree";
  752. /* istanbul ignore next */
  753. const VisitorKeys = (function() {
  754. return visitorKeys__namespace.KEYS;
  755. }());
  756. // Derive node types from VisitorKeys
  757. /* istanbul ignore next */
  758. const Syntax = (function() {
  759. let key,
  760. types = {};
  761. if (typeof Object.create === "function") {
  762. types = Object.create(null);
  763. }
  764. for (key in VisitorKeys) {
  765. if (Object.hasOwn(VisitorKeys, key)) {
  766. types[key] = key;
  767. }
  768. }
  769. if (typeof Object.freeze === "function") {
  770. Object.freeze(types);
  771. }
  772. return types;
  773. }());
  774. const latestEcmaVersion = getLatestEcmaVersion();
  775. const supportedEcmaVersions = getSupportedEcmaVersions();
  776. exports.Syntax = Syntax;
  777. exports.VisitorKeys = VisitorKeys;
  778. exports.latestEcmaVersion = latestEcmaVersion;
  779. exports.name = name;
  780. exports.parse = parse;
  781. exports.supportedEcmaVersions = supportedEcmaVersions;
  782. exports.tokenize = tokenize;
  783. exports.version = version;