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