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