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