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