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