source: frontend/node_modules/sucrase/dist/parser/traverser/expression.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 2 weeks ago

Fix frontend appearance

  • Property mode set to 100644
File size: 34.8 KB
Line 
1"use strict";Object.defineProperty(exports, "__esModule", {value: true});/* eslint max-len: 0 */
2
3// A recursive descent parser operates by defining functions for all
4// syntactic elements, and recursively calling those, each function
5// advancing the input stream and returning an AST node. Precedence
6// of constructs (for example, the fact that `!x[1]` means `!(x[1])`
7// instead of `(!x)[1]` is handled by the fact that the parser
8// function that parses unary prefix operators is called first, and
9// in turn calls the function that parses `[]` subscripts — that
10// way, it'll receive the node for `x[1]` already parsed, and wraps
11// *that* in the unary operator node.
12//
13// Acorn uses an [operator precedence parser][opp] to handle binary
14// operator precedence, because it is much more compact than using
15// the technique outlined above, which uses different, nesting
16// functions to specify precedence, for all of the ten binary
17// precedence levels that JavaScript defines.
18//
19// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser
20
21
22
23
24
25
26
27
28
29
30
31var _flow = require('../plugins/flow');
32var _index = require('../plugins/jsx/index');
33var _types = require('../plugins/types');
34
35
36
37
38
39
40
41
42
43var _typescript = require('../plugins/typescript');
44
45
46
47
48
49
50
51
52
53
54
55
56var _index3 = require('../tokenizer/index');
57var _keywords = require('../tokenizer/keywords');
58var _state = require('../tokenizer/state');
59var _types3 = require('../tokenizer/types');
60var _charcodes = require('../util/charcodes');
61var _identifier = require('../util/identifier');
62var _base = require('./base');
63
64
65
66
67
68
69var _lval = require('./lval');
70
71
72
73
74
75
76
77var _statement = require('./statement');
78
79
80
81
82
83
84
85
86
87var _util = require('./util');
88
89 class StopState {
90
91 constructor(stop) {
92 this.stop = stop;
93 }
94} exports.StopState = StopState;
95
96// ### Expression parsing
97
98// These nest, from the most general expression type at the top to
99// 'atomic', nondivisible expression types at the bottom. Most of
100// the functions will simply let the function (s) below them parse,
101// and, *if* the syntactic construct they handle is present, wrap
102// the AST node that the inner parser gave them in another node.
103 function parseExpression(noIn = false) {
104 parseMaybeAssign(noIn);
105 if (_index3.match.call(void 0, _types3.TokenType.comma)) {
106 while (_index3.eat.call(void 0, _types3.TokenType.comma)) {
107 parseMaybeAssign(noIn);
108 }
109 }
110} exports.parseExpression = parseExpression;
111
112/**
113 * noIn is used when parsing a for loop so that we don't interpret a following "in" as the binary
114 * operatior.
115 * isWithinParens is used to indicate that we're parsing something that might be a comma expression
116 * or might be an arrow function or might be a Flow type assertion (which requires explicit parens).
117 * In these cases, we should allow : and ?: after the initial "left" part.
118 */
119 function parseMaybeAssign(noIn = false, isWithinParens = false) {
120 if (_base.isTypeScriptEnabled) {
121 return _typescript.tsParseMaybeAssign.call(void 0, noIn, isWithinParens);
122 } else if (_base.isFlowEnabled) {
123 return _flow.flowParseMaybeAssign.call(void 0, noIn, isWithinParens);
124 } else {
125 return baseParseMaybeAssign(noIn, isWithinParens);
126 }
127} exports.parseMaybeAssign = parseMaybeAssign;
128
129// Parse an assignment expression. This includes applications of
130// operators like `+=`.
131// Returns true if the expression was an arrow function.
132 function baseParseMaybeAssign(noIn, isWithinParens) {
133 if (_index3.match.call(void 0, _types3.TokenType._yield)) {
134 parseYield();
135 return false;
136 }
137
138 if (_index3.match.call(void 0, _types3.TokenType.parenL) || _index3.match.call(void 0, _types3.TokenType.name) || _index3.match.call(void 0, _types3.TokenType._yield)) {
139 _base.state.potentialArrowAt = _base.state.start;
140 }
141
142 const wasArrow = parseMaybeConditional(noIn);
143 if (isWithinParens) {
144 parseParenItem();
145 }
146 if (_base.state.type & _types3.TokenType.IS_ASSIGN) {
147 _index3.next.call(void 0, );
148 parseMaybeAssign(noIn);
149 return false;
150 }
151 return wasArrow;
152} exports.baseParseMaybeAssign = baseParseMaybeAssign;
153
154// Parse a ternary conditional (`?:`) operator.
155// Returns true if the expression was an arrow function.
156function parseMaybeConditional(noIn) {
157 const wasArrow = parseExprOps(noIn);
158 if (wasArrow) {
159 return true;
160 }
161 parseConditional(noIn);
162 return false;
163}
164
165function parseConditional(noIn) {
166 if (_base.isTypeScriptEnabled || _base.isFlowEnabled) {
167 _types.typedParseConditional.call(void 0, noIn);
168 } else {
169 baseParseConditional(noIn);
170 }
171}
172
173 function baseParseConditional(noIn) {
174 if (_index3.eat.call(void 0, _types3.TokenType.question)) {
175 parseMaybeAssign();
176 _util.expect.call(void 0, _types3.TokenType.colon);
177 parseMaybeAssign(noIn);
178 }
179} exports.baseParseConditional = baseParseConditional;
180
181// Start the precedence parser.
182// Returns true if this was an arrow function
183function parseExprOps(noIn) {
184 const startTokenIndex = _base.state.tokens.length;
185 const wasArrow = parseMaybeUnary();
186 if (wasArrow) {
187 return true;
188 }
189 parseExprOp(startTokenIndex, -1, noIn);
190 return false;
191}
192
193// Parse binary operators with the operator precedence parsing
194// algorithm. `left` is the left-hand side of the operator.
195// `minPrec` provides context that allows the function to stop and
196// defer further parser to one of its callers when it encounters an
197// operator that has a lower precedence than the set it is parsing.
198function parseExprOp(startTokenIndex, minPrec, noIn) {
199 if (
200 _base.isTypeScriptEnabled &&
201 (_types3.TokenType._in & _types3.TokenType.PRECEDENCE_MASK) > minPrec &&
202 !_util.hasPrecedingLineBreak.call(void 0, ) &&
203 (_util.eatContextual.call(void 0, _keywords.ContextualKeyword._as) || _util.eatContextual.call(void 0, _keywords.ContextualKeyword._satisfies))
204 ) {
205 const oldIsType = _index3.pushTypeContext.call(void 0, 1);
206 _typescript.tsParseType.call(void 0, );
207 _index3.popTypeContext.call(void 0, oldIsType);
208 _index3.rescan_gt.call(void 0, );
209 parseExprOp(startTokenIndex, minPrec, noIn);
210 return;
211 }
212
213 const prec = _base.state.type & _types3.TokenType.PRECEDENCE_MASK;
214 if (prec > 0 && (!noIn || !_index3.match.call(void 0, _types3.TokenType._in))) {
215 if (prec > minPrec) {
216 const op = _base.state.type;
217 _index3.next.call(void 0, );
218 if (op === _types3.TokenType.nullishCoalescing) {
219 _base.state.tokens[_base.state.tokens.length - 1].nullishStartIndex = startTokenIndex;
220 }
221
222 const rhsStartTokenIndex = _base.state.tokens.length;
223 parseMaybeUnary();
224 // Extend the right operand of this operator if possible.
225 parseExprOp(rhsStartTokenIndex, op & _types3.TokenType.IS_RIGHT_ASSOCIATIVE ? prec - 1 : prec, noIn);
226 if (op === _types3.TokenType.nullishCoalescing) {
227 _base.state.tokens[startTokenIndex].numNullishCoalesceStarts++;
228 _base.state.tokens[_base.state.tokens.length - 1].numNullishCoalesceEnds++;
229 }
230 // Continue with any future operator holding this expression as the left operand.
231 parseExprOp(startTokenIndex, minPrec, noIn);
232 }
233 }
234}
235
236// Parse unary operators, both prefix and postfix.
237// Returns true if this was an arrow function.
238 function parseMaybeUnary() {
239 if (_base.isTypeScriptEnabled && !_base.isJSXEnabled && _index3.eat.call(void 0, _types3.TokenType.lessThan)) {
240 _typescript.tsParseTypeAssertion.call(void 0, );
241 return false;
242 }
243 if (
244 _util.isContextual.call(void 0, _keywords.ContextualKeyword._module) &&
245 _index3.lookaheadCharCode.call(void 0, ) === _charcodes.charCodes.leftCurlyBrace &&
246 !_util.hasFollowingLineBreak.call(void 0, )
247 ) {
248 parseModuleExpression();
249 return false;
250 }
251 if (_base.state.type & _types3.TokenType.IS_PREFIX) {
252 _index3.next.call(void 0, );
253 parseMaybeUnary();
254 return false;
255 }
256
257 const wasArrow = parseExprSubscripts();
258 if (wasArrow) {
259 return true;
260 }
261 while (_base.state.type & _types3.TokenType.IS_POSTFIX && !_util.canInsertSemicolon.call(void 0, )) {
262 // The tokenizer calls everything a preincrement, so make it a postincrement when
263 // we see it in that context.
264 if (_base.state.type === _types3.TokenType.preIncDec) {
265 _base.state.type = _types3.TokenType.postIncDec;
266 }
267 _index3.next.call(void 0, );
268 }
269 return false;
270} exports.parseMaybeUnary = parseMaybeUnary;
271
272// Parse call, dot, and `[]`-subscript expressions.
273// Returns true if this was an arrow function.
274 function parseExprSubscripts() {
275 const startTokenIndex = _base.state.tokens.length;
276 const wasArrow = parseExprAtom();
277 if (wasArrow) {
278 return true;
279 }
280 parseSubscripts(startTokenIndex);
281 // If there was any optional chain operation, the start token would be marked
282 // as such, so also mark the end now.
283 if (_base.state.tokens.length > startTokenIndex && _base.state.tokens[startTokenIndex].isOptionalChainStart) {
284 _base.state.tokens[_base.state.tokens.length - 1].isOptionalChainEnd = true;
285 }
286 return false;
287} exports.parseExprSubscripts = parseExprSubscripts;
288
289function parseSubscripts(startTokenIndex, noCalls = false) {
290 if (_base.isFlowEnabled) {
291 _flow.flowParseSubscripts.call(void 0, startTokenIndex, noCalls);
292 } else {
293 baseParseSubscripts(startTokenIndex, noCalls);
294 }
295}
296
297 function baseParseSubscripts(startTokenIndex, noCalls = false) {
298 const stopState = new StopState(false);
299 do {
300 parseSubscript(startTokenIndex, noCalls, stopState);
301 } while (!stopState.stop && !_base.state.error);
302} exports.baseParseSubscripts = baseParseSubscripts;
303
304function parseSubscript(startTokenIndex, noCalls, stopState) {
305 if (_base.isTypeScriptEnabled) {
306 _typescript.tsParseSubscript.call(void 0, startTokenIndex, noCalls, stopState);
307 } else if (_base.isFlowEnabled) {
308 _flow.flowParseSubscript.call(void 0, startTokenIndex, noCalls, stopState);
309 } else {
310 baseParseSubscript(startTokenIndex, noCalls, stopState);
311 }
312}
313
314/** Set 'state.stop = true' to indicate that we should stop parsing subscripts. */
315 function baseParseSubscript(
316 startTokenIndex,
317 noCalls,
318 stopState,
319) {
320 if (!noCalls && _index3.eat.call(void 0, _types3.TokenType.doubleColon)) {
321 parseNoCallExpr();
322 stopState.stop = true;
323 // Propagate startTokenIndex so that `a::b?.()` will keep `a` as the first token. We may want
324 // to revisit this in the future when fully supporting bind syntax.
325 parseSubscripts(startTokenIndex, noCalls);
326 } else if (_index3.match.call(void 0, _types3.TokenType.questionDot)) {
327 _base.state.tokens[startTokenIndex].isOptionalChainStart = true;
328 if (noCalls && _index3.lookaheadType.call(void 0, ) === _types3.TokenType.parenL) {
329 stopState.stop = true;
330 return;
331 }
332 _index3.next.call(void 0, );
333 _base.state.tokens[_base.state.tokens.length - 1].subscriptStartIndex = startTokenIndex;
334
335 if (_index3.eat.call(void 0, _types3.TokenType.bracketL)) {
336 parseExpression();
337 _util.expect.call(void 0, _types3.TokenType.bracketR);
338 } else if (_index3.eat.call(void 0, _types3.TokenType.parenL)) {
339 parseCallExpressionArguments();
340 } else {
341 parseMaybePrivateName();
342 }
343 } else if (_index3.eat.call(void 0, _types3.TokenType.dot)) {
344 _base.state.tokens[_base.state.tokens.length - 1].subscriptStartIndex = startTokenIndex;
345 parseMaybePrivateName();
346 } else if (_index3.eat.call(void 0, _types3.TokenType.bracketL)) {
347 _base.state.tokens[_base.state.tokens.length - 1].subscriptStartIndex = startTokenIndex;
348 parseExpression();
349 _util.expect.call(void 0, _types3.TokenType.bracketR);
350 } else if (!noCalls && _index3.match.call(void 0, _types3.TokenType.parenL)) {
351 if (atPossibleAsync()) {
352 // We see "async", but it's possible it's a usage of the name "async". Parse as if it's a
353 // function call, and if we see an arrow later, backtrack and re-parse as a parameter list.
354 const snapshot = _base.state.snapshot();
355 const asyncStartTokenIndex = _base.state.tokens.length;
356 _index3.next.call(void 0, );
357 _base.state.tokens[_base.state.tokens.length - 1].subscriptStartIndex = startTokenIndex;
358
359 const callContextId = _base.getNextContextId.call(void 0, );
360
361 _base.state.tokens[_base.state.tokens.length - 1].contextId = callContextId;
362 parseCallExpressionArguments();
363 _base.state.tokens[_base.state.tokens.length - 1].contextId = callContextId;
364
365 if (shouldParseAsyncArrow()) {
366 // We hit an arrow, so backtrack and start again parsing function parameters.
367 _base.state.restoreFromSnapshot(snapshot);
368 stopState.stop = true;
369 _base.state.scopeDepth++;
370
371 _statement.parseFunctionParams.call(void 0, );
372 parseAsyncArrowFromCallExpression(asyncStartTokenIndex);
373 }
374 } else {
375 _index3.next.call(void 0, );
376 _base.state.tokens[_base.state.tokens.length - 1].subscriptStartIndex = startTokenIndex;
377 const callContextId = _base.getNextContextId.call(void 0, );
378 _base.state.tokens[_base.state.tokens.length - 1].contextId = callContextId;
379 parseCallExpressionArguments();
380 _base.state.tokens[_base.state.tokens.length - 1].contextId = callContextId;
381 }
382 } else if (_index3.match.call(void 0, _types3.TokenType.backQuote)) {
383 // Tagged template expression.
384 parseTemplate();
385 } else {
386 stopState.stop = true;
387 }
388} exports.baseParseSubscript = baseParseSubscript;
389
390 function atPossibleAsync() {
391 // This was made less strict than the original version to avoid passing around nodes, but it
392 // should be safe to have rare false positives here.
393 return (
394 _base.state.tokens[_base.state.tokens.length - 1].contextualKeyword === _keywords.ContextualKeyword._async &&
395 !_util.canInsertSemicolon.call(void 0, )
396 );
397} exports.atPossibleAsync = atPossibleAsync;
398
399 function parseCallExpressionArguments() {
400 let first = true;
401 while (!_index3.eat.call(void 0, _types3.TokenType.parenR) && !_base.state.error) {
402 if (first) {
403 first = false;
404 } else {
405 _util.expect.call(void 0, _types3.TokenType.comma);
406 if (_index3.eat.call(void 0, _types3.TokenType.parenR)) {
407 break;
408 }
409 }
410
411 parseExprListItem(false);
412 }
413} exports.parseCallExpressionArguments = parseCallExpressionArguments;
414
415function shouldParseAsyncArrow() {
416 return _index3.match.call(void 0, _types3.TokenType.colon) || _index3.match.call(void 0, _types3.TokenType.arrow);
417}
418
419function parseAsyncArrowFromCallExpression(startTokenIndex) {
420 if (_base.isTypeScriptEnabled) {
421 _typescript.tsStartParseAsyncArrowFromCallExpression.call(void 0, );
422 } else if (_base.isFlowEnabled) {
423 _flow.flowStartParseAsyncArrowFromCallExpression.call(void 0, );
424 }
425 _util.expect.call(void 0, _types3.TokenType.arrow);
426 parseArrowExpression(startTokenIndex);
427}
428
429// Parse a no-call expression (like argument of `new` or `::` operators).
430
431function parseNoCallExpr() {
432 const startTokenIndex = _base.state.tokens.length;
433 parseExprAtom();
434 parseSubscripts(startTokenIndex, true);
435}
436
437// Parse an atomic expression — either a single token that is an
438// expression, an expression started by a keyword like `function` or
439// `new`, or an expression wrapped in punctuation like `()`, `[]`,
440// or `{}`.
441// Returns true if the parsed expression was an arrow function.
442 function parseExprAtom() {
443 if (_index3.eat.call(void 0, _types3.TokenType.modulo)) {
444 // V8 intrinsic expression. Just parse the identifier, and the function invocation is parsed
445 // naturally.
446 parseIdentifier();
447 return false;
448 }
449
450 if (_index3.match.call(void 0, _types3.TokenType.jsxText) || _index3.match.call(void 0, _types3.TokenType.jsxEmptyText)) {
451 parseLiteral();
452 return false;
453 } else if (_index3.match.call(void 0, _types3.TokenType.lessThan) && _base.isJSXEnabled) {
454 _base.state.type = _types3.TokenType.jsxTagStart;
455 _index.jsxParseElement.call(void 0, );
456 _index3.next.call(void 0, );
457 return false;
458 }
459
460 const canBeArrow = _base.state.potentialArrowAt === _base.state.start;
461 switch (_base.state.type) {
462 case _types3.TokenType.slash:
463 case _types3.TokenType.assign:
464 _index3.retokenizeSlashAsRegex.call(void 0, );
465 // Fall through.
466
467 case _types3.TokenType._super:
468 case _types3.TokenType._this:
469 case _types3.TokenType.regexp:
470 case _types3.TokenType.num:
471 case _types3.TokenType.bigint:
472 case _types3.TokenType.decimal:
473 case _types3.TokenType.string:
474 case _types3.TokenType._null:
475 case _types3.TokenType._true:
476 case _types3.TokenType._false:
477 _index3.next.call(void 0, );
478 return false;
479
480 case _types3.TokenType._import:
481 _index3.next.call(void 0, );
482 if (_index3.match.call(void 0, _types3.TokenType.dot)) {
483 // import.meta
484 _base.state.tokens[_base.state.tokens.length - 1].type = _types3.TokenType.name;
485 _index3.next.call(void 0, );
486 parseIdentifier();
487 }
488 return false;
489
490 case _types3.TokenType.name: {
491 const startTokenIndex = _base.state.tokens.length;
492 const functionStart = _base.state.start;
493 const contextualKeyword = _base.state.contextualKeyword;
494 parseIdentifier();
495 if (contextualKeyword === _keywords.ContextualKeyword._await) {
496 parseAwait();
497 return false;
498 } else if (
499 contextualKeyword === _keywords.ContextualKeyword._async &&
500 _index3.match.call(void 0, _types3.TokenType._function) &&
501 !_util.canInsertSemicolon.call(void 0, )
502 ) {
503 _index3.next.call(void 0, );
504 _statement.parseFunction.call(void 0, functionStart, false);
505 return false;
506 } else if (
507 canBeArrow &&
508 contextualKeyword === _keywords.ContextualKeyword._async &&
509 !_util.canInsertSemicolon.call(void 0, ) &&
510 _index3.match.call(void 0, _types3.TokenType.name)
511 ) {
512 _base.state.scopeDepth++;
513 _lval.parseBindingIdentifier.call(void 0, false);
514 _util.expect.call(void 0, _types3.TokenType.arrow);
515 // let foo = async bar => {};
516 parseArrowExpression(startTokenIndex);
517 return true;
518 } else if (_index3.match.call(void 0, _types3.TokenType._do) && !_util.canInsertSemicolon.call(void 0, )) {
519 _index3.next.call(void 0, );
520 _statement.parseBlock.call(void 0, );
521 return false;
522 }
523
524 if (canBeArrow && !_util.canInsertSemicolon.call(void 0, ) && _index3.match.call(void 0, _types3.TokenType.arrow)) {
525 _base.state.scopeDepth++;
526 _lval.markPriorBindingIdentifier.call(void 0, false);
527 _util.expect.call(void 0, _types3.TokenType.arrow);
528 parseArrowExpression(startTokenIndex);
529 return true;
530 }
531
532 _base.state.tokens[_base.state.tokens.length - 1].identifierRole = _index3.IdentifierRole.Access;
533 return false;
534 }
535
536 case _types3.TokenType._do: {
537 _index3.next.call(void 0, );
538 _statement.parseBlock.call(void 0, );
539 return false;
540 }
541
542 case _types3.TokenType.parenL: {
543 const wasArrow = parseParenAndDistinguishExpression(canBeArrow);
544 return wasArrow;
545 }
546
547 case _types3.TokenType.bracketL:
548 _index3.next.call(void 0, );
549 parseExprList(_types3.TokenType.bracketR, true);
550 return false;
551
552 case _types3.TokenType.braceL:
553 parseObj(false, false);
554 return false;
555
556 case _types3.TokenType._function:
557 parseFunctionExpression();
558 return false;
559
560 case _types3.TokenType.at:
561 _statement.parseDecorators.call(void 0, );
562 // Fall through.
563
564 case _types3.TokenType._class:
565 _statement.parseClass.call(void 0, false);
566 return false;
567
568 case _types3.TokenType._new:
569 parseNew();
570 return false;
571
572 case _types3.TokenType.backQuote:
573 parseTemplate();
574 return false;
575
576 case _types3.TokenType.doubleColon: {
577 _index3.next.call(void 0, );
578 parseNoCallExpr();
579 return false;
580 }
581
582 case _types3.TokenType.hash: {
583 const code = _index3.lookaheadCharCode.call(void 0, );
584 if (_identifier.IS_IDENTIFIER_START[code] || code === _charcodes.charCodes.backslash) {
585 parseMaybePrivateName();
586 } else {
587 _index3.next.call(void 0, );
588 }
589 // Smart pipeline topic reference.
590 return false;
591 }
592
593 default:
594 _util.unexpected.call(void 0, );
595 return false;
596 }
597} exports.parseExprAtom = parseExprAtom;
598
599function parseMaybePrivateName() {
600 _index3.eat.call(void 0, _types3.TokenType.hash);
601 parseIdentifier();
602}
603
604function parseFunctionExpression() {
605 const functionStart = _base.state.start;
606 parseIdentifier();
607 if (_index3.eat.call(void 0, _types3.TokenType.dot)) {
608 // function.sent
609 parseIdentifier();
610 }
611 _statement.parseFunction.call(void 0, functionStart, false);
612}
613
614 function parseLiteral() {
615 _index3.next.call(void 0, );
616} exports.parseLiteral = parseLiteral;
617
618 function parseParenExpression() {
619 _util.expect.call(void 0, _types3.TokenType.parenL);
620 parseExpression();
621 _util.expect.call(void 0, _types3.TokenType.parenR);
622} exports.parseParenExpression = parseParenExpression;
623
624// Returns true if this was an arrow expression.
625function parseParenAndDistinguishExpression(canBeArrow) {
626 // Assume this is a normal parenthesized expression, but if we see an arrow, we'll bail and
627 // start over as a parameter list.
628 const snapshot = _base.state.snapshot();
629
630 const startTokenIndex = _base.state.tokens.length;
631 _util.expect.call(void 0, _types3.TokenType.parenL);
632
633 let first = true;
634
635 while (!_index3.match.call(void 0, _types3.TokenType.parenR) && !_base.state.error) {
636 if (first) {
637 first = false;
638 } else {
639 _util.expect.call(void 0, _types3.TokenType.comma);
640 if (_index3.match.call(void 0, _types3.TokenType.parenR)) {
641 break;
642 }
643 }
644
645 if (_index3.match.call(void 0, _types3.TokenType.ellipsis)) {
646 _lval.parseRest.call(void 0, false /* isBlockScope */);
647 parseParenItem();
648 break;
649 } else {
650 parseMaybeAssign(false, true);
651 }
652 }
653
654 _util.expect.call(void 0, _types3.TokenType.parenR);
655
656 if (canBeArrow && shouldParseArrow()) {
657 const wasArrow = parseArrow();
658 if (wasArrow) {
659 // It was an arrow function this whole time, so start over and parse it as params so that we
660 // get proper token annotations.
661 _base.state.restoreFromSnapshot(snapshot);
662 _base.state.scopeDepth++;
663 // Don't specify a context ID because arrow functions don't need a context ID.
664 _statement.parseFunctionParams.call(void 0, );
665 parseArrow();
666 parseArrowExpression(startTokenIndex);
667 if (_base.state.error) {
668 // Nevermind! This must have been something that looks very much like an
669 // arrow function but where its "parameter list" isn't actually a valid
670 // parameter list. Force non-arrow parsing.
671 // See https://github.com/alangpierce/sucrase/issues/666 for an example.
672 _base.state.restoreFromSnapshot(snapshot);
673 parseParenAndDistinguishExpression(false);
674 return false;
675 }
676 return true;
677 }
678 }
679
680 return false;
681}
682
683function shouldParseArrow() {
684 return _index3.match.call(void 0, _types3.TokenType.colon) || !_util.canInsertSemicolon.call(void 0, );
685}
686
687// Returns whether there was an arrow token.
688 function parseArrow() {
689 if (_base.isTypeScriptEnabled) {
690 return _typescript.tsParseArrow.call(void 0, );
691 } else if (_base.isFlowEnabled) {
692 return _flow.flowParseArrow.call(void 0, );
693 } else {
694 return _index3.eat.call(void 0, _types3.TokenType.arrow);
695 }
696} exports.parseArrow = parseArrow;
697
698function parseParenItem() {
699 if (_base.isTypeScriptEnabled || _base.isFlowEnabled) {
700 _types.typedParseParenItem.call(void 0, );
701 }
702}
703
704// New's precedence is slightly tricky. It must allow its argument to
705// be a `[]` or dot subscript expression, but not a call — at least,
706// not without wrapping it in parentheses. Thus, it uses the noCalls
707// argument to parseSubscripts to prevent it from consuming the
708// argument list.
709function parseNew() {
710 _util.expect.call(void 0, _types3.TokenType._new);
711 if (_index3.eat.call(void 0, _types3.TokenType.dot)) {
712 // new.target
713 parseIdentifier();
714 return;
715 }
716 parseNewCallee();
717 if (_base.isFlowEnabled) {
718 _flow.flowStartParseNewArguments.call(void 0, );
719 }
720 if (_index3.eat.call(void 0, _types3.TokenType.parenL)) {
721 parseExprList(_types3.TokenType.parenR);
722 }
723}
724
725function parseNewCallee() {
726 parseNoCallExpr();
727 _index3.eat.call(void 0, _types3.TokenType.questionDot);
728}
729
730 function parseTemplate() {
731 // Finish `, read quasi
732 _index3.nextTemplateToken.call(void 0, );
733 // Finish quasi, read ${
734 _index3.nextTemplateToken.call(void 0, );
735 while (!_index3.match.call(void 0, _types3.TokenType.backQuote) && !_base.state.error) {
736 _util.expect.call(void 0, _types3.TokenType.dollarBraceL);
737 parseExpression();
738 // Finish }, read quasi
739 _index3.nextTemplateToken.call(void 0, );
740 // Finish quasi, read either ${ or `
741 _index3.nextTemplateToken.call(void 0, );
742 }
743 _index3.next.call(void 0, );
744} exports.parseTemplate = parseTemplate;
745
746// Parse an object literal or binding pattern.
747 function parseObj(isPattern, isBlockScope) {
748 // Attach a context ID to the object open and close brace and each object key.
749 const contextId = _base.getNextContextId.call(void 0, );
750 let first = true;
751
752 _index3.next.call(void 0, );
753 _base.state.tokens[_base.state.tokens.length - 1].contextId = contextId;
754
755 while (!_index3.eat.call(void 0, _types3.TokenType.braceR) && !_base.state.error) {
756 if (first) {
757 first = false;
758 } else {
759 _util.expect.call(void 0, _types3.TokenType.comma);
760 if (_index3.eat.call(void 0, _types3.TokenType.braceR)) {
761 break;
762 }
763 }
764
765 let isGenerator = false;
766 if (_index3.match.call(void 0, _types3.TokenType.ellipsis)) {
767 const previousIndex = _base.state.tokens.length;
768 _lval.parseSpread.call(void 0, );
769 if (isPattern) {
770 // Mark role when the only thing being spread over is an identifier.
771 if (_base.state.tokens.length === previousIndex + 2) {
772 _lval.markPriorBindingIdentifier.call(void 0, isBlockScope);
773 }
774 if (_index3.eat.call(void 0, _types3.TokenType.braceR)) {
775 break;
776 }
777 }
778 continue;
779 }
780
781 if (!isPattern) {
782 isGenerator = _index3.eat.call(void 0, _types3.TokenType.star);
783 }
784
785 if (!isPattern && _util.isContextual.call(void 0, _keywords.ContextualKeyword._async)) {
786 if (isGenerator) _util.unexpected.call(void 0, );
787
788 parseIdentifier();
789 if (
790 _index3.match.call(void 0, _types3.TokenType.colon) ||
791 _index3.match.call(void 0, _types3.TokenType.parenL) ||
792 _index3.match.call(void 0, _types3.TokenType.braceR) ||
793 _index3.match.call(void 0, _types3.TokenType.eq) ||
794 _index3.match.call(void 0, _types3.TokenType.comma)
795 ) {
796 // This is a key called "async" rather than an async function.
797 } else {
798 if (_index3.match.call(void 0, _types3.TokenType.star)) {
799 _index3.next.call(void 0, );
800 isGenerator = true;
801 }
802 parsePropertyName(contextId);
803 }
804 } else {
805 parsePropertyName(contextId);
806 }
807
808 parseObjPropValue(isPattern, isBlockScope, contextId);
809 }
810
811 _base.state.tokens[_base.state.tokens.length - 1].contextId = contextId;
812} exports.parseObj = parseObj;
813
814function isGetterOrSetterMethod(isPattern) {
815 // We go off of the next and don't bother checking if the node key is actually "get" or "set".
816 // This lets us avoid generating a node, and should only make the validation worse.
817 return (
818 !isPattern &&
819 (_index3.match.call(void 0, _types3.TokenType.string) || // get "string"() {}
820 _index3.match.call(void 0, _types3.TokenType.num) || // get 1() {}
821 _index3.match.call(void 0, _types3.TokenType.bracketL) || // get ["string"]() {}
822 _index3.match.call(void 0, _types3.TokenType.name) || // get foo() {}
823 !!(_base.state.type & _types3.TokenType.IS_KEYWORD)) // get debugger() {}
824 );
825}
826
827// Returns true if this was a method.
828function parseObjectMethod(isPattern, objectContextId) {
829 // We don't need to worry about modifiers because object methods can't have optional bodies, so
830 // the start will never be used.
831 const functionStart = _base.state.start;
832 if (_index3.match.call(void 0, _types3.TokenType.parenL)) {
833 if (isPattern) _util.unexpected.call(void 0, );
834 parseMethod(functionStart, /* isConstructor */ false);
835 return true;
836 }
837
838 if (isGetterOrSetterMethod(isPattern)) {
839 parsePropertyName(objectContextId);
840 parseMethod(functionStart, /* isConstructor */ false);
841 return true;
842 }
843 return false;
844}
845
846function parseObjectProperty(isPattern, isBlockScope) {
847 if (_index3.eat.call(void 0, _types3.TokenType.colon)) {
848 if (isPattern) {
849 _lval.parseMaybeDefault.call(void 0, isBlockScope);
850 } else {
851 parseMaybeAssign(false);
852 }
853 return;
854 }
855
856 // Since there's no colon, we assume this is an object shorthand.
857
858 // If we're in a destructuring, we've now discovered that the key was actually an assignee, so
859 // we need to tag it as a declaration with the appropriate scope. Otherwise, we might need to
860 // transform it on access, so mark it as a normal object shorthand.
861 let identifierRole;
862 if (isPattern) {
863 if (_base.state.scopeDepth === 0) {
864 identifierRole = _index3.IdentifierRole.ObjectShorthandTopLevelDeclaration;
865 } else if (isBlockScope) {
866 identifierRole = _index3.IdentifierRole.ObjectShorthandBlockScopedDeclaration;
867 } else {
868 identifierRole = _index3.IdentifierRole.ObjectShorthandFunctionScopedDeclaration;
869 }
870 } else {
871 identifierRole = _index3.IdentifierRole.ObjectShorthand;
872 }
873 _base.state.tokens[_base.state.tokens.length - 1].identifierRole = identifierRole;
874
875 // Regardless of whether we know this to be a pattern or if we're in an ambiguous context, allow
876 // parsing as if there's a default value.
877 _lval.parseMaybeDefault.call(void 0, isBlockScope, true);
878}
879
880function parseObjPropValue(
881 isPattern,
882 isBlockScope,
883 objectContextId,
884) {
885 if (_base.isTypeScriptEnabled) {
886 _typescript.tsStartParseObjPropValue.call(void 0, );
887 } else if (_base.isFlowEnabled) {
888 _flow.flowStartParseObjPropValue.call(void 0, );
889 }
890 const wasMethod = parseObjectMethod(isPattern, objectContextId);
891 if (!wasMethod) {
892 parseObjectProperty(isPattern, isBlockScope);
893 }
894}
895
896 function parsePropertyName(objectContextId) {
897 if (_base.isFlowEnabled) {
898 _flow.flowParseVariance.call(void 0, );
899 }
900 if (_index3.eat.call(void 0, _types3.TokenType.bracketL)) {
901 _base.state.tokens[_base.state.tokens.length - 1].contextId = objectContextId;
902 parseMaybeAssign();
903 _util.expect.call(void 0, _types3.TokenType.bracketR);
904 _base.state.tokens[_base.state.tokens.length - 1].contextId = objectContextId;
905 } else {
906 if (_index3.match.call(void 0, _types3.TokenType.num) || _index3.match.call(void 0, _types3.TokenType.string) || _index3.match.call(void 0, _types3.TokenType.bigint) || _index3.match.call(void 0, _types3.TokenType.decimal)) {
907 parseExprAtom();
908 } else {
909 parseMaybePrivateName();
910 }
911
912 _base.state.tokens[_base.state.tokens.length - 1].identifierRole = _index3.IdentifierRole.ObjectKey;
913 _base.state.tokens[_base.state.tokens.length - 1].contextId = objectContextId;
914 }
915} exports.parsePropertyName = parsePropertyName;
916
917// Parse object or class method.
918 function parseMethod(functionStart, isConstructor) {
919 const funcContextId = _base.getNextContextId.call(void 0, );
920
921 _base.state.scopeDepth++;
922 const startTokenIndex = _base.state.tokens.length;
923 const allowModifiers = isConstructor; // For TypeScript parameter properties
924 _statement.parseFunctionParams.call(void 0, allowModifiers, funcContextId);
925 parseFunctionBodyAndFinish(functionStart, funcContextId);
926 const endTokenIndex = _base.state.tokens.length;
927 _base.state.scopes.push(new (0, _state.Scope)(startTokenIndex, endTokenIndex, true));
928 _base.state.scopeDepth--;
929} exports.parseMethod = parseMethod;
930
931// Parse arrow function expression.
932// If the parameters are provided, they will be converted to an
933// assignable list.
934 function parseArrowExpression(startTokenIndex) {
935 parseFunctionBody(true);
936 const endTokenIndex = _base.state.tokens.length;
937 _base.state.scopes.push(new (0, _state.Scope)(startTokenIndex, endTokenIndex, true));
938 _base.state.scopeDepth--;
939} exports.parseArrowExpression = parseArrowExpression;
940
941 function parseFunctionBodyAndFinish(functionStart, funcContextId = 0) {
942 if (_base.isTypeScriptEnabled) {
943 _typescript.tsParseFunctionBodyAndFinish.call(void 0, functionStart, funcContextId);
944 } else if (_base.isFlowEnabled) {
945 _flow.flowParseFunctionBodyAndFinish.call(void 0, funcContextId);
946 } else {
947 parseFunctionBody(false, funcContextId);
948 }
949} exports.parseFunctionBodyAndFinish = parseFunctionBodyAndFinish;
950
951 function parseFunctionBody(allowExpression, funcContextId = 0) {
952 const isExpression = allowExpression && !_index3.match.call(void 0, _types3.TokenType.braceL);
953
954 if (isExpression) {
955 parseMaybeAssign();
956 } else {
957 _statement.parseBlock.call(void 0, true /* isFunctionScope */, funcContextId);
958 }
959} exports.parseFunctionBody = parseFunctionBody;
960
961// Parses a comma-separated list of expressions, and returns them as
962// an array. `close` is the token type that ends the list, and
963// `allowEmpty` can be turned on to allow subsequent commas with
964// nothing in between them to be parsed as `null` (which is needed
965// for array literals).
966
967function parseExprList(close, allowEmpty = false) {
968 let first = true;
969 while (!_index3.eat.call(void 0, close) && !_base.state.error) {
970 if (first) {
971 first = false;
972 } else {
973 _util.expect.call(void 0, _types3.TokenType.comma);
974 if (_index3.eat.call(void 0, close)) break;
975 }
976 parseExprListItem(allowEmpty);
977 }
978}
979
980function parseExprListItem(allowEmpty) {
981 if (allowEmpty && _index3.match.call(void 0, _types3.TokenType.comma)) {
982 // Empty item; nothing more to parse for this item.
983 } else if (_index3.match.call(void 0, _types3.TokenType.ellipsis)) {
984 _lval.parseSpread.call(void 0, );
985 parseParenItem();
986 } else if (_index3.match.call(void 0, _types3.TokenType.question)) {
987 // Partial function application proposal.
988 _index3.next.call(void 0, );
989 } else {
990 parseMaybeAssign(false, true);
991 }
992}
993
994// Parse the next token as an identifier.
995 function parseIdentifier() {
996 _index3.next.call(void 0, );
997 _base.state.tokens[_base.state.tokens.length - 1].type = _types3.TokenType.name;
998} exports.parseIdentifier = parseIdentifier;
999
1000// Parses await expression inside async function.
1001function parseAwait() {
1002 parseMaybeUnary();
1003}
1004
1005// Parses yield expression inside generator.
1006function parseYield() {
1007 _index3.next.call(void 0, );
1008 if (!_index3.match.call(void 0, _types3.TokenType.semi) && !_util.canInsertSemicolon.call(void 0, )) {
1009 _index3.eat.call(void 0, _types3.TokenType.star);
1010 parseMaybeAssign();
1011 }
1012}
1013
1014// https://github.com/tc39/proposal-js-module-blocks
1015function parseModuleExpression() {
1016 _util.expectContextual.call(void 0, _keywords.ContextualKeyword._module);
1017 _util.expect.call(void 0, _types3.TokenType.braceL);
1018 // For now, just call parseBlockBody to parse the block. In the future when we
1019 // implement full support, we'll want to emit scopes and possibly other
1020 // information.
1021 _statement.parseBlockBody.call(void 0, _types3.TokenType.braceR);
1022}
Note: See TracBrowser for help on using the repository browser.