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