Нет описания

index.js 33KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }/* eslint max-len: 0 */
  2. var _base = require('../traverser/base');
  3. var _util = require('../traverser/util');
  4. var _charcodes = require('../util/charcodes');
  5. var _identifier = require('../util/identifier');
  6. var _whitespace = require('../util/whitespace');
  7. var _keywords = require('./keywords');
  8. var _readWord = require('./readWord'); var _readWord2 = _interopRequireDefault(_readWord);
  9. var _types = require('./types');
  10. var IdentifierRole; (function (IdentifierRole) {
  11. const Access = 0; IdentifierRole[IdentifierRole["Access"] = Access] = "Access";
  12. const ExportAccess = Access + 1; IdentifierRole[IdentifierRole["ExportAccess"] = ExportAccess] = "ExportAccess";
  13. const TopLevelDeclaration = ExportAccess + 1; IdentifierRole[IdentifierRole["TopLevelDeclaration"] = TopLevelDeclaration] = "TopLevelDeclaration";
  14. const FunctionScopedDeclaration = TopLevelDeclaration + 1; IdentifierRole[IdentifierRole["FunctionScopedDeclaration"] = FunctionScopedDeclaration] = "FunctionScopedDeclaration";
  15. const BlockScopedDeclaration = FunctionScopedDeclaration + 1; IdentifierRole[IdentifierRole["BlockScopedDeclaration"] = BlockScopedDeclaration] = "BlockScopedDeclaration";
  16. const ObjectShorthandTopLevelDeclaration = BlockScopedDeclaration + 1; IdentifierRole[IdentifierRole["ObjectShorthandTopLevelDeclaration"] = ObjectShorthandTopLevelDeclaration] = "ObjectShorthandTopLevelDeclaration";
  17. const ObjectShorthandFunctionScopedDeclaration = ObjectShorthandTopLevelDeclaration + 1; IdentifierRole[IdentifierRole["ObjectShorthandFunctionScopedDeclaration"] = ObjectShorthandFunctionScopedDeclaration] = "ObjectShorthandFunctionScopedDeclaration";
  18. const ObjectShorthandBlockScopedDeclaration = ObjectShorthandFunctionScopedDeclaration + 1; IdentifierRole[IdentifierRole["ObjectShorthandBlockScopedDeclaration"] = ObjectShorthandBlockScopedDeclaration] = "ObjectShorthandBlockScopedDeclaration";
  19. const ObjectShorthand = ObjectShorthandBlockScopedDeclaration + 1; IdentifierRole[IdentifierRole["ObjectShorthand"] = ObjectShorthand] = "ObjectShorthand";
  20. // Any identifier bound in an import statement, e.g. both A and b from
  21. // `import A, * as b from 'A';`
  22. const ImportDeclaration = ObjectShorthand + 1; IdentifierRole[IdentifierRole["ImportDeclaration"] = ImportDeclaration] = "ImportDeclaration";
  23. const ObjectKey = ImportDeclaration + 1; IdentifierRole[IdentifierRole["ObjectKey"] = ObjectKey] = "ObjectKey";
  24. // The `foo` in `import {foo as bar} from "./abc";`.
  25. const ImportAccess = ObjectKey + 1; IdentifierRole[IdentifierRole["ImportAccess"] = ImportAccess] = "ImportAccess";
  26. })(IdentifierRole || (exports.IdentifierRole = IdentifierRole = {}));
  27. /**
  28. * Extra information on jsxTagStart tokens, used to determine which of the three
  29. * jsx functions are called in the automatic transform.
  30. */
  31. var JSXRole; (function (JSXRole) {
  32. // The element is self-closing or has a body that resolves to empty. We
  33. // shouldn't emit children at all in this case.
  34. const NoChildren = 0; JSXRole[JSXRole["NoChildren"] = NoChildren] = "NoChildren";
  35. // The element has a single explicit child, which might still be an arbitrary
  36. // expression like an array. We should emit that expression as the children.
  37. const OneChild = NoChildren + 1; JSXRole[JSXRole["OneChild"] = OneChild] = "OneChild";
  38. // The element has at least two explicitly-specified children or has spread
  39. // children, so child positions are assumed to be "static". We should wrap
  40. // these children in an array.
  41. const StaticChildren = OneChild + 1; JSXRole[JSXRole["StaticChildren"] = StaticChildren] = "StaticChildren";
  42. // The element has a prop named "key" after a prop spread, so we should fall
  43. // back to the createElement function.
  44. const KeyAfterPropSpread = StaticChildren + 1; JSXRole[JSXRole["KeyAfterPropSpread"] = KeyAfterPropSpread] = "KeyAfterPropSpread";
  45. })(JSXRole || (exports.JSXRole = JSXRole = {}));
  46. function isDeclaration(token) {
  47. const role = token.identifierRole;
  48. return (
  49. role === IdentifierRole.TopLevelDeclaration ||
  50. role === IdentifierRole.FunctionScopedDeclaration ||
  51. role === IdentifierRole.BlockScopedDeclaration ||
  52. role === IdentifierRole.ObjectShorthandTopLevelDeclaration ||
  53. role === IdentifierRole.ObjectShorthandFunctionScopedDeclaration ||
  54. role === IdentifierRole.ObjectShorthandBlockScopedDeclaration
  55. );
  56. } exports.isDeclaration = isDeclaration;
  57. function isNonTopLevelDeclaration(token) {
  58. const role = token.identifierRole;
  59. return (
  60. role === IdentifierRole.FunctionScopedDeclaration ||
  61. role === IdentifierRole.BlockScopedDeclaration ||
  62. role === IdentifierRole.ObjectShorthandFunctionScopedDeclaration ||
  63. role === IdentifierRole.ObjectShorthandBlockScopedDeclaration
  64. );
  65. } exports.isNonTopLevelDeclaration = isNonTopLevelDeclaration;
  66. function isTopLevelDeclaration(token) {
  67. const role = token.identifierRole;
  68. return (
  69. role === IdentifierRole.TopLevelDeclaration ||
  70. role === IdentifierRole.ObjectShorthandTopLevelDeclaration ||
  71. role === IdentifierRole.ImportDeclaration
  72. );
  73. } exports.isTopLevelDeclaration = isTopLevelDeclaration;
  74. function isBlockScopedDeclaration(token) {
  75. const role = token.identifierRole;
  76. // Treat top-level declarations as block scope since the distinction doesn't matter here.
  77. return (
  78. role === IdentifierRole.TopLevelDeclaration ||
  79. role === IdentifierRole.BlockScopedDeclaration ||
  80. role === IdentifierRole.ObjectShorthandTopLevelDeclaration ||
  81. role === IdentifierRole.ObjectShorthandBlockScopedDeclaration
  82. );
  83. } exports.isBlockScopedDeclaration = isBlockScopedDeclaration;
  84. function isFunctionScopedDeclaration(token) {
  85. const role = token.identifierRole;
  86. return (
  87. role === IdentifierRole.FunctionScopedDeclaration ||
  88. role === IdentifierRole.ObjectShorthandFunctionScopedDeclaration
  89. );
  90. } exports.isFunctionScopedDeclaration = isFunctionScopedDeclaration;
  91. function isObjectShorthandDeclaration(token) {
  92. return (
  93. token.identifierRole === IdentifierRole.ObjectShorthandTopLevelDeclaration ||
  94. token.identifierRole === IdentifierRole.ObjectShorthandBlockScopedDeclaration ||
  95. token.identifierRole === IdentifierRole.ObjectShorthandFunctionScopedDeclaration
  96. );
  97. } exports.isObjectShorthandDeclaration = isObjectShorthandDeclaration;
  98. // Object type used to represent tokens. Note that normally, tokens
  99. // simply exist as properties on the parser object. This is only
  100. // used for the onToken callback and the external tokenizer.
  101. class Token {
  102. constructor() {
  103. this.type = _base.state.type;
  104. this.contextualKeyword = _base.state.contextualKeyword;
  105. this.start = _base.state.start;
  106. this.end = _base.state.end;
  107. this.scopeDepth = _base.state.scopeDepth;
  108. this.isType = _base.state.isType;
  109. this.identifierRole = null;
  110. this.jsxRole = null;
  111. this.shadowsGlobal = false;
  112. this.isAsyncOperation = false;
  113. this.contextId = null;
  114. this.rhsEndIndex = null;
  115. this.isExpression = false;
  116. this.numNullishCoalesceStarts = 0;
  117. this.numNullishCoalesceEnds = 0;
  118. this.isOptionalChainStart = false;
  119. this.isOptionalChainEnd = false;
  120. this.subscriptStartIndex = null;
  121. this.nullishStartIndex = null;
  122. }
  123. // Initially false for all tokens, then may be computed in a follow-up step that does scope
  124. // analysis.
  125. // Initially false for all tokens, but may be set during transform to mark it as containing an
  126. // await operation.
  127. // For assignments, the index of the RHS. For export tokens, the end of the export.
  128. // For class tokens, records if the class is a class expression or a class statement.
  129. // Number of times to insert a `nullishCoalesce(` snippet before this token.
  130. // Number of times to insert a `)` snippet after this token.
  131. // If true, insert an `optionalChain([` snippet before this token.
  132. // If true, insert a `])` snippet after this token.
  133. // Tag for `.`, `?.`, `[`, `?.[`, `(`, and `?.(` to denote the "root" token for this
  134. // subscript chain. This can be used to determine if this chain is an optional chain.
  135. // Tag for `??` operators to denote the root token for this nullish coalescing call.
  136. } exports.Token = Token;
  137. // ## Tokenizer
  138. // Move to the next token
  139. function next() {
  140. _base.state.tokens.push(new Token());
  141. nextToken();
  142. } exports.next = next;
  143. // Call instead of next when inside a template, since that needs to be handled differently.
  144. function nextTemplateToken() {
  145. _base.state.tokens.push(new Token());
  146. _base.state.start = _base.state.pos;
  147. readTmplToken();
  148. } exports.nextTemplateToken = nextTemplateToken;
  149. // The tokenizer never parses regexes by default. Instead, the parser is responsible for
  150. // instructing it to parse a regex when we see a slash at the start of an expression.
  151. function retokenizeSlashAsRegex() {
  152. if (_base.state.type === _types.TokenType.assign) {
  153. --_base.state.pos;
  154. }
  155. readRegexp();
  156. } exports.retokenizeSlashAsRegex = retokenizeSlashAsRegex;
  157. function pushTypeContext(existingTokensInType) {
  158. for (let i = _base.state.tokens.length - existingTokensInType; i < _base.state.tokens.length; i++) {
  159. _base.state.tokens[i].isType = true;
  160. }
  161. const oldIsType = _base.state.isType;
  162. _base.state.isType = true;
  163. return oldIsType;
  164. } exports.pushTypeContext = pushTypeContext;
  165. function popTypeContext(oldIsType) {
  166. _base.state.isType = oldIsType;
  167. } exports.popTypeContext = popTypeContext;
  168. function eat(type) {
  169. if (match(type)) {
  170. next();
  171. return true;
  172. } else {
  173. return false;
  174. }
  175. } exports.eat = eat;
  176. function eatTypeToken(tokenType) {
  177. const oldIsType = _base.state.isType;
  178. _base.state.isType = true;
  179. eat(tokenType);
  180. _base.state.isType = oldIsType;
  181. } exports.eatTypeToken = eatTypeToken;
  182. function match(type) {
  183. return _base.state.type === type;
  184. } exports.match = match;
  185. function lookaheadType() {
  186. const snapshot = _base.state.snapshot();
  187. next();
  188. const type = _base.state.type;
  189. _base.state.restoreFromSnapshot(snapshot);
  190. return type;
  191. } exports.lookaheadType = lookaheadType;
  192. class TypeAndKeyword {
  193. constructor(type, contextualKeyword) {
  194. this.type = type;
  195. this.contextualKeyword = contextualKeyword;
  196. }
  197. } exports.TypeAndKeyword = TypeAndKeyword;
  198. function lookaheadTypeAndKeyword() {
  199. const snapshot = _base.state.snapshot();
  200. next();
  201. const type = _base.state.type;
  202. const contextualKeyword = _base.state.contextualKeyword;
  203. _base.state.restoreFromSnapshot(snapshot);
  204. return new TypeAndKeyword(type, contextualKeyword);
  205. } exports.lookaheadTypeAndKeyword = lookaheadTypeAndKeyword;
  206. function nextTokenStart() {
  207. return nextTokenStartSince(_base.state.pos);
  208. } exports.nextTokenStart = nextTokenStart;
  209. function nextTokenStartSince(pos) {
  210. _whitespace.skipWhiteSpace.lastIndex = pos;
  211. const skip = _whitespace.skipWhiteSpace.exec(_base.input);
  212. return pos + skip[0].length;
  213. } exports.nextTokenStartSince = nextTokenStartSince;
  214. function lookaheadCharCode() {
  215. return _base.input.charCodeAt(nextTokenStart());
  216. } exports.lookaheadCharCode = lookaheadCharCode;
  217. // Read a single token, updating the parser object's token-related
  218. // properties.
  219. function nextToken() {
  220. skipSpace();
  221. _base.state.start = _base.state.pos;
  222. if (_base.state.pos >= _base.input.length) {
  223. const tokens = _base.state.tokens;
  224. // We normally run past the end a bit, but if we're way past the end, avoid an infinite loop.
  225. // Also check the token positions rather than the types since sometimes we rewrite the token
  226. // type to something else.
  227. if (
  228. tokens.length >= 2 &&
  229. tokens[tokens.length - 1].start >= _base.input.length &&
  230. tokens[tokens.length - 2].start >= _base.input.length
  231. ) {
  232. _util.unexpected.call(void 0, "Unexpectedly reached the end of input.");
  233. }
  234. finishToken(_types.TokenType.eof);
  235. return;
  236. }
  237. readToken(_base.input.charCodeAt(_base.state.pos));
  238. } exports.nextToken = nextToken;
  239. function readToken(code) {
  240. // Identifier or keyword. '\uXXXX' sequences are allowed in
  241. // identifiers, so '\' also dispatches to that.
  242. if (
  243. _identifier.IS_IDENTIFIER_START[code] ||
  244. code === _charcodes.charCodes.backslash ||
  245. (code === _charcodes.charCodes.atSign && _base.input.charCodeAt(_base.state.pos + 1) === _charcodes.charCodes.atSign)
  246. ) {
  247. _readWord2.default.call(void 0, );
  248. } else {
  249. getTokenFromCode(code);
  250. }
  251. }
  252. function skipBlockComment() {
  253. while (
  254. _base.input.charCodeAt(_base.state.pos) !== _charcodes.charCodes.asterisk ||
  255. _base.input.charCodeAt(_base.state.pos + 1) !== _charcodes.charCodes.slash
  256. ) {
  257. _base.state.pos++;
  258. if (_base.state.pos > _base.input.length) {
  259. _util.unexpected.call(void 0, "Unterminated comment", _base.state.pos - 2);
  260. return;
  261. }
  262. }
  263. _base.state.pos += 2;
  264. }
  265. function skipLineComment(startSkip) {
  266. let ch = _base.input.charCodeAt((_base.state.pos += startSkip));
  267. if (_base.state.pos < _base.input.length) {
  268. while (
  269. ch !== _charcodes.charCodes.lineFeed &&
  270. ch !== _charcodes.charCodes.carriageReturn &&
  271. ch !== _charcodes.charCodes.lineSeparator &&
  272. ch !== _charcodes.charCodes.paragraphSeparator &&
  273. ++_base.state.pos < _base.input.length
  274. ) {
  275. ch = _base.input.charCodeAt(_base.state.pos);
  276. }
  277. }
  278. } exports.skipLineComment = skipLineComment;
  279. // Called at the start of the parse and after every token. Skips
  280. // whitespace and comments.
  281. function skipSpace() {
  282. while (_base.state.pos < _base.input.length) {
  283. const ch = _base.input.charCodeAt(_base.state.pos);
  284. switch (ch) {
  285. case _charcodes.charCodes.carriageReturn:
  286. if (_base.input.charCodeAt(_base.state.pos + 1) === _charcodes.charCodes.lineFeed) {
  287. ++_base.state.pos;
  288. }
  289. case _charcodes.charCodes.lineFeed:
  290. case _charcodes.charCodes.lineSeparator:
  291. case _charcodes.charCodes.paragraphSeparator:
  292. ++_base.state.pos;
  293. break;
  294. case _charcodes.charCodes.slash:
  295. switch (_base.input.charCodeAt(_base.state.pos + 1)) {
  296. case _charcodes.charCodes.asterisk:
  297. _base.state.pos += 2;
  298. skipBlockComment();
  299. break;
  300. case _charcodes.charCodes.slash:
  301. skipLineComment(2);
  302. break;
  303. default:
  304. return;
  305. }
  306. break;
  307. default:
  308. if (_whitespace.IS_WHITESPACE[ch]) {
  309. ++_base.state.pos;
  310. } else {
  311. return;
  312. }
  313. }
  314. }
  315. } exports.skipSpace = skipSpace;
  316. // Called at the end of every token. Sets various fields, and skips the space after the token, so
  317. // that the next one's `start` will point at the right position.
  318. function finishToken(
  319. type,
  320. contextualKeyword = _keywords.ContextualKeyword.NONE,
  321. ) {
  322. _base.state.end = _base.state.pos;
  323. _base.state.type = type;
  324. _base.state.contextualKeyword = contextualKeyword;
  325. } exports.finishToken = finishToken;
  326. // ### Token reading
  327. // This is the function that is called to fetch the next token. It
  328. // is somewhat obscure, because it works in character codes rather
  329. // than characters, and because operator parsing has been inlined
  330. // into it.
  331. //
  332. // All in the name of speed.
  333. function readToken_dot() {
  334. const nextChar = _base.input.charCodeAt(_base.state.pos + 1);
  335. if (nextChar >= _charcodes.charCodes.digit0 && nextChar <= _charcodes.charCodes.digit9) {
  336. readNumber(true);
  337. return;
  338. }
  339. if (nextChar === _charcodes.charCodes.dot && _base.input.charCodeAt(_base.state.pos + 2) === _charcodes.charCodes.dot) {
  340. _base.state.pos += 3;
  341. finishToken(_types.TokenType.ellipsis);
  342. } else {
  343. ++_base.state.pos;
  344. finishToken(_types.TokenType.dot);
  345. }
  346. }
  347. function readToken_slash() {
  348. const nextChar = _base.input.charCodeAt(_base.state.pos + 1);
  349. if (nextChar === _charcodes.charCodes.equalsTo) {
  350. finishOp(_types.TokenType.assign, 2);
  351. } else {
  352. finishOp(_types.TokenType.slash, 1);
  353. }
  354. }
  355. function readToken_mult_modulo(code) {
  356. // '%*'
  357. let tokenType = code === _charcodes.charCodes.asterisk ? _types.TokenType.star : _types.TokenType.modulo;
  358. let width = 1;
  359. let nextChar = _base.input.charCodeAt(_base.state.pos + 1);
  360. // Exponentiation operator **
  361. if (code === _charcodes.charCodes.asterisk && nextChar === _charcodes.charCodes.asterisk) {
  362. width++;
  363. nextChar = _base.input.charCodeAt(_base.state.pos + 2);
  364. tokenType = _types.TokenType.exponent;
  365. }
  366. // Match *= or %=, disallowing *=> which can be valid in flow.
  367. if (
  368. nextChar === _charcodes.charCodes.equalsTo &&
  369. _base.input.charCodeAt(_base.state.pos + 2) !== _charcodes.charCodes.greaterThan
  370. ) {
  371. width++;
  372. tokenType = _types.TokenType.assign;
  373. }
  374. finishOp(tokenType, width);
  375. }
  376. function readToken_pipe_amp(code) {
  377. // '|&'
  378. const nextChar = _base.input.charCodeAt(_base.state.pos + 1);
  379. if (nextChar === code) {
  380. if (_base.input.charCodeAt(_base.state.pos + 2) === _charcodes.charCodes.equalsTo) {
  381. // ||= or &&=
  382. finishOp(_types.TokenType.assign, 3);
  383. } else {
  384. // || or &&
  385. finishOp(code === _charcodes.charCodes.verticalBar ? _types.TokenType.logicalOR : _types.TokenType.logicalAND, 2);
  386. }
  387. return;
  388. }
  389. if (code === _charcodes.charCodes.verticalBar) {
  390. // '|>'
  391. if (nextChar === _charcodes.charCodes.greaterThan) {
  392. finishOp(_types.TokenType.pipeline, 2);
  393. return;
  394. } else if (nextChar === _charcodes.charCodes.rightCurlyBrace && _base.isFlowEnabled) {
  395. // '|}'
  396. finishOp(_types.TokenType.braceBarR, 2);
  397. return;
  398. }
  399. }
  400. if (nextChar === _charcodes.charCodes.equalsTo) {
  401. finishOp(_types.TokenType.assign, 2);
  402. return;
  403. }
  404. finishOp(code === _charcodes.charCodes.verticalBar ? _types.TokenType.bitwiseOR : _types.TokenType.bitwiseAND, 1);
  405. }
  406. function readToken_caret() {
  407. // '^'
  408. const nextChar = _base.input.charCodeAt(_base.state.pos + 1);
  409. if (nextChar === _charcodes.charCodes.equalsTo) {
  410. finishOp(_types.TokenType.assign, 2);
  411. } else {
  412. finishOp(_types.TokenType.bitwiseXOR, 1);
  413. }
  414. }
  415. function readToken_plus_min(code) {
  416. // '+-'
  417. const nextChar = _base.input.charCodeAt(_base.state.pos + 1);
  418. if (nextChar === code) {
  419. // Tentatively call this a prefix operator, but it might be changed to postfix later.
  420. finishOp(_types.TokenType.preIncDec, 2);
  421. return;
  422. }
  423. if (nextChar === _charcodes.charCodes.equalsTo) {
  424. finishOp(_types.TokenType.assign, 2);
  425. } else if (code === _charcodes.charCodes.plusSign) {
  426. finishOp(_types.TokenType.plus, 1);
  427. } else {
  428. finishOp(_types.TokenType.minus, 1);
  429. }
  430. }
  431. function readToken_lt() {
  432. const nextChar = _base.input.charCodeAt(_base.state.pos + 1);
  433. if (nextChar === _charcodes.charCodes.lessThan) {
  434. if (_base.input.charCodeAt(_base.state.pos + 2) === _charcodes.charCodes.equalsTo) {
  435. finishOp(_types.TokenType.assign, 3);
  436. return;
  437. }
  438. // We see <<, but need to be really careful about whether to treat it as a
  439. // true left-shift or as two < tokens.
  440. if (_base.state.isType) {
  441. // Within a type, << might come up in a snippet like `Array<<T>() => void>`,
  442. // so treat it as two < tokens. Importantly, this should only override <<
  443. // rather than other tokens like <= . If we treated <= as < in a type
  444. // context, then the snippet `a as T <= 1` would incorrectly start parsing
  445. // a type argument on T. We don't need to worry about `a as T << 1`
  446. // because TypeScript disallows that syntax.
  447. finishOp(_types.TokenType.lessThan, 1);
  448. } else {
  449. // Outside a type, this might be a true left-shift operator, or it might
  450. // still be two open-type-arg tokens, such as in `f<<T>() => void>()`. We
  451. // look at the token while considering the `f`, so we don't yet know that
  452. // we're in a type context. In this case, we initially tokenize as a
  453. // left-shift and correct after-the-fact as necessary in
  454. // tsParseTypeArgumentsWithPossibleBitshift .
  455. finishOp(_types.TokenType.bitShiftL, 2);
  456. }
  457. return;
  458. }
  459. if (nextChar === _charcodes.charCodes.equalsTo) {
  460. // <=
  461. finishOp(_types.TokenType.relationalOrEqual, 2);
  462. } else {
  463. finishOp(_types.TokenType.lessThan, 1);
  464. }
  465. }
  466. function readToken_gt() {
  467. if (_base.state.isType) {
  468. // Avoid right-shift for things like `Array<Array<string>>` and
  469. // greater-than-or-equal for things like `const a: Array<number>=[];`.
  470. finishOp(_types.TokenType.greaterThan, 1);
  471. return;
  472. }
  473. const nextChar = _base.input.charCodeAt(_base.state.pos + 1);
  474. if (nextChar === _charcodes.charCodes.greaterThan) {
  475. const size = _base.input.charCodeAt(_base.state.pos + 2) === _charcodes.charCodes.greaterThan ? 3 : 2;
  476. if (_base.input.charCodeAt(_base.state.pos + size) === _charcodes.charCodes.equalsTo) {
  477. finishOp(_types.TokenType.assign, size + 1);
  478. return;
  479. }
  480. finishOp(_types.TokenType.bitShiftR, size);
  481. return;
  482. }
  483. if (nextChar === _charcodes.charCodes.equalsTo) {
  484. // >=
  485. finishOp(_types.TokenType.relationalOrEqual, 2);
  486. } else {
  487. finishOp(_types.TokenType.greaterThan, 1);
  488. }
  489. }
  490. /**
  491. * Called after `as` expressions in TS; we're switching from a type to a
  492. * non-type context, so a > token may actually be >= . This is needed because >=
  493. * must be tokenized as a > in a type context because of code like
  494. * `const x: Array<T>=[];`, but `a as T >= 1` is a code example where it must be
  495. * treated as >=.
  496. *
  497. * Notably, this only applies to >, not <. In a code snippet like `a as T <= 1`,
  498. * we must NOT tokenize as <, or else the type parser will start parsing a type
  499. * argument and fail.
  500. */
  501. function rescan_gt() {
  502. if (_base.state.type === _types.TokenType.greaterThan) {
  503. _base.state.pos -= 1;
  504. readToken_gt();
  505. }
  506. } exports.rescan_gt = rescan_gt;
  507. function readToken_eq_excl(code) {
  508. // '=!'
  509. const nextChar = _base.input.charCodeAt(_base.state.pos + 1);
  510. if (nextChar === _charcodes.charCodes.equalsTo) {
  511. finishOp(_types.TokenType.equality, _base.input.charCodeAt(_base.state.pos + 2) === _charcodes.charCodes.equalsTo ? 3 : 2);
  512. return;
  513. }
  514. if (code === _charcodes.charCodes.equalsTo && nextChar === _charcodes.charCodes.greaterThan) {
  515. // '=>'
  516. _base.state.pos += 2;
  517. finishToken(_types.TokenType.arrow);
  518. return;
  519. }
  520. finishOp(code === _charcodes.charCodes.equalsTo ? _types.TokenType.eq : _types.TokenType.bang, 1);
  521. }
  522. function readToken_question() {
  523. // '?'
  524. const nextChar = _base.input.charCodeAt(_base.state.pos + 1);
  525. const nextChar2 = _base.input.charCodeAt(_base.state.pos + 2);
  526. if (
  527. nextChar === _charcodes.charCodes.questionMark &&
  528. // In Flow (but not TypeScript), ??string is a valid type that should be
  529. // tokenized as two individual ? tokens.
  530. !(_base.isFlowEnabled && _base.state.isType)
  531. ) {
  532. if (nextChar2 === _charcodes.charCodes.equalsTo) {
  533. // '??='
  534. finishOp(_types.TokenType.assign, 3);
  535. } else {
  536. // '??'
  537. finishOp(_types.TokenType.nullishCoalescing, 2);
  538. }
  539. } else if (
  540. nextChar === _charcodes.charCodes.dot &&
  541. !(nextChar2 >= _charcodes.charCodes.digit0 && nextChar2 <= _charcodes.charCodes.digit9)
  542. ) {
  543. // '.' not followed by a number
  544. _base.state.pos += 2;
  545. finishToken(_types.TokenType.questionDot);
  546. } else {
  547. ++_base.state.pos;
  548. finishToken(_types.TokenType.question);
  549. }
  550. }
  551. function getTokenFromCode(code) {
  552. switch (code) {
  553. case _charcodes.charCodes.numberSign:
  554. ++_base.state.pos;
  555. finishToken(_types.TokenType.hash);
  556. return;
  557. // The interpretation of a dot depends on whether it is followed
  558. // by a digit or another two dots.
  559. case _charcodes.charCodes.dot:
  560. readToken_dot();
  561. return;
  562. // Punctuation tokens.
  563. case _charcodes.charCodes.leftParenthesis:
  564. ++_base.state.pos;
  565. finishToken(_types.TokenType.parenL);
  566. return;
  567. case _charcodes.charCodes.rightParenthesis:
  568. ++_base.state.pos;
  569. finishToken(_types.TokenType.parenR);
  570. return;
  571. case _charcodes.charCodes.semicolon:
  572. ++_base.state.pos;
  573. finishToken(_types.TokenType.semi);
  574. return;
  575. case _charcodes.charCodes.comma:
  576. ++_base.state.pos;
  577. finishToken(_types.TokenType.comma);
  578. return;
  579. case _charcodes.charCodes.leftSquareBracket:
  580. ++_base.state.pos;
  581. finishToken(_types.TokenType.bracketL);
  582. return;
  583. case _charcodes.charCodes.rightSquareBracket:
  584. ++_base.state.pos;
  585. finishToken(_types.TokenType.bracketR);
  586. return;
  587. case _charcodes.charCodes.leftCurlyBrace:
  588. if (_base.isFlowEnabled && _base.input.charCodeAt(_base.state.pos + 1) === _charcodes.charCodes.verticalBar) {
  589. finishOp(_types.TokenType.braceBarL, 2);
  590. } else {
  591. ++_base.state.pos;
  592. finishToken(_types.TokenType.braceL);
  593. }
  594. return;
  595. case _charcodes.charCodes.rightCurlyBrace:
  596. ++_base.state.pos;
  597. finishToken(_types.TokenType.braceR);
  598. return;
  599. case _charcodes.charCodes.colon:
  600. if (_base.input.charCodeAt(_base.state.pos + 1) === _charcodes.charCodes.colon) {
  601. finishOp(_types.TokenType.doubleColon, 2);
  602. } else {
  603. ++_base.state.pos;
  604. finishToken(_types.TokenType.colon);
  605. }
  606. return;
  607. case _charcodes.charCodes.questionMark:
  608. readToken_question();
  609. return;
  610. case _charcodes.charCodes.atSign:
  611. ++_base.state.pos;
  612. finishToken(_types.TokenType.at);
  613. return;
  614. case _charcodes.charCodes.graveAccent:
  615. ++_base.state.pos;
  616. finishToken(_types.TokenType.backQuote);
  617. return;
  618. case _charcodes.charCodes.digit0: {
  619. const nextChar = _base.input.charCodeAt(_base.state.pos + 1);
  620. // '0x', '0X', '0o', '0O', '0b', '0B'
  621. if (
  622. nextChar === _charcodes.charCodes.lowercaseX ||
  623. nextChar === _charcodes.charCodes.uppercaseX ||
  624. nextChar === _charcodes.charCodes.lowercaseO ||
  625. nextChar === _charcodes.charCodes.uppercaseO ||
  626. nextChar === _charcodes.charCodes.lowercaseB ||
  627. nextChar === _charcodes.charCodes.uppercaseB
  628. ) {
  629. readRadixNumber();
  630. return;
  631. }
  632. }
  633. // Anything else beginning with a digit is an integer, octal
  634. // number, or float.
  635. case _charcodes.charCodes.digit1:
  636. case _charcodes.charCodes.digit2:
  637. case _charcodes.charCodes.digit3:
  638. case _charcodes.charCodes.digit4:
  639. case _charcodes.charCodes.digit5:
  640. case _charcodes.charCodes.digit6:
  641. case _charcodes.charCodes.digit7:
  642. case _charcodes.charCodes.digit8:
  643. case _charcodes.charCodes.digit9:
  644. readNumber(false);
  645. return;
  646. // Quotes produce strings.
  647. case _charcodes.charCodes.quotationMark:
  648. case _charcodes.charCodes.apostrophe:
  649. readString(code);
  650. return;
  651. // Operators are parsed inline in tiny state machines. '=' (charCodes.equalsTo) is
  652. // often referred to. `finishOp` simply skips the amount of
  653. // characters it is given as second argument, and returns a token
  654. // of the type given by its first argument.
  655. case _charcodes.charCodes.slash:
  656. readToken_slash();
  657. return;
  658. case _charcodes.charCodes.percentSign:
  659. case _charcodes.charCodes.asterisk:
  660. readToken_mult_modulo(code);
  661. return;
  662. case _charcodes.charCodes.verticalBar:
  663. case _charcodes.charCodes.ampersand:
  664. readToken_pipe_amp(code);
  665. return;
  666. case _charcodes.charCodes.caret:
  667. readToken_caret();
  668. return;
  669. case _charcodes.charCodes.plusSign:
  670. case _charcodes.charCodes.dash:
  671. readToken_plus_min(code);
  672. return;
  673. case _charcodes.charCodes.lessThan:
  674. readToken_lt();
  675. return;
  676. case _charcodes.charCodes.greaterThan:
  677. readToken_gt();
  678. return;
  679. case _charcodes.charCodes.equalsTo:
  680. case _charcodes.charCodes.exclamationMark:
  681. readToken_eq_excl(code);
  682. return;
  683. case _charcodes.charCodes.tilde:
  684. finishOp(_types.TokenType.tilde, 1);
  685. return;
  686. default:
  687. break;
  688. }
  689. _util.unexpected.call(void 0, `Unexpected character '${String.fromCharCode(code)}'`, _base.state.pos);
  690. } exports.getTokenFromCode = getTokenFromCode;
  691. function finishOp(type, size) {
  692. _base.state.pos += size;
  693. finishToken(type);
  694. }
  695. function readRegexp() {
  696. const start = _base.state.pos;
  697. let escaped = false;
  698. let inClass = false;
  699. for (;;) {
  700. if (_base.state.pos >= _base.input.length) {
  701. _util.unexpected.call(void 0, "Unterminated regular expression", start);
  702. return;
  703. }
  704. const code = _base.input.charCodeAt(_base.state.pos);
  705. if (escaped) {
  706. escaped = false;
  707. } else {
  708. if (code === _charcodes.charCodes.leftSquareBracket) {
  709. inClass = true;
  710. } else if (code === _charcodes.charCodes.rightSquareBracket && inClass) {
  711. inClass = false;
  712. } else if (code === _charcodes.charCodes.slash && !inClass) {
  713. break;
  714. }
  715. escaped = code === _charcodes.charCodes.backslash;
  716. }
  717. ++_base.state.pos;
  718. }
  719. ++_base.state.pos;
  720. // Need to use `skipWord` because '\uXXXX' sequences are allowed here (don't ask).
  721. skipWord();
  722. finishToken(_types.TokenType.regexp);
  723. }
  724. /**
  725. * Read a decimal integer. Note that this can't be unified with the similar code
  726. * in readRadixNumber (which also handles hex digits) because "e" needs to be
  727. * the end of the integer so that we can properly handle scientific notation.
  728. */
  729. function readInt() {
  730. while (true) {
  731. const code = _base.input.charCodeAt(_base.state.pos);
  732. if ((code >= _charcodes.charCodes.digit0 && code <= _charcodes.charCodes.digit9) || code === _charcodes.charCodes.underscore) {
  733. _base.state.pos++;
  734. } else {
  735. break;
  736. }
  737. }
  738. }
  739. function readRadixNumber() {
  740. _base.state.pos += 2; // 0x
  741. // Walk to the end of the number, allowing hex digits.
  742. while (true) {
  743. const code = _base.input.charCodeAt(_base.state.pos);
  744. if (
  745. (code >= _charcodes.charCodes.digit0 && code <= _charcodes.charCodes.digit9) ||
  746. (code >= _charcodes.charCodes.lowercaseA && code <= _charcodes.charCodes.lowercaseF) ||
  747. (code >= _charcodes.charCodes.uppercaseA && code <= _charcodes.charCodes.uppercaseF) ||
  748. code === _charcodes.charCodes.underscore
  749. ) {
  750. _base.state.pos++;
  751. } else {
  752. break;
  753. }
  754. }
  755. const nextChar = _base.input.charCodeAt(_base.state.pos);
  756. if (nextChar === _charcodes.charCodes.lowercaseN) {
  757. ++_base.state.pos;
  758. finishToken(_types.TokenType.bigint);
  759. } else {
  760. finishToken(_types.TokenType.num);
  761. }
  762. }
  763. // Read an integer, octal integer, or floating-point number.
  764. function readNumber(startsWithDot) {
  765. let isBigInt = false;
  766. let isDecimal = false;
  767. if (!startsWithDot) {
  768. readInt();
  769. }
  770. let nextChar = _base.input.charCodeAt(_base.state.pos);
  771. if (nextChar === _charcodes.charCodes.dot) {
  772. ++_base.state.pos;
  773. readInt();
  774. nextChar = _base.input.charCodeAt(_base.state.pos);
  775. }
  776. if (nextChar === _charcodes.charCodes.uppercaseE || nextChar === _charcodes.charCodes.lowercaseE) {
  777. nextChar = _base.input.charCodeAt(++_base.state.pos);
  778. if (nextChar === _charcodes.charCodes.plusSign || nextChar === _charcodes.charCodes.dash) {
  779. ++_base.state.pos;
  780. }
  781. readInt();
  782. nextChar = _base.input.charCodeAt(_base.state.pos);
  783. }
  784. if (nextChar === _charcodes.charCodes.lowercaseN) {
  785. ++_base.state.pos;
  786. isBigInt = true;
  787. } else if (nextChar === _charcodes.charCodes.lowercaseM) {
  788. ++_base.state.pos;
  789. isDecimal = true;
  790. }
  791. if (isBigInt) {
  792. finishToken(_types.TokenType.bigint);
  793. return;
  794. }
  795. if (isDecimal) {
  796. finishToken(_types.TokenType.decimal);
  797. return;
  798. }
  799. finishToken(_types.TokenType.num);
  800. }
  801. function readString(quote) {
  802. _base.state.pos++;
  803. for (;;) {
  804. if (_base.state.pos >= _base.input.length) {
  805. _util.unexpected.call(void 0, "Unterminated string constant");
  806. return;
  807. }
  808. const ch = _base.input.charCodeAt(_base.state.pos);
  809. if (ch === _charcodes.charCodes.backslash) {
  810. _base.state.pos++;
  811. } else if (ch === quote) {
  812. break;
  813. }
  814. _base.state.pos++;
  815. }
  816. _base.state.pos++;
  817. finishToken(_types.TokenType.string);
  818. }
  819. // Reads template string tokens.
  820. function readTmplToken() {
  821. for (;;) {
  822. if (_base.state.pos >= _base.input.length) {
  823. _util.unexpected.call(void 0, "Unterminated template");
  824. return;
  825. }
  826. const ch = _base.input.charCodeAt(_base.state.pos);
  827. if (
  828. ch === _charcodes.charCodes.graveAccent ||
  829. (ch === _charcodes.charCodes.dollarSign && _base.input.charCodeAt(_base.state.pos + 1) === _charcodes.charCodes.leftCurlyBrace)
  830. ) {
  831. if (_base.state.pos === _base.state.start && match(_types.TokenType.template)) {
  832. if (ch === _charcodes.charCodes.dollarSign) {
  833. _base.state.pos += 2;
  834. finishToken(_types.TokenType.dollarBraceL);
  835. return;
  836. } else {
  837. ++_base.state.pos;
  838. finishToken(_types.TokenType.backQuote);
  839. return;
  840. }
  841. }
  842. finishToken(_types.TokenType.template);
  843. return;
  844. }
  845. if (ch === _charcodes.charCodes.backslash) {
  846. _base.state.pos++;
  847. }
  848. _base.state.pos++;
  849. }
  850. }
  851. // Skip to the end of the current word. Note that this is the same as the snippet at the end of
  852. // readWord, but calling skipWord from readWord seems to slightly hurt performance from some rough
  853. // measurements.
  854. function skipWord() {
  855. while (_base.state.pos < _base.input.length) {
  856. const ch = _base.input.charCodeAt(_base.state.pos);
  857. if (_identifier.IS_IDENTIFIER_CHAR[ch]) {
  858. _base.state.pos++;
  859. } else if (ch === _charcodes.charCodes.backslash) {
  860. // \u
  861. _base.state.pos += 2;
  862. if (_base.input.charCodeAt(_base.state.pos) === _charcodes.charCodes.leftCurlyBrace) {
  863. while (
  864. _base.state.pos < _base.input.length &&
  865. _base.input.charCodeAt(_base.state.pos) !== _charcodes.charCodes.rightCurlyBrace
  866. ) {
  867. _base.state.pos++;
  868. }
  869. _base.state.pos++;
  870. }
  871. } else {
  872. break;
  873. }
  874. }
  875. } exports.skipWord = skipWord;