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