Coverage Report

Created: 2025-01-28 06:38

/src/hermes/lib/Parser/JSParserImpl.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) Meta Platforms, Inc. and affiliates.
3
 *
4
 * This source code is licensed under the MIT license found in the
5
 * LICENSE file in the root directory of this source tree.
6
 */
7
8
#include "JSParserImpl.h"
9
10
#include "hermes/AST/ESTreeJSONDumper.h"
11
#include "hermes/Support/PerfSection.h"
12
13
#include "llvh/Support/SaveAndRestore.h"
14
15
using llvh::cast;
16
using llvh::dyn_cast;
17
using llvh::isa;
18
19
namespace hermes {
20
namespace parser {
21
namespace detail {
22
23
JSParserImpl::JSParserImpl(
24
    Context &context,
25
    std::unique_ptr<llvh::MemoryBuffer> input)
26
160
    : context_(context),
27
160
      sm_(context.getSourceErrorManager()),
28
160
      lexer_(
29
160
          std::move(input),
30
160
          context.getSourceErrorManager(),
31
160
          context.getAllocator(),
32
160
          &context.getStringTable(),
33
160
          context.isStrictMode()),
34
160
      pass_(FullParse) {
35
160
  initializeIdentifiers();
36
160
}
37
38
JSParserImpl::JSParserImpl(Context &context, uint32_t bufferId, ParserPass pass)
39
450
    : context_(context),
40
450
      sm_(context.getSourceErrorManager()),
41
450
      lexer_(
42
450
          bufferId,
43
450
          context.getSourceErrorManager(),
44
450
          context.getAllocator(),
45
450
          &context.getStringTable(),
46
450
          context.isStrictMode()),
47
450
      pass_(pass) {
48
450
  preParsed_ = context.getPreParsedBufferInfo(bufferId);
49
450
  initializeIdentifiers();
50
450
}
51
52
610
void JSParserImpl::initializeIdentifiers() {
53
610
  getIdent_ = lexer_.getIdentifier("get");
54
610
  setIdent_ = lexer_.getIdentifier("set");
55
610
  initIdent_ = lexer_.getIdentifier("init");
56
610
  useStrictIdent_ = lexer_.getIdentifier("use strict");
57
610
  showSourceIdent_ = lexer_.getIdentifier("show source");
58
610
  hideSourceIdent_ = lexer_.getIdentifier("hide source");
59
610
  sensitiveIdent_ = lexer_.getIdentifier("sensitive");
60
610
  useStaticBuiltinIdent_ = lexer_.getIdentifier("use static builtin");
61
610
  letIdent_ = lexer_.getIdentifier("let");
62
610
  ofIdent_ = lexer_.getIdentifier("of");
63
610
  fromIdent_ = lexer_.getIdentifier("from");
64
610
  asIdent_ = lexer_.getIdentifier("as");
65
610
  implementsIdent_ = lexer_.getIdentifier("implements");
66
610
  interfaceIdent_ = lexer_.getIdentifier("interface");
67
610
  packageIdent_ = lexer_.getIdentifier("package");
68
610
  privateIdent_ = lexer_.getIdentifier("private");
69
610
  protectedIdent_ = lexer_.getIdentifier("protected");
70
610
  publicIdent_ = lexer_.getIdentifier("public");
71
610
  staticIdent_ = lexer_.getIdentifier("static");
72
610
  methodIdent_ = lexer_.getIdentifier("method");
73
610
  constructorIdent_ = lexer_.getIdentifier("constructor");
74
610
  yieldIdent_ = lexer_.getIdentifier("yield");
75
610
  newIdent_ = lexer_.getIdentifier("new");
76
610
  targetIdent_ = lexer_.getIdentifier("target");
77
610
  importIdent_ = lexer_.getIdentifier("import");
78
610
  metaIdent_ = lexer_.getIdentifier("meta");
79
610
  valueIdent_ = lexer_.getIdentifier("value");
80
610
  typeIdent_ = lexer_.getIdentifier("type");
81
610
  asyncIdent_ = lexer_.getIdentifier("async");
82
610
  awaitIdent_ = lexer_.getIdentifier("await");
83
610
  assertIdent_ = lexer_.getIdentifier("assert");
84
85
610
#if HERMES_PARSE_FLOW
86
87
610
  typeofIdent_ = lexer_.getIdentifier("typeof");
88
610
  keyofIdent_ = lexer_.getIdentifier("keyof");
89
610
  declareIdent_ = lexer_.getIdentifier("declare");
90
610
  protoIdent_ = lexer_.getIdentifier("proto");
91
610
  opaqueIdent_ = lexer_.getIdentifier("opaque");
92
610
  plusIdent_ = lexer_.getIdentifier("plus");
93
610
  minusIdent_ = lexer_.getIdentifier("minus");
94
610
  moduleIdent_ = lexer_.getIdentifier("module");
95
610
  exportsIdent_ = lexer_.getIdentifier("exports");
96
610
  esIdent_ = lexer_.getIdentifier("ES");
97
610
  commonJSIdent_ = lexer_.getIdentifier("CommonJS");
98
610
  mixinsIdent_ = lexer_.getIdentifier("mixins");
99
610
  thisIdent_ = lexer_.getIdentifier("this");
100
101
610
  anyIdent_ = lexer_.getIdentifier("any");
102
610
  mixedIdent_ = lexer_.getIdentifier("mixed");
103
610
  emptyIdent_ = lexer_.getIdentifier("empty");
104
610
  booleanIdent_ = lexer_.getIdentifier("boolean");
105
610
  boolIdent_ = lexer_.getIdentifier("bool");
106
610
  numberIdent_ = lexer_.getIdentifier("number");
107
610
  stringIdent_ = lexer_.getIdentifier("string");
108
610
  voidIdent_ = lexer_.getIdentifier("void");
109
610
  nullIdent_ = lexer_.getIdentifier("null");
110
610
  symbolIdent_ = lexer_.getIdentifier("symbol");
111
610
  bigintIdent_ = lexer_.getIdentifier("bigint");
112
113
610
  mappedTypeOptionalIdent_ = lexer_.getIdentifier("Optional");
114
610
  mappedTypePlusOptionalIdent_ = lexer_.getIdentifier("PlusOptional");
115
610
  mappedTypeMinusOptionalIdent_ = lexer_.getIdentifier("MinusOptional");
116
117
610
  checksIdent_ = lexer_.getIdentifier("%checks");
118
610
  assertsIdent_ = lexer_.getIdentifier("asserts");
119
610
  impliesIdent_ = lexer_.getIdentifier("implies");
120
121
  // Flow Component syntax
122
610
  componentIdent_ = lexer_.getIdentifier("component");
123
610
  rendersIdent_ = lexer_.getIdentifier("renders");
124
610
  rendersMaybeOperator_ = lexer_.getIdentifier("renders?");
125
610
  rendersStarOperator_ = lexer_.getIdentifier("renders*");
126
610
  hookIdent_ = lexer_.getIdentifier("hook");
127
128
  // Flow match expressions and statements
129
610
  matchIdent_ = lexer_.getIdentifier("match");
130
610
  underscoreIdent_ = lexer_.getIdentifier("_");
131
610
#endif
132
133
610
#if HERMES_PARSE_TS
134
610
  readonlyIdent_ = lexer_.getIdentifier("readonly");
135
610
  neverIdent_ = lexer_.getIdentifier("never");
136
610
  undefinedIdent_ = lexer_.getIdentifier("undefined");
137
610
  unknownIdent_ = lexer_.getIdentifier("unknown");
138
610
#endif
139
140
610
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
141
610
  namespaceIdent_ = lexer_.getIdentifier("namespace");
142
610
  isIdent_ = lexer_.getIdentifier("is");
143
610
  inferIdent_ = lexer_.getIdentifier("infer");
144
610
  constIdent_ = lexer_.getIdentifier("const");
145
610
#endif
146
147
  // Generate the string representation of all tokens.
148
75.0k
  for (unsigned i = 0; i != NUM_JS_TOKENS; ++i)
149
74.4k
    tokenIdent_[i] = lexer_.getIdentifier(tokenKindStr((TokenKind)i));
150
610
}
151
152
610
Optional<ESTree::ProgramNode *> JSParserImpl::parse() {
153
610
  PerfSection parsing("Parsing JavaScript");
154
610
  tok_ = lexer_.advance();
155
610
  auto res = parseProgram();
156
610
  if (!res)
157
29
    return None;
158
581
  if (lexer_.getSourceMgr().getErrorCount() != 0)
159
14
    return None;
160
567
  return res.getValue();
161
581
}
162
163
void JSParserImpl::errorExpected(
164
    ArrayRef<TokenKind> toks,
165
    const char *where,
166
    const char *what,
167
11
    SMLoc whatLoc) {
168
11
  llvh::SmallString<4> str;
169
11
  llvh::raw_svector_ostream ss{str};
170
171
22
  for (unsigned i = 0; i < toks.size(); ++i) {
172
    // Insert a separator after the first token.
173
11
    if (i > 0) {
174
      // Use " or " instead of ", " before the last token.
175
0
      if (i == toks.size() - 1)
176
0
        ss << " or ";
177
0
      else
178
0
        ss << ", ";
179
0
    }
180
11
    ss << "'" << tokenKindStr(toks[i]) << "'";
181
11
  }
182
183
11
  ss << " expected";
184
185
  // Optionally append the 'where' description.
186
11
  if (where)
187
11
    ss << " " << where;
188
189
11
  SMLoc errorLoc = tok_->getStartLoc();
190
11
  SourceErrorManager::SourceCoords curCoords;
191
11
  SourceErrorManager::SourceCoords whatCoords;
192
193
  // If the location of 'what' is provided, find its and the error's source
194
  // coordinates.
195
11
  if (whatLoc.isValid()) {
196
11
    sm_.findBufferLineAndLoc(errorLoc, curCoords);
197
11
    sm_.findBufferLineAndLoc(whatLoc, whatCoords);
198
11
  }
199
200
11
  if (whatCoords.isSameSourceLineAs(curCoords)) {
201
    // If the what source coordinates are on the same line as the error, show
202
    // them both.
203
10
    sm_.error(
204
10
        errorLoc,
205
10
        SourceErrorManager::combineIntoRange(whatLoc, errorLoc),
206
10
        ss.str(),
207
10
        Subsystem::Parser);
208
10
  } else {
209
1
    sm_.error(errorLoc, ss.str(), Subsystem::Parser);
210
211
1
    if (what && whatCoords.isValid())
212
1
      sm_.note(whatLoc, what, Subsystem::Parser);
213
1
  }
214
11
}
215
216
bool JSParserImpl::need(
217
    TokenKind kind,
218
    const char *where,
219
    const char *what,
220
283k
    SMLoc whatLoc) {
221
283k
  if (tok_->getKind() == kind) {
222
283k
    return true;
223
283k
  }
224
11
  errorExpected(kind, where, what, whatLoc);
225
11
  return false;
226
283k
}
227
228
bool JSParserImpl::eat(
229
    TokenKind kind,
230
    JSLexer::GrammarContext grammarContext,
231
    const char *where,
232
    const char *what,
233
272k
    SMLoc whatLoc) {
234
272k
  if (need(kind, where, what, whatLoc)) {
235
272k
    advance(grammarContext);
236
272k
    return true;
237
272k
  }
238
11
  return false;
239
272k
}
240
241
bool JSParserImpl::checkAndEat(
242
    TokenKind kind,
243
12.8M
    JSLexer::GrammarContext grammarContext) {
244
12.8M
  if (tok_->getKind() == kind) {
245
3.05M
    advance(grammarContext);
246
3.05M
    return true;
247
3.05M
  }
248
9.78M
  return false;
249
12.8M
}
250
251
bool JSParserImpl::checkAndEat(
252
    UniqueString *ident,
253
0
    JSLexer::GrammarContext grammarContext) {
254
0
  if (check(ident)) {
255
0
    advance(grammarContext);
256
0
    return true;
257
0
  }
258
0
  return false;
259
0
}
260
261
6.40M
bool JSParserImpl::checkAssign() const {
262
6.40M
  return checkN(
263
6.40M
      TokenKind::equal,
264
6.40M
      TokenKind::starequal,
265
6.40M
      TokenKind::slashequal,
266
6.40M
      TokenKind::percentequal,
267
6.40M
      TokenKind::plusequal,
268
6.40M
      TokenKind::minusequal,
269
6.40M
      TokenKind::lesslessequal,
270
6.40M
      TokenKind::greatergreaterequal,
271
6.40M
      TokenKind::greatergreatergreaterequal,
272
6.40M
      TokenKind::starstarequal,
273
6.40M
      TokenKind::pipepipeequal,
274
6.40M
      TokenKind::ampampequal,
275
6.40M
      TokenKind::questionquestionequal,
276
6.40M
      TokenKind::ampequal,
277
6.40M
      TokenKind::caretequal,
278
6.40M
      TokenKind::pipeequal);
279
6.40M
}
280
281
bool JSParserImpl::checkEndAssignmentExpression(
282
9.27k
    OfEndsAssignment ofEndsAssignment) const {
283
9.27k
  return checkN(
284
9.27k
             TokenKind::rw_in,
285
9.27k
             TokenKind::r_paren,
286
9.27k
             TokenKind::r_brace,
287
9.27k
             TokenKind::r_square,
288
9.27k
             TokenKind::comma,
289
9.27k
             TokenKind::semi,
290
9.27k
             TokenKind::colon,
291
9.27k
             TokenKind::eof) ||
292
9.27k
      (ofEndsAssignment == OfEndsAssignment::Yes && check(ofIdent_)) ||
293
9.27k
      lexer_.isNewLineBeforeCurrentToken();
294
9.27k
}
295
296
375
bool JSParserImpl::checkAsyncFunction() {
297
  // async [no LineTerminator here] function
298
  // ^
299
375
  assert(
300
375
      check(asyncIdent_) && "check for async function must occur at 'async'");
301
  // Avoid passing TokenKind::rw_function here, because parseFunctionHelper
302
  // relies on seeing `async` in order to construct its AST node.
303
  // This function must also be idempotent to allow for branching based on its
304
  // result in parseStatementListItem without having to store another flag,
305
  // for example.
306
375
  OptValue<TokenKind> optNext = lexer_.lookahead1(llvh::None);
307
375
  return optNext.hasValue() && *optNext == TokenKind::rw_function;
308
375
}
309
310
723k
bool JSParserImpl::eatSemi(bool optional) {
311
723k
  if (tok_->getKind() == TokenKind::semi) {
312
512k
    advance();
313
512k
    return true;
314
512k
  }
315
316
210k
  if (tok_->getKind() == TokenKind::r_brace ||
317
210k
      tok_->getKind() == TokenKind::eof ||
318
210k
      lexer_.isNewLineBeforeCurrentToken()) {
319
210k
    return true;
320
210k
  }
321
322
5
  if (!optional)
323
4
    error(tok_->getStartLoc(), "';' expected");
324
5
  return false;
325
210k
}
326
327
4
void JSParserImpl::processDirective(UniqueString *directive) {
328
4
  seenDirectives_.push_back(directive);
329
4
  if (directive == useStrictIdent_)
330
0
    setStrictMode(true);
331
4
  if (directive == useStaticBuiltinIdent_)
332
0
    setUseStaticBuiltin();
333
4
}
334
335
4
bool JSParserImpl::recursionDepthExceeded() {
336
4
  error(
337
4
      tok_->getStartLoc(),
338
4
      "Too many nested expressions/statements/declarations");
339
4
  return true;
340
4
}
341
342
610
Optional<ESTree::ProgramNode *> JSParserImpl::parseProgram() {
343
610
  SMLoc startLoc = tok_->getStartLoc();
344
610
  SaveStrictModeAndSeenDirectives saveStrictModeAndSeenDirectives{this};
345
610
  ESTree::NodeList stmtList;
346
347
610
  if (!parseStatementList(
348
610
          Param{}, TokenKind::eof, true, AllowImportExport::Yes, stmtList))
349
29
    return None;
350
351
581
  SMLoc endLoc = startLoc;
352
581
  if (!stmtList.empty()) {
353
577
    endLoc = stmtList.back().getEndLoc();
354
577
  }
355
581
  auto *program = setLocation(
356
581
      startLoc,
357
581
      endLoc,
358
581
      new (context_) ESTree::ProgramNode(std::move(stmtList)));
359
581
  return program;
360
610
}
361
362
Optional<ESTree::FunctionDeclarationNode *>
363
5.44k
JSParserImpl::parseFunctionDeclaration(Param param, bool forceEagerly) {
364
5.44k
  auto optRes = parseFunctionHelper(param, true, forceEagerly);
365
5.44k
  if (!optRes)
366
0
    return None;
367
5.44k
  return cast<ESTree::FunctionDeclarationNode>(*optRes);
368
5.44k
}
369
370
Optional<ESTree::FunctionLikeNode *> JSParserImpl::parseFunctionHelper(
371
    Param param,
372
    bool isDeclaration,
373
5.60k
    bool forceEagerly) {
374
  // function or async function
375
5.60k
  assert(check(TokenKind::rw_function) || check(asyncIdent_));
376
5.60k
  bool isAsync = check(asyncIdent_);
377
378
5.60k
  SMLoc startLoc = advance().Start;
379
380
5.60k
  if (isAsync) {
381
    // async function
382
    //       ^
383
0
    advance();
384
0
  }
385
386
5.60k
  bool isGenerator = checkAndEat(TokenKind::star);
387
388
  // newParamYield setting per the grammar:
389
  // FunctionDeclaration: BindingIdentifier[?Yield, ?Await]
390
  // FunctionExpression: BindingIdentifier[~Yield, ~Await]
391
  // GeneratorFunctionDeclaration: BindingIdentifier[?Yield, ?Await]
392
  // GeneratorFunctionExpression: BindingIdentifier[+Yield, ~Await]
393
  // AsyncFunctionDeclaration: BindingIdentifier[?Yield, ?Await]
394
  // AsyncFunctionExpression: BindingIdentifier[+Yield, +Await]
395
  // AsyncGeneratorDeclaration: BindingIdentifier[?Yield, ?Await]
396
  // AsyncGeneratorExpression: BindingIdentifier[+Yield, +Await]
397
5.60k
  bool nameParamYield = isDeclaration ? paramYield_ : isGenerator;
398
5.60k
  llvh::SaveAndRestore<bool> saveNameParamYield(paramYield_, nameParamYield);
399
5.60k
  bool nameParamAwait = isDeclaration ? paramAwait_ : isAsync;
400
5.60k
  llvh::SaveAndRestore<bool> saveNameParamAwait(paramAwait_, nameParamAwait);
401
402
  // identifier
403
5.60k
  auto optId = parseBindingIdentifier(Param{});
404
  // If this is a default function declaration, then we can match
405
  // [+Default] function ( FormalParameters ) { FunctionBody }
406
  // so the identifier is optional and we can make it nullptr.
407
5.60k
  if (isDeclaration && !param.has(ParamDefault) && !optId) {
408
0
    errorExpected(
409
0
        TokenKind::identifier,
410
0
        "after 'function'",
411
0
        "location of 'function'",
412
0
        startLoc);
413
0
    return None;
414
0
  }
415
416
5.60k
  ESTree::Node *typeParams = nullptr;
417
418
5.60k
#if HERMES_PARSE_FLOW
419
5.60k
  if (context_.getParseFlow() && check(TokenKind::less)) {
420
0
    auto optTypeParams = parseTypeParamsFlow();
421
0
    if (!optTypeParams)
422
0
      return None;
423
0
    typeParams = *optTypeParams;
424
0
  }
425
5.60k
#endif
426
427
5.60k
#if HERMES_PARSE_TS
428
5.60k
  if (context_.getParseTS() && check(TokenKind::less)) {
429
0
    auto optTypeParams = parseTSTypeParameters();
430
0
    if (!optTypeParams)
431
0
      return None;
432
0
    typeParams = *optTypeParams;
433
0
  }
434
5.60k
#endif
435
436
  // (
437
5.60k
  if (!need(
438
5.60k
          TokenKind::l_paren,
439
5.60k
          "at start of function parameter list",
440
5.60k
          isDeclaration ? "function declaration starts here"
441
5.60k
                        : "function expression starts here",
442
5.60k
          startLoc)) {
443
0
    return None;
444
0
  }
445
446
5.60k
  ESTree::NodeList paramList;
447
448
5.60k
  llvh::SaveAndRestore<bool> saveArgsAndBodyParamYield(
449
5.60k
      paramYield_, isGenerator);
450
5.60k
  llvh::SaveAndRestore<bool> saveArgsAndBodyParamAwait(paramAwait_, isAsync);
451
452
5.60k
  if (!parseFormalParameters(param, paramList))
453
1
    return None;
454
455
5.60k
  ESTree::Node *returnType = nullptr;
456
5.60k
  ESTree::Node *predicate = nullptr;
457
5.60k
#if HERMES_PARSE_FLOW
458
5.60k
  if (context_.getParseFlow() && check(TokenKind::colon)) {
459
0
    SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
460
0
    if (!check(checksIdent_)) {
461
0
      auto optRet = parseReturnTypeAnnotationFlow(annotStart);
462
0
      if (!optRet)
463
0
        return None;
464
0
      returnType = *optRet;
465
0
    }
466
467
0
    if (check(checksIdent_)) {
468
0
      auto optPred = parsePredicateFlow();
469
0
      if (!optPred)
470
0
        return None;
471
0
      predicate = *optPred;
472
0
    }
473
0
  }
474
5.60k
#endif
475
5.60k
#if HERMES_PARSE_TS
476
5.60k
  if (context_.getParseTS() && check(TokenKind::colon)) {
477
0
    SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
478
0
    if (!check(checksIdent_)) {
479
0
      auto optRet = parseTypeAnnotationTS(annotStart);
480
0
      if (!optRet)
481
0
        return None;
482
0
      returnType = *optRet;
483
0
    }
484
0
  }
485
5.60k
#endif
486
487
  // {
488
5.60k
  if (!need(
489
5.60k
          TokenKind::l_brace,
490
5.60k
          isDeclaration ? "in function declaration" : "in function expression",
491
5.60k
          isDeclaration ? "start of function declaration"
492
5.60k
                        : "start of function expression",
493
5.60k
          startLoc)) {
494
0
    return None;
495
0
  }
496
497
5.60k
  SaveStrictModeAndSeenDirectives saveStrictModeAndSeenDirectives{this};
498
499
  // Grammar context to be used when lexing the closing brace.
500
5.60k
  auto grammarContext =
501
5.60k
      isDeclaration ? JSLexer::AllowRegExp : JSLexer::AllowDiv;
502
503
5.60k
  if (pass_ == PreParse) {
504
    // Create the nodes we want to keep before the AllocationScope.
505
83
    ESTree::FunctionLikeNode *node;
506
507
83
    if (isDeclaration) {
508
0
      auto *decl = new (context_) ESTree::FunctionDeclarationNode(
509
0
          optId ? *optId : nullptr,
510
0
          std::move(paramList),
511
0
          nullptr,
512
0
          typeParams,
513
0
          returnType,
514
0
          predicate,
515
0
          isGenerator,
516
0
          isAsync);
517
      // Initialize the node with a blank body.
518
0
      decl->_body = new (context_) ESTree::BlockStatementNode({});
519
0
      node = decl;
520
83
    } else {
521
83
      auto *expr = new (context_) ESTree::FunctionExpressionNode(
522
83
          optId ? *optId : nullptr,
523
83
          std::move(paramList),
524
83
          nullptr,
525
83
          typeParams,
526
83
          returnType,
527
83
          predicate,
528
83
          isGenerator,
529
83
          isAsync);
530
      // Initialize the node with a blank body.
531
83
      expr->_body = new (context_) ESTree::BlockStatementNode({});
532
83
      node = expr;
533
83
    }
534
535
83
    AllocationScope scope(context_.getAllocator());
536
83
    auto body = parseFunctionBody(
537
83
        Param{},
538
83
        false,
539
83
        saveArgsAndBodyParamYield.get(),
540
83
        saveArgsAndBodyParamAwait.get(),
541
83
        grammarContext,
542
83
        true);
543
83
    if (!body)
544
2
      return None;
545
546
81
    return setLocation(startLoc, body.getValue(), node);
547
83
  }
548
549
5.52k
  auto parsedBody = parseFunctionBody(
550
5.52k
      Param{},
551
5.52k
      forceEagerly,
552
5.52k
      saveArgsAndBodyParamYield.get(),
553
5.52k
      saveArgsAndBodyParamAwait.get(),
554
5.52k
      grammarContext,
555
5.52k
      true);
556
5.52k
  if (!parsedBody)
557
2
    return None;
558
5.52k
  auto *body = parsedBody.getValue();
559
560
5.52k
  ESTree::FunctionLikeNode *node;
561
5.52k
  if (isDeclaration) {
562
5.44k
    auto *decl = new (context_) ESTree::FunctionDeclarationNode(
563
5.44k
        optId ? *optId : nullptr,
564
5.44k
        std::move(paramList),
565
5.44k
        body,
566
5.44k
        typeParams,
567
5.44k
        returnType,
568
5.44k
        predicate,
569
5.44k
        isGenerator,
570
5.44k
        isAsync);
571
5.44k
    node = decl;
572
5.44k
  } else {
573
82
    auto *expr = new (context_) ESTree::FunctionExpressionNode(
574
82
        optId ? *optId : nullptr,
575
82
        std::move(paramList),
576
82
        body,
577
82
        typeParams,
578
82
        returnType,
579
82
        predicate,
580
82
        isGenerator,
581
82
        isAsync);
582
82
    node = expr;
583
82
  }
584
5.52k
  return setLocation(startLoc, body, node);
585
5.52k
}
586
587
bool JSParserImpl::parseFormalParameters(
588
    Param param,
589
5.60k
    ESTree::NodeList &paramList) {
590
5.60k
  assert(check(TokenKind::l_paren) && "FormalParameters must start with '('");
591
  // (
592
5.60k
  SMLoc lparenLoc = advance().Start;
593
594
5.60k
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
595
  // The first parameter can be 'this' in Flow and TypeScript.
596
5.60k
  if (context_.getParseTypes() && check(TokenKind::rw_this)) {
597
0
    auto *name = tok_->getResWordIdentifier();
598
0
    SMLoc thisParamStart = advance().Start;
599
600
0
    SMLoc annotStart = tok_->getStartLoc();
601
0
    if (!eat(
602
0
            TokenKind::colon,
603
0
            JSLexer::GrammarContext::Type,
604
0
            "in 'this' type annotation",
605
0
            "start of 'this'",
606
0
            thisParamStart))
607
0
      return false;
608
609
0
    auto optType = parseTypeAnnotation(annotStart);
610
0
    if (!optType)
611
0
      return false;
612
0
    ESTree::Node *type = *optType;
613
0
    paramList.push_back(*setLocation(
614
0
        thisParamStart,
615
0
        getPrevTokenEndLoc(),
616
0
        new (context_) ESTree::IdentifierNode(name, type, false)));
617
618
0
    checkAndEat(TokenKind::comma);
619
0
  }
620
5.60k
#endif
621
622
5.60k
  while (!check(TokenKind::r_paren)) {
623
1
    if (check(TokenKind::dotdotdot)) {
624
      // BindingRestElement.
625
0
      auto optRestElem = parseBindingRestElement(param);
626
0
      if (!optRestElem)
627
0
        return false;
628
0
      paramList.push_back(*optRestElem.getValue());
629
0
      break;
630
0
    }
631
632
    // BindingElement.
633
1
    auto optElem = parseBindingElement(param);
634
1
    if (!optElem)
635
0
      return false;
636
637
1
    paramList.push_back(*optElem.getValue());
638
639
1
    if (!checkAndEat(TokenKind::comma))
640
1
      break;
641
1
  }
642
643
  // )
644
5.60k
  if (!eat(
645
5.60k
          TokenKind::r_paren,
646
5.60k
          JSLexer::AllowRegExp,
647
5.60k
          "at end of function parameter list",
648
5.60k
          "start of parameter list",
649
5.60k
          lparenLoc)) {
650
1
    return false;
651
1
  }
652
653
5.60k
  return true;
654
5.60k
}
655
656
1.22M
Optional<ESTree::Node *> JSParserImpl::parseStatement(Param param) {
657
1.22M
  CHECK_RECURSION;
658
659
1.22M
#define _RET(parseFunc)       \
660
1.22M
  if (auto res = (parseFunc)) \
661
1.22M
    return res.getValue();    \
662
1.22M
  else                        \
663
1.22M
    return None;
664
665
1.22M
  switch (tok_->getKind()) {
666
2
    case TokenKind::l_brace:
667
2
      _RET(parseBlock(param));
668
3.84k
    case TokenKind::rw_var:
669
3.84k
      _RET(parseVariableStatement(Param{}));
670
10.6k
    case TokenKind::semi:
671
10.6k
      _RET(parseEmptyStatement());
672
0
    case TokenKind::rw_if:
673
0
      _RET(parseIfStatement(param.get(ParamReturn)));
674
0
    case TokenKind::rw_while:
675
0
      _RET(parseWhileStatement(param.get(ParamReturn)));
676
0
    case TokenKind::rw_do:
677
0
      _RET(parseDoWhileStatement(param.get(ParamReturn)));
678
32
    case TokenKind::rw_for:
679
32
      _RET(parseForStatement(param.get(ParamReturn)));
680
0
    case TokenKind::rw_continue:
681
0
      _RET(parseContinueStatement());
682
1
    case TokenKind::rw_break:
683
1
      _RET(parseBreakStatement());
684
0
    case TokenKind::rw_return:
685
0
      if (!param.has(ParamReturn) && !context_.allowReturnOutsideFunction()) {
686
        // Illegal location for a return statement, but we can keep parsing.
687
0
        error(tok_->getSourceRange(), "'return' not in a function");
688
0
      }
689
0
      _RET(parseReturnStatement());
690
0
    case TokenKind::rw_with:
691
0
      _RET(parseWithStatement(param.get(ParamReturn)));
692
0
    case TokenKind::rw_switch:
693
0
      _RET(parseSwitchStatement(param.get(ParamReturn)));
694
0
    case TokenKind::rw_throw:
695
0
      _RET(parseThrowStatement(Param{}));
696
0
    case TokenKind::rw_try:
697
0
      _RET(parseTryStatement(param.get(ParamReturn)));
698
0
    case TokenKind::rw_debugger:
699
0
      _RET(parseDebuggerStatement());
700
701
1.21M
    default:
702
1.21M
#if HERMES_PARSE_FLOW
703
1.21M
      if (context_.getParseFlow() && context_.getParseFlowMatch() &&
704
1.21M
          LLVM_UNLIKELY(checkMaybeFlowMatch())) {
705
0
        auto optMatch = tryParseMatchStatementFlow(param.get(ParamReturn));
706
0
        if (!optMatch)
707
0
          return None;
708
0
        if (*optMatch)
709
0
          return *optMatch;
710
0
      }
711
1.21M
#endif
712
1.21M
      _RET(parseExpressionOrLabelledStatement(param.get(ParamReturn)));
713
1.22M
  }
714
715
1.22M
#undef _RET
716
1.22M
}
717
718
llvh::SmallVector<llvh::SmallString<24>, 1> JSParserImpl::copySeenDirectives()
719
81
    const {
720
81
  llvh::SmallVector<llvh::SmallString<24>, 1> copies;
721
81
  for (UniqueString *directive : seenDirectives_) {
722
0
    copies.emplace_back(directive->str());
723
0
  }
724
81
  return copies;
725
81
}
726
727
Optional<ESTree::BlockStatementNode *> JSParserImpl::parseFunctionBody(
728
    Param param,
729
    bool eagerly,
730
    bool paramYield,
731
    bool paramAwait,
732
    JSLexer::GrammarContext grammarContext,
733
5.60k
    bool parseDirectives) {
734
5.60k
  if (pass_ == LazyParse && !eagerly) {
735
81
    auto startLoc = tok_->getStartLoc();
736
81
    assert(
737
81
        preParsed_->functionInfo.count(startLoc) == 1 &&
738
81
        "no function info stored during preparse");
739
81
    PreParsedFunctionInfo functionInfo = preParsed_->functionInfo[startLoc];
740
81
    SMLoc endLoc = functionInfo.end;
741
81
    if ((unsigned)(endLoc.getPointer() - startLoc.getPointer()) >=
742
81
        context_.getPreemptiveFunctionCompilationThreshold()) {
743
81
      lexer_.seek(endLoc);
744
81
      advance(grammarContext);
745
746
      // Emulate parsing the "use strict" directive in parseBlock.
747
81
      setStrictMode(functionInfo.strictMode);
748
749
      // PreParse collected directives idents into \c PreParsedFunctionInfo,
750
      // iterate on them and fabricate directive nodes into the body node so
751
      // the semantic validator can scan them back.
752
81
      ESTree::NodeList stmtList;
753
81
      for (const llvh::SmallString<24> &directive : functionInfo.directives) {
754
0
        auto *strLit = new (context_)
755
0
            ESTree::StringLiteralNode(lexer_.getIdentifier(directive));
756
0
        auto *dirStmt = new (context_)
757
0
            ESTree::ExpressionStatementNode(strLit, strLit->_value);
758
0
        stmtList.push_back(*dirStmt);
759
0
      }
760
761
81
      auto *body =
762
81
          new (context_) ESTree::BlockStatementNode(std::move(stmtList));
763
81
      body->isLazyFunctionBody = true;
764
      // Set params based on what they were at the _start_ of the function's
765
      // source, not what they are now, because they might have changed.
766
      // For example,
767
      // get [yield]() {}
768
      // means different things based on the value of paramYield at `get`,
769
      // not at the `{`.
770
81
      body->paramYield = paramYield;
771
81
      body->paramAwait = paramAwait;
772
81
      body->bufferId = lexer_.getBufferId();
773
81
      return setLocation(startLoc, endLoc, body);
774
81
    }
775
81
  }
776
777
5.52k
  auto body = parseBlock(ParamReturn, grammarContext, parseDirectives);
778
5.52k
  if (!body)
779
4
    return None;
780
781
5.52k
  if (pass_ == PreParse) {
782
81
    preParsed_->functionInfo[(*body)->getStartLoc()] = PreParsedFunctionInfo{
783
81
        (*body)->getEndLoc(), isStrictMode(), copySeenDirectives()};
784
81
  }
785
786
5.52k
  return body;
787
5.52k
}
788
789
5.49k
Optional<ESTree::Node *> JSParserImpl::parseDeclaration(Param param) {
790
5.49k
  CHECK_RECURSION;
791
792
5.49k
  assert(checkDeclaration() && "invalid start for declaration");
793
794
5.49k
  if (check(TokenKind::rw_function) || check(asyncIdent_)) {
795
5.44k
    auto fdecl = parseFunctionDeclaration(Param{});
796
5.44k
    if (!fdecl)
797
0
      return None;
798
799
5.44k
    return *fdecl;
800
5.44k
  }
801
802
50
  if (check(TokenKind::rw_class)) {
803
0
    auto optClass = parseClassDeclaration(Param{});
804
0
    if (!optClass)
805
0
      return None;
806
807
0
    return *optClass;
808
0
  }
809
810
50
  if (checkN(TokenKind::rw_const, letIdent_)) {
811
50
    auto optLexDecl = parseLexicalDeclaration(ParamIn);
812
50
    if (!optLexDecl)
813
0
      return None;
814
815
50
    return *optLexDecl;
816
50
  }
817
818
0
#if HERMES_PARSE_FLOW
819
0
  if (context_.getParseFlow()) {
820
0
    auto optDecl = parseFlowDeclaration();
821
0
    if (!optDecl)
822
0
      return None;
823
0
    return *optDecl;
824
0
  }
825
0
#endif
826
827
0
#if HERMES_PARSE_TS
828
0
  if (context_.getParseTS()) {
829
0
    auto optDecl = parseTSDeclaration();
830
0
    if (!optDecl)
831
0
      return None;
832
0
    return *optDecl;
833
0
  }
834
0
#endif
835
836
0
  assert(false && "checkDeclaration() returned true without a declaration");
837
0
  return None;
838
0
}
839
840
bool JSParserImpl::parseStatementListItem(
841
    Param param,
842
    AllowImportExport allowImportExport,
843
739k
    ESTree::NodeList &stmtList) {
844
739k
  if (checkDeclaration()) {
845
5.49k
    auto decl = parseDeclaration(Param{});
846
5.49k
    if (!decl)
847
0
      return false;
848
849
5.49k
    stmtList.push_back(*decl.getValue());
850
5.49k
#if HERMES_PARSE_FLOW
851
733k
  } else if (context_.getParseFlow() && checkDeclareType()) {
852
    // declare var, declare function, declare interface, etc.
853
0
    SMLoc start = advance(JSLexer::GrammarContext::Type).Start;
854
0
    auto decl = parseDeclareFLow(start);
855
0
    if (!decl)
856
0
      return false;
857
0
    stmtList.push_back(*decl.getValue());
858
0
#endif
859
733k
  } else if (tok_->getKind() == TokenKind::rw_import) {
860
    // 'import' can indicate an import declaration, but it's also possible a
861
    // Statement begins with a call to `import()`, so do a lookahead to see if
862
    // the next token is '('.
863
    // It can also be import.meta, so check for '.'.
864
0
    auto optNext = lexer_.lookahead1(None);
865
0
    if (optNext.hasValue() &&
866
0
        (*optNext == TokenKind::l_paren || *optNext == TokenKind::period)) {
867
0
      auto stmt = parseStatement(param.get(ParamReturn));
868
0
      if (!stmt)
869
0
        return false;
870
871
0
      stmtList.push_back(*stmt.getValue());
872
0
    } else {
873
0
      auto importDecl = parseImportDeclaration();
874
0
      if (!importDecl) {
875
0
        return false;
876
0
      }
877
878
0
      stmtList.push_back(*importDecl.getValue());
879
0
      if (allowImportExport == AllowImportExport::No) {
880
0
        error(
881
0
            importDecl.getValue()->getSourceRange(),
882
0
            "import declaration must be at top level of module");
883
0
      }
884
0
    }
885
733k
  } else if (tok_->getKind() == TokenKind::rw_export) {
886
0
    auto exportDecl = parseExportDeclaration();
887
0
    if (!exportDecl) {
888
0
      return false;
889
0
    }
890
891
0
    if (allowImportExport == AllowImportExport::Yes) {
892
0
      stmtList.push_back(**exportDecl);
893
0
    } else {
894
0
      error(
895
0
          exportDecl.getValue()->getSourceRange(),
896
0
          "export declaration must be at top level of module");
897
0
    }
898
733k
  } else {
899
733k
    auto stmt = parseStatement(param.get(ParamReturn));
900
733k
    if (!stmt)
901
35
      return false;
902
903
733k
    stmtList.push_back(*stmt.getValue());
904
733k
  }
905
906
739k
  return true;
907
739k
}
908
909
template <typename... Tail>
910
Optional<bool> JSParserImpl::parseStatementList(
911
    Param param,
912
    TokenKind until,
913
    bool parseDirectives,
914
    AllowImportExport allowImportExport,
915
    ESTree::NodeList &stmtList,
916
6.13k
    Tail... otherUntil) {
917
6.13k
  if (parseDirectives) {
918
6.13k
    ESTree::ExpressionStatementNode *dirStmt;
919
6.14k
    while (check(TokenKind::string_literal) &&
920
6.14k
           (dirStmt = parseDirective()) != nullptr) {
921
4
      stmtList.push_back(*dirStmt);
922
4
    }
923
6.13k
  }
924
925
745k
  while (!check(TokenKind::eof) && !checkN(until, otherUntil...)) {
926
739k
    if (!parseStatementListItem(param, allowImportExport, stmtList)) {
927
35
      return None;
928
35
    }
929
739k
  }
930
931
6.10k
  return true;
932
6.13k
}
llvh::Optional<bool> hermes::parser::detail::JSParserImpl::parseStatementList<>(hermes::parser::detail::Param, hermes::parser::TokenKind, bool, hermes::parser::detail::JSParserImpl::AllowImportExport, llvh::simple_ilist<hermes::ESTree::Node>&)
Line
Count
Source
916
6.13k
    Tail... otherUntil) {
917
6.13k
  if (parseDirectives) {
918
6.13k
    ESTree::ExpressionStatementNode *dirStmt;
919
6.14k
    while (check(TokenKind::string_literal) &&
920
6.14k
           (dirStmt = parseDirective()) != nullptr) {
921
4
      stmtList.push_back(*dirStmt);
922
4
    }
923
6.13k
  }
924
925
745k
  while (!check(TokenKind::eof) && !checkN(until, otherUntil...)) {
926
739k
    if (!parseStatementListItem(param, allowImportExport, stmtList)) {
927
35
      return None;
928
35
    }
929
739k
  }
930
931
6.10k
  return true;
932
6.13k
}
Unexecuted instantiation: llvh::Optional<bool> hermes::parser::detail::JSParserImpl::parseStatementList<hermes::parser::TokenKind, hermes::parser::TokenKind>(hermes::parser::detail::Param, hermes::parser::TokenKind, bool, hermes::parser::detail::JSParserImpl::AllowImportExport, llvh::simple_ilist<hermes::ESTree::Node>&, hermes::parser::TokenKind, hermes::parser::TokenKind)
933
934
Optional<ESTree::BlockStatementNode *> JSParserImpl::parseBlock(
935
    Param param,
936
    JSLexer::GrammarContext grammarContext,
937
5.52k
    bool parseDirectives) {
938
  // {
939
5.52k
  assert(check(TokenKind::l_brace));
940
5.52k
  SMLoc startLoc = advance().Start;
941
942
5.52k
  ESTree::NodeList stmtList;
943
944
5.52k
  if (!parseStatementList(
945
5.52k
          param,
946
5.52k
          TokenKind::r_brace,
947
5.52k
          parseDirectives,
948
5.52k
          AllowImportExport::No,
949
5.52k
          stmtList)) {
950
6
    return None;
951
6
  }
952
953
  // }
954
5.52k
  auto *body = setLocation(
955
5.52k
      startLoc,
956
5.52k
      tok_,
957
5.52k
      new (context_) ESTree::BlockStatementNode(std::move(stmtList)));
958
5.52k
  if (!eat(
959
5.52k
          TokenKind::r_brace,
960
5.52k
          grammarContext,
961
5.52k
          "at end of block",
962
5.52k
          "block starts here",
963
5.52k
          startLoc))
964
0
    return None;
965
966
5.52k
  return body;
967
5.52k
}
968
969
bool JSParserImpl::validateBindingIdentifier(
970
    Param param,
971
    SMRange range,
972
    UniqueString *id,
973
215k
    TokenKind kind) {
974
215k
  if (id == yieldIdent_) {
975
    // yield is permitted as BindingIdentifier in the grammar,
976
    // and prohibited with static semantics.
977
0
    if (isStrictMode() || paramYield_) {
978
0
      error(range, "Unexpected usage of 'yield' as an identifier");
979
0
    }
980
0
  }
981
982
215k
  if (id == awaitIdent_) {
983
    // await is permitted as BindingIdentifier in the grammar,
984
    // and prohibited with static semantics.
985
0
    if (paramAwait_) {
986
0
      error(range, "Unexpected usage of 'await' as an identifier");
987
0
    }
988
0
  }
989
990
215k
  if (isStrictMode() && id == letIdent_) {
991
    // ES9.0 12.1.1
992
    // BindingIdentifier : Identifier
993
    // Identifier : IdentifierName (but not ReservedWord)
994
    // It is a Syntax Error if this phrase is contained in strict mode code
995
    // and the StringValue of IdentifierName is: "implements", "interface",
996
    // "let", "package", "private", "protected", "public", "static", or
997
    // "yield".
998
    // NOTE: All except 'let' are scanned as reserved words instead of
999
    // identifiers, so we only check for `let` here.
1000
0
    error(
1001
0
        range,
1002
0
        "Invalid use of strict mode reserved word as binding identifier");
1003
0
  }
1004
1005
215k
  return kind == TokenKind::identifier || kind == TokenKind::rw_yield;
1006
215k
}
1007
1008
Optional<ESTree::IdentifierNode *> JSParserImpl::parseBindingIdentifier(
1009
9.49k
    Param param) {
1010
9.49k
  if (!check(TokenKind::identifier) && !tok_->isResWord()) {
1011
168
    return None;
1012
168
  }
1013
9.33k
  SMRange identRng = tok_->getSourceRange();
1014
1015
  // If we have an identifier or reserved word, then store it and the kind,
1016
  // and pass it to the validateBindingIdentifier function.
1017
9.33k
  UniqueString *id = tok_->getResWordOrIdentifier();
1018
9.33k
  TokenKind kind = tok_->getKind();
1019
9.33k
  if (!validateBindingIdentifier(param, tok_->getSourceRange(), id, kind)) {
1020
0
    return None;
1021
0
  }
1022
9.33k
  advance();
1023
1024
9.33k
  ESTree::Node *type = nullptr;
1025
9.33k
  bool optional = false;
1026
9.33k
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
1027
9.33k
  if (context_.getParseTypes()) {
1028
0
    if (check(TokenKind::question)) {
1029
0
      optional = true;
1030
0
      advance(JSLexer::GrammarContext::Type);
1031
0
    }
1032
1033
0
    if (check(TokenKind::colon)) {
1034
0
      SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
1035
0
      auto optType = parseTypeAnnotation(annotStart);
1036
0
      if (!optType)
1037
0
        return None;
1038
0
      type = *optType;
1039
0
    }
1040
0
  }
1041
9.33k
#endif
1042
1043
9.33k
  return setLocation(
1044
9.33k
      identRng,
1045
9.33k
      getPrevTokenEndLoc(),
1046
9.33k
      new (context_) ESTree::IdentifierNode(id, type, optional));
1047
9.33k
}
1048
1049
Optional<ESTree::VariableDeclarationNode *>
1050
3.89k
JSParserImpl::parseLexicalDeclaration(Param param) {
1051
3.89k
  assert(
1052
3.89k
      (check(TokenKind::rw_var) || check(TokenKind::rw_const) ||
1053
3.89k
       check(letIdent_)) &&
1054
3.89k
      "parseLexicalDeclaration() expects var/const/let");
1055
3.89k
  bool isConst = check(TokenKind::rw_const);
1056
3.89k
  auto kindIdent = tok_->getResWordOrIdentifier();
1057
1058
3.89k
  SMLoc startLoc = advance().Start;
1059
1060
3.89k
  ESTree::NodeList declList;
1061
3.89k
  if (!parseVariableDeclarationList(param, declList, startLoc))
1062
0
    return None;
1063
1064
3.89k
  if (!eatSemi())
1065
0
    return None;
1066
1067
3.89k
  if (isConst) {
1068
0
    for (const ESTree::Node &decl : declList) {
1069
0
      const auto *varDecl = cast<ESTree::VariableDeclaratorNode>(&decl);
1070
0
      if (!varDecl->_init) {
1071
        // ES9.0 13.3.1.1
1072
        // LexicalBinding : BindingIdentifier Initializer
1073
        // It is a Syntax Error if Initializer is not present and
1074
        // IsConstantDeclaration of the LexicalDeclaration containing this
1075
        // LexicalBinding is true.
1076
        // Note that we don't perform this check in the SemanticValidator
1077
        // because `const` declarations in `for` loops don't need initializers.
1078
0
        error(
1079
0
            varDecl->getSourceRange(),
1080
0
            "missing initializer in const declaration");
1081
0
      }
1082
0
    }
1083
0
  }
1084
1085
3.89k
  auto *res = setLocation(
1086
3.89k
      startLoc,
1087
3.89k
      getPrevTokenEndLoc(),
1088
3.89k
      new (context_)
1089
3.89k
          ESTree::VariableDeclarationNode(kindIdent, std::move(declList)));
1090
1091
3.89k
  ensureDestructuringInitialized(res);
1092
1093
3.89k
  return res;
1094
3.89k
}
1095
1096
Optional<ESTree::VariableDeclarationNode *>
1097
3.84k
JSParserImpl::parseVariableStatement(Param param) {
1098
3.84k
  return parseLexicalDeclaration(ParamIn);
1099
3.84k
}
1100
1101
0
Optional<ESTree::PrivateNameNode *> JSParserImpl::parsePrivateName() {
1102
0
  assert(check(TokenKind::private_identifier));
1103
0
  ESTree::Node *ident = setLocation(
1104
0
      tok_,
1105
0
      tok_,
1106
0
      new (context_)
1107
0
          ESTree::IdentifierNode(tok_->getPrivateIdentifier(), nullptr, false));
1108
0
  SMLoc start = advance(JSLexer::GrammarContext::AllowDiv).Start;
1109
0
  return setLocation(
1110
0
      start, ident, new (context_) ESTree::PrivateNameNode(ident));
1111
0
}
1112
1113
Optional<const char *> JSParserImpl::parseVariableDeclarationList(
1114
    Param param,
1115
    ESTree::NodeList &declList,
1116
3.89k
    SMLoc declLoc) {
1117
3.89k
  do {
1118
3.89k
    auto optDecl = parseVariableDeclaration(param, declLoc);
1119
3.89k
    if (!optDecl)
1120
0
      return None;
1121
3.89k
    declList.push_back(*optDecl.getValue());
1122
3.89k
  } while (checkAndEat(TokenKind::comma));
1123
1124
3.89k
  return "OK";
1125
3.89k
}
1126
1127
void JSParserImpl::ensureDestructuringInitialized(
1128
3.89k
    ESTree::VariableDeclarationNode *declNode) {
1129
3.89k
  for (auto &elem : declNode->_declarations) {
1130
3.89k
    auto *declarator = cast<ESTree::VariableDeclaratorNode>(&elem);
1131
1132
3.89k
    if (!isa<ESTree::PatternNode>(declarator->_id) || declarator->_init)
1133
3.89k
      continue;
1134
1135
0
    error(
1136
0
        declarator->_id->getSourceRange(),
1137
0
        "destucturing declaration must be initialized");
1138
0
  }
1139
3.89k
}
1140
1141
Optional<ESTree::VariableDeclaratorNode *>
1142
3.89k
JSParserImpl::parseVariableDeclaration(Param param, SMLoc declLoc) {
1143
3.89k
  ESTree::Node *target;
1144
3.89k
  SMLoc startLoc = tok_->getStartLoc();
1145
1146
3.89k
  if (check(TokenKind::l_square, TokenKind::l_brace)) {
1147
0
    auto optPat = parseBindingPattern(param);
1148
0
    if (!optPat)
1149
0
      return None;
1150
1151
0
    target = *optPat;
1152
3.89k
  } else {
1153
3.89k
    auto optIdent = parseBindingIdentifier(Param{});
1154
3.89k
    if (!optIdent) {
1155
0
      errorExpected(
1156
0
          TokenKind::identifier,
1157
0
          "in declaration",
1158
0
          "declaration started here",
1159
0
          declLoc);
1160
0
      return None;
1161
0
    }
1162
1163
3.89k
    target = *optIdent;
1164
3.89k
  }
1165
1166
  // No initializer?
1167
3.89k
  if (!check(TokenKind::equal)) {
1168
3.89k
    return setLocation(
1169
3.89k
        startLoc,
1170
3.89k
        getPrevTokenEndLoc(),
1171
3.89k
        new (context_) ESTree::VariableDeclaratorNode(nullptr, target));
1172
3.89k
  };
1173
1174
  // Parse the initializer.
1175
0
  auto debugLoc = advance().Start;
1176
1177
0
  auto expr = parseAssignmentExpression(
1178
0
      param, AllowTypedArrowFunction::Yes, CoverTypedParameters::No);
1179
0
  if (!expr)
1180
0
    return None;
1181
1182
0
  return setLocation(
1183
0
      startLoc,
1184
0
      getPrevTokenEndLoc(),
1185
0
      debugLoc,
1186
0
      new (context_) ESTree::VariableDeclaratorNode(*expr, target));
1187
0
}
1188
1189
0
Optional<ESTree::Node *> JSParserImpl::parseBindingPattern(Param param) {
1190
0
  assert(
1191
0
      check(TokenKind::l_square, TokenKind::l_brace) &&
1192
0
      "BindingPattern expects '{' or '['");
1193
0
  if (check(TokenKind::l_square)) {
1194
0
    auto optAB = parseArrayBindingPattern(param);
1195
0
    if (!optAB)
1196
0
      return None;
1197
0
    return *optAB;
1198
0
  } else {
1199
0
    auto optOB = parseObjectBindingPattern(param);
1200
0
    if (!optOB)
1201
0
      return None;
1202
0
    return *optOB;
1203
0
  }
1204
0
}
1205
1206
Optional<ESTree::ArrayPatternNode *> JSParserImpl::parseArrayBindingPattern(
1207
0
    Param param) {
1208
0
  assert(check(TokenKind::l_square) && "ArrayBindingPattern expects '['");
1209
1210
  // Eat the '[', recording the start location.
1211
0
  auto startLoc = advance().Start;
1212
1213
0
  ESTree::NodeList elemList;
1214
1215
0
  if (!check(TokenKind::r_square)) {
1216
0
    for (;;) {
1217
0
      if (check(TokenKind::comma)) {
1218
        // Elision.
1219
0
        elemList.push_back(
1220
0
            *setLocation(tok_, tok_, new (context_) ESTree::EmptyNode()));
1221
0
      } else if (check(TokenKind::dotdotdot)) {
1222
        // BindingRestElement.
1223
0
        auto optRestElem = parseBindingRestElement(param);
1224
0
        if (!optRestElem)
1225
0
          return None;
1226
0
        elemList.push_back(*optRestElem.getValue());
1227
0
        break;
1228
0
      } else {
1229
        // BindingElement.
1230
0
        auto optElem = parseBindingElement(param);
1231
0
        if (!optElem)
1232
0
          return None;
1233
0
        elemList.push_back(*optElem.getValue());
1234
0
      }
1235
1236
0
      if (!checkAndEat(TokenKind::comma))
1237
0
        break;
1238
0
      if (check(TokenKind::r_square)) // Check for ",]".
1239
0
        break;
1240
0
    }
1241
0
  }
1242
1243
0
  if (!eat(
1244
0
          TokenKind::r_square,
1245
0
          JSLexer::AllowDiv,
1246
0
          "at end of array binding pattern '[...'",
1247
0
          "location of '['",
1248
0
          startLoc))
1249
0
    return None;
1250
1251
0
  ESTree::Node *type = nullptr;
1252
0
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
1253
0
  if (context_.getParseTypes()) {
1254
0
    if (check(TokenKind::colon)) {
1255
0
      SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
1256
0
      auto optType = parseTypeAnnotation(annotStart);
1257
0
      if (!optType)
1258
0
        return None;
1259
0
      type = *optType;
1260
0
    }
1261
0
  }
1262
0
#endif
1263
1264
0
  return setLocation(
1265
0
      startLoc,
1266
0
      getPrevTokenEndLoc(),
1267
0
      new (context_) ESTree::ArrayPatternNode(std::move(elemList), type));
1268
0
}
1269
1270
1
Optional<ESTree::Node *> JSParserImpl::parseBindingElement(Param param) {
1271
1
  CHECK_RECURSION;
1272
1
  ESTree::Node *elem;
1273
1274
1
  if (check(TokenKind::l_square, TokenKind::l_brace)) {
1275
0
    auto optPat = parseBindingPattern(param);
1276
0
    if (!optPat)
1277
0
      return None;
1278
0
    elem = *optPat;
1279
1
  } else {
1280
1
    auto optIdent = parseBindingIdentifier(param);
1281
1
    if (!optIdent) {
1282
0
      error(
1283
0
          tok_->getStartLoc(),
1284
0
          "identifier, '{' or '[' expected in binding pattern");
1285
0
      return None;
1286
0
    }
1287
1
    elem = *optIdent;
1288
1
  }
1289
1290
  // No initializer?
1291
1
  if (!check(TokenKind::equal))
1292
1
    return elem;
1293
1294
0
  auto optInit = parseBindingInitializer(param, elem);
1295
0
  if (!optInit)
1296
0
    return None;
1297
0
  return *optInit;
1298
0
}
1299
1300
0
Optional<ESTree::Node *> JSParserImpl::parseBindingRestElement(Param param) {
1301
0
  assert(
1302
0
      check(TokenKind::dotdotdot) &&
1303
0
      "BindingRestElement expected to start with '...'");
1304
1305
0
  auto startLoc = advance().Start;
1306
1307
0
  auto optElem = parseBindingElement(param);
1308
0
  if (!optElem)
1309
0
    return None;
1310
0
  if (isa<ESTree::AssignmentPatternNode>(*optElem)) {
1311
0
    error(
1312
0
        optElem.getValue()->getSourceRange(),
1313
0
        "rest elemenent may not have a default initializer");
1314
0
    return None;
1315
0
  }
1316
1317
0
  return setLocation(
1318
0
      startLoc,
1319
0
      getPrevTokenEndLoc(),
1320
0
      new (context_) ESTree::RestElementNode(*optElem));
1321
0
}
1322
1323
Optional<ESTree::AssignmentPatternNode *> JSParserImpl::parseBindingInitializer(
1324
    Param param,
1325
0
    ESTree::Node *left) {
1326
0
  assert(check(TokenKind::equal) && "binding initializer requires '='");
1327
1328
  // Parse the initializer.
1329
0
  auto debugLoc = advance().Start;
1330
1331
0
  auto expr = parseAssignmentExpression(ParamIn + param);
1332
0
  if (!expr)
1333
0
    return None;
1334
1335
0
  return setLocation(
1336
0
      left,
1337
0
      getPrevTokenEndLoc(),
1338
0
      debugLoc,
1339
0
      new (context_) ESTree::AssignmentPatternNode(left, *expr));
1340
0
}
1341
1342
Optional<ESTree::ObjectPatternNode *> JSParserImpl::parseObjectBindingPattern(
1343
0
    Param param) {
1344
0
  assert(check(TokenKind::l_brace) && "ObjectBindingPattern expects '{'");
1345
1346
  // Eat the '{', recording the start location.
1347
0
  auto startLoc = advance().Start;
1348
1349
0
  ESTree::NodeList propList{};
1350
1351
0
  if (!check(TokenKind::r_brace)) {
1352
0
    for (;;) {
1353
0
      if (check(TokenKind::dotdotdot)) {
1354
        // BindingRestProperty.
1355
0
        auto optRestElem = parseBindingRestProperty(param);
1356
0
        if (!optRestElem)
1357
0
          return None;
1358
0
        propList.push_back(*optRestElem.getValue());
1359
0
        break;
1360
0
      }
1361
0
      auto optProp = parseBindingProperty(param);
1362
0
      if (!optProp)
1363
0
        return None;
1364
1365
0
      propList.push_back(**optProp);
1366
1367
0
      if (!checkAndEat(TokenKind::comma))
1368
0
        break;
1369
0
      if (check(TokenKind::r_brace)) // check for ",}"
1370
0
        break;
1371
0
    }
1372
0
  }
1373
1374
0
  if (!eat(
1375
0
          TokenKind::r_brace,
1376
0
          JSLexer::AllowDiv,
1377
0
          "at end of object binding pattern '{...'",
1378
0
          "location of '{'",
1379
0
          startLoc))
1380
0
    return None;
1381
1382
0
  ESTree::Node *type = nullptr;
1383
0
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
1384
0
  if (context_.getParseTypes()) {
1385
0
    if (check(TokenKind::colon)) {
1386
0
      SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
1387
0
      auto optType = parseTypeAnnotation(annotStart);
1388
0
      if (!optType)
1389
0
        return None;
1390
0
      type = *optType;
1391
0
    }
1392
0
  }
1393
0
#endif
1394
1395
0
  return setLocation(
1396
0
      startLoc,
1397
0
      getPrevTokenEndLoc(),
1398
0
      new (context_) ESTree::ObjectPatternNode(std::move(propList), type));
1399
0
}
1400
1401
Optional<ESTree::PropertyNode *> JSParserImpl::parseBindingProperty(
1402
0
    Param param) {
1403
0
  bool computed = check(TokenKind::l_square);
1404
0
  SMLoc startLoc = tok_->getStartLoc();
1405
0
  auto optKey = parsePropertyName();
1406
0
  if (!optKey)
1407
0
    return None;
1408
0
  ESTree::Node *key = optKey.getValue();
1409
1410
0
  ESTree::Node *value = nullptr;
1411
0
  bool shorthand = false;
1412
1413
0
  if (checkAndEat(TokenKind::colon)) {
1414
    // PropertyName ":" BindingElement
1415
    //               ^
1416
0
    auto optElement = parseBindingElement(Param{});
1417
0
    if (!optElement)
1418
0
      return None;
1419
0
    value = optElement.getValue();
1420
0
  } else {
1421
    // SingleNameBinding :
1422
    //   BindingIdentifier Initializer[opt]
1423
    //                     ^
1424
1425
    // Must validate BindingIdentifier, because there are certain identifiers
1426
    // which are valid as PropertyName but not as BindingIdentifier.
1427
0
    auto *ident = dyn_cast<ESTree::IdentifierNode>(key);
1428
0
    if (!ident ||
1429
0
        !validateBindingIdentifier(
1430
0
            Param{},
1431
0
            ident->getSourceRange(),
1432
0
            ident->_name,
1433
0
            TokenKind::identifier)) {
1434
0
      error(startLoc, "identifier expected in object binding pattern");
1435
0
      return None;
1436
0
    }
1437
1438
0
    shorthand = true;
1439
1440
0
    if (check(TokenKind::equal)) {
1441
      // BindingIdentifier Initializer
1442
      //                   ^
1443
      // Clone the key because parseBindingInitializer will wrap it.
1444
0
      auto *left = setLocation(
1445
0
          ident,
1446
0
          ident,
1447
0
          new (context_) ESTree::IdentifierNode(ident->_name, nullptr, false));
1448
0
      auto optInit = parseBindingInitializer(param + ParamIn, left);
1449
0
      if (!optInit)
1450
0
        return None;
1451
1452
0
      value = *optInit;
1453
0
    } else {
1454
      // BindingIdentifier
1455
      //                   ^
1456
      // Shorthand property initialization, clone the key directly.
1457
0
      value = setLocation(
1458
0
          ident,
1459
0
          ident,
1460
0
          new (context_) ESTree::IdentifierNode(ident->_name, nullptr, false));
1461
0
    }
1462
0
  }
1463
1464
0
  return setLocation(
1465
0
      startLoc,
1466
0
      getPrevTokenEndLoc(),
1467
0
      new (context_) ESTree::PropertyNode(
1468
0
          key, value, initIdent_, computed, false, shorthand));
1469
0
}
1470
1471
Optional<ESTree::Node *> JSParserImpl::parseBindingRestProperty(
1472
0
    hermes::parser::detail::Param param) {
1473
0
  assert(
1474
0
      check(TokenKind::dotdotdot) &&
1475
0
      "BindingRestProperty expected to start with '...'");
1476
1477
0
  auto startLoc = advance().Start;
1478
1479
  // NOTE: the spec says that this cannot be another pattern, even though it
1480
  // would make sense.
1481
#if 0
1482
  auto optElem = parseBindingElement(param);
1483
#else
1484
0
  auto optElem = parseBindingIdentifier(param);
1485
0
#endif
1486
0
  if (!optElem) {
1487
0
    error(
1488
0
        tok_->getStartLoc(),
1489
0
        "identifier expected after '...' in object pattern");
1490
0
    return None;
1491
0
  }
1492
1493
0
  return setLocation(
1494
0
      startLoc,
1495
0
      getPrevTokenEndLoc(),
1496
0
      new (context_) ESTree::RestElementNode(*optElem));
1497
0
}
1498
1499
10.6k
Optional<ESTree::EmptyStatementNode *> JSParserImpl::parseEmptyStatement() {
1500
10.6k
  assert(check(TokenKind::semi));
1501
10.6k
  auto *empty =
1502
10.6k
      setLocation(tok_, tok_, new (context_) ESTree::EmptyStatementNode());
1503
10.6k
  advance();
1504
1505
10.6k
  return empty;
1506
10.6k
}
1507
1508
Optional<ESTree::Node *> JSParserImpl::parseExpressionOrLabelledStatement(
1509
1.21M
    Param param) {
1510
1.21M
  bool startsWithIdentifier = check(TokenKind::identifier);
1511
1512
  // ES9.0 13.5
1513
  // Lookahead cannot be any of: {, function, async function, class, let [
1514
  // Allow execution to continue because the expression may be parsed,
1515
  // but report an error because it will be ambiguous whether the parse was
1516
  // correct.
1517
1.21M
  if (checkN(TokenKind::l_brace, TokenKind::rw_function, TokenKind::rw_class) ||
1518
1.21M
      (check(asyncIdent_) && checkAsyncFunction())) {
1519
    // There's no need to stop reporting errors.
1520
0
    error(
1521
0
        tok_->getSourceRange(),
1522
0
        "declaration not allowed as expression statement");
1523
0
  }
1524
1525
1.21M
  if (check(letIdent_)) {
1526
0
    SMLoc letLoc = advance().Start;
1527
0
    if (check(TokenKind::l_square)) {
1528
      // let [
1529
0
      error(
1530
0
          {letLoc, tok_->getEndLoc()},
1531
0
          "ambiguous 'let [': either a 'let' binding or a member expression");
1532
0
    }
1533
0
    lexer_.seek(letLoc);
1534
0
    advance();
1535
0
  }
1536
1537
1.21M
  SMLoc startLoc = tok_->getStartLoc();
1538
1.21M
  auto optExpr = parseExpression(ParamIn, CoverTypedParameters::No);
1539
1.21M
  if (!optExpr)
1540
29
    return None;
1541
1542
  // Check whether this is a label. The expression must have started with an
1543
  // identifier, be just an identifier and be
1544
  // followed by ':'
1545
1.21M
  if (startsWithIdentifier && isa<ESTree::IdentifierNode>(optExpr.getValue()) &&
1546
1.21M
      checkAndEat(TokenKind::colon)) {
1547
492k
    auto *id = cast<ESTree::IdentifierNode>(optExpr.getValue());
1548
1549
492k
    ESTree::Node *body = nullptr;
1550
492k
    if (check(TokenKind::rw_function)) {
1551
0
      auto optFunc = parseFunctionDeclaration(param);
1552
0
      if (!optFunc)
1553
0
        return None;
1554
      /// ES9.0 13.13.1
1555
      /// It is a Syntax Error if any source text matches this rule.
1556
      /// LabelledItem : FunctionDeclaration
1557
      /// NOTE: GeneratorDeclarations are disallowed as part of the grammar
1558
      /// as well, so all FunctionDeclarations are disallowed as labeled
1559
      /// items, except via an AnnexB extension which is unsupported in
1560
      /// Hermes.
1561
0
      error(
1562
0
          optFunc.getValue()->getSourceRange().Start,
1563
0
          "Function declaration not allowed as body of labeled statement");
1564
0
      body = optFunc.getValue();
1565
492k
    } else {
1566
      // Statement
1567
492k
      auto optBody = parseStatement(param.get(ParamReturn));
1568
492k
      if (!optBody)
1569
4
        return None;
1570
492k
      body = optBody.getValue();
1571
492k
    }
1572
1573
492k
    return setLocation(
1574
492k
        id, body, new (context_) ESTree::LabeledStatementNode(id, body));
1575
719k
  } else {
1576
719k
    if (!eatSemi())
1577
4
      return None;
1578
1579
719k
    return setLocation(
1580
719k
        startLoc,
1581
719k
        getPrevTokenEndLoc(),
1582
719k
        new (context_)
1583
719k
            ESTree::ExpressionStatementNode(optExpr.getValue(), nullptr));
1584
719k
  }
1585
1.21M
}
1586
1587
Optional<ESTree::IfStatementNode *> JSParserImpl::parseIfStatement(
1588
0
    Param param) {
1589
0
  assert(check(TokenKind::rw_if));
1590
0
  SMLoc startLoc = advance().Start;
1591
1592
0
  SMLoc condLoc = tok_->getStartLoc();
1593
0
  if (!eat(
1594
0
          TokenKind::l_paren,
1595
0
          JSLexer::AllowRegExp,
1596
0
          "after 'if'",
1597
0
          "location of 'if'",
1598
0
          startLoc))
1599
0
    return None;
1600
0
  auto optTest = parseExpression();
1601
0
  if (!optTest)
1602
0
    return None;
1603
0
  if (!eat(
1604
0
          TokenKind::r_paren,
1605
0
          JSLexer::AllowRegExp,
1606
0
          "at end of 'if' condition",
1607
0
          "'if' condition starts here",
1608
0
          condLoc))
1609
0
    return None;
1610
1611
  /// Parse a statement or (only in loose mode) a function declaration.
1612
  /// ES2022 B.3.3 allows FunctionDeclaration as consequent and alternate.
1613
  /// These FunctionDeclarations are supposed to be processed precisely as if
1614
  /// they were surrounded by BlockStatement, including function promotion.
1615
  /// To allow this, surround them with a synthetic BlockStatement.
1616
0
  auto parseStatementOrFunctionDeclaration =
1617
0
      [this, param]() -> Optional<ESTree::Node *> {
1618
0
    if (check(TokenKind::rw_function)) {
1619
0
      auto optFunction = parseFunctionDeclaration(Param{});
1620
0
      if (!optFunction)
1621
0
        return None;
1622
0
      if (isStrictMode()) {
1623
0
        error(
1624
0
            (*optFunction)->getStartLoc(),
1625
0
            "In strict mode, functions cannot be declared in if statements");
1626
0
      }
1627
0
      if ((*optFunction)->_generator || (*optFunction)->_async) {
1628
0
        error(
1629
0
            (*optFunction)->getStartLoc(),
1630
0
            "Functions in if statements cannot be generator/async");
1631
0
      }
1632
0
      ESTree::NodeList stmts;
1633
0
      stmts.push_back(**optFunction);
1634
0
      return setLocation(
1635
0
          *optFunction,
1636
0
          *optFunction,
1637
0
          new (context_) ESTree::BlockStatementNode(std::move(stmts)));
1638
0
    }
1639
0
    auto optStatement = parseStatement(param.get(ParamReturn));
1640
0
    if (!optStatement)
1641
0
      return None;
1642
0
    return *optStatement;
1643
0
  };
1644
1645
0
  auto optConsequent = parseStatementOrFunctionDeclaration();
1646
0
  if (!optConsequent)
1647
0
    return None;
1648
1649
0
  if (checkAndEat(TokenKind::rw_else)) {
1650
0
    auto optAlternate = parseStatementOrFunctionDeclaration();
1651
0
    if (!optAlternate)
1652
0
      return None;
1653
1654
0
    return setLocation(
1655
0
        startLoc,
1656
0
        optAlternate.getValue(),
1657
0
        new (context_) ESTree::IfStatementNode(
1658
0
            optTest.getValue(),
1659
0
            optConsequent.getValue(),
1660
0
            optAlternate.getValue()));
1661
0
  } else {
1662
0
    return setLocation(
1663
0
        startLoc,
1664
0
        optConsequent.getValue(),
1665
0
        new (context_) ESTree::IfStatementNode(
1666
0
            optTest.getValue(), optConsequent.getValue(), nullptr));
1667
0
  }
1668
0
}
1669
1670
Optional<ESTree::WhileStatementNode *> JSParserImpl::parseWhileStatement(
1671
0
    Param param) {
1672
0
  assert(check(TokenKind::rw_while));
1673
0
  SMLoc startLoc = advance().Start;
1674
1675
0
  if (!eat(
1676
0
          TokenKind::l_paren,
1677
0
          JSLexer::AllowRegExp,
1678
0
          "after 'while'",
1679
0
          "location of 'while'",
1680
0
          startLoc))
1681
0
    return None;
1682
0
  auto optTest = parseExpression();
1683
0
  if (!optTest)
1684
0
    return None;
1685
0
  if (!eat(
1686
0
          TokenKind::r_paren,
1687
0
          JSLexer::AllowRegExp,
1688
0
          "at end of 'while' condition",
1689
0
          "location of 'while'",
1690
0
          startLoc))
1691
0
    return None;
1692
1693
0
  auto optBody = parseStatement(param.get(ParamReturn));
1694
0
  if (!optBody)
1695
0
    return None;
1696
1697
0
  return setLocation(
1698
0
      startLoc,
1699
0
      optBody.getValue(),
1700
0
      new (context_)
1701
0
          ESTree::WhileStatementNode(optBody.getValue(), optTest.getValue()));
1702
0
}
1703
1704
Optional<ESTree::DoWhileStatementNode *> JSParserImpl::parseDoWhileStatement(
1705
0
    Param param) {
1706
0
  assert(check(TokenKind::rw_do));
1707
0
  SMLoc startLoc = advance().Start;
1708
1709
0
  auto optBody = parseStatement(param.get(ParamReturn));
1710
0
  if (!optBody)
1711
0
    return None;
1712
1713
0
  SMLoc whileLoc = tok_->getStartLoc();
1714
0
  if (!eat(
1715
0
          TokenKind::rw_while,
1716
0
          JSLexer::AllowRegExp,
1717
0
          "at end of 'do-while'",
1718
0
          "'do-while' starts here",
1719
0
          startLoc))
1720
0
    return None;
1721
1722
0
  if (!eat(
1723
0
          TokenKind::l_paren,
1724
0
          JSLexer::AllowRegExp,
1725
0
          "after 'do-while'",
1726
0
          "location of 'while'",
1727
0
          whileLoc))
1728
0
    return None;
1729
0
  auto optTest = parseExpression();
1730
0
  if (!optTest)
1731
0
    return None;
1732
0
  if (!eat(
1733
0
          TokenKind::r_paren,
1734
0
          JSLexer::AllowRegExp,
1735
0
          "at end of 'do-while' condition",
1736
0
          "location of 'while'",
1737
0
          whileLoc))
1738
0
    return None;
1739
1740
0
  eatSemi(true);
1741
1742
0
  return setLocation(
1743
0
      startLoc,
1744
0
      getPrevTokenEndLoc(),
1745
0
      new (context_)
1746
0
          ESTree::DoWhileStatementNode(optBody.getValue(), optTest.getValue()));
1747
0
}
1748
1749
32
Optional<ESTree::Node *> JSParserImpl::parseForStatement(Param param) {
1750
32
  assert(check(TokenKind::rw_for));
1751
32
  SMLoc startLoc = advance().Start;
1752
1753
32
  bool await = false;
1754
32
  SMRange awaitRng;
1755
32
  if (paramAwait_ && check(awaitIdent_)) {
1756
0
    awaitRng = advance();
1757
0
    await = true;
1758
0
  }
1759
1760
32
  SMLoc lparenLoc = tok_->getStartLoc();
1761
32
  if (!eat(
1762
32
          TokenKind::l_paren,
1763
32
          JSLexer::AllowRegExp,
1764
32
          "after 'for'",
1765
32
          "location of 'for'",
1766
32
          startLoc))
1767
0
    return None;
1768
1769
32
  ESTree::VariableDeclarationNode *decl = nullptr;
1770
32
  ESTree::NodePtr expr1 = nullptr;
1771
1772
32
  if (checkN(TokenKind::rw_var, TokenKind::rw_const, letIdent_)) {
1773
    // Productions valid here:
1774
    //   for ( var/let/const VariableDeclarationList
1775
    //   for [await] ( var/let/const VariableDeclaration
1776
0
    SMLoc varStartLoc = tok_->getStartLoc();
1777
0
    auto *declIdent = tok_->getResWordOrIdentifier();
1778
0
    advance();
1779
1780
0
    ESTree::NodeList declList;
1781
0
    if (!parseVariableDeclarationList(Param{}, declList, varStartLoc))
1782
0
      return None;
1783
1784
0
    auto endLoc = declList.back().getEndLoc();
1785
0
    decl = setLocation(
1786
0
        varStartLoc,
1787
0
        endLoc,
1788
0
        new (context_)
1789
0
            ESTree::VariableDeclarationNode(declIdent, std::move(declList)));
1790
32
  } else {
1791
32
    if (!check(TokenKind::semi)) {
1792
31
      llvh::Optional<ESTree::Node *> optExpr1;
1793
31
      if (await) {
1794
        //   for await ( LeftHandSideExpression
1795
        //               ^
1796
0
        optExpr1 = parseLeftHandSideExpression();
1797
31
      } else {
1798
        // ForStatement:
1799
        //   for ( Expression_opt
1800
        //         ^
1801
        // ForInOfStatement:
1802
        //   for ( LeftHandSideExpression
1803
        //         ^
1804
        // Lookahead for LeftHandSideExpression cannot be 'let' or 'async of'.
1805
        // We've handled `let` above.
1806
        // To distinguish between the two productions here, we let the resolver
1807
        // check that the LHS of the `of` or `in` is valid (the resolver will
1808
        // throw the error instead of the parser).
1809
31
        optExpr1 = parseExpression(Param{});
1810
31
      }
1811
31
      if (!optExpr1)
1812
0
        return None;
1813
31
      expr1 = optExpr1.getValue();
1814
31
    }
1815
32
  }
1816
1817
32
  if (checkN(TokenKind::rw_in, ofIdent_)) {
1818
    // Productions valid here:
1819
    //   for [await] ( var/let/const VariableDeclaration[In] in/of
1820
    //   for [await] ( LeftHandSideExpression in/of
1821
1822
31
    if (decl && decl->_declarations.size() > 1) {
1823
0
      error(
1824
0
          decl->getSourceRange(),
1825
0
          "Only one binding must be declared in a for-in/for-of loop");
1826
0
      return None;
1827
0
    }
1828
1829
    // Check for destructuring pattern on the left and reparse it.
1830
31
    if (expr1 &&
1831
31
        (isa<ESTree::ArrayExpressionNode>(expr1) ||
1832
31
         isa<ESTree::ObjectExpressionNode>(expr1))) {
1833
0
      auto optExpr1 = reparseAssignmentPattern(expr1, false);
1834
0
      if (!optExpr1)
1835
0
        return None;
1836
0
      expr1 = *optExpr1;
1837
0
    }
1838
1839
    // Remember whether we are parsing for-in or for-of.
1840
31
    bool const forInLoop = check(TokenKind::rw_in);
1841
31
    advance();
1842
1843
31
    if (forInLoop && await)
1844
0
      error(awaitRng, "unexpected 'await' in for..in loop");
1845
1846
31
    auto optRightExpr =
1847
31
        forInLoop ? parseExpression() : parseAssignmentExpression(ParamIn);
1848
1849
31
    if (!eat(
1850
31
            TokenKind::r_paren,
1851
31
            JSLexer::AllowRegExp,
1852
31
            "after 'for(... in/of ...'",
1853
31
            "location of '('",
1854
31
            lparenLoc))
1855
0
      return None;
1856
1857
31
    auto optBody = parseStatement(param.get(ParamReturn));
1858
31
    if (!optBody || !optRightExpr)
1859
0
      return None;
1860
1861
31
    ESTree::Node *node;
1862
31
    if (forInLoop) {
1863
31
      node = new (context_) ESTree::ForInStatementNode(
1864
31
          decl ? decl : expr1, optRightExpr.getValue(), optBody.getValue());
1865
31
    } else {
1866
0
      node = new (context_) ESTree::ForOfStatementNode(
1867
0
          decl ? decl : expr1,
1868
0
          optRightExpr.getValue(),
1869
0
          optBody.getValue(),
1870
0
          await);
1871
0
    }
1872
31
    return setLocation(startLoc, optBody.getValue(), node);
1873
31
  } else if (checkAndEat(TokenKind::semi)) {
1874
    // Productions valid here:
1875
    //   for ( var/let/const VariableDeclarationList[In] ; Expressionopt ;
1876
    //   Expressionopt )
1877
    //       Statement
1878
    //   for ( Expression[In]opt ; Expressionopt ; Expressionopt ) Statement
1879
1880
1
    if (await)
1881
0
      error(awaitRng, "unexpected 'await' in for loop without 'of'");
1882
1883
1
    if (decl)
1884
0
      ensureDestructuringInitialized(decl);
1885
1886
1
    ESTree::NodePtr test = nullptr;
1887
1
    if (!check(TokenKind::semi)) {
1888
1
      auto optTest = parseExpression();
1889
1
      if (!optTest)
1890
0
        return None;
1891
1
      test = optTest.getValue();
1892
1
    }
1893
1894
1
    if (!eat(
1895
1
            TokenKind::semi,
1896
1
            JSLexer::AllowRegExp,
1897
1
            "after 'for( ... ; ...'",
1898
1
            "location of '('",
1899
1
            lparenLoc))
1900
0
      return None;
1901
1902
1
    ESTree::NodePtr update = nullptr;
1903
1
    if (!check(TokenKind::r_paren)) {
1904
0
      auto optUpdate = parseExpression();
1905
0
      if (!optUpdate)
1906
0
        return None;
1907
0
      update = optUpdate.getValue();
1908
0
    }
1909
1910
1
    if (!eat(
1911
1
            TokenKind::r_paren,
1912
1
            JSLexer::AllowRegExp,
1913
1
            "after 'for( ... ; ... ; ...'",
1914
1
            "location of '('",
1915
1
            lparenLoc))
1916
0
      return None;
1917
1918
1
    auto optBody = parseStatement(param.get(ParamReturn));
1919
1
    if (!optBody)
1920
1
      return None;
1921
1922
0
    return setLocation(
1923
0
        startLoc,
1924
0
        optBody.getValue(),
1925
0
        new (context_) ESTree::ForStatementNode(
1926
0
            decl ? decl : expr1, test, update, optBody.getValue()));
1927
1
  } else {
1928
0
    errorExpected(
1929
0
        TokenKind::semi,
1930
0
        TokenKind::rw_in,
1931
0
        "inside 'for'",
1932
0
        "location of the 'for'",
1933
0
        startLoc);
1934
0
    return None;
1935
0
  }
1936
32
}
1937
1938
Optional<ESTree::ContinueStatementNode *>
1939
0
JSParserImpl::parseContinueStatement() {
1940
0
  assert(check(TokenKind::rw_continue));
1941
0
  SMLoc startLoc = advance().Start;
1942
1943
0
  if (eatSemi(true))
1944
0
    return setLocation(
1945
0
        startLoc,
1946
0
        getPrevTokenEndLoc(),
1947
0
        new (context_) ESTree::ContinueStatementNode(nullptr));
1948
1949
0
  if (!need(
1950
0
          TokenKind::identifier,
1951
0
          "after 'continue'",
1952
0
          "location of 'continue'",
1953
0
          startLoc))
1954
0
    return None;
1955
0
  auto *id = setLocation(
1956
0
      tok_,
1957
0
      tok_,
1958
0
      new (context_)
1959
0
          ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
1960
0
  advance();
1961
1962
0
  if (!eatSemi())
1963
0
    return None;
1964
1965
0
  return setLocation(
1966
0
      startLoc,
1967
0
      getPrevTokenEndLoc(),
1968
0
      new (context_) ESTree::ContinueStatementNode(id));
1969
0
}
1970
1971
1
Optional<ESTree::BreakStatementNode *> JSParserImpl::parseBreakStatement() {
1972
1
  assert(check(TokenKind::rw_break));
1973
1
  SMLoc startLoc = advance().Start;
1974
1975
1
  if (eatSemi(true))
1976
0
    return setLocation(
1977
0
        startLoc,
1978
0
        getPrevTokenEndLoc(),
1979
0
        new (context_) ESTree::BreakStatementNode(nullptr));
1980
1981
1
  if (!need(
1982
1
          TokenKind::identifier,
1983
1
          "after 'break'",
1984
1
          "location of 'break'",
1985
1
          startLoc))
1986
0
    return None;
1987
1
  auto *id = setLocation(
1988
1
      tok_,
1989
1
      tok_,
1990
1
      new (context_)
1991
1
          ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
1992
1
  advance();
1993
1994
1
  if (!eatSemi())
1995
0
    return None;
1996
1997
1
  return setLocation(
1998
1
      startLoc,
1999
1
      getPrevTokenEndLoc(),
2000
1
      new (context_) ESTree::BreakStatementNode(id));
2001
1
}
2002
2003
0
Optional<ESTree::ReturnStatementNode *> JSParserImpl::parseReturnStatement() {
2004
0
  assert(check(TokenKind::rw_return));
2005
0
  SMLoc startLoc = advance().Start;
2006
2007
0
  if (eatSemi(true))
2008
0
    return setLocation(
2009
0
        startLoc,
2010
0
        getPrevTokenEndLoc(),
2011
0
        new (context_) ESTree::ReturnStatementNode(nullptr));
2012
2013
0
  auto optArg = parseExpression();
2014
0
  if (!optArg)
2015
0
    return None;
2016
2017
0
  if (!eatSemi())
2018
0
    return None;
2019
2020
0
  return setLocation(
2021
0
      startLoc,
2022
0
      getPrevTokenEndLoc(),
2023
0
      new (context_) ESTree::ReturnStatementNode(optArg.getValue()));
2024
0
}
2025
2026
Optional<ESTree::WithStatementNode *> JSParserImpl::parseWithStatement(
2027
0
    Param param) {
2028
0
  assert(check(TokenKind::rw_with));
2029
0
  SMLoc startLoc = advance().Start;
2030
2031
0
  SMLoc lparenLoc = tok_->getStartLoc();
2032
0
  if (!eat(
2033
0
          TokenKind::l_paren,
2034
0
          JSLexer::AllowRegExp,
2035
0
          "after 'with'",
2036
0
          "location of 'with'",
2037
0
          startLoc))
2038
0
    return None;
2039
2040
0
  auto optExpr = parseExpression();
2041
0
  if (!optExpr)
2042
0
    return None;
2043
2044
0
  if (!eat(
2045
0
          TokenKind::r_paren,
2046
0
          JSLexer::AllowRegExp,
2047
0
          "after 'with (...'",
2048
0
          "location of '('",
2049
0
          lparenLoc))
2050
0
    return None;
2051
2052
0
  auto optBody = parseStatement(param.get(ParamReturn));
2053
0
  if (!optBody)
2054
0
    return None;
2055
2056
0
  return setLocation(
2057
0
      startLoc,
2058
0
      optBody.getValue(),
2059
0
      new (context_)
2060
0
          ESTree::WithStatementNode(optExpr.getValue(), optBody.getValue()));
2061
0
}
2062
2063
Optional<ESTree::SwitchStatementNode *> JSParserImpl::parseSwitchStatement(
2064
0
    Param param) {
2065
0
  assert(check(TokenKind::rw_switch));
2066
0
  SMLoc startLoc = advance().Start;
2067
2068
0
  SMLoc lparenLoc = tok_->getStartLoc();
2069
0
  if (!eat(
2070
0
          TokenKind::l_paren,
2071
0
          JSLexer::AllowRegExp,
2072
0
          "after 'switch'",
2073
0
          "location of 'switch'",
2074
0
          startLoc))
2075
0
    return None;
2076
2077
0
  auto optDiscriminant = parseExpression();
2078
0
  if (!optDiscriminant)
2079
0
    return None;
2080
2081
0
  if (!eat(
2082
0
          TokenKind::r_paren,
2083
0
          JSLexer::AllowRegExp,
2084
0
          "after 'switch (...'",
2085
0
          "location of '('",
2086
0
          lparenLoc))
2087
0
    return None;
2088
2089
0
  SMLoc lbraceLoc = tok_->getStartLoc();
2090
0
  if (!eat(
2091
0
          TokenKind::l_brace,
2092
0
          JSLexer::AllowRegExp,
2093
0
          "after 'switch (...)'",
2094
0
          "'switch' starts here",
2095
0
          startLoc))
2096
0
    return None;
2097
2098
0
  ESTree::NodeList clauseList;
2099
0
  SMLoc defaultLocation; // location of the 'default' clause
2100
2101
  // Parse the switch body.
2102
0
  while (!check(TokenKind::r_brace)) {
2103
0
    SMLoc clauseStartLoc = tok_->getStartLoc();
2104
2105
0
    ESTree::NodePtr testExpr = nullptr;
2106
0
    bool ignoreClause = false; // Set to true in error recovery when we want to
2107
                               // parse but ignore the parsed statements.
2108
0
    ESTree::NodeList stmtList;
2109
2110
0
    SMLoc caseLoc = tok_->getStartLoc();
2111
0
    if (checkAndEat(TokenKind::rw_case)) {
2112
0
      auto optTestExpr = parseExpression(ParamIn, CoverTypedParameters::No);
2113
0
      if (!optTestExpr)
2114
0
        return None;
2115
0
      testExpr = optTestExpr.getValue();
2116
0
    } else if (checkAndEat(TokenKind::rw_default)) {
2117
0
      if (defaultLocation.isValid()) {
2118
0
        error(clauseStartLoc, "more than one 'default' clause in 'switch'");
2119
0
        sm_.note(defaultLocation, "first 'default' clause was defined here");
2120
2121
        // We want to continue parsing but ignore the statements.
2122
0
        ignoreClause = true;
2123
0
      } else {
2124
0
        defaultLocation = clauseStartLoc;
2125
0
      }
2126
0
    } else {
2127
0
      errorExpected(
2128
0
          TokenKind::rw_case,
2129
0
          TokenKind::rw_default,
2130
0
          "inside 'switch'",
2131
0
          "location of 'switch'",
2132
0
          startLoc);
2133
0
      return None;
2134
0
    }
2135
2136
0
    SMLoc colonLoc =
2137
0
        tok_->getEndLoc(); // save the location in case the clause is empty
2138
0
    if (!eat(
2139
0
            TokenKind::colon,
2140
0
            JSLexer::AllowRegExp,
2141
0
            "after 'case ...' or 'default'",
2142
0
            "location of 'case'/'default'",
2143
0
            caseLoc))
2144
0
      return None;
2145
2146
    /// case Expression : StatementList[opt]
2147
    ///                   ^
2148
0
    if (!parseStatementList(
2149
0
            param.get(ParamReturn),
2150
0
            TokenKind::rw_default,
2151
0
            false,
2152
0
            AllowImportExport::No,
2153
0
            stmtList,
2154
0
            TokenKind::rw_case,
2155
0
            TokenKind::r_brace))
2156
0
      return None;
2157
2158
0
    if (!ignoreClause) {
2159
0
      auto clauseEndLoc =
2160
0
          stmtList.empty() ? colonLoc : stmtList.back().getEndLoc();
2161
0
      clauseList.push_back(*setLocation(
2162
0
          clauseStartLoc,
2163
0
          clauseEndLoc,
2164
0
          new (context_)
2165
0
              ESTree::SwitchCaseNode(testExpr, std::move(stmtList))));
2166
0
    }
2167
0
  }
2168
2169
0
  SMLoc endLoc = tok_->getEndLoc();
2170
0
  if (!eat(
2171
0
          TokenKind::r_brace,
2172
0
          JSLexer::AllowRegExp,
2173
0
          "at end of 'switch' statement",
2174
0
          "location of '{'",
2175
0
          lbraceLoc))
2176
0
    return None;
2177
2178
0
  return setLocation(
2179
0
      startLoc,
2180
0
      endLoc,
2181
0
      new (context_) ESTree::SwitchStatementNode(
2182
0
          optDiscriminant.getValue(), std::move(clauseList)));
2183
0
}
2184
2185
Optional<ESTree::ThrowStatementNode *> JSParserImpl::parseThrowStatement(
2186
0
    Param param) {
2187
0
  assert(check(TokenKind::rw_throw));
2188
0
  SMLoc startLoc = advance().Start;
2189
2190
0
  if (lexer_.isNewLineBeforeCurrentToken()) {
2191
0
    error(tok_->getStartLoc(), "'throw' argument must be on the same line");
2192
0
    sm_.note(startLoc, "location of the 'throw'");
2193
0
    return None;
2194
0
  }
2195
2196
0
  auto optExpr = parseExpression();
2197
0
  if (!optExpr)
2198
0
    return None;
2199
2200
0
  if (!eatSemi())
2201
0
    return None;
2202
2203
0
  return setLocation(
2204
0
      startLoc,
2205
0
      getPrevTokenEndLoc(),
2206
0
      new (context_) ESTree::ThrowStatementNode(optExpr.getValue()));
2207
0
}
2208
2209
Optional<ESTree::TryStatementNode *> JSParserImpl::parseTryStatement(
2210
0
    Param param) {
2211
0
  assert(check(TokenKind::rw_try));
2212
0
  SMLoc startLoc = advance().Start;
2213
2214
0
  if (!need(TokenKind::l_brace, "after 'try'", "location of 'try'", startLoc))
2215
0
    return None;
2216
0
  auto optTryBody = parseBlock(param.get(ParamReturn));
2217
0
  if (!optTryBody)
2218
0
    return None;
2219
2220
0
  ESTree::CatchClauseNode *catchHandler = nullptr;
2221
0
  ESTree::BlockStatementNode *finallyHandler = nullptr;
2222
2223
  // Parse the optional 'catch' handler.
2224
0
  SMLoc handlerStartLoc = tok_->getStartLoc();
2225
0
  if (checkAndEat(TokenKind::rw_catch)) {
2226
0
    ESTree::Node *catchParam = nullptr;
2227
0
    if (checkAndEat(TokenKind::l_paren)) {
2228
      // CatchClause param is optional.
2229
0
      if (check(TokenKind::l_square, TokenKind::l_brace)) {
2230
0
        auto optPattern = parseBindingPattern(Param{});
2231
0
        if (!optPattern)
2232
0
          return None;
2233
0
        catchParam = *optPattern;
2234
0
      } else {
2235
0
        auto optIdent = parseBindingIdentifier(Param{});
2236
0
        if (!optIdent) {
2237
0
          errorExpected(
2238
0
              TokenKind::identifier,
2239
0
              "inside catch list",
2240
0
              "location of 'catch'",
2241
0
              handlerStartLoc);
2242
0
          return None;
2243
0
        }
2244
0
        catchParam = *optIdent;
2245
0
      }
2246
2247
0
      if (!eat(
2248
0
              TokenKind::r_paren,
2249
0
              JSLexer::AllowRegExp,
2250
0
              "after 'catch (...'",
2251
0
              "location of 'catch'",
2252
0
              handlerStartLoc))
2253
0
        return None;
2254
0
    }
2255
2256
0
    if (!need(
2257
0
            TokenKind::l_brace,
2258
0
            "after 'catch(...)'",
2259
0
            "location of 'catch'",
2260
0
            handlerStartLoc))
2261
0
      return None;
2262
0
    auto optCatchBody = parseBlock(param.get(ParamReturn));
2263
0
    if (!optCatchBody)
2264
0
      return None;
2265
2266
0
    catchHandler = setLocation(
2267
0
        handlerStartLoc,
2268
0
        optCatchBody.getValue(),
2269
0
        new (context_)
2270
0
            ESTree::CatchClauseNode(catchParam, optCatchBody.getValue()));
2271
0
  }
2272
2273
  // Parse the optional 'finally' handler.
2274
0
  SMLoc finallyLoc = tok_->getStartLoc();
2275
0
  if (checkAndEat(TokenKind::rw_finally)) {
2276
0
    if (!need(
2277
0
            TokenKind::l_brace,
2278
0
            "after 'finally'",
2279
0
            "location of 'finally'",
2280
0
            finallyLoc))
2281
0
      return None;
2282
0
    auto optFinallyBody = parseBlock(param.get(ParamReturn));
2283
0
    if (!optFinallyBody)
2284
0
      return None;
2285
2286
0
    finallyHandler = optFinallyBody.getValue();
2287
0
  }
2288
2289
  // At least one handler must be present.
2290
0
  if (!catchHandler && !finallyHandler) {
2291
0
    errorExpected(
2292
0
        TokenKind::rw_catch,
2293
0
        TokenKind::rw_finally,
2294
0
        "after 'try' block",
2295
0
        "location of 'try'",
2296
0
        startLoc);
2297
0
    return None;
2298
0
  }
2299
2300
  // Use the last handler's location as the end location.
2301
0
  SMLoc endLoc =
2302
0
      finallyHandler ? finallyHandler->getEndLoc() : catchHandler->getEndLoc();
2303
0
  return setLocation(
2304
0
      startLoc,
2305
0
      endLoc,
2306
0
      new (context_) ESTree::TryStatementNode(
2307
0
          optTryBody.getValue(), catchHandler, finallyHandler));
2308
0
}
2309
2310
Optional<ESTree::DebuggerStatementNode *>
2311
0
JSParserImpl::parseDebuggerStatement() {
2312
0
  assert(check(TokenKind::rw_debugger));
2313
0
  SMRange startLoc = advance();
2314
2315
0
  if (!eatSemi())
2316
0
    return None;
2317
2318
0
  return setLocation(
2319
0
      startLoc,
2320
0
      getPrevTokenEndLoc(),
2321
0
      new (context_) ESTree::DebuggerStatementNode());
2322
0
}
2323
2324
8.90M
Optional<ESTree::Node *> JSParserImpl::parsePrimaryExpression() {
2325
8.90M
  CHECK_RECURSION;
2326
2327
8.90M
  switch (tok_->getKind()) {
2328
4
    case TokenKind::rw_this: {
2329
4
      auto *res =
2330
4
          setLocation(tok_, tok_, new (context_) ESTree::ThisExpressionNode());
2331
4
      advance(JSLexer::AllowDiv);
2332
4
      return res;
2333
0
    }
2334
2335
3.34M
    case TokenKind::identifier: {
2336
3.34M
      if (check(yieldIdent_)) {
2337
        // yield is only allowed as an IdentifierReference when ParamYield is
2338
        // false.
2339
0
        if (paramYield_) {
2340
0
          error(
2341
0
              tok_->getSourceRange(),
2342
0
              "Unexpected usage of 'yield' as an identifier reference");
2343
0
        }
2344
0
      }
2345
3.34M
      if (check(asyncIdent_) && checkAsyncFunction()) {
2346
0
        auto func = parseFunctionExpression();
2347
0
        if (!func)
2348
0
          return None;
2349
0
        return func.getValue();
2350
0
      }
2351
3.34M
#if HERMES_PARSE_FLOW
2352
3.34M
      if (context_.getParseFlow() && context_.getParseFlowMatch() &&
2353
3.34M
          checkMaybeFlowMatch()) {
2354
0
        return parseMatchCallOrMatchExpressionFlow();
2355
0
      }
2356
3.34M
#endif
2357
3.34M
      auto *res = setLocation(
2358
3.34M
          tok_,
2359
3.34M
          tok_,
2360
3.34M
          new (context_)
2361
3.34M
              ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
2362
3.34M
      advance(JSLexer::AllowDiv);
2363
3.34M
      return res;
2364
3.34M
    }
2365
2366
0
    case TokenKind::rw_null: {
2367
0
      auto *res =
2368
0
          setLocation(tok_, tok_, new (context_) ESTree::NullLiteralNode());
2369
0
      advance(JSLexer::AllowDiv);
2370
0
      return res;
2371
3.34M
    }
2372
2373
0
    case TokenKind::rw_true:
2374
0
    case TokenKind::rw_false: {
2375
0
      auto *res = setLocation(
2376
0
          tok_,
2377
0
          tok_,
2378
0
          new (context_) ESTree::BooleanLiteralNode(
2379
0
              tok_->getKind() == TokenKind::rw_true));
2380
0
      advance(JSLexer::AllowDiv);
2381
0
      return res;
2382
0
    }
2383
2384
5.13M
    case TokenKind::numeric_literal: {
2385
5.13M
      auto *res = setLocation(
2386
5.13M
          tok_,
2387
5.13M
          tok_,
2388
5.13M
          new (context_) ESTree::NumericLiteralNode(tok_->getNumericLiteral()));
2389
5.13M
      advance(JSLexer::AllowDiv);
2390
5.13M
      return res;
2391
0
    }
2392
2393
54
    case TokenKind::bigint_literal: {
2394
54
      auto *res = setLocation(
2395
54
          tok_,
2396
54
          tok_,
2397
54
          new (context_) ESTree::BigIntLiteralNode(tok_->getBigIntLiteral()));
2398
54
      advance(JSLexer::AllowDiv);
2399
54
      return res;
2400
0
    }
2401
2402
45
    case TokenKind::string_literal: {
2403
45
      auto *res = setLocation(
2404
45
          tok_,
2405
45
          tok_,
2406
45
          new (context_) ESTree::StringLiteralNode(tok_->getStringLiteral()));
2407
45
      advance(JSLexer::AllowDiv);
2408
45
      return res;
2409
0
    }
2410
2411
240
    case TokenKind::regexp_literal: {
2412
240
      auto *res = setLocation(
2413
240
          tok_,
2414
240
          tok_,
2415
240
          new (context_) ESTree::RegExpLiteralNode(
2416
240
              tok_->getRegExpLiteral()->getBody(),
2417
240
              tok_->getRegExpLiteral()->getFlags()));
2418
240
      advance(JSLexer::AllowDiv);
2419
240
      return res;
2420
0
    }
2421
2422
45.0k
    case TokenKind::l_square: {
2423
45.0k
      auto res = parseArrayLiteral();
2424
45.0k
      if (!res)
2425
12
        return None;
2426
45.0k
      return res.getValue();
2427
45.0k
    }
2428
2429
4
    case TokenKind::l_brace: {
2430
4
      auto res = parseObjectLiteral();
2431
4
      if (!res)
2432
0
        return None;
2433
4
      return res.getValue();
2434
4
    }
2435
2436
1.62k
    case TokenKind::l_paren: {
2437
1.62k
      SMLoc startLoc = advance().Start;
2438
2439
      // Cover "()".
2440
1.62k
      if (check(TokenKind::r_paren)) {
2441
292
        SMLoc endLoc = advance().End;
2442
292
        return setLocation(
2443
292
            startLoc, endLoc, new (context_) ESTree::CoverEmptyArgsNode());
2444
292
      }
2445
2446
1.33k
      ESTree::Node *expr;
2447
1.33k
      if (check(TokenKind::dotdotdot)) {
2448
0
        auto optRest = parseBindingRestElement(ParamIn);
2449
0
        if (!optRest)
2450
0
          return None;
2451
2452
0
        expr = setLocation(
2453
0
            *optRest,
2454
0
            *optRest,
2455
0
            new (context_) ESTree::CoverRestElementNode(*optRest));
2456
1.33k
      } else {
2457
1.33k
        auto optExpr = parseExpression(ParamIn, CoverTypedParameters::Yes);
2458
1.33k
        if (!optExpr)
2459
1.17k
          return None;
2460
163
        expr = *optExpr;
2461
163
      }
2462
2463
163
#if HERMES_PARSE_FLOW
2464
163
      if (context_.getParseFlow()) {
2465
        // In both these cases, we set the location to encompass the `()`.
2466
        // (x: T)
2467
        // ^^^^^^
2468
        // by using `startLoc` and `tok_` as the start/end.
2469
        // If `tok_` is not `)`, then we'll error on the `eat` call immediately
2470
        // after these checks.
2471
0
        if (auto *cover = dyn_cast<ESTree::CoverTypedIdentifierNode>(expr)) {
2472
0
          if (cover->_right && !cover->_optional) {
2473
0
            expr = setLocation(
2474
0
                startLoc,
2475
0
                tok_,
2476
0
                new (context_) ESTree::TypeCastExpressionNode(
2477
0
                    cover->_left, cover->_right));
2478
0
          }
2479
0
        } else if (check(TokenKind::colon)) {
2480
0
          SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
2481
0
          auto optType = parseTypeAnnotationFlow(annotStart);
2482
0
          if (!optType)
2483
0
            return None;
2484
0
          ESTree::Node *type = *optType;
2485
0
          expr = setLocation(
2486
0
              startLoc,
2487
0
              tok_,
2488
0
              new (context_) ESTree::TypeCastExpressionNode(expr, type));
2489
0
        }
2490
0
      }
2491
163
#endif
2492
2493
163
      if (!eat(
2494
163
              TokenKind::r_paren,
2495
163
              JSLexer::AllowDiv,
2496
163
              "at end of parenthesized expression",
2497
163
              "started here",
2498
163
              startLoc))
2499
0
        return None;
2500
      // Record the number of parens surrounding an expression.
2501
163
      expr->incParens();
2502
163
      return expr;
2503
163
    }
2504
2505
168
    case TokenKind::rw_function: {
2506
168
      auto fExpr = parseFunctionExpression();
2507
168
      if (!fExpr)
2508
5
        return None;
2509
163
      return fExpr.getValue();
2510
168
    }
2511
2512
0
    case TokenKind::rw_class: {
2513
0
      auto optClass = parseClassExpression();
2514
0
      if (!optClass)
2515
0
        return None;
2516
0
      return optClass.getValue();
2517
0
    }
2518
2519
382k
    case TokenKind::no_substitution_template:
2520
382k
    case TokenKind::template_head: {
2521
382k
      auto optTemplate = parseTemplateLiteral(Param{});
2522
382k
      if (!optTemplate) {
2523
3
        return None;
2524
3
      }
2525
382k
      return optTemplate.getValue();
2526
382k
    }
2527
2528
0
#if HERMES_PARSE_JSX
2529
0
    case TokenKind::less:
2530
0
      if (context_.getParseJSX()) {
2531
0
        auto optJSX = parseJSX();
2532
0
        if (!optJSX)
2533
0
          return None;
2534
0
        return optJSX.getValue();
2535
0
      }
2536
0
      error(
2537
0
          tok_->getStartLoc(),
2538
0
          "invalid expression (possible JSX: pass -parse-jsx to parse)");
2539
0
      return None;
2540
0
#endif
2541
2542
8
    default:
2543
8
      error(tok_->getStartLoc(), "invalid expression");
2544
8
      return None;
2545
8.90M
  }
2546
8.90M
}
2547
2548
45.0k
Optional<ESTree::ArrayExpressionNode *> JSParserImpl::parseArrayLiteral() {
2549
45.0k
  assert(check(TokenKind::l_square));
2550
45.0k
  SMLoc startLoc = advance().Start;
2551
2552
45.0k
  ESTree::NodeList elemList;
2553
2554
45.0k
  bool trailingComma = false;
2555
2556
45.0k
  if (!check(TokenKind::r_square)) {
2557
2.51M
    for (;;) {
2558
      // Elision.
2559
2.51M
      if (check(TokenKind::comma)) {
2560
82
        elemList.push_back(
2561
82
            *setLocation(tok_, tok_, new (context_) ESTree::EmptyNode()));
2562
2.51M
      } else if (check(TokenKind::dotdotdot)) {
2563
        // Spread.
2564
0
        auto optSpread = parseSpreadElement();
2565
0
        if (!optSpread)
2566
0
          return None;
2567
2568
0
        elemList.push_back(**optSpread);
2569
2.51M
      } else {
2570
2.51M
        auto expr = parseAssignmentExpression();
2571
2.51M
        if (!expr)
2572
2
          return None;
2573
2.51M
        elemList.push_back(*expr.getValue());
2574
2.51M
      }
2575
2576
2.51M
      if (!checkAndEat(TokenKind::comma))
2577
40.6k
        break;
2578
2.47M
      if (check(TokenKind::r_square)) {
2579
        // Check for ",]".
2580
2
        trailingComma = true;
2581
2
        break;
2582
2
      }
2583
2.47M
    }
2584
40.6k
  }
2585
2586
45.0k
  SMLoc endLoc = tok_->getEndLoc();
2587
45.0k
  if (!eat(
2588
45.0k
          TokenKind::r_square,
2589
45.0k
          JSLexer::AllowDiv,
2590
45.0k
          "at end of array literal '[...'",
2591
45.0k
          "location of '['",
2592
45.0k
          startLoc))
2593
10
    return None;
2594
2595
45.0k
  return setLocation(
2596
45.0k
      startLoc,
2597
45.0k
      endLoc,
2598
45.0k
      new (context_)
2599
45.0k
          ESTree::ArrayExpressionNode(std::move(elemList), trailingComma));
2600
45.0k
}
2601
2602
4
Optional<ESTree::ObjectExpressionNode *> JSParserImpl::parseObjectLiteral() {
2603
4
  assert(check(TokenKind::l_brace));
2604
4
  SMLoc startLoc = advance().Start;
2605
2606
4
  ESTree::NodeList elemList;
2607
2608
4
  if (!check(TokenKind::r_brace)) {
2609
2
    for (;;) {
2610
2
      if (check(TokenKind::dotdotdot)) {
2611
        // Spread.
2612
0
        auto optSpread = parseSpreadElement();
2613
0
        if (!optSpread)
2614
0
          return None;
2615
2616
0
        elemList.push_back(**optSpread);
2617
2
      } else {
2618
2
        auto prop = parsePropertyAssignment(false);
2619
2
        if (!prop)
2620
0
          return None;
2621
2622
2
        elemList.push_back(*prop.getValue());
2623
2
      }
2624
2625
2
      if (!checkAndEat(TokenKind::comma))
2626
0
        break;
2627
2
      if (check(TokenKind::r_brace)) // check for ",}"
2628
2
        break;
2629
2
    }
2630
2
  }
2631
2632
4
  SMLoc endLoc = tok_->getEndLoc();
2633
4
  if (!eat(
2634
4
          TokenKind::r_brace,
2635
4
          JSLexer::AllowDiv,
2636
4
          "at end of object literal '{...'",
2637
4
          "location of '{'",
2638
4
          startLoc))
2639
0
    return None;
2640
2641
4
  return setLocation(
2642
4
      startLoc,
2643
4
      endLoc,
2644
4
      new (context_) ESTree::ObjectExpressionNode(std::move(elemList)));
2645
4
}
2646
2647
0
Optional<ESTree::Node *> JSParserImpl::parseSpreadElement() {
2648
0
  assert(check(TokenKind::dotdotdot) && "SpreadElement must start with '...'");
2649
0
  auto spreadStartLoc = advance();
2650
2651
0
  auto optExpr = parseAssignmentExpression();
2652
0
  if (!optExpr)
2653
0
    return None;
2654
2655
0
  return setLocation(
2656
0
      spreadStartLoc,
2657
0
      getPrevTokenEndLoc(),
2658
0
      new (context_) ESTree::SpreadElementNode(*optExpr));
2659
0
}
2660
2661
2
Optional<ESTree::Node *> JSParserImpl::parsePropertyAssignment(bool eagerly) {
2662
2
  SMLoc startLoc = tok_->getStartLoc();
2663
2
  ESTree::NodePtr key = nullptr;
2664
2665
2
  SaveStrictModeAndSeenDirectives saveStrictModeAndSeenDirectives{this};
2666
2667
2
  bool computed = false;
2668
2
  bool generator = false;
2669
2
  bool async = false;
2670
2
  bool method = false;
2671
2672
2
  if (check(getIdent_)) {
2673
0
    UniqueString *ident = tok_->getResWordOrIdentifier();
2674
0
    SMRange identRng = tok_->getSourceRange();
2675
0
    advance();
2676
2677
    // This could either be a getter, or a property named 'get'.
2678
0
    if (check(TokenKind::colon, TokenKind::l_paren)) {
2679
      // This is just a property.
2680
0
      key = setLocation(
2681
0
          identRng,
2682
0
          identRng,
2683
0
          new (context_) ESTree::IdentifierNode(ident, nullptr, false));
2684
0
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
2685
0
    } else if (context_.getParseTypes() && check(TokenKind::less)) {
2686
      // This is a method definition.
2687
0
      method = true;
2688
0
      key = setLocation(
2689
0
          identRng,
2690
0
          identRng,
2691
0
          new (context_) ESTree::IdentifierNode(ident, nullptr, false));
2692
0
#endif
2693
0
    } else if (check(TokenKind::comma, TokenKind::r_brace)) {
2694
      // If the next token is "," or "}", this is a shorthand property
2695
      // definition.
2696
0
      key = setLocation(
2697
0
          identRng,
2698
0
          identRng,
2699
0
          new (context_) ESTree::IdentifierNode(ident, nullptr, false));
2700
0
      auto *value = setLocation(
2701
0
          key,
2702
0
          key,
2703
0
          new (context_) ESTree::IdentifierNode(ident, nullptr, false));
2704
0
      return setLocation(
2705
0
          startLoc,
2706
0
          value,
2707
0
          new (context_)
2708
0
              ESTree::PropertyNode(key, value, initIdent_, false, false, true));
2709
0
    } else {
2710
      // A getter method.
2711
0
      computed = check(TokenKind::l_square);
2712
0
      auto optKey = parsePropertyName();
2713
0
      if (!optKey)
2714
0
        return None;
2715
2716
0
      if (!eat(
2717
0
              TokenKind::l_paren,
2718
0
              JSLexer::AllowRegExp,
2719
0
              "in getter declaration",
2720
0
              "start of getter declaration",
2721
0
              startLoc))
2722
0
        return None;
2723
0
      if (!eat(
2724
0
              TokenKind::r_paren,
2725
0
              JSLexer::AllowRegExp,
2726
0
              "in empty getter parameter list",
2727
0
              "start of getter declaration",
2728
0
              startLoc))
2729
0
        return None;
2730
2731
0
      ESTree::Node *returnType = nullptr;
2732
0
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
2733
0
      if (context_.getParseTypes() && check(TokenKind::colon)) {
2734
0
        SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
2735
0
        auto optRet = parseReturnTypeAnnotation(annotStart);
2736
0
        if (!optRet)
2737
0
          return None;
2738
0
        returnType = *optRet;
2739
0
      }
2740
0
#endif
2741
2742
0
      llvh::SaveAndRestore<bool> oldParamYield(paramYield_, false);
2743
0
      llvh::SaveAndRestore<bool> oldParamAwait(paramAwait_, false);
2744
0
      if (!need(
2745
0
              TokenKind::l_brace,
2746
0
              "in getter declaration",
2747
0
              "start of getter declaration",
2748
0
              startLoc))
2749
0
        return None;
2750
0
      auto block = parseFunctionBody(
2751
0
          ParamReturn,
2752
0
          eagerly,
2753
0
          oldParamYield.get(),
2754
0
          oldParamAwait.get(),
2755
0
          JSLexer::AllowRegExp,
2756
0
          true);
2757
0
      if (!block)
2758
0
        return None;
2759
2760
0
      auto *funcExpr = new (context_) ESTree::FunctionExpressionNode(
2761
0
          nullptr,
2762
0
          ESTree::NodeList{},
2763
0
          block.getValue(),
2764
0
          nullptr,
2765
0
          returnType,
2766
0
          /* predicate */ nullptr,
2767
0
          false,
2768
0
          false);
2769
0
      funcExpr->isMethodDefinition = true;
2770
0
      setLocation(startLoc, block.getValue(), funcExpr);
2771
2772
0
      auto *node = new (context_) ESTree::PropertyNode(
2773
0
          optKey.getValue(), funcExpr, getIdent_, computed, false, false);
2774
0
      return setLocation(startLoc, block.getValue(), node);
2775
0
    }
2776
2
  } else if (check(setIdent_)) {
2777
0
    UniqueString *ident = tok_->getResWordOrIdentifier();
2778
0
    SMRange identRng = tok_->getSourceRange();
2779
0
    advance();
2780
2781
    // This could either be a setter, or a property named 'set'.
2782
0
    if (check(TokenKind::colon, TokenKind::l_paren)) {
2783
      // This is just a property.
2784
0
      key = setLocation(
2785
0
          identRng,
2786
0
          identRng,
2787
0
          new (context_) ESTree::IdentifierNode(ident, nullptr, false));
2788
0
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
2789
0
    } else if (context_.getParseTypes() && check(TokenKind::less)) {
2790
      // This is a method definition.
2791
0
      method = true;
2792
0
      key = setLocation(
2793
0
          identRng,
2794
0
          identRng,
2795
0
          new (context_) ESTree::IdentifierNode(ident, nullptr, false));
2796
0
#endif
2797
0
    } else if (check(TokenKind::comma, TokenKind::r_brace)) {
2798
      // If the next token is "," or "}", this is a shorthand property
2799
      // definition.
2800
0
      key = setLocation(
2801
0
          identRng,
2802
0
          identRng,
2803
0
          new (context_) ESTree::IdentifierNode(ident, nullptr, false));
2804
0
      auto *value = setLocation(
2805
0
          key,
2806
0
          key,
2807
0
          new (context_) ESTree::IdentifierNode(ident, nullptr, false));
2808
0
      return setLocation(
2809
0
          startLoc,
2810
0
          value,
2811
0
          new (context_)
2812
0
              ESTree::PropertyNode(key, value, initIdent_, false, false, true));
2813
0
    } else {
2814
      // A setter method.
2815
0
      computed = check(TokenKind::l_square);
2816
0
      auto optKey = parsePropertyName();
2817
0
      if (!optKey)
2818
0
        return None;
2819
2820
0
      llvh::SaveAndRestore<bool> oldParamYield(paramYield_, false);
2821
0
      llvh::SaveAndRestore<bool> oldParamAwait(paramAwait_, false);
2822
2823
0
      ESTree::NodeList params;
2824
0
      eat(TokenKind::l_paren,
2825
0
          JSLexer::AllowRegExp,
2826
0
          "in setter declaration",
2827
0
          "start of setter declaration",
2828
0
          startLoc);
2829
2830
      // PropertySetParameterList -> FormalParameter -> BindingElement
2831
0
      auto optParam = parseBindingElement(Param{});
2832
0
      if (!optParam)
2833
0
        return None;
2834
0
      params.push_back(**optParam);
2835
2836
0
      if (!eat(
2837
0
              TokenKind::r_paren,
2838
0
              JSLexer::AllowRegExp,
2839
0
              "at end of setter parameter list",
2840
0
              "start of setter declaration",
2841
0
              startLoc))
2842
0
        return None;
2843
2844
0
      ESTree::Node *returnType = nullptr;
2845
0
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
2846
0
      if (context_.getParseTypes() && check(TokenKind::colon)) {
2847
0
        SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
2848
0
        auto optRet = parseReturnTypeAnnotation(annotStart);
2849
0
        if (!optRet)
2850
0
          return None;
2851
0
        returnType = *optRet;
2852
0
      }
2853
0
#endif
2854
2855
0
      if (!need(
2856
0
              TokenKind::l_brace,
2857
0
              "in setter declaration",
2858
0
              "start of setter declaration",
2859
0
              startLoc))
2860
0
        return None;
2861
0
      auto block = parseFunctionBody(
2862
0
          ParamReturn,
2863
0
          eagerly,
2864
0
          oldParamYield.get(),
2865
0
          oldParamAwait.get(),
2866
0
          JSLexer::AllowRegExp,
2867
0
          true);
2868
0
      if (!block)
2869
0
        return None;
2870
2871
0
      auto *funcExpr = new (context_) ESTree::FunctionExpressionNode(
2872
0
          nullptr,
2873
0
          std::move(params),
2874
0
          block.getValue(),
2875
0
          nullptr,
2876
0
          returnType,
2877
0
          /* predicate */ nullptr,
2878
0
          false,
2879
0
          false);
2880
0
      funcExpr->isMethodDefinition = true;
2881
0
      setLocation(startLoc, block.getValue(), funcExpr);
2882
2883
0
      auto *node = new (context_) ESTree::PropertyNode(
2884
0
          optKey.getValue(), funcExpr, setIdent_, computed, false, false);
2885
0
      return setLocation(startLoc, block.getValue(), node);
2886
0
    }
2887
2
  } else if (check(asyncIdent_)) {
2888
0
    UniqueString *ident = tok_->getResWordOrIdentifier();
2889
0
    SMRange identRng = tok_->getSourceRange();
2890
0
    advance();
2891
2892
    // This could either be an async function, or a property named 'async'.
2893
0
    if (check(TokenKind::colon, TokenKind::l_paren)) {
2894
      // This is just a property (or method) called 'async'.
2895
0
      key = setLocation(
2896
0
          identRng,
2897
0
          identRng,
2898
0
          new (context_) ESTree::IdentifierNode(ident, nullptr, false));
2899
0
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
2900
0
    } else if (context_.getParseTypes() && check(TokenKind::less)) {
2901
      // This is a method definition.
2902
0
      method = true;
2903
0
      key = setLocation(
2904
0
          identRng,
2905
0
          identRng,
2906
0
          new (context_) ESTree::IdentifierNode(ident, nullptr, false));
2907
0
#endif
2908
0
    } else if (check(TokenKind::comma, TokenKind::r_brace)) {
2909
      // If the next token is "," or "}", this is a shorthand property
2910
      // definition.
2911
0
      key = setLocation(
2912
0
          identRng,
2913
0
          identRng,
2914
0
          new (context_) ESTree::IdentifierNode(ident, nullptr, false));
2915
0
      auto *value = setLocation(
2916
0
          key,
2917
0
          key,
2918
0
          new (context_) ESTree::IdentifierNode(ident, nullptr, false));
2919
0
      return setLocation(
2920
0
          startLoc,
2921
0
          value,
2922
0
          new (context_)
2923
0
              ESTree::PropertyNode(key, value, initIdent_, false, false, true));
2924
0
    } else {
2925
0
      if (lexer_.isNewLineBeforeCurrentToken()) {
2926
0
        error(
2927
0
            tok_->getSourceRange(),
2928
0
            "newline not allowed after 'async' in a method definition");
2929
0
      }
2930
      // This is an async function, parse the key and set `async` to true.
2931
0
      async = true;
2932
0
      method = true;
2933
0
      generator = checkAndEat(TokenKind::star);
2934
0
      computed = check(TokenKind::l_square);
2935
0
      auto optKey = parsePropertyName();
2936
0
      if (!optKey)
2937
0
        return None;
2938
2939
0
      key = optKey.getValue();
2940
0
    }
2941
2
  } else if (check(TokenKind::identifier)) {
2942
2
    auto *ident = tok_->getIdentifier();
2943
2
    key = setLocation(
2944
2
        tok_,
2945
2
        tok_,
2946
2
        new (context_) ESTree::IdentifierNode(ident, nullptr, false));
2947
2
    advance();
2948
    // If the next token is "," or "}", this is a shorthand property definition.
2949
2
    if (check(TokenKind::comma, TokenKind::r_brace)) {
2950
2
      auto *value = setLocation(
2951
2
          key,
2952
2
          key,
2953
2
          new (context_) ESTree::IdentifierNode(ident, nullptr, false));
2954
2955
2
      return setLocation(
2956
2
          startLoc,
2957
2
          value,
2958
2
          new (context_)
2959
2
              ESTree::PropertyNode(key, value, initIdent_, false, false, true));
2960
2
    }
2961
2
  } else {
2962
0
    generator = checkAndEat(TokenKind::star);
2963
0
    computed = check(TokenKind::l_square);
2964
0
    auto optKey = parsePropertyName();
2965
0
    if (!optKey)
2966
0
      return None;
2967
2968
0
    key = optKey.getValue();
2969
0
  }
2970
2971
0
  ESTree::Node *value;
2972
0
  bool shorthand = false;
2973
2974
0
  if (isa<ESTree::IdentifierNode>(key) && check(TokenKind::equal)) {
2975
    // Check for CoverInitializedName: IdentifierReference Initializer
2976
0
    auto startLoc = advance().Start;
2977
0
    auto optInit = parseAssignmentExpression();
2978
0
    if (!optInit)
2979
0
      return None;
2980
2981
0
    shorthand = true;
2982
2983
0
    value = setLocation(
2984
0
        startLoc,
2985
0
        getPrevTokenEndLoc(),
2986
0
        new (context_) ESTree::CoverInitializerNode(*optInit));
2987
0
  } else if (check(TokenKind::l_paren, TokenKind::less) || async) {
2988
    // Try this branch when we have '(' or '<' to indicate a method
2989
    // or when we know this is async, because async must also indicate a method,
2990
    // and we must avoid parsing ordinary properties from ':'.
2991
2992
    // Parse the MethodDefinition manually here.
2993
    // Do not use `parseClassElement` because we had to parsePropertyName
2994
    // in this function ourselves and check for SingleNameBindings, which are
2995
    // not parsed with `parsePropertyName`.
2996
    // MethodDefinition:
2997
    // PropertyName "(" UniqueFormalParameters ")" "{" FunctionBody "}"
2998
    //               ^
2999
0
    llvh::SaveAndRestore<bool> oldParamYield(paramYield_, generator);
3000
0
    llvh::SaveAndRestore<bool> oldParamAwait(paramAwait_, async);
3001
3002
0
    method = true;
3003
3004
0
    ESTree::Node *typeParams = nullptr;
3005
0
#if HERMES_PARSE_FLOW
3006
0
    if (context_.getParseFlow() && check(TokenKind::less)) {
3007
0
      auto optTypeParams = parseTypeParamsFlow();
3008
0
      if (!optTypeParams)
3009
0
        return None;
3010
0
      typeParams = *optTypeParams;
3011
0
    }
3012
0
#endif
3013
0
#if HERMES_PARSE_TS
3014
0
    if (context_.getParseTS() && check(TokenKind::less)) {
3015
0
      auto optTypeParams = parseTSTypeParameters();
3016
0
      if (!optTypeParams)
3017
0
        return None;
3018
0
      typeParams = *optTypeParams;
3019
0
    }
3020
0
#endif
3021
3022
    // (
3023
0
    if (!need(
3024
0
            TokenKind::l_paren,
3025
0
            "in method definition",
3026
0
            "start of method definition",
3027
0
            startLoc))
3028
0
      return None;
3029
3030
0
    ESTree::NodeList args{};
3031
0
    if (!parseFormalParameters(Param{}, args))
3032
0
      return None;
3033
3034
0
    ESTree::Node *returnType = nullptr;
3035
0
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
3036
0
    if (context_.getParseTypes() && check(TokenKind::colon)) {
3037
0
      SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
3038
0
      auto optRet = parseReturnTypeAnnotation(annotStart);
3039
0
      if (!optRet)
3040
0
        return None;
3041
0
      returnType = *optRet;
3042
0
    }
3043
0
#endif
3044
3045
0
    if (!need(
3046
0
            TokenKind::l_brace,
3047
0
            "in method definition",
3048
0
            "start of method definition",
3049
0
            startLoc))
3050
0
      return None;
3051
0
    auto optBody = parseFunctionBody(
3052
0
        ParamReturn,
3053
0
        eagerly,
3054
0
        oldParamYield.get(),
3055
0
        oldParamAwait.get(),
3056
0
        JSLexer::AllowRegExp,
3057
0
        true);
3058
0
    if (!optBody)
3059
0
      return None;
3060
3061
0
    auto *funcExpr = new (context_) ESTree::FunctionExpressionNode(
3062
0
        nullptr,
3063
0
        std::move(args),
3064
0
        optBody.getValue(),
3065
0
        typeParams,
3066
0
        returnType,
3067
0
        /* predicate */ nullptr,
3068
0
        generator,
3069
0
        async);
3070
0
    funcExpr->isMethodDefinition = true;
3071
0
    setLocation(startLoc, optBody.getValue(), funcExpr);
3072
3073
0
    value = funcExpr;
3074
0
  } else {
3075
0
    if (!eat(
3076
0
            TokenKind::colon,
3077
0
            JSLexer::AllowRegExp,
3078
0
            "in property initialization",
3079
0
            "start of property initialization",
3080
0
            startLoc))
3081
0
      return None;
3082
3083
0
    auto optValue = parseAssignmentExpression();
3084
0
    if (!optValue)
3085
0
      return None;
3086
0
    value = *optValue;
3087
0
  }
3088
3089
0
  return setLocation(
3090
0
      startLoc,
3091
0
      getPrevTokenEndLoc(),
3092
0
      new (context_) ESTree::PropertyNode(
3093
0
          key, value, initIdent_, computed, method, shorthand));
3094
0
}
3095
3096
0
Optional<ESTree::Node *> JSParserImpl::parsePropertyName() {
3097
0
  switch (tok_->getKind()) {
3098
0
    case TokenKind::string_literal: {
3099
0
      auto *res = setLocation(
3100
0
          tok_,
3101
0
          tok_,
3102
0
          new (context_) ESTree::StringLiteralNode(tok_->getStringLiteral()));
3103
0
      advance();
3104
0
      return res;
3105
0
    }
3106
3107
0
    case TokenKind::numeric_literal: {
3108
0
      auto *res = setLocation(
3109
0
          tok_,
3110
0
          tok_,
3111
0
          new (context_) ESTree::NumericLiteralNode(tok_->getNumericLiteral()));
3112
0
      advance();
3113
0
      return res;
3114
0
    }
3115
3116
0
    case TokenKind::identifier: {
3117
0
      auto *res = setLocation(
3118
0
          tok_,
3119
0
          tok_,
3120
0
          new (context_)
3121
0
              ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
3122
0
      advance();
3123
0
      return res;
3124
0
    }
3125
3126
0
    case TokenKind::l_square: {
3127
0
      SMLoc start = advance().Start;
3128
0
      auto optExpr = parseAssignmentExpression(ParamIn);
3129
0
      if (!optExpr) {
3130
0
        return None;
3131
0
      }
3132
0
      if (!need(
3133
0
              TokenKind::r_square,
3134
0
              "at end of computed property key",
3135
0
              "start of property key",
3136
0
              start)) {
3137
0
        return llvh::None;
3138
0
      }
3139
0
      advance();
3140
0
      return *optExpr;
3141
0
    }
3142
3143
0
    default:
3144
0
      if (tok_->isResWord()) {
3145
0
        auto *res = setLocation(
3146
0
            tok_,
3147
0
            tok_,
3148
0
            new (context_) ESTree::IdentifierNode(
3149
0
                tok_->getResWordIdentifier(), nullptr, false));
3150
0
        advance();
3151
0
        return res;
3152
0
      } else {
3153
0
        error(
3154
0
            tok_->getSourceRange(),
3155
0
            "invalid property name - must be a string, number or identifier");
3156
0
        return None;
3157
0
      }
3158
0
  }
3159
0
}
3160
3161
388k
Optional<ESTree::Node *> JSParserImpl::parseTemplateLiteral(Param param) {
3162
388k
  assert(checkTemplateLiteral() && "invalid template literal start");
3163
3164
388k
  SMLoc start = tok_->getStartLoc();
3165
3166
388k
  ESTree::NodeList quasis;
3167
388k
  ESTree::NodeList expressions;
3168
3169
  /// Push the current TemplateElement onto quasis and advance the lexer.
3170
  /// \param tail true if pushing the last element.
3171
  /// \return false on failure.
3172
1.09M
  auto pushTemplateElement = [&quasis, &param, this](bool tail) -> bool {
3173
1.09M
    if (tok_->getTemplateLiteralContainsNotEscapes() &&
3174
1.09M
        !param.has(ParamTagged)) {
3175
0
      error(
3176
0
          tok_->getSourceRange(),
3177
0
          "untagged template literal contains invalid escape sequence");
3178
0
      return false;
3179
0
    }
3180
1.09M
    auto *quasi = setLocation(
3181
1.09M
        tok_,
3182
1.09M
        tok_,
3183
1.09M
        new (context_) ESTree::TemplateElementNode(
3184
1.09M
            tail, tok_->getTemplateValue(), tok_->getTemplateRawValue()));
3185
1.09M
    quasis.push_back(*quasi);
3186
1.09M
    return true;
3187
1.09M
  };
3188
3189
  // TemplateSpans
3190
388k
  while (
3191
1.09M
      !check(TokenKind::no_substitution_template, TokenKind::template_tail)) {
3192
    // TemplateSpans
3193
    // Alternate TemplateMiddle and Expression until TemplateTail.
3194
703k
    if (!check(TokenKind::template_head, TokenKind::template_middle)) {
3195
0
      error(tok_->getSourceRange(), "expected template literal");
3196
0
      return None;
3197
0
    }
3198
3199
    // First, push the TemplateElement.
3200
703k
    if (!pushTemplateElement(false))
3201
0
      return None;
3202
703k
    SMLoc subStart = advance().Start;
3203
3204
    // Parse the next expression and add it to the expressions.
3205
703k
    auto optExpr = parseExpression(ParamIn);
3206
703k
    if (!optExpr)
3207
3
      return None;
3208
703k
    expressions.push_back(*optExpr.getValue());
3209
3210
703k
    if (!check(TokenKind::r_brace)) {
3211
0
      errorExpected(
3212
0
          TokenKind::r_brace,
3213
0
          "at end of substition in template literal",
3214
0
          "start of substitution",
3215
0
          subStart);
3216
0
      return None;
3217
0
    }
3218
3219
    // The } at the end of the expression must be rescanned as a
3220
    // TemplateMiddle or TemplateTail.
3221
703k
    lexer_.rescanRBraceInTemplateLiteral();
3222
703k
  }
3223
3224
  // TemplateTail or NoSubstitutionTemplate
3225
388k
  if (!pushTemplateElement(true))
3226
0
    return None;
3227
3228
388k
  return setLocation(
3229
388k
      start,
3230
388k
      advance().End,
3231
388k
      new (context_) ESTree::TemplateLiteralNode(
3232
388k
          std::move(quasis), std::move(expressions)));
3233
388k
}
3234
3235
Optional<ESTree::FunctionExpressionNode *>
3236
168
JSParserImpl::parseFunctionExpression(bool forceEagerly) {
3237
168
  auto optRes = parseFunctionHelper(Param{}, false, forceEagerly);
3238
168
  if (!optRes)
3239
5
    return None;
3240
163
  return cast<ESTree::FunctionExpressionNode>(*optRes);
3241
168
}
3242
3243
Optional<ESTree::Node *> JSParserImpl::parseOptionalExpressionExceptNew(
3244
8.90M
    IsConstructorCall isConstructorCall) {
3245
8.90M
  SMLoc startLoc = tok_->getStartLoc();
3246
3247
8.90M
  ESTree::NodePtr expr;
3248
8.90M
  if (check(TokenKind::rw_super)) {
3249
    // SuperProperty can be used the same way as PrimaryExpression, but
3250
    // must not have a TemplateLiteral immediately after the `super` keyword.
3251
0
    expr = setLocation(tok_, tok_, new (context_) ESTree::SuperNode());
3252
0
    advance();
3253
0
    if (!checkN(TokenKind::l_paren, TokenKind::l_square, TokenKind::period)) {
3254
0
      errorExpected(
3255
0
          {TokenKind::l_paren, TokenKind::l_square, TokenKind::period},
3256
0
          "after 'super' keyword",
3257
0
          "location of 'super'",
3258
0
          startLoc);
3259
0
      return None;
3260
0
    }
3261
8.90M
  } else if (check(TokenKind::rw_import)) {
3262
0
    SMRange importRange = advance();
3263
0
    if (checkAndEat(TokenKind::period)) {
3264
      // ImportMeta: import . meta
3265
      //                      ^
3266
0
      if (!check(metaIdent_)) {
3267
0
        error(tok_->getSourceRange(), "'meta' expected in member expression");
3268
0
        sm_.note(
3269
0
            importRange.Start, "start of member expression", Subsystem::Parser);
3270
0
        return None;
3271
0
      }
3272
0
      auto *meta = setLocation(
3273
0
          importRange,
3274
0
          importRange,
3275
0
          new (context_) ESTree::IdentifierNode(importIdent_, nullptr, false));
3276
0
      auto *prop = setLocation(
3277
0
          tok_,
3278
0
          tok_,
3279
0
          new (context_) ESTree::IdentifierNode(metaIdent_, nullptr, false));
3280
0
      advance();
3281
0
      expr = setLocation(
3282
0
          meta,
3283
0
          getPrevTokenEndLoc(),
3284
0
          new (context_) ESTree::MetaPropertyNode(meta, prop));
3285
0
    } else {
3286
      // Guard against parseAssignmentExpression without parsePrimaryExpression.
3287
0
      CHECK_RECURSION;
3288
3289
      // ImportCall must be a call with an AssignmentExpression as the
3290
      // argument.
3291
0
      if (!eat(
3292
0
              TokenKind::l_paren,
3293
0
              JSLexer::AllowRegExp,
3294
0
              "in import call",
3295
0
              "location of 'import'",
3296
0
              startLoc))
3297
0
        return None;
3298
3299
0
      auto optSource = parseAssignmentExpression(ParamIn);
3300
0
      if (!optSource)
3301
0
        return None;
3302
0
      ESTree::Node *source = *optSource;
3303
3304
0
      checkAndEat(TokenKind::comma);
3305
3306
0
      ESTree::Node *attributes = nullptr;
3307
0
      if (!check(TokenKind::r_paren)) {
3308
0
        auto optAttributes = parseAssignmentExpression();
3309
0
        if (!optAttributes)
3310
0
          return None;
3311
0
        attributes = *optAttributes;
3312
0
        checkAndEat(TokenKind::comma);
3313
0
      }
3314
3315
0
      SMLoc endLoc = tok_->getEndLoc();
3316
0
      if (!eat(
3317
0
              TokenKind::r_paren,
3318
0
              JSLexer::AllowRegExp,
3319
0
              "in import call",
3320
0
              "location of 'import'",
3321
0
              startLoc))
3322
0
        return None;
3323
3324
0
      expr = setLocation(
3325
0
          startLoc,
3326
0
          endLoc,
3327
0
          new (context_) ESTree::ImportExpressionNode(source, attributes));
3328
0
    }
3329
8.90M
  } else {
3330
8.90M
    auto primExpr = parsePrimaryExpression();
3331
8.90M
    if (!primExpr)
3332
1.20k
      return None;
3333
8.90M
    expr = primExpr.getValue();
3334
8.90M
  }
3335
3336
8.90M
  return parseOptionalExpressionExceptNew_tail(
3337
8.90M
      isConstructorCall, startLoc, expr);
3338
8.90M
}
3339
3340
Optional<ESTree::Node *> JSParserImpl::parseOptionalExpressionExceptNew_tail(
3341
    IsConstructorCall isConstructorCall,
3342
    SMLoc startLoc,
3343
8.90M
    ESTree::Node *expr) {
3344
8.90M
  SMLoc objectLoc = startLoc;
3345
8.90M
  bool seenOptionalChain = false;
3346
8.90M
  llvh::SaveAndRestore<unsigned> savedRecursionDepth{
3347
8.90M
      recursionDepth_, recursionDepth_};
3348
8.90M
  while (
3349
9.00M
      checkN(TokenKind::l_square, TokenKind::period, TokenKind::questiondot) ||
3350
9.00M
      checkTemplateLiteral()) {
3351
92.7k
    ++recursionDepth_;
3352
92.7k
    if (LLVM_UNLIKELY(recursionDepthCheck())) {
3353
0
      return None;
3354
0
    }
3355
92.7k
    SMLoc nextObjectLoc = tok_->getStartLoc();
3356
92.7k
    if (checkN(
3357
92.7k
            TokenKind::l_square, TokenKind::period, TokenKind::questiondot)) {
3358
87.0k
      if (check(TokenKind::questiondot)) {
3359
1.91k
        seenOptionalChain = true;
3360
1.91k
        if (isConstructorCall == IsConstructorCall::Yes) {
3361
          // Report the error here, but continue on because we can still parse
3362
          // the rest of the file.
3363
0
          error(
3364
0
              tok_->getSourceRange(),
3365
0
              "Constructor calls may not contain an optional chain");
3366
0
        }
3367
1.91k
      }
3368
      // MemberExpression [ Expression ]
3369
      // MemberExpression . IdentifierName
3370
      // MemberExpression OptionalChain
3371
87.0k
      auto msel =
3372
87.0k
          parseMemberSelect(startLoc, objectLoc, expr, seenOptionalChain);
3373
87.0k
      if (!msel)
3374
1
        return None;
3375
87.0k
      objectLoc = nextObjectLoc;
3376
87.0k
      expr = msel.getValue();
3377
87.0k
    } else {
3378
5.70k
      assert(checkTemplateLiteral());
3379
5.70k
      if (isa<ESTree::SuperNode>(expr)) {
3380
0
        error(
3381
0
            expr->getSourceRange(),
3382
0
            "invalid use of 'super' as a template literal tag");
3383
0
        return None;
3384
0
      }
3385
5.70k
      if (seenOptionalChain) {
3386
        // This construction is allowed by the grammar but accounted for by
3387
        // static semantics in order to prevent ASI from being used like this:
3388
        // \code
3389
        // a?.b
3390
        // `abc`;
3391
        // \endcode
3392
0
        error(
3393
0
            tok_->getSourceRange(),
3394
0
            "invalid use of tagged template literal in optional chain");
3395
0
        sm_.note(expr->getSourceRange(), "location of optional chain");
3396
0
      }
3397
      // MemberExpression TemplateLiteral
3398
5.70k
      auto optTemplate = parseTemplateLiteral(ParamTagged);
3399
5.70k
      if (!optTemplate)
3400
0
        return None;
3401
5.70k
      expr = setLocation(
3402
5.70k
          startLoc,
3403
5.70k
          optTemplate.getValue(),
3404
5.70k
          new (context_) ESTree::TaggedTemplateExpressionNode(
3405
5.70k
              expr, optTemplate.getValue()));
3406
5.70k
      objectLoc = nextObjectLoc;
3407
5.70k
    }
3408
92.7k
  }
3409
3410
8.90M
  return expr;
3411
8.90M
}
3412
3413
Optional<const char *> JSParserImpl::parseArguments(
3414
    ESTree::NodeList &argList,
3415
2.96k
    SMLoc &endLoc) {
3416
2.96k
  assert(check(TokenKind::l_paren));
3417
2.96k
  SMLoc startLoc = advance().Start;
3418
2.96k
  if (!check(TokenKind::r_paren)) {
3419
880
    for (;;) {
3420
880
      SMLoc argStart = tok_->getStartLoc();
3421
880
      bool isSpread = checkAndEat(TokenKind::dotdotdot);
3422
3423
880
      auto arg = parseAssignmentExpression();
3424
880
      if (!arg)
3425
876
        return None;
3426
3427
4
      if (isSpread) {
3428
0
        argList.push_back(*setLocation(
3429
0
            argStart,
3430
0
            getPrevTokenEndLoc(),
3431
0
            new (context_) ESTree::SpreadElementNode(arg.getValue())));
3432
4
      } else {
3433
4
        argList.push_back(*arg.getValue());
3434
4
      }
3435
3436
4
      if (!checkAndEat(TokenKind::comma))
3437
4
        break;
3438
3439
      // Check for ",)".
3440
0
      if (check(TokenKind::r_paren))
3441
0
        break;
3442
0
    }
3443
880
  }
3444
2.08k
  endLoc = tok_->getEndLoc();
3445
2.08k
  if (!eat(
3446
2.08k
          TokenKind::r_paren,
3447
2.08k
          JSLexer::AllowDiv,
3448
2.08k
          "at end of function call",
3449
2.08k
          "location of '('",
3450
2.08k
          startLoc))
3451
0
    return None;
3452
3453
2.08k
  return "OK";
3454
2.08k
}
3455
3456
Optional<ESTree::Node *> JSParserImpl::parseMemberSelect(
3457
    SMLoc startLoc,
3458
    SMLoc objectLoc,
3459
    ESTree::NodePtr expr,
3460
89.2k
    bool seenOptionalChain) {
3461
89.2k
  assert(
3462
89.2k
      checkN(TokenKind::l_square, TokenKind::period, TokenKind::questiondot));
3463
89.2k
  SMLoc puncLoc = tok_->getStartLoc();
3464
89.2k
  bool optional = checkAndEat(TokenKind::questiondot);
3465
89.2k
  if (checkAndEat(TokenKind::l_square)) {
3466
    // Parsing another Expression directly without going through
3467
    // PrimaryExpression. This can overflow, so check.
3468
2.18k
    CHECK_RECURSION;
3469
2.18k
    auto propExpr = parseExpression();
3470
2.18k
    if (!propExpr)
3471
2.04k
      return None;
3472
143
    SMLoc endLoc = tok_->getEndLoc();
3473
143
    if (!eat(
3474
143
            TokenKind::r_square,
3475
143
            JSLexer::AllowDiv,
3476
143
            "at end of member expression '[...'",
3477
143
            "location iof '['",
3478
143
            puncLoc))
3479
0
      return None;
3480
3481
143
    if (optional || seenOptionalChain) {
3482
0
      return setLocation(
3483
0
          startLoc,
3484
0
          endLoc,
3485
0
          puncLoc,
3486
0
          new (context_) ESTree::OptionalMemberExpressionNode(
3487
0
              expr, propExpr.getValue(), true, optional));
3488
0
    }
3489
143
    return setLocation(
3490
143
        startLoc,
3491
143
        endLoc,
3492
143
        puncLoc,
3493
143
        new (context_)
3494
143
            ESTree::MemberExpressionNode(expr, propExpr.getValue(), true));
3495
87.0k
  } else if (
3496
87.0k
      checkAndEat(TokenKind::period) ||
3497
87.0k
      (optional &&
3498
1.96k
       !(check(TokenKind::l_paren) ||
3499
87.0k
         (context_.getParseFlow() && check(TokenKind::less))))) {
3500
87.0k
    if (!check(TokenKind::identifier, TokenKind::private_identifier) &&
3501
87.0k
        !tok_->isResWord()) {
3502
      // Just use the pattern here, even though we know it will fail.
3503
0
      if (!need(
3504
0
              TokenKind::identifier,
3505
0
              "after '.' or '?.' in member expression",
3506
0
              "start of member expression",
3507
0
              objectLoc))
3508
0
        return None;
3509
0
    }
3510
3511
87.0k
    ESTree::Node *id = nullptr;
3512
87.0k
    if (check(TokenKind::private_identifier)) {
3513
0
      auto optId = parsePrivateName();
3514
0
      if (!optId)
3515
0
        return None;
3516
0
      id = *optId;
3517
87.0k
    } else {
3518
87.0k
      id = setLocation(
3519
87.0k
          tok_,
3520
87.0k
          tok_,
3521
87.0k
          new (context_) ESTree::IdentifierNode(
3522
87.0k
              tok_->getResWordOrIdentifier(), nullptr, false));
3523
87.0k
      advance(JSLexer::AllowDiv);
3524
87.0k
    }
3525
3526
87.0k
    if (optional || seenOptionalChain) {
3527
51.9k
      return setLocation(
3528
51.9k
          startLoc,
3529
51.9k
          id,
3530
51.9k
          puncLoc,
3531
51.9k
          new (context_)
3532
51.9k
              ESTree::OptionalMemberExpressionNode(expr, id, false, optional));
3533
51.9k
    }
3534
35.0k
    return setLocation(
3535
35.0k
        startLoc,
3536
35.0k
        id,
3537
35.0k
        puncLoc,
3538
35.0k
        new (context_) ESTree::MemberExpressionNode(expr, id, false));
3539
87.0k
  } else {
3540
0
    assert(
3541
0
        optional &&
3542
0
        (check(TokenKind::l_paren) ||
3543
0
         (context_.getParseFlow() && check(TokenKind::less))) &&
3544
0
        "must be ?.() at this point");
3545
    // ?. Arguments :
3546
    // ?. ( ArgumentList )
3547
    //      ^
3548
0
    auto debugLoc = tok_->getStartLoc();
3549
3550
0
    ESTree::NodePtr typeArgs = nullptr;
3551
0
#if HERMES_PARSE_FLOW
3552
0
    if (context_.getParseFlow() && check(TokenKind::less)) {
3553
0
      auto optTypeArgs = parseTypeArgsFlow();
3554
0
      if (!optTypeArgs) {
3555
0
        return None;
3556
0
      }
3557
3558
0
      typeArgs = *optTypeArgs;
3559
3560
0
      if (!need(
3561
0
              TokenKind::l_paren,
3562
0
              "after type arguments in optional call",
3563
0
              "start of optional call",
3564
0
              objectLoc))
3565
0
        return None;
3566
0
    }
3567
0
#endif
3568
0
#if HERMES_PARSE_TS
3569
0
    if (context_.getParseTS() && check(TokenKind::less)) {
3570
0
      auto optTypeArgs = parseTSTypeArguments();
3571
0
      if (!optTypeArgs) {
3572
0
        return None;
3573
0
      }
3574
3575
0
      typeArgs = *optTypeArgs;
3576
3577
0
      if (!need(
3578
0
              TokenKind::l_paren,
3579
0
              "after type arguments in optional call",
3580
0
              "start of optional call",
3581
0
              objectLoc))
3582
0
        return None;
3583
0
    }
3584
0
#endif
3585
3586
0
    ESTree::NodeList argList;
3587
0
    SMLoc endLoc;
3588
0
    if (!parseArguments(argList, endLoc))
3589
0
      return None;
3590
3591
0
    return setLocation(
3592
0
        startLoc,
3593
0
        endLoc,
3594
0
        debugLoc,
3595
0
        new (context_) ESTree::OptionalCallExpressionNode(
3596
0
            expr, typeArgs, std::move(argList), true));
3597
0
  }
3598
3599
89.2k
  llvm_unreachable("Invalid token in parseMemberSelect");
3600
89.2k
}
3601
3602
Optional<ESTree::Node *> JSParserImpl::parseCallExpression(
3603
    SMLoc startLoc,
3604
    ESTree::NodePtr expr,
3605
    ESTree::NodePtr typeArgs,
3606
    bool seenOptionalChain,
3607
2.95k
    bool optional) {
3608
2.95k
  assert(checkN(
3609
2.95k
      TokenKind::l_paren,
3610
2.95k
      TokenKind::no_substitution_template,
3611
2.95k
      TokenKind::template_head));
3612
3613
2.95k
  SMLoc objectLoc = startLoc;
3614
3615
5.22k
  for (;;) {
3616
5.22k
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
3617
5.22k
    if ((context_.getParseFlowAmbiguous() || context_.getParseTS()) &&
3618
5.22k
        !typeArgs && check(TokenKind::less)) {
3619
0
      JSLexer::SavePoint savePoint{&lexer_};
3620
      // Each call in a chain may have type arguments.
3621
      // As such, we must attempt to parse them upon encountering '<',
3622
      // but roll back if it just ended up being a comparison operator.
3623
0
      SourceErrorManager::SaveAndSuppressMessages suppress{
3624
0
          &sm_, Subsystem::Parser};
3625
0
      auto optTypeArgs =
3626
0
          context_.getParseTS() ? parseTSTypeArguments() : parseTypeArgsFlow();
3627
0
      if (optTypeArgs && check(TokenKind::l_paren)) {
3628
        // Call expression with type arguments.
3629
0
        typeArgs = *optTypeArgs;
3630
0
      } else {
3631
        // Failed to parse a call expression with type arguments,
3632
        // simply roll back and start again.
3633
0
        savePoint.restore();
3634
0
      }
3635
0
    }
3636
5.22k
#endif
3637
5.22k
    if (check(TokenKind::l_paren)) {
3638
2.96k
      auto debugLoc = tok_->getStartLoc();
3639
2.96k
      ESTree::NodeList argList;
3640
2.96k
      SMLoc endLoc;
3641
3642
      // parseArguments can result in another call to parseCallExpression
3643
      // without parsing another primary or declaration.
3644
2.96k
      CHECK_RECURSION;
3645
2.96k
      if (!parseArguments(argList, endLoc))
3646
876
        return None;
3647
3648
2.08k
      if (seenOptionalChain) {
3649
38
        expr = setLocation(
3650
38
            startLoc,
3651
38
            endLoc,
3652
38
            debugLoc,
3653
38
            new (context_) ESTree::OptionalCallExpressionNode(
3654
38
                expr, typeArgs, std::move(argList), optional));
3655
2.04k
      } else {
3656
2.04k
        expr = setLocation(
3657
2.04k
            startLoc,
3658
2.04k
            endLoc,
3659
2.04k
            debugLoc,
3660
2.04k
            new (context_)
3661
2.04k
                ESTree::CallExpressionNode(expr, typeArgs, std::move(argList)));
3662
2.04k
      }
3663
3664
      // typeArgs have been used, discard them so the next item in the call
3665
      // chain can populate them if necessary.
3666
2.08k
      typeArgs = nullptr;
3667
2.26k
    } else if (checkN(
3668
2.26k
                   TokenKind::l_square,
3669
2.26k
                   TokenKind::period,
3670
2.26k
                   TokenKind::questiondot)) {
3671
2.21k
      if (check(TokenKind::questiondot)) {
3672
47
        seenOptionalChain = true;
3673
47
      }
3674
3675
2.21k
      SMLoc nextObjectLoc = tok_->getStartLoc();
3676
2.21k
      auto msel =
3677
2.21k
          parseMemberSelect(startLoc, objectLoc, expr, seenOptionalChain);
3678
2.21k
      if (!msel)
3679
2.04k
        return None;
3680
171
      objectLoc = nextObjectLoc;
3681
171
      expr = msel.getValue();
3682
171
    } else if (check(
3683
48
                   TokenKind::no_substitution_template,
3684
48
                   TokenKind::template_head)) {
3685
14
      auto debugLoc = tok_->getStartLoc();
3686
14
      auto optTemplate = parseTemplateLiteral(ParamTagged);
3687
14
      if (!optTemplate)
3688
0
        return None;
3689
14
      expr = setLocation(
3690
14
          startLoc,
3691
14
          optTemplate.getValue(),
3692
14
          debugLoc,
3693
14
          new (context_) ESTree::TaggedTemplateExpressionNode(
3694
14
              expr, optTemplate.getValue()));
3695
34
    } else {
3696
34
      break;
3697
34
    }
3698
5.22k
  }
3699
3700
34
  return expr;
3701
2.95k
}
3702
3703
//  Parsing NewExpression, MemberExpression and CallExpression is tricky.
3704
//
3705
//  The key realizations are that NewExpression can be one or more
3706
//  constructor calls without arguments (the s-expressions below represent
3707
//  productions that have been recursively matched, not AST nodes):
3708
//
3709
//       new foo ->
3710
//           (NewExpression (MemberExpression))
3711
//       new new foo ->
3712
//           (NewExpression (NewExpression (MemberExpression)))
3713
//
3714
//  MemberExpression can be one or more constructor calls with arguments:
3715
//
3716
//       new foo() ->
3717
//           (MemberExpression (MemberExpression))
3718
//       new new foo()()
3719
//           (MemberExpression (MemberExpression (MemberExpression))
3720
//
3721
//  Call expression are formed from arguments that don't match up with a `new`:
3722
//
3723
//       foo() ->
3724
//           (CallExpression (MemberExpression))
3725
//       new foo()()
3726
//           (CallExpression (MemberExpression (MemberExpression)))
3727
3728
Optional<ESTree::Node *> JSParserImpl::parseNewExpressionOrOptionalExpression(
3729
8.96M
    IsConstructorCall isConstructorCall) {
3730
8.96M
  if (!check(TokenKind::rw_new))
3731
8.90M
    return parseOptionalExpressionExceptNew(isConstructorCall);
3732
3733
50.6k
  SMRange newRange = advance();
3734
3735
50.6k
  if (checkAndEat(TokenKind::period)) {
3736
    // NewTarget: new . target
3737
    //                  ^
3738
0
    if (!check(targetIdent_)) {
3739
0
      error(tok_->getSourceRange(), "'target' expected in member expression");
3740
0
      sm_.note(newRange.Start, "start of member expression");
3741
0
      return None;
3742
0
    }
3743
0
    auto *meta = setLocation(
3744
0
        newRange,
3745
0
        newRange,
3746
0
        new (context_) ESTree::IdentifierNode(newIdent_, nullptr, false));
3747
0
    auto *prop = setLocation(
3748
0
        tok_,
3749
0
        tok_,
3750
0
        new (context_) ESTree::IdentifierNode(targetIdent_, nullptr, false));
3751
0
    advance();
3752
0
    auto *expr = setLocation(
3753
0
        meta, prop, new (context_) ESTree::MetaPropertyNode(meta, prop));
3754
0
    return parseOptionalExpressionExceptNew_tail(
3755
0
        isConstructorCall, newRange.Start, expr);
3756
0
  }
3757
3758
101k
  CHECK_RECURSION;
3759
101k
  auto optExpr = parseNewExpressionOrOptionalExpression(IsConstructorCall::Yes);
3760
101k
  if (!optExpr)
3761
0
    return None;
3762
50.6k
  ESTree::NodePtr expr = optExpr.getValue();
3763
3764
50.6k
  ESTree::Node *typeArgs = nullptr;
3765
50.6k
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
3766
50.6k
  if ((context_.getParseFlowAmbiguous() || context_.getParseTS()) &&
3767
50.6k
      check(TokenKind::less)) {
3768
0
    JSLexer::SavePoint savePoint{&lexer_};
3769
    // Attempt to parse type args upon encountering '<',
3770
    // but roll back if it just ended up being a comparison operator.
3771
0
    SourceErrorManager::SaveAndSuppressMessages suppress{
3772
0
        &sm_, Subsystem::Parser};
3773
0
    auto optTypeArgs =
3774
0
        context_.getParseTS() ? parseTSTypeArguments() : parseTypeArgsFlow();
3775
0
    if (optTypeArgs) {
3776
      // New expression with type arguments.
3777
0
      typeArgs = *optTypeArgs;
3778
0
    } else {
3779
      // Failed to parse a call expression with type arguments,
3780
      // simply roll back and start again.
3781
0
      savePoint.restore();
3782
0
    }
3783
0
  }
3784
50.6k
#endif
3785
3786
  // Do we have arguments to a child MemberExpression? If yes, then it really
3787
  // was a 'new MemberExpression(args)', otherwise it is a NewExpression
3788
50.6k
  if (!check(TokenKind::l_paren)) {
3789
50.6k
    return setLocation(
3790
50.6k
        newRange,
3791
50.6k
        getPrevTokenEndLoc(),
3792
50.6k
        new (context_)
3793
50.6k
            ESTree::NewExpressionNode(expr, typeArgs, ESTree::NodeList{}));
3794
50.6k
  }
3795
3796
0
  auto debugLoc = tok_->getStartLoc();
3797
0
  ESTree::NodeList argList;
3798
0
  SMLoc endLoc;
3799
0
  if (!parseArguments(argList, endLoc))
3800
0
    return None;
3801
3802
0
  expr = setLocation(
3803
0
      newRange,
3804
0
      endLoc,
3805
0
      debugLoc,
3806
0
      new (context_)
3807
0
          ESTree::NewExpressionNode(expr, typeArgs, std::move(argList)));
3808
3809
0
  SMLoc objectLoc = newRange.Start;
3810
0
  while (
3811
0
      checkN(TokenKind::l_square, TokenKind::period, TokenKind::questiondot)) {
3812
0
    SMLoc nextObjectLoc = tok_->getStartLoc();
3813
0
    auto optMSel = parseMemberSelect(newRange.Start, objectLoc, expr, false);
3814
0
    if (!optMSel)
3815
0
      return None;
3816
0
    objectLoc = nextObjectLoc;
3817
0
    expr = optMSel.getValue();
3818
0
  }
3819
3820
0
  return expr;
3821
0
}
3822
3823
8.90M
Optional<ESTree::Node *> JSParserImpl::parseLeftHandSideExpression() {
3824
8.90M
  SMLoc startLoc = tok_->getStartLoc();
3825
3826
8.90M
  auto optExpr = parseNewExpressionOrOptionalExpression(IsConstructorCall::No);
3827
8.90M
  if (!optExpr)
3828
1.20k
    return None;
3829
3830
8.90M
  return parseLeftHandSideExpressionTail(startLoc, optExpr.getValue());
3831
8.90M
}
3832
3833
Optional<ESTree::Node *> JSParserImpl::parseLeftHandSideExpressionTail(
3834
    SMLoc startLoc,
3835
8.90M
    ESTree::Node *expr) {
3836
8.90M
  bool optional = checkAndEat(TokenKind::questiondot);
3837
8.90M
  bool seenOptionalChain = optional ||
3838
8.90M
      (expr->getParens() == 0 &&
3839
8.90M
       (llvh::isa<ESTree::OptionalMemberExpressionNode>(expr) ||
3840
8.90M
        llvh::isa<ESTree::OptionalCallExpressionNode>(expr)));
3841
3842
8.90M
  ESTree::Node *typeArgs = nullptr;
3843
8.90M
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
3844
  // If the less than sign is immediately following a question dot then it
3845
  // cannot be a binary expression and is unambiguously Flow type syntax.
3846
8.90M
  if (((optional ? context_.getParseFlow()
3847
8.90M
                 : context_.getParseFlowAmbiguous()) ||
3848
8.90M
       context_.getParseTS()) &&
3849
8.90M
      check(TokenKind::less)) {
3850
0
    JSLexer::SavePoint savePoint{&lexer_};
3851
    // Suppress messages from the parser while still displaying lexer messages.
3852
0
    SourceErrorManager::SaveAndSuppressMessages suppress{
3853
0
        &sm_, Subsystem::Parser};
3854
0
    auto optTypeArgs =
3855
0
        context_.getParseTS() ? parseTSTypeArguments() : parseTypeArgsFlow();
3856
0
    if (optTypeArgs && check(TokenKind::l_paren)) {
3857
      // Call expression with type arguments.
3858
0
      typeArgs = *optTypeArgs;
3859
0
    } else {
3860
      // Failed to parse a call expression with type arguments,
3861
      // simply roll back and start again.
3862
0
      savePoint.restore();
3863
0
    }
3864
0
  }
3865
8.90M
#endif
3866
3867
  // Is this a CallExpression?
3868
8.90M
  if (checkN(
3869
8.90M
          TokenKind::l_paren,
3870
8.90M
          TokenKind::no_substitution_template,
3871
8.90M
          TokenKind::template_head)) {
3872
2.95k
    auto optCallExpr = parseCallExpression(
3873
2.95k
        startLoc, expr, typeArgs, seenOptionalChain, optional);
3874
2.95k
    if (!optCallExpr)
3875
2.91k
      return None;
3876
34
    expr = optCallExpr.getValue();
3877
34
  }
3878
3879
8.90M
  return expr;
3880
8.90M
}
3881
3882
8.90M
Optional<ESTree::Node *> JSParserImpl::parsePostfixExpression() {
3883
8.90M
  SMLoc startLoc = tok_->getStartLoc();
3884
8.90M
  auto optLHandExpr = parseLeftHandSideExpression();
3885
8.90M
  if (!optLHandExpr)
3886
4.12k
    return None;
3887
3888
8.90M
  if (check(TokenKind::plusplus, TokenKind::minusminus) &&
3889
8.90M
      !lexer_.isNewLineBeforeCurrentToken()) {
3890
0
    auto *res = setLocation(
3891
0
        startLoc,
3892
0
        tok_,
3893
0
        tok_,
3894
0
        new (context_) ESTree::UpdateExpressionNode(
3895
0
            getTokenIdent(tok_->getKind()), optLHandExpr.getValue(), false));
3896
0
    advance(JSLexer::AllowDiv);
3897
0
    return res;
3898
8.90M
  } else {
3899
8.90M
    return optLHandExpr.getValue();
3900
8.90M
  }
3901
8.90M
}
3902
3903
8.96M
Optional<ESTree::Node *> JSParserImpl::parseUnaryExpression() {
3904
8.96M
  SMLoc startLoc = tok_->getStartLoc();
3905
3906
8.96M
  switch (tok_->getKind()) {
3907
0
    case TokenKind::rw_delete:
3908
0
    case TokenKind::rw_void:
3909
20
    case TokenKind::rw_typeof:
3910
1.05k
    case TokenKind::plus:
3911
44.6k
    case TokenKind::minus:
3912
51.7k
    case TokenKind::tilde:
3913
51.8k
    case TokenKind::exclaim: {
3914
51.8k
      UniqueString *op = getTokenIdent(tok_->getKind());
3915
51.8k
      advance();
3916
51.8k
      CHECK_RECURSION;
3917
51.8k
      auto expr = parseUnaryExpression();
3918
51.8k
      if (!expr)
3919
0
        return None;
3920
3921
51.8k
      if (check(TokenKind::starstar)) {
3922
        // ExponentiationExpression only allows UpdateExpressionNode on the
3923
        // left. The simplest way to enforce that the left operand is not
3924
        // an unparenthesized UnaryExpression is to check here.
3925
0
        error(
3926
0
            {startLoc, tok_->getEndLoc()},
3927
0
            "Unary operator before ** must use parens to disambiguate");
3928
0
      }
3929
3930
51.8k
      return setLocation(
3931
51.8k
          startLoc,
3932
51.8k
          getPrevTokenEndLoc(),
3933
51.8k
          new (context_)
3934
51.8k
              ESTree::UnaryExpressionNode(op, expr.getValue(), true));
3935
51.8k
    }
3936
3937
2
    case TokenKind::plusplus:
3938
2
    case TokenKind::minusminus: {
3939
2
      UniqueString *op = getTokenIdent(tok_->getKind());
3940
2
      advance();
3941
2
      CHECK_RECURSION;
3942
2
      auto expr = parseUnaryExpression();
3943
2
      if (!expr)
3944
0
        return None;
3945
3946
2
      return setLocation(
3947
2
          startLoc,
3948
2
          getPrevTokenEndLoc(),
3949
2
          new (context_)
3950
2
              ESTree::UpdateExpressionNode(op, expr.getValue(), true));
3951
2
    }
3952
3953
0
#if HERMES_PARSE_TS
3954
0
    case TokenKind::less:
3955
0
      if (context_.getParseTS() && !context_.getParseJSX()) {
3956
        // TSTypeAssertions are only parsed if JSX is disabled,
3957
        // so there's no backtracking necessary here.
3958
        // < Type > UnaryExpression
3959
        // ^
3960
0
        advance(JSLexer::GrammarContext::Type);
3961
0
        auto optType = parseTypeAnnotationTS();
3962
0
        if (!optType)
3963
0
          return None;
3964
0
        if (!eat(
3965
0
                TokenKind::greater,
3966
0
                JSLexer::GrammarContext::AllowRegExp,
3967
0
                "in type assertion",
3968
0
                "start of assertion",
3969
0
                startLoc))
3970
0
          return None;
3971
0
        CHECK_RECURSION;
3972
0
        auto optExpr = parseUnaryExpression();
3973
0
        if (!optExpr)
3974
0
          return None;
3975
0
        return setLocation(
3976
0
            startLoc,
3977
0
            getPrevTokenEndLoc(),
3978
0
            new (context_) ESTree::TSTypeAssertionNode(*optType, *optExpr));
3979
0
      }
3980
0
      break;
3981
0
#endif
3982
3983
3.33M
    case TokenKind::identifier:
3984
3.33M
      if (check(awaitIdent_) && paramAwait_) {
3985
0
        advance();
3986
0
        CHECK_RECURSION;
3987
0
        auto optExpr = parseUnaryExpression();
3988
0
        if (!optExpr)
3989
0
          return None;
3990
0
        return setLocation(
3991
0
            startLoc,
3992
0
            getPrevTokenEndLoc(),
3993
0
            new (context_) ESTree::AwaitExpressionNode(optExpr.getValue()));
3994
0
      }
3995
      // Default for all other identifiers.
3996
3.33M
      break;
3997
3998
5.57M
    default:
3999
5.57M
      break;
4000
8.96M
  }
4001
8.90M
  return parsePostfixExpression();
4002
8.96M
}
4003
4004
namespace {
4005
4006
/// Associates precedence levels with binary operators. Higher precedences are
4007
/// represented by higher values.
4008
/// \returns the precedence level starting from 1, or 0 if not a binop.
4009
13.7M
inline unsigned getPrecedence(TokenKind kind) {
4010
  // Record the precedence of all binary operators.
4011
13.7M
  static const unsigned precedence[] = {
4012
744M
#define TOK(...) 0,
4013
317M
#define BINOP(name, str, precedence) precedence,
4014
13.7M
#define IDENT_OP(name, str, precedence) precedence,
4015
4016
// There are two reserved words that are binary operators.
4017
13.7M
#define RESWORD(name)                                       \
4018
606M
  (TokenKind::rw_##name == TokenKind::rw_in ||              \
4019
606M
           TokenKind::rw_##name == TokenKind::rw_instanceof \
4020
606M
       ? 8                                                  \
4021
606M
       : 0),
4022
13.7M
#include "hermes/Parser/TokenKinds.def"
4023
13.7M
  };
4024
4025
13.7M
  return precedence[static_cast<unsigned>(kind)];
4026
13.7M
}
4027
4028
/// \return true if \p kind is left associative, false if right associative.
4029
2.20M
inline bool isLeftAssoc(TokenKind kind) {
4030
2.20M
  return kind != TokenKind::starstar;
4031
2.20M
}
4032
4033
/// Return the precedence of \p token unless it happens to be equal to \p
4034
/// except, in which case return 0.
4035
/// \param asIdent if not null, the "as" UniqueString used to parse TS
4036
///   AsExpressions.
4037
8.90M
inline unsigned getPrecedenceExcept(const Token *token, TokenKind except) {
4038
8.90M
  const TokenKind kind = token->getKind();
4039
8.90M
  return LLVM_LIKELY(kind != except) ? getPrecedence(kind) : 0;
4040
8.90M
}
4041
} // namespace
4042
4043
8.90M
inline void JSParserImpl::convertIdentOpIfPossible() {
4044
8.90M
#if HERMES_PARSE_TS || HERMES_PARSE_FLOW
4045
8.90M
  if (LLVM_UNLIKELY(tok_->getKind() == TokenKind::identifier) &&
4046
8.90M
      context_.getParseTypes()) {
4047
0
    if (tok_->getIdentifier() == asIdent_)
4048
0
      lexer_.convertCurTokenToIdentOp(TokenKind::as_operator);
4049
0
  }
4050
8.90M
#endif
4051
8.90M
};
4052
4053
6.61M
Optional<ESTree::Node *> JSParserImpl::parseBinaryExpression(Param param) {
4054
  // The stack can never go deeper than the number of precedence levels,
4055
  // unless we have a right-associative operator.
4056
  // We have 10 precedence levels.
4057
6.61M
  constexpr unsigned STACK_SIZE = 16;
4058
4059
6.61M
  struct PrecedenceStackEntry {
4060
    /// Left hand side expression.
4061
6.61M
    ESTree::NodePtr expr;
4062
    // Operator for this expression.
4063
6.61M
    TokenKind opKind;
4064
    // Start location for the left hand side expression.
4065
6.61M
    SMLoc exprStartLoc;
4066
4067
6.61M
    PrecedenceStackEntry(
4068
6.61M
        ESTree::NodePtr expr,
4069
6.61M
        TokenKind opKind,
4070
6.61M
        SMLoc exprStartLoc)
4071
6.61M
        : expr(expr), opKind(opKind), exprStartLoc(exprStartLoc) {}
4072
6.61M
  };
4073
6.61M
  llvh::SmallVector<PrecedenceStackEntry, STACK_SIZE> stack{};
4074
4075
  // True upon encountering a '??' operator.
4076
6.61M
  bool hasNullish = false;
4077
  // True upon encountering a '&&' or '||' operator.
4078
6.61M
  bool hasBoolean = false;
4079
4080
  /// Allocate a binary expression node with the specified children and
4081
  /// operator.
4082
6.61M
  const auto newBinNode = [this, &hasNullish, &hasBoolean](
4083
6.61M
                              ESTree::NodePtr left,
4084
6.61M
                              TokenKind opKind,
4085
6.61M
                              ESTree::NodePtr right,
4086
6.61M
                              SMLoc startLoc,
4087
6.61M
                              SMLoc endLoc) -> ESTree::NodePtr {
4088
2.29M
    UniqueString *opIdent = getTokenIdent(opKind);
4089
2.29M
    if (opKind == TokenKind::ampamp || opKind == TokenKind::pipepipe ||
4090
2.29M
        opKind == TokenKind::questionquestion) {
4091
70.7k
      if ((hasNullish && opKind != TokenKind::questionquestion) ||
4092
70.7k
          (hasBoolean && opKind == TokenKind::questionquestion)) {
4093
        // This error doesn't prevent parsing the rest of the binary expression,
4094
        // because it's only there to avoid confusion from the JS author's
4095
        // perspective. Report the error but continue parsing.
4096
        // The question marks are escaped to avoid triggering a trigraph.
4097
0
        error(
4098
0
            {left->getStartLoc(), right->getEndLoc()},
4099
0
            "Mixing '\?\?' with '&&' or '||' requires parentheses");
4100
0
      }
4101
70.7k
      if (opKind == TokenKind::questionquestion) {
4102
0
        hasNullish = true;
4103
70.7k
      } else {
4104
70.7k
        hasBoolean = true;
4105
70.7k
      }
4106
70.7k
      return setLocation(
4107
70.7k
          startLoc,
4108
70.7k
          endLoc,
4109
70.7k
          new (context_) ESTree::LogicalExpressionNode(left, right, opIdent));
4110
70.7k
#if HERMES_PARSE_TS || HERMES_PARSE_FLOW
4111
2.22M
    } else if (LLVM_UNLIKELY(opKind == TokenKind::as_operator)) {
4112
0
      if (context_.getParseTS()) {
4113
0
        return setLocation(
4114
0
            startLoc,
4115
0
            endLoc,
4116
0
            new (context_) ESTree::TSAsExpressionNode(left, right));
4117
0
      } else {
4118
0
        assert(context_.getParseFlow() && "must be parsing types");
4119
0
        if (auto *gen =
4120
0
                llvh::dyn_cast<ESTree::GenericTypeAnnotationNode>(right);
4121
0
            gen && !gen->_typeParameters && gen->getParens() == 0) {
4122
0
          if (auto *ident = llvh::dyn_cast<ESTree::IdentifierNode>(gen->_id)) {
4123
0
            if (ident->_name == constIdent_ && !ident->_optional &&
4124
0
                !ident->_typeAnnotation) {
4125
              // Special case for `x as const`,
4126
              // which only is used when the `const` type has no parens
4127
              // (otherwise, it's just a GenericTypeAnnotationNode).
4128
0
              return setLocation(
4129
0
                  startLoc,
4130
0
                  endLoc,
4131
0
                  new (context_) ESTree::AsConstExpressionNode(left));
4132
0
            }
4133
0
          }
4134
0
        }
4135
0
        return setLocation(
4136
0
            startLoc,
4137
0
            endLoc,
4138
0
            new (context_) ESTree::AsExpressionNode(left, right));
4139
0
      }
4140
0
#endif
4141
2.22M
    } else {
4142
2.22M
      return setLocation(
4143
2.22M
          startLoc,
4144
2.22M
          endLoc,
4145
2.22M
          new (context_) ESTree::BinaryExpressionNode(left, right, opIdent));
4146
2.22M
    }
4147
2.29M
  };
4148
4149
  /// Parse a private identifier, which can only be used as LHS in an `in`.
4150
  /// If it's not in a valid position, report an error.
4151
6.61M
  const auto consumePrivateIdentifier = [this, &stack]() -> ESTree::Node * {
4152
0
    assert(check(TokenKind::private_identifier));
4153
0
    ESTree::Node *name = setLocation(
4154
0
        tok_,
4155
0
        tok_,
4156
0
        new (context_) ESTree::PrivateNameNode(setLocation(
4157
0
            tok_,
4158
0
            tok_,
4159
0
            new (context_) ESTree::IdentifierNode(
4160
0
                tok_->getPrivateIdentifier(), nullptr, false))));
4161
0
    advance(JSLexer::GrammarContext::AllowDiv);
4162
0
    unsigned prevPrec = stack.empty() ? 0 : getPrecedence(stack.back().opKind);
4163
    // Check the precedence of the previous operator on the stack if it exists.
4164
    // If prevPrec is higher precedence than `in`, the private name will end
4165
    // up as the RHS in an invalid binary expression, so report an error.
4166
0
    if (!check(TokenKind::rw_in) || prevPrec >= getPrecedence(TokenKind::rw_in))
4167
0
      error(
4168
0
          name->getSourceRange(),
4169
0
          "Private name can only be used as left-hand side of `in` expression");
4170
0
    return name;
4171
0
  };
4172
4173
  // Decide whether to recognize "in" as a binary operator.
4174
6.61M
  const TokenKind exceptKind =
4175
6.61M
      !param.has(ParamIn) ? TokenKind::rw_in : TokenKind::none;
4176
4177
6.61M
  SMLoc topExprStartLoc = tok_->getStartLoc();
4178
6.61M
  ESTree::Node *topExpr = nullptr;
4179
6.61M
  if (LLVM_UNLIKELY(check(TokenKind::private_identifier))) {
4180
0
    topExpr = consumePrivateIdentifier();
4181
6.61M
  } else {
4182
6.61M
    auto optExpr = parseUnaryExpression();
4183
6.61M
    if (!optExpr)
4184
4.11k
      return None;
4185
6.61M
    topExpr = optExpr.getValue();
4186
6.61M
  }
4187
6.61M
  SMLoc topExprEndLoc = getPrevTokenEndLoc();
4188
6.61M
  convertIdentOpIfPossible();
4189
4190
  // While the current token is a binary operator.
4191
8.90M
  while (unsigned precedence = getPrecedenceExcept(tok_, exceptKind)) {
4192
    // If the next operator has no greater precedence than the operator on the
4193
    // stack, pop the stack, creating a new binary expression.
4194
4.56M
    while (!stack.empty() && precedence <= getPrecedence(stack.back().opKind)) {
4195
2.27M
      if (precedence == getPrecedence(stack.back().opKind) &&
4196
2.27M
          !isLeftAssoc(stack.back().opKind)) {
4197
        // If the precedences are equal, then we avoid popping for
4198
        // right-associative operators to allow for the entire right-associative
4199
        // expression to be built from the right.
4200
0
        break;
4201
0
      }
4202
2.27M
      topExpr = newBinNode(
4203
2.27M
          stack.back().expr,
4204
2.27M
          stack.back().opKind,
4205
2.27M
          topExpr,
4206
2.27M
          stack.back().exprStartLoc,
4207
2.27M
          topExprEndLoc);
4208
2.27M
      topExprStartLoc = topExpr->getStartLoc();
4209
2.27M
      stack.pop_back();
4210
2.27M
    }
4211
4212
    // The next operator has a higher precedence than the previous one (or there
4213
    // is no previous one). The situation looks something like this:
4214
    //    .... + topExpr * rightExpr ....
4215
    //                     ^
4216
    //                 We are here
4217
    // Push topExpr and the '*', so we can parse rightExpr.
4218
2.29M
    stack.emplace_back(topExpr, tok_->getKind(), topExprStartLoc);
4219
4220
2.29M
#if HERMES_PARSE_TS || HERMES_PARSE_FLOW
4221
2.29M
    if (LLVM_UNLIKELY(stack.back().opKind == TokenKind::as_operator)) {
4222
0
      advance(JSLexer::GrammarContext::Type);
4223
0
      topExprStartLoc = tok_->getStartLoc();
4224
0
      auto optRightExpr = parseTypeAnnotation();
4225
0
      if (!optRightExpr)
4226
0
        return None;
4227
0
      topExpr = optRightExpr.getValue();
4228
0
    } else
4229
2.29M
#endif
4230
2.29M
    {
4231
2.29M
      advance();
4232
2.29M
      topExprStartLoc = tok_->getStartLoc();
4233
2.29M
      if (LLVM_UNLIKELY(check(TokenKind::private_identifier))) {
4234
0
        topExpr = consumePrivateIdentifier();
4235
2.29M
      } else {
4236
2.29M
        auto optRightExpr = parseUnaryExpression();
4237
2.29M
        if (!optRightExpr)
4238
5
          return None;
4239
2.29M
        topExpr = optRightExpr.getValue();
4240
2.29M
      }
4241
2.29M
    }
4242
4243
2.29M
    topExprEndLoc = getPrevTokenEndLoc();
4244
2.29M
    convertIdentOpIfPossible();
4245
2.29M
  }
4246
4247
  // We have consumed all binary operators. Pop the stack, creating expressions.
4248
6.62M
  while (!stack.empty()) {
4249
15.2k
    topExpr = newBinNode(
4250
15.2k
        stack.back().expr,
4251
15.2k
        stack.back().opKind,
4252
15.2k
        topExpr,
4253
15.2k
        stack.back().exprStartLoc,
4254
15.2k
        topExprEndLoc);
4255
15.2k
    stack.pop_back();
4256
15.2k
  }
4257
4258
6.61M
  assert(
4259
6.61M
      stack.empty() &&
4260
6.61M
      "Stack must be empty when done parsing binary expression");
4261
4262
6.61M
  return topExpr;
4263
6.61M
}
4264
4265
Optional<ESTree::Node *> JSParserImpl::parseConditionalExpression(
4266
    Param param,
4267
6.61M
    CoverTypedParameters coverTypedParameters) {
4268
6.61M
  SMLoc startLoc = tok_->getStartLoc();
4269
6.61M
  auto optTest = parseBinaryExpression(param);
4270
6.61M
  if (!optTest)
4271
4.12k
    return None;
4272
6.61M
  ESTree::Node *test = *optTest;
4273
4274
6.61M
  if (!check(TokenKind::question)) {
4275
    // No '?', so this isn't a conditional expression.
4276
    // If CoverTypedParameters::Yes, we still need to account for this
4277
    // being formal parameters, so try that.
4278
    // TS doesn't have type casts with this syntax, but we must still
4279
    // cover the typed identifier node for when it turns into an arrow function.
4280
6.60M
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
4281
6.60M
    if (context_.getParseTypes() &&
4282
6.60M
        coverTypedParameters == CoverTypedParameters::Yes) {
4283
0
      auto optCover = tryParseCoverTypedIdentifierNode(test, false);
4284
0
      if (!optCover)
4285
0
        return None;
4286
0
      if (*optCover)
4287
0
        return *optCover;
4288
0
    }
4289
6.60M
#endif
4290
4291
    // No CoverTypedParameters found, just return the LHS.
4292
6.60M
    return test;
4293
6.60M
  }
4294
4295
7.33k
  ESTree::Node *consequent = nullptr;
4296
7.33k
  SMRange questionRange = tok_->getSourceRange();
4297
4298
7.33k
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
4299
7.33k
  if (context_.getParseTypes()) {
4300
    // Save here to save the question mark (we can only save on punctuators).
4301
    // Early returns will happen if we find anything that leads to
4302
    // short-circuiting out of the traditional conditional expression.
4303
0
    JSLexer::SavePoint savePoint{&lexer_};
4304
0
    advance();
4305
4306
    // If CoverTypedParameters::Yes, we still need to account for this
4307
    // being formal parameters, so try that,
4308
    // in which case the '?' was part of an optional parameter, not a
4309
    // conditional expression.
4310
0
    if (coverTypedParameters == CoverTypedParameters::Yes) {
4311
0
      auto optCover = tryParseCoverTypedIdentifierNode(test, true);
4312
0
      if (!optCover)
4313
0
        return None;
4314
0
      if (*optCover)
4315
0
        return *optCover;
4316
0
    }
4317
4318
    // It is also possible to have a '?' without ':' but not be a conditional
4319
    // expression, in the case of typed arrow parameters that didn't have a type
4320
    // annotation. For example:
4321
    // (foo?) => 1
4322
    //      ^
4323
    // The tokens which can come here are limited to ',', '=', and ')'.
4324
0
    if (coverTypedParameters == CoverTypedParameters::Yes &&
4325
0
        checkN(TokenKind::comma, TokenKind::r_paren, TokenKind::equal)) {
4326
0
      return setLocation(
4327
0
          startLoc,
4328
0
          questionRange,
4329
0
          new (context_) ESTree::CoverTypedIdentifierNode(test, nullptr, true));
4330
0
    }
4331
4332
    // Now we're in the real backtracking stage.
4333
    // First, parse with AllowTypedArrowFunction::Yes to allow for the
4334
    // possibility of a concise arrow function with return types. However, we
4335
    // want to avoid the possibility of eating the ':' that we'll need for the
4336
    // conditional expression's alternate. For example:
4337
    // a ? b1 => (c1) : b2 => (c2)
4338
    // We want to account for b2 incorrectly being parsed as the returnType
4339
    // of an arrow function returned by the arrow function with param b1.
4340
    // Thus, after parsing with AllowTypedArrowFunction::Yes, we check to
4341
    // see if there is a ':' afterwards. If there isn't, failure is assured,
4342
    // so we restore to the '?' and try again below, with
4343
    // AllowTypedArrowFunction::No.
4344
0
    SourceErrorManager::SaveAndSuppressMessages suppress{
4345
0
        &sm_, Subsystem::Parser};
4346
0
    CHECK_RECURSION;
4347
0
    auto optConsequent = parseAssignmentExpression(
4348
0
        ParamIn, AllowTypedArrowFunction::Yes, CoverTypedParameters::No);
4349
0
    if (optConsequent && check(TokenKind::colon)) {
4350
0
      consequent = *optConsequent;
4351
0
    } else {
4352
      // Parsing with typed arrow functions failed because we don't have a :,
4353
      // so reset and try again.
4354
0
      savePoint.restore();
4355
0
    }
4356
0
  }
4357
7.33k
#endif
4358
4359
  // Calls to parseAssignmentExpression may recursively invoke
4360
  // parseConditionalExpression.
4361
14.6k
  CHECK_RECURSION;
4362
4363
  // Only try with AllowTypedArrowFunction::No if we haven't already set
4364
  // up the consequent using AllowTypedArrowFunction::Yes.
4365
14.6k
  if (!consequent) {
4366
    // Consume the '?' (either for the first time or after savePoint.restore()).
4367
7.33k
    advance();
4368
7.33k
    auto optConsequent = parseAssignmentExpression(
4369
7.33k
        ParamIn, AllowTypedArrowFunction::No, CoverTypedParameters::No);
4370
7.33k
    if (!optConsequent)
4371
0
      return None;
4372
7.33k
    consequent = *optConsequent;
4373
7.33k
  }
4374
4375
7.33k
  if (!eat(
4376
7.33k
          TokenKind::colon,
4377
7.33k
          JSLexer::AllowRegExp,
4378
7.33k
          "in conditional expression after '... ? ...'",
4379
7.33k
          "location of '?'",
4380
7.33k
          questionRange.Start))
4381
0
    return None;
4382
4383
7.33k
  auto optAlternate = parseAssignmentExpression(
4384
7.33k
      param, AllowTypedArrowFunction::Yes, CoverTypedParameters::No);
4385
7.33k
  if (!optAlternate)
4386
0
    return None;
4387
7.33k
  ESTree::Node *alternate = *optAlternate;
4388
4389
7.33k
  return setLocation(
4390
7.33k
      startLoc,
4391
7.33k
      getPrevTokenEndLoc(),
4392
7.33k
      new (context_)
4393
7.33k
          ESTree::ConditionalExpressionNode(test, alternate, consequent));
4394
7.33k
}
4395
4396
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
4397
Optional<ESTree::Node *> JSParserImpl::tryParseCoverTypedIdentifierNode(
4398
    ESTree::Node *test,
4399
0
    bool optional) {
4400
0
  assert(context_.getParseTypes() && "must be parsing types");
4401
  // In the case of flow types in arrow function parameters, we may have
4402
  // optional parameters which look like:
4403
  // Identifier ? : TypeAnnotation
4404
  // Because the colon and the type annotation are optional, we check and
4405
  // consume the colon here and return a CoverTypedIdentifierNode if it's
4406
  // possible we are parsing typed arrow parameters.
4407
0
  if (check(TokenKind::colon) && test->getParens() == 0) {
4408
0
    if (isa<ESTree::IdentifierNode>(test) ||
4409
0
        isa<ESTree::ObjectExpressionNode>(test) ||
4410
0
        isa<ESTree::ArrayExpressionNode>(test)) {
4411
      // Deliberately wrap the type annotation later when reparsing.
4412
0
      SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
4413
0
      auto optRet = parseTypeAnnotation(annotStart);
4414
0
      if (!optRet)
4415
0
        return None;
4416
0
      ESTree::Node *type = *optRet;
4417
4418
0
      return setLocation(
4419
0
          test,
4420
0
          getPrevTokenEndLoc(),
4421
0
          new (context_)
4422
0
              ESTree::CoverTypedIdentifierNode(test, type, optional));
4423
0
    }
4424
    // The colon must indicate something another than the typeAnnotation for
4425
    // the parameter. Continue as usual.
4426
0
  }
4427
0
  return nullptr;
4428
0
}
4429
#endif
4430
4431
Optional<ESTree::YieldExpressionNode *> JSParserImpl::parseYieldExpression(
4432
0
    Param param) {
4433
0
  assert(
4434
0
      paramYield_ && check(TokenKind::rw_yield, TokenKind::identifier) &&
4435
0
      tok_->getResWordOrIdentifier() == yieldIdent_ &&
4436
0
      "yield expression must start with 'yield'");
4437
0
  SMRange yieldLoc = advance();
4438
4439
0
  if (check(TokenKind::semi) ||
4440
0
      checkEndAssignmentExpression(OfEndsAssignment::No)) {
4441
    // 'of' doesn't end the assignment expression in a yield.
4442
    //    yield of;
4443
    //          ^
4444
    // is a valid position here and should simply yield a variable called 'of'.
4445
0
    return setLocation(
4446
0
        yieldLoc,
4447
0
        yieldLoc,
4448
0
        new (context_) ESTree::YieldExpressionNode(nullptr, false));
4449
0
  }
4450
4451
0
  bool delegate = checkAndEat(TokenKind::star);
4452
4453
0
  auto optArg = parseAssignmentExpression(
4454
0
      param.get(ParamIn),
4455
0
      AllowTypedArrowFunction::Yes,
4456
0
      CoverTypedParameters::No);
4457
0
  if (!optArg)
4458
0
    return None;
4459
4460
0
  return setLocation(
4461
0
      yieldLoc,
4462
0
      getPrevTokenEndLoc(),
4463
0
      new (context_) ESTree::YieldExpressionNode(optArg.getValue(), delegate));
4464
0
}
4465
4466
Optional<ESTree::ClassDeclarationNode *> JSParserImpl::parseClassDeclaration(
4467
0
    Param param) {
4468
0
  assert(check(TokenKind::rw_class) && "class must start with 'class'");
4469
  // NOTE: Class definition is always strict mode code.
4470
0
  SaveStrictModeAndSeenDirectives saveStrictModeAndSeenDirectives{this};
4471
0
  setStrictMode(true);
4472
4473
0
  SMLoc startLoc = advance().Start;
4474
4475
0
  ESTree::Node *name = nullptr;
4476
0
  ESTree::Node *typeParams = nullptr;
4477
4478
0
  if (check(TokenKind::identifier)) {
4479
0
    auto optName = parseBindingIdentifier(Param{});
4480
0
    if (!optName) {
4481
0
      errorExpected(
4482
0
          TokenKind::identifier,
4483
0
          "in class declaration",
4484
0
          "location of 'class'",
4485
0
          startLoc);
4486
0
      return None;
4487
0
    }
4488
0
    name = *optName;
4489
0
  } else if (!param.has(ParamDefault)) {
4490
    // Identifier is required unless we have +Default parameter.
4491
0
    errorExpected(
4492
0
        TokenKind::identifier,
4493
0
        "after 'class'",
4494
0
        "location of 'class'",
4495
0
        startLoc);
4496
0
    return None;
4497
0
  }
4498
4499
0
#if HERMES_PARSE_FLOW
4500
0
  if (context_.getParseFlow() && check(TokenKind::less)) {
4501
0
    auto optParams = parseTypeParamsFlow();
4502
0
    if (!optParams)
4503
0
      return None;
4504
0
    typeParams = *optParams;
4505
0
  }
4506
0
#endif
4507
0
#if HERMES_PARSE_TS
4508
0
  if (context_.getParseTS() && check(TokenKind::less)) {
4509
0
    auto optParams = parseTSTypeParameters();
4510
0
    if (!optParams)
4511
0
      return None;
4512
0
    typeParams = *optParams;
4513
0
  }
4514
0
#endif
4515
4516
0
  auto optClass =
4517
0
      parseClassTail(startLoc, name, typeParams, ClassParseKind::Declaration);
4518
0
  if (!optClass)
4519
0
    return None;
4520
0
  return llvh::cast<ESTree::ClassDeclarationNode>(*optClass);
4521
0
}
4522
4523
0
Optional<ESTree::ClassExpressionNode *> JSParserImpl::parseClassExpression() {
4524
0
  assert(check(TokenKind::rw_class) && "class must start with 'class'");
4525
  // NOTE: A class definition is always strict mode code.
4526
0
  SaveStrictModeAndSeenDirectives saveStrictModeAndSeenDirectives{this};
4527
0
  setStrictMode(true);
4528
4529
0
  SMLoc start = advance().Start;
4530
4531
0
  ESTree::Node *name = nullptr;
4532
0
  ESTree::Node *typeParams = nullptr;
4533
4534
0
  if (!check(TokenKind::rw_extends, TokenKind::l_brace) &&
4535
0
      !(context_.getParseFlow() &&
4536
0
        check(TokenKind::rw_implements, TokenKind::less)) &&
4537
0
      !(context_.getParseTS() && check(TokenKind::less))) {
4538
    // Try to parse a BindingIdentifier if we did not see a ClassHeritage
4539
    // or a '{'.
4540
0
    auto optName = parseBindingIdentifier(Param{});
4541
0
    if (!optName) {
4542
0
      errorExpected(
4543
0
          TokenKind::identifier,
4544
0
          "in class expression",
4545
0
          "location of 'class'",
4546
0
          start);
4547
0
      return None;
4548
0
    }
4549
0
    name = *optName;
4550
0
  }
4551
4552
0
#if HERMES_PARSE_FLOW
4553
0
  if (context_.getParseFlow() && check(TokenKind::less)) {
4554
0
    auto optParams = parseTypeParamsFlow();
4555
0
    if (!optParams)
4556
0
      return None;
4557
0
    typeParams = *optParams;
4558
0
  }
4559
0
#endif
4560
0
#if HERMES_PARSE_TS
4561
0
  if (context_.getParseTS() && check(TokenKind::less)) {
4562
0
    auto optParams = parseTSTypeParameters();
4563
0
    if (!optParams)
4564
0
      return None;
4565
0
    typeParams = *optParams;
4566
0
  }
4567
0
#endif
4568
4569
0
  auto optClass =
4570
0
      parseClassTail(start, name, typeParams, ClassParseKind::Expression);
4571
0
  if (!optClass)
4572
0
    return None;
4573
0
  return llvh::cast<ESTree::ClassExpressionNode>(*optClass);
4574
0
}
4575
4576
Optional<ESTree::Node *> JSParserImpl::parseClassTail(
4577
    SMLoc startLoc,
4578
    ESTree::Node *name,
4579
    ESTree::Node *typeParams,
4580
0
    ClassParseKind kind) {
4581
0
  ESTree::Node *superClass = nullptr;
4582
0
  ESTree::Node *superTypeParams = nullptr;
4583
4584
0
  if (checkAndEat(TokenKind::rw_extends)) {
4585
    // ClassHeritage[opt] { ClassBody[opt] }
4586
    // ^
4587
0
    auto optSuperClass = parseLeftHandSideExpression();
4588
0
    if (!optSuperClass)
4589
0
      return None;
4590
0
    superClass = *optSuperClass;
4591
0
#if HERMES_PARSE_FLOW
4592
0
    if (context_.getParseFlow() && check(TokenKind::less)) {
4593
0
      auto optParams = parseTypeArgsFlow();
4594
0
      if (!optParams)
4595
0
        return None;
4596
0
      superTypeParams = *optParams;
4597
0
    }
4598
0
#endif
4599
0
#if HERMES_PARSE_TS
4600
0
    if (context_.getParseTS() && check(TokenKind::less)) {
4601
0
      auto optParams = parseTSTypeArguments();
4602
0
      if (!optParams)
4603
0
        return None;
4604
0
      superTypeParams = *optParams;
4605
0
    }
4606
0
#endif
4607
0
  }
4608
4609
0
  ESTree::NodeList implements{};
4610
0
#if HERMES_PARSE_FLOW
4611
0
  if (context_.getParseFlow()) {
4612
0
    if (checkAndEat(TokenKind::rw_implements) ||
4613
0
        checkAndEat(implementsIdent_)) {
4614
0
      while (!check(TokenKind::l_brace)) {
4615
0
        if (!need(
4616
0
                TokenKind::identifier,
4617
0
                "in class 'implements'",
4618
0
                "start of class",
4619
0
                startLoc))
4620
0
          return None;
4621
0
        auto optImpl = parseClassImplementsFlow();
4622
0
        if (!optImpl)
4623
0
          return None;
4624
0
        implements.push_back(**optImpl);
4625
0
        if (!checkAndEat(TokenKind::comma)) {
4626
0
          break;
4627
0
        }
4628
0
      }
4629
0
    }
4630
0
  }
4631
0
#endif
4632
4633
0
  if (!need(
4634
0
          TokenKind::l_brace,
4635
0
          "in class definition",
4636
0
          "start of class",
4637
0
          startLoc)) {
4638
0
    return None;
4639
0
  }
4640
4641
0
  auto optBody = parseClassBody(startLoc);
4642
0
  if (!optBody)
4643
0
    return None;
4644
4645
0
  if (kind == ClassParseKind::Declaration) {
4646
0
    return setLocation(
4647
0
        startLoc,
4648
0
        *optBody,
4649
0
        new (context_) ESTree::ClassDeclarationNode(
4650
0
            name,
4651
0
            typeParams,
4652
0
            superClass,
4653
0
            superTypeParams,
4654
0
            std::move(implements),
4655
0
            {},
4656
0
            *optBody));
4657
0
  }
4658
0
  return setLocation(
4659
0
      startLoc,
4660
0
      *optBody,
4661
0
      new (context_) ESTree::ClassExpressionNode(
4662
0
          name,
4663
0
          typeParams,
4664
0
          superClass,
4665
0
          superTypeParams,
4666
0
          std::move(implements),
4667
0
          {},
4668
0
          *optBody));
4669
0
}
4670
4671
0
Optional<ESTree::ClassBodyNode *> JSParserImpl::parseClassBody(SMLoc startLoc) {
4672
0
  assert(check(TokenKind::l_brace) && "class body must begin with '{'");
4673
0
  SMLoc braceLoc = advance().Start;
4674
4675
  // It is a Syntax Error if PrototypePropertyNameList of ClassElementList
4676
  // contains more than one occurrence of  "constructor".
4677
0
  ESTree::Node *constructor = nullptr;
4678
4679
0
  ESTree::NodeList body{};
4680
0
  while (!check(TokenKind::r_brace)) {
4681
0
    bool isStatic = false;
4682
0
    SMRange startRange = tok_->getSourceRange();
4683
4684
0
    bool declare = false;
4685
0
    bool readonly = false;
4686
0
    ESTree::NodeLabel accessibility = nullptr;
4687
4688
0
#if HERMES_PARSE_FLOW
4689
0
    if (context_.getParseFlow() && check(declareIdent_)) {
4690
      // Check for "declare" class properties.
4691
0
      auto optNext = lexer_.lookahead1(llvh::None);
4692
0
      if (optNext.hasValue() &&
4693
0
          (*optNext == TokenKind::rw_static ||
4694
0
           *optNext == TokenKind::identifier || *optNext == TokenKind::plus ||
4695
0
           *optNext == TokenKind::minus)) {
4696
0
        declare = true;
4697
0
        advance();
4698
0
      }
4699
0
    }
4700
0
#endif
4701
4702
0
#if HERMES_PARSE_TS
4703
0
    if (context_.getParseTS()) {
4704
      // In TS, modifiers may appear in this order: accessibility - static -
4705
      // readonly. And all of them can be used as identifier.
4706
0
      if (checkN(
4707
0
              TokenKind::rw_private,
4708
0
              TokenKind::rw_protected,
4709
0
              TokenKind::rw_public)) {
4710
0
        if (canFollowModifierTS(lexer_.lookahead1(llvh::None))) {
4711
0
          accessibility = tok_->getResWordIdentifier();
4712
0
          advance();
4713
0
        }
4714
0
      }
4715
4716
0
      if (check(TokenKind::rw_static)) {
4717
0
        if (canFollowModifierTS(lexer_.lookahead1(llvh::None))) {
4718
0
          isStatic = true;
4719
0
          advance();
4720
0
        }
4721
0
      }
4722
4723
0
      if (check(readonlyIdent_)) {
4724
0
        if (canFollowModifierTS(lexer_.lookahead1(llvh::None))) {
4725
0
          readonly = true;
4726
0
          advance();
4727
0
        }
4728
0
      }
4729
0
    }
4730
0
#endif
4731
4732
0
    switch (tok_->getKind()) {
4733
0
      case TokenKind::semi:
4734
0
        advance();
4735
0
        break;
4736
4737
0
      case TokenKind::rw_static:
4738
0
        if (context_.getParseTS() && (readonly || isStatic)) {
4739
          // Don't advance() when `readonly` or `static` is already seen,
4740
          // so the current one can be regarded as an identifier.
4741
          // `static` modifier cannot come after `readonly` in TS.
4742
0
        } else {
4743
          // static MethodDefinition
4744
          // static FieldDefinition
4745
0
          isStatic = true;
4746
0
          advance();
4747
0
        }
4748
0
        LLVM_FALLTHROUGH;
4749
0
      default: {
4750
        // ClassElement
4751
0
        auto optElem = parseClassElement(
4752
0
            isStatic, startRange, declare, readonly, accessibility);
4753
0
        if (!optElem)
4754
0
          return None;
4755
0
        if (auto *method = dyn_cast<ESTree::MethodDefinitionNode>(*optElem)) {
4756
0
          if (method->_kind == constructorIdent_) {
4757
0
            if (constructor) {
4758
              // Cannot have duplicate constructors, but report the error
4759
              // and move on to parse the rest of the class.
4760
0
              error(
4761
0
                  method->getSourceRange(), "duplicate constructors in class");
4762
0
              sm_.note(
4763
0
                  constructor->getSourceRange(),
4764
0
                  "first constructor definition",
4765
0
                  Subsystem::Parser);
4766
0
            } else {
4767
0
              constructor = method;
4768
0
            }
4769
0
          }
4770
0
        } else if (auto *prop = dyn_cast<ESTree::ClassPropertyNode>(*optElem)) {
4771
0
          if (auto *propId = dyn_cast<ESTree::IdentifierNode>(prop->_key)) {
4772
0
            if (propId->_name == constructorIdent_) {
4773
0
              error(prop->getSourceRange(), "invalid class property name");
4774
0
            }
4775
0
          } else if (
4776
0
              auto *propStr = dyn_cast<ESTree::StringLiteralNode>(prop->_key)) {
4777
0
            if (propStr->_value == constructorIdent_) {
4778
0
              error(prop->getSourceRange(), "invalid class property name");
4779
0
            }
4780
0
          }
4781
0
        }
4782
4783
0
        body.push_back(**optElem);
4784
0
      }
4785
0
    }
4786
0
  }
4787
4788
0
  if (!need(
4789
0
          TokenKind::r_brace,
4790
0
          "at end of class definition",
4791
0
          "start of class",
4792
0
          startLoc)) {
4793
0
    return None;
4794
0
  }
4795
4796
0
  return setLocation(
4797
0
      braceLoc,
4798
0
      advance().End,
4799
0
      new (context_) ESTree::ClassBodyNode(std::move(body)));
4800
0
}
4801
4802
Optional<ESTree::Node *> JSParserImpl::parseClassElement(
4803
    bool isStatic,
4804
    SMRange startRange,
4805
    bool declare,
4806
    bool readonly,
4807
    ESTree::NodeLabel accessibility,
4808
0
    bool eagerly) {
4809
0
  SMLoc startLoc = tok_->getStartLoc();
4810
4811
0
  bool optional = false;
4812
0
  bool isPrivate = false;
4813
4814
0
  enum class SpecialKind {
4815
0
    None,
4816
0
    Get,
4817
0
    Set,
4818
0
    Generator,
4819
0
    Async,
4820
0
    AsyncGenerator,
4821
0
    ClassProperty,
4822
0
  };
4823
4824
  // Indicates if this method is out of the ordinary.
4825
  // In particular, indicates getters and setters.
4826
0
  SpecialKind special = SpecialKind::None;
4827
4828
  // When true, call parsePropertyName.
4829
  // Set to false if the identifiers 'get' or 'set' were already parsed as
4830
  // function names instead of as getter/setter specifiers.
4831
0
  bool doParsePropertyName = true;
4832
4833
  /// \return true when the current token indicates that `static` was actually
4834
  /// the property name and not a modifier.
4835
  /// e.g. `static() {}` returns true when the current tok is '(',
4836
  /// but `static x;` returns false when the current tok is 'x'.
4837
  /// When this returns `true`, we're done parsing the property name,
4838
  /// and we might have to use `static` as the property name if it was given in.
4839
0
  const auto staticIsPropertyName = [this]() -> bool {
4840
0
    if (checkN(
4841
0
            TokenKind::l_paren,
4842
0
            TokenKind::equal,
4843
0
            TokenKind::r_brace,
4844
0
            TokenKind::semi)) {
4845
0
      return true;
4846
0
    }
4847
0
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
4848
0
    if (context_.getParseTypes() && check(TokenKind::less, TokenKind::colon)) {
4849
0
      return true;
4850
0
    }
4851
0
#endif
4852
0
    return false;
4853
0
  };
4854
4855
0
  ESTree::Node *prop = nullptr;
4856
0
  if (check(getIdent_)) {
4857
0
    SMRange range = advance();
4858
0
    if (!checkN(
4859
0
            TokenKind::less,
4860
0
            TokenKind::l_paren,
4861
0
            TokenKind::r_brace,
4862
0
            TokenKind::equal,
4863
0
            TokenKind::colon,
4864
0
            TokenKind::semi)) {
4865
      // This was actually a getter.
4866
0
      special = SpecialKind::Get;
4867
0
    } else {
4868
0
      prop = setLocation(
4869
0
          range,
4870
0
          range,
4871
0
          new (context_) ESTree::IdentifierNode(getIdent_, nullptr, false));
4872
0
      doParsePropertyName = false;
4873
0
    }
4874
0
  } else if (check(setIdent_)) {
4875
0
    SMRange range = advance();
4876
0
    if (!checkN(
4877
0
            TokenKind::less,
4878
0
            TokenKind::l_paren,
4879
0
            TokenKind::r_brace,
4880
0
            TokenKind::equal,
4881
0
            TokenKind::colon,
4882
0
            TokenKind::semi)) {
4883
      // If we don't see '(' then this was actually a setter.
4884
0
      special = SpecialKind::Set;
4885
0
    } else {
4886
0
      prop = setLocation(
4887
0
          range,
4888
0
          range,
4889
0
          new (context_) ESTree::IdentifierNode(setIdent_, nullptr, false));
4890
0
      doParsePropertyName = false;
4891
0
    }
4892
0
  } else if (check(asyncIdent_)) {
4893
0
    SMRange range = advance();
4894
0
    if (!checkN(
4895
0
            TokenKind::less,
4896
0
            TokenKind::l_paren,
4897
0
            TokenKind::r_brace,
4898
0
            TokenKind::equal,
4899
0
            TokenKind::colon,
4900
0
            TokenKind::semi) &&
4901
0
        !lexer_.isNewLineBeforeCurrentToken()) {
4902
      // If we don't see '(' then this was actually an async method.
4903
      // Async methods cannot have a newline between 'async' and the name.
4904
      // These can be either Async or AsyncGenerator, so check for that.
4905
0
      special = checkAndEat(TokenKind::star) ? SpecialKind::AsyncGenerator
4906
0
                                             : SpecialKind::Async;
4907
0
    } else {
4908
0
      prop = setLocation(
4909
0
          range,
4910
0
          range,
4911
0
          new (context_) ESTree::IdentifierNode(asyncIdent_, nullptr, false));
4912
0
      doParsePropertyName = false;
4913
0
    }
4914
0
  } else if (checkAndEat(TokenKind::star)) {
4915
0
    special = SpecialKind::Generator;
4916
0
  } else if (isStatic && checkAndEat(TokenKind::l_brace)) {
4917
    // This is a static block.
4918
    // ES14.0 15.7
4919
    // ClassStaticBlock :
4920
    //   static { ClassStaticBlockBody }
4921
    //          ^
4922
0
    SMLoc braceLoc = tok_->getStartLoc();
4923
0
    ESTree::NodeList body;
4924
4925
0
    {
4926
      // ClassStaticBlockStatementList :
4927
      //   StatementList[~Yield, +Await, ~Return]opt
4928
      //   ^
4929
0
      llvh::SaveAndRestore oldParamYield{paramYield_, false};
4930
0
      llvh::SaveAndRestore oldParamAwait{paramAwait_, true};
4931
0
      if (!parseStatementList(
4932
0
              Param{},
4933
0
              TokenKind::r_brace,
4934
0
              /* parseDirectives */ false,
4935
0
              AllowImportExport::No,
4936
0
              body)) {
4937
0
        return None;
4938
0
      }
4939
0
    }
4940
0
    if (!eat(
4941
0
            TokenKind::r_brace,
4942
0
            JSLexer::GrammarContext::AllowRegExp,
4943
0
            "at end of static block",
4944
0
            "static block starts here",
4945
0
            braceLoc))
4946
0
      return None;
4947
4948
0
    return setLocation(
4949
0
        startLoc,
4950
0
        getPrevTokenEndLoc(),
4951
0
        new (context_) ESTree::StaticBlockNode(std::move(body)));
4952
0
  } else if (isStatic && staticIsPropertyName()) {
4953
    // This is the name of the property/method.
4954
    // We've already parsed 'static', but it must be used as the
4955
    // PropertyName and not as an indicator for a static function.
4956
0
    prop = setLocation(
4957
0
        startRange,
4958
0
        startRange,
4959
0
        new (context_) ESTree::IdentifierNode(staticIdent_, nullptr, false));
4960
0
    isStatic = false;
4961
0
    doParsePropertyName = false;
4962
0
  }
4963
4964
0
  ESTree::Node *variance = nullptr;
4965
0
#if HERMES_PARSE_FLOW
4966
0
  if (context_.getParseFlow() && check(TokenKind::plus, TokenKind::minus)) {
4967
0
    variance = setLocation(
4968
0
        tok_,
4969
0
        tok_,
4970
0
        new (context_) ESTree::VarianceNode(
4971
0
            check(TokenKind::plus) ? plusIdent_ : minusIdent_));
4972
0
    advance(JSLexer::GrammarContext::Type);
4973
0
  }
4974
0
#endif
4975
4976
0
  bool computed = false;
4977
0
  if (doParsePropertyName) {
4978
0
    if (check(TokenKind::private_identifier)) {
4979
0
      isPrivate = true;
4980
0
      prop = setLocation(
4981
0
          tok_,
4982
0
          tok_,
4983
0
          new (context_) ESTree::IdentifierNode(
4984
0
              tok_->getPrivateIdentifier(), nullptr, false));
4985
0
      advance();
4986
0
    } else {
4987
0
      computed = check(TokenKind::l_square);
4988
0
      auto optProp = parsePropertyName();
4989
0
      if (!optProp)
4990
0
        return None;
4991
0
      prop = *optProp;
4992
0
    }
4993
0
  }
4994
4995
  // Store the propName for comparisons, used for SyntaxErrors.
4996
0
  UniqueString *propName = nullptr;
4997
0
  if (auto *id = dyn_cast<ESTree::IdentifierNode>(prop)) {
4998
0
    propName = id->_name;
4999
0
  } else if (auto *str = dyn_cast<ESTree::StringLiteralNode>(prop)) {
5000
0
    propName = str->_value;
5001
0
  }
5002
5003
0
  bool isConstructor =
5004
0
      !isStatic && !computed && propName && propName->str() == "constructor";
5005
5006
0
  if (special == SpecialKind::None &&
5007
0
      !check(TokenKind::less, TokenKind::l_paren)) {
5008
    // Parse a class property, because this can't be a method definition.
5009
    // Attempt ASI after the fact, and continue on, letting the next iteration
5010
    // error if it wasn't actually a class property.
5011
    // FieldDefinition ;
5012
    //                 ^
5013
0
    ESTree::Node *typeAnnotation = nullptr;
5014
0
#if HERMES_PARSE_TS
5015
0
    if (context_.getParseTS() && checkAndEat(TokenKind::question)) {
5016
0
      optional = true;
5017
0
    }
5018
0
#endif
5019
0
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
5020
0
    if (context_.getParseTypes() && check(TokenKind::colon)) {
5021
0
      SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
5022
0
      auto optType = parseTypeAnnotation(annotStart);
5023
0
      if (!optType)
5024
0
        return None;
5025
0
      typeAnnotation = *optType;
5026
0
    }
5027
0
#endif
5028
0
    ESTree::Node *value = nullptr;
5029
0
    if (checkAndEat(TokenKind::equal)) {
5030
      // ClassElementName Initializer[opt]
5031
      //                  ^
5032
      // NOTE: This is technically non-compliant, but having yield/await in the
5033
      // field initializer doesn't make sense.
5034
      // See https://github.com/tc39/ecma262/issues/3333
5035
      // Do [~Yield, +Await, ~Return] as suggested and error in resolution.
5036
0
      llvh::SaveAndRestore<bool> saveParamYield{paramYield_, false};
5037
0
      llvh::SaveAndRestore<bool> saveParamAwait{paramAwait_, true};
5038
0
      auto optValue = parseAssignmentExpression();
5039
0
      if (!optValue)
5040
0
        return None;
5041
0
      value = *optValue;
5042
0
      if (declare) {
5043
0
        error(startRange, "Invalid 'declare' with initializer");
5044
0
      }
5045
0
    }
5046
    // ASI is allowed for separating class elements.
5047
0
    if (!eatSemi(true) && !typeAnnotation) {
5048
0
      errorExpected(
5049
0
          TokenKind::semi,
5050
0
          "after class property",
5051
0
          "start of class property",
5052
0
          startRange.Start);
5053
0
      return None;
5054
0
    }
5055
0
    if (isPrivate) {
5056
0
      if (accessibility) {
5057
0
        error(
5058
0
            startRange,
5059
0
            "An accessibility modifier cannot be used with a private identifier");
5060
0
      }
5061
0
      ESTree::Node *modifiers = nullptr;
5062
0
#if HERMES_PARSE_TS
5063
0
      if (context_.getParseTS()) {
5064
0
        modifiers = new (context_) ESTree::TSModifiersNode(nullptr, readonly);
5065
0
      }
5066
0
#endif
5067
0
      return setLocation(
5068
0
          prop,
5069
0
          getPrevTokenEndLoc(),
5070
0
          new (context_) ESTree::ClassPrivatePropertyNode(
5071
0
              prop,
5072
0
              value,
5073
0
              isStatic,
5074
0
              declare,
5075
0
              optional,
5076
0
              variance,
5077
0
              typeAnnotation,
5078
0
              modifiers));
5079
0
    }
5080
0
    ESTree::Node *modifiers = nullptr;
5081
0
#if HERMES_PARSE_TS
5082
0
    if (context_.getParseTS()) {
5083
0
      modifiers =
5084
0
          new (context_) ESTree::TSModifiersNode(accessibility, readonly);
5085
0
    }
5086
0
#endif
5087
0
    return setLocation(
5088
0
        startRange,
5089
0
        getPrevTokenEndLoc(),
5090
0
        new (context_) ESTree::ClassPropertyNode(
5091
0
            prop,
5092
0
            value,
5093
0
            computed,
5094
0
            isStatic,
5095
0
            declare,
5096
0
            optional,
5097
0
            variance,
5098
0
            typeAnnotation,
5099
0
            modifiers));
5100
0
  }
5101
5102
0
  if (declare) {
5103
0
    error(startRange, "Invalid 'declare' in class method");
5104
0
  }
5105
5106
0
  SMLoc funcExprStartLoc = tok_->getStartLoc();
5107
5108
0
  ESTree::Node *typeParams = nullptr;
5109
0
#if HERMES_PARSE_FLOW
5110
0
  if (context_.getParseFlow() && check(TokenKind::less)) {
5111
0
    auto optTypeParams = parseTypeParamsFlow();
5112
0
    if (!optTypeParams)
5113
0
      return None;
5114
0
    typeParams = *optTypeParams;
5115
0
  }
5116
0
#endif
5117
5118
  // (
5119
0
  if (!need(
5120
0
          TokenKind::l_paren,
5121
0
          "in method definition",
5122
0
          "start of method definition",
5123
0
          startLoc))
5124
0
    return None;
5125
0
  ESTree::NodeList args{};
5126
5127
0
  llvh::SaveAndRestore<bool> saveArgsAndBodyParamYield(
5128
0
      paramYield_,
5129
0
      special == SpecialKind::Generator ||
5130
0
          special == SpecialKind::AsyncGenerator);
5131
5132
0
  llvh::SaveAndRestore<bool> saveArgsAndBodyParamAwait(
5133
0
      paramAwait_,
5134
0
      special == SpecialKind::Async || special == SpecialKind::AsyncGenerator);
5135
5136
0
  if (!parseFormalParameters(Param{}, args))
5137
0
    return None;
5138
5139
0
  ESTree::Node *returnType = nullptr;
5140
0
#if HERMES_PARSE_FLOW || HERMES_PARSE_TS
5141
0
  if (context_.getParseTypes() && check(TokenKind::colon)) {
5142
0
    SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
5143
0
    auto optRet = parseReturnTypeAnnotation(annotStart);
5144
0
    if (!optRet)
5145
0
      return None;
5146
0
    returnType = *optRet;
5147
0
  }
5148
0
#endif
5149
5150
0
  if (!need(
5151
0
          TokenKind::l_brace,
5152
0
          "in method definition",
5153
0
          "start of method definition",
5154
0
          startLoc))
5155
0
    return None;
5156
5157
0
  auto optBody = parseFunctionBody(
5158
0
      ParamReturn,
5159
0
      eagerly,
5160
0
      saveArgsAndBodyParamYield.get(),
5161
0
      saveArgsAndBodyParamAwait.get(),
5162
0
      JSLexer::AllowRegExp,
5163
0
      true);
5164
0
  if (!optBody)
5165
0
    return None;
5166
5167
0
  auto *funcExpr = setLocation(
5168
0
      funcExprStartLoc,
5169
0
      optBody.getValue(),
5170
0
      new (context_) ESTree::FunctionExpressionNode(
5171
0
          nullptr,
5172
0
          std::move(args),
5173
0
          optBody.getValue(),
5174
0
          typeParams,
5175
0
          returnType,
5176
0
          /* predicate */ nullptr,
5177
0
          special == SpecialKind::Generator ||
5178
0
              special == SpecialKind::AsyncGenerator,
5179
0
          special == SpecialKind::Async ||
5180
0
              special == SpecialKind::AsyncGenerator));
5181
0
  assert(isStrictMode() && "parseClassElement should only be used for classes");
5182
0
  funcExpr->isMethodDefinition = true;
5183
5184
0
  if (special == SpecialKind::Get && funcExpr->_params.size() != 0) {
5185
0
    error(
5186
0
        {startLoc, funcExpr->getEndLoc()},
5187
0
        Twine("getter method must no one formal arguments, found ") +
5188
0
            Twine(funcExpr->_params.size()));
5189
0
  }
5190
5191
0
  if (special == SpecialKind::Set && funcExpr->_params.size() != 1) {
5192
0
    error(
5193
0
        {startLoc, funcExpr->getEndLoc()},
5194
0
        Twine("setter method must have exactly one formal argument, found ") +
5195
0
            Twine(funcExpr->_params.size()));
5196
0
  }
5197
5198
0
#if HERMES_PARSE_FLOW
5199
0
  if ((special == SpecialKind::Get || special == SpecialKind::Set) &&
5200
0
      typeParams != nullptr) {
5201
0
    error(
5202
0
        {startLoc, funcExpr->getEndLoc()},
5203
0
        "accessor method may not have type parameters");
5204
0
  }
5205
0
#endif
5206
5207
0
  if (isStatic && propName && propName->str() == "prototype") {
5208
    // ClassElement : static MethodDefinition
5209
    // It is a Syntax Error if PropName of MethodDefinition is "prototype".
5210
0
    error(
5211
0
        {startLoc, funcExpr->getEndLoc()},
5212
0
        "prototype method must not be static");
5213
0
    return None;
5214
0
  }
5215
5216
0
  UniqueString *kind = methodIdent_;
5217
0
  if (isConstructor) {
5218
0
    if (special != SpecialKind::None) {
5219
      // It is a Syntax Error if PropName of MethodDefinition is "constructor"
5220
      // and SpecialMethod of MethodDefinition is true.
5221
      // TODO: Account for generator methods in SpecialMethod here.
5222
0
      error(
5223
0
          {startLoc, funcExpr->getEndLoc()},
5224
0
          "constructor method must not be a getter or setter");
5225
0
      return None;
5226
0
    }
5227
0
    kind = constructorIdent_;
5228
0
  } else if (special == SpecialKind::Get) {
5229
0
    kind = getIdent_;
5230
0
  } else if (special == SpecialKind::Set) {
5231
0
    kind = setIdent_;
5232
0
  }
5233
5234
0
  if (isPrivate) {
5235
0
    prop = setLocation(
5236
0
        startLoc, prop, new (context_) ESTree::PrivateNameNode(prop));
5237
0
  }
5238
5239
0
  if (variance) {
5240
0
    error(variance->getSourceRange(), "Unexpected variance sigil");
5241
0
  }
5242
5243
0
  return setLocation(
5244
0
      startRange,
5245
0
      optBody.getValue(),
5246
0
      new (context_) ESTree::MethodDefinitionNode(
5247
0
          prop, funcExpr, kind, computed, isStatic));
5248
0
}
5249
5250
bool JSParserImpl::reparseArrowParameters(
5251
    ESTree::Node *node,
5252
    bool hasNewLine,
5253
    ESTree::NodeList &paramList,
5254
206k
    bool &isAsync) {
5255
  // Empty argument list "()".
5256
206k
  if (node->getParens() == 0 && isa<ESTree::CoverEmptyArgsNode>(node))
5257
0
    return true;
5258
5259
  // A single identifier without parens.
5260
206k
  if (node->getParens() == 0 && isa<ESTree::IdentifierNode>(node)) {
5261
206k
    paramList.push_back(*node);
5262
206k
    return validateBindingIdentifier(
5263
206k
        Param{},
5264
206k
        node->getSourceRange(),
5265
206k
        cast<ESTree::IdentifierNode>(node)->_name,
5266
206k
        TokenKind::identifier);
5267
206k
  }
5268
5269
0
  ESTree::NodeList nodeList{};
5270
5271
0
  if (auto *callNode = dyn_cast<ESTree::CallExpressionNode>(node)) {
5272
    // Async function parameters look like call expressions. For example:
5273
    // async(x,y)
5274
    // It must have no surrounding parens and the name must be 'async'.
5275
    // It must also not already be `async`, because the CallExpression
5276
    // determines whether it is `async`.
5277
    // It must not have a newline between 'async' and the parameters.
5278
    // Set `isAsync = true` to indicate that this was async.
5279
0
    auto *callee = dyn_cast<ESTree::IdentifierNode>(callNode->_callee);
5280
0
    if (!isAsync && callNode->getParens() == 0 && callee &&
5281
0
        callee->_name == asyncIdent_ && !hasNewLine) {
5282
0
      nodeList = std::move(callNode->_arguments);
5283
0
      isAsync = true;
5284
0
    } else {
5285
0
      error(node->getSourceRange(), "invalid arrow function parameter list");
5286
0
      return false;
5287
0
    }
5288
0
  } else {
5289
0
    if (node->getParens() != 1) {
5290
0
      error(node->getSourceRange(), "invalid arrow function parameter list");
5291
0
      return false;
5292
0
    }
5293
5294
0
    if (auto *seqNode = dyn_cast<ESTree::SequenceExpressionNode>(node)) {
5295
0
      nodeList = std::move(seqNode->_expressions);
5296
0
    } else {
5297
0
      node->clearParens();
5298
0
      nodeList.push_back(*node);
5299
0
    }
5300
0
  }
5301
5302
0
  llvh::SaveAndRestore<bool> oldParamAwait(paramAwait_, paramAwait_ || isAsync);
5303
5304
  // If the node has 0 parentheses, return true, otherwise print an error and
5305
  // return false.
5306
0
  auto checkParens = [this](ESTree::Node *n) {
5307
0
    if (n->getParens() == 0)
5308
0
      return true;
5309
5310
0
    error(n->getSourceRange(), "parentheses are not allowed around parameters");
5311
0
    return false;
5312
0
  };
5313
5314
0
  for (auto it = nodeList.begin(), e = nodeList.end(); it != e;) {
5315
0
    auto *expr = &*it;
5316
0
    it = nodeList.erase(it);
5317
5318
0
    if (!checkParens(expr))
5319
0
      continue;
5320
5321
0
    if (auto *CRE = dyn_cast<ESTree::CoverRestElementNode>(expr)) {
5322
0
      if (it != e)
5323
0
        error(expr->getSourceRange(), "rest parameter must be last");
5324
0
      else
5325
0
        paramList.push_back(*CRE->_rest);
5326
0
      continue;
5327
0
    }
5328
5329
0
    if (auto *spread = dyn_cast<ESTree::SpreadElementNode>(expr)) {
5330
      // async arrow heads are initially parsed as CallExpression,
5331
      // which means that Rest elements are parsed as SpreadElement.
5332
0
      if (it != e)
5333
0
        error(expr->getSourceRange(), "rest parameter must be last");
5334
0
      else
5335
0
        paramList.push_back(*new (context_)
5336
0
                                ESTree::RestElementNode(spread->_argument));
5337
0
      continue;
5338
0
    }
5339
5340
0
    if (isa<ESTree::CoverTrailingCommaNode>(expr)) {
5341
0
      assert(
5342
0
          it == e &&
5343
0
          "CoverTrailingCommaNode should have been only parsed last");
5344
      // Just skip it.
5345
0
      continue;
5346
0
    }
5347
5348
0
    ESTree::AssignmentExpressionNode *asn = nullptr;
5349
0
    ESTree::Node *init = nullptr;
5350
5351
    // If we encounter an initializer, unpack it.
5352
0
    if ((asn = dyn_cast<ESTree::AssignmentExpressionNode>(expr))) {
5353
0
      if (asn->_operator == getTokenIdent(TokenKind::equal)) {
5354
0
        expr = asn->_left;
5355
0
        init = asn->_right;
5356
5357
0
        if (!checkParens(expr))
5358
0
          continue;
5359
0
      }
5360
0
    }
5361
5362
0
    auto optParam = reparseAssignmentPattern(expr, true);
5363
0
    if (!optParam)
5364
0
      continue;
5365
0
    expr = *optParam;
5366
5367
0
    if (init) {
5368
0
      expr = setLocation(
5369
0
          asn, asn, new (context_) ESTree::AssignmentPatternNode(expr, init));
5370
0
    }
5371
5372
0
    if (auto *ident = dyn_cast<ESTree::IdentifierNode>(expr)) {
5373
0
      validateBindingIdentifier(
5374
0
          Param{},
5375
0
          ident->getSourceRange(),
5376
0
          ident->_name,
5377
0
          TokenKind::identifier);
5378
0
    }
5379
5380
0
    paramList.push_back(*expr);
5381
0
  }
5382
5383
0
  return true;
5384
0
}
5385
5386
Optional<ESTree::Node *> JSParserImpl::parseArrowFunctionExpression(
5387
    Param param,
5388
    ESTree::Node *leftExpr,
5389
    bool hasNewLine,
5390
    ESTree::Node *typeParams,
5391
    ESTree::Node *returnType,
5392
    ESTree::Node *predicate,
5393
    SMLoc startLoc,
5394
    AllowTypedArrowFunction allowTypedArrowFunction,
5395
206k
    bool forceAsync) {
5396
  // ArrowFunction : ArrowParameters [no line terminator] => ConciseBody.
5397
206k
  assert(
5398
206k
      check(TokenKind::equalgreater) && !lexer_.isNewLineBeforeCurrentToken() &&
5399
206k
      "ArrowFunctionExpression expects [no new line] '=>'");
5400
5401
206k
  llvh::SaveAndRestore<bool> argsParamAwait(paramAwait_, forceAsync);
5402
5403
206k
  if (!eat(
5404
206k
          TokenKind::equalgreater,
5405
206k
          JSLexer::GrammarContext::AllowRegExp,
5406
206k
          "in arrow function expression",
5407
206k
          "start of arrow function",
5408
206k
          startLoc))
5409
0
    return None;
5410
5411
206k
  bool isAsync = forceAsync;
5412
206k
  ESTree::NodeList paramList;
5413
206k
  if (!reparseArrowParameters(leftExpr, hasNewLine, paramList, isAsync))
5414
0
    return None;
5415
5416
206k
  SaveStrictModeAndSeenDirectives saveStrictModeAndSeenDirectives{this};
5417
206k
  ESTree::Node *body;
5418
206k
  bool expression;
5419
5420
206k
  llvh::SaveAndRestore<bool> oldParamYield(paramYield_, false);
5421
206k
  llvh::SaveAndRestore<bool> bodyParamAwait(paramAwait_, isAsync);
5422
206k
  if (check(TokenKind::l_brace)) {
5423
0
    auto optBody = parseFunctionBody(
5424
0
        Param{},
5425
0
        true,
5426
0
        oldParamYield.get(),
5427
0
        argsParamAwait.get(),
5428
0
        JSLexer::AllowDiv,
5429
0
        true);
5430
0
    if (!optBody)
5431
0
      return None;
5432
0
    body = *optBody;
5433
0
    expression = false;
5434
206k
  } else {
5435
    // It's possible to recurse onto parseAssignmentExpression directly
5436
    // and get stuck without a depth check if we don't have one here.
5437
206k
    CHECK_RECURSION;
5438
206k
    auto optConcise = parseAssignmentExpression(
5439
206k
        param.get(ParamIn),
5440
206k
        allowTypedArrowFunction,
5441
206k
        CoverTypedParameters::No,
5442
206k
        nullptr);
5443
206k
    if (!optConcise)
5444
0
      return None;
5445
206k
    body = *optConcise;
5446
206k
    expression = true;
5447
206k
  }
5448
5449
206k
  auto *arrow = new (context_) ESTree::ArrowFunctionExpressionNode(
5450
206k
      nullptr,
5451
206k
      std::move(paramList),
5452
206k
      body,
5453
206k
      typeParams,
5454
206k
      returnType,
5455
206k
      predicate,
5456
206k
      expression,
5457
206k
      isAsync);
5458
5459
206k
  return setLocation(startLoc, getPrevTokenEndLoc(), arrow);
5460
206k
}
5461
5462
Optional<ESTree::Node *> JSParserImpl::reparseAssignmentPattern(
5463
    ESTree::Node *node,
5464
44.7k
    bool inDecl) {
5465
44.7k
  if (!node->getParens()) {
5466
44.7k
    if (auto *AEN = dyn_cast<ESTree::ArrayExpressionNode>(node)) {
5467
44.7k
      return reparseArrayAsignmentPattern(AEN, inDecl);
5468
44.7k
    }
5469
2
    if (auto *OEN = dyn_cast<ESTree::ObjectExpressionNode>(node)) {
5470
0
      return reparseObjectAssignmentPattern(OEN, inDecl);
5471
0
    }
5472
2
    if (auto *ident = dyn_cast<ESTree::IdentifierNode>(node)) {
5473
      // Validate in this function to avoid validating in each branch of
5474
      // the conditions within the other reparse functions.
5475
      // Validation does not prevent progress of the parse here, so we can
5476
      // return node regardless of whether we failed to validate.
5477
1
      validateBindingIdentifier(
5478
1
          Param{},
5479
1
          ident->getSourceRange(),
5480
1
          ident->_name,
5481
1
          TokenKind::identifier);
5482
1
      return node;
5483
1
    }
5484
1
    if (isa<ESTree::PatternNode>(node)) {
5485
      // Pattern nodes validate their binding identifiers when they are
5486
      // initially parsed, no work to do here.
5487
0
      return node;
5488
0
    }
5489
1
#if HERMES_PARSE_FLOW
5490
1
    if (auto *cover = dyn_cast<ESTree::CoverTypedIdentifierNode>(node)) {
5491
0
      auto optAssn = reparseAssignmentPattern(cover->_left, inDecl);
5492
      // type may be nullptr, but the patterns may have null typeAnnotation.
5493
0
      auto *type = cover->_right;
5494
0
      if (!optAssn)
5495
0
        return None;
5496
0
      if (auto *apn = dyn_cast<ESTree::ArrayPatternNode>(*optAssn)) {
5497
0
        apn->_typeAnnotation = type;
5498
0
        return setLocation(cover, cover, apn);
5499
0
      }
5500
0
      if (auto *opn = dyn_cast<ESTree::ObjectPatternNode>(*optAssn)) {
5501
0
        opn->_typeAnnotation = type;
5502
0
        return setLocation(cover, cover, opn);
5503
0
      }
5504
0
      if (auto *id = dyn_cast<ESTree::IdentifierNode>(*optAssn)) {
5505
0
        id->_typeAnnotation = type;
5506
0
        id->_optional = cover->_optional;
5507
0
        return setLocation(cover, cover, id);
5508
0
      }
5509
0
    }
5510
1
    if (auto *typecast = dyn_cast<ESTree::TypeCastExpressionNode>(node)) {
5511
0
      auto optAssn = reparseAssignmentPattern(typecast->_expression, inDecl);
5512
0
      auto *type = typecast->_typeAnnotation;
5513
0
      if (!optAssn)
5514
0
        return None;
5515
0
      if (auto *apn = dyn_cast<ESTree::ArrayPatternNode>(*optAssn)) {
5516
0
        apn->_typeAnnotation = type;
5517
0
        return setLocation(apn, type, apn);
5518
0
      }
5519
0
      if (auto *opn = dyn_cast<ESTree::ObjectPatternNode>(*optAssn)) {
5520
0
        opn->_typeAnnotation = type;
5521
0
        return setLocation(opn, type, opn);
5522
0
      }
5523
0
      if (auto *id = dyn_cast<ESTree::IdentifierNode>(*optAssn)) {
5524
0
        id->_typeAnnotation = type;
5525
0
        return setLocation(id, type, id);
5526
0
      }
5527
0
    }
5528
1
#endif
5529
1
  }
5530
5531
1
  if (inDecl) {
5532
0
    error(node->getSourceRange(), "identifier or pattern expected");
5533
0
    return None;
5534
0
  }
5535
5536
1
  return node;
5537
1
}
5538
5539
Optional<ESTree::Node *> JSParserImpl::reparseArrayAsignmentPattern(
5540
    ESTree::ArrayExpressionNode *AEN,
5541
44.7k
    bool inDecl) {
5542
44.7k
  ESTree::NodeList elements{};
5543
5544
85.4k
  for (auto it = AEN->_elements.begin(), e = AEN->_elements.end(); it != e;) {
5545
40.6k
    ESTree::Node *elem = &*it++;
5546
40.6k
    AEN->_elements.remove(*elem);
5547
5548
    // Every element in the array assignment pattern is optional,
5549
    // because we can parse the Elision production.
5550
40.6k
    if (isa<ESTree::EmptyNode>(elem)) {
5551
0
      elements.push_back(*elem);
5552
0
      continue;
5553
0
    }
5554
5555
40.6k
    if (auto *spread = dyn_cast<ESTree::SpreadElementNode>(elem)) {
5556
0
      if (it != e || AEN->_trailingComma) {
5557
0
        error(spread->getSourceRange(), "rest element must be last");
5558
0
        continue;
5559
0
      }
5560
5561
0
      auto optSubPattern = reparseAssignmentPattern(spread->_argument, inDecl);
5562
0
      if (!optSubPattern)
5563
0
        continue;
5564
0
      elem = setLocation(
5565
0
          spread,
5566
0
          spread,
5567
0
          new (context_) ESTree::RestElementNode(*optSubPattern));
5568
40.6k
    } else {
5569
40.6k
      ESTree::AssignmentExpressionNode *asn = nullptr;
5570
40.6k
      ESTree::Node *init = nullptr;
5571
5572
      // If we encounter an initializer, unpack it.
5573
40.6k
      if (!elem->getParens()) {
5574
40.6k
        if ((asn = dyn_cast<ESTree::AssignmentExpressionNode>(elem))) {
5575
0
          if (asn->_operator == getTokenIdent(TokenKind::equal)) {
5576
0
            elem = asn->_left;
5577
0
            init = asn->_right;
5578
0
          }
5579
0
        }
5580
40.6k
      }
5581
5582
      // Reparse {...} or [...]
5583
40.6k
      auto optSubPattern = reparseAssignmentPattern(elem, inDecl);
5584
40.6k
      if (!optSubPattern)
5585
0
        continue;
5586
40.6k
      elem = *optSubPattern;
5587
5588
40.6k
      if (init) {
5589
0
        elem = setLocation(
5590
0
            asn, asn, new (context_) ESTree::AssignmentPatternNode(elem, init));
5591
0
      }
5592
40.6k
    }
5593
5594
40.6k
    elements.push_back(*elem);
5595
40.6k
  }
5596
5597
44.7k
  return setLocation(
5598
44.7k
      AEN->getStartLoc(),
5599
44.7k
      AEN->getEndLoc(),
5600
44.7k
      new (context_) ESTree::ArrayPatternNode(std::move(elements), nullptr));
5601
44.7k
}
5602
5603
Optional<ESTree::Node *> JSParserImpl::reparseObjectAssignmentPattern(
5604
    ESTree::ObjectExpressionNode *OEN,
5605
0
    bool inDecl) {
5606
0
  ESTree::NodeList elements{};
5607
5608
0
  for (auto it = OEN->_properties.begin(), e = OEN->_properties.end();
5609
0
       it != e;) {
5610
0
    auto *node = &*it++;
5611
0
    OEN->_properties.remove(*node);
5612
5613
0
    if (auto *spread = dyn_cast<ESTree::SpreadElementNode>(node)) {
5614
0
      if (it != e) {
5615
0
        error(spread->getSourceRange(), "rest property must be last");
5616
0
        continue;
5617
0
      }
5618
5619
      // NOTE: the spec says that AssignmentRestProperty cannot be another
5620
      // pattern (see
5621
      // https://www.ecma-international.org/ecma-262/9.0/index.html#sec-destructuring-assignment-static-semantics-early-errors)
5622
      // even though it would be logical.
5623
#if 0
5624
      auto optSubPattern = reparseAssignmentPattern(spread->_argument, inDecl);
5625
      if (!optSubPattern)
5626
        continue;
5627
      node = *optSubPattern;
5628
#else
5629
0
      node = spread->_argument;
5630
0
      if (inDecl) {
5631
0
        if (!isa<ESTree::IdentifierNode>(node)) {
5632
0
          error(
5633
0
              node->getSourceRange(), "identifier expected in parameter list");
5634
0
          continue;
5635
0
        }
5636
0
      }
5637
0
#endif
5638
0
      node = setLocation(
5639
0
          spread, spread, new (context_) ESTree::RestElementNode(node));
5640
0
    } else {
5641
0
      auto *propNode = cast<ESTree::PropertyNode>(node);
5642
5643
0
      if (propNode->_kind != initIdent_) {
5644
0
        error(
5645
0
            SourceErrorManager::combineIntoRange(
5646
0
                propNode->getStartLoc(), propNode->_key->getStartLoc()),
5647
0
            "invalid destructuring target");
5648
0
        continue;
5649
0
      }
5650
5651
0
      ESTree::Node *value = propNode->_value;
5652
0
      ESTree::Node *init = nullptr;
5653
0
      SMLoc endLoc = value->getEndLoc();
5654
5655
      // If we encounter an initializer, unpack it.
5656
0
      if (auto *asn = dyn_cast<ESTree::AssignmentExpressionNode>(value)) {
5657
0
        if (asn->_operator == getTokenIdent(TokenKind::equal)) {
5658
0
          value = asn->_left;
5659
0
          init = asn->_right;
5660
0
        }
5661
0
      } else if (
5662
0
          auto *coverInitializer =
5663
0
              dyn_cast<ESTree::CoverInitializerNode>(value)) {
5664
0
        assert(
5665
0
            isa<ESTree::IdentifierNode>(propNode->_key) &&
5666
0
            "CoverInitializedName must start with an identifier");
5667
        // Clone the key.
5668
0
        auto *ident = cast<ESTree::IdentifierNode>(propNode->_key);
5669
0
        value = new (context_) ESTree::IdentifierNode(
5670
0
            ident->_name, ident->_typeAnnotation, ident->_optional);
5671
0
        value->copyLocationFrom(propNode->_key);
5672
5673
0
        init = coverInitializer->_init;
5674
0
      }
5675
5676
      // Reparse {...} or [...]
5677
0
      auto optSubPattern = reparseAssignmentPattern(value, inDecl);
5678
0
      if (!optSubPattern)
5679
0
        continue;
5680
0
      value = *optSubPattern;
5681
5682
      // If we have an initializer, create an AssignmentPattern.
5683
0
      if (init) {
5684
0
        value = setLocation(
5685
0
            value,
5686
0
            endLoc,
5687
0
            new (context_) ESTree::AssignmentPatternNode(value, init));
5688
0
      }
5689
5690
0
      propNode->_value = value;
5691
0
    }
5692
5693
0
    elements.push_back(*node);
5694
0
  }
5695
5696
0
  auto *OP =
5697
0
      new (context_) ESTree::ObjectPatternNode(std::move(elements), nullptr);
5698
0
  OP->copyLocationFrom(OEN);
5699
0
  return OP;
5700
0
}
5701
5702
#if HERMES_PARSE_FLOW
5703
Optional<ESTree::Node *> JSParserImpl::tryParseTypedAsyncArrowFunction(
5704
0
    Param param) {
5705
0
  assert(context_.getParseFlow());
5706
0
  assert(check(asyncIdent_));
5707
0
  JSLexer::SavePoint savePoint{&lexer_};
5708
0
  SMLoc start = advance().Start;
5709
5710
0
  ESTree::Node *leftExpr = nullptr;
5711
0
  bool hasNewLine = false;
5712
0
  ESTree::Node *typeParams = nullptr;
5713
0
  ESTree::Node *returnType = nullptr;
5714
0
  ESTree::Node *predicate = nullptr;
5715
0
  {
5716
0
    SourceErrorManager::SaveAndSuppressMessages suppress{
5717
0
        &sm_, Subsystem::Parser};
5718
0
    if (check(TokenKind::less)) {
5719
0
      auto optTypeParams = parseTypeParamsFlow();
5720
0
      if (!optTypeParams) {
5721
0
        savePoint.restore();
5722
0
        return None;
5723
0
      }
5724
0
      typeParams = *optTypeParams;
5725
0
    }
5726
5727
0
    if (!check(TokenKind::l_paren)) {
5728
0
      savePoint.restore();
5729
0
      return None;
5730
0
    }
5731
5732
0
    hasNewLine = lexer_.isNewLineBeforeCurrentToken();
5733
0
    auto optLeftExpr =
5734
0
        parseConditionalExpression(param, CoverTypedParameters::Yes);
5735
0
    if (!optLeftExpr) {
5736
0
      savePoint.restore();
5737
0
      return None;
5738
0
    }
5739
0
    leftExpr = *optLeftExpr;
5740
5741
0
    if (check(TokenKind::colon)) {
5742
0
      SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
5743
0
      if (!check(checksIdent_)) {
5744
0
        auto optType = parseReturnTypeAnnotationFlow(
5745
0
            annotStart, AllowAnonFunctionType::No);
5746
0
        if (!optType) {
5747
0
          savePoint.restore();
5748
0
          return None;
5749
0
        }
5750
0
        returnType = *optType;
5751
0
      }
5752
0
      if (check(checksIdent_)) {
5753
0
        auto optPredicate = parsePredicateFlow();
5754
0
        if (!optPredicate) {
5755
0
          savePoint.restore();
5756
0
          return None;
5757
0
        }
5758
0
        predicate = *optPredicate;
5759
0
      }
5760
0
    }
5761
5762
0
    if (!check(TokenKind::equalgreater)) {
5763
0
      savePoint.restore();
5764
0
      return None;
5765
0
    }
5766
0
  }
5767
5768
0
  return parseArrowFunctionExpression(
5769
0
      param,
5770
0
      leftExpr,
5771
0
      hasNewLine,
5772
0
      typeParams,
5773
0
      returnType,
5774
0
      predicate,
5775
0
      start,
5776
0
      AllowTypedArrowFunction::Yes,
5777
0
      /* forceAsync */ true);
5778
0
}
5779
#endif
5780
5781
Optional<ESTree::Node *> JSParserImpl::parseAssignmentExpression(
5782
    Param param,
5783
    AllowTypedArrowFunction allowTypedArrowFunction,
5784
    CoverTypedParameters coverTypedParameters,
5785
6.60M
    ESTree::Node *typeParams) {
5786
6.60M
  struct State {
5787
6.60M
    SMLoc leftStartLoc = {};
5788
6.60M
    Optional<ESTree::Node *> optLeftExpr = llvh::None;
5789
6.60M
    bool hasNewLine = false;
5790
6.60M
    UniqueString *op = nullptr;
5791
6.60M
    SMLoc debugLoc = {};
5792
5793
6.61M
    explicit State() {}
5794
6.60M
  };
5795
5796
6.60M
  auto parseHelper = [this](
5797
6.60M
                         State &state,
5798
6.60M
                         Param param,
5799
6.60M
                         AllowTypedArrowFunction allowTypedArrowFunction,
5800
6.60M
                         CoverTypedParameters coverTypedParameters,
5801
6.61M
                         ESTree::Node *typeParams) -> Optional<ESTree::Node *> {
5802
    // Check for yield, which may be lexed as a reserved word, but only in
5803
    // strict mode.
5804
6.61M
    if (paramYield_ && check(TokenKind::rw_yield, TokenKind::identifier) &&
5805
6.61M
        tok_->getResWordOrIdentifier() == yieldIdent_) {
5806
0
      auto optYieldExpr = parseYieldExpression(param.get(ParamIn));
5807
0
      if (!optYieldExpr)
5808
0
        return None;
5809
0
      ESTree::YieldExpressionNode *yieldExpr = *optYieldExpr;
5810
0
      if (yieldExpr->_argument && !checkEndAssignmentExpression()) {
5811
0
        error(tok_->getStartLoc(), "unexpected token after yield expression");
5812
0
        return None;
5813
0
      }
5814
0
      return yieldExpr;
5815
0
    }
5816
5817
6.61M
    SMLoc startLoc = tok_->getStartLoc();
5818
6.61M
    bool forceAsync = false;
5819
6.61M
    if (check(asyncIdent_)) {
5820
125
      OptValue<TokenKind> optNext = lexer_.lookahead1(TokenKind::identifier);
5821
125
      if (optNext.hasValue() && *optNext == TokenKind::identifier) {
5822
0
        forceAsync = true;
5823
0
      }
5824
125
#if HERMES_PARSE_FLOW
5825
125
      if (context_.getParseFlow() && optNext.hasValue() &&
5826
125
          (*optNext == TokenKind::less || *optNext == TokenKind::l_paren)) {
5827
0
        auto optAsyncArrow = tryParseTypedAsyncArrowFunction(param);
5828
0
        if (optAsyncArrow.hasValue()) {
5829
0
          return *optAsyncArrow;
5830
0
        }
5831
0
      }
5832
125
#endif
5833
125
    }
5834
5835
6.61M
#if HERMES_PARSE_FLOW
5836
6.61M
    if (context_.getParseFlow() &&
5837
6.61M
        allowTypedArrowFunction == AllowTypedArrowFunction::Yes &&
5838
6.61M
        !typeParams && check(TokenKind::less)) {
5839
0
      JSLexer::SavePoint savePoint{&lexer_};
5840
      // Suppress messages from the parser while still displaying lexer
5841
      // messages.
5842
0
      CollectMessagesRAII collect{&sm_, true};
5843
      // Do as the flow parser does due to JSX ambiguities.
5844
      // First we try and parse as an assignment expression disallowing
5845
      // typed arrow functions. If that fails, then try again while allowing
5846
      // typed arrow functions and attach the type parameters after the fact.
5847
0
      auto optAssign = parseAssignmentExpression(
5848
0
          param,
5849
0
          AllowTypedArrowFunction::No,
5850
0
          CoverTypedParameters::No,
5851
0
          nullptr);
5852
0
      if (optAssign) {
5853
        // That worked, so just return it directly.
5854
0
        collect.setDiscardMessages(false);
5855
0
        return *optAssign;
5856
0
      } else {
5857
        // Consume the type parameters and try again.
5858
0
        savePoint.restore();
5859
0
        auto optTypeParams = parseTypeParamsFlow();
5860
        // Type parameters must be followed by a '(' to be meaningful.
5861
0
        if (optTypeParams && check(TokenKind::l_paren)) {
5862
0
          typeParams = *optTypeParams;
5863
0
          optAssign = parseAssignmentExpression(
5864
0
              param,
5865
0
              AllowTypedArrowFunction::Yes,
5866
0
              CoverTypedParameters::No,
5867
0
              typeParams);
5868
0
          if (optAssign) {
5869
            // We've got the arrow function now, return it directly.
5870
0
            return *optAssign;
5871
0
          } else {
5872
            // That's everything we can try.
5873
0
            error(
5874
0
                typeParams->getSourceRange(),
5875
0
                "type parameters must be used in an arrow function expression");
5876
0
            return None;
5877
0
          }
5878
0
        } else {
5879
          // Invalid type params, and also invalid JSX. Bail.
5880
0
          savePoint.restore();
5881
0
        }
5882
0
      }
5883
0
    }
5884
6.61M
#endif
5885
5886
6.61M
    state.leftStartLoc = tok_->getStartLoc();
5887
6.61M
    state.hasNewLine = lexer_.isNewLineBeforeCurrentToken();
5888
6.61M
    state.optLeftExpr = parseConditionalExpression(param, coverTypedParameters);
5889
6.61M
    if (!state.optLeftExpr)
5890
4.12k
      return None;
5891
5892
6.61M
    ESTree::Node *returnType = nullptr;
5893
6.61M
    ESTree::Node *predicate = nullptr;
5894
6.61M
#if HERMES_PARSE_FLOW
5895
6.61M
    if (context_.getParseFlow()) {
5896
0
      if (allowTypedArrowFunction == AllowTypedArrowFunction::Yes &&
5897
0
          ((*state.optLeftExpr)->getParens() != 0 ||
5898
0
           isa<ESTree::CoverEmptyArgsNode>(*state.optLeftExpr)) &&
5899
0
          check(TokenKind::colon)) {
5900
0
        JSLexer::SavePoint savePoint{&lexer_};
5901
        // Defer our decision on whether to show or suppress messages for this
5902
        // next section.
5903
        // If we are unsuccessful during the parse, it can mean that we need to
5904
        // start parsing JSX children inside tags, instead of function type
5905
        // parameters. We need to suppress lexer messages because the lexing
5906
        // rules inside JSX are quite different from JS/Flow. For example: x ?
5907
        // (1) : <tag>#{foo}</tag>;
5908
        //         ^
5909
        // and
5910
        // x ? (1) : <tag>"</tag>;
5911
        //         ^
5912
        // must be able to handle the lexer errors that would occur if we lexed
5913
        // the inside of the JSX tags as JS.
5914
0
        CollectMessagesRAII collect{&sm_, true};
5915
0
        SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
5916
0
        bool startsWithPredicate = check(checksIdent_);
5917
0
        auto optType = startsWithPredicate
5918
0
            ? llvh::None
5919
0
            : parseReturnTypeAnnotationFlow(
5920
0
                  annotStart, AllowAnonFunctionType::No);
5921
0
        if (optType)
5922
0
          returnType = *optType;
5923
0
        if (optType || startsWithPredicate) {
5924
0
          if (check(TokenKind::equalgreater)) {
5925
0
            assert(
5926
0
                !startsWithPredicate && "no returnType if startsWithPredicate");
5927
            // Done parsing the return type and predicate.
5928
            // Successful parse, show any messages that the lexer emitted.
5929
0
            collect.setDiscardMessages(false);
5930
0
          } else if (check(checksIdent_)) {
5931
0
            auto optPred = parsePredicateFlow();
5932
0
            if (optPred && check(TokenKind::equalgreater)) {
5933
              // Done parsing the return type and predicate.
5934
0
              predicate = *optPred;
5935
              // Successful parse, show any messages that the lexer emitted.
5936
0
              collect.setDiscardMessages(false);
5937
0
            } else {
5938
0
              savePoint.restore();
5939
0
            }
5940
0
          } else {
5941
0
            savePoint.restore();
5942
0
          }
5943
0
        } else {
5944
0
          savePoint.restore();
5945
0
        }
5946
0
      }
5947
0
    }
5948
6.61M
#endif
5949
5950
6.61M
#if HERMES_PARSE_TS
5951
6.61M
    if (context_.getParseTS()) {
5952
      // Separate logic for TS parsing here, because the semantics don't
5953
      // require as much complexity as Flow due to a lack of predicates.
5954
0
      if (allowTypedArrowFunction == AllowTypedArrowFunction::Yes &&
5955
0
          ((*state.optLeftExpr)->getParens() != 0 ||
5956
0
           isa<ESTree::CoverEmptyArgsNode>(*state.optLeftExpr)) &&
5957
0
          check(TokenKind::colon)) {
5958
0
        JSLexer::SavePoint savePoint{&lexer_};
5959
        // Defer our decision on whether to show or suppress messages for this
5960
        // next section.
5961
        // If we are unsuccessful during the parse, it can mean that we need to
5962
        // start parsing JSX children inside tags, instead of function type
5963
        // parameters. We need to suppress lexer messages because the lexing
5964
        // rules inside JSX are quite different from TS. For example: x ? (1) :
5965
        // <tag>#{foo}</tag>;
5966
        //         ^
5967
        // and
5968
        // x ? (1) : <tag>"</tag>;
5969
        //         ^
5970
        // must be able to handle the lexer errors that would occur if we lexed
5971
        // the inside of the JSX tags as JS.
5972
0
        CollectMessagesRAII collect{&sm_, true};
5973
0
        SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
5974
0
        auto optType = parseTypeAnnotationTS(annotStart);
5975
0
        if (optType)
5976
0
          returnType = *optType;
5977
0
        if (optType) {
5978
0
          if (check(TokenKind::equalgreater)) {
5979
            // Done parsing the return type.
5980
            // Successful parse, show any messages that the lexer emitted.
5981
0
            collect.setDiscardMessages(false);
5982
0
          } else {
5983
0
            savePoint.restore();
5984
0
          }
5985
0
        } else {
5986
0
          savePoint.restore();
5987
0
        }
5988
0
      }
5989
0
    }
5990
5991
6.61M
#endif
5992
5993
    // Check for ArrowFunction.
5994
    //   ArrowFunction : ArrowParameters [no line terminator] => ConciseBody.
5995
    //   AsyncArrowFunction :
5996
    //   async [no line terminator] ArrowParameters [no line terminator] =>
5997
    //   ConciseBody.
5998
6.61M
    if (check(TokenKind::equalgreater) &&
5999
6.61M
        !lexer_.isNewLineBeforeCurrentToken()) {
6000
206k
      return parseArrowFunctionExpression(
6001
206k
          param,
6002
206k
          *state.optLeftExpr,
6003
206k
          state.hasNewLine,
6004
206k
          typeParams,
6005
206k
          returnType,
6006
206k
          predicate,
6007
206k
          typeParams ? typeParams->getStartLoc() : startLoc,
6008
206k
          allowTypedArrowFunction,
6009
206k
          forceAsync);
6010
206k
    }
6011
6012
6.40M
#if HERMES_PARSE_FLOW
6013
6.40M
    if (typeParams) {
6014
0
      errorExpected(
6015
0
          TokenKind::equalgreater,
6016
0
          "in generic arrow function",
6017
0
          "start of function",
6018
0
          typeParams->getStartLoc());
6019
0
      return None;
6020
0
    }
6021
6.40M
#endif
6022
6023
6.40M
    if (!checkAssign())
6024
6.39M
      return *state.optLeftExpr;
6025
6026
    // Check for destructuring assignment.
6027
9.27k
    if (check(TokenKind::equal) &&
6028
9.27k
        (isa<ESTree::ArrayExpressionNode>(*state.optLeftExpr) ||
6029
9.14k
         isa<ESTree::ObjectExpressionNode>(*state.optLeftExpr))) {
6030
4.18k
      state.optLeftExpr = reparseAssignmentPattern(*state.optLeftExpr, false);
6031
4.18k
      if (!state.optLeftExpr)
6032
0
        return None;
6033
4.18k
    }
6034
6035
9.27k
    state.op = getTokenIdent(tok_->getKind());
6036
9.27k
    state.debugLoc = advance().Start;
6037
9.27k
    return nullptr;
6038
9.27k
  };
6039
6040
6.60M
  llvh::SmallVector<State, 2> stack;
6041
6042
6.60M
  stack.emplace_back();
6043
6.60M
  auto optRes = parseHelper(
6044
6.60M
      stack.back(),
6045
6.60M
      param,
6046
6.60M
      allowTypedArrowFunction,
6047
6.60M
      coverTypedParameters,
6048
6.60M
      typeParams);
6049
6050
6.61M
  for (;;) {
6051
6.61M
    if (!optRes)
6052
4.12k
      return None;
6053
6.61M
    if (!stack.back().op) {
6054
6.60M
      stack.pop_back();
6055
6.60M
      break;
6056
6.60M
    }
6057
9.27k
    if (stack.size() > ESTree::MAX_NESTED_ASSIGNMENTS) {
6058
0
      recursionDepthExceeded();
6059
0
      return None;
6060
0
    }
6061
9.27k
    stack.emplace_back();
6062
9.27k
    optRes = parseHelper(
6063
9.27k
        stack.back(),
6064
9.27k
        param,
6065
9.27k
        AllowTypedArrowFunction::Yes,
6066
9.27k
        CoverTypedParameters::No,
6067
9.27k
        nullptr);
6068
9.27k
  }
6069
6070
6.60M
  assert(optRes.getValue() != nullptr);
6071
6072
6.61M
  while (!stack.empty()) {
6073
9.27k
    if (!checkEndAssignmentExpression()) {
6074
      // Note: We don't assert the valid end of an AssignmentExpression here
6075
      // because we do not know yet whether the entire file is well-formed.
6076
      // This check errors here to ensure that we still catch missing elements
6077
      // in `checkEndAssignmentExpression` while allowing us to avoid actually
6078
      // asserting and crashing.
6079
2
      error(
6080
2
          tok_->getStartLoc(), "unexpected token after assignment expression");
6081
2
      return None;
6082
2
    }
6083
9.27k
    auto &top = stack.back();
6084
9.27k
    optRes = setLocation(
6085
9.27k
        top.leftStartLoc,
6086
9.27k
        getPrevTokenEndLoc(),
6087
9.27k
        top.debugLoc,
6088
9.27k
        new (context_) ESTree::AssignmentExpressionNode(
6089
9.27k
            top.op, top.optLeftExpr.getValue(), optRes.getValue()));
6090
9.27k
    stack.pop_back();
6091
9.27k
  }
6092
6093
6.60M
  return optRes.getValue();
6094
6.60M
}
6095
6096
Optional<ESTree::Node *> JSParserImpl::parseExpression(
6097
    Param param,
6098
1.91M
    CoverTypedParameters coverTypedParameters) {
6099
1.91M
  SMLoc startLoc = tok_->getStartLoc();
6100
1.91M
  auto optExpr = parseAssignmentExpression(
6101
1.91M
      param, AllowTypedArrowFunction::Yes, coverTypedParameters, nullptr);
6102
1.91M
  if (!optExpr)
6103
3.24k
    return None;
6104
6105
1.91M
  if (!check(TokenKind::comma))
6106
1.91M
    return optExpr.getValue();
6107
6108
402
  ESTree::NodeList exprList;
6109
402
  exprList.push_back(*optExpr.getValue());
6110
6111
1.95M
  while (check(TokenKind::comma)) {
6112
    // Eat the ",".
6113
1.95M
    auto commaRng = advance();
6114
6115
    // CoverParenthesizedExpressionAndArrowParameterList: (Expression ,)
6116
1.95M
    if (check(TokenKind::r_paren)) {
6117
0
      auto *coverNode = setLocation(
6118
0
          commaRng,
6119
0
          tok_->getStartLoc(),
6120
0
          new (context_) ESTree::CoverTrailingCommaNode());
6121
0
      exprList.push_back(*coverNode);
6122
0
      break;
6123
0
    }
6124
6125
1.95M
    ESTree::Node *expr2;
6126
6127
1.95M
    if (check(TokenKind::dotdotdot)) {
6128
0
      auto optRest = parseBindingRestElement(param);
6129
0
      if (!optRest)
6130
0
        return None;
6131
0
      expr2 = setLocation(
6132
0
          *optRest,
6133
0
          *optRest,
6134
0
          new (context_) ESTree::CoverRestElementNode(*optRest));
6135
1.95M
    } else {
6136
1.95M
      auto optExpr2 = parseAssignmentExpression(param);
6137
1.95M
      if (!optExpr2)
6138
2
        return None;
6139
1.95M
      expr2 = *optExpr2;
6140
1.95M
    }
6141
6142
1.95M
    exprList.push_back(*expr2);
6143
1.95M
  }
6144
6145
400
  return setLocation(
6146
400
      startLoc,
6147
400
      getPrevTokenEndLoc(),
6148
400
      new (context_) ESTree::SequenceExpressionNode(std::move(exprList)));
6149
402
}
6150
6151
0
Optional<ESTree::StringLiteralNode *> JSParserImpl::parseFromClause() {
6152
0
  SMLoc startLoc = tok_->getStartLoc();
6153
6154
0
  if (!checkAndEat(fromIdent_)) {
6155
0
    error(startLoc, "'from' expected");
6156
0
    return None;
6157
0
  }
6158
6159
0
  if (!need(
6160
0
          TokenKind::string_literal,
6161
0
          "after 'from'",
6162
0
          "location of 'from'",
6163
0
          startLoc)) {
6164
0
    return None;
6165
0
  }
6166
6167
0
  auto *source = setLocation(
6168
0
      tok_,
6169
0
      tok_,
6170
0
      new (context_) ESTree::StringLiteralNode(tok_->getStringLiteral()));
6171
6172
0
  advance();
6173
0
  return source;
6174
0
}
6175
6176
0
bool JSParserImpl::parseAssertClause(ESTree::NodeList &attributes) {
6177
0
  assert(check(assertIdent_));
6178
0
  SMLoc start = advance().Start;
6179
6180
  // assert { }
6181
  // assert { AssertEntries ,[opt] }
6182
  //        ^
6183
6184
0
  if (!eat(
6185
0
          TokenKind::l_brace,
6186
0
          JSLexer::GrammarContext::AllowRegExp,
6187
0
          "in import assertion",
6188
0
          "start of assertion",
6189
0
          start))
6190
0
    return false;
6191
6192
0
  while (!check(TokenKind::r_brace)) {
6193
    // AssertionKey : StringLiteral
6194
    // ^
6195
0
    ESTree::Node *key = nullptr;
6196
0
    if (check(TokenKind::string_literal)) {
6197
0
      key = setLocation(
6198
0
          tok_,
6199
0
          tok_,
6200
0
          new (context_) ESTree::StringLiteralNode(tok_->getStringLiteral()));
6201
0
      advance();
6202
0
    } else {
6203
0
      if (!need(
6204
0
              TokenKind::identifier,
6205
0
              "in import assertion",
6206
0
              "start of assertion",
6207
0
              start))
6208
0
        return false;
6209
6210
0
      key = setLocation(
6211
0
          tok_,
6212
0
          tok_,
6213
0
          new (context_)
6214
0
              ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
6215
0
      advance();
6216
0
    }
6217
6218
0
    if (!eat(
6219
0
            TokenKind::colon,
6220
0
            JSLexer::GrammarContext::AllowRegExp,
6221
0
            "in import assertion",
6222
0
            "start of assertion",
6223
0
            start))
6224
0
      return false;
6225
6226
    // AssertionKey : StringLiteral
6227
    //                ^
6228
6229
0
    if (!need(
6230
0
            TokenKind::string_literal,
6231
0
            "in import assertion",
6232
0
            "start of assertion",
6233
0
            start))
6234
0
      return false;
6235
6236
0
    ESTree::Node *value = setLocation(
6237
0
        tok_,
6238
0
        tok_,
6239
0
        new (context_) ESTree::StringLiteralNode(tok_->getStringLiteral()));
6240
0
    advance();
6241
0
    attributes.push_back(*setLocation(
6242
0
        key, value, new (context_) ESTree::ImportAttributeNode(key, value)));
6243
6244
0
    if (!checkAndEat(TokenKind::comma))
6245
0
      break;
6246
0
  }
6247
6248
  // assert { AssertEntries ,[opt] }
6249
  //                               ^
6250
6251
0
  if (!eat(
6252
0
          TokenKind::r_brace,
6253
0
          JSLexer::GrammarContext::AllowRegExp,
6254
0
          "in import assertion",
6255
0
          "start of assertion",
6256
0
          start))
6257
0
    return false;
6258
6259
0
  return true;
6260
0
}
6261
6262
Optional<ESTree::ImportDeclarationNode *>
6263
0
JSParserImpl::parseImportDeclaration() {
6264
0
  assert(
6265
0
      check(TokenKind::rw_import) &&
6266
0
      "import declaration must start with 'import'");
6267
0
  SMLoc startLoc = advance().Start;
6268
6269
0
  if (check(TokenKind::string_literal)) {
6270
    // import ModuleSpecifier ;
6271
    // If the first token is a string literal, there are no specifiers,
6272
    // so the import clause should not be parsed.
6273
0
    auto *source = setLocation(
6274
0
        tok_,
6275
0
        tok_,
6276
0
        new (context_) ESTree::StringLiteralNode(tok_->getStringLiteral()));
6277
0
    advance();
6278
6279
0
    ESTree::NodeList attributes{};
6280
0
    if (check(assertIdent_) && !lexer_.isNewLineBeforeCurrentToken()) {
6281
0
      if (!parseAssertClause(attributes))
6282
0
        return None;
6283
0
    }
6284
6285
0
    if (!eatSemi()) {
6286
0
      return None;
6287
0
    }
6288
6289
0
    return setLocation(
6290
0
        startLoc,
6291
0
        getPrevTokenEndLoc(),
6292
0
        new (context_) ESTree::ImportDeclarationNode(
6293
0
            {}, source, std::move(attributes), valueIdent_));
6294
0
  }
6295
6296
0
  ESTree::NodeList specifiers;
6297
0
  auto optKind = parseImportClause(specifiers);
6298
0
  if (!optKind)
6299
0
    return None;
6300
0
  UniqueString *kind = *optKind;
6301
6302
0
  auto optFromClause = parseFromClause();
6303
0
  if (!optFromClause) {
6304
0
    return None;
6305
0
  }
6306
6307
0
  ESTree::NodeList attributes{};
6308
0
  if (check(assertIdent_) && !lexer_.isNewLineBeforeCurrentToken()) {
6309
0
    if (!parseAssertClause(attributes))
6310
0
      return None;
6311
0
  }
6312
6313
0
  if (!eatSemi()) {
6314
0
    return None;
6315
0
  }
6316
6317
0
  return setLocation(
6318
0
      startLoc,
6319
0
      getPrevTokenEndLoc(),
6320
0
      new (context_) ESTree::ImportDeclarationNode(
6321
0
          std::move(specifiers), *optFromClause, std::move(attributes), kind));
6322
0
}
6323
6324
Optional<UniqueString *> JSParserImpl::parseImportClause(
6325
0
    ESTree::NodeList &specifiers) {
6326
0
  SMLoc startLoc = tok_->getStartLoc();
6327
6328
0
  UniqueString *kind = valueIdent_;
6329
0
  SMRange kindRange{};
6330
0
#if HERMES_PARSE_FLOW
6331
0
  if (context_.getParseFlow()) {
6332
0
    if (checkN(typeIdent_, TokenKind::rw_typeof)) {
6333
0
      kind = tok_->getResWordOrIdentifier();
6334
0
      kindRange = advance();
6335
0
    }
6336
0
  }
6337
0
#endif
6338
0
#if HERMES_PARSE_TS
6339
0
  if (context_.getParseTS()) {
6340
0
    if (checkN(typeIdent_)) {
6341
0
      kind = tok_->getResWordOrIdentifier();
6342
0
      kindRange = advance();
6343
0
    }
6344
0
  }
6345
0
#endif
6346
6347
0
  if (check(TokenKind::identifier)) {
6348
0
    if (check(fromIdent_) && kind == typeIdent_) {
6349
      // Not actually a type import, just import default with the name 'type'.
6350
0
      kind = valueIdent_;
6351
0
      auto *defaultBinding = setLocation(
6352
0
          kindRange,
6353
0
          kindRange,
6354
0
          new (context_) ESTree::IdentifierNode(typeIdent_, nullptr, false));
6355
0
      specifiers.push_back(*setLocation(
6356
0
          defaultBinding,
6357
0
          defaultBinding,
6358
0
          new (context_) ESTree::ImportDefaultSpecifierNode(defaultBinding)));
6359
0
    } else {
6360
      // ImportedDefaultBinding
6361
      // ImportedDefaultBinding , NameSpaceImport
6362
      // ImportedDefaultBinding , NamedImports
6363
0
      auto optDefaultBinding = parseBindingIdentifier(Param{});
6364
0
      if (!optDefaultBinding) {
6365
0
        errorExpected(
6366
0
            TokenKind::identifier,
6367
0
            "in import clause",
6368
0
            "start of import clause",
6369
0
            startLoc);
6370
0
        return None;
6371
0
      }
6372
0
      ESTree::IdentifierNode *defaultBinding = *optDefaultBinding;
6373
0
      specifiers.push_back(*setLocation(
6374
0
          defaultBinding,
6375
0
          defaultBinding,
6376
0
          new (context_) ESTree::ImportDefaultSpecifierNode(defaultBinding)));
6377
0
    }
6378
0
    if (!checkAndEat(TokenKind::comma)) {
6379
      // If there was no comma, there's no more bindings to parse,
6380
      // so return immediately.
6381
0
      return kind;
6382
0
    }
6383
0
  }
6384
6385
  // At this point, either:
6386
  // - the ImportedDefaultBinding was parsed and had a comma after it
6387
  // - there was no ImportedDefaultBinding and we simply continue
6388
6389
0
  if (check(TokenKind::star)) {
6390
    // NameSpaceImport
6391
0
    auto optNsImport = parseNameSpaceImport();
6392
0
    if (!optNsImport) {
6393
0
      return None;
6394
0
    }
6395
0
    specifiers.push_back(*optNsImport.getValue());
6396
0
    return kind;
6397
0
  }
6398
6399
  // NamedImports is the only remaining possibility.
6400
0
  if (!need(
6401
0
          TokenKind::l_brace,
6402
0
          "in import specifier clause",
6403
0
          "location of import specifiers",
6404
0
          startLoc)) {
6405
0
    return kind;
6406
0
  }
6407
6408
0
  if (!parseNamedImports(specifiers))
6409
0
    return None;
6410
0
  return kind;
6411
0
}
6412
6413
0
Optional<ESTree::Node *> JSParserImpl::parseNameSpaceImport() {
6414
0
  assert(check(TokenKind::star) && "import namespace must start with *");
6415
6416
0
  SMLoc startLoc = advance().Start;
6417
0
  if (!checkAndEat(asIdent_)) {
6418
0
    error(tok_->getStartLoc(), "'as' expected");
6419
0
    return None;
6420
0
  }
6421
6422
0
  auto optLocal = parseBindingIdentifier(Param{});
6423
0
  if (!optLocal) {
6424
0
    errorExpected(
6425
0
        TokenKind::identifier,
6426
0
        "in namespace import",
6427
0
        "location of namespace import",
6428
0
        startLoc);
6429
0
    return None;
6430
0
  }
6431
6432
0
  return setLocation(
6433
0
      startLoc,
6434
0
      *optLocal,
6435
0
      new (context_) ESTree::ImportNamespaceSpecifierNode(*optLocal));
6436
0
}
6437
6438
0
bool JSParserImpl::parseNamedImports(ESTree::NodeList &specifiers) {
6439
0
  assert(check(TokenKind::l_brace) && "named imports must start with {");
6440
0
  SMLoc startLoc = advance().Start;
6441
6442
  // BoundNames to check for duplicate entries in ImportDeclaration.
6443
  // Values are the actual IdentifierNodes, used for error reporting.
6444
0
  llvh::DenseMap<UniqueString *, ESTree::IdentifierNode *> boundNames{};
6445
6446
0
  while (!check(TokenKind::r_brace)) {
6447
0
    auto optSpecifier = parseImportSpecifier(startLoc);
6448
0
    if (!optSpecifier) {
6449
0
      return false;
6450
0
    }
6451
6452
    // Check if the bound name was duplicated.
6453
0
    ESTree::IdentifierNode *localIdent =
6454
0
        cast<ESTree::IdentifierNode>(optSpecifier.getValue()->_local);
6455
0
    auto insertRes = boundNames.try_emplace(localIdent->_name, localIdent);
6456
0
    if (insertRes.second) {
6457
0
      specifiers.push_back(*optSpecifier.getValue());
6458
0
    } else {
6459
      // Report the error but continue parsing to see if there's any others.
6460
0
      error(
6461
0
          localIdent->getSourceRange(),
6462
0
          "Duplicate entry in import declaration list");
6463
0
      sm_.note(
6464
0
          insertRes.first->second->getSourceRange(), "first usage of name");
6465
0
    }
6466
6467
0
    if (!checkAndEat(TokenKind::comma)) {
6468
0
      break;
6469
0
    }
6470
0
  }
6471
0
  if (!eat(
6472
0
          TokenKind::r_brace,
6473
0
          JSLexer::AllowDiv,
6474
0
          "at end of named imports",
6475
0
          "location of '{'",
6476
0
          startLoc)) {
6477
0
    return false;
6478
0
  }
6479
6480
0
  return true;
6481
0
}
6482
6483
Optional<ESTree::ImportSpecifierNode *> JSParserImpl::parseImportSpecifier(
6484
0
    SMLoc importLoc) {
6485
  // ImportSpecifier:
6486
  //   ImportedBinding
6487
  //   IdentifierName as ImportedBinding
6488
0
  SMLoc startLoc = tok_->getStartLoc();
6489
6490
0
  UniqueString *kind = valueIdent_;
6491
0
  ESTree::IdentifierNode *imported = nullptr;
6492
0
  ESTree::IdentifierNode *local = nullptr;
6493
0
  TokenKind localKind;
6494
6495
0
#if HERMES_PARSE_FLOW
6496
0
  if (context_.getParseFlow() && checkAndEat(TokenKind::rw_typeof)) {
6497
0
    kind = typeofIdent_;
6498
0
  }
6499
0
#endif
6500
6501
  // This isn't wrapped in #if HERMES_PARSE_FLOW, as it is entangled
6502
  // in the rest of the import specifier parsing code and doesn't actually
6503
  // depend on JSParserImpl-flow specific code at all.
6504
0
  if (HERMES_PARSE_FLOW && context_.getParseFlow() && check(typeIdent_) &&
6505
0
      kind == valueIdent_) {
6506
    // Consume 'type', but make no assumptions about what it means yet.
6507
0
    SMRange typeRange = advance();
6508
0
    if (check(TokenKind::r_brace, TokenKind::comma)) {
6509
      // 'type'
6510
0
      imported = setLocation(
6511
0
          typeRange,
6512
0
          typeRange,
6513
0
          new (context_) ESTree::IdentifierNode(typeIdent_, nullptr, false));
6514
0
      local = imported;
6515
0
      localKind = TokenKind::identifier;
6516
0
    } else if (check(asIdent_)) {
6517
0
      SMRange asRange = advance();
6518
0
      if (check(TokenKind::r_brace, TokenKind::comma)) {
6519
        // 'type' 'as'
6520
0
        kind = typeIdent_;
6521
0
        imported = setLocation(
6522
0
            asRange,
6523
0
            asRange,
6524
0
            new (context_) ESTree::IdentifierNode(asIdent_, nullptr, false));
6525
0
        local = imported;
6526
0
        localKind = TokenKind::identifier;
6527
0
        advance();
6528
0
      } else if (checkAndEat(asIdent_)) {
6529
        // 'type' 'as' 'as' Identifier
6530
        //                  ^
6531
0
        if (!check(TokenKind::identifier) && !tok_->isResWord()) {
6532
0
          errorExpected(
6533
0
              TokenKind::identifier,
6534
0
              "in import specifier",
6535
0
              "specifiers start",
6536
0
              importLoc);
6537
0
          return None;
6538
0
        }
6539
0
        kind = typeIdent_;
6540
0
        imported = setLocation(
6541
0
            asRange,
6542
0
            asRange,
6543
0
            new (context_) ESTree::IdentifierNode(asIdent_, nullptr, false));
6544
0
        local = setLocation(
6545
0
            tok_,
6546
0
            tok_,
6547
0
            new (context_) ESTree::IdentifierNode(
6548
0
                tok_->getResWordOrIdentifier(), nullptr, false));
6549
0
        localKind = TokenKind::identifier;
6550
0
        advance();
6551
0
      } else {
6552
        // 'type' 'as' Identifier
6553
        //             ^
6554
0
        if (!check(TokenKind::identifier) && !tok_->isResWord()) {
6555
0
          errorExpected(
6556
0
              TokenKind::identifier,
6557
0
              "in import specifier",
6558
0
              "specifiers start",
6559
0
              importLoc);
6560
0
          return None;
6561
0
        }
6562
0
        imported = setLocation(
6563
0
            typeRange,
6564
0
            typeRange,
6565
0
            new (context_) ESTree::IdentifierNode(typeIdent_, nullptr, false));
6566
0
        local = setLocation(
6567
0
            tok_,
6568
0
            tok_,
6569
0
            new (context_) ESTree::IdentifierNode(
6570
0
                tok_->getResWordOrIdentifier(), nullptr, false));
6571
0
        localKind = TokenKind::identifier;
6572
0
        advance();
6573
0
      }
6574
0
    } else {
6575
      // 'type' Identifier
6576
      //        ^
6577
0
      kind = typeIdent_;
6578
0
      if (!check(TokenKind::identifier) && !tok_->isResWord()) {
6579
0
        errorExpected(
6580
0
            TokenKind::identifier,
6581
0
            "in import specifier",
6582
0
            "specifiers start",
6583
0
            importLoc);
6584
0
        return None;
6585
0
      }
6586
0
      imported = setLocation(
6587
0
          tok_,
6588
0
          tok_,
6589
0
          new (context_) ESTree::IdentifierNode(
6590
0
              tok_->getResWordOrIdentifier(), nullptr, false));
6591
0
      local = imported;
6592
0
      localKind = tok_->getKind();
6593
0
      advance();
6594
0
      if (checkAndEat(asIdent_)) {
6595
        // type Identifier 'as' Identifier
6596
        //                      ^
6597
0
        if (!check(TokenKind::identifier) && !tok_->isResWord()) {
6598
0
          errorExpected(
6599
0
              TokenKind::identifier,
6600
0
              "in import specifier",
6601
0
              "specifiers start",
6602
0
              importLoc);
6603
0
          return None;
6604
0
        }
6605
0
        local = setLocation(
6606
0
            tok_,
6607
0
            tok_,
6608
0
            new (context_) ESTree::IdentifierNode(
6609
0
                tok_->getResWordOrIdentifier(), nullptr, false));
6610
0
        localKind = tok_->getKind();
6611
0
        advance();
6612
0
      }
6613
0
    }
6614
0
  } else {
6615
    // Not attempting to parse a type identifier.
6616
0
    if (!check(TokenKind::identifier) && !tok_->isResWord()) {
6617
0
      errorExpected(
6618
0
          TokenKind::identifier,
6619
0
          "in import specifier",
6620
0
          "specifiers start",
6621
0
          importLoc);
6622
0
      return None;
6623
0
    }
6624
0
    imported = setLocation(
6625
0
        tok_,
6626
0
        tok_,
6627
0
        new (context_) ESTree::IdentifierNode(
6628
0
            tok_->getResWordOrIdentifier(), nullptr, false));
6629
0
    local = imported;
6630
0
    localKind = tok_->getKind();
6631
0
    advance();
6632
6633
0
    if (checkAndEat(asIdent_)) {
6634
0
      if (!check(TokenKind::identifier) && !tok_->isResWord()) {
6635
0
        errorExpected(
6636
0
            TokenKind::identifier,
6637
0
            "in import specifier",
6638
0
            "specifiers start",
6639
0
            importLoc);
6640
0
        return None;
6641
0
      }
6642
0
      local = setLocation(
6643
0
          tok_,
6644
0
          tok_,
6645
0
          new (context_) ESTree::IdentifierNode(
6646
0
              tok_->getResWordOrIdentifier(), nullptr, false));
6647
0
      localKind = tok_->getKind();
6648
0
      advance();
6649
0
    }
6650
0
  }
6651
6652
  // Only the local name must be parsed as a binding identifier.
6653
  // We need to check for 'as' before knowing what the local name is.
6654
  // Thus, we need to validate the binding identifier for the local name
6655
  // after the fact.
6656
0
  if (!validateBindingIdentifier(
6657
0
          Param{}, local->getSourceRange(), local->_name, localKind)) {
6658
0
    error(local->getSourceRange(), "Invalid local name for import");
6659
0
  }
6660
6661
0
  return setLocation(
6662
0
      startLoc,
6663
0
      getPrevTokenEndLoc(),
6664
0
      new (context_) ESTree::ImportSpecifierNode(imported, local, kind));
6665
0
}
6666
6667
0
Optional<ESTree::Node *> JSParserImpl::parseExportDeclaration() {
6668
0
  assert(
6669
0
      check(TokenKind::rw_export) &&
6670
0
      "parseExportDeclaration requires 'export'");
6671
0
  SMLoc startLoc = advance().Start;
6672
6673
0
#if HERMES_PARSE_FLOW
6674
0
  if (context_.getParseFlow() && check(typeIdent_)) {
6675
0
    return parseExportTypeDeclarationFlow(startLoc);
6676
0
  }
6677
0
#endif
6678
6679
0
  if (checkAndEat(TokenKind::star)) {
6680
    // export * FromClause;
6681
    // export * as IdentifierName FromClause;
6682
0
    ESTree::Node *exportAs = nullptr;
6683
0
    if (checkAndEat(asIdent_)) {
6684
      // export * as IdentifierName FromClause;
6685
      //             ^
6686
0
      if (!check(TokenKind::identifier) && !tok_->isResWord()) {
6687
0
        errorExpected(
6688
0
            TokenKind::identifier,
6689
0
            "in export clause",
6690
0
            "start of export",
6691
0
            startLoc);
6692
0
        return None;
6693
0
      }
6694
0
      exportAs = setLocation(
6695
0
          tok_,
6696
0
          tok_,
6697
0
          new (context_) ESTree::IdentifierNode(
6698
0
              tok_->getResWordOrIdentifier(), nullptr, false));
6699
0
      advance();
6700
0
    }
6701
0
    auto optFromClause = parseFromClause();
6702
0
    if (!optFromClause) {
6703
0
      return None;
6704
0
    }
6705
0
    if (!eatSemi()) {
6706
0
      return None;
6707
0
    }
6708
0
    if (exportAs) {
6709
0
      ESTree::NodeList specifiers{};
6710
0
      specifiers.push_back(*setLocation(
6711
0
          startLoc,
6712
0
          getPrevTokenEndLoc(),
6713
0
          new (context_) ESTree::ExportNamespaceSpecifierNode(exportAs)));
6714
0
      return setLocation(
6715
0
          startLoc,
6716
0
          getPrevTokenEndLoc(),
6717
0
          new (context_) ESTree::ExportNamedDeclarationNode(
6718
0
              nullptr, std::move(specifiers), *optFromClause, valueIdent_));
6719
0
    }
6720
0
    return setLocation(
6721
0
        startLoc,
6722
0
        getPrevTokenEndLoc(),
6723
0
        new (context_)
6724
0
            ESTree::ExportAllDeclarationNode(*optFromClause, valueIdent_));
6725
0
  } else if (checkAndEat(TokenKind::rw_default)) {
6726
0
    CHECK_RECURSION;
6727
    // export default
6728
0
    if (check(TokenKind::rw_function) ||
6729
0
        (check(asyncIdent_) && checkAsyncFunction())) {
6730
      // export default HoistableDeclaration
6731
      // Currently, the only hoistable declarations are functions.
6732
0
      auto optFunDecl = parseFunctionDeclaration(ParamDefault);
6733
0
      if (!optFunDecl) {
6734
0
        return None;
6735
0
      }
6736
0
      return setLocation(
6737
0
          startLoc,
6738
0
          *optFunDecl,
6739
0
          new (context_) ESTree::ExportDefaultDeclarationNode(*optFunDecl));
6740
0
    } else if (check(TokenKind::rw_class)) {
6741
0
      auto optClassDecl = parseClassDeclaration(ParamDefault);
6742
0
      if (!optClassDecl) {
6743
0
        return None;
6744
0
      }
6745
0
      return setLocation(
6746
0
          startLoc,
6747
0
          *optClassDecl,
6748
0
          new (context_) ESTree::ExportDefaultDeclarationNode(*optClassDecl));
6749
0
#if HERMES_PARSE_FLOW
6750
0
    } else if (
6751
0
        context_.getParseFlow() && context_.getParseFlowComponentSyntax() &&
6752
0
        checkComponentDeclarationFlow()) {
6753
0
      auto optComponent = parseComponentDeclarationFlow(
6754
0
          tok_->getStartLoc(), /* declare */ false);
6755
0
      if (!optComponent) {
6756
0
        return None;
6757
0
      }
6758
0
      return setLocation(
6759
0
          startLoc,
6760
0
          *optComponent,
6761
0
          new (context_) ESTree::ExportDefaultDeclarationNode(*optComponent));
6762
0
    } else if (
6763
0
        context_.getParseFlow() && context_.getParseFlowComponentSyntax() &&
6764
0
        checkHookDeclarationFlow()) {
6765
0
      auto optHook = parseHookDeclarationFlow(tok_->getStartLoc());
6766
0
      if (!optHook) {
6767
0
        return None;
6768
0
      }
6769
0
      return setLocation(
6770
0
          startLoc,
6771
0
          *optHook,
6772
0
          new (context_) ESTree::ExportDefaultDeclarationNode(*optHook));
6773
0
    } else if (context_.getParseFlow() && check(TokenKind::rw_enum)) {
6774
0
      auto optEnum =
6775
0
          parseEnumDeclarationFlow(tok_->getStartLoc(), /* declare */ false);
6776
0
      if (!optEnum) {
6777
0
        return None;
6778
0
      }
6779
0
      return setLocation(
6780
0
          startLoc,
6781
0
          *optEnum,
6782
0
          new (context_) ESTree::ExportDefaultDeclarationNode(*optEnum));
6783
0
#endif
6784
0
    } else {
6785
      // export default AssignmentExpression ;
6786
0
      auto optExpr = parseAssignmentExpression(ParamIn);
6787
0
      if (!optExpr) {
6788
0
        return None;
6789
0
      }
6790
0
      if (!eatSemi()) {
6791
0
        return None;
6792
0
      }
6793
0
      return setLocation(
6794
0
          startLoc,
6795
0
          getPrevTokenEndLoc(),
6796
0
          new (context_) ESTree::ExportDefaultDeclarationNode(*optExpr));
6797
0
    }
6798
0
  } else if (check(TokenKind::l_brace)) {
6799
    // export ExportClause FromClause ;
6800
    // export ExportClause ;
6801
0
    ESTree::NodeList specifiers{};
6802
0
    llvh::SmallVector<SMRange, 2> invalids{};
6803
6804
0
    auto optExportClause = parseExportClause(specifiers, invalids);
6805
0
    if (!optExportClause) {
6806
0
      return None;
6807
0
    }
6808
6809
0
    ESTree::Node *source = nullptr;
6810
0
    if (check(fromIdent_)) {
6811
      // export ExportClause FromClause ;
6812
0
      auto optFromClause = parseFromClause();
6813
0
      if (!optFromClause) {
6814
0
        return None;
6815
0
      }
6816
0
      source = *optFromClause;
6817
0
    } else {
6818
      // export ExportClause ;
6819
      // ES9.0 15.2.3.1
6820
      // When there is no FromClause, any ranges added to invalids are actually
6821
      // invalid, and should be reported as errors.
6822
0
      for (const SMRange &range : invalids) {
6823
0
        error(range, "Invalid exported name");
6824
0
      }
6825
0
    }
6826
6827
0
    if (!eatSemi()) {
6828
0
      return None;
6829
0
    }
6830
6831
0
    return setLocation(
6832
0
        startLoc,
6833
0
        getPrevTokenEndLoc(),
6834
0
        new (context_) ESTree::ExportNamedDeclarationNode(
6835
0
            nullptr, std::move(specifiers), source, valueIdent_));
6836
0
  } else if (check(TokenKind::rw_var)) {
6837
    // Could find another AssignmentExpression without hitting
6838
    // PrimaryExpression.
6839
0
    CHECK_RECURSION;
6840
    // export VariableStatement
6841
0
    auto optVar = parseVariableStatement(Param{});
6842
0
    if (!optVar) {
6843
0
      return None;
6844
0
    }
6845
0
    return setLocation(
6846
0
        startLoc,
6847
0
        *optVar,
6848
0
        new (context_) ESTree::ExportNamedDeclarationNode(
6849
0
            *optVar, {}, nullptr, valueIdent_));
6850
0
  }
6851
6852
  // export Declaration [~Yield]
6853
6854
0
  if (!checkDeclaration()) {
6855
0
    error(tok_->getSourceRange(), "expected declaration in export");
6856
0
    return None;
6857
0
  }
6858
6859
0
  auto optDecl = parseDeclaration(Param{});
6860
0
  if (!optDecl) {
6861
0
    return None;
6862
0
  }
6863
0
  ESTree::Node *decl = *optDecl;
6864
6865
0
  UniqueString *kind = valueIdent_;
6866
0
#if HERMES_PARSE_FLOW
6867
0
  if (isa<ESTree::TypeAliasNode>(decl) || isa<ESTree::OpaqueTypeNode>(decl) ||
6868
0
      isa<ESTree::DeclareTypeAliasNode>(decl) ||
6869
0
      isa<ESTree::InterfaceDeclarationNode>(decl)) {
6870
0
    kind = typeIdent_;
6871
0
  }
6872
0
#endif
6873
6874
0
  return setLocation(
6875
0
      startLoc,
6876
0
      decl,
6877
0
      new (context_)
6878
0
          ESTree::ExportNamedDeclarationNode(decl, {}, nullptr, kind));
6879
0
}
6880
6881
bool JSParserImpl::parseExportClause(
6882
    ESTree::NodeList &specifiers,
6883
0
    llvh::SmallVectorImpl<SMRange> &invalids) {
6884
  // ExportClause:
6885
  //   { }
6886
  //   { ExportsList }
6887
  //   { ExportsList , '}
6888
6889
0
  assert(check(TokenKind::l_brace) && "ExportClause requires '{'");
6890
0
  SMLoc startLoc = advance().Start;
6891
6892
0
  while (!check(TokenKind::r_brace)) {
6893
    // Read all the elements of the ExportsList.
6894
0
    auto optSpecifier = parseExportSpecifier(startLoc, invalids);
6895
0
    if (!optSpecifier) {
6896
0
      return false;
6897
0
    }
6898
0
    specifiers.push_back(*optSpecifier.getValue());
6899
6900
0
    if (!checkAndEat(TokenKind::comma)) {
6901
0
      break;
6902
0
    }
6903
0
  }
6904
6905
0
  return eat(
6906
0
      TokenKind::r_brace,
6907
0
      JSLexer::AllowDiv,
6908
0
      "at end of export clause",
6909
0
      "location of export",
6910
0
      startLoc);
6911
0
}
6912
6913
Optional<ESTree::Node *> JSParserImpl::parseExportSpecifier(
6914
    SMLoc exportLoc,
6915
0
    llvh::SmallVectorImpl<SMRange> &invalids) {
6916
  // ExportSpecifier:
6917
  //   IdentifierName
6918
  //   IdentifierName as IdentifierName
6919
6920
0
  if (!check(TokenKind::identifier) && !tok_->isResWord()) {
6921
0
    errorExpected(
6922
0
        TokenKind::identifier,
6923
0
        "in export clause",
6924
0
        "location of export clause",
6925
0
        exportLoc);
6926
0
    return None;
6927
0
  }
6928
6929
  // ES9.0 15.2.3.1 Early errors for ReferencedBindings in ExportClause.
6930
  // Add potentially error-raising identifier ranges to the invalids list here,
6931
  // and the owner of the invalids list will report the ranges as errors if
6932
  // necessary.
6933
0
  if (tok_->isResWord() || check(implementsIdent_) || check(interfaceIdent_) ||
6934
0
      check(letIdent_) || check(packageIdent_) || check(privateIdent_) ||
6935
0
      check(protectedIdent_) || check(publicIdent_) || check(staticIdent_)) {
6936
0
    invalids.push_back(tok_->getSourceRange());
6937
0
  }
6938
6939
0
  auto *local = setLocation(
6940
0
      tok_,
6941
0
      tok_,
6942
0
      new (context_) ESTree::IdentifierNode(
6943
0
          tok_->getResWordOrIdentifier(), nullptr, false));
6944
0
  advance();
6945
0
  ESTree::Node *exported;
6946
0
  if (checkAndEat(asIdent_)) {
6947
    // IdentifierName as IdentifierName
6948
0
    if (!check(TokenKind::identifier) && !tok_->isResWord()) {
6949
0
      errorExpected(
6950
0
          TokenKind::identifier,
6951
0
          "in export clause",
6952
0
          "location of export clause",
6953
0
          exportLoc);
6954
0
      return None;
6955
0
    }
6956
0
    exported = setLocation(
6957
0
        tok_,
6958
0
        tok_,
6959
0
        new (context_) ESTree::IdentifierNode(
6960
0
            tok_->getResWordOrIdentifier(), nullptr, false));
6961
0
    advance();
6962
0
  } else {
6963
    // IdentifierName
6964
0
    exported = local;
6965
0
  }
6966
6967
0
  return setLocation(
6968
0
      local,
6969
0
      exported,
6970
0
      new (context_) ESTree::ExportSpecifierNode(exported, local));
6971
0
}
6972
6973
14
ESTree::ExpressionStatementNode *JSParserImpl::parseDirective() {
6974
  // Is the current token a directive?
6975
14
  if (!lexer_.isCurrentTokenADirective())
6976
10
    return nullptr;
6977
6978
  // Allocate a StringLiteralNode for the directive.
6979
4
  auto *strLit = setLocation(
6980
4
      tok_,
6981
4
      tok_,
6982
4
      new (context_) ESTree::StringLiteralNode(tok_->getStringLiteral()));
6983
4
  auto endLoc = tok_->getEndLoc();
6984
6985
  // Actually process the directive. Note that we want to do that before we
6986
  // have consumed any more tokens - strictness can affect the interpretation
6987
  // of tokens.
6988
4
  processDirective(strLit->_value);
6989
6990
4
  advance(JSLexer::AllowDiv);
6991
6992
  // Consume the optional semicolon.
6993
4
  if (check(TokenKind::semi))
6994
0
    endLoc = advance().End;
6995
6996
  // Allocate an ExpressionStatementNode for the directive.
6997
4
  return setLocation(
6998
4
      strLit,
6999
4
      endLoc,
7000
4
      new (context_) ESTree::ExpressionStatementNode(strLit, strLit->_value));
7001
14
}
7002
7003
namespace {
7004
/// Upcast an Optional node type to a generic NodePtr, e.g.
7005
/// \p Optional<FunctionExpressionNode> to \p Optional<NodePtr>.
7006
template <typename T>
7007
0
Optional<ESTree::NodePtr> castNode(Optional<T> node) {
7008
0
  if (!node.hasValue())
7009
0
    return None;
7010
0
  return Optional<ESTree::NodePtr>(node.getValue());
7011
0
}
Unexecuted instantiation: JSParserImpl.cpp:llvh::Optional<hermes::ESTree::Node*> hermes::parser::detail::(anonymous namespace)::castNode<hermes::ESTree::FunctionExpressionNode*>(llvh::Optional<hermes::ESTree::FunctionExpressionNode*>)
Unexecuted instantiation: JSParserImpl.cpp:llvh::Optional<hermes::ESTree::Node*> hermes::parser::detail::(anonymous namespace)::castNode<hermes::ESTree::FunctionDeclarationNode*>(llvh::Optional<hermes::ESTree::FunctionDeclarationNode*>)
7012
7013
class PreParser {
7014
  AllocationScope scope_;
7015
7016
 public:
7017
  JSParserImpl parser;
7018
7019
  explicit PreParser(Context &context, uint32_t bufferId)
7020
244
      : scope_(context.getAllocator()), parser(context, bufferId, PreParse) {}
7021
};
7022
7023
} // namespace
7024
7025
std::shared_ptr<JSParserImpl> JSParserImpl::preParseBuffer(
7026
    Context &context,
7027
244
    uint32_t bufferId) {
7028
244
  PerfSection preparsing("Pre-Parsing JavaScript");
7029
244
  auto preParser = std::make_shared<PreParser>(context, bufferId);
7030
244
  auto result = preParser->parser.parse();
7031
244
  if (!result.hasValue())
7032
41
    return nullptr;
7033
7034
  // Return a pointer only to JSParserImpl, while aliasing and maintaining
7035
  // ownership of the entire PreParser object.
7036
203
  return std::shared_ptr<JSParserImpl>(preParser, &preParser->parser);
7037
244
}
7038
7039
Optional<ESTree::NodePtr> JSParserImpl::parseLazyFunction(
7040
    ESTree::NodeKind kind,
7041
    bool paramYield,
7042
    bool paramAwait,
7043
0
    SMLoc start) {
7044
0
  seek(start);
7045
7046
0
  paramYield_ = paramYield;
7047
0
  paramAwait_ = paramAwait;
7048
7049
0
  switch (kind) {
7050
0
    case ESTree::NodeKind::FunctionExpression:
7051
0
      return castNode(parseFunctionExpression(true));
7052
7053
0
    case ESTree::NodeKind::FunctionDeclaration:
7054
0
      return castNode(parseFunctionDeclaration(ParamReturn, true));
7055
7056
0
    case ESTree::NodeKind::Property: {
7057
0
      auto node = parsePropertyAssignment(true);
7058
0
      assert(node && "Reparsing of property assignment failed");
7059
0
      if (auto *prop = dyn_cast<ESTree::PropertyNode>(*node)) {
7060
0
        return prop->_value;
7061
0
      } else {
7062
        // This isn't technically (llvm_)unreachable, since it'll happen if you
7063
        // fudge the source buffer during execution. Assert and fail instead.
7064
0
        assert(false && "Expected a getter/setter function");
7065
0
        return None;
7066
0
      }
7067
0
    }
7068
7069
0
    default:
7070
0
      llvm_unreachable("Asked to parse unexpected node type");
7071
0
  }
7072
0
}
7073
} // namespace detail
7074
} // namespace parser
7075
} // namespace hermes