• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "parserImpl.h"
17 
18 #include <binder/scope.h>
19 #include <binder/tsBinding.h>
20 #include <util/helpers.h>
21 #include <ir/astDump.h>
22 #include <ir/astNode.h>
23 #include <ir/base/classDefinition.h>
24 #include <ir/base/classProperty.h>
25 #include <ir/base/decorator.h>
26 #include <ir/base/methodDefinition.h>
27 #include <ir/base/property.h>
28 #include <ir/base/scriptFunction.h>
29 #include <ir/base/spreadElement.h>
30 #include <ir/expression.h>
31 #include <ir/expressions/arrayExpression.h>
32 #include <ir/expressions/assignmentExpression.h>
33 #include <ir/expressions/callExpression.h>
34 #include <ir/expressions/functionExpression.h>
35 #include <ir/expressions/identifier.h>
36 #include <ir/expressions/literals/bigIntLiteral.h>
37 #include <ir/expressions/literals/booleanLiteral.h>
38 #include <ir/expressions/literals/nullLiteral.h>
39 #include <ir/expressions/literals/numberLiteral.h>
40 #include <ir/expressions/literals/stringLiteral.h>
41 #include <ir/expressions/memberExpression.h>
42 #include <ir/expressions/objectExpression.h>
43 #include <ir/expressions/superExpression.h>
44 #include <ir/module/exportDefaultDeclaration.h>
45 #include <ir/module/exportNamedDeclaration.h>
46 #include <ir/module/exportSpecifier.h>
47 #include <ir/statements/blockStatement.h>
48 #include <ir/statements/classDeclaration.h>
49 #include <ir/statements/emptyStatement.h>
50 #include <ir/statements/expressionStatement.h>
51 #include <ir/statements/functionDeclaration.h>
52 #include <ir/statements/variableDeclaration.h>
53 #include <ir/ts/tsAnyKeyword.h>
54 #include <ir/ts/tsArrayType.h>
55 #include <ir/ts/tsAsExpression.h>
56 #include <ir/ts/tsBigintKeyword.h>
57 #include <ir/ts/tsBooleanKeyword.h>
58 #include <ir/ts/tsClassImplements.h>
59 #include <ir/ts/tsConditionalType.h>
60 #include <ir/ts/tsConstructorType.h>
61 #include <ir/ts/tsEnumDeclaration.h>
62 #include <ir/ts/tsEnumMember.h>
63 #include <ir/ts/tsFunctionType.h>
64 #include <ir/ts/tsImportType.h>
65 #include <ir/ts/tsIndexSignature.h>
66 #include <ir/ts/tsIndexedAccessType.h>
67 #include <ir/ts/tsInferType.h>
68 #include <ir/ts/tsIntersectionType.h>
69 #include <ir/ts/tsLiteralType.h>
70 #include <ir/ts/tsMappedType.h>
71 #include <ir/ts/tsMethodSignature.h>
72 #include <ir/ts/tsModuleDeclaration.h>
73 #include <ir/ts/tsNamedTupleMember.h>
74 #include <ir/ts/tsNeverKeyword.h>
75 #include <ir/ts/tsNullKeyword.h>
76 #include <ir/ts/tsNumberKeyword.h>
77 #include <ir/ts/tsObjectKeyword.h>
78 #include <ir/ts/tsOptionalType.h>
79 #include <ir/ts/tsParameterProperty.h>
80 #include <ir/ts/tsParenthesizedType.h>
81 #include <ir/ts/tsPrivateIdentifier.h>
82 #include <ir/ts/tsPropertySignature.h>
83 #include <ir/ts/tsQualifiedName.h>
84 #include <ir/ts/tsRestType.h>
85 #include <ir/ts/tsSignatureDeclaration.h>
86 #include <ir/ts/tsStringKeyword.h>
87 #include <ir/ts/tsSymbolKeyword.h>
88 #include <ir/ts/tsTemplateLiteralType.h>
89 #include <ir/ts/tsThisType.h>
90 #include <ir/ts/tsTupleType.h>
91 #include <ir/ts/tsTypeAssertion.h>
92 #include <ir/ts/tsTypeLiteral.h>
93 #include <ir/ts/tsTypeOperator.h>
94 #include <ir/ts/tsTypeParameterDeclaration.h>
95 #include <ir/ts/tsTypeParameterInstantiation.h>
96 #include <ir/ts/tsTypePredicate.h>
97 #include <ir/ts/tsTypeQuery.h>
98 #include <ir/ts/tsTypeReference.h>
99 #include <ir/ts/tsUndefinedKeyword.h>
100 #include <ir/ts/tsUnionType.h>
101 #include <ir/ts/tsUnknownKeyword.h>
102 #include <ir/ts/tsVoidKeyword.h>
103 #include <lexer/lexer.h>
104 #include <lexer/token/letters.h>
105 #include <lexer/token/sourceLocation.h>
106 #include <mem/pool_manager.h>
107 
108 namespace panda::es2panda::parser {
109 
ParserImpl(ScriptExtension extension)110 ParserImpl::ParserImpl(ScriptExtension extension) : program_(extension), context_(&program_) {}
111 
InitLexer(const std::string & fileName,const std::string & source)112 std::unique_ptr<lexer::Lexer> ParserImpl::InitLexer(const std::string &fileName, const std::string &source)
113 {
114     bool isDtsFile = false;
115     if (Extension() == ScriptExtension::TS) {
116         isDtsFile = util::Helpers::FileExtensionIs(fileName, ".d.ts");
117     }
118     program_.SetSource(source, fileName, isDtsFile);
119     auto lexer = std::make_unique<lexer::Lexer>(&context_);
120     lexer_ = lexer.get();
121 
122     return lexer;
123 }
124 
Parse(const std::string & fileName,const std::string & source,const std::string & recordName,ScriptKind kind)125 Program ParserImpl::Parse(const std::string &fileName, const std::string &source,
126                           const std::string &recordName, ScriptKind kind)
127 {
128     program_.SetKind(kind);
129     program_.SetRecordName(recordName);
130 
131     /*
132      * In order to make the lexer's memory alive, the return value 'lexer' can not be omitted.
133      */
134     auto lexer = InitLexer(fileName, source);
135     switch (kind) {
136         case ScriptKind::SCRIPT: {
137             ParseScript();
138             break;
139         }
140         case ScriptKind::MODULE: {
141             ParseModule();
142             break;
143         }
144         case ScriptKind::COMMONJS: {
145             ParseCommonjs();
146             break;
147         }
148         default: {
149             UNREACHABLE();
150         }
151     }
152     binder::ResolveBindingFlags bindFlags = binder::ResolveBindingFlags::ALL;
153     if (Extension() == ScriptExtension::TS) {
154         bindFlags = binder::ResolveBindingFlags::TS_BEFORE_TRANSFORM;
155     }
156     Binder()->IdentifierAnalysis(bindFlags);
157     return std::move(program_);
158 }
159 
ParseScript()160 void ParserImpl::ParseScript()
161 {
162     ParseProgram(ScriptKind::SCRIPT);
163 }
164 
ParseModule()165 void ParserImpl::ParseModule()
166 {
167     context_.Status() |= (ParserStatus::MODULE);
168     ParseProgram(ScriptKind::MODULE);
169 }
170 
ParseProgram(ScriptKind kind)171 void ParserImpl::ParseProgram(ScriptKind kind)
172 {
173     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
174     lexer_->NextToken();
175 
176     auto statements = ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
177     if (IsDtsFile() && !CheckTopStatementsForRequiredDeclare(statements)) {
178         ThrowSyntaxError(
179             "Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier.");
180     }
181 
182     auto *blockStmt = AllocNode<ir::BlockStatement>(Binder()->GetScope(), std::move(statements));
183     Binder()->GetScope()->BindNode(blockStmt);
184     blockStmt->SetRange({startLoc, lexer_->GetToken().End()});
185 
186     program_.SetAst(blockStmt);
187 }
188 
CheckTopStatementsForRequiredDeclare(const ArenaVector<ir::Statement * > & statements)189 bool ParserImpl::CheckTopStatementsForRequiredDeclare(const ArenaVector<ir::Statement *> &statements)
190 {
191     for (auto *statement : statements) {
192         switch (statement->Type()) {
193             case ir::AstNodeType::TS_INTERFACE_DECLARATION:
194             case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION:
195             case ir::AstNodeType::IMPORT_DECLARATION:
196             case ir::AstNodeType::TS_IMPORT_EQUALS_DECLARATION:
197             case ir::AstNodeType::EXPORT_ALL_DECLARATION:
198             case ir::AstNodeType::EXPORT_DEFAULT_DECLARATION:
199             case ir::AstNodeType::EXPORT_NAMED_DECLARATION:
200             case ir::AstNodeType::TS_NAMESPACE_EXPORT_DECLARATION:
201                 continue;
202             case ir::AstNodeType::CLASS_DECLARATION: {
203                 if (!statement->AsClassDeclaration()->Definition()->Declare()) {
204                     return false;
205                 }
206                 break;
207             }
208             case ir::AstNodeType::FUNCTION_DECLARATION: {
209                 if (!statement->AsFunctionDeclaration()->Function()->Declare() &&
210                     !statement->AsFunctionDeclaration()->Function()->IsOverload()) {
211                     return false;
212                 }
213                 break;
214             }
215             case ir::AstNodeType::VARIABLE_DECLARATION: {
216                 if (!statement->AsVariableDeclaration()->Declare()) {
217                     return false;
218                 }
219                 break;
220             }
221             case ir::AstNodeType::TS_MODULE_DECLARATION: {
222                 if (!statement->AsTSModuleDeclaration()->Declare()) {
223                     return false;
224                 }
225                 break;
226             }
227             case ir::AstNodeType::TS_ENUM_DECLARATION: {
228                 if (!statement->AsTSEnumDeclaration()->IsDeclare()) {
229                     return false;
230                 }
231                 break;
232             }
233             default:
234                 ThrowSyntaxError("Statements are not allowed in ambient contexts.");
235                 UNREACHABLE();
236         }
237     }
238     return true;
239 }
240 
241 /*
242  * Definitions of private methods
243  */
CarryExpressionParserFlag(ExpressionParseFlags origin,ExpressionParseFlags carry)244 ExpressionParseFlags ParserImpl::CarryExpressionParserFlag(ExpressionParseFlags origin, ExpressionParseFlags carry)
245 {
246     return static_cast<ExpressionParseFlags>(origin & carry);
247 }
248 
CarryPatternFlags(ExpressionParseFlags flags)249 ExpressionParseFlags ParserImpl::CarryPatternFlags(ExpressionParseFlags flags)
250 {
251     return CarryExpressionParserFlag(flags, ExpressionParseFlags::POTENTIALLY_IN_PATTERN |
252                                                 ExpressionParseFlags::OBJECT_PATTERN);
253 }
254 
CarryAllowTsParamAndPatternFlags(ExpressionParseFlags flags)255 ExpressionParseFlags ParserImpl::CarryAllowTsParamAndPatternFlags(ExpressionParseFlags flags)
256 {
257     return CarryExpressionParserFlag(flags, ExpressionParseFlags::ALLOW_TS_PARAM_TOKEN |
258                                             ExpressionParseFlags::POTENTIALLY_IN_PATTERN |
259                                             ExpressionParseFlags::OBJECT_PATTERN);
260 }
261 
CurrentLiteralIsBasicType()262 bool ParserImpl::CurrentLiteralIsBasicType()
263 {
264     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
265            lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS);
266 
267     switch (lexer_->GetToken().KeywordType()) {
268         case lexer::TokenType::KEYW_ANY:
269         case lexer::TokenType::KEYW_BOOLEAN:
270         case lexer::TokenType::KEYW_NUMBER:
271         case lexer::TokenType::KEYW_STRING:
272         case lexer::TokenType::KEYW_SYMBOL:
273         case lexer::TokenType::KEYW_UNKNOWN:
274         case lexer::TokenType::KEYW_UNDEFINED:
275         case lexer::TokenType::KEYW_NEVER:
276         case lexer::TokenType::KEYW_OBJECT:
277         case lexer::TokenType::KEYW_BIGINT: {
278             return true;
279         }
280         default: {
281             break;
282         }
283     }
284 
285     return false;
286 }
CurrentIsBasicType()287 bool ParserImpl::CurrentIsBasicType()
288 {
289     switch (lexer_->GetToken().Type()) {
290         case lexer::TokenType::PUNCTUATOR_MINUS:
291         case lexer::TokenType::LITERAL_NUMBER:
292         case lexer::TokenType::LITERAL_STRING:
293         case lexer::TokenType::LITERAL_FALSE:
294         case lexer::TokenType::LITERAL_TRUE:
295         case lexer::TokenType::LITERAL_NULL:
296         case lexer::TokenType::KEYW_VOID: {
297             return true;
298         }
299         case lexer::TokenType::LITERAL_IDENT: {
300             return CurrentLiteralIsBasicType();
301         }
302         default: {
303             break;
304         }
305     }
306 
307     return false;
308 }
309 
ParseTsConstExpression()310 ir::TSTypeReference *ParserImpl::ParseTsConstExpression()
311 {
312     auto *identRef = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
313     identRef->SetReference();
314     identRef->SetRange(lexer_->GetToken().Loc());
315 
316     auto *typeReference = AllocNode<ir::TSTypeReference>(identRef, nullptr);
317     typeReference->SetRange(lexer_->GetToken().Loc());
318 
319     lexer_->NextToken();
320 
321     return typeReference;
322 }
323 
ParseTsIdentifierReference(TypeAnnotationParsingOptions options)324 ir::Expression *ParserImpl::ParseTsIdentifierReference(TypeAnnotationParsingOptions options)
325 {
326     if (CurrentLiteralIsBasicType() && lexer_->Lookahead() != LEX_CHAR_DOT) {
327         return ParseTsBasicType(options);
328     }
329 
330     return ParseTsTypeReferenceOrQuery(options, false);
331 }
332 
IsStartOfMappedType() const333 bool ParserImpl::IsStartOfMappedType() const
334 {
335     auto pos = lexer_->Save();
336     lexer_->NextToken();
337     bool result = false;
338 
339     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ||
340         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PLUS) {
341         lexer_->NextToken();
342         result = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY;
343         lexer_->Rewind(pos);
344         return result;
345     }
346 
347     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY) {
348         lexer_->NextToken();
349     }
350 
351     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
352         lexer_->Rewind(pos);
353         return false;
354     }
355 
356     lexer_->NextToken();
357 
358     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
359         lexer_->Rewind(pos);
360         return false;
361     }
362 
363     lexer_->NextToken();
364 
365     result = lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN;
366 
367     lexer_->Rewind(pos);
368     return result;
369 }
370 
IsStartOfTsTypePredicate() const371 bool ParserImpl::IsStartOfTsTypePredicate() const
372 {
373     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
374            lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS);
375 
376     auto pos = lexer_->Save();
377     bool isAsserts = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ASSERTS;
378     if (isAsserts) {
379         lexer_->NextToken();
380     }
381 
382     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT &&
383         lexer_->GetToken().Type() != lexer::TokenType::KEYW_THIS) {
384         lexer_->Rewind(pos);
385         return false;
386     }
387 
388     if (isAsserts) {
389         lexer_->Rewind(pos);
390         return true;
391     }
392 
393     lexer_->NextToken();
394 
395     bool result = !lexer_->GetToken().NewLine() && (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IS);
396     lexer_->Rewind(pos);
397     return result;
398 }
399 
IsStartOfAbstractConstructorType() const400 bool ParserImpl::IsStartOfAbstractConstructorType() const
401 {
402     if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_ABSTRACT) {
403         return false;
404     }
405 
406     lexer::LexerPosition pos = lexer_->Save();
407     lexer_->NextToken();  // eat 'abstract'
408     bool result = lexer_->GetToken().Type() == lexer::TokenType::KEYW_NEW;
409 
410     lexer_->Rewind(pos);
411 
412     return result;
413 }
414 
ParseTsTypeLiteralOrTsMappedType(ir::Expression * typeAnnotation)415 ir::Expression *ParserImpl::ParseTsTypeLiteralOrTsMappedType(ir::Expression *typeAnnotation)
416 {
417     if (typeAnnotation) {
418         return nullptr;
419     }
420 
421     if (IsStartOfMappedType()) {
422         return ParseTsMappedType();
423     }
424 
425     lexer::SourcePosition bodyStart = lexer_->GetToken().Start();
426     auto members = ParseTsTypeLiteralOrInterface();
427     lexer::SourcePosition bodyEnd = lexer_->GetToken().End();
428     lexer_->NextToken();
429 
430     auto *literalType = AllocNode<ir::TSTypeLiteral>(std::move(members));
431     auto *typeVar = binder::Scope::CreateVar(Allocator(), "__type", binder::VariableFlags::TYPE, literalType);
432     literalType->SetVariable(typeVar);
433     literalType->SetRange({bodyStart, bodyEnd});
434     return literalType;
435 }
436 
ParseTsTypeReferenceOrTsTypePredicate(ir::Expression * typeAnnotation,bool canBeTsTypePredicate,bool throwError)437 ir::Expression *ParserImpl::ParseTsTypeReferenceOrTsTypePredicate(ir::Expression *typeAnnotation,
438                                                                   bool canBeTsTypePredicate, bool throwError)
439 {
440     if (typeAnnotation) {
441         return nullptr;
442     }
443 
444     if (canBeTsTypePredicate && IsStartOfTsTypePredicate()) {
445         return ParseTsTypePredicate();
446     }
447 
448     return ParseTsTypeOperatorOrTypeReference(throwError);
449 }
450 
ParseTsThisTypeOrTsTypePredicate(ir::Expression * typeAnnotation,bool canBeTsTypePredicate,bool throwError)451 ir::Expression *ParserImpl::ParseTsThisTypeOrTsTypePredicate(ir::Expression *typeAnnotation, bool canBeTsTypePredicate,
452                                                              bool throwError)
453 {
454     if (typeAnnotation) {
455         return nullptr;
456     }
457 
458     if (canBeTsTypePredicate && IsStartOfTsTypePredicate()) {
459         return ParseTsTypePredicate();
460     }
461 
462     return ParseTsThisType(throwError);
463 }
464 
ParseTsTemplateLiteralType(bool throwError)465 ir::Expression *ParserImpl::ParseTsTemplateLiteralType(bool throwError)
466 {
467     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BACK_TICK);
468     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
469 
470     ArenaVector<ir::TemplateElement *> quasis(Allocator()->Adapter());
471     ArenaVector<ir::Expression *> references(Allocator()->Adapter());
472 
473     while (true) {
474         lexer_->ResetTokenEnd();
475         const auto startPos = lexer_->Save();
476 
477         lexer_->ScanString<LEX_CHAR_BACK_TICK>();
478         util::StringView cooked = lexer_->GetToken().String();
479 
480         lexer_->Rewind(startPos);
481         auto [raw, end, scanExpression] = lexer_->ScanTemplateString();
482 
483         auto *element = AllocNode<ir::TemplateElement>(raw.View(), cooked);
484         element->SetRange({lexer::SourcePosition{startPos.iterator.Index(), startPos.line},
485                            lexer::SourcePosition{end, lexer_->Line()}});
486         quasis.push_back(element);
487 
488         if (!scanExpression) {
489             lexer_->ScanTemplateStringEnd();
490             break;
491         }
492 
493         ir::Expression *reference = nullptr;
494 
495         {
496             lexer::TemplateLiteralParserContext ctx(lexer_);
497             lexer_->PushTemplateContext(&ctx);
498             lexer_->NextToken();
499             TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
500             reference = ParseTsTypeAnnotation(&options);
501         }
502 
503         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
504             if (throwError) {
505                 ThrowSyntaxError("Unexpected token, expected '}'.");
506             }
507             return nullptr;
508         }
509 
510         references.push_back(reference);
511     }
512 
513     ir::Expression *typeAnnotation = AllocNode<ir::TSTemplateLiteralType>(std::move(quasis), std::move(references));
514     typeAnnotation->SetRange({startLoc, lexer_->GetToken().End()});
515 
516     lexer_->NextToken();
517 
518     return typeAnnotation;
519 }
520 
ParseTsTypeAnnotationElement(ir::Expression * typeAnnotation,TypeAnnotationParsingOptions * options)521 ir::Expression *ParserImpl::ParseTsTypeAnnotationElement(ir::Expression *typeAnnotation,
522                                                          TypeAnnotationParsingOptions *options)
523 {
524     switch (lexer_->GetToken().Type()) {
525         case lexer::TokenType::PUNCTUATOR_BITWISE_OR: {
526             if (*options & (TypeAnnotationParsingOptions::IN_MODIFIER | TypeAnnotationParsingOptions::IN_UNION |
527                 TypeAnnotationParsingOptions::IN_INTERSECTION)) {
528                 break;
529             }
530 
531             return ParseTsUnionType(typeAnnotation, *options & TypeAnnotationParsingOptions::RESTRICT_EXTENDS);
532         }
533         case lexer::TokenType::PUNCTUATOR_BITWISE_AND: {
534             if (*options & (TypeAnnotationParsingOptions::IN_MODIFIER |
535                 TypeAnnotationParsingOptions::IN_INTERSECTION)) {
536                 break;
537             }
538 
539             return ParseTsIntersectionType(typeAnnotation, *options & TypeAnnotationParsingOptions::IN_UNION,
540                                            *options & TypeAnnotationParsingOptions::RESTRICT_EXTENDS);
541         }
542         case lexer::TokenType::PUNCTUATOR_LESS_THAN:
543         case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS:
544         case lexer::TokenType::KEYW_NEW: {
545             return ParseTsParenthesizedOrFunctionType(typeAnnotation,
546                                                       *options & TypeAnnotationParsingOptions::THROW_ERROR);
547         }
548         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
549             if (typeAnnotation) {
550                 if (lexer_->GetToken().NewLine()) {
551                     break;
552                 }
553                 if (lexer_->Lookahead() == LEX_CHAR_RIGHT_SQUARE) {
554                     return ParseTsArrayType(typeAnnotation);
555                 }
556 
557                 return ParseTsIndexAccessType(typeAnnotation, *options & TypeAnnotationParsingOptions::THROW_ERROR);
558             }
559 
560             return ParseTsTupleType();
561         }
562         case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
563             return ParseTsTypeLiteralOrTsMappedType(typeAnnotation);
564         }
565         case lexer::TokenType::PUNCTUATOR_MINUS:
566         case lexer::TokenType::LITERAL_NUMBER:
567         case lexer::TokenType::LITERAL_STRING:
568         case lexer::TokenType::LITERAL_FALSE:
569         case lexer::TokenType::LITERAL_TRUE:
570         case lexer::TokenType::LITERAL_NULL:
571         case lexer::TokenType::KEYW_VOID: {
572             if (typeAnnotation) {
573                 break;
574             }
575 
576             return ParseTsBasicType(*options);
577         }
578         case lexer::TokenType::KEYW_TYPEOF: {
579             if (typeAnnotation) {
580                 break;
581             }
582 
583             return ParseTsTypeReferenceOrQuery(*options, true);
584         }
585         case lexer::TokenType::KEYW_IMPORT: {
586             if (typeAnnotation) {
587                 break;
588             }
589 
590             lexer::SourcePosition startLoc = lexer_->GetToken().Start();
591             return ParseTsImportType(startLoc);
592         }
593         case lexer::TokenType::KEYW_CONST: {
594             if (!(*options & TypeAnnotationParsingOptions::ALLOW_CONST)) {
595                 break;
596             }
597 
598             *options &= ~TypeAnnotationParsingOptions::ALLOW_CONST;
599             return ParseTsConstExpression();
600         }
601         case lexer::TokenType::LITERAL_IDENT: {
602             if (IsStartOfAbstractConstructorType()) {
603                 return ParseTsParenthesizedOrFunctionType(typeAnnotation,
604                                                           *options & TypeAnnotationParsingOptions::THROW_ERROR);
605             }
606 
607             return ParseTsTypeReferenceOrTsTypePredicate(
608                 typeAnnotation, *options & TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE,
609                 *options & TypeAnnotationParsingOptions::THROW_ERROR);
610         }
611         case lexer::TokenType::KEYW_EXTENDS: {
612             if (*options & (TypeAnnotationParsingOptions::IN_UNION | TypeAnnotationParsingOptions::IN_INTERSECTION)) {
613                 break;
614             }
615 
616             if (!typeAnnotation) {
617                 return ParseTsIdentifierReference(*options);
618             }
619 
620             return ParseTsConditionalType(typeAnnotation, *options & TypeAnnotationParsingOptions::RESTRICT_EXTENDS);
621         }
622         case lexer::TokenType::KEYW_THIS: {
623             return ParseTsThisTypeOrTsTypePredicate(typeAnnotation,
624                                                     *options & TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE,
625                                                     *options & TypeAnnotationParsingOptions::THROW_ERROR);
626         }
627         case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
628             return ParseTsTemplateLiteralType(*options & TypeAnnotationParsingOptions::THROW_ERROR);
629         }
630         default: {
631             break;
632         }
633     }
634 
635     if (!typeAnnotation && (*options & TypeAnnotationParsingOptions::THROW_ERROR)) {
636         ThrowSyntaxError("Type expected");
637     }
638 
639     return nullptr;
640 }
641 
ParseTsImportType(const lexer::SourcePosition & startLoc,bool isTypeof)642 ir::TSImportType *ParserImpl::ParseTsImportType(const lexer::SourcePosition &startLoc, bool isTypeof)
643 {
644     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_IMPORT);
645 
646     lexer_->NextToken();
647 
648     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
649         ThrowSyntaxError("'(' expected");
650     }
651 
652     lexer_->NextToken();
653 
654     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
655     ir::Expression *param = ParseTsTypeAnnotation(&options);
656 
657     if (!param->IsTSLiteralType() || !param->AsTSLiteralType()->Literal()->IsStringLiteral()) {
658         ThrowSyntaxError("String literal expected");
659     }
660 
661     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
662         ThrowSyntaxError("')' expected");
663     }
664 
665     lexer_->NextToken();
666 
667     ir::Expression *qualifier = nullptr;
668     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
669         lexer_->NextToken();
670 
671         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
672             ThrowSyntaxError("Identifier expected");
673         }
674 
675         qualifier = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
676         qualifier->SetRange(lexer_->GetToken().Loc());
677 
678         lexer_->NextToken();
679 
680         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
681             qualifier = ParseTsQualifiedReference(qualifier);
682         }
683     }
684 
685     ir::TSTypeParameterInstantiation *typeParams = nullptr;
686     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT ||
687         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
688         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
689             lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
690         }
691 
692         typeParams = ParseTsTypeParameterInstantiation();
693     }
694 
695     auto *importType = AllocNode<ir::TSImportType>(param, typeParams, qualifier, isTypeof);
696 
697     importType->SetRange({startLoc, lexer_->GetToken().End()});
698 
699     return importType;
700 }
701 
ParseTsThisType(bool throwError)702 ir::Expression *ParserImpl::ParseTsThisType(bool throwError)
703 {
704     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS);
705 
706     if (throwError && !(context_.Status() & ParserStatus::ALLOW_THIS_TYPE)) {
707         ThrowSyntaxError(
708             "A 'this' type is available only in a non-static member "
709             "of a class or interface.");
710     }
711 
712     auto *returnType = AllocNode<ir::TSThisType>();
713     returnType->SetRange(lexer_->GetToken().Loc());
714 
715     lexer_->NextToken();
716 
717     return returnType;
718 }
719 
ParseTsConditionalType(ir::Expression * checkType,bool restrictExtends)720 ir::Expression *ParserImpl::ParseTsConditionalType(ir::Expression *checkType, bool restrictExtends)
721 {
722     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS);
723     if (restrictExtends) {
724         ThrowSyntaxError("'?' expected.");
725     }
726 
727     lexer::SourcePosition startLoc = checkType->Start();
728 
729     lexer_->NextToken();  // eat 'extends'
730 
731     ParserStatus savedStatus = context_.Status();
732     context_.Status() |= ParserStatus::IN_EXTENDS;
733 
734     TypeAnnotationParsingOptions options =
735         TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
736     auto *extendsType = ParseTsTypeAnnotation(&options);
737 
738     context_.Status() = savedStatus;
739 
740     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
741         ThrowSyntaxError("'?' expected.");
742     }
743 
744     lexer_->NextToken();  // eat '?'
745 
746     options &= ~TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
747     auto *trueType = ParseTsTypeAnnotation(&options);
748 
749     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
750         ThrowSyntaxError("':' expected.");
751     }
752 
753     lexer_->NextToken();  // eat ':'
754 
755     auto *falseType = ParseTsTypeAnnotation(&options);
756 
757     lexer::SourcePosition endLoc = falseType->End();
758 
759     auto *conditionalType = AllocNode<ir::TSConditionalType>(checkType, extendsType, trueType, falseType);
760 
761     conditionalType->SetRange({startLoc, endLoc});
762 
763     return conditionalType;
764 }
765 
ParseTsTypeAnnotation(TypeAnnotationParsingOptions * options)766 ir::Expression *ParserImpl::ParseTsTypeAnnotation(TypeAnnotationParsingOptions *options)
767 {
768     ir::Expression *typeAnnotation = nullptr;
769 
770     while (true) {
771         ir::Expression *element = ParseTsTypeAnnotationElement(typeAnnotation, options);
772 
773         *options &= ~TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
774 
775         if (!element) {
776             break;
777         }
778 
779         typeAnnotation = element;
780 
781         if ((*options & TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE) && lexer_->GetToken().NewLine()) {
782             break;
783         }
784     }
785 
786     return typeAnnotation;
787 }
788 
ParseTsTypeOperatorOrTypeReference(bool throwError)789 ir::Expression *ParserImpl::ParseTsTypeOperatorOrTypeReference(bool throwError)
790 {
791     TypeAnnotationParsingOptions options = throwError ?
792         TypeAnnotationParsingOptions::THROW_ERROR : TypeAnnotationParsingOptions::NO_OPTS;
793 
794     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY) {
795         lexer::SourcePosition typeOperatorStart = lexer_->GetToken().Start();
796         lexer_->NextToken();
797 
798         options |= TypeAnnotationParsingOptions::IN_MODIFIER;
799         ir::Expression *type = ParseTsTypeAnnotation(&options);
800         ASSERT(type != nullptr);
801 
802         if (!type->IsTSArrayType() && !type->IsTSTupleType()) {
803             ThrowSyntaxError(
804                 "'readonly' type modifier is only permitted on array "
805                 "and tuple literal types.");
806         }
807 
808         auto *typeOperator = AllocNode<ir::TSTypeOperator>(type, ir::TSOperatorType::READONLY);
809 
810         typeOperator->SetRange({typeOperatorStart, type->End()});
811 
812         return typeOperator;
813     }
814 
815     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_KEYOF) {
816         lexer::SourcePosition typeOperatorStart = lexer_->GetToken().Start();
817         lexer_->NextToken();
818 
819         options |= TypeAnnotationParsingOptions::IN_MODIFIER;
820         ir::Expression *type = ParseTsTypeAnnotation(&options);
821         ASSERT(type != nullptr);
822 
823         auto *typeOperator = AllocNode<ir::TSTypeOperator>(type, ir::TSOperatorType::KEYOF);
824 
825         typeOperator->SetRange({typeOperatorStart, type->End()});
826 
827         return typeOperator;
828     }
829 
830     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_UNIQUE) {
831         lexer::SourcePosition typeOperatorStart = lexer_->GetToken().Start();
832         lexer_->NextToken();
833 
834         ir::Expression *type = ParseTsTypeAnnotation(&options);
835         ASSERT(type != nullptr);
836 
837         auto *typeOperator = AllocNode<ir::TSTypeOperator>(type, ir::TSOperatorType::UNIQUE);
838 
839         typeOperator->SetRange({typeOperatorStart, type->End()});
840 
841         return typeOperator;
842     }
843 
844     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INFER) {
845         if (!(context_.Status() & ParserStatus::IN_EXTENDS)) {
846             ThrowSyntaxError(
847                 "'infer' declarations are only permitted in the "
848                 "'extends' clause of a conditional type.");
849         }
850 
851         lexer::SourcePosition inferStart = lexer_->GetToken().Start();
852         lexer_->NextToken();
853 
854         ir::TSTypeParameter *typeParam = ParseTsTypeParameter(true);
855 
856         auto *inferType = AllocNode<ir::TSInferType>(typeParam);
857 
858         inferType->SetRange({inferStart, lexer_->GetToken().End()});
859 
860         return inferType;
861     }
862 
863     return ParseTsIdentifierReference(options);
864 }
865 
IsTSNamedTupleMember()866 bool ParserImpl::IsTSNamedTupleMember()
867 {
868     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
869         return false;
870     }
871     const auto savePos = lexer_->Save();
872     bool isNamedMember = false;
873     lexer_->NextToken();
874     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON ||
875         (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK &&
876          lexer_->Lookahead() == LEX_CHAR_COLON)) {
877             isNamedMember = true;
878     }
879     lexer_->Rewind(savePos);
880     return isNamedMember;
881 }
882 
HandleRestType(ir::AstNodeType elementType,bool * hasRestType) const883 void ParserImpl::HandleRestType(ir::AstNodeType elementType, bool *hasRestType) const
884 {
885     if (elementType ==  ir::AstNodeType::TS_ARRAY_TYPE && *hasRestType) {
886         ThrowSyntaxError("A rest element cannot follow another rest element");
887     }
888     *hasRestType = true;
889 }
890 
ParseTsTupleElement(ir::TSTupleKind * kind,bool * seenOptional,bool * hasRestType)891 ir::Expression *ParserImpl::ParseTsTupleElement(ir::TSTupleKind *kind, bool *seenOptional, bool *hasRestType)
892 {
893     lexer::SourcePosition startPos = lexer_->GetToken().Start();
894     ir::Expression *element = nullptr;
895     bool isRestType = false;
896     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
897 
898     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
899         isRestType = true;
900         lexer_->NextToken();  // eat '...'
901     }
902 
903     if (IsTSNamedTupleMember()) {
904         if (*kind == ir::TSTupleKind::DEFAULT) {
905             ThrowSyntaxError("Tuple members must all have or haven't names");
906         }
907         *kind = ir::TSTupleKind::NAMED;
908 
909         auto *elementIdent = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
910         elementIdent->SetRange(lexer_->GetToken().Loc());
911         lexer_->NextToken();  // eat identifier
912 
913         bool isOptional = false;
914         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
915             lexer_->NextToken();  // eat '?'
916             isOptional = true;
917             *seenOptional = true;
918         } else if (*seenOptional && !isRestType) {
919             ThrowSyntaxError("A required element cannot follow an optional element");
920         }
921 
922         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
923             ThrowSyntaxError("':' expected");
924         }
925 
926         lexer_->NextToken();  // eat ':'
927         auto *elementType = ParseTsTypeAnnotation(&options);
928         ASSERT(elementType != nullptr);
929 
930         if (elementType && isRestType) {
931             HandleRestType(elementType->Type(), hasRestType);
932         }
933 
934         element = AllocNode<ir::TSNamedTupleMember>(elementIdent, elementType, isOptional, isRestType);
935         element->SetRange({startPos, elementType->End()});
936     } else {
937         if (*kind == ir::TSTupleKind::NAMED) {
938             ThrowSyntaxError("Tuple members must all have or haven't names");
939         }
940         *kind = ir::TSTupleKind::DEFAULT;
941 
942         element = ParseTsTypeAnnotation(&options);
943         ASSERT(element != nullptr);
944         if (element && isRestType) {
945             HandleRestType(element->Type(), hasRestType);
946             lexer::SourcePosition endPos = element->End();
947             element = AllocNode<ir::TSRestType>(std::move(element));
948             element->SetRange({startPos, endPos});
949         }
950 
951         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
952             lexer::SourcePosition elementStartPos = element->Start();
953             element = AllocNode<ir::TSOptionalType>(std::move(element));
954             element->SetRange({elementStartPos, lexer_->GetToken().End()});
955             lexer_->NextToken();  // eat '?'
956             *seenOptional = true;
957         } else if (*seenOptional && !isRestType) {
958             ThrowSyntaxError("A required element cannot follow an optional element");
959         }
960     }
961     return element;
962 }
963 
ParseTsTupleType()964 ir::TSTupleType *ParserImpl::ParseTsTupleType()
965 {
966     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
967     lexer::SourcePosition tupleStart = lexer_->GetToken().Start();
968     ArenaVector<ir::Expression *> elements(Allocator()->Adapter());
969     ir::TSTupleKind kind = ir::TSTupleKind::NONE;
970     bool seenOptional = false;
971     bool hasRestType = false;
972 
973     lexer_->NextToken();  // eat '['
974 
975     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
976         ir::Expression *element = ParseTsTupleElement(&kind, &seenOptional, &hasRestType);
977 
978         elements.push_back(element);
979 
980         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
981             break;
982         }
983 
984         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
985             ThrowSyntaxError("',' expected.");
986         }
987 
988         lexer_->NextToken();  // eat ','
989     }
990 
991     lexer::SourcePosition tupleEnd = lexer_->GetToken().End();
992     lexer_->NextToken();  // eat ']'
993 
994     auto *tupleType = AllocNode<ir::TSTupleType>(std::move(elements));
995     tupleType->SetRange({tupleStart, tupleEnd});
996     return tupleType;
997 }
998 
ParseTsQualifiedReference(ir::Expression * typeName)999 ir::Expression *ParserImpl::ParseTsQualifiedReference(ir::Expression *typeName)
1000 {
1001     lexer::SourcePosition startLoc = typeName->Start();
1002 
1003     do {
1004         lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '.'
1005 
1006         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1007             ThrowSyntaxError("Identifier expected");
1008         }
1009 
1010         auto *propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1011         propName->SetRange(lexer_->GetToken().Loc());
1012 
1013         typeName = AllocNode<ir::TSQualifiedName>(typeName, propName);
1014         typeName->SetRange({typeName->AsTSQualifiedName()->Left()->Start(), lexer_->GetToken().End()});
1015 
1016         lexer_->NextToken();
1017     } while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD);
1018 
1019     typeName->SetRange({startLoc, lexer_->GetToken().End()});
1020 
1021     return typeName;
1022 }
1023 
ParseTsIndexAccessType(ir::Expression * typeName,bool throwError)1024 ir::Expression *ParserImpl::ParseTsIndexAccessType(ir::Expression *typeName, bool throwError)
1025 {
1026     TypeAnnotationParsingOptions options = throwError ?
1027         TypeAnnotationParsingOptions::THROW_ERROR : TypeAnnotationParsingOptions::NO_OPTS;
1028 
1029     do {
1030         lexer_->NextToken();  // eat '['
1031 
1032         ir::Expression *indexType = ParseTsTypeAnnotation(&options);
1033 
1034         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1035             if (!throwError) {
1036                 return nullptr;
1037             }
1038             ThrowSyntaxError("']' expected");
1039         }
1040 
1041         lexer_->NextToken();  // eat ']'
1042 
1043         typeName = AllocNode<ir::TSIndexedAccessType>(typeName, indexType);
1044         typeName->SetRange({typeName->AsTSIndexedAccessType()->ObjectType()->Start(), lexer_->GetToken().End()});
1045     } while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET &&
1046              lexer_->Lookahead() != LEX_CHAR_RIGHT_SQUARE);
1047 
1048     return typeName;
1049 }
1050 
ParseTsTypeReferenceOrQuery(TypeAnnotationParsingOptions options,bool parseQuery)1051 ir::Expression *ParserImpl::ParseTsTypeReferenceOrQuery(TypeAnnotationParsingOptions options, bool parseQuery)
1052 {
1053     lexer::SourcePosition referenceStartLoc = lexer_->GetToken().Start();
1054 
1055     if (parseQuery) {
1056         ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_TYPEOF);
1057         lexer_->NextToken();  // eat 'typeof'
1058 
1059         if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IMPORT) {
1060             lexer::SourcePosition &startLoc = referenceStartLoc;
1061             return ParseTsImportType(startLoc, true);
1062         }
1063 
1064         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1065             ThrowSyntaxError("Identifier expected.");
1066         }
1067     }
1068 
1069     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
1070            lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS);
1071 
1072     ir::Expression *typeName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1073     typeName->SetRange(lexer_->GetToken().Loc());
1074     typeName->AsIdentifier()->SetReference();
1075 
1076     if (lexer_->Lookahead() == LEX_CHAR_LESS_THAN) {
1077         lexer_->ForwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
1078     } else {
1079         lexer_->NextToken();
1080     }
1081 
1082     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
1083         typeName = ParseTsQualifiedReference(typeName);
1084     }
1085 
1086     ir::TSTypeParameterInstantiation *typeParamInst = nullptr;
1087     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1088         if (parseQuery) {
1089             ThrowSyntaxError("Unexpected token.");
1090         }
1091 
1092         typeParamInst = ParseTsTypeParameterInstantiation(options & TypeAnnotationParsingOptions::THROW_ERROR);
1093     }
1094 
1095     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET &&
1096         lexer_->Lookahead() != LEX_CHAR_RIGHT_SQUARE) {
1097         if (parseQuery) {
1098             typeName = AllocNode<ir::TSTypeQuery>(typeName);
1099         } else {
1100             typeName = AllocNode<ir::TSTypeReference>(typeName, typeParamInst);
1101         }
1102 
1103         typeName->SetRange({referenceStartLoc, lexer_->GetToken().End()});
1104 
1105         return ParseTsIndexAccessType(typeName, options & TypeAnnotationParsingOptions::THROW_ERROR);
1106     }
1107 
1108     ir::Expression *returnNode = nullptr;
1109 
1110     lexer::SourcePosition referenceEndLoc = typeName->End();
1111 
1112     if (parseQuery) {
1113         returnNode = AllocNode<ir::TSTypeQuery>(typeName);
1114     } else {
1115         returnNode = AllocNode<ir::TSTypeReference>(typeName, typeParamInst);
1116     }
1117 
1118     returnNode->SetRange({referenceStartLoc, referenceEndLoc});
1119 
1120     return returnNode;
1121 }
1122 
ParseTsMappedTypeParameter()1123 ir::TSTypeParameter *ParserImpl::ParseTsMappedTypeParameter()
1124 {
1125     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1126 
1127     auto *paramName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1128     paramName->SetRange({lexer_->GetToken().Start(), lexer_->GetToken().End()});
1129 
1130     lexer_->NextToken();
1131 
1132     lexer_->NextToken();  // eat 'in'
1133 
1134     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1135     ir::Expression *constraint = ParseTsTypeAnnotation(&options);
1136 
1137     lexer::SourcePosition endLoc = constraint->End();
1138 
1139     auto *typeParameter = AllocNode<ir::TSTypeParameter>(paramName, constraint, nullptr);
1140 
1141     typeParameter->SetRange({startLoc, endLoc});
1142 
1143     return typeParameter;
1144 }
1145 
ParseMappedOption(lexer::TokenType tokenType)1146 ir::MappedOption ParserImpl::ParseMappedOption(lexer::TokenType tokenType)
1147 {
1148     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MINUS &&
1149         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PLUS &&
1150         lexer_->GetToken().KeywordType() != tokenType && lexer_->GetToken().Type() != tokenType) {
1151         return ir::MappedOption::NO_OPTS;
1152     }
1153 
1154     auto result = lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ? ir::MappedOption::MINUS
1155                                                                                   : ir::MappedOption::PLUS;
1156 
1157     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS ||
1158         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PLUS) {
1159         lexer_->NextToken();
1160     }
1161 
1162     if (lexer_->GetToken().KeywordType() != tokenType && lexer_->GetToken().Type() != tokenType) {
1163         ThrowSyntaxError({"'", TokenToString(tokenType), "' expected."});
1164     }
1165 
1166     lexer_->NextToken();
1167 
1168     return result;
1169 }
1170 
ParseTsMappedType()1171 ir::TSMappedType *ParserImpl::ParseTsMappedType()
1172 {
1173     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
1174 
1175     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1176     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
1177 
1178     ir::MappedOption readonly = ParseMappedOption(lexer::TokenType::KEYW_READONLY);
1179 
1180     lexer_->NextToken();  // eat '['
1181 
1182     ir::TSTypeParameter *typeParameter = ParseTsMappedTypeParameter();
1183 
1184     ir::Expression *nameKeyType = nullptr;
1185     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
1186         lexer_->NextToken();  // eat 'as'
1187         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1188         nameKeyType = ParseTsTypeAnnotation(&options);
1189         ASSERT(nameKeyType != nullptr);
1190     }
1191 
1192     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1193         ThrowSyntaxError("']' expected");
1194     }
1195 
1196     lexer_->NextToken();  // eat ']'
1197 
1198     ir::MappedOption optional = ParseMappedOption(lexer::TokenType::PUNCTUATOR_QUESTION_MARK);
1199 
1200     ir::Expression *typeAnnotation = nullptr;
1201     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1202         lexer_->NextToken();  // eat ':'
1203         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1204         typeAnnotation = ParseTsTypeAnnotation(&options);
1205     }
1206 
1207     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
1208         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1209         ThrowSyntaxError("';' expected");
1210     }
1211 
1212     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1213         lexer_->NextToken();  // eat ';'
1214     }
1215 
1216     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1217         ThrowSyntaxError("'}' expected");
1218     }
1219 
1220     auto *mappedType = AllocNode<ir::TSMappedType>(typeParameter, nameKeyType, typeAnnotation, readonly, optional);
1221 
1222     mappedType->SetRange({startLoc, lexer_->GetToken().End()});
1223 
1224     lexer_->NextToken();  // eat '}'
1225 
1226     return mappedType;
1227 }
1228 
ParseTsTypePredicate()1229 ir::TSTypePredicate *ParserImpl::ParseTsTypePredicate()
1230 {
1231     auto pos = lexer_->Save();
1232     lexer::SourcePosition startPos = lexer_->GetToken().Start();
1233     bool isAsserts = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ASSERTS;
1234     if (isAsserts) {
1235         lexer_->NextToken();  // eat 'asserts'
1236         if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IS) {
1237             isAsserts = false;
1238             lexer_->Rewind(pos);
1239         }
1240     }
1241 
1242     ir::Expression *parameterName = nullptr;
1243     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1244         parameterName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1245     } else {
1246         parameterName = AllocNode<ir::TSThisType>();
1247     }
1248 
1249     parameterName->SetRange({lexer_->GetToken().Start(), lexer_->GetToken().End()});
1250 
1251     lexer_->NextToken();
1252 
1253     ir::Expression *typeAnnotation = nullptr;
1254     lexer::SourcePosition endPos;
1255     ir::TSTypePredicate *result = nullptr;
1256 
1257     if (isAsserts && lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_IS) {
1258         endPos = parameterName->End();
1259         result = AllocNode<ir::TSTypePredicate>(parameterName, typeAnnotation, isAsserts);
1260         result->SetRange({startPos, endPos});
1261         return result;
1262     }
1263 
1264     lexer_->NextToken();  // eat 'is'
1265 
1266     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1267     typeAnnotation = ParseTsTypeAnnotation(&options);
1268     endPos = typeAnnotation->End();
1269 
1270     result = AllocNode<ir::TSTypePredicate>(parameterName, typeAnnotation, isAsserts);
1271 
1272     result->SetRange({startPos, endPos});
1273 
1274     return result;
1275 }
1276 
ParseTsTypeLiteralOrInterfaceKey(bool * computed,bool * signature,bool * isIndexSignature)1277 ir::Expression *ParserImpl::ParseTsTypeLiteralOrInterfaceKey(bool *computed, bool *signature, bool *isIndexSignature)
1278 {
1279     ir::Expression *key = nullptr;
1280 
1281     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
1282         (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_NEW ||
1283          (lexer_->Lookahead() != LEX_CHAR_LEFT_PAREN && lexer_->Lookahead() != LEX_CHAR_LESS_THAN))) {
1284         key = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1285         key->SetRange(lexer_->GetToken().Loc());
1286         lexer_->NextToken();
1287     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NUMBER) {
1288         if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
1289             key = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
1290         } else {
1291             key = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
1292         }
1293 
1294         key->SetRange(lexer_->GetToken().Loc());
1295         lexer_->NextToken();
1296     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
1297         key = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
1298         key->SetRange(lexer_->GetToken().Loc());
1299         lexer_->NextToken();
1300     } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1301         *computed = true;
1302         lexer_->NextToken();  // eat '['
1303 
1304         if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && lexer_->Lookahead() == LEX_CHAR_COLON) {
1305             *isIndexSignature = true;
1306             key = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1307             key->SetRange(lexer_->GetToken().Loc());
1308 
1309             lexer_->NextToken();  // eat param
1310 
1311             if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
1312                 ThrowSyntaxError("':' expected");
1313             }
1314 
1315             lexer_->NextToken();  // eat ':'
1316 
1317             TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1318             ir::Expression *typeAnnotation = ParseTsTypeAnnotation(&options);
1319 
1320             if (!typeAnnotation->IsTSNumberKeyword() && !typeAnnotation->IsTSStringKeyword()) {
1321                 ThrowSyntaxError(
1322                     "An index signature parameter type must be either "
1323                     "'string' or 'number'");
1324             }
1325 
1326             key->SetTsTypeAnnotation(typeAnnotation);
1327         } else {
1328             key = ParseExpression();
1329         }
1330 
1331         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1332             ThrowSyntaxError("']' expected");
1333         }
1334 
1335         lexer_->NextToken();  // eat ']'
1336     } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1337                lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN &&
1338                lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_NEW) {
1339         ThrowSyntaxError("Unexpected token");
1340     } else {
1341         *signature = true;
1342     }
1343 
1344     return key;
1345 }
1346 
CreateTSVariableForProperty(ir::AstNode * node,const ir::Expression * key,binder::VariableFlags flags)1347 void ParserImpl::CreateTSVariableForProperty(ir::AstNode *node, const ir::Expression *key, binder::VariableFlags flags)
1348 {
1349     binder::Variable *propVar = nullptr;
1350     bool isMethod = flags & binder::VariableFlags::METHOD;
1351     util::StringView propName = "__computed";
1352 
1353     switch (key->Type()) {
1354         case ir::AstNodeType::IDENTIFIER: {
1355             propName = key->AsIdentifier()->Name();
1356             break;
1357         }
1358         case ir::AstNodeType::NUMBER_LITERAL: {
1359             propName = key->AsNumberLiteral()->Str();
1360             flags |= binder::VariableFlags::NUMERIC_NAME;
1361             break;
1362         }
1363         case ir::AstNodeType::STRING_LITERAL: {
1364             propName = key->AsStringLiteral()->Str();
1365             break;
1366         }
1367         default: {
1368             flags |= binder::VariableFlags::COMPUTED;
1369             break;
1370         }
1371     }
1372 
1373     propVar = isMethod ? binder::Scope::CreateVar<binder::MethodDecl>(Allocator(), propName, flags, node)
1374                        : binder::Scope::CreateVar<binder::PropertyDecl>(Allocator(), propName, flags, node);
1375 
1376     node->SetVariable(propVar);
1377 }
1378 
ParseTsTypeLiteralOrInterfaceMember()1379 ir::Expression *ParserImpl::ParseTsTypeLiteralOrInterfaceMember()
1380 {
1381     bool computed = false;
1382     bool optional = false;
1383     bool signature = false;
1384     bool readonly = false;
1385     bool isConstructSignature = false;
1386     bool isIndexSignature = false;
1387     lexer::SourcePosition memberStartLoc = lexer_->GetToken().Start();
1388     char32_t nextToken = lexer_->Lookahead();
1389     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY && nextToken != LEX_CHAR_LEFT_PAREN &&
1390         nextToken != LEX_CHAR_COLON && nextToken != LEX_CHAR_COMMA && nextToken != LEX_CHAR_LESS_THAN &&
1391         nextToken != LEX_CHAR_SEMICOLON) {
1392         readonly = true;
1393         lexer_->NextToken();
1394     }
1395 
1396     ir::Expression *key = ParseTsTypeLiteralOrInterfaceKey(&computed, &signature, &isIndexSignature);
1397 
1398     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
1399         if (isIndexSignature) {
1400             ThrowSyntaxError("';' expected");
1401         }
1402 
1403         optional = true;
1404         lexer_->NextToken();  // eat '?'
1405     }
1406 
1407     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NEW && signature) {
1408         lexer_->NextToken();  // eat 'new'
1409 
1410         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1411             lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1412             ThrowSyntaxError("'(' expected");
1413         }
1414 
1415         isConstructSignature = true;
1416     }
1417 
1418     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
1419     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1420         if (isIndexSignature) {
1421             ThrowSyntaxError("';' expected");
1422         }
1423 
1424         typeParamDecl = ParseTsTypeParameterDeclaration();
1425 
1426         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1427             ThrowSyntaxError("'(' expected");
1428         }
1429     }
1430 
1431     ir::Expression *member = nullptr;
1432     ir::Expression *typeAnnotation = nullptr;
1433     binder::VariableFlags flags = binder::VariableFlags::NONE;
1434 
1435     if (optional) {
1436         flags |= binder::VariableFlags::OPTIONAL;
1437     }
1438 
1439     if (readonly) {
1440         flags |= binder::VariableFlags::READONLY;
1441     }
1442 
1443     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && !isIndexSignature) {
1444         FunctionParameterContext funcParamContext(&context_, Binder());
1445         auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
1446         ArenaVector<ir::Expression *> params = ParseFunctionParams(true);
1447 
1448         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1449             lexer_->NextToken();  // eat ':'
1450             TypeAnnotationParsingOptions options =
1451                 TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
1452             typeAnnotation = ParseTsTypeAnnotation(&options);
1453         }
1454 
1455         if (signature) {
1456             auto kind = isConstructSignature
1457                             ? ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CONSTRUCT_SIGNATURE
1458                             : ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CALL_SIGNATURE;
1459             member = AllocNode<ir::TSSignatureDeclaration>(funcParamScope, kind, typeParamDecl, std::move(params),
1460                                                            typeAnnotation);
1461             funcParamScope->BindNode(member);
1462         } else {
1463             member = AllocNode<ir::TSMethodSignature>(funcParamScope, key, typeParamDecl, std::move(params),
1464                                                       typeAnnotation, computed, optional);
1465             funcParamScope->BindNode(member);
1466             CreateTSVariableForProperty(member, key, flags | binder::VariableFlags::METHOD);
1467         }
1468     } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1469         lexer_->NextToken();  // eat ':'
1470         TypeAnnotationParsingOptions options =
1471             TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE;
1472         typeAnnotation = ParseTsTypeAnnotation(&options);
1473     } else if (isIndexSignature) {
1474         ThrowSyntaxError("An index signature must have a type annotation.", memberStartLoc);
1475     }
1476 
1477     if (!member && isIndexSignature) {
1478         member = AllocNode<ir::TSIndexSignature>(key, typeAnnotation, readonly);
1479     } else if (!member) {
1480         member = AllocNode<ir::TSPropertySignature>(key, typeAnnotation, computed, optional, readonly);
1481         CreateTSVariableForProperty(member, key, flags | binder::VariableFlags::PROPERTY);
1482     } else if (readonly) {
1483         ThrowSyntaxError(
1484             "'readonly' modifier can only appear on a property "
1485             "declaration or index signature.",
1486             memberStartLoc);
1487     }
1488 
1489     member->SetRange({memberStartLoc, lexer_->GetToken().End()});
1490 
1491     return member;
1492 }
1493 
GetTSPropertyName(ir::Expression * key)1494 util::StringView GetTSPropertyName(ir::Expression *key)
1495 {
1496     switch (key->Type()) {
1497         case ir::AstNodeType::IDENTIFIER: {
1498             return key->AsIdentifier()->Name();
1499         }
1500         case ir::AstNodeType::NUMBER_LITERAL: {
1501             return key->AsNumberLiteral()->Str();
1502         }
1503         case ir::AstNodeType::STRING_LITERAL: {
1504             return key->AsStringLiteral()->Str();
1505         }
1506         default: {
1507             UNREACHABLE();
1508         }
1509     }
1510 }
1511 
CheckObjectTypeForDuplicatedProperties(ir::Expression * member,ArenaVector<ir::Expression * > const & members)1512 void ParserImpl::CheckObjectTypeForDuplicatedProperties(ir::Expression *member,
1513     ArenaVector<ir::Expression *> const &members)
1514 {
1515     ir::Expression *key = nullptr;
1516 
1517     if (member->IsTSPropertySignature()) {
1518         key = member->AsTSPropertySignature()->Key();
1519     } else if (member->IsTSMethodSignature()) {
1520         key = member->AsTSMethodSignature()->Key();
1521     } else {
1522         return;
1523     }
1524 
1525     if (!key->IsIdentifier() && !key->IsNumberLiteral() && !key->IsStringLiteral()) {
1526         return;
1527     }
1528 
1529     for (auto *it : members) {
1530         ir::Expression *compare = nullptr;
1531 
1532         switch (it->Type()) {
1533             case ir::AstNodeType::TS_PROPERTY_SIGNATURE: {
1534                 compare = it->AsTSPropertySignature()->Key();
1535                 break;
1536             }
1537             case ir::AstNodeType::TS_METHOD_SIGNATURE: {
1538                 compare = it->AsTSMethodSignature()->Key();
1539                 break;
1540             }
1541             default: {
1542                 continue;
1543             }
1544         }
1545 
1546         if (!compare->IsIdentifier() && !compare->IsNumberLiteral() && !compare->IsStringLiteral()) {
1547             continue;
1548         }
1549 
1550         if (member->IsTSMethodSignature() && it->Type() == ir::AstNodeType::TS_METHOD_SIGNATURE) {
1551             continue;
1552         }
1553 
1554         if (GetTSPropertyName(key) == GetTSPropertyName(compare)) {
1555             ThrowSyntaxError("Duplicated identifier", key->Start());
1556         }
1557     }
1558 }
1559 
ParseTsTypeLiteralOrInterface()1560 ArenaVector<ir::Expression *> ParserImpl::ParseTsTypeLiteralOrInterface()
1561 {
1562     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
1563 
1564     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
1565 
1566     ArenaVector<ir::Expression *> members(Allocator()->Adapter());
1567 
1568     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1569         ir::Expression *member = ParseTsTypeLiteralOrInterfaceMember();
1570 
1571         CheckObjectTypeForDuplicatedProperties(member, members);
1572 
1573         members.push_back(member);
1574 
1575         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1576             break;
1577         }
1578 
1579         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
1580             lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1581             if (!lexer_->GetToken().NewLine()) {
1582                 ThrowSyntaxError("',' expected");
1583             }
1584 
1585             if (lexer_->GetToken().IsKeyword()) {
1586                 lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
1587             }
1588 
1589             continue;
1590         }
1591 
1592         lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
1593     }
1594 
1595     return members;
1596 }
1597 
ParseTsArrayType(ir::Expression * elementType)1598 ir::TSArrayType *ParserImpl::ParseTsArrayType(ir::Expression *elementType)
1599 {
1600     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
1601     lexer_->NextToken();  // eat '['
1602 
1603     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1604         ThrowSyntaxError("']' expected");
1605     }
1606 
1607     lexer::SourcePosition endLoc = lexer_->GetToken().End();
1608     lexer_->NextToken();  // eat ']'
1609 
1610     lexer::SourcePosition startLoc = elementType->Start();
1611     auto *arrayType = AllocNode<ir::TSArrayType>(elementType);
1612     arrayType->SetRange({startLoc, endLoc});
1613 
1614     return arrayType;
1615 }
1616 
ParseTsUnionType(ir::Expression * type,bool restrictExtends)1617 ir::TSUnionType *ParserImpl::ParseTsUnionType(ir::Expression *type, bool restrictExtends)
1618 {
1619     ArenaVector<ir::Expression *> types(Allocator()->Adapter());
1620     lexer::SourcePosition startLoc;
1621 
1622     TypeAnnotationParsingOptions options =
1623         TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::IN_UNION;
1624 
1625     if (restrictExtends) {
1626         options |= TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
1627     }
1628 
1629     if (type) {
1630         startLoc = type->Start();
1631         types.push_back(type);
1632     } else {
1633         startLoc = lexer_->GetToken().Start();
1634     }
1635 
1636     while (true) {
1637         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
1638             break;
1639         }
1640 
1641         lexer_->NextToken();  // eat '|'
1642 
1643         types.push_back(ParseTsTypeAnnotation(&options));
1644     }
1645 
1646     lexer::SourcePosition endLoc = types.back()->End();
1647 
1648     auto *unionType = AllocNode<ir::TSUnionType>(std::move(types));
1649     auto *typeVar = binder::Scope::CreateVar(Allocator(), "__type", binder::VariableFlags::TYPE, unionType);
1650     unionType->SetVariable(typeVar);
1651     unionType->SetRange({startLoc, endLoc});
1652 
1653     return unionType;
1654 }
1655 
ParseTsIntersectionType(ir::Expression * type,bool inUnion,bool restrictExtends)1656 ir::TSIntersectionType *ParserImpl::ParseTsIntersectionType(ir::Expression *type, bool inUnion, bool restrictExtends)
1657 {
1658     ArenaVector<ir::Expression *> types(Allocator()->Adapter());
1659     lexer::SourcePosition startLoc;
1660 
1661     TypeAnnotationParsingOptions options =
1662         TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::IN_INTERSECTION;
1663 
1664     if (restrictExtends) {
1665         options |= TypeAnnotationParsingOptions::RESTRICT_EXTENDS;
1666     }
1667 
1668     if (inUnion) {
1669         options |= TypeAnnotationParsingOptions::IN_UNION;
1670     }
1671 
1672     if (type) {
1673         startLoc = type->Start();
1674         types.push_back(type);
1675     } else {
1676         startLoc = lexer_->GetToken().Start();
1677     }
1678 
1679     while (true) {
1680         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_BITWISE_AND) {
1681             break;
1682         }
1683 
1684         lexer_->NextToken();  // eat '&'
1685 
1686         types.push_back(ParseTsTypeAnnotation(&options));
1687     }
1688 
1689     lexer::SourcePosition endLoc = types.back()->End();
1690 
1691     auto *intersectionType = AllocNode<ir::TSIntersectionType>(std::move(types));
1692     auto *typeVar = binder::Scope::CreateVar(Allocator(), "__type", binder::VariableFlags::TYPE, intersectionType);
1693     intersectionType->SetVariable(typeVar);
1694     intersectionType->SetRange({startLoc, endLoc});
1695 
1696     return intersectionType;
1697 }
1698 
IsTsFunctionType()1699 bool ParserImpl::IsTsFunctionType()
1700 {
1701     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1702     const auto startPos = lexer_->Save();
1703     lexer_->NextToken();  // eat '('
1704     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS ||
1705         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
1706         lexer_->Rewind(startPos);
1707         return true;
1708     }
1709 
1710     try {
1711         ParseModifiers();
1712         if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
1713             (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS)) {
1714             lexer_->NextToken();
1715         } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1716             ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1717         } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1718             ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN);
1719         } else {
1720             lexer_->Rewind(startPos);
1721             return false;
1722         }
1723     } catch ([[maybe_unused]] const class Error &e) {
1724         lexer_->Rewind(startPos);
1725         return false;
1726     }
1727 
1728     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA ||
1729         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK ||
1730         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON ||
1731         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EQUAL) {
1732         lexer_->Rewind(startPos);
1733         return true;
1734     }
1735 
1736     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1737         lexer_->NextToken();  // eat ')'
1738         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) {
1739             lexer_->Rewind(startPos);
1740             return true;
1741         }
1742     }
1743     lexer_->Rewind(startPos);
1744     return false;
1745 }
1746 
ParseTsParenthesizedOrFunctionType(ir::Expression * typeAnnotation,bool throwError)1747 ir::Expression *ParserImpl::ParseTsParenthesizedOrFunctionType(ir::Expression *typeAnnotation, bool throwError)
1748 {
1749     if (typeAnnotation) {
1750         return nullptr;
1751     }
1752 
1753     lexer::SourcePosition typeStart = lexer_->GetToken().Start();
1754 
1755     bool abstractConstructor = lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT;
1756     if (abstractConstructor) {
1757         lexer_->NextToken();  // eat 'abstract'
1758     }
1759 
1760     bool isConstructionType = false;
1761 
1762     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_NEW) {
1763         lexer_->NextToken();  // eat 'new'
1764         isConstructionType = true;
1765 
1766         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1767             lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1768             if (!throwError) {
1769                 return nullptr;
1770             }
1771             ThrowSyntaxError("'(' expected");
1772         }
1773     }
1774 
1775     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN || isConstructionType) {
1776         return ParseTsFunctionType(typeStart, isConstructionType, throwError, abstractConstructor);
1777     }
1778 
1779     if (IsTsFunctionType()) {
1780         return ParseTsFunctionType(typeStart, false, throwError);
1781     }
1782 
1783     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1784     lexer_->NextToken();  // eat '('
1785 
1786     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
1787     ir::Expression *type = ParseTsTypeAnnotation(&options);
1788 
1789     if (throwError && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1790         ThrowSyntaxError("')' expected");
1791     }
1792 
1793     lexer::SourcePosition endLoc = lexer_->GetToken().End();
1794     lexer_->NextToken();  // eat ')'
1795 
1796     auto *result = AllocNode<ir::TSParenthesizedType>(type);
1797     result->SetRange({typeStart, endLoc});
1798 
1799     return result;
1800 }
1801 
ParseTsFunctionType(lexer::SourcePosition startLoc,bool isConstructionType,bool throwError,bool abstractConstructor)1802 ir::Expression *ParserImpl::ParseTsFunctionType(lexer::SourcePosition startLoc, bool isConstructionType,
1803                                                 bool throwError, bool abstractConstructor)
1804 {
1805     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
1806     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1807         typeParamDecl = ParseTsTypeParameterDeclaration(throwError);
1808 
1809         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1810             if (!throwError) {
1811                 return nullptr;
1812             }
1813 
1814             ThrowSyntaxError("'(' expected");
1815         }
1816     }
1817 
1818     FunctionParameterContext funcParamContext(&context_, Binder());
1819     auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
1820 
1821     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
1822     try {
1823         params = ParseFunctionParams(true);
1824     } catch (const Error &e) {
1825         if (!throwError) {
1826             return nullptr;
1827         }
1828         throw e;
1829     }
1830 
1831     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
1832         ThrowSyntaxError("'=>' expected");
1833     }
1834 
1835     lexer_->NextToken();  // eat '=>'
1836 
1837     TypeAnnotationParsingOptions options =
1838         TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
1839     ir::Expression *returnTypeAnnotation = ParseTsTypeAnnotation(&options);
1840 
1841     ir::Expression *funcType = nullptr;
1842 
1843     if (isConstructionType) {
1844         funcType = AllocNode<ir::TSConstructorType>(funcParamScope, std::move(params), typeParamDecl,
1845                                                     returnTypeAnnotation, abstractConstructor);
1846     } else {
1847         funcType =
1848             AllocNode<ir::TSFunctionType>(funcParamScope, std::move(params), typeParamDecl, returnTypeAnnotation);
1849     }
1850 
1851     funcType->SetRange({startLoc, returnTypeAnnotation->End()});
1852     funcParamScope->BindNode(funcType);
1853 
1854     return funcType;
1855 }
1856 
ParseTsBasicType(TypeAnnotationParsingOptions options)1857 ir::Expression *ParserImpl::ParseTsBasicType(TypeAnnotationParsingOptions options)
1858 {
1859     ir::Expression *typeAnnotation = nullptr;
1860 
1861     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS) {
1862         lexer_->NextToken();
1863 
1864         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_NUMBER) {
1865             if (options & TypeAnnotationParsingOptions::THROW_ERROR) {
1866                 ThrowSyntaxError("Type expected");
1867             } else {
1868                 return nullptr;
1869             }
1870         }
1871     }
1872     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NUMBER) {
1873         if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
1874             auto *bigintNode = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
1875             bigintNode->SetRange(lexer_->GetToken().Loc());
1876 
1877             typeAnnotation = AllocNode<ir::TSLiteralType>(bigintNode);
1878         } else {
1879             auto *numberNode = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
1880             numberNode->SetRange(lexer_->GetToken().Loc());
1881 
1882             typeAnnotation = AllocNode<ir::TSLiteralType>(numberNode);
1883         }
1884     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
1885         auto *stringNode = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
1886         stringNode->SetRange(lexer_->GetToken().Loc());
1887 
1888         typeAnnotation = AllocNode<ir::TSLiteralType>(stringNode);
1889     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_TRUE) {
1890         auto *booleanLiteral = AllocNode<ir::BooleanLiteral>(true);
1891         booleanLiteral->SetRange(lexer_->GetToken().Loc());
1892 
1893         typeAnnotation = AllocNode<ir::TSLiteralType>(booleanLiteral);
1894     } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_FALSE) {
1895         auto *booleanLiteral = AllocNode<ir::BooleanLiteral>(false);
1896         booleanLiteral->SetRange(lexer_->GetToken().Loc());
1897 
1898         typeAnnotation = AllocNode<ir::TSLiteralType>(booleanLiteral);
1899     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ANY) {
1900         typeAnnotation = AllocNode<ir::TSAnyKeyword>();
1901     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_BOOLEAN) {
1902         typeAnnotation = AllocNode<ir::TSBooleanKeyword>();
1903     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NUMBER) {
1904         typeAnnotation = AllocNode<ir::TSNumberKeyword>();
1905     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_STRING) {
1906         typeAnnotation = AllocNode<ir::TSStringKeyword>();
1907     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_UNKNOWN) {
1908         typeAnnotation = AllocNode<ir::TSUnknownKeyword>();
1909     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_VOID) {
1910         typeAnnotation = AllocNode<ir::TSVoidKeyword>();
1911     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::LITERAL_NULL) {
1912         typeAnnotation = AllocNode<ir::TSNullKeyword>();
1913     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_UNDEFINED) {
1914         typeAnnotation = AllocNode<ir::TSUndefinedKeyword>();
1915     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NEVER) {
1916         typeAnnotation = AllocNode<ir::TSNeverKeyword>();
1917     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OBJECT) {
1918         typeAnnotation = AllocNode<ir::TSObjectKeyword>();
1919     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_BIGINT) {
1920         typeAnnotation = AllocNode<ir::TSBigintKeyword>();
1921     } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_SYMBOL) {
1922         typeAnnotation = AllocNode<ir::TSSymbolKeyword>();
1923     } else {
1924         ThrowSyntaxError("Unexpected type");
1925     }
1926 
1927     typeAnnotation->SetRange(lexer_->GetToken().Loc());
1928 
1929     lexer_->NextToken();
1930     return typeAnnotation;
1931 }
1932 
GetAccessability(ir::ModifierFlags modifiers)1933 static ir::ModifierFlags GetAccessability(ir::ModifierFlags modifiers)
1934 {
1935     if (modifiers & ir::ModifierFlags::PUBLIC) {
1936         return ir::ModifierFlags::PUBLIC;
1937     }
1938 
1939     if (modifiers & ir::ModifierFlags::PRIVATE) {
1940         return ir::ModifierFlags::PRIVATE;
1941     }
1942 
1943     if (modifiers & ir::ModifierFlags::PROTECTED) {
1944         return ir::ModifierFlags::PROTECTED;
1945     }
1946 
1947     return ir::ModifierFlags::NONE;
1948 }
1949 
IsModifierKind(const lexer::Token & token)1950 static bool IsModifierKind(const lexer::Token &token)
1951 {
1952     if (token.Type() == lexer::TokenType::LITERAL_IDENT) {
1953         switch (token.KeywordType()) {
1954             case lexer::TokenType::KEYW_PUBLIC:
1955             case lexer::TokenType::KEYW_PRIVATE:
1956             case lexer::TokenType::KEYW_PROTECTED:
1957             case lexer::TokenType::KEYW_STATIC:
1958             case lexer::TokenType::KEYW_ASYNC:
1959             case lexer::TokenType::KEYW_ABSTRACT:
1960             case lexer::TokenType::KEYW_DECLARE:
1961             case lexer::TokenType::KEYW_READONLY:
1962                 return true;
1963             default:
1964                 return false;
1965         }
1966     }
1967 
1968     return false;
1969 }
1970 
ParseModifiers()1971 ir::ModifierFlags ParserImpl::ParseModifiers()
1972 {
1973     ir::ModifierFlags resultStatus = ir::ModifierFlags::NONE;
1974     ir::ModifierFlags prevStatus = ir::ModifierFlags::ALL;
1975 
1976     while (IsModifierKind(lexer_->GetToken())) {
1977         char32_t nextCp = lexer_->Lookahead();
1978         if (!((Extension() == ScriptExtension::JS && nextCp != LEX_CHAR_LEFT_PAREN) ||
1979               (Extension() == ScriptExtension::TS && nextCp != LEX_CHAR_EQUALS && nextCp != LEX_CHAR_SEMICOLON &&
1980                nextCp != LEX_CHAR_COMMA && nextCp != LEX_CHAR_LEFT_PAREN))) {
1981             break;
1982         }
1983 
1984         lexer::TokenFlags tokenFlags = lexer_->GetToken().Flags();
1985         if (tokenFlags & lexer::TokenFlags::HAS_ESCAPE) {
1986             ThrowSyntaxError("Keyword must not contain escaped characters");
1987         }
1988 
1989         ir::ModifierFlags actualStatus = ir::ModifierFlags::NONE;
1990         ir::ModifierFlags nextStatus = ir::ModifierFlags::NONE;
1991 
1992         switch (lexer_->GetToken().KeywordType()) {
1993             case lexer::TokenType::KEYW_PUBLIC: {
1994                 actualStatus = ir::ModifierFlags::PUBLIC;
1995                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
1996                              ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
1997                 break;
1998             }
1999             case lexer::TokenType::KEYW_PRIVATE: {
2000                 actualStatus = ir::ModifierFlags::PRIVATE;
2001                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
2002                              ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
2003                 break;
2004             }
2005             case lexer::TokenType::KEYW_PROTECTED: {
2006                 actualStatus = ir::ModifierFlags::PROTECTED;
2007                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY |
2008                              ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
2009                 break;
2010             }
2011             case lexer::TokenType::KEYW_STATIC: {
2012                 actualStatus = ir::ModifierFlags::STATIC;
2013                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE |
2014                              ir::ModifierFlags::ABSTRACT;
2015                 break;
2016             }
2017             case lexer::TokenType::KEYW_ASYNC: {
2018                 actualStatus = ir::ModifierFlags::ASYNC;
2019                 nextStatus = ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
2020                 break;
2021             }
2022             case lexer::TokenType::KEYW_ABSTRACT: {
2023                 actualStatus = ir::ModifierFlags::ABSTRACT;
2024                 nextStatus = ir::ModifierFlags::ACCESS | ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC |
2025                              ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE;
2026                 break;
2027             }
2028             case lexer::TokenType::KEYW_DECLARE: {
2029                 actualStatus = ir::ModifierFlags::DECLARE;
2030                 nextStatus = ir::ModifierFlags::ACCESS | ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC |
2031                              ir::ModifierFlags::READONLY;
2032                 break;
2033             }
2034             case lexer::TokenType::KEYW_READONLY: {
2035                 actualStatus = ir::ModifierFlags::READONLY;
2036                 nextStatus = ir::ModifierFlags::ASYNC | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
2037                 break;
2038             }
2039             default: {
2040                 UNREACHABLE();
2041             }
2042         }
2043 
2044         if (lexer_->Lookahead() == LEX_CHAR_COLON || lexer_->Lookahead() == LEX_CHAR_COMMA ||
2045             lexer_->Lookahead() == LEX_CHAR_RIGHT_PAREN || lexer_->Lookahead() == LEX_CHAR_QUESTION ||
2046             lexer_->Lookahead() == LEX_CHAR_RIGHT_BRACE || lexer_->Lookahead() == LEX_CHAR_LESS_THAN) {
2047             break;
2048         }
2049 
2050         auto pos = lexer_->Save();
2051         lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2052 
2053         if ((prevStatus & actualStatus) == 0) {
2054             lexer_->Rewind(pos);
2055             ThrowSyntaxError("Unexpected modifier");
2056         }
2057 
2058         if ((resultStatus & actualStatus) != 0) {
2059             lexer_->Rewind(pos);
2060             ThrowSyntaxError("Duplicated modifier is not allowed");
2061         }
2062 
2063         if ((context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) &&
2064             (actualStatus & ~ir::ModifierFlags::ALLOWED_IN_CTOR_PARAMETER)) {
2065             lexer_->Rewind(pos);
2066             ThrowParameterModifierError(actualStatus);
2067         }
2068 
2069         resultStatus |= actualStatus;
2070         prevStatus = nextStatus;
2071     }
2072 
2073     return resultStatus;
2074 }
2075 
CheckAccessorPair(const ArenaVector<ir::Statement * > & properties,const ir::Expression * propName,ir::MethodDefinitionKind methodKind,ir::ModifierFlags access,bool hasDecorator,lexer::SourcePosition errorInfo)2076 void ParserImpl::CheckAccessorPair(const ArenaVector<ir::Statement *> &properties, const ir::Expression *propName,
2077                                    ir::MethodDefinitionKind methodKind, ir::ModifierFlags access, bool hasDecorator,
2078                                    lexer::SourcePosition errorInfo)
2079 {
2080     for (const auto &it : properties) {
2081         if (!it->IsMethodDefinition() || (!hasDecorator && it->AsMethodDefinition()->Kind() != methodKind)) {
2082             continue;
2083         }
2084 
2085         const ir::Expression *key = it->AsMethodDefinition()->Key();
2086 
2087         if (key->Type() != propName->Type()) {
2088             continue;
2089         }
2090 
2091         bool keyIsSame = false;
2092 
2093         if (key->IsIdentifier()) {
2094             const util::StringView &strName = propName->AsIdentifier()->Name();
2095             const util::StringView &compareName = (key->AsIdentifier()->Name());
2096 
2097             keyIsSame = strName == compareName;
2098         } else if (key->IsNumberLiteral()) {
2099             keyIsSame = *key->AsNumberLiteral() == *propName->AsNumberLiteral();
2100         } else if (key->IsStringLiteral()) {
2101             keyIsSame = *key->AsStringLiteral() == *propName->AsStringLiteral();
2102         }
2103 
2104         if (!keyIsSame) {
2105             continue;
2106         }
2107 
2108         if (hasDecorator &&
2109             (it->AsMethodDefinition()->Kind() == ir::MethodDefinitionKind::GET ||
2110              it->AsMethodDefinition()->Kind() == ir::MethodDefinitionKind::SET) &&
2111             !it->AsMethodDefinition()->Decorators().empty()) {
2112             ThrowSyntaxError("Decorators cannot be applied to multiple get/set accessors of the same name.", errorInfo);
2113         }
2114 
2115         if (it->AsMethodDefinition()->Kind() != methodKind) {
2116             continue;
2117         }
2118 
2119         ir::ModifierFlags getAccess = ir::ModifierFlags::NONE;
2120         ir::ModifierFlags setAccess = ir::ModifierFlags::NONE;
2121 
2122         if (methodKind == ir::MethodDefinitionKind::GET) {
2123             setAccess = access;
2124             getAccess = GetAccessability(it->AsMethodDefinition()->Modifiers());
2125         } else {
2126             getAccess = access;
2127             setAccess = GetAccessability(it->AsMethodDefinition()->Modifiers());
2128         }
2129 
2130         if ((setAccess == ir::ModifierFlags::NONE && getAccess > ir::ModifierFlags::PUBLIC) ||
2131             (setAccess != ir::ModifierFlags::NONE && getAccess > setAccess)) {
2132             ThrowSyntaxError("A get accessor must be at least as accessible as the setter", key->Start());
2133         }
2134     }
2135 }
2136 
ParseClassKeyModifiers(ClassElmentDescriptor * desc)2137 void ParserImpl::ParseClassKeyModifiers(ClassElmentDescriptor *desc)
2138 {
2139     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2140         return;
2141     }
2142     char32_t nextCp = lexer_->Lookahead();
2143     if ((Extension() == ScriptExtension::JS && nextCp != LEX_CHAR_LEFT_PAREN) ||
2144         (Extension() == ScriptExtension::TS &&
2145         nextCp != LEX_CHAR_EQUALS && nextCp != LEX_CHAR_SEMICOLON && nextCp != LEX_CHAR_LEFT_PAREN &&
2146         nextCp != LEX_CHAR_LESS_THAN && nextCp != LEX_CHAR_QUESTION && nextCp != LEX_CHAR_COLON)) {
2147         if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GET) {
2148             if (desc->isPrivateIdent) {
2149                 ThrowSyntaxError("Private identifier can not be getter");
2150             }
2151 
2152             if (lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) {
2153                 ThrowSyntaxError("Keyword must not contain escaped characters");
2154             }
2155 
2156             desc->methodKind = ir::MethodDefinitionKind::GET;
2157             desc->methodStart = lexer_->GetToken().Start();
2158 
2159             lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2160         } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_SET) {
2161             if (desc->isPrivateIdent) {
2162                 ThrowSyntaxError("Private identifier can not be setter");
2163             }
2164 
2165             if (lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) {
2166                 ThrowSyntaxError("Keyword must not contain escaped characters");
2167             }
2168 
2169             desc->methodKind = ir::MethodDefinitionKind::SET;
2170             desc->methodStart = lexer_->GetToken().Start();
2171 
2172             lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2173         }
2174     }
2175 }
2176 
ThrowIfPrivateIdent(ClassElmentDescriptor * desc,const char * msg)2177 void ParserImpl::ThrowIfPrivateIdent(ClassElmentDescriptor *desc, const char *msg)
2178 {
2179     if (desc->isPrivateIdent) {
2180         ThrowSyntaxError(msg);
2181     }
2182 }
2183 
ValidateClassKey(ClassElmentDescriptor * desc,bool isDeclare)2184 void ParserImpl::ValidateClassKey(ClassElmentDescriptor *desc, bool isDeclare)
2185 {
2186     if ((desc->modifiers & ir::ModifierFlags::ASYNC) &&
2187         (desc->methodKind == ir::MethodDefinitionKind::GET || desc->methodKind == ir::MethodDefinitionKind::SET)) {
2188         ThrowSyntaxError("Async method can not be getter nor setter");
2189     }
2190 
2191     const util::StringView &propNameStr = lexer_->GetToken().Ident();
2192 
2193     if (propNameStr.Is("constructor")) {
2194         ThrowIfPrivateIdent(desc, "Private identifier can not be constructor");
2195 
2196         if (!(desc->modifiers & ir::ModifierFlags::STATIC)) {
2197             if ((desc->modifiers & ir::ModifierFlags::ASYNC) || desc->methodKind == ir::MethodDefinitionKind::GET ||
2198                 desc->methodKind == ir::MethodDefinitionKind::SET || desc->isGenerator) {
2199                 ThrowSyntaxError("Constructor can not be special method");
2200             }
2201 
2202             desc->methodKind = ir::MethodDefinitionKind::CONSTRUCTOR;
2203             desc->methodStart = lexer_->GetToken().Start();
2204             desc->newStatus |= ParserStatus::CONSTRUCTOR_FUNCTION;
2205 
2206             if (desc->hasSuperClass) {
2207                 desc->newStatus |= ParserStatus::ALLOW_SUPER_CALL;
2208             }
2209         } else if (Extension() == ScriptExtension::TS) {
2210             ThrowSyntaxError("Static modifier can not appear on a constructor");
2211         }
2212     } else if (!isDeclare && propNameStr.Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC)) {
2213         ThrowSyntaxError("Classes may not have static property named prototype");
2214     }
2215 }
2216 
ParseClassKey(ClassElmentDescriptor * desc,bool isDeclare)2217 ir::Expression *ParserImpl::ParseClassKey(ClassElmentDescriptor *desc, bool isDeclare)
2218 {
2219     ir::Expression *propName = nullptr;
2220     if (lexer_->GetToken().IsKeyword()) {
2221         lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
2222     }
2223 
2224     switch (lexer_->GetToken().Type()) {
2225         case lexer::TokenType::LITERAL_IDENT: {
2226             ValidateClassKey(desc, isDeclare);
2227 
2228             propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2229             propName->SetRange(lexer_->GetToken().Loc());
2230             break;
2231         }
2232         case lexer::TokenType::LITERAL_STRING: {
2233             ThrowIfPrivateIdent(desc, "Private identifier name can not be string");
2234 
2235             propName = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
2236             propName->SetRange(lexer_->GetToken().Loc());
2237             break;
2238         }
2239         case lexer::TokenType::LITERAL_NUMBER: {
2240             ThrowIfPrivateIdent(desc, "Private identifier name can not be number");
2241 
2242             if (lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) {
2243                 propName = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
2244             } else {
2245                 propName = AllocNode<ir::NumberLiteral>(lexer_->GetToken().Number(), lexer_->GetToken().String());
2246             }
2247 
2248             propName->SetRange(lexer_->GetToken().Loc());
2249             break;
2250         }
2251         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
2252             ThrowIfPrivateIdent(desc, "Unexpected character in private identifier");
2253 
2254             lexer_->NextToken();  // eat left square bracket
2255 
2256             if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2257                 lexer_->Lookahead() == LEX_CHAR_COLON) {
2258                 desc->isIndexSignature = true;
2259 
2260                 propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2261                 propName->SetRange(lexer_->GetToken().Loc());
2262 
2263                 lexer_->NextToken();  // eat param
2264 
2265                 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
2266                     ThrowSyntaxError("':' expected");
2267                 }
2268 
2269                 lexer_->NextToken();  // eat ':'
2270                 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
2271                 ir::Expression *typeAnnotation = ParseTsTypeAnnotation(&options);
2272 
2273                 if (!typeAnnotation->IsTSNumberKeyword() && !typeAnnotation->IsTSStringKeyword()) {
2274                     ThrowSyntaxError(
2275                         "An index signature parameter type must be either "
2276                         "'string' or 'number'");
2277                 }
2278 
2279                 propName->SetTsTypeAnnotation(typeAnnotation);
2280 
2281                 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2282                     ThrowSyntaxError("']' expected");
2283                 }
2284 
2285                 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2286 
2287                 return propName;
2288             }
2289 
2290             desc->isComputed = true;
2291 
2292             propName = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
2293 
2294             if (Extension() == ScriptExtension::TS) {
2295                 // TODO(songqi): Determine whether MemberExpression is a symbol during type check.
2296                 desc->invalidComputedProperty = !propName->IsNumberLiteral() &&
2297                     util::Helpers::GetSignedNumberLiteral(propName) == util::SignedNumberLiteral::UNRECOGNIZED &&
2298                     !propName->IsStringLiteral() && !propName->IsMemberExpression() && !propName->IsIdentifier();
2299             }
2300 
2301             if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2302                 ThrowSyntaxError("Unexpected token, expected ']'");
2303             }
2304             break;
2305         }
2306         default: {
2307             ThrowSyntaxError("Unexpected token in class property");
2308         }
2309     }
2310 
2311     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2312 
2313     return propName;
2314 }
2315 
ValidateClassMethodStart(ClassElmentDescriptor * desc,ir::Expression * typeAnnotation)2316 void ParserImpl::ValidateClassMethodStart(ClassElmentDescriptor *desc, ir::Expression *typeAnnotation)
2317 {
2318     if (Extension() == ScriptExtension::JS) {
2319         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
2320             return;
2321         }
2322         desc->classMethod = true;
2323     }
2324 
2325     if (Extension() == ScriptExtension::TS &&
2326         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && desc->isPrivateIdent) {
2327         ThrowSyntaxError("A method cannot be named with a private identifier");
2328     }
2329 
2330     if (Extension() == ScriptExtension::TS) {
2331         if (!typeAnnotation && (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
2332                                 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN)) {
2333             if ((desc->modifiers & (ir::ModifierFlags::DECLARE | ir::ModifierFlags::READONLY))) {
2334                 ThrowSyntaxError("Class method can not be declare nor readonly");
2335             }
2336             desc->classMethod = true;
2337         } else {
2338             if ((desc->modifiers & ir::ModifierFlags::ASYNC) || desc->isGenerator) {
2339                 ThrowSyntaxError("Expected '('");
2340             }
2341             desc->classField = true;
2342 
2343             if (desc->invalidComputedProperty) {
2344                 ThrowSyntaxError(
2345                     "Computed property name must refer to a symbol or "
2346                     "literal expression whos value is "
2347                     "number or string");
2348             }
2349         }
2350     }
2351 
2352     if (desc->modifiers & ir::ModifierFlags::ASYNC) {
2353         desc->newStatus |= ParserStatus::ASYNC_FUNCTION;
2354     }
2355 
2356     if (desc->isGenerator) {
2357         desc->newStatus |= ParserStatus::GENERATOR_FUNCTION;
2358     }
2359 }
2360 
ValidateClassSetter(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,ir::ScriptFunction * func,bool hasDecorator,lexer::SourcePosition errorInfo)2361 void ParserImpl::ValidateClassSetter(ClassElmentDescriptor *desc, const ArenaVector<ir::Statement *> &properties,
2362                                      ir::Expression *propName, ir::ScriptFunction *func, bool hasDecorator,
2363                                      lexer::SourcePosition errorInfo)
2364 {
2365     if (func->Params().size() != 1) {
2366         ThrowSyntaxError("Setter must have exactly one formal parameter");
2367     }
2368 
2369     if (Extension() == ScriptExtension::TS && !(desc->modifiers & ir::ModifierFlags::STATIC)) {
2370         ir::ModifierFlags access = GetAccessability(desc->modifiers);
2371         CheckAccessorPair(properties, propName, ir::MethodDefinitionKind::GET, access, hasDecorator, errorInfo);
2372     }
2373 }
2374 
ValidateClassGetter(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,ir::ScriptFunction * func,bool hasDecorator,lexer::SourcePosition errorInfo)2375 void ParserImpl::ValidateClassGetter(ClassElmentDescriptor *desc, const ArenaVector<ir::Statement *> &properties,
2376                                      ir::Expression *propName, ir::ScriptFunction *func, bool hasDecorator,
2377                                      lexer::SourcePosition errorInfo)
2378 {
2379     if (!func->Params().empty()) {
2380         ThrowSyntaxError("Getter must not have formal parameters");
2381     }
2382 
2383     if (Extension() == ScriptExtension::TS && !(desc->modifiers & ir::ModifierFlags::STATIC)) {
2384         ir::ModifierFlags access = GetAccessability(desc->modifiers);
2385 
2386         CheckAccessorPair(properties, propName, ir::MethodDefinitionKind::SET, access, hasDecorator, errorInfo);
2387     }
2388 }
2389 
ParseClassMethod(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,lexer::SourcePosition * propEnd,ArenaVector<ir::Decorator * > && decorators,bool isDeclare)2390 ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElmentDescriptor *desc,
2391                                                    const ArenaVector<ir::Statement *> &properties,
2392                                                    ir::Expression *propName, lexer::SourcePosition *propEnd,
2393                                                    ArenaVector<ir::Decorator *> &&decorators, bool isDeclare)
2394 {
2395     if (Extension() == ScriptExtension::TS) {
2396         if (desc->methodKind == ir::MethodDefinitionKind::SET || desc->methodKind == ir::MethodDefinitionKind::GET) {
2397             desc->newStatus |= ParserStatus::ACCESSOR_FUNCTION;
2398         }
2399 
2400         desc->newStatus |= ParserStatus::IN_METHOD_DEFINITION;
2401     }
2402 
2403     if (isDeclare && (desc->newStatus & ParserStatus::ASYNC_FUNCTION)) {
2404         ThrowSyntaxError("'async' modifier cannot be used in an ambient context.");
2405     }
2406 
2407     if (isDeclare && desc->isGenerator) {
2408         ThrowSyntaxError("Generators are not allowed in an ambient context.");
2409     }
2410 
2411     ArenaVector<ir::ParamDecorators> paramDecorators(Allocator()->Adapter());
2412     ir::ScriptFunction *func = ParseFunction(desc->newStatus, isDeclare, &paramDecorators);
2413     if (func->Body() != nullptr) {
2414         lexer_->NextToken();
2415     }
2416 
2417     if (func->IsOverload() && !decorators.empty()) {
2418         ThrowSyntaxError("A decorator can only decorate a method implementation, not an overload.",
2419                          decorators.front()->Start());
2420     }
2421 
2422     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
2423     funcExpr->SetRange(func->Range());
2424 
2425     lexer::SourcePosition errorInfo = decorators.empty() ? func->Start() : decorators[0]->Start();
2426 
2427     if (desc->methodKind == ir::MethodDefinitionKind::SET) {
2428         ValidateClassSetter(desc, properties, propName, func, !decorators.empty(), errorInfo);
2429     } else if (desc->methodKind == ir::MethodDefinitionKind::GET) {
2430         ValidateClassGetter(desc, properties, propName, func, !decorators.empty(), errorInfo);
2431     }
2432 
2433     *propEnd = func->End();
2434     func->AddFlag(ir::ScriptFunctionFlags::METHOD);
2435     auto *method = AllocNode<ir::MethodDefinition>(desc->methodKind, propName, funcExpr, desc->modifiers, Allocator(),
2436                                                    std::move(decorators), std::move(paramDecorators),
2437                                                    desc->isComputed);
2438     method->SetRange(funcExpr->Range());
2439     return method;
2440 }
2441 
ParseClassProperty(ClassElmentDescriptor * desc,const ArenaVector<ir::Statement * > & properties,ir::Expression * propName,ir::Expression * typeAnnotation,ArenaVector<ir::Decorator * > && decorators,bool isDeclare)2442 ir::Statement *ParserImpl::ParseClassProperty(ClassElmentDescriptor *desc,
2443                                               const ArenaVector<ir::Statement *> &properties, ir::Expression *propName,
2444                                               ir::Expression *typeAnnotation, ArenaVector<ir::Decorator *> &&decorators,
2445                                               bool isDeclare)
2446 {
2447     lexer::SourcePosition propEnd = propName->End();
2448     ir::Statement *property = nullptr;
2449 
2450     if (desc->classMethod) {
2451         property = ParseClassMethod(desc, properties, propName, &propEnd, std::move(decorators), isDeclare);
2452         property->SetRange({desc->propStart, propEnd});
2453         return property;
2454     }
2455 
2456     ir::Expression *value = nullptr;
2457 
2458     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2459         lexer_->NextToken();  // eat equals
2460 
2461         if (isDeclare) {
2462             ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
2463         }
2464         // TODO(songqi):static classProperty's value can use super keyword in TypeScript4.4.
2465         // Currently only Parser is supported, Compiler support requires Transformer.
2466         context_.Status() |= ParserStatus::ALLOW_SUPER;
2467         value = ParseExpression();
2468         context_.Status() &= ~ParserStatus::ALLOW_SUPER;
2469         propEnd = value->End();
2470     }
2471 
2472     ir::Expression *privateId = nullptr;
2473 
2474     if (Extension() == ScriptExtension::JS) {
2475         if (desc->isPrivateIdent) {
2476             ThrowSyntaxError("Private js fields are not supported");
2477         }
2478     } else {
2479         if (desc->isPrivateIdent) {
2480             privateId = AllocNode<ir::TSPrivateIdentifier>(propName, value, typeAnnotation);
2481             privateId->SetRange({desc->propStart, propName->End()});
2482         }
2483     }
2484 
2485     property = AllocNode<ir::ClassProperty>(desc->isPrivateIdent ? privateId : propName, value, typeAnnotation,
2486                                             desc->modifiers, std::move(decorators), desc->isComputed,
2487                                             desc->modifiers & ir::ModifierFlags::DEFINITE);
2488 
2489     property->SetRange({desc->propStart, propEnd});
2490     return property;
2491 }
2492 
CheckClassGeneratorMethod(ClassElmentDescriptor * desc)2493 void ParserImpl::CheckClassGeneratorMethod(ClassElmentDescriptor *desc)
2494 {
2495     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2496         return;
2497     }
2498 
2499     ThrowIfPrivateIdent(desc, "Unexpected character in private identifier");
2500 
2501     desc->isGenerator = true;
2502     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2503 }
2504 
CheckClassPrivateIdentifier(ClassElmentDescriptor * desc)2505 void ParserImpl::CheckClassPrivateIdentifier(ClassElmentDescriptor *desc)
2506 {
2507     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_HASH_MARK) {
2508         return;
2509     }
2510 
2511     if (Extension() == ScriptExtension::JS) {
2512         ThrowSyntaxError("JS private class fields are not supported.");
2513     }
2514 
2515     if (Extension() == ScriptExtension::AS) {
2516         return;
2517     }
2518 
2519     if (desc->modifiers & ~ir::ModifierFlags::READONLY) {
2520         ThrowSyntaxError("Unexpected modifier on private identifier");
2521     }
2522 
2523     desc->isPrivateIdent = true;
2524     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2525 }
2526 
ParseClassKeyAnnotation()2527 ir::Expression *ParserImpl::ParseClassKeyAnnotation()
2528 {
2529     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
2530         lexer_->NextToken();  // eat ':'
2531         TypeAnnotationParsingOptions options =
2532             TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::BREAK_AT_NEW_LINE;
2533         return ParseTsTypeAnnotation(&options);
2534     }
2535 
2536     return nullptr;
2537 }
2538 
ParseDecorator()2539 ir::Decorator *ParserImpl::ParseDecorator()
2540 {
2541     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT);
2542 
2543     lexer::SourcePosition start = lexer_->GetToken().Start();
2544     lexer_->NextToken();  // eat '@'
2545 
2546     ir::Expression *expr = ParseLeftHandSideExpression();
2547     auto *result = AllocNode<ir::Decorator>(expr);
2548     result->SetRange({start, expr->End()});
2549 
2550     return result;
2551 }
2552 
ParseDecorators()2553 ArenaVector<ir::Decorator *> ParserImpl::ParseDecorators()
2554 {
2555     ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter());
2556     auto savedStatus = context_.Status();
2557     context_.Status() |= ParserStatus::IN_DECORATOR;
2558 
2559     while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT) {
2560         decorators.push_back(ParseDecorator());
2561     }
2562 
2563     if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS &&
2564         (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0 &&
2565         lexer_->GetToken().Type() != lexer::TokenType::KEYW_EXPORT &&
2566         !(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2567           (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE ||
2568            lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT))) {
2569         ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2570     }
2571 
2572     context_.Status() = savedStatus;
2573     return decorators;
2574 }
2575 
ParseClassElement(const ArenaVector<ir::Statement * > & properties,ArenaVector<ir::TSIndexSignature * > * indexSignatures,bool hasSuperClass,bool isDeclare,bool isAbstractClass)2576 ir::Statement *ParserImpl::ParseClassElement(const ArenaVector<ir::Statement *> &properties,
2577                                              ArenaVector<ir::TSIndexSignature *> *indexSignatures, bool hasSuperClass,
2578                                              bool isDeclare, bool isAbstractClass)
2579 {
2580     ClassElmentDescriptor desc;
2581 
2582     desc.methodKind = ir::MethodDefinitionKind::METHOD;
2583     desc.newStatus = ParserStatus::ALLOW_SUPER;
2584     desc.hasSuperClass = hasSuperClass;
2585     desc.propStart = lexer_->GetToken().Start();
2586 
2587     auto decorators = ParseDecorators();
2588 
2589     desc.modifiers = ParseModifiers();
2590 
2591     if ((desc.modifiers & ir::ModifierFlags::ABSTRACT) && !isAbstractClass) {
2592         ThrowSyntaxError("Abstract methods can only appear within an abstract class.");
2593     }
2594 
2595     CheckClassPrivateIdentifier(&desc);
2596     CheckClassGeneratorMethod(&desc);
2597     ParseClassKeyModifiers(&desc);
2598 
2599     if (!(desc.modifiers & ir::ModifierFlags::STATIC)) {
2600         context_.Status() |= ParserStatus::ALLOW_THIS_TYPE;
2601     }
2602 
2603     ir::Expression *propName = ParseClassKey(&desc, isDeclare);
2604 
2605     if (desc.methodKind == ir::MethodDefinitionKind::CONSTRUCTOR && !decorators.empty()) {
2606         ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2607     }
2608 
2609     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
2610         if (desc.isIndexSignature) {
2611             ThrowSyntaxError("';' expected");
2612         }
2613 
2614         if (desc.methodKind == ir::MethodDefinitionKind::CONSTRUCTOR) {
2615             ThrowSyntaxError("'(' expected");
2616         }
2617 
2618         desc.modifiers |= ir::ModifierFlags::OPTIONAL;
2619         lexer_->NextToken();
2620     } else if (Extension() == ScriptExtension::TS &&
2621                lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
2622         if (desc.isIndexSignature || lexer_->Lookahead() != LEX_CHAR_COLON) {
2623             ThrowSyntaxError("';' expected");
2624         }
2625 
2626         desc.modifiers |= ir::ModifierFlags::DEFINITE;
2627         lexer_->NextToken();
2628     }
2629 
2630     ir::Expression *typeAnnotation = ParseClassKeyAnnotation();
2631 
2632     ir::Statement *property = nullptr;
2633     if (desc.isIndexSignature) {
2634         if (!decorators.empty()) {
2635             ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2636         }
2637 
2638         if (!typeAnnotation) {
2639             ThrowSyntaxError("An index signature must have a type annotation");
2640         }
2641 
2642         auto *indexSignature =
2643             AllocNode<ir::TSIndexSignature>(propName, typeAnnotation, desc.modifiers & ir::ModifierFlags::READONLY);
2644 
2645         indexSignature->SetRange({indexSignature->Param()->Start(), indexSignature->TypeAnnotation()->End()});
2646 
2647         indexSignatures->push_back(indexSignature);
2648 
2649         property = AllocNode<ir::EmptyStatement>();
2650     } else {
2651         ValidateClassMethodStart(&desc, typeAnnotation);
2652         property = ParseClassProperty(&desc, properties, propName, typeAnnotation, std::move(decorators),
2653                                       isDeclare || (desc.modifiers & ir::ModifierFlags::DECLARE));
2654     }
2655 
2656     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
2657         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
2658         !(lexer_->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) &&
2659         !(property->IsMethodDefinition() && property->AsMethodDefinition()->Value()->Function()->Body())) {
2660         ThrowSyntaxError("';' expected.");
2661     }
2662 
2663     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
2664         lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2665     }
2666 
2667     context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
2668 
2669     return property;
2670 }
2671 
IsConstructor(ir::Statement * stmt)2672 static bool IsConstructor(ir::Statement *stmt)
2673 {
2674     if (!stmt->IsMethodDefinition()) {
2675         return false;
2676     }
2677 
2678     ir::MethodDefinition *def = stmt->AsMethodDefinition();
2679     return def->Kind() == ir::MethodDefinitionKind::CONSTRUCTOR;
2680 }
2681 
CreateImplicitConstructor(ir::Expression * superClass,bool hasSuperClass,bool isDeclare)2682 ir::MethodDefinition *ParserImpl::CreateImplicitConstructor(ir::Expression *superClass,
2683                                                             bool hasSuperClass, bool isDeclare)
2684 {
2685     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
2686     ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
2687 
2688     auto *paramScope = Binder()->Allocator()->New<binder::FunctionParamScope>(Allocator(), Binder()->GetScope());
2689     auto *scope = Binder()->Allocator()->New<binder::FunctionScope>(Allocator(), paramScope);
2690 
2691     if (hasSuperClass) {
2692         if (Extension() != ScriptExtension::TS || !superClass->IsNullLiteral()) {
2693             util::StringView argsStr = "args";
2694             params.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT,
2695                                                           AllocNode<ir::Identifier>(argsStr)));
2696             paramScope->AddParamDecl(Allocator(), params.back());
2697 
2698             ArenaVector<ir::Expression *> callArgs(Allocator()->Adapter());
2699             auto *superExpr = AllocNode<ir::SuperExpression>();
2700             callArgs.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::SPREAD_ELEMENT,
2701                                                             AllocNode<ir::Identifier>(argsStr)));
2702 
2703             auto *callExpr = AllocNode<ir::CallExpression>(superExpr, std::move(callArgs), nullptr, false);
2704             statements.push_back(AllocNode<ir::ExpressionStatement>(callExpr));
2705         }
2706     }
2707 
2708     auto *body = AllocNode<ir::BlockStatement>(scope, std::move(statements));
2709     auto *func = AllocNode<ir::ScriptFunction>(scope, std::move(params), nullptr, isDeclare ? nullptr : body, nullptr,
2710                                                ir::ScriptFunctionFlags::CONSTRUCTOR, isDeclare,
2711                                                Extension() == ScriptExtension::TS);
2712     scope->BindNode(func);
2713     paramScope->BindNode(func);
2714     scope->BindParamScope(paramScope);
2715     paramScope->BindFunctionScope(scope);
2716 
2717     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
2718     auto *key = AllocNode<ir::Identifier>("constructor");
2719 
2720     ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter());
2721     ArenaVector<ir::ParamDecorators> paramDecorators(Allocator()->Adapter());
2722     auto *ctor = AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr,
2723                                                  ir::ModifierFlags::NONE, Allocator(), std::move(decorators),
2724                                                  std::move(paramDecorators), false);
2725 
2726     return ctor;
2727 }
2728 
IsPropertyKeysAreSame(const ir::Expression * exp1,const ir::Expression * exp2)2729 bool ParserImpl::IsPropertyKeysAreSame(const ir::Expression *exp1, const ir::Expression *exp2)
2730 {
2731     if (exp1->IsIdentifier() && exp2->IsIdentifier()) {
2732         return exp1->AsIdentifier()->Name() == exp2->AsIdentifier()->Name();
2733     }
2734 
2735     if (exp1->IsIdentifier() && exp2->IsStringLiteral()) {
2736         return exp1->AsIdentifier()->Name() == exp2->AsStringLiteral()->Str();
2737     }
2738 
2739     if (exp1->IsStringLiteral() && exp2->IsStringLiteral()) {
2740         return *exp1->AsStringLiteral() == *exp2->AsStringLiteral();
2741     }
2742 
2743     if (exp1->IsStringLiteral() && exp2->IsIdentifier()) {
2744         return exp1->AsStringLiteral()->Str() == exp2->AsIdentifier()->Name();
2745     }
2746 
2747     if (exp1->IsStringLiteral() && exp2->IsNumberLiteral()) {
2748         std::string exp2String = std::to_string(exp2->AsNumberLiteral()->Number<double>());
2749         exp2String.erase(exp2String.find_last_not_of('0'), std::string::npos);
2750         return exp1->AsStringLiteral()->Str().Utf8() == exp2String;
2751     }
2752 
2753     if (exp1->IsNumberLiteral() && exp2->IsNumberLiteral()) {
2754         return exp1->AsNumberLiteral()->Number<double>() == exp2->AsNumberLiteral()->Number<double>();
2755     }
2756 
2757     if (exp1->IsNumberLiteral() && exp2->IsStringLiteral()) {
2758         std::string exp1String = std::to_string(exp1->AsNumberLiteral()->Number<double>());
2759         exp1String.erase(exp1String.find_last_not_of('0'), std::string::npos);
2760         return exp1String == exp2->AsStringLiteral()->Str().Utf8();
2761     }
2762 
2763     return false;
2764 }
2765 
IsMemberExpressionsAreSame(const ir::MemberExpression * mExp1,const ir::MemberExpression * mExp2)2766 bool ParserImpl::IsMemberExpressionsAreSame(const ir::MemberExpression *mExp1, const ir::MemberExpression *mExp2)
2767 {
2768     if (!IsPropertyKeysAreSame(mExp1->Property(), mExp2->Property())) {
2769         return false;
2770     }
2771 
2772     if (mExp1->Object()->IsMemberExpression() && mExp2->Object()->IsMemberExpression()) {
2773         return IsMemberExpressionsAreSame(mExp1->Object()->AsMemberExpression(), mExp2->Object()->AsMemberExpression());
2774     }
2775 
2776     return IsPropertyKeysAreSame(mExp1->Object(), mExp2->Object());
2777 }
2778 
IsMethodDefinitionsAreSame(const ir::MethodDefinition * property,ir::MethodDefinition * overload)2779 bool ParserImpl::IsMethodDefinitionsAreSame(const ir::MethodDefinition *property, ir::MethodDefinition *overload)
2780 {
2781     if (property->Kind() != overload->Kind() || property->IsStatic() != overload->IsStatic()) {
2782         return false;
2783     }
2784 
2785     if (property->Key()->IsMemberExpression() && overload->Key()->IsMemberExpression()) {
2786         return IsMemberExpressionsAreSame(property->Key()->AsMemberExpression(), overload->Key()->AsMemberExpression());
2787     }
2788 
2789     return IsPropertyKeysAreSame(property->Key(), overload->Key());
2790 }
2791 
SetIdentNodeInClassDefinition(bool isDeclare,binder::ConstDecl ** decl)2792 ir::Identifier *ParserImpl::SetIdentNodeInClassDefinition(bool isDeclare, binder::ConstDecl **decl)
2793 {
2794     lexer::TokenType keywType = lexer_->GetToken().KeywordType();
2795     CheckStrictReservedWord();
2796 
2797     if (keywType == lexer::TokenType::KEYW_AWAIT && context_.IsModule()) {
2798         ThrowSyntaxError("Unexpected reserved word");
2799     }
2800 
2801     const util::StringView &identStr = lexer_->GetToken().Ident();
2802 
2803     *decl = Binder()->AddDecl<binder::ConstDecl>(lexer_->GetToken().Start(), isDeclare, identStr);
2804 
2805     auto *identNode = AllocNode<ir::Identifier>(identStr);
2806     identNode->SetRange(lexer_->GetToken().Loc());
2807 
2808     lexer_->NextToken();
2809 
2810     return identNode;
2811 }
2812 
ParseClassDefinition(bool isDeclaration,bool idRequired,bool isDeclare,bool isAbstract)2813 ir::ClassDefinition *ParserImpl::ParseClassDefinition(bool isDeclaration, bool idRequired, bool isDeclare,
2814                                                       bool isAbstract)
2815 {
2816     isDeclare = isDeclare | (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT);
2817     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2818     lexer_->NextToken();
2819 
2820     binder::ConstDecl *decl = nullptr;
2821     ir::Identifier *identNode = nullptr;
2822 
2823     auto classCtx = binder::LexicalScope<binder::LocalScope>(Binder());
2824 
2825     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && (Extension() != ScriptExtension::TS ||
2826         lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_IMPLEMENTS)) {
2827         identNode = SetIdentNodeInClassDefinition(isDeclare, &decl);
2828     } else if (isDeclaration && idRequired) {
2829         ThrowSyntaxError("Unexpected token, expected an identifier.");
2830     }
2831 
2832     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
2833     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
2834         typeParamDecl = ParseTsTypeParameterDeclaration();
2835     }
2836 
2837     // Parse SuperClass
2838     ir::Expression *superClass = nullptr;
2839     bool hasSuperClass = false;
2840 
2841     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
2842         lexer_->NextToken();
2843         hasSuperClass = true;
2844         superClass = ParseLeftHandSideExpression();
2845     }
2846 
2847     ir::TSTypeParameterInstantiation *superTypeParams = nullptr;
2848     if (Extension() == ScriptExtension::TS && (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN ||
2849                                                lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT)) {
2850         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
2851             lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
2852         }
2853 
2854         superTypeParams = ParseTsTypeParameterInstantiation();
2855     }
2856 
2857     ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
2858     if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IMPLEMENTS) {
2859         lexer_->NextToken();
2860 
2861         while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2862             lexer::SourcePosition implStart = lexer_->GetToken().Start();
2863 
2864             if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2865                 ThrowSyntaxError("Identifier expected");
2866             }
2867 
2868             ir::Expression *expr = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2869             expr->SetRange(lexer_->GetToken().Loc());
2870             expr->AsIdentifier()->SetReference();
2871 
2872             lexer_->NextToken();
2873 
2874             if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
2875                 expr = ParseTsQualifiedReference(expr);
2876             }
2877 
2878             ir::TSTypeParameterInstantiation *implTypeParams = nullptr;
2879             if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
2880                 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
2881             }
2882 
2883             if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN ||
2884                 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
2885                 implTypeParams = ParseTsTypeParameterInstantiation();
2886             }
2887 
2888             auto *impl = AllocNode<ir::TSClassImplements>(expr, implTypeParams);
2889             impl->SetRange({implStart, lexer_->GetToken().End()});
2890             implements.push_back(impl);
2891 
2892             if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2893                 lexer_->NextToken();
2894                 continue;
2895             }
2896 
2897             if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2898                 ThrowSyntaxError("',' expected");
2899             }
2900         }
2901 
2902         if (implements.empty()) {
2903             ThrowSyntaxError("Implements clause can not be empty");
2904         }
2905     }
2906 
2907     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2908         ThrowSyntaxError("Unexpected token, expected '{'");
2909     }
2910 
2911     // Parse ClassBody
2912     auto savedStatus = context_.Status();
2913     context_.Status() |= ParserStatus::IN_CLASS_BODY;
2914     context_.Status() &= ~(ParserStatus::CONSTRUCTOR_FUNCTION);
2915     lexer::SourcePosition classBodyStartLoc = lexer_->GetToken().Start();
2916     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2917 
2918     ir::MethodDefinition *ctor = nullptr;
2919     ArenaVector<ir::Statement *> properties(Allocator()->Adapter());
2920     ArenaVector<ir::TSIndexSignature *> indexSignatures(Allocator()->Adapter());
2921     bool hasConstructorFuncBody = false;
2922     bool isCtorContinuousDefined = true;
2923 
2924     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2925         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
2926             lexer_->NextToken();
2927             continue;
2928         }
2929 
2930         ir::Statement *property = ParseClassElement(properties, &indexSignatures, hasSuperClass, isDeclare, isAbstract);
2931 
2932         if (property->IsEmptyStatement()) {
2933             continue;
2934         }
2935 
2936         if (IsConstructor(property)) {
2937             if (!isDeclare && !isCtorContinuousDefined) {
2938                 ThrowSyntaxError("Constructor implementation is missing.", property->Start());
2939             }
2940 
2941             if (hasConstructorFuncBody) {
2942                 ThrowSyntaxError("Multiple constructor implementations are not allowed.", property->Start());
2943             }
2944             ctor = property->AsMethodDefinition();
2945             hasConstructorFuncBody = ctor->Value()->Function()->Body() != nullptr;
2946             continue;
2947         }
2948         isCtorContinuousDefined = ctor == nullptr;
2949         properties.push_back(property);
2950     }
2951 
2952     context_.Status() = savedStatus;
2953 
2954     lexer::SourcePosition classBodyEndLoc = lexer_->GetToken().End();
2955     if (ctor == nullptr) {
2956         ctor = CreateImplicitConstructor(superClass, hasSuperClass, isDeclare);
2957         ctor->SetRange({startLoc, classBodyEndLoc});
2958         hasConstructorFuncBody = !isDeclare;
2959     }
2960     lexer_->NextToken();
2961 
2962     ValidateClassConstructor(ctor, properties, superClass, isDeclare, hasConstructorFuncBody, hasSuperClass);
2963 
2964     auto *classDefinition = AllocNode<ir::ClassDefinition>(
2965         classCtx.GetScope(), identNode, typeParamDecl, superTypeParams, std::move(implements), ctor, superClass,
2966         std::move(properties), std::move(indexSignatures), isDeclare, isAbstract);
2967 
2968     classDefinition->SetRange({classBodyStartLoc, classBodyEndLoc});
2969     if (decl != nullptr) {
2970         decl->BindNode(classDefinition);
2971     }
2972 
2973     return classDefinition;
2974 }
2975 
ValidateClassConstructor(ir::MethodDefinition * ctor,ArenaVector<ir::Statement * > & properties,ir::Expression * superClass,bool isDeclare,bool hasConstructorFuncBody,bool hasSuperClass)2976 void ParserImpl::ValidateClassConstructor(ir::MethodDefinition *ctor,
2977                                           ArenaVector<ir::Statement *> &properties,
2978                                           ir::Expression *superClass,
2979                                           bool isDeclare, bool hasConstructorFuncBody, bool hasSuperClass)
2980 {
2981     if (!hasConstructorFuncBody) {
2982         if (isDeclare) {
2983             return;
2984         }
2985         ThrowSyntaxError("Constructor implementation is missing.", ctor->Start());
2986     }
2987 
2988     if (Extension() != ScriptExtension::TS || !hasSuperClass) {
2989         return;
2990     }
2991 
2992     bool hasSuperCall = false;
2993     FindSuperCallInConstructor(ctor, &hasSuperCall);
2994     if (hasSuperCall) {
2995         if (superClass->IsNullLiteral()) {
2996             ThrowSyntaxError("A constructor cannot contain a super call when its class extends null.", ctor->Start());
2997         }
2998 
2999         if (SuperCallShouldBeFirst(ctor, properties)) {
3000             ir::Statement *firstStat = nullptr;
3001             ASSERT(ctor->Function()->Body()->IsBlockStatement());
3002             ir::BlockStatement *blockStat = ctor->Function()->Body()->AsBlockStatement();
3003             for (auto iter = blockStat->Statements().begin(); iter != blockStat->Statements().end();) {
3004                 if ((*iter)->IsExpressionStatement() &&
3005                     (*iter)->AsExpressionStatement()->GetExpression()->IsStringLiteral()) {
3006                     iter++;
3007                 } else {
3008                     firstStat = *iter;
3009                     break;
3010                 }
3011             }
3012 
3013             if (firstStat == nullptr || !firstStat->IsExpressionStatement() ||
3014                 !firstStat->AsExpressionStatement()->GetExpression()->IsCallExpression() ||
3015                 !firstStat->AsExpressionStatement()->GetExpression()->AsCallExpression()
3016                 ->Callee()->IsSuperExpression()) {
3017                 ThrowSyntaxError("A super call must be the first statement in the constructor when a class contains "
3018                                  "initialized properties, parameter properties, or private identifiers.",
3019                                  ctor->Start());
3020             }
3021         }
3022     } else if (!superClass->IsNullLiteral()) {
3023         ThrowSyntaxError("Constructors for derived classes must contain a super call.", ctor->Start());
3024     }
3025 }
3026 
SuperCallShouldBeFirst(ir::MethodDefinition * ctor,ArenaVector<ir::Statement * > & properties)3027 bool ParserImpl::SuperCallShouldBeFirst(ir::MethodDefinition *ctor, ArenaVector<ir::Statement *> &properties)
3028 {
3029     for (const auto *property : properties) {
3030         if (property->IsClassProperty() && (property->AsClassProperty()->Value() != nullptr ||
3031             property->AsClassProperty()->Key()->IsTSPrivateIdentifier())) {
3032             return true;
3033         }
3034     }
3035 
3036     for (const auto &param : ctor->Function()->Params()) {
3037         if (param->IsTSParameterProperty() &&
3038             (param->AsTSParameterProperty()->Accessibility() != ir::AccessibilityOption::NO_OPTS ||
3039             param->AsTSParameterProperty()->Readonly())) {
3040             return true;
3041         }
3042     }
3043     return false;
3044 }
3045 
FindSuperCallInConstructor(const ir::AstNode * parent,bool * hasSuperCall)3046 void ParserImpl::FindSuperCallInConstructor(const ir::AstNode *parent, bool *hasSuperCall)
3047 {
3048     parent->Iterate([this, hasSuperCall](auto *childNode) {
3049         FindSuperCallInConstructorChildNode(childNode, hasSuperCall);
3050     });
3051 }
3052 
FindSuperCallInConstructorChildNode(const ir::AstNode * childNode,bool * hasSuperCall)3053 void ParserImpl::FindSuperCallInConstructorChildNode(const ir::AstNode *childNode, bool *hasSuperCall)
3054 {
3055     if (*hasSuperCall) {
3056         return;
3057     }
3058     switch (childNode->Type()) {
3059         case ir::AstNodeType::CALL_EXPRESSION: {
3060             if (childNode->AsCallExpression()->Callee()->IsSuperExpression()) {
3061                 *hasSuperCall = true;
3062             }
3063             break;
3064         }
3065         case ir::AstNodeType::CLASS_DEFINITION: {
3066             break;
3067         }
3068         default: {
3069             FindSuperCallInConstructor(childNode, hasSuperCall);
3070             break;
3071         }
3072     }
3073 }
3074 
ParseEnumMembers(ir::Identifier * key,const lexer::SourcePosition & enumStart,bool isExport,bool isDeclare,bool isConst)3075 ir::TSEnumDeclaration *ParserImpl::ParseEnumMembers(ir::Identifier *key, const lexer::SourcePosition &enumStart,
3076                                                     bool isExport, bool isDeclare, bool isConst)
3077 {
3078     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3079         ThrowSyntaxError("'{' expected");
3080     }
3081 
3082     ArenaVector<ir::TSEnumMember *> members(Allocator()->Adapter());
3083     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
3084 
3085     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
3086         ir::Expression *memberKey = nullptr;
3087         const auto &keyStartLoc = lexer_->GetToken().Start();
3088         binder::EnumDecl *decl {};
3089 
3090         if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
3091             memberKey = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
3092             decl = Binder()->AddDecl<binder::EnumDecl>(keyStartLoc, isDeclare, lexer_->GetToken().Ident());
3093             memberKey->SetRange(lexer_->GetToken().Loc());
3094             lexer_->NextToken();
3095         } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
3096             memberKey = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
3097             decl = Binder()->AddDecl<binder::EnumDecl>(keyStartLoc, isDeclare, lexer_->GetToken().String());
3098             memberKey->SetRange(lexer_->GetToken().Loc());
3099             lexer_->NextToken();
3100         } else {
3101             ThrowSyntaxError("Unexpected token in enum member");
3102         }
3103 
3104         ir::Expression *memberInit = nullptr;
3105         lexer::SourcePosition initStart = lexer_->GetToken().Start();
3106 
3107         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
3108             lexer_->NextToken();  // eat '='
3109             initStart = lexer_->GetToken().Start();
3110             memberInit = ParseExpression();
3111         }
3112 
3113         auto *member = AllocNode<ir::TSEnumMember>(memberKey, memberInit);
3114         decl->BindNode(member);
3115         member->SetRange({initStart, lexer_->GetToken().End()});
3116         members.push_back(member);
3117 
3118         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3119             lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat ','
3120         }
3121     }
3122 
3123     auto *enumDeclaration = AllocNode<ir::TSEnumDeclaration>(
3124         Binder()->GetScope()->AsTSEnumScope(), key, std::move(members), isExport, isDeclare, isConst);
3125     enumDeclaration->SetRange({enumStart, lexer_->GetToken().End()});
3126     Binder()->GetScope()->BindNode(enumDeclaration);
3127     lexer_->NextToken();  // eat '}'
3128 
3129     return enumDeclaration;
3130 }
3131 
ParseEnumDeclaration(bool isExport,bool isDeclare,bool isConst)3132 ir::TSEnumDeclaration *ParserImpl::ParseEnumDeclaration(bool isExport, bool isDeclare, bool isConst)
3133 {
3134     ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM);
3135     lexer::SourcePosition enumStart = lexer_->GetToken().Start();
3136     lexer_->NextToken();  // eat enum keyword
3137 
3138     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
3139         ThrowSyntaxError("Identifier expected");
3140     }
3141 
3142     const util::StringView &ident = lexer_->GetToken().Ident();
3143     auto *currentScope = Binder()->GetScope();
3144     binder::Variable *res = currentScope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(ident);
3145     if (res == nullptr && isExport && currentScope->IsTSModuleScope()) {
3146         res = currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::ENUMLITERAL>(ident);
3147         if (res != nullptr) {
3148             currentScope->AddLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(ident, res);
3149         }
3150     }
3151     if (res == nullptr) {
3152         Binder()->AddTsDecl<binder::EnumLiteralDecl>(lexer_->GetToken().Start(), isDeclare,
3153                                                      Allocator(), ident, isExport, isConst);
3154         res = currentScope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(ident);
3155         if (isExport && currentScope->IsTSModuleScope()) {
3156             currentScope->AsTSModuleScope()->AddExportTSVariable<binder::TSBindingType::ENUMLITERAL>(ident, res);
3157         }
3158         res->AsEnumLiteralVariable()->SetEnumMembers(Allocator()->New<binder::VariableMap>(Allocator()->Adapter()));
3159     }
3160     binder::VariableMap *enumMemberBindings = res->AsEnumLiteralVariable()->GetEnumMembers();
3161 
3162     auto *key = AllocNode<ir::Identifier>(ident);
3163     key->SetRange(lexer_->GetToken().Loc());
3164     key->SetReference();
3165     lexer_->NextToken();
3166 
3167     if (!res->Declaration()->IsEnumLiteralDecl() ||
3168         (isConst ^ res->Declaration()->AsEnumLiteralDecl()->IsConst())) {
3169         Binder()->ThrowRedeclaration(lexer_->GetToken().Start(), ident);
3170     }
3171 
3172     auto enumCtx = binder::LexicalScope<binder::TSEnumScope>(Binder(), enumMemberBindings);
3173     auto *enumDeclaration = ParseEnumMembers(key, enumStart, isExport, isDeclare, isConst);
3174     res->Declaration()->AsEnumLiteralDecl()->Add(enumDeclaration);
3175 
3176     return enumDeclaration;
3177 }
3178 
ValidateFunctionParam(const ArenaVector<ir::Expression * > & params,const ir::Expression * parameter,bool * seenOptional)3179 void ParserImpl::ValidateFunctionParam(const ArenaVector<ir::Expression *> &params, const ir::Expression *parameter,
3180                                        bool *seenOptional)
3181 {
3182     if (!parameter->IsIdentifier()) {
3183         context_.Status() |= ParserStatus::HAS_COMPLEX_PARAM;
3184         if (!parameter->IsRestElement()) {
3185             return;
3186         }
3187 
3188         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
3189             const char *msg = (Extension() == ScriptExtension::JS ? "Rest parameter must be last formal parameter"
3190                                                                   : "A rest parameter must be last in parameter list");
3191             ThrowSyntaxError(msg);
3192         }
3193         return;
3194     }
3195 
3196     if (Extension() != ScriptExtension::TS) {
3197         return;
3198     }
3199 
3200     bool currentIsOptinal = parameter->AsIdentifier()->IsOptional();
3201     if (*seenOptional && !currentIsOptinal) {
3202         ThrowSyntaxError("A required parameter cannot follow an optional parameter");
3203     }
3204 
3205     *seenOptional |= currentIsOptinal;
3206     const util::StringView &paramName = parameter->AsIdentifier()->Name();
3207 
3208     if (paramName.Is("this")) {
3209         if (!params.empty()) {
3210             ThrowSyntaxError("A 'this' parameter must be the first parameter");
3211         }
3212 
3213         if (context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) {
3214             ThrowSyntaxError("A constructor cannot have a 'this' parameter");
3215         }
3216 
3217         if (context_.Status() & ParserStatus::ARROW_FUNCTION) {
3218             ThrowSyntaxError("An arrow function cannot have a 'this' parameter");
3219         }
3220 
3221         if (context_.Status() & ParserStatus::ACCESSOR_FUNCTION) {
3222             ThrowSyntaxError("'get' and 'set' accessors cannot declare 'this' parameters");
3223         }
3224     }
3225 
3226     if (paramName.Is("constructor") && (context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION)) {
3227         ThrowSyntaxError("'constructor' cannot be used as a parameter property name");
3228     }
3229 }
3230 
ParseFunctionParams(bool isDeclare,ArenaVector<ir::ParamDecorators> * paramDecorators)3231 ArenaVector<ir::Expression *> ParserImpl::ParseFunctionParams(bool isDeclare,
3232                                                               ArenaVector<ir::ParamDecorators> *paramDecorators)
3233 {
3234     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
3235     lexer_->NextToken();
3236 
3237     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
3238     bool seenOptional = false;
3239 
3240     size_t index = 0;
3241     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
3242         if (context_.Status() & ParserStatus::IN_METHOD_DEFINITION) {
3243             auto decorators = ParseDecorators();
3244             if (!decorators.empty()) {
3245                 ASSERT(paramDecorators != nullptr);
3246                 paramDecorators->push_back({index, std::move(decorators)});
3247             }
3248         }
3249 
3250         ir::Expression *parameter = ParseFunctionParameter(isDeclare);
3251         ValidateFunctionParam(params, parameter, &seenOptional);
3252 
3253         params.push_back(parameter);
3254 
3255         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
3256             lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
3257             ThrowSyntaxError(", expected");
3258         }
3259 
3260         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3261             lexer_->NextToken();
3262         }
3263 
3264         index++;
3265     }
3266 
3267     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
3268     lexer_->NextToken();
3269 
3270     return params;
3271 }
3272 
CheckTypeNameIsReserved(const util::StringView & paramName)3273 bool ParserImpl::CheckTypeNameIsReserved(const util::StringView &paramName)
3274 {
3275     return paramName.Is("number") || paramName.Is("any") || paramName.Is("unknown") || paramName.Is("never") ||
3276            paramName.Is("bigint") || paramName.Is("boolean") || paramName.Is("string") || paramName.Is("string") ||
3277            paramName.Is("void") || paramName.Is("object");
3278 }
3279 
ParseTsTypeParameter(bool throwError,bool addBinding)3280 ir::TSTypeParameter *ParserImpl::ParseTsTypeParameter(bool throwError, bool addBinding)
3281 {
3282     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3283 
3284     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
3285         if (!throwError) {
3286             return nullptr;
3287         }
3288 
3289         ThrowSyntaxError("Type parameter declaration expected");
3290     }
3291 
3292     const auto &ident = lexer_->GetToken().Ident();
3293 
3294     if (CheckTypeNameIsReserved(ident)) {
3295         if (!throwError) {
3296             return nullptr;
3297         }
3298 
3299         ThrowSyntaxError("Invalid type parameter name");
3300     }
3301 
3302     auto *paramIdent = AllocNode<ir::Identifier>(ident);
3303 
3304     if (addBinding) {
3305         Binder()->AddDecl<binder::LetDecl>(lexer_->GetToken().Start(), false, ident);
3306     }
3307 
3308     paramIdent->SetRange({lexer_->GetToken().Start(), lexer_->GetToken().End()});
3309 
3310     lexer_->NextToken();
3311 
3312     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
3313 
3314     if (throwError) {
3315         options |= TypeAnnotationParsingOptions::THROW_ERROR;
3316     }
3317 
3318     ir::Expression *constraint = nullptr;
3319     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
3320         lexer_->NextToken();
3321         constraint = ParseTsTypeAnnotation(&options);
3322     }
3323 
3324     ir::Expression *defaultType = nullptr;
3325     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
3326         lexer_->NextToken();
3327         defaultType = ParseTsTypeAnnotation(&options);
3328     }
3329 
3330     auto *typeParam = AllocNode<ir::TSTypeParameter>(paramIdent, constraint, defaultType);
3331 
3332     typeParam->SetRange({startLoc, lexer_->GetToken().End()});
3333 
3334     return typeParam;
3335 }
3336 
ParseTsTypeParameterDeclaration(bool throwError)3337 ir::TSTypeParameterDeclaration *ParserImpl::ParseTsTypeParameterDeclaration(bool throwError)
3338 {
3339     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
3340 
3341     auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder());
3342 
3343     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3344     ArenaVector<ir::TSTypeParameter *> params(Allocator()->Adapter());
3345     bool seenDefault = false;
3346     size_t requiredParams = 0;
3347     lexer_->NextToken();  // eat '<'
3348 
3349     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3350         ir::TSTypeParameter *currentParam = ParseTsTypeParameter(throwError, true);
3351 
3352         if (!currentParam) {
3353             ASSERT(!throwError);
3354             return nullptr;
3355         }
3356 
3357         if (currentParam->DefaultType()) {
3358             seenDefault = true;
3359         } else if (seenDefault) {
3360             ThrowSyntaxError("Required type parameters may not follow optional type parameters.");
3361         } else {
3362             requiredParams++;
3363         }
3364 
3365         params.push_back(currentParam);
3366 
3367         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3368             lexer_->NextToken();
3369             continue;
3370         }
3371 
3372         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3373             if (!throwError) {
3374                 return nullptr;
3375             }
3376 
3377             ThrowSyntaxError("'>' expected");
3378         }
3379     }
3380 
3381     if (params.empty()) {
3382         ThrowSyntaxError("Type parameter list cannot be empty.");
3383     }
3384 
3385     lexer::SourcePosition endLoc = lexer_->GetToken().End();
3386     lexer_->NextToken();  // eat '>'
3387 
3388     auto *typeParamDecl =
3389         AllocNode<ir::TSTypeParameterDeclaration>(localCtx.GetScope(), std::move(params), requiredParams);
3390     typeParamDecl->SetRange({startLoc, endLoc});
3391     localCtx.GetScope()->BindNode(typeParamDecl);
3392 
3393     return typeParamDecl;
3394 }
3395 
ParseTsTypeParameterInstantiation(bool throwError)3396 ir::TSTypeParameterInstantiation *ParserImpl::ParseTsTypeParameterInstantiation(bool throwError)
3397 {
3398     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
3399     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3400     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
3401     lexer_->NextToken();  // eat '<'
3402 
3403     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
3404         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::NO_OPTS;
3405 
3406         if (throwError) {
3407             options |= TypeAnnotationParsingOptions::THROW_ERROR;
3408         }
3409 
3410         ir::Expression *currentParam = ParseTsTypeAnnotation(&options);
3411 
3412         if (!currentParam) {
3413             return nullptr;
3414         }
3415 
3416         params.push_back(currentParam);
3417 
3418         switch (lexer_->GetToken().Type()) {
3419             case lexer::TokenType::PUNCTUATOR_COMMA: {
3420                 lexer_->NextToken();
3421                 continue;
3422             }
3423             case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: {
3424                 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 1);
3425                 break;
3426             }
3427             case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: {
3428                 lexer_->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 2);
3429                 break;
3430             }
3431             case lexer::TokenType::PUNCTUATOR_GREATER_THAN: {
3432                 break;
3433             }
3434             default: {
3435                 if (throwError) {
3436                     ThrowSyntaxError("'>' expected");
3437                 }
3438 
3439                 return nullptr;
3440             }
3441         }
3442     }
3443 
3444     lexer::SourcePosition endLoc = lexer_->GetToken().End();
3445     lexer_->NextToken();
3446 
3447     auto *typeParamInst = AllocNode<ir::TSTypeParameterInstantiation>(std::move(params));
3448 
3449     typeParamInst->SetRange({startLoc, endLoc});
3450 
3451     return typeParamInst;
3452 }
3453 
ParseFunction(ParserStatus newStatus,bool isDeclare,ArenaVector<ir::ParamDecorators> * paramDecorators)3454 ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus,
3455                                               bool isDeclare,
3456                                               ArenaVector<ir::ParamDecorators> *paramDecorators)
3457 {
3458     FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET);
3459 
3460     FunctionParameterContext funcParamContext(&context_, Binder());
3461     auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
3462 
3463     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3464 
3465     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
3466     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
3467         typeParamDecl = ParseTsTypeParameterDeclaration();
3468     }
3469 
3470     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
3471         ThrowSyntaxError("Unexpected token, expected '('");
3472     }
3473 
3474     if (newStatus & (ParserStatus::ASYNC_FUNCTION | ParserStatus::FUNCTION_DECLARATION)) {
3475         context_.Status() |= ParserStatus::DISALLOW_AWAIT;
3476     }
3477 
3478     ArenaVector<ir::Expression *> params = ParseFunctionParams(isDeclare, paramDecorators);
3479 
3480     ir::Expression *returnTypeAnnotation = nullptr;
3481 
3482     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
3483         lexer_->NextToken();  // eat ':'
3484         TypeAnnotationParsingOptions options =
3485             TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE;
3486         returnTypeAnnotation = ParseTsTypeAnnotation(&options);
3487     }
3488 
3489     auto functionCtx = binder::LexicalScope<binder::FunctionScope>(Binder());
3490     auto *functionScope = functionCtx.GetScope();
3491     functionScope->BindParamScope(funcParamScope);
3492     funcParamScope->BindFunctionScope(functionScope);
3493 
3494     ir::BlockStatement *body = nullptr;
3495     lexer::SourcePosition endLoc = lexer_->GetToken().End();
3496     bool letDeclare = true;
3497 
3498     if (newStatus & ParserStatus::ASYNC_FUNCTION) {
3499         context_.Status() &= ~ParserStatus::DISALLOW_AWAIT;
3500     } else {
3501         context_.Status() |= ParserStatus::DISALLOW_AWAIT;
3502     }
3503 
3504     if (newStatus & ParserStatus::GENERATOR_FUNCTION) {
3505         context_.Status() |= ParserStatus::ALLOW_YIELD;
3506     }
3507 
3508     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3509         if (Extension() == ScriptExtension::TS && (newStatus & ParserStatus::FUNCTION_DECLARATION)) {
3510             ValidateTsFunctionOverloadParams(params);
3511             functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
3512         } else if (!isDeclare && !(context_.Status() & ParserStatus::IN_METHOD_DEFINITION)) {
3513             ThrowSyntaxError("Unexpected token, expected '{'");
3514         } else {
3515             letDeclare = false;
3516             functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
3517         }
3518     } else if (isDeclare) {
3519         ThrowSyntaxError("An implementation cannot be declared in ambient contexts.");
3520     } else {
3521         body = ParseBlockStatement(functionScope);
3522         endLoc = body->End();
3523     }
3524 
3525     auto *funcNode =
3526         AllocNode<ir::ScriptFunction>(functionScope, std::move(params), typeParamDecl, body, returnTypeAnnotation,
3527                                       functionContext.Flags(), isDeclare && letDeclare,
3528                                       Extension() == ScriptExtension::TS);
3529     functionScope->BindNode(funcNode);
3530     funcParamScope->BindNode(funcNode);
3531     funcNode->SetRange({startLoc, endLoc});
3532 
3533     return funcNode;
3534 }
3535 
ValidateTsFunctionOverloadParams(const ArenaVector<ir::Expression * > & params)3536 void ParserImpl::ValidateTsFunctionOverloadParams(const ArenaVector<ir::Expression *> &params)
3537 {
3538     for (auto *it : params) {
3539         if (it->IsAssignmentPattern()) {
3540             ThrowSyntaxError(
3541                 "A parameter initializer is only allowed in a function "
3542                 "or constructor implementation.",
3543                 it->Start());
3544         }
3545     }
3546 }
3547 
ParseSpreadElement(ExpressionParseFlags flags)3548 ir::SpreadElement *ParserImpl::ParseSpreadElement(ExpressionParseFlags flags)
3549 {
3550     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD);
3551     lexer::SourcePosition startLocation = lexer_->GetToken().Start();
3552     bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN);
3553     lexer_->NextToken();
3554 
3555     ir::Expression *argument {};
3556     if (inPattern) {
3557         argument = ParsePatternElement(ExpressionParseFlags::IN_REST);
3558         if ((flags & ExpressionParseFlags::OBJECT_PATTERN) && !argument->IsIdentifier()) {
3559             ThrowSyntaxError("RestParameter must be followed by an identifier in declaration contexts");
3560         }
3561     } else {
3562         argument = ParseExpression(flags);
3563     }
3564 
3565     ir::Expression *typeAnnotation = nullptr;
3566 
3567     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
3568         lexer_->NextToken();  // eat ':'
3569         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
3570         typeAnnotation = ParseTsTypeAnnotation(&options);
3571     }
3572 
3573     if (inPattern && argument->IsAssignmentExpression()) {
3574         ThrowSyntaxError("RestParameter does not support an initializer");
3575     }
3576 
3577     lexer::SourcePosition endLoc = typeAnnotation ? typeAnnotation->End() : argument->End();
3578 
3579     auto nodeType = inPattern ? ir::AstNodeType::REST_ELEMENT : ir::AstNodeType::SPREAD_ELEMENT;
3580     auto *spreadElementNode = AllocNode<ir::SpreadElement>(nodeType, argument);
3581     spreadElementNode->SetRange({startLocation, endLoc});
3582 
3583     if (typeAnnotation) {
3584         spreadElementNode->SetTsTypeAnnotation(typeAnnotation);
3585     }
3586 
3587     return spreadElementNode;
3588 }
3589 
CreateTsParameterProperty(ir::Expression * parameter,ir::ModifierFlags modifiers)3590 ir::TSParameterProperty *ParserImpl::CreateTsParameterProperty(ir::Expression *parameter, ir::ModifierFlags modifiers)
3591 {
3592     auto accessibility = ir::AccessibilityOption::NO_OPTS;
3593     bool readonly = false;
3594     bool isStatic = false;
3595     bool isExport = false;
3596 
3597     if (modifiers & ir::ModifierFlags::PRIVATE) {
3598         accessibility = ir::AccessibilityOption::PRIVATE;
3599     } else if ((modifiers & ir::ModifierFlags::PUBLIC)) {
3600         accessibility = ir::AccessibilityOption::PUBLIC;
3601     } else if (modifiers & ir::ModifierFlags::PROTECTED) {
3602         accessibility = ir::AccessibilityOption::PROTECTED;
3603     }
3604 
3605     if (modifiers & ir::ModifierFlags::READONLY) {
3606         readonly = true;
3607     }
3608 
3609     if (modifiers & ir::ModifierFlags::STATIC) {
3610         isStatic = true;
3611     }
3612 
3613     // TODO(Csaba Repasi): Handle export property of TSParameterProperty
3614 
3615     return AllocNode<ir::TSParameterProperty>(accessibility, parameter, readonly, isStatic, isExport);
3616 }
3617 
ParseFunctionParameter(bool isDeclare)3618 ir::Expression *ParserImpl::ParseFunctionParameter(bool isDeclare)
3619 {
3620     if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_THIS) {
3621         lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
3622     }
3623 
3624     lexer::SourcePosition parameterStart = lexer_->GetToken().Start();
3625     ir::ModifierFlags modifiers = ParseModifiers();
3626     // TODO(Csaba Repasi): throw error if using strick mode reserved keyword here
3627     if (!(context_.Status() & ParserStatus::CONSTRUCTOR_FUNCTION) && modifiers != ir::ModifierFlags::NONE) {
3628         ThrowSyntaxError("A parameter property is only allowed in a constructor implementation.", parameterStart);
3629     }
3630 
3631     lexer::TokenType tokenType = lexer_->GetToken().Type();
3632     if (tokenType == lexer::TokenType::LITERAL_IDENT &&
3633         (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ARGUMENTS ||
3634          lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_EVAL)) {
3635         ThrowSyntaxError(
3636             "'eval' or 'arguments' can't be defined or assigned to "
3637             "in strict mode code",
3638             lexer_->GetToken().Start());
3639     }
3640 
3641     ir::Expression *functionParameter = ParsePatternElement(ExpressionParseFlags::NO_OPTS, true, isDeclare);
3642 
3643     if (modifiers != ir::ModifierFlags::NONE && functionParameter->IsRestElement()) {
3644         ThrowSyntaxError("A parameter property cannot be declared using a rest parameter.", parameterStart);
3645     }
3646 
3647     if (modifiers != ir::ModifierFlags::NONE &&
3648         (functionParameter->IsArrayPattern() || functionParameter->IsObjectPattern() ||
3649          (functionParameter->IsAssignmentPattern() &&
3650           (functionParameter->AsAssignmentPattern()->Left()->IsArrayPattern() ||
3651            functionParameter->AsAssignmentPattern()->Left()->IsObjectPattern())))) {
3652         ThrowSyntaxError("A parameter property may not be declared using a binding pattern.", parameterStart);
3653     }
3654 
3655     if (modifiers != ir::ModifierFlags::NONE) {
3656         functionParameter = CreateTsParameterProperty(functionParameter, modifiers);
3657         functionParameter->SetRange({parameterStart, functionParameter->AsTSParameterProperty()->Parameter()->End()});
3658     }
3659 
3660     Binder()->AddParamDecl(functionParameter);
3661 
3662     return functionParameter;
3663 }
3664 
ValidateLvalueAssignmentTarget(ir::Expression * node) const3665 void ParserImpl::ValidateLvalueAssignmentTarget(ir::Expression *node) const
3666 {
3667     switch (node->Type()) {
3668         case ir::AstNodeType::IDENTIFIER: {
3669             // Check the prevoius ident name
3670             if (node->AsIdentifier()->Name().Is("arguments")) {
3671                 ThrowSyntaxError("Assigning to 'arguments' in strict mode is invalid");
3672             } else if (node->AsIdentifier()->Name().Is("eval")) {
3673                 ThrowSyntaxError("Assigning to 'eval' in strict mode is invalid");
3674             }
3675             break;
3676         }
3677         case ir::AstNodeType::MEMBER_EXPRESSION: {
3678             break;
3679         }
3680         case ir::AstNodeType::TS_AS_EXPRESSION: {
3681             ValidateLvalueAssignmentTarget(node->AsTSAsExpression()->Expr());
3682             break;
3683         }
3684         case ir::AstNodeType::TS_TYPE_ASSERTION: {
3685             ValidateLvalueAssignmentTarget(node->AsTSTypeAssertion()->GetExpression());
3686             break;
3687         }
3688         default: {
3689             ThrowSyntaxError("Invalid left-hand side in assignment expression");
3690         }
3691     }
3692 }
3693 
ValidateAssignmentTarget(ExpressionParseFlags flags,ir::Expression * node)3694 void ParserImpl::ValidateAssignmentTarget(ExpressionParseFlags flags, ir::Expression *node)
3695 {
3696     switch (node->Type()) {
3697         case ir::AstNodeType::ARRAY_PATTERN:
3698         case ir::AstNodeType::OBJECT_PATTERN: {
3699             break;
3700         }
3701         case ir::AstNodeType::ARRAY_EXPRESSION:
3702         case ir::AstNodeType::OBJECT_EXPRESSION: {
3703             if (flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) {
3704                 return;
3705             }
3706 
3707             [[fallthrough]];
3708         }
3709         default: {
3710             return ValidateLvalueAssignmentTarget(node);
3711         }
3712     }
3713 }
3714 
ValidateArrowParameterBindings(const ir::Expression * node)3715 void ParserImpl::ValidateArrowParameterBindings(const ir::Expression *node)
3716 {
3717     switch (node->Type()) {
3718         case ir::AstNodeType::IDENTIFIER: {
3719             const util::StringView &identifier = node->AsIdentifier()->Name();
3720 
3721             if (context_.IsAsync() && identifier.Is("await")) {
3722                 ThrowSyntaxError("'await' in formal parameter is invalid.", node->Start());
3723             }
3724             break;
3725         }
3726         case ir::AstNodeType::OMITTED_EXPRESSION: {
3727             break;
3728         }
3729         case ir::AstNodeType::REST_ELEMENT: {
3730             ValidateArrowParameterBindings(node->AsRestElement()->Argument());
3731             break;
3732         }
3733         case ir::AstNodeType::PROPERTY: {
3734             break;
3735         }
3736         case ir::AstNodeType::OBJECT_PATTERN: {
3737             const auto &props = node->AsObjectPattern()->Properties();
3738 
3739             for (auto *it : props) {
3740                 ValidateArrowParameterBindings(it);
3741             }
3742             break;
3743         }
3744         case ir::AstNodeType::ARRAY_PATTERN: {
3745             const auto &elements = node->AsArrayPattern()->Elements();
3746 
3747             for (auto *it : elements) {
3748                 ValidateArrowParameterBindings(it);
3749             }
3750             break;
3751         }
3752         case ir::AstNodeType::ASSIGNMENT_PATTERN: {
3753             ValidateArrowParameterBindings(node->AsAssignmentPattern()->Left());
3754             break;
3755         }
3756         default: {
3757             ThrowSyntaxError("Unexpected ArrowParameter element");
3758         }
3759     }
3760 }
3761 
CurrentTokenIsModifier(char32_t nextCp) const3762 bool ParserImpl::CurrentTokenIsModifier(char32_t nextCp) const
3763 {
3764     return (Extension() == ScriptExtension::TS &&
3765             (nextCp != LEX_CHAR_EQUALS || nextCp != LEX_CHAR_SEMICOLON || nextCp != LEX_CHAR_LEFT_PAREN));
3766 }
3767 
ThrowParameterModifierError(ir::ModifierFlags status) const3768 void ParserImpl::ThrowParameterModifierError(ir::ModifierFlags status) const
3769 {
3770     ThrowSyntaxError(
3771         {"'", (status & ir::ModifierFlags::STATIC) ? "static" :
3772                                                      ((status & ir::ModifierFlags::ASYNC) ? "async" : "declare"),
3773          "' modifier cannot appear on a parameter."},
3774         lexer_->GetToken().Start());
3775 }
3776 
ThrowSyntaxError(std::string_view errorMessage) const3777 void ParserImpl::ThrowSyntaxError(std::string_view errorMessage) const
3778 {
3779     ThrowSyntaxError(errorMessage, lexer_->GetToken().Start());
3780 }
3781 
ThrowSyntaxError(std::initializer_list<std::string_view> list) const3782 void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list) const
3783 {
3784     ThrowSyntaxError(list, lexer_->GetToken().Start());
3785 }
3786 
ThrowSyntaxError(std::initializer_list<std::string_view> list,const lexer::SourcePosition & pos) const3787 void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list, const lexer::SourcePosition &pos) const
3788 {
3789     std::stringstream ss;
3790 
3791     for (const auto &it : list) {
3792         ss << it;
3793     }
3794 
3795     std::string err = ss.str();
3796 
3797     ThrowSyntaxError(std::string_view {err}, pos);
3798 }
3799 
ThrowSyntaxError(std::string_view errorMessage,const lexer::SourcePosition & pos) const3800 void ParserImpl::ThrowSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos) const
3801 {
3802     lexer::LineIndex index(program_.SourceCode());
3803     lexer::SourceLocation loc = index.GetLocation(pos);
3804 
3805     throw Error {ErrorType::SYNTAX, errorMessage, loc.line, loc.col};
3806 }
3807 
Extension() const3808 ScriptExtension ParserImpl::Extension() const
3809 {
3810     return program_.Extension();
3811 }
3812 
GetSourceTextModuleRecord()3813 parser::SourceTextModuleRecord *ParserImpl::GetSourceTextModuleRecord()
3814 {
3815     return Binder()->Program()->ModuleRecord();
3816 }
3817 
GetSourceTextTypeModuleRecord()3818 parser::SourceTextModuleRecord *ParserImpl::GetSourceTextTypeModuleRecord()
3819 {
3820     return Binder()->Program()->TypeModuleRecord();
3821 }
3822 
AddPatchFixHelper(util::PatchFix * patchFixHelper)3823 void ParserImpl::AddPatchFixHelper(util::PatchFix *patchFixHelper)
3824 {
3825     program_.AddPatchFixHelper(patchFixHelper);
3826 }
3827 
IsDtsFile() const3828 bool ParserImpl::IsDtsFile() const
3829 {
3830     return program_.IsDtsFile();
3831 }
3832 
CheckStrictReservedWord() const3833 void ParserImpl::CheckStrictReservedWord() const
3834 {
3835     if (Extension() == ScriptExtension::JS) {
3836         if (lexer_->GetToken().IsJsStrictReservedWord()) {
3837             ThrowSyntaxError("Unexpected reserved word in strict mode.");
3838         }
3839     } else {
3840         if (lexer_->GetToken().KeywordType() >= lexer::TokenType::KEYW_ARGUMENTS) {
3841             ThrowSyntaxError("Unexpected reserved word in strict mode.");
3842         }
3843     }
3844 }
3845 
RecursiveDepthException()3846 void ParserImpl::RecursiveDepthException()
3847 {
3848     auto pos = lexer_->GetToken().Start();
3849     lexer::LineIndex index(program_.SourceCode());
3850     lexer::SourceLocation loc = index.GetLocation(pos);
3851     throw Error(ErrorType::GENERIC, "Too many nested expressions/statemnets/declarations", loc.line, loc.col);
3852 }
3853 
3854 }  // namespace panda::es2panda::parser
3855