Нет описания

statement.js 32KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282
  1. /* eslint max-len: 0 */
  2. import {File} from "../index";
  3. import {
  4. flowAfterParseClassSuper,
  5. flowAfterParseVarHead,
  6. flowParseExportDeclaration,
  7. flowParseExportStar,
  8. flowParseIdentifierStatement,
  9. flowParseImportSpecifier,
  10. flowParseTypeAnnotation,
  11. flowParseTypeParameterDeclaration,
  12. flowShouldDisallowExportDefaultSpecifier,
  13. flowShouldParseExportDeclaration,
  14. flowShouldParseExportStar,
  15. flowStartParseFunctionParams,
  16. flowStartParseImportSpecifiers,
  17. flowTryParseExportDefaultExpression,
  18. flowTryParseStatement,
  19. } from "../plugins/flow";
  20. import {
  21. tsAfterParseClassSuper,
  22. tsAfterParseVarHead,
  23. tsIsDeclarationStart,
  24. tsParseExportDeclaration,
  25. tsParseExportSpecifier,
  26. tsParseIdentifierStatement,
  27. tsParseImportEqualsDeclaration,
  28. tsParseImportSpecifier,
  29. tsParseMaybeDecoratorArguments,
  30. tsParseModifiers,
  31. tsStartParseFunctionParams,
  32. tsTryParseClassMemberWithIsStatic,
  33. tsTryParseExport,
  34. tsTryParseExportDefaultExpression,
  35. tsTryParseStatementContent,
  36. tsTryParseTypeAnnotation,
  37. tsTryParseTypeParameters,
  38. } from "../plugins/typescript";
  39. import {
  40. eat,
  41. eatTypeToken,
  42. IdentifierRole,
  43. lookaheadType,
  44. lookaheadTypeAndKeyword,
  45. match,
  46. next,
  47. nextTokenStart,
  48. nextTokenStartSince,
  49. popTypeContext,
  50. pushTypeContext,
  51. } from "../tokenizer";
  52. import {ContextualKeyword} from "../tokenizer/keywords";
  53. import {Scope} from "../tokenizer/state";
  54. import { TokenType as tt} from "../tokenizer/types";
  55. import {charCodes} from "../util/charcodes";
  56. import {getNextContextId, input, isFlowEnabled, isTypeScriptEnabled, state} from "./base";
  57. import {
  58. parseCallExpressionArguments,
  59. parseExprAtom,
  60. parseExpression,
  61. parseExprSubscripts,
  62. parseFunctionBodyAndFinish,
  63. parseIdentifier,
  64. parseMaybeAssign,
  65. parseMethod,
  66. parseObj,
  67. parseParenExpression,
  68. parsePropertyName,
  69. } from "./expression";
  70. import {
  71. parseBindingAtom,
  72. parseBindingIdentifier,
  73. parseBindingList,
  74. parseImportedIdentifier,
  75. } from "./lval";
  76. import {
  77. canInsertSemicolon,
  78. eatContextual,
  79. expect,
  80. expectContextual,
  81. hasFollowingLineBreak,
  82. hasPrecedingLineBreak,
  83. isContextual,
  84. isLineTerminator,
  85. isLookaheadContextual,
  86. semicolon,
  87. unexpected,
  88. } from "./util";
  89. export function parseTopLevel() {
  90. parseBlockBody(tt.eof);
  91. state.scopes.push(new Scope(0, state.tokens.length, true));
  92. if (state.scopeDepth !== 0) {
  93. throw new Error(`Invalid scope depth at end of file: ${state.scopeDepth}`);
  94. }
  95. return new File(state.tokens, state.scopes);
  96. }
  97. // Parse a single statement.
  98. //
  99. // If expecting a statement and finding a slash operator, parse a
  100. // regular expression literal. This is to handle cases like
  101. // `if (foo) /blah/.exec(foo)`, where looking at the previous token
  102. // does not help.
  103. export function parseStatement(declaration) {
  104. if (isFlowEnabled) {
  105. if (flowTryParseStatement()) {
  106. return;
  107. }
  108. }
  109. if (match(tt.at)) {
  110. parseDecorators();
  111. }
  112. parseStatementContent(declaration);
  113. }
  114. function parseStatementContent(declaration) {
  115. if (isTypeScriptEnabled) {
  116. if (tsTryParseStatementContent()) {
  117. return;
  118. }
  119. }
  120. const starttype = state.type;
  121. // Most types of statements are recognized by the keyword they
  122. // start with. Many are trivial to parse, some require a bit of
  123. // complexity.
  124. switch (starttype) {
  125. case tt._break:
  126. case tt._continue:
  127. parseBreakContinueStatement();
  128. return;
  129. case tt._debugger:
  130. parseDebuggerStatement();
  131. return;
  132. case tt._do:
  133. parseDoStatement();
  134. return;
  135. case tt._for:
  136. parseForStatement();
  137. return;
  138. case tt._function:
  139. if (lookaheadType() === tt.dot) break;
  140. if (!declaration) unexpected();
  141. parseFunctionStatement();
  142. return;
  143. case tt._class:
  144. if (!declaration) unexpected();
  145. parseClass(true);
  146. return;
  147. case tt._if:
  148. parseIfStatement();
  149. return;
  150. case tt._return:
  151. parseReturnStatement();
  152. return;
  153. case tt._switch:
  154. parseSwitchStatement();
  155. return;
  156. case tt._throw:
  157. parseThrowStatement();
  158. return;
  159. case tt._try:
  160. parseTryStatement();
  161. return;
  162. case tt._let:
  163. case tt._const:
  164. if (!declaration) unexpected(); // NOTE: falls through to _var
  165. case tt._var:
  166. parseVarStatement(starttype !== tt._var);
  167. return;
  168. case tt._while:
  169. parseWhileStatement();
  170. return;
  171. case tt.braceL:
  172. parseBlock();
  173. return;
  174. case tt.semi:
  175. parseEmptyStatement();
  176. return;
  177. case tt._export:
  178. case tt._import: {
  179. const nextType = lookaheadType();
  180. if (nextType === tt.parenL || nextType === tt.dot) {
  181. break;
  182. }
  183. next();
  184. if (starttype === tt._import) {
  185. parseImport();
  186. } else {
  187. parseExport();
  188. }
  189. return;
  190. }
  191. case tt.name:
  192. if (state.contextualKeyword === ContextualKeyword._async) {
  193. const functionStart = state.start;
  194. // peek ahead and see if next token is a function
  195. const snapshot = state.snapshot();
  196. next();
  197. if (match(tt._function) && !canInsertSemicolon()) {
  198. expect(tt._function);
  199. parseFunction(functionStart, true);
  200. return;
  201. } else {
  202. state.restoreFromSnapshot(snapshot);
  203. }
  204. } else if (
  205. state.contextualKeyword === ContextualKeyword._using &&
  206. !hasFollowingLineBreak() &&
  207. // Statements like `using[0]` and `using in foo` aren't actual using
  208. // declarations.
  209. lookaheadType() === tt.name
  210. ) {
  211. parseVarStatement(true);
  212. return;
  213. }
  214. default:
  215. // Do nothing.
  216. break;
  217. }
  218. // If the statement does not start with a statement keyword or a
  219. // brace, it's an ExpressionStatement or LabeledStatement. We
  220. // simply start parsing an expression, and afterwards, if the
  221. // next token is a colon and the expression was a simple
  222. // Identifier node, we switch to interpreting it as a label.
  223. const initialTokensLength = state.tokens.length;
  224. parseExpression();
  225. let simpleName = null;
  226. if (state.tokens.length === initialTokensLength + 1) {
  227. const token = state.tokens[state.tokens.length - 1];
  228. if (token.type === tt.name) {
  229. simpleName = token.contextualKeyword;
  230. }
  231. }
  232. if (simpleName == null) {
  233. semicolon();
  234. return;
  235. }
  236. if (eat(tt.colon)) {
  237. parseLabeledStatement();
  238. } else {
  239. // This was an identifier, so we might want to handle flow/typescript-specific cases.
  240. parseIdentifierStatement(simpleName);
  241. }
  242. }
  243. export function parseDecorators() {
  244. while (match(tt.at)) {
  245. parseDecorator();
  246. }
  247. }
  248. function parseDecorator() {
  249. next();
  250. if (eat(tt.parenL)) {
  251. parseExpression();
  252. expect(tt.parenR);
  253. } else {
  254. parseIdentifier();
  255. while (eat(tt.dot)) {
  256. parseIdentifier();
  257. }
  258. parseMaybeDecoratorArguments();
  259. }
  260. }
  261. function parseMaybeDecoratorArguments() {
  262. if (isTypeScriptEnabled) {
  263. tsParseMaybeDecoratorArguments();
  264. } else {
  265. baseParseMaybeDecoratorArguments();
  266. }
  267. }
  268. export function baseParseMaybeDecoratorArguments() {
  269. if (eat(tt.parenL)) {
  270. parseCallExpressionArguments();
  271. }
  272. }
  273. function parseBreakContinueStatement() {
  274. next();
  275. if (!isLineTerminator()) {
  276. parseIdentifier();
  277. semicolon();
  278. }
  279. }
  280. function parseDebuggerStatement() {
  281. next();
  282. semicolon();
  283. }
  284. function parseDoStatement() {
  285. next();
  286. parseStatement(false);
  287. expect(tt._while);
  288. parseParenExpression();
  289. eat(tt.semi);
  290. }
  291. function parseForStatement() {
  292. state.scopeDepth++;
  293. const startTokenIndex = state.tokens.length;
  294. parseAmbiguousForStatement();
  295. const endTokenIndex = state.tokens.length;
  296. state.scopes.push(new Scope(startTokenIndex, endTokenIndex, false));
  297. state.scopeDepth--;
  298. }
  299. /**
  300. * Determine if this token is a `using` declaration (explicit resource
  301. * management) as part of a loop.
  302. * https://github.com/tc39/proposal-explicit-resource-management
  303. */
  304. function isUsingInLoop() {
  305. if (!isContextual(ContextualKeyword._using)) {
  306. return false;
  307. }
  308. // This must be `for (using of`, where `using` is the name of the loop
  309. // variable.
  310. if (isLookaheadContextual(ContextualKeyword._of)) {
  311. return false;
  312. }
  313. return true;
  314. }
  315. // Disambiguating between a `for` and a `for`/`in` or `for`/`of`
  316. // loop is non-trivial. Basically, we have to parse the init `var`
  317. // statement or expression, disallowing the `in` operator (see
  318. // the second parameter to `parseExpression`), and then check
  319. // whether the next token is `in` or `of`. When there is no init
  320. // part (semicolon immediately after the opening parenthesis), it
  321. // is a regular `for` loop.
  322. function parseAmbiguousForStatement() {
  323. next();
  324. let forAwait = false;
  325. if (isContextual(ContextualKeyword._await)) {
  326. forAwait = true;
  327. next();
  328. }
  329. expect(tt.parenL);
  330. if (match(tt.semi)) {
  331. if (forAwait) {
  332. unexpected();
  333. }
  334. parseFor();
  335. return;
  336. }
  337. if (match(tt._var) || match(tt._let) || match(tt._const) || isUsingInLoop()) {
  338. next();
  339. parseVar(true, state.type !== tt._var);
  340. if (match(tt._in) || isContextual(ContextualKeyword._of)) {
  341. parseForIn(forAwait);
  342. return;
  343. }
  344. parseFor();
  345. return;
  346. }
  347. parseExpression(true);
  348. if (match(tt._in) || isContextual(ContextualKeyword._of)) {
  349. parseForIn(forAwait);
  350. return;
  351. }
  352. if (forAwait) {
  353. unexpected();
  354. }
  355. parseFor();
  356. }
  357. function parseFunctionStatement() {
  358. const functionStart = state.start;
  359. next();
  360. parseFunction(functionStart, true);
  361. }
  362. function parseIfStatement() {
  363. next();
  364. parseParenExpression();
  365. parseStatement(false);
  366. if (eat(tt._else)) {
  367. parseStatement(false);
  368. }
  369. }
  370. function parseReturnStatement() {
  371. next();
  372. // In `return` (and `break`/`continue`), the keywords with
  373. // optional arguments, we eagerly look for a semicolon or the
  374. // possibility to insert one.
  375. if (!isLineTerminator()) {
  376. parseExpression();
  377. semicolon();
  378. }
  379. }
  380. function parseSwitchStatement() {
  381. next();
  382. parseParenExpression();
  383. state.scopeDepth++;
  384. const startTokenIndex = state.tokens.length;
  385. expect(tt.braceL);
  386. // Don't bother validation; just go through any sequence of cases, defaults, and statements.
  387. while (!match(tt.braceR) && !state.error) {
  388. if (match(tt._case) || match(tt._default)) {
  389. const isCase = match(tt._case);
  390. next();
  391. if (isCase) {
  392. parseExpression();
  393. }
  394. expect(tt.colon);
  395. } else {
  396. parseStatement(true);
  397. }
  398. }
  399. next(); // Closing brace
  400. const endTokenIndex = state.tokens.length;
  401. state.scopes.push(new Scope(startTokenIndex, endTokenIndex, false));
  402. state.scopeDepth--;
  403. }
  404. function parseThrowStatement() {
  405. next();
  406. parseExpression();
  407. semicolon();
  408. }
  409. function parseCatchClauseParam() {
  410. parseBindingAtom(true /* isBlockScope */);
  411. if (isTypeScriptEnabled) {
  412. tsTryParseTypeAnnotation();
  413. }
  414. }
  415. function parseTryStatement() {
  416. next();
  417. parseBlock();
  418. if (match(tt._catch)) {
  419. next();
  420. let catchBindingStartTokenIndex = null;
  421. if (match(tt.parenL)) {
  422. state.scopeDepth++;
  423. catchBindingStartTokenIndex = state.tokens.length;
  424. expect(tt.parenL);
  425. parseCatchClauseParam();
  426. expect(tt.parenR);
  427. }
  428. parseBlock();
  429. if (catchBindingStartTokenIndex != null) {
  430. // We need a special scope for the catch binding which includes the binding itself and the
  431. // catch block.
  432. const endTokenIndex = state.tokens.length;
  433. state.scopes.push(new Scope(catchBindingStartTokenIndex, endTokenIndex, false));
  434. state.scopeDepth--;
  435. }
  436. }
  437. if (eat(tt._finally)) {
  438. parseBlock();
  439. }
  440. }
  441. export function parseVarStatement(isBlockScope) {
  442. next();
  443. parseVar(false, isBlockScope);
  444. semicolon();
  445. }
  446. function parseWhileStatement() {
  447. next();
  448. parseParenExpression();
  449. parseStatement(false);
  450. }
  451. function parseEmptyStatement() {
  452. next();
  453. }
  454. function parseLabeledStatement() {
  455. parseStatement(true);
  456. }
  457. /**
  458. * Parse a statement starting with an identifier of the given name. Subclasses match on the name
  459. * to handle statements like "declare".
  460. */
  461. function parseIdentifierStatement(contextualKeyword) {
  462. if (isTypeScriptEnabled) {
  463. tsParseIdentifierStatement(contextualKeyword);
  464. } else if (isFlowEnabled) {
  465. flowParseIdentifierStatement(contextualKeyword);
  466. } else {
  467. semicolon();
  468. }
  469. }
  470. // Parse a semicolon-enclosed block of statements.
  471. export function parseBlock(isFunctionScope = false, contextId = 0) {
  472. const startTokenIndex = state.tokens.length;
  473. state.scopeDepth++;
  474. expect(tt.braceL);
  475. if (contextId) {
  476. state.tokens[state.tokens.length - 1].contextId = contextId;
  477. }
  478. parseBlockBody(tt.braceR);
  479. if (contextId) {
  480. state.tokens[state.tokens.length - 1].contextId = contextId;
  481. }
  482. const endTokenIndex = state.tokens.length;
  483. state.scopes.push(new Scope(startTokenIndex, endTokenIndex, isFunctionScope));
  484. state.scopeDepth--;
  485. }
  486. export function parseBlockBody(end) {
  487. while (!eat(end) && !state.error) {
  488. parseStatement(true);
  489. }
  490. }
  491. // Parse a regular `for` loop. The disambiguation code in
  492. // `parseStatement` will already have parsed the init statement or
  493. // expression.
  494. function parseFor() {
  495. expect(tt.semi);
  496. if (!match(tt.semi)) {
  497. parseExpression();
  498. }
  499. expect(tt.semi);
  500. if (!match(tt.parenR)) {
  501. parseExpression();
  502. }
  503. expect(tt.parenR);
  504. parseStatement(false);
  505. }
  506. // Parse a `for`/`in` and `for`/`of` loop, which are almost
  507. // same from parser's perspective.
  508. function parseForIn(forAwait) {
  509. if (forAwait) {
  510. eatContextual(ContextualKeyword._of);
  511. } else {
  512. next();
  513. }
  514. parseExpression();
  515. expect(tt.parenR);
  516. parseStatement(false);
  517. }
  518. // Parse a list of variable declarations.
  519. function parseVar(isFor, isBlockScope) {
  520. while (true) {
  521. parseVarHead(isBlockScope);
  522. if (eat(tt.eq)) {
  523. const eqIndex = state.tokens.length - 1;
  524. parseMaybeAssign(isFor);
  525. state.tokens[eqIndex].rhsEndIndex = state.tokens.length;
  526. }
  527. if (!eat(tt.comma)) {
  528. break;
  529. }
  530. }
  531. }
  532. function parseVarHead(isBlockScope) {
  533. parseBindingAtom(isBlockScope);
  534. if (isTypeScriptEnabled) {
  535. tsAfterParseVarHead();
  536. } else if (isFlowEnabled) {
  537. flowAfterParseVarHead();
  538. }
  539. }
  540. // Parse a function declaration or literal (depending on the
  541. // `isStatement` parameter).
  542. export function parseFunction(
  543. functionStart,
  544. isStatement,
  545. optionalId = false,
  546. ) {
  547. if (match(tt.star)) {
  548. next();
  549. }
  550. if (isStatement && !optionalId && !match(tt.name) && !match(tt._yield)) {
  551. unexpected();
  552. }
  553. let nameScopeStartTokenIndex = null;
  554. if (match(tt.name)) {
  555. // Expression-style functions should limit their name's scope to the function body, so we make
  556. // a new function scope to enforce that.
  557. if (!isStatement) {
  558. nameScopeStartTokenIndex = state.tokens.length;
  559. state.scopeDepth++;
  560. }
  561. parseBindingIdentifier(false);
  562. }
  563. const startTokenIndex = state.tokens.length;
  564. state.scopeDepth++;
  565. parseFunctionParams();
  566. parseFunctionBodyAndFinish(functionStart);
  567. const endTokenIndex = state.tokens.length;
  568. // In addition to the block scope of the function body, we need a separate function-style scope
  569. // that includes the params.
  570. state.scopes.push(new Scope(startTokenIndex, endTokenIndex, true));
  571. state.scopeDepth--;
  572. if (nameScopeStartTokenIndex !== null) {
  573. state.scopes.push(new Scope(nameScopeStartTokenIndex, endTokenIndex, true));
  574. state.scopeDepth--;
  575. }
  576. }
  577. export function parseFunctionParams(
  578. allowModifiers = false,
  579. funcContextId = 0,
  580. ) {
  581. if (isTypeScriptEnabled) {
  582. tsStartParseFunctionParams();
  583. } else if (isFlowEnabled) {
  584. flowStartParseFunctionParams();
  585. }
  586. expect(tt.parenL);
  587. if (funcContextId) {
  588. state.tokens[state.tokens.length - 1].contextId = funcContextId;
  589. }
  590. parseBindingList(
  591. tt.parenR,
  592. false /* isBlockScope */,
  593. false /* allowEmpty */,
  594. allowModifiers,
  595. funcContextId,
  596. );
  597. if (funcContextId) {
  598. state.tokens[state.tokens.length - 1].contextId = funcContextId;
  599. }
  600. }
  601. // Parse a class declaration or literal (depending on the
  602. // `isStatement` parameter).
  603. export function parseClass(isStatement, optionalId = false) {
  604. // Put a context ID on the class keyword, the open-brace, and the close-brace, so that later
  605. // code can easily navigate to meaningful points on the class.
  606. const contextId = getNextContextId();
  607. next();
  608. state.tokens[state.tokens.length - 1].contextId = contextId;
  609. state.tokens[state.tokens.length - 1].isExpression = !isStatement;
  610. // Like with functions, we declare a special "name scope" from the start of the name to the end
  611. // of the class, but only with expression-style classes, to represent the fact that the name is
  612. // available to the body of the class but not an outer declaration.
  613. let nameScopeStartTokenIndex = null;
  614. if (!isStatement) {
  615. nameScopeStartTokenIndex = state.tokens.length;
  616. state.scopeDepth++;
  617. }
  618. parseClassId(isStatement, optionalId);
  619. parseClassSuper();
  620. const openBraceIndex = state.tokens.length;
  621. parseClassBody(contextId);
  622. if (state.error) {
  623. return;
  624. }
  625. state.tokens[openBraceIndex].contextId = contextId;
  626. state.tokens[state.tokens.length - 1].contextId = contextId;
  627. if (nameScopeStartTokenIndex !== null) {
  628. const endTokenIndex = state.tokens.length;
  629. state.scopes.push(new Scope(nameScopeStartTokenIndex, endTokenIndex, false));
  630. state.scopeDepth--;
  631. }
  632. }
  633. function isClassProperty() {
  634. return match(tt.eq) || match(tt.semi) || match(tt.braceR) || match(tt.bang) || match(tt.colon);
  635. }
  636. function isClassMethod() {
  637. return match(tt.parenL) || match(tt.lessThan);
  638. }
  639. function parseClassBody(classContextId) {
  640. expect(tt.braceL);
  641. while (!eat(tt.braceR) && !state.error) {
  642. if (eat(tt.semi)) {
  643. continue;
  644. }
  645. if (match(tt.at)) {
  646. parseDecorator();
  647. continue;
  648. }
  649. const memberStart = state.start;
  650. parseClassMember(memberStart, classContextId);
  651. }
  652. }
  653. function parseClassMember(memberStart, classContextId) {
  654. if (isTypeScriptEnabled) {
  655. tsParseModifiers([
  656. ContextualKeyword._declare,
  657. ContextualKeyword._public,
  658. ContextualKeyword._protected,
  659. ContextualKeyword._private,
  660. ContextualKeyword._override,
  661. ]);
  662. }
  663. let isStatic = false;
  664. if (match(tt.name) && state.contextualKeyword === ContextualKeyword._static) {
  665. parseIdentifier(); // eats 'static'
  666. if (isClassMethod()) {
  667. parseClassMethod(memberStart, /* isConstructor */ false);
  668. return;
  669. } else if (isClassProperty()) {
  670. parseClassProperty();
  671. return;
  672. }
  673. // otherwise something static
  674. state.tokens[state.tokens.length - 1].type = tt._static;
  675. isStatic = true;
  676. if (match(tt.braceL)) {
  677. // This is a static block. Mark the word "static" with the class context ID for class element
  678. // detection and parse as a regular block.
  679. state.tokens[state.tokens.length - 1].contextId = classContextId;
  680. parseBlock();
  681. return;
  682. }
  683. }
  684. parseClassMemberWithIsStatic(memberStart, isStatic, classContextId);
  685. }
  686. function parseClassMemberWithIsStatic(
  687. memberStart,
  688. isStatic,
  689. classContextId,
  690. ) {
  691. if (isTypeScriptEnabled) {
  692. if (tsTryParseClassMemberWithIsStatic(isStatic)) {
  693. return;
  694. }
  695. }
  696. if (eat(tt.star)) {
  697. // a generator
  698. parseClassPropertyName(classContextId);
  699. parseClassMethod(memberStart, /* isConstructor */ false);
  700. return;
  701. }
  702. // Get the identifier name so we can tell if it's actually a keyword like "async", "get", or
  703. // "set".
  704. parseClassPropertyName(classContextId);
  705. let isConstructor = false;
  706. const token = state.tokens[state.tokens.length - 1];
  707. // We allow "constructor" as either an identifier or a string.
  708. if (token.contextualKeyword === ContextualKeyword._constructor) {
  709. isConstructor = true;
  710. }
  711. parsePostMemberNameModifiers();
  712. if (isClassMethod()) {
  713. parseClassMethod(memberStart, isConstructor);
  714. } else if (isClassProperty()) {
  715. parseClassProperty();
  716. } else if (token.contextualKeyword === ContextualKeyword._async && !isLineTerminator()) {
  717. state.tokens[state.tokens.length - 1].type = tt._async;
  718. // an async method
  719. const isGenerator = match(tt.star);
  720. if (isGenerator) {
  721. next();
  722. }
  723. // The so-called parsed name would have been "async": get the real name.
  724. parseClassPropertyName(classContextId);
  725. parsePostMemberNameModifiers();
  726. parseClassMethod(memberStart, false /* isConstructor */);
  727. } else if (
  728. (token.contextualKeyword === ContextualKeyword._get ||
  729. token.contextualKeyword === ContextualKeyword._set) &&
  730. !(isLineTerminator() && match(tt.star))
  731. ) {
  732. if (token.contextualKeyword === ContextualKeyword._get) {
  733. state.tokens[state.tokens.length - 1].type = tt._get;
  734. } else {
  735. state.tokens[state.tokens.length - 1].type = tt._set;
  736. }
  737. // `get\n*` is an uninitialized property named 'get' followed by a generator.
  738. // a getter or setter
  739. // The so-called parsed name would have been "get/set": get the real name.
  740. parseClassPropertyName(classContextId);
  741. parseClassMethod(memberStart, /* isConstructor */ false);
  742. } else if (token.contextualKeyword === ContextualKeyword._accessor && !isLineTerminator()) {
  743. parseClassPropertyName(classContextId);
  744. parseClassProperty();
  745. } else if (isLineTerminator()) {
  746. // an uninitialized class property (due to ASI, since we don't otherwise recognize the next token)
  747. parseClassProperty();
  748. } else {
  749. unexpected();
  750. }
  751. }
  752. function parseClassMethod(functionStart, isConstructor) {
  753. if (isTypeScriptEnabled) {
  754. tsTryParseTypeParameters();
  755. } else if (isFlowEnabled) {
  756. if (match(tt.lessThan)) {
  757. flowParseTypeParameterDeclaration();
  758. }
  759. }
  760. parseMethod(functionStart, isConstructor);
  761. }
  762. // Return the name of the class property, if it is a simple identifier.
  763. export function parseClassPropertyName(classContextId) {
  764. parsePropertyName(classContextId);
  765. }
  766. export function parsePostMemberNameModifiers() {
  767. if (isTypeScriptEnabled) {
  768. const oldIsType = pushTypeContext(0);
  769. eat(tt.question);
  770. popTypeContext(oldIsType);
  771. }
  772. }
  773. export function parseClassProperty() {
  774. if (isTypeScriptEnabled) {
  775. eatTypeToken(tt.bang);
  776. tsTryParseTypeAnnotation();
  777. } else if (isFlowEnabled) {
  778. if (match(tt.colon)) {
  779. flowParseTypeAnnotation();
  780. }
  781. }
  782. if (match(tt.eq)) {
  783. const equalsTokenIndex = state.tokens.length;
  784. next();
  785. parseMaybeAssign();
  786. state.tokens[equalsTokenIndex].rhsEndIndex = state.tokens.length;
  787. }
  788. semicolon();
  789. }
  790. function parseClassId(isStatement, optionalId = false) {
  791. if (
  792. isTypeScriptEnabled &&
  793. (!isStatement || optionalId) &&
  794. isContextual(ContextualKeyword._implements)
  795. ) {
  796. return;
  797. }
  798. if (match(tt.name)) {
  799. parseBindingIdentifier(true);
  800. }
  801. if (isTypeScriptEnabled) {
  802. tsTryParseTypeParameters();
  803. } else if (isFlowEnabled) {
  804. if (match(tt.lessThan)) {
  805. flowParseTypeParameterDeclaration();
  806. }
  807. }
  808. }
  809. // Returns true if there was a superclass.
  810. function parseClassSuper() {
  811. let hasSuper = false;
  812. if (eat(tt._extends)) {
  813. parseExprSubscripts();
  814. hasSuper = true;
  815. } else {
  816. hasSuper = false;
  817. }
  818. if (isTypeScriptEnabled) {
  819. tsAfterParseClassSuper(hasSuper);
  820. } else if (isFlowEnabled) {
  821. flowAfterParseClassSuper(hasSuper);
  822. }
  823. }
  824. // Parses module export declaration.
  825. export function parseExport() {
  826. const exportIndex = state.tokens.length - 1;
  827. if (isTypeScriptEnabled) {
  828. if (tsTryParseExport()) {
  829. return;
  830. }
  831. }
  832. // export * from '...'
  833. if (shouldParseExportStar()) {
  834. parseExportStar();
  835. } else if (isExportDefaultSpecifier()) {
  836. // export default from
  837. parseIdentifier();
  838. if (match(tt.comma) && lookaheadType() === tt.star) {
  839. expect(tt.comma);
  840. expect(tt.star);
  841. expectContextual(ContextualKeyword._as);
  842. parseIdentifier();
  843. } else {
  844. parseExportSpecifiersMaybe();
  845. }
  846. parseExportFrom();
  847. } else if (eat(tt._default)) {
  848. // export default ...
  849. parseExportDefaultExpression();
  850. } else if (shouldParseExportDeclaration()) {
  851. parseExportDeclaration();
  852. } else {
  853. // export { x, y as z } [from '...']
  854. parseExportSpecifiers();
  855. parseExportFrom();
  856. }
  857. state.tokens[exportIndex].rhsEndIndex = state.tokens.length;
  858. }
  859. function parseExportDefaultExpression() {
  860. if (isTypeScriptEnabled) {
  861. if (tsTryParseExportDefaultExpression()) {
  862. return;
  863. }
  864. }
  865. if (isFlowEnabled) {
  866. if (flowTryParseExportDefaultExpression()) {
  867. return;
  868. }
  869. }
  870. const functionStart = state.start;
  871. if (eat(tt._function)) {
  872. parseFunction(functionStart, true, true);
  873. } else if (isContextual(ContextualKeyword._async) && lookaheadType() === tt._function) {
  874. // async function declaration
  875. eatContextual(ContextualKeyword._async);
  876. eat(tt._function);
  877. parseFunction(functionStart, true, true);
  878. } else if (match(tt._class)) {
  879. parseClass(true, true);
  880. } else if (match(tt.at)) {
  881. parseDecorators();
  882. parseClass(true, true);
  883. } else {
  884. parseMaybeAssign();
  885. semicolon();
  886. }
  887. }
  888. function parseExportDeclaration() {
  889. if (isTypeScriptEnabled) {
  890. tsParseExportDeclaration();
  891. } else if (isFlowEnabled) {
  892. flowParseExportDeclaration();
  893. } else {
  894. parseStatement(true);
  895. }
  896. }
  897. function isExportDefaultSpecifier() {
  898. if (isTypeScriptEnabled && tsIsDeclarationStart()) {
  899. return false;
  900. } else if (isFlowEnabled && flowShouldDisallowExportDefaultSpecifier()) {
  901. return false;
  902. }
  903. if (match(tt.name)) {
  904. return state.contextualKeyword !== ContextualKeyword._async;
  905. }
  906. if (!match(tt._default)) {
  907. return false;
  908. }
  909. const _next = nextTokenStart();
  910. const lookahead = lookaheadTypeAndKeyword();
  911. const hasFrom =
  912. lookahead.type === tt.name && lookahead.contextualKeyword === ContextualKeyword._from;
  913. if (lookahead.type === tt.comma) {
  914. return true;
  915. }
  916. // lookahead again when `export default from` is seen
  917. if (hasFrom) {
  918. const nextAfterFrom = input.charCodeAt(nextTokenStartSince(_next + 4));
  919. return nextAfterFrom === charCodes.quotationMark || nextAfterFrom === charCodes.apostrophe;
  920. }
  921. return false;
  922. }
  923. function parseExportSpecifiersMaybe() {
  924. if (eat(tt.comma)) {
  925. parseExportSpecifiers();
  926. }
  927. }
  928. export function parseExportFrom() {
  929. if (eatContextual(ContextualKeyword._from)) {
  930. parseExprAtom();
  931. maybeParseImportAssertions();
  932. }
  933. semicolon();
  934. }
  935. function shouldParseExportStar() {
  936. if (isFlowEnabled) {
  937. return flowShouldParseExportStar();
  938. } else {
  939. return match(tt.star);
  940. }
  941. }
  942. function parseExportStar() {
  943. if (isFlowEnabled) {
  944. flowParseExportStar();
  945. } else {
  946. baseParseExportStar();
  947. }
  948. }
  949. export function baseParseExportStar() {
  950. expect(tt.star);
  951. if (isContextual(ContextualKeyword._as)) {
  952. parseExportNamespace();
  953. } else {
  954. parseExportFrom();
  955. }
  956. }
  957. function parseExportNamespace() {
  958. next();
  959. state.tokens[state.tokens.length - 1].type = tt._as;
  960. parseIdentifier();
  961. parseExportSpecifiersMaybe();
  962. parseExportFrom();
  963. }
  964. function shouldParseExportDeclaration() {
  965. return (
  966. (isTypeScriptEnabled && tsIsDeclarationStart()) ||
  967. (isFlowEnabled && flowShouldParseExportDeclaration()) ||
  968. state.type === tt._var ||
  969. state.type === tt._const ||
  970. state.type === tt._let ||
  971. state.type === tt._function ||
  972. state.type === tt._class ||
  973. isContextual(ContextualKeyword._async) ||
  974. match(tt.at)
  975. );
  976. }
  977. // Parses a comma-separated list of module exports.
  978. export function parseExportSpecifiers() {
  979. let first = true;
  980. // export { x, y as z } [from '...']
  981. expect(tt.braceL);
  982. while (!eat(tt.braceR) && !state.error) {
  983. if (first) {
  984. first = false;
  985. } else {
  986. expect(tt.comma);
  987. if (eat(tt.braceR)) {
  988. break;
  989. }
  990. }
  991. parseExportSpecifier();
  992. }
  993. }
  994. function parseExportSpecifier() {
  995. if (isTypeScriptEnabled) {
  996. tsParseExportSpecifier();
  997. return;
  998. }
  999. parseIdentifier();
  1000. state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.ExportAccess;
  1001. if (eatContextual(ContextualKeyword._as)) {
  1002. parseIdentifier();
  1003. }
  1004. }
  1005. /**
  1006. * Starting at the `module` token in an import, determine if it was truly an
  1007. * import reflection token or just looks like one.
  1008. *
  1009. * Returns true for:
  1010. * import module foo from "foo";
  1011. * import module from from "foo";
  1012. *
  1013. * Returns false for:
  1014. * import module from "foo";
  1015. * import module, {bar} from "foo";
  1016. */
  1017. function isImportReflection() {
  1018. const snapshot = state.snapshot();
  1019. expectContextual(ContextualKeyword._module);
  1020. if (eatContextual(ContextualKeyword._from)) {
  1021. if (isContextual(ContextualKeyword._from)) {
  1022. state.restoreFromSnapshot(snapshot);
  1023. return true;
  1024. } else {
  1025. state.restoreFromSnapshot(snapshot);
  1026. return false;
  1027. }
  1028. } else if (match(tt.comma)) {
  1029. state.restoreFromSnapshot(snapshot);
  1030. return false;
  1031. } else {
  1032. state.restoreFromSnapshot(snapshot);
  1033. return true;
  1034. }
  1035. }
  1036. /**
  1037. * Eat the "module" token from the import reflection proposal.
  1038. * https://github.com/tc39/proposal-import-reflection
  1039. */
  1040. function parseMaybeImportReflection() {
  1041. // isImportReflection does snapshot/restore, so only run it if we see the word
  1042. // "module".
  1043. if (isContextual(ContextualKeyword._module) && isImportReflection()) {
  1044. next();
  1045. }
  1046. }
  1047. // Parses import declaration.
  1048. export function parseImport() {
  1049. if (isTypeScriptEnabled && match(tt.name) && lookaheadType() === tt.eq) {
  1050. tsParseImportEqualsDeclaration();
  1051. return;
  1052. }
  1053. if (isTypeScriptEnabled && isContextual(ContextualKeyword._type)) {
  1054. const lookahead = lookaheadTypeAndKeyword();
  1055. if (lookahead.type === tt.name && lookahead.contextualKeyword !== ContextualKeyword._from) {
  1056. // One of these `import type` cases:
  1057. // import type T = require('T');
  1058. // import type A from 'A';
  1059. expectContextual(ContextualKeyword._type);
  1060. if (lookaheadType() === tt.eq) {
  1061. tsParseImportEqualsDeclaration();
  1062. return;
  1063. }
  1064. // If this is an `import type...from` statement, then we already ate the
  1065. // type token, so proceed to the regular import parser.
  1066. } else if (lookahead.type === tt.star || lookahead.type === tt.braceL) {
  1067. // One of these `import type` cases, in which case we can eat the type token
  1068. // and proceed as normal:
  1069. // import type * as A from 'A';
  1070. // import type {a} from 'A';
  1071. expectContextual(ContextualKeyword._type);
  1072. }
  1073. // Otherwise, we are importing the name "type".
  1074. }
  1075. // import '...'
  1076. if (match(tt.string)) {
  1077. parseExprAtom();
  1078. } else {
  1079. parseMaybeImportReflection();
  1080. parseImportSpecifiers();
  1081. expectContextual(ContextualKeyword._from);
  1082. parseExprAtom();
  1083. }
  1084. maybeParseImportAssertions();
  1085. semicolon();
  1086. }
  1087. // eslint-disable-next-line no-unused-vars
  1088. function shouldParseDefaultImport() {
  1089. return match(tt.name);
  1090. }
  1091. function parseImportSpecifierLocal() {
  1092. parseImportedIdentifier();
  1093. }
  1094. // Parses a comma-separated list of module imports.
  1095. function parseImportSpecifiers() {
  1096. if (isFlowEnabled) {
  1097. flowStartParseImportSpecifiers();
  1098. }
  1099. let first = true;
  1100. if (shouldParseDefaultImport()) {
  1101. // import defaultObj, { x, y as z } from '...'
  1102. parseImportSpecifierLocal();
  1103. if (!eat(tt.comma)) return;
  1104. }
  1105. if (match(tt.star)) {
  1106. next();
  1107. expectContextual(ContextualKeyword._as);
  1108. parseImportSpecifierLocal();
  1109. return;
  1110. }
  1111. expect(tt.braceL);
  1112. while (!eat(tt.braceR) && !state.error) {
  1113. if (first) {
  1114. first = false;
  1115. } else {
  1116. // Detect an attempt to deep destructure
  1117. if (eat(tt.colon)) {
  1118. unexpected(
  1119. "ES2015 named imports do not destructure. Use another statement for destructuring after the import.",
  1120. );
  1121. }
  1122. expect(tt.comma);
  1123. if (eat(tt.braceR)) {
  1124. break;
  1125. }
  1126. }
  1127. parseImportSpecifier();
  1128. }
  1129. }
  1130. function parseImportSpecifier() {
  1131. if (isTypeScriptEnabled) {
  1132. tsParseImportSpecifier();
  1133. return;
  1134. }
  1135. if (isFlowEnabled) {
  1136. flowParseImportSpecifier();
  1137. return;
  1138. }
  1139. parseImportedIdentifier();
  1140. if (isContextual(ContextualKeyword._as)) {
  1141. state.tokens[state.tokens.length - 1].identifierRole = IdentifierRole.ImportAccess;
  1142. next();
  1143. parseImportedIdentifier();
  1144. }
  1145. }
  1146. /**
  1147. * Parse import assertions like `assert {type: "json"}`.
  1148. *
  1149. * Import assertions technically have their own syntax, but are always parseable
  1150. * as a plain JS object, so just do that for simplicity.
  1151. */
  1152. function maybeParseImportAssertions() {
  1153. if (isContextual(ContextualKeyword._assert) && !hasPrecedingLineBreak()) {
  1154. next();
  1155. parseObj(false, false);
  1156. }
  1157. }