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