1/* 2 * Copyright (c) 2022 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 "transformer.h" 17 18#include <util/ustring.h> 19 20#include "binder/scope.h" 21#include "ir/base/catchClause.h" 22#include "ir/base/classProperty.h" 23#include "ir/base/classStaticBlock.h" 24#include "ir/base/decorator.h" 25#include "ir/base/methodDefinition.h" 26#include "ir/base/scriptFunction.h" 27#include "ir/base/templateElement.h" 28#include "ir/expressions/assignmentExpression.h" 29#include "ir/expressions/binaryExpression.h" 30#include "ir/expressions/callExpression.h" 31#include "ir/expressions/classExpression.h" 32#include "ir/expressions/functionExpression.h" 33#include "ir/expressions/identifier.h" 34#include "ir/expressions/literals/bigIntLiteral.h" 35#include "ir/expressions/literals/numberLiteral.h" 36#include "ir/expressions/literals/stringLiteral.h" 37#include "ir/expressions/memberExpression.h" 38#include "ir/expressions/objectExpression.h" 39#include "ir/expressions/sequenceExpression.h" 40#include "ir/expressions/superExpression.h" 41#include "ir/expressions/templateLiteral.h" 42#include "ir/expressions/thisExpression.h" 43#include "ir/module/exportDefaultDeclaration.h" 44#include "ir/module/exportNamedDeclaration.h" 45#include "ir/module/exportSpecifier.h" 46#include "ir/statements/blockStatement.h" 47#include "ir/statements/classDeclaration.h" 48#include "ir/statements/doWhileStatement.h" 49#include "ir/statements/emptyStatement.h" 50#include "ir/statements/expressionStatement.h" 51#include "ir/statements/forInStatement.h" 52#include "ir/statements/forOfStatement.h" 53#include "ir/statements/forUpdateStatement.h" 54#include "ir/statements/functionDeclaration.h" 55#include "ir/statements/returnStatement.h" 56#include "ir/statements/switchStatement.h" 57#include "ir/statements/variableDeclaration.h" 58#include "ir/statements/variableDeclarator.h" 59#include "ir/statements/whileStatement.h" 60#include "ir/ts/tsConstructorType.h" 61#include "ir/ts/tsEnumDeclaration.h" 62#include "ir/ts/tsEnumMember.h" 63#include "ir/ts/tsFunctionType.h" 64#include "ir/ts/tsImportEqualsDeclaration.h" 65#include "ir/ts/tsInterfaceDeclaration.h" 66#include "ir/ts/tsMethodSignature.h" 67#include "ir/ts/tsModuleBlock.h" 68#include "ir/ts/tsModuleDeclaration.h" 69#include "ir/ts/tsParameterProperty.h" 70#include "ir/ts/tsPrivateIdentifier.h" 71#include "ir/ts/tsQualifiedName.h" 72#include "ir/ts/tsSignatureDeclaration.h" 73#include "ir/ts/tsTypeParameterDeclaration.h" 74#include "util/helpers.h" 75 76namespace panda::es2panda::parser { 77 78void Transformer::Transform(Program *program) 79{ 80 program_ = program; 81 if (Extension() == ScriptExtension::TS) { 82 TransformFromTS(); 83 } 84} 85 86void Transformer::TransformFromTS() 87{ 88 ASSERT(Extension() == ScriptExtension::TS); 89 VisitTSNodes(program_->Ast()); 90 PushVariablesToNearestStatements(program_->Ast()); 91} 92 93ir::AstNode *Transformer::VisitTSNodes(ir::AstNode *parent) 94{ 95 if (!parent) { 96 return nullptr; 97 } 98 parent->UpdateSelf([this](auto *childNode) { return VisitTSNode(childNode); }, Binder()); 99 return parent; 100} 101 102void Transformer::AddVariableToNearestStatements(util::StringView name) 103{ 104 /* 105 * Add variable declare like 'var ##var_1;' to nearest statements in namespace function or top level scope 106 * Record the variable name and scope in tempVarDeclStatements_ and will push the VariableDeclaration nodes 107 * to statements in PushVariablesToNearestStatements 108 */ 109 auto currentScope = Scope(); 110 while (currentScope != nullptr) { 111 if (currentScope->IsTSModuleScope()) { 112 auto node = currentScope->Node(); 113 ASSERT(node->IsTSModuleDeclaration()); 114 if (node->AsTSModuleDeclaration()->Body()->IsTSModuleBlock()) { 115 break; 116 } 117 } 118 if (currentScope->IsFunctionScope()) { 119 auto node = currentScope->Node(); 120 ASSERT(node->IsScriptFunction()); 121 if (!node->AsScriptFunction()->FunctionBodyIsExpression()) { 122 break; 123 } 124 } 125 currentScope = currentScope->Parent(); 126 } 127 tempVarDeclStatements_.insert({name, currentScope}); 128} 129 130void Transformer::PushVariablesToNearestStatements(ir::BlockStatement *ast) 131{ 132 /* 133 * Push the VariableDeclaration nodes to nearest statements 134 * For example, transform: 135 * namespace ns { 136 * ... 137 * } 138 * 139 * To: 140 * namespace ns { 141 * var ##var_1; 142 * ... 143 * } 144 */ 145 if (tempVarDeclStatements_.empty()) { 146 return; 147 } 148 for (auto it : tempVarDeclStatements_) { 149 auto *scope = it.second; 150 if (scope == nullptr) { 151 auto scopeCtx = binder::LexicalScope<binder::Scope>::Enter(Binder(), ast->Scope()); 152 ast->AddStatementAtPos(0, CreateVariableDeclarationWithIdentify(it.first, VariableParsingFlags::VAR, 153 nullptr, false)); 154 } else if (scope->IsFunctionScope() || scope->IsTSModuleScope()) { 155 auto *body = scope->Node()->AsScriptFunction()->Body(); 156 ASSERT(body->IsBlockStatement()); 157 auto scopeCtx = binder::LexicalScope<binder::Scope>::Enter(Binder(), scope); 158 body->AsBlockStatement()->AddStatementAtPos(0, CreateVariableDeclarationWithIdentify(it.first, 159 VariableParsingFlags::VAR, nullptr, false)); 160 } 161 } 162} 163 164binder::Scope *Transformer::FindExportVariableInTsModuleScope(util::StringView name) const 165{ 166 bool isExport = false; 167 auto currentScope = Scope(); 168 while (currentScope != nullptr) { 169 binder::Variable *v = currentScope->FindLocal(name, binder::ResolveBindingOptions::BINDINGS); 170 bool isTSModuleScope = currentScope->IsTSModuleScope(); 171 if (v != nullptr) { 172 if (!v->Declaration()->IsVarDecl() && !v->Declaration()->IsLetDecl() && !v->Declaration()->IsConstDecl()) { 173 break; 174 } 175 if (isTSModuleScope && v->Declaration()->IsExportDeclInTsModule()) { 176 isExport = true; 177 } 178 break; 179 } 180 if (currentScope->InLocalTSBindings(name) && 181 !currentScope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name)) { 182 break; 183 } 184 if (isTSModuleScope && currentScope->AsTSModuleScope()->InExportBindings(name)) { 185 isExport = true; 186 break; 187 } 188 currentScope = currentScope->Parent(); 189 } 190 if (!isExport) { 191 return nullptr; 192 } 193 return currentScope; 194} 195 196ir::UpdateNodes Transformer::VisitTSNode(ir::AstNode *childNode) 197{ 198 ASSERT(childNode != nullptr); 199 switch (childNode->Type()) { 200 case ir::AstNodeType::IDENTIFIER: { 201 auto *ident = childNode->AsIdentifier(); 202 if (!ident->IsReference() || (!IsTsModule() && !IsTsEnum() && !InClass())) { 203 return VisitTSNodes(childNode); 204 } 205 206 auto name = ident->Name(); 207 if (InClass()) { 208 auto *classDefinition = GetClassReference(name); 209 auto aliasName = GetClassAliasName(name, classDefinition); 210 if (classDefinition != nullptr && aliasName != name) { 211 ident->SetName(aliasName); 212 } 213 } 214 215 if (IsTsEnum()) { 216 auto scope = FindEnumMemberScope(name); 217 if (scope) { 218 return CreateMemberExpressionFromIdentifier(scope, ident); 219 } 220 } 221 if (IsTsModule()) { 222 auto scope = FindExportVariableInTsModuleScope(name); 223 if (scope) { 224 return CreateMemberExpressionFromIdentifier(scope, ident); 225 } 226 } 227 228 return VisitTSNodes(childNode); 229 } 230 case ir::AstNodeType::TS_MODULE_DECLARATION: { 231 auto *node = childNode->AsTSModuleDeclaration(); 232 if (node->Declare() || !node->IsInstantiated()) { 233 return childNode; 234 } 235 auto res = VisitTsModuleDeclaration(node); 236 SetOriginalNode(res, childNode); 237 return res; 238 } 239 case ir::AstNodeType::TS_ENUM_DECLARATION: { 240 auto *node = childNode->AsTSEnumDeclaration(); 241 if (node->IsDeclare()) { 242 return childNode; 243 } 244 auto res = VisitTsEnumDeclaration(node); 245 SetOriginalNode(res, childNode); 246 return res; 247 } 248 case ir::AstNodeType::EXPORT_NAMED_DECLARATION: { 249 auto *node = childNode->AsExportNamedDeclaration(); 250 auto *decl = node->Decl(); 251 if (!decl) { 252 return VisitTSNodes(childNode); 253 } 254 255 if (decl->IsTSModuleDeclaration()) { 256 auto *tsModuleDeclaration = decl->AsTSModuleDeclaration(); 257 if (tsModuleDeclaration->Declare() || !tsModuleDeclaration->IsInstantiated()) { 258 return childNode; 259 } 260 auto res = VisitTsModuleDeclaration(tsModuleDeclaration, true); 261 SetOriginalNode(res, childNode); 262 return res; 263 } 264 265 if (decl->IsTSEnumDeclaration()) { 266 if (decl->AsTSEnumDeclaration()->IsDeclare() || 267 (decl->AsTSEnumDeclaration()->IsConst() && program_->IsShared())) { 268 return childNode; 269 } 270 auto res = VisitTsEnumDeclaration(decl->AsTSEnumDeclaration(), true); 271 SetOriginalNode(res, childNode); 272 return res; 273 } 274 275 if (IsTsModule()) { 276 auto res = VisitExportNamedVariable(decl); 277 SetOriginalNode(res, node); 278 return res; 279 } 280 281 if (decl->IsClassDeclaration()) { 282 return VisitExportClassDeclaration<ir::ExportNamedDeclaration>(node); 283 } 284 285 return VisitTSNodes(node); 286 } 287 case ir::AstNodeType::EXPORT_DEFAULT_DECLARATION: { 288 auto *node = childNode->AsExportDefaultDeclaration(); 289 auto *decl = node->Decl(); 290 ASSERT(decl != nullptr); 291 if (decl->IsClassDeclaration()) { 292 return VisitExportClassDeclaration<ir::ExportDefaultDeclaration>(node); 293 } 294 // When we export default an identify 'a', a maybe a interface or type. So we should check here. 295 // if decl is not an identifier, it's won't be a type. 296 if (decl->IsIdentifier() && !IsValueReference(decl->AsIdentifier())) { 297 RemoveDefaultLocalExportEntry(); 298 return nullptr; 299 } 300 return VisitTSNodes(childNode); 301 } 302 case ir::AstNodeType::TS_IMPORT_EQUALS_DECLARATION: { 303 auto *node = childNode->AsTSImportEqualsDeclaration(); 304 auto *express = node->ModuleReference(); 305 if (express->IsTSExternalModuleReference()) { 306 return VisitTSNodes(childNode); 307 } 308 auto *res = VisitTsImportEqualsDeclaration(node); 309 SetOriginalNode(res, childNode); 310 return res; 311 } 312 case ir::AstNodeType::CLASS_DECLARATION: { 313 auto *node = childNode->AsClassDeclaration(); 314 if (node->Definition()->Declare() || node->IsAnnotationDecl()) { 315 return node; 316 } 317 DuringClass duringClass(&classList_, node->Definition()->GetName(), 318 CreateClassAliasName(node), node->Definition()); 319 auto *classNode = VisitTSNodes(node); 320 CHECK_NOT_NULL(classNode); 321 node = classNode->AsClassDeclaration(); 322 auto res = VisitClassDeclaration(node); 323 SetOriginalNode(res, childNode); 324 ResetParentScope(res, Scope()); 325 return res; 326 } 327 case ir::AstNodeType::CLASS_EXPRESSION: { 328 auto *node = childNode->AsClassExpression(); 329 DuringClass duringClass(&classList_, node->Definition()->GetName(), 330 node->Definition()->GetName(), node->Definition()); 331 auto *classNode = VisitTSNodes(node); 332 CHECK_NOT_NULL(classNode); 333 node = classNode->AsClassExpression(); 334 auto res = VisitClassExpression(node); 335 SetOriginalNode(res, childNode); 336 return res; 337 } 338 case ir::AstNodeType::CLASS_DEFINITION: { 339 auto *node = childNode->AsClassDefinition(); 340 VisitPrivateElement(node); 341 VisitComputedProperty(node); 342 // Process auto accessor properties 343 VisitAutoAccessorProperty(node); 344 auto res = VisitTSNodes(childNode); 345 SetOriginalNode(res, childNode); 346 return res; 347 } 348 case ir::AstNodeType::TS_PRIVATE_IDENTIFIER: { 349 auto id = childNode->AsTSPrivateIdentifier()->Key()->AsIdentifier(); 350 auto name = FindPrivateElementBindName(id->Name()); 351 auto res = CreateReferenceIdentifier(name); 352 SetOriginalNode(res, childNode); 353 return res; 354 } 355 default: { 356 return VisitTSNodes(childNode); 357 } 358 } 359} 360 361template <typename T> 362ir::UpdateNodes Transformer::VisitExportClassDeclaration(T *node) 363{ 364 auto *decl = node->Decl(); 365 auto newDecl = VisitTSNode(decl); 366 if (std::holds_alternative<ir::AstNode *>(newDecl)) { 367 auto statement = std::get<ir::AstNode *>(newDecl); 368 ASSERT(statement->IsClassDeclaration()); 369 node->SetDecl(statement->AsClassDeclaration()); 370 return node; 371 } else { 372 auto statements = std::get<std::vector<ir::AstNode *>>(newDecl); 373 std::vector<ir::AstNode *> res; 374 auto firstStatement = statements.front(); 375 statements.erase(statements.begin()); 376 if (firstStatement->IsVariableDeclaration()) { 377 node->SetDecl(firstStatement->AsVariableDeclaration()); 378 } else { 379 ASSERT(firstStatement->IsClassDeclaration()); 380 node->SetDecl(firstStatement->AsClassDeclaration()); 381 } 382 res.push_back(node); 383 res.insert(res.end(), statements.begin(), statements.end()); 384 return res; 385 } 386} 387 388util::StringView Transformer::CreateNewVariable(bool needAddToStatements) 389{ 390 util::StringView name = CreateNewVariableName(); 391 if (needAddToStatements) { 392 AddVariableToNearestStatements(name); 393 } 394 return name; 395} 396 397util::StringView Transformer::CreateUniqueName(const std::string &head, size_t *index) const 398{ 399 util::StringView name; 400 size_t idx = 0; 401 if (index != nullptr) { 402 idx = *index; 403 } 404 do { 405 idx++; 406 std::stringstream ss; 407 ss << head << std::to_string(idx); 408 auto s = ss.str(); 409 if (!Binder()->HasVariableName(util::StringView(s))) { 410 name = util::UString(s, Allocator()).View(); 411 break; 412 } 413 } while (true); 414 if (index != nullptr) { 415 *index = idx; 416 } 417 Binder()->AddDeclarationName(name); 418 return name; 419} 420 421util::StringView Transformer::CreateNewVariableName() const 422{ 423 auto name = CreateUniqueName(std::string(NEW_VAR_PREFIX) + std::string(NEW_VAR_HEAD)); 424 return name; 425} 426 427ir::UpdateNodes Transformer::VisitClassExpression(ir::ClassExpression *node) 428{ 429 /* 430 * Transform: 431 * var c = class C { 432 * static a = 1 433 * } 434 * 435 * To: 436 * var ##var_1; 437 * var c = (##var_1 = class C {}, 438 * ##var_1.a = 1, 439 * ##var_1) 440 */ 441 auto instanceComputedProperty = VisitInstanceProperty(node->Definition()); 442 443 VisitTSParameterProperty(node->Definition()); 444 445 auto varName = CreateNewVariable(false); 446 auto staticProperty = VisitStaticProperty(node->Definition(), varName); 447 if (instanceComputedProperty.empty() && staticProperty.empty()) { 448 return node; 449 } 450 AddVariableToNearestStatements(varName); 451 452 auto assignment = AllocNode<ir::AssignmentExpression>(CreateReferenceIdentifier(varName), 453 node->AsExpression(), lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 454 ArenaVector<ir::Expression *> sequence(Allocator()->Adapter()); 455 sequence.push_back(assignment); 456 457 for (auto *it : instanceComputedProperty) { 458 sequence.push_back(it->GetExpression()); 459 } 460 for (auto *it : staticProperty) { 461 sequence.push_back(it->GetExpression()); 462 } 463 464 sequence.push_back(CreateReferenceIdentifier(varName)); 465 return AllocNode<ir::SequenceExpression>(std::move(sequence)); 466} 467 468void Transformer::VisitComputedProperty(ir::ClassDefinition *node) 469{ 470 /* 471 * Only create variable for the computed members with decorators or static class property 472 * The new value will be used in the decorators or static property initialize 473 * Transform: 474 * class C { 475 * @f 476 * [a](){} 477 * static [b] = 1 478 * [c] = 1 479 * } 480 * 481 * To: 482 * var ##var_1; 483 * var ##var_2; 484 * var ##var_3; 485 * class C { 486 * @f 487 * [##var_1 = a](){} 488 * static [##var_2 = b] = 1 489 * [##var_3 = c] = 1 490 * } 491 */ 492 for (auto *it : node->Body()) { 493 if (it->IsClassProperty()) { 494 auto *classProperty = it->AsClassProperty(); 495 if (!classProperty->IsComputed()) { 496 continue; 497 } 498 if (classProperty->IsAutoAccessor()) { 499 // Left to processing in auto aceessor process procedure. 500 continue; 501 } 502 auto *key = classProperty->Key(); 503 auto name = CreateNewVariable(); 504 auto *newKey = AllocNode<ir::AssignmentExpression>(CreateReferenceIdentifier(name), 505 key, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 506 classProperty->SetKey(newKey); 507 AddComputedPropertyBinding(it, name); 508 } else if (it->IsMethodDefinition()) { 509 auto *methodDefinition = it->AsMethodDefinition(); 510 if (!methodDefinition->Computed() || 511 (!methodDefinition->HasDecorators() && !methodDefinition->HasParamDecorators())) { 512 continue; 513 } 514 auto *key = methodDefinition->Key(); 515 auto name = CreateNewVariable(); 516 auto *newKey = AllocNode<ir::AssignmentExpression>(CreateReferenceIdentifier(name), 517 key, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 518 methodDefinition->SetKey(newKey); 519 AddComputedPropertyBinding(it, name); 520 } 521 } 522} 523 524const ir::ClassDefinition *Transformer::GetClassReference(util::StringView name) const 525{ 526 auto *scope = Scope(); 527 while (scope != nullptr) { 528 auto *v = scope->FindLocal(name, binder::ResolveBindingOptions::BINDINGS); 529 if (v != nullptr) { 530 if (v->Declaration() != nullptr && v->Declaration()->Node() != nullptr && 531 v->Declaration()->Node()->IsClassDefinition()) { 532 ASSERT(v->Declaration()->Node()->AsClassDefinition()->GetName() == name); 533 return v->Declaration()->Node()->AsClassDefinition(); 534 } else { 535 return nullptr; 536 } 537 } 538 539 scope = scope->Parent(); 540 } 541 542 return nullptr; 543} 544 545util::StringView Transformer::CreateClassAliasName(ir::ClassDeclaration *node) 546{ 547 if (node->HasDecorators()) { 548 return CreateUniqueName(std::string(NEW_VAR_PREFIX) + std::string(NEW_VAR_HEAD)); 549 } 550 return node->Definition()->GetName(); 551} 552 553void Transformer::VisitPrivateElement(ir::ClassDefinition *node) 554{ 555 /* 556 * Create an unique variable name for private property member in class 557 * Transform: 558 * class C { 559 * #a = 1 560 * } 561 * 562 * To: 563 * class C { 564 * ##${RecordName}#C#a#1 = 1 565 * } 566 */ 567 for (auto *it : node->Body()) { 568 if (!it->IsClassProperty() && !it->IsMethodDefinition()) { 569 continue; 570 } 571 auto *key = it->IsClassProperty() ? it->AsClassProperty()->Key() : it->AsMethodDefinition()->Key(); 572 if (!key->IsTSPrivateIdentifier()) { 573 continue; 574 } 575 auto name = key->AsTSPrivateIdentifier()->Key()->AsIdentifier()->Name(); 576 auto bindName = CreatePrivateElementBindName(name); 577 AddPrivateElementBinding(name, bindName); 578 } 579} 580 581util::StringView Transformer::FindPrivateElementBindName(util::StringView name) 582{ 583 for (int i = static_cast<int>(classList_.size() - 1); i >= 0; i--) { 584 auto res = classList_[i].bindNameMap->find(name); 585 if (res != classList_[i].bindNameMap->end()) { 586 return res->second; 587 } 588 } 589 UNREACHABLE(); 590} 591 592util::StringView Transformer::CreatePrivateElementBindName(util::StringView name) 593{ 594 std::stringstream head; 595 head << NEW_VAR_PREFIX << std::string(RecordName()); 596 for (auto it : classList_) { 597 head << PRIVATE_PROPERTY_SIGN << std::string(it.name); 598 } 599 head << PRIVATE_PROPERTY_SIGN << std::string(name) << PRIVATE_PROPERTY_SIGN; 600 size_t index = GetCurrentClassInfoPropertyIndex(); 601 auto uniqueName = CreateUniqueName(head.str(), &index); 602 SetCurrentClassInfoPropertyIndex(index); 603 return uniqueName; 604} 605 606size_t Transformer::GetInsertPosForConstructor(ir::ClassDefinition *node) 607{ 608 size_t insertPos = 0; 609 ir::BlockStatement *blockStat = node->Ctor()->Function()->Body()->AsBlockStatement(); 610 auto iter = blockStat->Statements().begin(); 611 for (; iter != blockStat->Statements().end();) { 612 if ((*iter)->IsExpressionStatement() && 613 (*iter)->AsExpressionStatement()->GetExpression()->IsStringLiteral()) { 614 iter++; 615 insertPos++; 616 } else { 617 break; 618 } 619 } 620 621 if (node->Super() == nullptr || node->Super()->IsNullLiteral()) { 622 return insertPos; 623 } 624 625 for (; iter != blockStat->Statements().end(); iter++) { 626 insertPos++; 627 628 bool hasSuperCall = false; 629 FindSuperCallInCtorChildNode(*iter, &hasSuperCall); 630 if (hasSuperCall) { 631 break; 632 } 633 } 634 635 return insertPos; 636} 637 638void Transformer::FindSuperCall(const ir::AstNode *parent, bool *hasSuperCall) 639{ 640 parent->Iterate([this, hasSuperCall](auto *childNode) { 641 FindSuperCallInCtorChildNode(childNode, hasSuperCall); 642 }); 643} 644 645void Transformer::FindSuperCallInCtorChildNode(const ir::AstNode *childNode, bool *hasSuperCall) 646{ 647 if (*hasSuperCall) { 648 return; 649 } 650 switch (childNode->Type()) { 651 case ir::AstNodeType::CALL_EXPRESSION: { 652 if (childNode->AsCallExpression()->Callee()->IsSuperExpression()) { 653 *hasSuperCall = true; 654 return; 655 } 656 break; 657 } 658 case ir::AstNodeType::CLASS_DEFINITION: 659 case ir::AstNodeType::FUNCTION_DECLARATION: 660 case ir::AstNodeType::FUNCTION_EXPRESSION: 661 case ir::AstNodeType::ARROW_FUNCTION_EXPRESSION: { 662 break; 663 } 664 default: { 665 FindSuperCall(childNode, hasSuperCall); 666 break; 667 } 668 } 669} 670 671std::vector<ir::ExpressionStatement *> Transformer::VisitInstanceProperty(ir::ClassDefinition *node) 672{ 673 /* 674 * Move class InstanceProperty to constructor. 675 * Transform: 676 * class C { 677 * "prop" = 1; 678 * } 679 * 680 * To: 681 * class C { 682 * constructor () { 683 * this["prop"] = 1; 684 * } 685 * } 686 */ 687 std::vector<ir::ClassProperty *> addToCtor; 688 // Non-null computed properties need to be added outside the class. It is a subset of addToCtor. 689 std::vector<ir::ExpressionStatement *> computedProps; 690 for (auto *it : node->Body()) { 691 if (it->IsClassProperty() && !it->AsClassProperty()->IsStatic() && 692 !it->AsClassProperty()->Key()->IsPrivateIdentifier() && it->AsClassProperty()->Value() != nullptr) { 693 addToCtor.push_back(it->AsClassProperty()); 694 } 695 } 696 if (addToCtor.empty()) { 697 return {}; 698 } 699 700 auto ctorScopeCtx = binder::LexicalScope<binder::FunctionScope>::Enter(Binder(), node->Ctor()->Function()->Scope()); 701 702 ir::BlockStatement *blockStat = node->Ctor()->Function()->Body()->AsBlockStatement(); 703 size_t insertPos = GetInsertPosForConstructor(node); 704 for (auto *it : addToCtor) { 705 if (it->IsComputed()) { 706 computedProps.push_back(AllocNode<ir::ExpressionStatement>(it->Key())); 707 } 708 709 ir::MemberExpression *left = nullptr; 710 auto *member = GetClassMemberName(it->Key(), it->IsComputed(), it, false); 711 if (member->IsIdentifier() && !it->IsComputed()) { 712 left = AllocNode<ir::MemberExpression>(AllocNode<ir::ThisExpression>(), member, 713 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, 714 false, false); 715 } else { 716 left = AllocNode<ir::MemberExpression>(AllocNode<ir::ThisExpression>(), member, 717 ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS, 718 true, false); 719 } 720 auto assignment = AllocNode<ir::AssignmentExpression>(left, it->Value(), 721 lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 722 723 ResetParentScopeForAstNode(assignment, Scope()); 724 blockStat->AddStatementAtPos(insertPos, AllocNode<ir::ExpressionStatement>(assignment)); 725 insertPos++; 726 } 727 return computedProps; 728} 729 730void Transformer::VisitTSParameterProperty(ir::ClassDefinition *node) 731{ 732 /* 733 * Add class property for the parameter property declaration in constructor 734 * Transform: 735 * class C { 736 * constructor(public a = 1) {} 737 * } 738 * 739 * To: 740 * class C { 741 * constructor(public a = 1) { 742 * this.a = a; 743 * } 744 * } 745 */ 746 auto *func = node->Ctor()->Function(); 747 auto *body = func->Body(); 748 if (body == nullptr) { 749 return; 750 } 751 auto blockStatement = body->AsBlockStatement(); 752 size_t insertPos = GetInsertPosForConstructor(node); 753 for (auto *it : func->Params()) { 754 if (!it->IsTSParameterProperty()) { 755 continue; 756 } 757 auto *parameter = it->AsTSParameterProperty()->Parameter(); 758 util::StringView name; 759 // TSParameterPropert only can be identifier or assignment pattern 760 if (parameter->IsIdentifier()) { 761 name = parameter->AsIdentifier()->Name(); 762 } else { 763 ASSERT(parameter->IsAssignmentPattern()); 764 auto *left = parameter->AsAssignmentPattern()->Left(); 765 ASSERT(left->IsIdentifier()); 766 name = left->AsIdentifier()->Name(); 767 } 768 auto left = AllocNode<ir::MemberExpression>(AllocNode<ir::ThisExpression>(), 769 AllocNode<ir::Identifier>(name), 770 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); 771 auto right = CreateReferenceIdentifier(name); 772 auto assignment = AllocNode<ir::AssignmentExpression>(left, right, 773 lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 774 blockStatement->AddStatementAtPos(insertPos, AllocNode<ir::ExpressionStatement>(assignment)); 775 insertPos++; 776 } 777} 778 779void Transformer::VisitAutoAccessorProperty(ir::ClassDefinition *node) 780{ 781 ASSERT(node != nullptr); 782 std::vector<ir::ClassProperty *> autoAccessorPropertyList; 783 for (auto *it : node->Body()) { 784 if (!it->IsClassProperty()) { 785 continue; 786 } 787 auto* prop = it->AsClassProperty(); 788 if (prop->IsAutoAccessor()) { 789 autoAccessorPropertyList.push_back(prop); 790 } 791 } 792 // Must process after iterating complete(can't add node during iterating). 793 for (auto *prop : autoAccessorPropertyList) { 794 ProcessAutoAccessorProperty(prop, node); 795 } 796} 797 798ir::Expression *Transformer::CopyClassKeyExpression(ir::Expression *orginalExpr) 799{ 800 ir::Expression *newExpr = nullptr; 801 switch (orginalExpr->Type()) { 802 case ir::AstNodeType::IDENTIFIER: { 803 ir::Identifier *ident = orginalExpr->AsIdentifier(); 804 newExpr = AllocNode<ir::Identifier>(ident->Name()); 805 break; 806 } 807 case ir::AstNodeType::PRIVATE_IDENTIFIER: { 808 ir::PrivateIdentifier *ident = orginalExpr->AsPrivateIdentifier(); 809 newExpr = AllocNode<ir::PrivateIdentifier>(ident->Name()); 810 break; 811 } 812 case ir::AstNodeType::TS_PRIVATE_IDENTIFIER: { 813 ir::Identifier *ident = orginalExpr->AsTSPrivateIdentifier()->Key()->AsIdentifier(); 814 newExpr = AllocNode<ir::Identifier>(ident->Name()); 815 break; 816 } 817 case ir::AstNodeType::STRING_LITERAL: { 818 ir::StringLiteral *stringLiteral = orginalExpr->AsStringLiteral(); 819 newExpr = AllocNode<ir::StringLiteral>(stringLiteral->Str()); 820 break; 821 } 822 case ir::AstNodeType::BIGINT_LITERAL: { 823 ir::BigIntLiteral *bigIntLiteral = orginalExpr->AsBigIntLiteral(); 824 newExpr = AllocNode<ir::BigIntLiteral>(bigIntLiteral->Str()); 825 break; 826 } 827 case ir::AstNodeType::NUMBER_LITERAL: { 828 auto *numberLiteral = orginalExpr->AsNumberLiteral(); 829 newExpr = AllocNode<ir::NumberLiteral>(numberLiteral->Number(), numberLiteral->Str()); 830 break; 831 } 832 default: { 833 UNREACHABLE(); 834 } 835 } 836 newExpr->SetRange(orginalExpr->Range()); 837 return newExpr; 838} 839 840void Transformer::ProcessAutoAccessorProperty(ir::ClassProperty *node, ir::ClassDefinition *classDefinition) 841{ 842 /* 843 * Transform for auto accessor 844 * class A { 845 * accessor name:string; 846 * } 847 * 848 * To: 849 * 850 * class A { 851 * #__name:string; 852 * get name() { 853 * return this.#__name; 854 * } 855 * set name(value: string) { 856 * this.#__name == value; 857 * } 858 * } 859 * 860 * For computed auto accessor property: 861 * class A { 862 * accessor [name]:string; 863 * } 864 * 865 * To: 866 * var #var_1; // unique name 867 * class A { 868 * #__name:string; 869 * get [#var_1 = name]() { 870 * return this.#__name; 871 * } 872 * set [#var_1](value: string) { 873 * this.#__name == value; 874 * } 875 * } 876 */ 877 878 // 1. Create a private property 879 ASSERT(node->Key() != nullptr); 880 auto *originKeyNode = node->Key(); 881 auto transformedName = CreatePrivateElementBindName(AUTO_ACCESSOR_STORAGE_NAME); 882 auto *internalIdentifier = AllocNode<ir::Identifier>(transformedName); 883 internalIdentifier->SetRange(originKeyNode->Range()); 884 internalIdentifier->SetParent(originKeyNode->Parent()); 885 node->SetKey(internalIdentifier); 886 887 util::StringView backupVarName; 888 bool computed = node->IsComputed(); 889 if (computed) { 890 backupVarName = CreateNewVariable(true); 891 node->SetComputed(false); // Transform this property to internal property, and removed the computed type. 892 } 893 // 2. Add get and set accessor 894 ir::ModifierFlags modifierMask = ir::ModifierFlags::ACCESS | ir::ModifierFlags::STATIC; 895 ir::ModifierFlags modifiers = static_cast<ir::ModifierFlags>(node->Modifiers() & modifierMask); 896 897 MethodInfo getMethodInfo = {CopyClassKeyExpression(originKeyNode), backupVarName, ir::MethodDefinitionKind::GET, 898 modifiers, computed}; 899 AddGeneratedSetOrGetMethodToClass(classDefinition, node, getMethodInfo); 900 MethodInfo setMethodInfo = {CopyClassKeyExpression(originKeyNode), backupVarName, ir::MethodDefinitionKind::SET, 901 modifiers, computed}; 902 AddGeneratedSetOrGetMethodToClass(classDefinition, node, setMethodInfo); 903} 904 905ir::MethodDefinition* Transformer::AddMethodToClass(ir::ClassDefinition *classDefinition, 906 const MethodInfo& methodInfo, 907 ArenaVector<ir::Expression *> ¶ms, 908 ArenaVector<ir::Statement *> &statements) 909{ 910 CHECK_NOT_NULL(classDefinition); 911 ASSERT((methodInfo.kind == ir::MethodDefinitionKind::GET) || (methodInfo.kind == ir::MethodDefinitionKind::SET)); 912 913 auto *paramScope = Binder()->Allocator()->New<binder::FunctionParamScope>(Allocator(), Binder()->GetScope()); 914 CHECK_NOT_NULL(paramScope); 915 for (auto ¶m : params) { 916 paramScope->AddParamDecl(Allocator(), param); 917 } 918 auto *scope = Binder()->Allocator()->New<binder::FunctionScope>(Allocator(), paramScope); 919 CHECK_NOT_NULL(scope); 920 paramScope->BindFunctionScope(scope); 921 auto *body = AllocNode<ir::BlockStatement>(scope, std::move(statements)); 922 auto *func = AllocNode<ir::ScriptFunction>(scope, std::move(params), nullptr, body, nullptr, 923 ir::ScriptFunctionFlags::METHOD, false, false); 924 scope->BindNode(func); 925 scope->BindParamScope(paramScope); 926 paramScope->BindNode(func); 927 928 auto *funcExpr = AllocNode<ir::FunctionExpression>(func); 929 ir::Expression *keyNode = nullptr; 930 if (!methodInfo.isComputed) { 931 keyNode = methodInfo.key; 932 } else { 933 if (methodInfo.kind == ir::MethodDefinitionKind::GET) { 934 auto *backupNode = CreateReferenceIdentifier(methodInfo.backupName); 935 keyNode = AllocNode<ir::AssignmentExpression>(backupNode, methodInfo.key, 936 lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 937 } else { 938 auto *backupNode = CreateReferenceIdentifier(methodInfo.backupName); 939 keyNode = backupNode; 940 } 941 } 942 943 ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter()); 944 ArenaVector<ir::Annotation *> annotations(Allocator()->Adapter()); 945 ArenaVector<ir::ParamDecorators> paramDecorators(Allocator()->Adapter()); 946 auto *method = AllocNode<ir::MethodDefinition>(methodInfo.kind, keyNode, funcExpr, 947 methodInfo.modifiers, Allocator(), std::move(decorators), 948 std::move(annotations), std::move(paramDecorators), 949 methodInfo.isComputed); 950 classDefinition->AddToBody(method); 951 if (methodInfo.isComputed) { 952 AddComputedPropertyBinding(method, methodInfo.backupName); 953 } 954 return method; 955} 956 957ir::MethodDefinition* Transformer::AddGeneratedMethodToClass(ir::ClassDefinition *classDefinition, 958 const MethodInfo &methodInfo, 959 util::StringView propName) 960{ 961 ASSERT(classDefinition != nullptr); 962 ArenaVector<ir::Expression *> params(Allocator()->Adapter()); 963 ArenaVector<ir::Statement *> statements(Allocator()->Adapter()); 964 965 if (methodInfo.kind == ir::MethodDefinitionKind::GET) { 966 /* 967 * Add `return this.prop` to function body. 968 */ 969 auto *identNode = AllocNode<ir::Identifier>(propName); 970 auto *returnExpr = AllocNode<ir::MemberExpression>(AllocNode<ir::ThisExpression>(), identNode, 971 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); 972 ir::ReturnStatement *returnStatement = AllocNode<ir::ReturnStatement>(returnExpr); 973 statements.push_back(returnStatement); 974 } else if (methodInfo.kind == ir::MethodDefinitionKind::SET) { 975 /* 976 * 1. Add `value` to params 977 * 2. Add `this.prop = value` to function body 978 */ 979 util::StringView paramName = util::UString("value", Allocator()).View(); 980 auto *identNode = AllocNode<ir::Identifier>(paramName); 981 params.push_back(identNode); 982 983 auto *identNodeProp = AllocNode<ir::Identifier>(propName); 984 auto *propAccessExpr = AllocNode<ir::MemberExpression>(AllocNode<ir::ThisExpression>(), identNodeProp, 985 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); 986 auto *identNodeRight = AllocNode<ir::Identifier>(paramName); 987 auto *setExpr = AllocNode<ir::AssignmentExpression>(propAccessExpr, identNodeRight, 988 lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 989 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(setExpr); 990 statements.push_back(exprStatementNode); 991 } else { 992 UNREACHABLE(); 993 } 994 auto *method = AddMethodToClass(classDefinition, methodInfo, params, statements); 995 return method; 996} 997 998void Transformer::AddGeneratedSetOrGetMethodToClass(ir::ClassDefinition *classDefinition, 999 ir::ClassProperty *propertyNode, 1000 const MethodInfo &methodInfo) 1001{ 1002 ASSERT(classDefinition != nullptr); 1003 ASSERT(propertyNode != nullptr); 1004 // The key of the property can only be Idetifier here. 1005 auto propName = propertyNode->Key()->AsIdentifier()->Name(); 1006 auto *method = AddGeneratedMethodToClass(classDefinition, methodInfo, propName); 1007 method->SetOriginal(propertyNode); 1008 method->SetRange(propertyNode->Range()); 1009} 1010 1011std::vector<ir::ExpressionStatement *> Transformer::VisitStaticProperty(ir::ClassDefinition *node, 1012 util::StringView name) 1013{ 1014 /* 1015 * Create statement for static class property 1016 * If it's a conputed property, we should initialize it's new variable first. 1017 * Transform: 1018 * var ##var_1; 1019 * class C { 1020 * static a = 1 1021 * static [##var_1 = s] = 1 1022 * } 1023 * 1024 * To: 1025 * var ##var_1; 1026 * class C { 1027 * } 1028 * C.a = 1; 1029 * ##var_1 = s; 1030 * C[##var_1] = 1; 1031 * 1032 * TODO(xucheng): should support static private property 1033 */ 1034 1035 // When targetApiVersion is greater than 10, for classes with decorators, 1036 // the static public class properties in them will go through the transform process. 1037 // The number 10 is used to indicate the target api version 1038 if (program_->TargetApiVersion() > 10 && !(node->IsClassDecoratorPresent())) { 1039 return {}; 1040 } 1041 1042 std::vector<ir::ExpressionStatement *> res; 1043 auto classDefinitionBody = node->Body(); 1044 for (auto *it : classDefinitionBody) { 1045 if (!it->IsClassProperty()) { 1046 continue; 1047 } 1048 auto *classProperty = it->AsClassProperty(); 1049 if (!classProperty->IsStatic()) { 1050 continue; 1051 } 1052 1053 // if property in the form of `static #a`, it will not be processed. 1054 if (classProperty->IsPrivate()) { 1055 continue; 1056 } 1057 1058 if (classProperty->IsComputed()) { 1059 res.push_back(AllocNode<ir::ExpressionStatement>(classProperty->Key())); 1060 } 1061 auto right = classProperty->Value(); 1062 if (right == nullptr) { 1063 continue; 1064 } 1065 1066 ir::MemberExpression *left = nullptr; 1067 auto *member = GetClassMemberName(classProperty->Key(), classProperty->IsComputed(), classProperty, false); 1068 if (member->IsIdentifier() && !classProperty->IsComputed()) { 1069 left = AllocNode<ir::MemberExpression>(CreateReferenceIdentifier(name), member, 1070 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, 1071 false, false); 1072 } else { 1073 left = AllocNode<ir::MemberExpression>(CreateReferenceIdentifier(name), member, 1074 ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS, 1075 true, false); 1076 } 1077 auto assignment = AllocNode<ir::AssignmentExpression>(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 1078 1079 // When TargetApiVersion is greater than 10, for classes with decorators, 1080 // the value of the public static class property in the class will be assigned to nullptr, 1081 // and the value will be assigned outside the class. 1082 // The number 10 is used to indicate the target api version 1083 if (program_->TargetApiVersion() > 10) { 1084 classProperty->RemoveValue(); 1085 } 1086 res.push_back(AllocNode<ir::ExpressionStatement>(assignment)); 1087 } 1088 return res; 1089} 1090 1091ir::UpdateNodes Transformer::VisitClassDeclaration(ir::ClassDeclaration *node) 1092{ 1093 auto name = node->Definition()->GetName(); 1094 std::vector<ir::AstNode *> res; 1095 bool hasClassDecorators = node->HasDecorators(); 1096 if (hasClassDecorators) { 1097 auto aliasName = GetClassAliasName(); 1098 res.push_back(CreateVariableDeclarationWithIdentify(aliasName, VariableParsingFlags::VAR, nullptr, false)); 1099 auto *clsExpression = AllocNode<ir::ClassExpression>(node->Definition()); 1100 auto *assignExpr = AllocNode<ir::AssignmentExpression>(CreateReferenceIdentifier(aliasName), clsExpression, 1101 lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 1102 res.push_back(CreateVariableDeclarationWithIdentify(name, VariableParsingFlags::LET, node, false, 1103 assignExpr, false)); 1104 } else { 1105 res.push_back(node); 1106 } 1107 1108 auto instanceComputedProperty = VisitInstanceProperty(node->Definition()); 1109 // instanceComputedProperty has been transformed by VisitComputedPerporty before, here is an assignmentExpression. 1110 if (!instanceComputedProperty.empty()) { 1111 res.insert(res.end(), instanceComputedProperty.begin(), instanceComputedProperty.end()); 1112 } 1113 1114 VisitTSParameterProperty(node->Definition()); 1115 1116 auto staticProperty = VisitStaticProperty(node->Definition(), name); 1117 if (!staticProperty.empty()) { 1118 res.insert(res.end(), staticProperty.begin(), staticProperty.end()); 1119 } 1120 1121 auto classDefinitionBody = node->Definition()->Body(); 1122 bool hasPrivateIdentifier = HasPrivateIdentifierInDecorators(node->Definition()); 1123 ir::ClassStaticBlock *staticBlock = CreateClassStaticBlock(node, hasPrivateIdentifier); 1124 1125 // decorators of static members, should be called after instance members 1126 std::vector<ir::AstNode *> staticMemberDecorators; 1127 for (auto *it : classDefinitionBody) { 1128 auto scopeCtx = binder::LexicalScope<binder::Scope>::Enter(Binder(), 1129 hasPrivateIdentifier ? staticBlock->GetBody()->Scope() : Scope()); 1130 if (it->IsMethodDefinition()) { 1131 auto *definition = it->AsMethodDefinition(); 1132 bool isStatic = definition->IsStatic(); 1133 1134 auto variableDeclarations = CreateVariableDeclarationForDecorators(definition); 1135 if (isStatic) { 1136 staticMemberDecorators.insert(staticMemberDecorators.end(), 1137 variableDeclarations.begin(), variableDeclarations.end()); 1138 } else if (!hasPrivateIdentifier) { 1139 res.insert(res.end(), variableDeclarations.begin(), variableDeclarations.end()); 1140 } 1141 1142 auto paramDecorators = CreateParamDecorators(name, definition, variableDeclarations, false, isStatic); 1143 if (isStatic) { 1144 staticMemberDecorators.insert(staticMemberDecorators.end(), 1145 paramDecorators.begin(), paramDecorators.end()); 1146 } else if (!hasPrivateIdentifier) { 1147 res.insert(res.end(), paramDecorators.begin(), paramDecorators.end()); 1148 } 1149 1150 if (!definition->HasDecorators()) { 1151 continue; 1152 } 1153 1154 auto methodDecorators = CreateMethodDecorators(name, definition, variableDeclarations, isStatic); 1155 if (isStatic) { 1156 staticMemberDecorators.insert(staticMemberDecorators.end(), 1157 methodDecorators.begin(), methodDecorators.end()); 1158 } else if (!hasPrivateIdentifier) { 1159 res.insert(res.end(), methodDecorators.begin(), methodDecorators.end()); 1160 } 1161 1162 if (hasPrivateIdentifier && !isStatic) { 1163 for (auto *it : variableDeclarations) { 1164 staticBlock->GetBody()->AddStatementAtPos( 1165 staticBlock->GetBody()->Statements().size(), it->AsStatement()); 1166 } 1167 for (auto *it : paramDecorators) { 1168 staticBlock->GetBody()->AddStatementAtPos( 1169 staticBlock->GetBody()->Statements().size(), it->AsStatement()); 1170 } 1171 for (auto *it : methodDecorators) { 1172 staticBlock->GetBody()->AddStatementAtPos( 1173 staticBlock->GetBody()->Statements().size(), it->AsStatement()); 1174 } 1175 } 1176 } else if (it->IsClassProperty()) { 1177 auto *classProperty = it->AsClassProperty(); 1178 bool isStatic = classProperty->IsStatic(); 1179 if (!classProperty->HasDecorators()) { 1180 continue; 1181 } 1182 1183 if (classProperty->IsComputed() && !isStatic && classProperty->Value() == nullptr) { 1184 res.push_back(AllocNode<ir::ExpressionStatement>(classProperty->Key())); 1185 } 1186 1187 auto variableDeclarations = CreateVariableDeclarationForDecorators(classProperty); 1188 if (isStatic) { 1189 staticMemberDecorators.insert(staticMemberDecorators.end(), 1190 variableDeclarations.begin(), variableDeclarations.end()); 1191 } else if (!hasPrivateIdentifier) { 1192 res.insert(res.end(), variableDeclarations.begin(), variableDeclarations.end()); 1193 } 1194 1195 auto propertyDecorators = CreatePropertyDecorators(name, classProperty, variableDeclarations, isStatic); 1196 if (isStatic) { 1197 staticMemberDecorators.insert(staticMemberDecorators.end(), 1198 propertyDecorators.begin(), propertyDecorators.end()); 1199 } else if (!hasPrivateIdentifier) { 1200 res.insert(res.end(), propertyDecorators.begin(), propertyDecorators.end()); 1201 } 1202 1203 if (hasPrivateIdentifier && !isStatic) { 1204 for (auto *it : variableDeclarations) { 1205 staticBlock->GetBody()->AddStatementAtPos( 1206 staticBlock->GetBody()->Statements().size(), it->AsStatement()); 1207 } 1208 for (auto *it : propertyDecorators) { 1209 staticBlock->GetBody()->AddStatementAtPos( 1210 staticBlock->GetBody()->Statements().size(), it->AsStatement()); 1211 } 1212 } 1213 } 1214 } 1215 1216 if (!staticMemberDecorators.empty()) { 1217 if (hasPrivateIdentifier) { 1218 for (auto *it : staticMemberDecorators) { 1219 staticBlock->GetBody()->AddStatementAtPos( 1220 staticBlock->GetBody()->Statements().size(), it->AsStatement()); 1221 } 1222 } else { 1223 res.insert(res.end(), staticMemberDecorators.begin(), staticMemberDecorators.end()); 1224 } 1225 } 1226 1227 auto variableDeclarationsForCtorOrClass = CreateVariableDeclarationForDecorators(node); 1228 res.insert(res.end(), variableDeclarationsForCtorOrClass.begin(), variableDeclarationsForCtorOrClass.end()); 1229 1230 // constructor decorators 1231 auto *ctor = node->Definition()->Ctor(); 1232 auto ctorParamDecorators = CreateParamDecorators(name, ctor, variableDeclarationsForCtorOrClass, true, false); 1233 res.insert(res.end(), ctorParamDecorators.begin(), ctorParamDecorators.end()); 1234 1235 // class decorators 1236 if (hasClassDecorators) { 1237 auto classDecorators = CreateClassDecorators(node, variableDeclarationsForCtorOrClass); 1238 res.insert(res.end(), classDecorators.begin(), classDecorators.end()); 1239 } 1240 if (res.size() == 1) { 1241 return res.front(); 1242 } 1243 return res; 1244} 1245 1246ir::ClassStaticBlock *Transformer::CreateClassStaticBlock(ir::ClassDeclaration *node, bool hasPrivateIdentifer) 1247{ 1248 if (!hasPrivateIdentifer) { 1249 return nullptr; 1250 } 1251 1252 ir::MethodDefinition *staticInitializer = node->Definition()->StaticInitializer(); 1253 auto scopeCtx = binder::LexicalScope<binder::FunctionScope>::Enter(Binder(), 1254 staticInitializer->Function()->Scope()); 1255 1256 auto lexScope = binder::LexicalScope<binder::StaticBlockScope>(Binder()); 1257 ir::BlockStatement *blockStatement = nullptr; 1258 1259 { 1260 auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder()); 1261 ArenaVector<ir::Statement *> statements(Allocator()->Adapter()); 1262 blockStatement = AllocNode<ir::BlockStatement>(localCtx.GetScope(), std::move(statements)); 1263 localCtx.GetScope()->BindNode(blockStatement); 1264 } 1265 1266 ir::ClassStaticBlock *staticBlock = AllocNode<ir::ClassStaticBlock>(lexScope.GetScope(), blockStatement); 1267 lexScope.GetScope()->BindNode(staticBlock); 1268 node->Definition()->AddToBody(staticBlock); 1269 1270 return staticBlock; 1271} 1272 1273bool Transformer::HasPrivateIdentifierInDecorators(const ir::ClassDefinition *classDefinition) 1274{ 1275 bool hasPrivateIdentifer = false; 1276 for (auto *it : classDefinition->Body()) { 1277 if (it->IsMethodDefinition()) { 1278 auto methodDecorators = it->AsMethodDefinition()->Decorators(); 1279 for (size_t i = 0; i < methodDecorators.size(); i++) { 1280 FindPrivateIdentifierInDecorator(methodDecorators[i]->Expr(), &hasPrivateIdentifer); 1281 if (hasPrivateIdentifer) { 1282 return true; 1283 } 1284 } 1285 1286 auto paramsDecorators = it->AsMethodDefinition()->GetParamDecorators(); 1287 for (size_t i = 0; i < paramsDecorators.size(); i++) { 1288 auto paramDecorators = paramsDecorators[i].decorators; 1289 for (size_t j = 0; j < paramDecorators.size(); j++) { 1290 FindPrivateIdentifierInDecorator(paramDecorators[j]->Expr(), &hasPrivateIdentifer); 1291 if (hasPrivateIdentifer) { 1292 return true; 1293 } 1294 } 1295 } 1296 } else if (it->IsClassProperty()) { 1297 auto propDecorators = it->AsClassProperty()->Decorators(); 1298 for (size_t i = 0; i < propDecorators.size(); i++) { 1299 FindPrivateIdentifierInDecorator(propDecorators[i]->Expr(), &hasPrivateIdentifer); 1300 if (hasPrivateIdentifer) { 1301 return true; 1302 } 1303 } 1304 } 1305 } 1306 1307 return hasPrivateIdentifer; 1308} 1309 1310void Transformer::FindPrivateIdentifierInDecorator(const ir::AstNode *parent, bool *hasprivateIdentifier) 1311{ 1312 parent->Iterate([this, hasprivateIdentifier](auto *childNode) { 1313 FindPrivateIdentifierInChildNode(childNode, hasprivateIdentifier); 1314 }); 1315} 1316 1317void Transformer::FindPrivateIdentifierInChildNode(const ir::AstNode *childNode, bool *hasprivateIdentifier) 1318{ 1319 if (*hasprivateIdentifier) { 1320 return; 1321 } 1322 1323 switch (childNode->Type()) { 1324 case ir::AstNodeType::MEMBER_EXPRESSION: { 1325 if (childNode->AsMemberExpression()->Property()->IsPrivateIdentifier()) { 1326 *hasprivateIdentifier = true; 1327 return; 1328 } 1329 break; 1330 } 1331 default: { 1332 FindPrivateIdentifierInDecorator(childNode, hasprivateIdentifier); 1333 break; 1334 } 1335 } 1336} 1337 1338std::vector<ir::AstNode *> Transformer::CreateVariableDeclarationForDecorators(ir::AstNode *node) 1339{ 1340 std::vector<ir::AstNode *> res; 1341 1342 switch (node->Type()) { 1343 case ir::AstNodeType::METHOD_DEFINITION: { 1344 auto methodDecorators = node->AsMethodDefinition()->Decorators(); 1345 for (size_t i = 0; i < methodDecorators.size(); i++) { 1346 util::StringView varName = CreateNewVariable(false); 1347 res.push_back(CreateVariableDeclarationWithIdentify(varName, VariableParsingFlags::LET, nullptr, 1348 false, methodDecorators[i]->Expr(), true)); 1349 } 1350 1351 auto paramsDecorators = node->AsMethodDefinition()->GetParamDecorators(); 1352 for (size_t i = 0; i < paramsDecorators.size(); i++) { 1353 auto paramDecorators = paramsDecorators[i].decorators; 1354 for (size_t j = 0; j < paramDecorators.size(); j++) { 1355 util::StringView varName = CreateNewVariable(false); 1356 res.push_back(CreateVariableDeclarationWithIdentify(varName, VariableParsingFlags::LET, nullptr, 1357 false, paramDecorators[j]->Expr(), true)); 1358 } 1359 } 1360 return res; 1361 } 1362 case ir::AstNodeType::CLASS_PROPERTY: { 1363 auto propDecorators = node->AsClassProperty()->Decorators(); 1364 for (size_t i = 0; i < propDecorators.size(); i++) { 1365 util::StringView varName = CreateNewVariable(false); 1366 res.push_back(CreateVariableDeclarationWithIdentify(varName, VariableParsingFlags::LET, nullptr, 1367 false, propDecorators[i]->Expr(), true)); 1368 } 1369 return res; 1370 } 1371 case ir::AstNodeType::CLASS_DECLARATION: { 1372 auto classDecorators = node->AsClassDeclaration()->Decorators(); 1373 for (size_t i = 0; i < classDecorators.size(); i++) { 1374 util::StringView varName = CreateNewVariable(false); 1375 res.push_back(CreateVariableDeclarationWithIdentify(varName, VariableParsingFlags::LET, nullptr, 1376 false, classDecorators[i]->Expr(), true)); 1377 } 1378 1379 auto ctorParamsDecorators = node->AsClassDeclaration()->Definition()->Ctor()->GetParamDecorators(); 1380 for (size_t i = 0; i < ctorParamsDecorators.size(); i++) { 1381 auto ctorParamDecorators = ctorParamsDecorators[i].decorators; 1382 for (size_t j = 0; j < ctorParamDecorators.size(); j++) { 1383 util::StringView varName = CreateNewVariable(false); 1384 res.push_back(CreateVariableDeclarationWithIdentify(varName, VariableParsingFlags::LET, nullptr, 1385 false, ctorParamDecorators[j]->Expr(), true)); 1386 } 1387 } 1388 return res; 1389 } 1390 default: { 1391 UNREACHABLE(); 1392 } 1393 } 1394} 1395 1396std::vector<ir::AstNode *> Transformer::CreateParamDecorators(util::StringView className, 1397 ir::MethodDefinition *node, 1398 const std::vector<ir::AstNode *> &variableDeclarations, 1399 bool isConstructor, 1400 bool isStatic) 1401{ 1402 /* 1403 * Param decorators 1404 * Transform: 1405 * class C { 1406 * f(@g a){} 1407 * } 1408 * 1409 * To: 1410 * class C { 1411 * f(a){} 1412 * } 1413 * g(C.prototype, "f", 0) 1414 * 1415 * Static method or constructor will use constructor function of the class instead of prototype of class 1416 */ 1417 std::vector<ir::AstNode *> res; 1418 size_t pos = variableDeclarations.size(); 1419 auto paramsDecorators = node->GetParamDecorators(); 1420 for (int i = static_cast<int>(paramsDecorators.size()) - 1; i >= 0; i--) { 1421 auto paramIndex = paramsDecorators[i].paramIndex; 1422 auto decorators = paramsDecorators[i].decorators; 1423 for (int j = static_cast<int>(decorators.size()) - 1; j >= 0; j--) { 1424 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter()); 1425 arguments.push_back(CreateDecoratorTarget(className, isConstructor || isStatic)); 1426 arguments.push_back(isConstructor ? 1427 CreateReferenceIdentifier(CONSTRUCTOR_NAME) : 1428 GetClassMemberName(node->Key(), node->Computed(), node)); 1429 arguments.push_back(AllocNode<ir::NumberLiteral>(paramIndex)); 1430 auto *callExpr = AllocNode<ir::CallExpression>( 1431 variableDeclarations[--pos]->AsVariableDeclaration()->Declarators().front()->Id(), 1432 std::move(arguments), nullptr, false); 1433 res.push_back(AllocNode<ir::ExpressionStatement>(callExpr)); 1434 } 1435 } 1436 return res; 1437} 1438 1439std::vector<ir::AstNode *> Transformer::CreatePropertyDecorators(util::StringView className, 1440 ir::ClassProperty *node, 1441 const std::vector<ir::AstNode *> &variableDeclarations, 1442 bool isStatic) 1443{ 1444 /* 1445 * Property decorators 1446 * Transform: 1447 * class C { 1448 * @f a = 1 1449 * } 1450 * 1451 * To: 1452 * class C { 1453 * a = 1 1454 * } 1455 * f(C.prototype, "a") 1456 * 1457 * Static property will use constructor function of the class instead of prototype of class 1458 */ 1459 std::vector<ir::AstNode *> res; 1460 auto decorators = node->Decorators(); 1461 for (int i = static_cast<int>(decorators.size() - 1); i >= 0; i--) { 1462 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter()); 1463 arguments.push_back(CreateDecoratorTarget(className, isStatic)); 1464 arguments.push_back(GetClassMemberName(node->Key(), node->IsComputed(), node)); 1465 auto *callExpr = AllocNode<ir::CallExpression>( 1466 variableDeclarations[i]->AsVariableDeclaration()->Declarators().front()->Id(), 1467 std::move(arguments), nullptr, false); 1468 1469 res.push_back(AllocNode<ir::ExpressionStatement>(callExpr)); 1470 } 1471 return res; 1472} 1473 1474std::vector<ir::AstNode *> Transformer::CreateMethodDecorators(util::StringView className, 1475 ir::MethodDefinition *node, 1476 const std::vector<ir::AstNode *> &variableDeclarations, 1477 bool isStatic) 1478{ 1479 /* 1480 * Method decorators and accessor decorators 1481 * Transform: 1482 * class C { 1483 * @g 1484 * f(){} 1485 * } 1486 * 1487 * To: 1488 * class C { 1489 * f(){} 1490 * } 1491 * var ###a = Object.getOwnPropertyDescriptor(C.prototype, "f"); 1492 * Object.defineProperty(C.prototype, "f", 1493 * g(C.prototype, "f", ###a) || ###a); 1494 * 1495 * static method will use constructor function of the class instead of prototype of class 1496 * If the decorator has a return value, it will be set as the new property of the method 1497 */ 1498 std::vector<ir::AstNode *> res; 1499 size_t pos = node->Decorators().size(); 1500 auto decorators = node->Decorators(); 1501 for (int i = static_cast<int>(decorators.size() - 1); i >= 0; i--) { 1502 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter()); 1503 arguments.push_back(CreateDecoratorTarget(className, isStatic)); 1504 arguments.push_back(GetClassMemberName(node->Key(), node->Computed(), node)); 1505 util::StringView varName = CreateNewVariable(false); 1506 auto getOwnPropertyDescriptorCall = CreateGetOwnPropertyDescriptorCall( 1507 CreateDecoratorTarget(className, isStatic), GetClassMemberName(node->Key(), node->Computed(), node)); 1508 res.push_back(CreateVariableDeclarationWithIdentify(varName, VariableParsingFlags::LET, nullptr, 1509 false, getOwnPropertyDescriptorCall, true)); 1510 arguments.push_back(AllocNode<ir::Identifier>(varName)); 1511 auto *callExpr = AllocNode<ir::CallExpression>( 1512 variableDeclarations[--pos]->AsVariableDeclaration()->Declarators().front()->Id(), 1513 std::move(arguments), nullptr, false); 1514 1515 auto newValue = AllocNode<ir::BinaryExpression>(callExpr, AllocNode<ir::Identifier>(varName), 1516 lexer::TokenType::PUNCTUATOR_LOGICAL_OR); 1517 1518 auto *defineProperty = CreateDefinePropertyCall(CreateDecoratorTarget(className, isStatic), 1519 GetClassMemberName(node->Key(), node->Computed(), node), newValue); 1520 1521 res.push_back(AllocNode<ir::ExpressionStatement>(defineProperty)); 1522 } 1523 return res; 1524} 1525 1526ir::Expression *Transformer::CreateDecoratorTarget(util::StringView className, bool isStatic) 1527{ 1528 if (isStatic) { 1529 return CreateReferenceIdentifier(className); 1530 } 1531 return CreateClassPrototype(className); 1532} 1533 1534ir::MemberExpression *Transformer::CreateClassPrototype(util::StringView className) 1535{ 1536 auto *cls = CreateReferenceIdentifier(className); 1537 return AllocNode<ir::MemberExpression>(cls, AllocNode<ir::Identifier>(CLASS_PROTOTYPE), 1538 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); 1539} 1540 1541ir::CallExpression *Transformer::CreateDefinePropertyCall(ir::Expression *target, 1542 ir::Expression *key, 1543 ir::Expression *value) 1544{ 1545 auto *id = CreateReferenceIdentifier(OBJECT_VAR_NAME); 1546 auto *caller = AllocNode<ir::MemberExpression>(id, AllocNode<ir::Identifier>(FUNC_NAME_OF_DEFINE_PROPERTY), 1547 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); 1548 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter()); 1549 arguments.push_back(target); 1550 arguments.push_back(key); 1551 arguments.push_back(value); 1552 return AllocNode<ir::CallExpression>(caller, std::move(arguments), nullptr, false); 1553} 1554 1555ir::CallExpression *Transformer::CreateGetOwnPropertyDescriptorCall(ir::Expression *target, ir::Expression *key) 1556{ 1557 auto *id = CreateReferenceIdentifier(OBJECT_VAR_NAME); 1558 auto *caller = AllocNode<ir::MemberExpression>(id, 1559 AllocNode<ir::Identifier>(FUNC_NAME_OF_GET_OWN_PROPERTY_DESCRIPTOR), 1560 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); 1561 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter()); 1562 arguments.push_back(target); 1563 arguments.push_back(key); 1564 return AllocNode<ir::CallExpression>(caller, std::move(arguments), nullptr, false); 1565} 1566 1567ir::Expression *Transformer::GetClassMemberName(ir::Expression *key, bool isComputed, 1568 ir::Statement *node, bool inDecorator) 1569{ 1570 if (isComputed) { 1571 auto name = GetComputedPropertyBinding(node); 1572 return AllocNode<ir::Identifier>(name); 1573 } 1574 if (key->IsIdentifier()) { 1575 if (inDecorator) { 1576 return AllocNode<ir::StringLiteral>(key->AsIdentifier()->Name()); 1577 } else { 1578 return AllocNode<ir::Identifier>(key->AsIdentifier()->Name()); 1579 } 1580 } else if (key->IsStringLiteral()) { 1581 return AllocNode<ir::StringLiteral>(key->AsStringLiteral()->Str()); 1582 } else if (key->IsNumberLiteral()) { 1583 return AllocNode<ir::NumberLiteral>(key->AsNumberLiteral()->Number(), key->AsNumberLiteral()->Str()); 1584 } else if (key->IsBigIntLiteral()) { 1585 return AllocNode<ir::BigIntLiteral>(key->AsBigIntLiteral()->Str()); 1586 } 1587 UNREACHABLE(); 1588 return nullptr; 1589} 1590 1591std::vector<ir::AstNode *> Transformer::CreateClassDecorators(ir::ClassDeclaration *node, 1592 const std::vector<ir::AstNode *> &variableDeclarations) 1593{ 1594 /* 1595 * Class decorators 1596 * Transform: 1597 * @f 1598 * class C { 1599 * } 1600 * 1601 * To: 1602 * class C { 1603 * } 1604 * C = f(C) || C; 1605 * 1606 * If the decorator has a return value, it will be used as the new declaration of the class 1607 */ 1608 auto name = node->Definition()->GetName(); 1609 auto decorators = node->Decorators(); 1610 auto size = decorators.size(); 1611 size_t pos = size; 1612 std::vector<ir::AstNode *> res; 1613 for (int i = static_cast<int>(size - 1); i >= 0; i--) { 1614 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter()); 1615 arguments.push_back(CreateReferenceIdentifier(name)); 1616 auto *callExpr = AllocNode<ir::CallExpression>( 1617 variableDeclarations[--pos]->AsVariableDeclaration()->Declarators().front()->Id(), 1618 std::move(arguments), nullptr, false); 1619 1620 auto left = CreateReferenceIdentifier(name); 1621 auto id = CreateReferenceIdentifier(name); 1622 auto right = AllocNode<ir::BinaryExpression>(callExpr, id, lexer::TokenType::PUNCTUATOR_LOGICAL_OR); 1623 auto middle = CreateReferenceIdentifier(GetClassAliasName()); 1624 auto innerAssignExpr = AllocNode<ir::AssignmentExpression>(middle, right, 1625 lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 1626 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, innerAssignExpr, 1627 lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 1628 1629 res.push_back(AllocNode<ir::ExpressionStatement>(assignExpr)); 1630 } 1631 return res; 1632} 1633 1634ir::AstNode *Transformer::VisitTsImportEqualsDeclaration(ir::TSImportEqualsDeclaration *node) 1635{ 1636 if (!IsInstantiatedImportEquals(node, Scope())) { 1637 return node; 1638 } 1639 auto *express = node->ModuleReference(); 1640 auto name = node->Id()->Name(); 1641 if (IsTsModule() && node->IsExport()) { 1642 auto moduleName = GetCurrentTSModuleName(); 1643 auto *id = CreateReferenceIdentifier(moduleName); 1644 auto *left = AllocNode<ir::MemberExpression>(id, AllocNode<ir::Identifier>(name), 1645 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); 1646 ir::Expression *right = CreateMemberExpressionFromQualified(express); 1647 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right, 1648 lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 1649 auto *res = AllocNode<ir::ExpressionStatement>(assignExpr); 1650 return res; 1651 } 1652 1653 ir::Expression *init = CreateMemberExpressionFromQualified(express); 1654 ir::Statement *res = CreateVariableDeclarationWithIdentify(name, VariableParsingFlags::VAR, node, 1655 node->IsExport(), init); 1656 if (node->IsExport()) { 1657 ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter()); 1658 res = AllocNode<ir::ExportNamedDeclaration>(res, std::move(specifiers)); 1659 AddExportLocalEntryItem(name, node->Id()); 1660 } 1661 return res; 1662} 1663 1664bool Transformer::IsInstantiatedImportEquals(const ir::TSImportEqualsDeclaration *node, binder::Scope *scope) const 1665{ 1666 if (!node) { 1667 return false; 1668 } 1669 bool isType = true; 1670 auto *var = FindTSModuleVariable(node->ModuleReference(), scope, &isType); 1671 if (var == nullptr) { 1672 return !isType; 1673 } 1674 auto *decl = var->Declaration(); 1675 ASSERT(decl->IsNamespaceDecl()); 1676 return decl->AsNamespaceDecl()->IsInstantiated(); 1677 return false; 1678} 1679 1680binder::Variable *Transformer::FindTSModuleVariable(const ir::Expression *node, 1681 const binder::Scope *scope, 1682 bool *isType) const 1683{ 1684 if (node == nullptr || !(node->IsTSQualifiedName() || node->IsIdentifier())) { 1685 return nullptr; 1686 } 1687 if (node->IsTSQualifiedName()) { 1688 auto *tsQualifiedName = node->AsTSQualifiedName(); 1689 auto *var = FindTSModuleVariable(tsQualifiedName->Left(), scope, isType); 1690 if (var == nullptr) { 1691 // If it's not a namespace, we would set isType flag before. So we don't set isType here. 1692 return nullptr; 1693 } 1694 auto *exportTSBindings = var->AsNamespaceVariable()->GetExportBindings(); 1695 auto name = tsQualifiedName->Right()->Name(); 1696 binder::Variable *res = exportTSBindings->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name); 1697 if (res != nullptr) { 1698 return res; 1699 } 1700 res = exportTSBindings->FindExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name); 1701 if (res != nullptr) { 1702 auto *node = res->Declaration()->Node(); 1703 return FindTSModuleVariable(node->Parent()->AsTSImportEqualsDeclaration()->ModuleReference(), 1704 res->AsImportEqualsVariable()->GetScope(), isType); 1705 } 1706 1707 // We process namespace and import equals before. So it should be a type, if it's not a js value or enum. 1708 // And const enum was processed as enum in es2abc, so we don't thought it as type here. 1709 // We should process const enum as type, if we change const enum to literal in es2abc later. 1710 *isType = exportTSBindings->FindExportVariable(name) == nullptr && 1711 exportTSBindings->FindExportTSVariable<binder::TSBindingType::ENUMLITERAL>(name) == nullptr; 1712 1713 return nullptr; 1714 } 1715 1716 auto name = node->AsIdentifier()->Name(); 1717 auto *currentScope = scope; 1718 while (currentScope != nullptr) { 1719 auto *res = FindTSVariable<binder::TSBindingType::NAMESPACE>(currentScope, name); 1720 if (res != nullptr) { 1721 return res; 1722 } 1723 1724 res = FindTSVariable<binder::TSBindingType::IMPORT_EQUALS>(currentScope, name); 1725 if (res != nullptr) { 1726 auto *node = res->Declaration()->Node(); 1727 return FindTSModuleVariable(node->Parent()->AsTSImportEqualsDeclaration()->ModuleReference(), 1728 res->AsImportEqualsVariable()->GetScope(), isType); 1729 } 1730 1731 // Enum is not a module, so we return null here. 1732 // Const enum was processed as enum in es2abc, so we don't process it as type here. 1733 res = FindTSVariable<binder::TSBindingType::ENUMLITERAL>(currentScope, name); 1734 if (res != nullptr) { 1735 *isType = false; 1736 return nullptr; 1737 } 1738 1739 res = currentScope->FindLocal(name, binder::ResolveBindingOptions::BINDINGS); 1740 if (res != nullptr) { 1741 *isType = false; 1742 return nullptr; 1743 } 1744 1745 currentScope = currentScope->Parent(); 1746 } 1747 1748 // can not find variable 1749 *isType = true; 1750 return nullptr; 1751} 1752 1753template <binder::TSBindingType type> 1754binder::Variable *Transformer::FindTSVariable(const binder::Scope *scope, const util::StringView &name) const 1755{ 1756 binder::Variable *res = scope->FindLocalTSVariable<type>(name); 1757 if (res == nullptr && scope->IsTSModuleScope()) { 1758 res = scope->AsTSModuleScope()->FindExportTSVariable<type>(name); 1759 } 1760 return res; 1761} 1762 1763std::vector<ir::AstNode *> Transformer::VisitExportNamedVariable(ir::Statement *decl) 1764{ 1765 std::vector<ir::AstNode *> res; 1766 if (decl->IsVariableDeclaration()) { 1767 auto declarators = decl->AsVariableDeclaration()->Declarators(); 1768 for (auto *it : declarators) { 1769 if (it->Init()) { 1770 auto *left = std::get<ir::AstNode *>(VisitTSNode(it->Id()))->AsExpression(); 1771 auto *right = std::get<ir::AstNode *>(VisitTSNode(it->Init()))->AsExpression(); 1772 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right, 1773 lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 1774 res.push_back(AllocNode<ir::ExpressionStatement>(assignExpr)); 1775 } 1776 } 1777 } else if (decl->IsFunctionDeclaration() || decl->IsClassDeclaration()) { 1778 auto newDecl = VisitTSNode(decl); 1779 if (std::holds_alternative<ir::AstNode *>(newDecl)) { 1780 res.push_back(std::get<ir::AstNode *>(newDecl)); 1781 } else { 1782 auto statements = std::get<std::vector<ir::AstNode *>>(newDecl); 1783 res.insert(res.end(), statements.begin(), statements.end()); 1784 } 1785 1786 auto name = decl->IsFunctionDeclaration() ? 1787 decl->AsFunctionDeclaration()->Function()->Id() : 1788 decl->AsClassDeclaration()->Definition()->Ident(); 1789 ASSERT(name != nullptr); 1790 res.push_back(CreateTsModuleAssignment(name->Name())); 1791 } 1792 return res; 1793} 1794 1795ir::Expression *Transformer::CreateMemberExpressionFromQualified(ir::Expression *node) 1796{ 1797 if (node->IsTSQualifiedName()) { 1798 auto *tsQualifiedName = node->AsTSQualifiedName(); 1799 auto *left = CreateMemberExpressionFromQualified(tsQualifiedName->Left()); 1800 auto *right = AllocNode<ir::Identifier>(tsQualifiedName->Right()->Name()); 1801 return AllocNode<ir::MemberExpression>(left, right, 1802 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); 1803 } 1804 ASSERT(node->IsIdentifier()); 1805 auto *id = CreateReferenceIdentifier(node->AsIdentifier()->Name()); 1806 return id; 1807} 1808 1809void Transformer::SetOriginalNode(ir::UpdateNodes res, ir::AstNode *originalNode) const 1810{ 1811 if (std::holds_alternative<ir::AstNode *>(res)) { 1812 auto *node = std::get<ir::AstNode *>(res); 1813 if (node == nullptr || node == originalNode) { 1814 return; 1815 } 1816 node->SetOriginal(originalNode); 1817 node->SetRange(originalNode->Range()); 1818 } else { 1819 auto nodes = std::get<std::vector<ir::AstNode *>>(res); 1820 for (auto *it : nodes) { 1821 it->SetOriginal(originalNode); 1822 it->SetRange(originalNode->Range()); 1823 } 1824 } 1825} 1826 1827void Transformer::ResetParentScope(ir::UpdateNodes res, binder::Scope *parentScope) const 1828{ 1829 if (std::holds_alternative<ir::AstNode *>(res)) { 1830 auto *node = std::get<ir::AstNode *>(res); 1831 if (node == nullptr) { 1832 return; 1833 } 1834 ResetParentScopeForAstNode(node, parentScope); 1835 } else { 1836 auto nodes = std::get<std::vector<ir::AstNode *>>(res); 1837 for (auto *it : nodes) { 1838 ResetParentScopeForAstNode(it, parentScope); 1839 } 1840 } 1841} 1842 1843ir::ExpressionStatement *Transformer::CreateTsModuleAssignment(util::StringView name) 1844{ 1845 auto moduleName = GetCurrentTSModuleName(); 1846 auto *id = CreateReferenceIdentifier(moduleName); 1847 auto *left = AllocNode<ir::MemberExpression>(id, AllocNode<ir::Identifier>(name), 1848 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); 1849 auto *right = CreateReferenceIdentifier(name); 1850 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 1851 return AllocNode<ir::ExpressionStatement>(assignExpr); 1852} 1853 1854util::StringView Transformer::GetNameFromModuleDeclaration(ir::TSModuleDeclaration *node) const 1855{ 1856 return node->Name()->AsIdentifier()->Name(); 1857} 1858 1859ir::VariableDeclaration *Transformer::CreateVariableDeclarationWithIdentify(util::StringView name, 1860 VariableParsingFlags flags, 1861 ir::AstNode *node, 1862 bool isExport, 1863 ir::Expression *init, 1864 bool needBinding) 1865{ 1866 auto *ident = CreateReferenceIdentifier(name); 1867 auto *declarator = AllocNode<ir::VariableDeclarator>(ident, init); 1868 ArenaVector<ir::VariableDeclarator *> declarators(Allocator()->Adapter()); 1869 declarators.push_back(declarator); 1870 1871 auto varKind = ir::VariableDeclaration::VariableDeclarationKind::VAR; 1872 if (flags & VariableParsingFlags::VAR) { 1873 } else if (flags & VariableParsingFlags::LET) { 1874 varKind = ir::VariableDeclaration::VariableDeclarationKind::LET; 1875 } else { 1876 varKind = ir::VariableDeclaration::VariableDeclarationKind::CONST; 1877 } 1878 auto *declaration = AllocNode<ir::VariableDeclaration>(varKind, std::move(declarators), false); 1879 1880 lexer::SourcePosition startPos(0, 0); 1881 if (node != nullptr) { 1882 startPos = node->Start(); 1883 } 1884 if (needBinding) { 1885 binder::Decl *decl = nullptr; 1886 binder::DeclarationFlags declflag = isExport ? 1887 binder::DeclarationFlags::EXPORT : 1888 binder::DeclarationFlags::NONE; 1889 if (flags & VariableParsingFlags::VAR) { 1890 decl = Binder()->AddDecl<binder::VarDecl>(startPos, declflag, false, name); 1891 } else if (flags & VariableParsingFlags::LET) { 1892 decl = Binder()->AddDecl<binder::LetDecl>(startPos, declflag, false, name); 1893 } else { 1894 decl = Binder()->AddDecl<binder::ConstDecl>(startPos, declflag, false, name); 1895 } 1896 decl->BindNode(declaration); 1897 } 1898 1899 return declaration; 1900} 1901 1902util::StringView Transformer::GetParamName(ir::AstNode *node, util::StringView name) const 1903{ 1904 if (node->IsTSModuleDeclaration()) { 1905 auto scope = node->AsTSModuleDeclaration()->Scope(); 1906 if (scope && !scope->HasVariableName(name)) { 1907 return name; 1908 } 1909 } 1910 if (node->IsTSEnumDeclaration()) { 1911 auto scope = node->AsTSEnumDeclaration()->Scope(); 1912 if (scope && !scope->HasDeclarationName(name)) { 1913 return name; 1914 } 1915 } 1916 1917 auto uniqueName = CreateUniqueName(std::string(name) + std::string(INDEX_DIVISION)); 1918 return uniqueName; 1919} 1920 1921ir::CallExpression *Transformer::CreateCallExpressionForTsModule(ir::TSModuleDeclaration *node, 1922 util::StringView name, 1923 bool isExport) 1924{ 1925 ir::ScriptFunction *funcNode = nullptr; 1926 1927 binder::FunctionScope *funcScope = node->Scope(); 1928 binder::FunctionParamScope *funcParamScope = funcScope->ParamScope(); 1929 auto paramName = GetParamName(node, name); 1930 { 1931 auto paramScopeCtx = binder::LexicalScope<binder::FunctionParamScope>::Enter(Binder(), funcParamScope); 1932 1933 ArenaVector<ir::Expression *> params(Allocator()->Adapter()); 1934 auto *parameter = CreateReferenceIdentifier(paramName); 1935 Binder()->AddParamDecl(parameter); 1936 params.push_back(parameter); 1937 1938 ir::BlockStatement *blockNode = nullptr; 1939 { 1940 auto scopeCtx = binder::LexicalScope<binder::FunctionScope>::Enter(Binder(), funcScope); 1941 tsModuleList_.push_back({paramName, funcScope}); 1942 if (node->Body()->IsTSModuleDeclaration()) { 1943 auto *tsModule = node->Body()->AsTSModuleDeclaration(); 1944 auto body = std::get<std::vector<ir::AstNode *>>(VisitTsModuleDeclaration(tsModule, true)); 1945 ArenaVector<ir::Statement *> statements(Allocator()->Adapter()); 1946 for (auto *it : body) { 1947 statements.push_back(static_cast<ir::Statement *>(it)); 1948 } 1949 blockNode = AllocNode<ir::BlockStatement>(funcScope, std::move(statements)); 1950 } else { 1951 auto body = VisitTSNodes(node->Body()); 1952 blockNode = AllocNode<ir::BlockStatement>(funcScope, 1953 std::move(body->AsTSModuleBlock()->Statements())); 1954 } 1955 tsModuleList_.pop_back(); 1956 funcScope->AddBindsFromParam(); 1957 } 1958 1959 funcNode = AllocNode<ir::ScriptFunction>(funcScope, std::move(params), nullptr, blockNode, nullptr, 1960 ir::ScriptFunctionFlags::NONE, false, Extension() == ScriptExtension::TS); 1961 1962 funcScope->BindNode(funcNode); 1963 funcParamScope->BindNode(funcNode); 1964 } 1965 1966 auto *funcExpr = AllocNode<ir::FunctionExpression>(funcNode); 1967 1968 ArenaVector<ir::Expression *> arguments = CreateCallExpressionArguments(name, isExport); 1969 auto *callExpr = AllocNode<ir::CallExpression>(funcExpr, std::move(arguments), nullptr, false); 1970 1971 return callExpr; 1972} 1973 1974ir::Expression *Transformer::CreateTsModuleParam(util::StringView paramName, bool isExport) 1975{ 1976 if (isExport) { 1977 auto moduleName = GetCurrentTSModuleName(); 1978 auto *id = CreateReferenceIdentifier(moduleName); 1979 return AllocNode<ir::MemberExpression>(id, AllocNode<ir::Identifier>(paramName), 1980 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); 1981 } 1982 1983 auto *id = CreateReferenceIdentifier(paramName); 1984 return id; 1985} 1986 1987void Transformer::AddExportLocalEntryItem(util::StringView name, const ir::Identifier *identifier) 1988{ 1989 auto moduleRecord = GetSourceTextModuleRecord(); 1990 auto *entry = moduleRecord->NewEntry<SourceTextModuleRecord::ExportEntry>(name, name, identifier, identifier); 1991 [[maybe_unused]] bool res = moduleRecord->AddLocalExportEntry(entry); 1992 ASSERT(res); 1993} 1994 1995ir::UpdateNodes Transformer::VisitTsModuleDeclaration(ir::TSModuleDeclaration *node, bool isExport) 1996{ 1997 std::vector<ir::AstNode *> res; 1998 1999 util::StringView name = GetNameFromModuleDeclaration(node); 2000 2001 auto findRes = Scope()->FindLocal(name, binder::ResolveBindingOptions::BINDINGS); 2002 if (findRes == nullptr) { 2003 res.push_back(CreateVariableDeclarationForTSEnumOrTSModule(name, node, isExport)); 2004 } 2005 2006 auto *callExpr = CreateCallExpressionForTsModule(node, name, isExport && IsTsModule()); 2007 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(callExpr); 2008 res.push_back(exprStatementNode); 2009 2010 return res; 2011} 2012 2013ir::Identifier *Transformer::CreateReferenceIdentifier(util::StringView name) 2014{ 2015 auto *node = AllocNode<ir::Identifier>(name); 2016 node->AsIdentifier()->SetReference(); 2017 return node; 2018} 2019 2020ir::UpdateNodes Transformer::VisitTsEnumDeclaration(ir::TSEnumDeclaration *node, bool isExport) 2021{ 2022 std::vector<ir::AstNode *> res; 2023 2024 util::StringView name = GetNameFromTsEnumDeclaration(node); 2025 2026 auto findRes = Scope()->FindLocal(name); // Find if the variable with the same name is already defined 2027 if (findRes == nullptr) { 2028 res.push_back(CreateVariableDeclarationForTSEnumOrTSModule(name, node, isExport)); 2029 } 2030 2031 auto *callExpr = CreateCallExpressionForTsEnum(node, name, isExport && IsTsModule()); 2032 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(callExpr); 2033 res.push_back(exprStatementNode); 2034 2035 return res; 2036} 2037 2038ir::AstNode *Transformer::CreateVariableDeclarationForTSEnumOrTSModule(util::StringView name, 2039 ir::AstNode *node, bool isExport) 2040{ 2041 auto flag = Scope()->Parent() == nullptr ? VariableParsingFlags::VAR : VariableParsingFlags::LET; 2042 auto *variableDeclaration = CreateVariableDeclarationWithIdentify(name, flag, node, isExport); 2043 bool doExport = isExport && !IsTsModule(); 2044 if (doExport) { // export var 2045 ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter()); 2046 auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(variableDeclaration, std::move(specifiers)); 2047 auto *ident = node->IsTSEnumDeclaration() ? 2048 node->AsTSEnumDeclaration()->Key()->AsIdentifier() : node->AsTSModuleDeclaration()->Name()->AsIdentifier(); 2049 AddExportLocalEntryItem(name, ident); 2050 return exportDeclaration; 2051 } 2052 return variableDeclaration; 2053} 2054 2055util::StringView Transformer::GetNameFromTsEnumDeclaration(const ir::TSEnumDeclaration *node) const 2056{ 2057 auto *name = node->AsTSEnumDeclaration()->Key(); 2058 return name->AsIdentifier()->Name(); 2059} 2060 2061ir::CallExpression *Transformer::CreateCallExpressionForTsEnum(ir::TSEnumDeclaration *node, util::StringView name, 2062 bool isExport) 2063{ 2064 ir::ScriptFunction *funcNode = nullptr; 2065 2066 binder::FunctionScope *funcScope = node->Scope(); 2067 binder::FunctionParamScope *funcParamScope = funcScope->ParamScope(); 2068 util::StringView paramName = GetParamName(node, name); // modify the name of the function param 2069 { 2070 auto paramScopeCtx = binder::LexicalScope<binder::FunctionParamScope>::Enter(Binder(), funcParamScope); 2071 // create function param 2072 ArenaVector<ir::Expression *> params(Allocator()->Adapter()); 2073 auto *parameter = CreateReferenceIdentifier(paramName); 2074 Binder()->AddParamDecl(parameter); 2075 params.push_back(parameter); 2076 // create function body 2077 ir::BlockStatement *blockNode = nullptr; 2078 { 2079 auto scopeCtx = binder::LexicalScope<binder::FunctionScope>::Enter(Binder(), funcScope); 2080 tsEnumList_.push_back({paramName, funcScope}); 2081 2082 ArenaVector<ir::TSEnumMember *> members = node->Members(); 2083 ArenaVector<ir::Statement *> statements(Allocator()->Adapter()); 2084 ir::TSEnumMember *preTsEnumMember = nullptr; 2085 for (auto member : members) { 2086 auto *currTsEnumMember = member->AsTSEnumMember(); 2087 auto statement = CreateTsEnumMember(currTsEnumMember, preTsEnumMember, paramName); 2088 preTsEnumMember = currTsEnumMember; 2089 statements.push_back(statement); 2090 } 2091 2092 blockNode = AllocNode<ir::BlockStatement>(funcScope, std::move(statements)); 2093 tsEnumList_.pop_back(); 2094 funcScope->AddBindsFromParam(); 2095 } 2096 funcNode = AllocNode<ir::ScriptFunction>(funcScope, std::move(params), nullptr, blockNode, nullptr, 2097 ir::ScriptFunctionFlags::NONE, false, Extension() == ScriptExtension::TS); 2098 2099 funcScope->BindNode(funcNode); 2100 funcParamScope->BindNode(funcNode); 2101 } 2102 auto *funcExpr = AllocNode<ir::FunctionExpression>(funcNode); 2103 2104 ArenaVector<ir::Expression *> arguments = CreateCallExpressionArguments(name, isExport); 2105 auto *callExpr = AllocNode<ir::CallExpression>(funcExpr, std::move(arguments), nullptr, false); 2106 2107 return callExpr; 2108} 2109 2110ArenaVector<ir::Expression *> Transformer::CreateCallExpressionArguments(util::StringView name, bool isExport) 2111{ 2112 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter()); 2113 ArenaVector<ir::Expression *> properties(Allocator()->Adapter()); 2114 auto *objectExpression = AllocNode<ir::ObjectExpression>(ir::AstNodeType::OBJECT_EXPRESSION, 2115 std::move(properties), 2116 false); 2117 auto assignExpr = AllocNode<ir::AssignmentExpression>(CreateTsModuleParam(name, isExport), 2118 objectExpression, 2119 lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 2120 auto argument = AllocNode<ir::BinaryExpression>(CreateTsModuleParam(name, isExport), 2121 assignExpr, 2122 lexer::TokenType::PUNCTUATOR_LOGICAL_OR); 2123 if (isExport) { 2124 auto *id = CreateReferenceIdentifier(name); 2125 arguments.push_back(AllocNode<ir::AssignmentExpression>(id, argument, 2126 lexer::TokenType::PUNCTUATOR_SUBSTITUTION)); 2127 } else { 2128 arguments.push_back(argument); 2129 } 2130 2131 return arguments; 2132} 2133 2134ir::ExpressionStatement *Transformer::CreateTsEnumMember(ir::TSEnumMember *node, ir::TSEnumMember *preNode, 2135 util::StringView enumLiteralName) 2136{ 2137 util::StringView enumMemberName = GetNameFromEnumMember(node); 2138 binder::Variable *enumVar = Scope()->AsTSEnumScope()->FindEnumMemberVariable(enumMemberName); 2139 CHECK_NOT_NULL(enumVar); 2140 if (node->Init() != nullptr) { 2141 bool isStringInit = enumVar->AsEnumVariable()->StringInit(); 2142 if (!enumVar->AsEnumVariable()->IsVisited()) { 2143 isStringInit = IsStringInitForEnumMember(node->Init(), Scope()); 2144 if (isStringInit) { 2145 enumVar->AsEnumVariable()->SetStringInit(); 2146 } 2147 enumVar->AsEnumVariable()->SetVisited(); 2148 } 2149 return isStringInit ? CreateTsEnumMemberWithStringInit(node, enumLiteralName, enumMemberName) : 2150 CreateTsEnumMemberWithNumberInit(node, enumLiteralName, enumMemberName); 2151 } 2152 2153 enumVar->AsEnumVariable()->SetVisited(); 2154 return CreateTsEnumMemberWithoutInit(node, preNode, enumLiteralName, enumMemberName); 2155} 2156 2157ir::ExpressionStatement *Transformer::CreateTsEnumMemberWithStringInit(ir::TSEnumMember *node, 2158 util::StringView enumLiteralName, 2159 util::StringView enumMemberName) 2160{ 2161 // transform to the shape like E["a"] = "str"; 2162 auto *object = CreateReferenceIdentifier(enumLiteralName); 2163 auto *property = AllocNode<ir::StringLiteral>(enumMemberName); 2164 auto *left = AllocNode<ir::MemberExpression>(object, property, 2165 ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS, 2166 true, false); 2167 auto *right = std::get<ir::AstNode *>(VisitTSNode(node->Init()))->AsExpression(); 2168 2169 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 2170 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(assignExpr); 2171 2172 return exprStatementNode; 2173} 2174 2175ir::ExpressionStatement *Transformer::CreateTsEnumMemberWithNumberInit(ir::TSEnumMember *node, 2176 util::StringView enumLiteralName, 2177 util::StringView enumMemberName) 2178{ 2179 // transform to the shape like E[E["a"] = init] = "a"; 2180 auto *innerObject = CreateReferenceIdentifier(enumLiteralName); 2181 auto *innerProperty = AllocNode<ir::StringLiteral>(enumMemberName); 2182 auto *innerLeft = AllocNode<ir::MemberExpression>(innerObject, innerProperty, 2183 ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS, 2184 true, false); 2185 auto *innerRight = std::get<ir::AstNode *>(VisitTSNode(node->Init()))->AsExpression(); 2186 2187 auto *object = CreateReferenceIdentifier(enumLiteralName); 2188 auto *property = AllocNode<ir::AssignmentExpression>(innerLeft, innerRight, 2189 lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 2190 auto *left = AllocNode<ir::MemberExpression>(object, property, 2191 ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS, 2192 true, false); 2193 2194 auto *right = AllocNode<ir::StringLiteral>(enumMemberName); 2195 2196 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 2197 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(assignExpr); 2198 2199 return exprStatementNode; 2200} 2201 2202ir::ExpressionStatement *Transformer::CreateTsEnumMemberWithoutInit(ir::TSEnumMember *node, 2203 ir::TSEnumMember *preNode, 2204 util::StringView enumLiteralName, 2205 util::StringView enumMemberName) 2206{ 2207 // transform to the shape like E[E["a"] = value] = "a"; 2208 auto *innerObject = CreateReferenceIdentifier(enumLiteralName); 2209 auto *innerProperty = AllocNode<ir::StringLiteral>(enumMemberName); 2210 auto *innerLeft = AllocNode<ir::MemberExpression>(innerObject, innerProperty, 2211 ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS, 2212 true, false); 2213 2214 ir::AssignmentExpression *property = nullptr; 2215 if (preNode == nullptr) { // first enumMember, value = 0 2216 auto *innerRight = AllocNode<ir::NumberLiteral>(0); 2217 property = AllocNode<ir::AssignmentExpression>(innerLeft, innerRight, 2218 lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 2219 } else { // not first enumMember, value = E.prenode + 1 2220 auto *innerRightObject = CreateReferenceIdentifier(enumLiteralName); 2221 auto *innerPropertyForMemberExpr = AllocNode<ir::Identifier>(GetNameFromEnumMember(preNode)); 2222 auto *innerMemberExpr = AllocNode<ir::MemberExpression>(innerRightObject, innerPropertyForMemberExpr, 2223 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); 2224 auto *innerRight = AllocNode<ir::BinaryExpression>(innerMemberExpr, AllocNode<ir::NumberLiteral>(1), 2225 lexer::TokenType::PUNCTUATOR_PLUS); 2226 property = AllocNode<ir::AssignmentExpression>(innerLeft, innerRight, 2227 lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 2228 } 2229 auto *object = CreateReferenceIdentifier(enumLiteralName); 2230 auto *left = AllocNode<ir::MemberExpression>(object, property, 2231 ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS, 2232 true, false); 2233 2234 auto *right = AllocNode<ir::StringLiteral>(enumMemberName); 2235 2236 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 2237 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(assignExpr); 2238 2239 return exprStatementNode; 2240} 2241 2242bool Transformer::IsStringInitForEnumMember(const ir::Expression *expr, binder::Scope *scope) const 2243{ 2244 if (expr == nullptr) { 2245 return false; 2246 } 2247 2248 // The string enumMember is either initialized with a string literal, or with another string enumMember. 2249 switch (expr->Type()) { 2250 case ir::AstNodeType::STRING_LITERAL: 2251 case ir::AstNodeType::TEMPLATE_LITERAL: { 2252 // TemplateLiteral in Enum must be a string literal. 2253 return true; 2254 } 2255 case ir::AstNodeType::IDENTIFIER: { 2256 // Return true if this identifier is a string enumMember of the current Enum. 2257 util::StringView identName = expr->AsIdentifier()->Name(); 2258 ASSERT(scope && scope->IsTSEnumScope()); 2259 binder::Variable *v = scope->AsTSEnumScope()->FindEnumMemberVariable(identName); 2260 if (v == nullptr) { 2261 return false; 2262 } 2263 if (!v->AsEnumVariable()->IsVisited()) { // visit the quoted item 2264 auto *initExpr = v->AsEnumVariable()->Declaration()->Node()->AsTSEnumMember()->Init(); 2265 if (IsStringInitForEnumMember(initExpr, scope)) { 2266 v->AsEnumVariable()->SetStringInit(); 2267 } 2268 v->AsEnumVariable()->SetVisited(); 2269 } 2270 if (v->AsEnumVariable()->IsVisited() && v->AsEnumVariable()->StringInit()) { 2271 return true; 2272 } 2273 2274 return false; 2275 } 2276 case ir::AstNodeType::MEMBER_EXPRESSION: { 2277 return IsStringForMemberExpression(expr->AsMemberExpression(), scope); 2278 } 2279 case ir::AstNodeType::BINARY_EXPRESSION: { 2280 auto *left = expr->AsBinaryExpression()->Left(); 2281 auto *right = expr->AsBinaryExpression()->Right(); 2282 if (expr->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_PLUS && 2283 IsStringInitForEnumMember(right, scope) && IsStringInitForEnumMember(left, scope)) { 2284 return true; 2285 } 2286 return false; 2287 } 2288 default: 2289 return false; 2290 } 2291 2292 return false; 2293} 2294 2295bool Transformer::IsStringForMemberExpression(const ir::MemberExpression *memberExpr, binder::Scope *scope) const 2296{ 2297 // Return true only if memberExpression is a string enumMember. 2298 const ir::Expression *expr = memberExpr; 2299 ArenaDeque<const ir::Expression *> members(Allocator()->Adapter()); 2300 while (expr->IsMemberExpression()) { 2301 if (expr->AsMemberExpression()->Property()->IsIdentifier() || 2302 expr->AsMemberExpression()->Property()->IsStringLiteral() || 2303 expr->AsMemberExpression()->Property()->IsTemplateLiteral()) { 2304 members.push_front(expr->AsMemberExpression()->Property()); 2305 expr = expr->AsMemberExpression()->Object(); 2306 } else { 2307 return false; 2308 } 2309 } 2310 if (!expr->IsIdentifier()) { 2311 return false; 2312 } 2313 members.push_front(expr->AsIdentifier()); 2314 2315 // Find front Ident TSVariables 2316 ArenaVector<binder::Variable *> findRes = FindFrontIdentifierTSVariables(members.front()->AsIdentifier(), scope); 2317 members.pop_front(); 2318 2319 for (auto currVar : findRes) { 2320 if (VerifyMemberExpressionDeque(currVar, members)) { 2321 return true; 2322 } 2323 } 2324 return false; 2325} 2326 2327ArenaVector<binder::Variable *> Transformer::FindFrontIdentifierTSVariables(const ir::Identifier *ident, 2328 binder::Scope *scope) const 2329{ 2330 util::StringView name = ident->Name(); 2331 binder::Variable *v = nullptr; 2332 ArenaVector<binder::Variable *> findRes(Allocator()->Adapter()); 2333 while (scope != nullptr) { 2334 // find enumMemberBindings_ 2335 if (scope->IsTSEnumScope()) { 2336 v = scope->AsTSEnumScope()->FindEnumMemberVariable(name); 2337 if (v != nullptr) { 2338 break; 2339 } 2340 } 2341 2342 const std::vector<binder::TSBindingType> types = {binder::TSBindingType::NAMESPACE, 2343 binder::TSBindingType::ENUMLITERAL, 2344 binder::TSBindingType::IMPORT_EQUALS}; 2345 // find tsBindings_ 2346 FindLocalTSVariables(scope, name, types, findRes); 2347 // find exportTSBindings_ 2348 if (scope->IsTSModuleScope()) { 2349 FindExportTSVariables(scope, name, types, findRes); 2350 } 2351 2352 if (!findRes.empty()) { 2353 break; 2354 } 2355 2356 // find js variable 2357 v = scope->FindLocal(name); 2358 if (v != nullptr) { 2359 if (scope->IsTSModuleScope() || scope->IsTSEnumScope()) { // v may be converted from ts variable 2360 v = scope->Parent()->FindLocal(name); 2361 if (v == nullptr) { 2362 break; 2363 } 2364 } else { 2365 break; 2366 } 2367 } 2368 if (scope->IsTSModuleScope()) { 2369 v = scope->AsTSModuleScope()->FindExportVariable(name); 2370 if (v != nullptr) { 2371 break; 2372 } 2373 } 2374 2375 if (scope->IsTSModuleScope() || scope->IsTSEnumScope()) { 2376 scope = scope->Parent(); 2377 } 2378 scope = scope->Parent(); 2379 } 2380 2381 return findRes; 2382} 2383 2384bool Transformer::IsInstantiatedNamespaceVariable(binder::Variable *var) const 2385{ 2386 ASSERT(var->IsNamespaceVariable()); 2387 auto *decl = var->AsNamespaceVariable()->Declaration(); 2388 ASSERT(decl->IsNamespaceDecl()); 2389 ArenaVector<ir::TSModuleDeclaration *> nodes = decl->AsNamespaceDecl()->Decls(); 2390 for (ir::TSModuleDeclaration *node : nodes) { 2391 if (node->IsInstantiated()) { 2392 return true; 2393 } 2394 } 2395 return false; 2396} 2397 2398void Transformer::FindLocalTSVariables(binder::Scope *scope, const util::StringView name, 2399 const std::vector<binder::TSBindingType> &types, 2400 ArenaVector<binder::Variable *> &findRes) const 2401{ 2402 for (binder::TSBindingType type : types) { 2403 binder::Variable *v = nullptr; 2404 switch (type) { 2405 case binder::TSBindingType::NAMESPACE: { 2406 v = scope->FindLocalTSVariable<binder::TSBindingType::NAMESPACE>(name); 2407 if (v != nullptr && !IsInstantiatedNamespaceVariable(v)) { 2408 v = nullptr; 2409 } 2410 break; 2411 } 2412 case binder::TSBindingType::ENUMLITERAL: { 2413 v = scope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(name); 2414 break; 2415 } 2416 case binder::TSBindingType::IMPORT_EQUALS: { 2417 v = scope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name); 2418 if (v != nullptr && 2419 !IsInstantiatedImportEquals(v->AsImportEqualsVariable()->Declaration()->Node()-> 2420 Parent()->AsTSImportEqualsDeclaration(), scope)) { 2421 v = nullptr; 2422 } 2423 break; 2424 } 2425 default: 2426 continue; 2427 } 2428 if (v != nullptr) { 2429 findRes.push_back(v); 2430 } 2431 } 2432} 2433 2434void Transformer::FindExportTSVariables(binder::Scope *scope, const util::StringView name, 2435 const std::vector<binder::TSBindingType> &types, 2436 ArenaVector<binder::Variable *> &findRes) const 2437{ 2438 for (binder::TSBindingType type : types) { 2439 binder::Variable *v = nullptr; 2440 switch (type) { 2441 case binder::TSBindingType::NAMESPACE: { 2442 v = scope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name); 2443 if (v != nullptr && !IsInstantiatedNamespaceVariable(v)) { 2444 v = nullptr; 2445 } 2446 break; 2447 } 2448 case binder::TSBindingType::ENUMLITERAL: { 2449 v = scope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::ENUMLITERAL>(name); 2450 break; 2451 } 2452 case binder::TSBindingType::IMPORT_EQUALS: { 2453 v = scope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name); 2454 if (v != nullptr && 2455 !IsInstantiatedImportEquals(v->AsImportEqualsVariable()->Declaration()->Node()-> 2456 Parent()->AsTSImportEqualsDeclaration(), scope)) { 2457 v = nullptr; 2458 } 2459 break; 2460 } 2461 default: 2462 continue; 2463 } 2464 if (v != nullptr) { 2465 findRes.push_back(v); 2466 } 2467 } 2468} 2469 2470bool Transformer::VerifyMemberExpressionDeque(binder::Variable *currVar, 2471 ArenaDeque<const ir::Expression *> members) const 2472{ 2473 ASSERT(!members.empty()); 2474 switch (currVar->Flags()) { 2475 case binder::VariableFlags::ENUM_LITERAL: { 2476 // the recursion ends. 2477 util::StringView enumMemberName = GetNameForMemberExpressionItem(members.front()); 2478 members.pop_front(); 2479 if (!members.empty()) { 2480 return false; 2481 } 2482 binder::Variable *enumMemberVar = currVar->AsEnumLiteralVariable()->FindEnumMemberVariable(enumMemberName); 2483 if (enumMemberVar == nullptr) { 2484 return false; 2485 } 2486 if (!enumMemberVar->AsEnumVariable()->IsVisited()) { // visit the quoted item 2487 auto *scope = enumMemberVar->AsEnumVariable()->Declaration()-> 2488 Node()->Parent()->AsTSEnumDeclaration()->Scope(); 2489 auto *initExpr = enumMemberVar->AsEnumVariable()->Declaration()->Node()->AsTSEnumMember()->Init(); 2490 if (IsStringInitForEnumMember(initExpr, scope)) { 2491 enumMemberVar->AsEnumVariable()->SetStringInit(); 2492 } 2493 enumMemberVar->AsEnumVariable()->SetVisited(); 2494 } 2495 if (enumMemberVar->AsEnumVariable()->IsVisited() && enumMemberVar->AsEnumVariable()->StringInit()) { 2496 return true; 2497 } 2498 2499 return false; 2500 } 2501 case binder::VariableFlags::NAMESPACE: { 2502 auto *exportTSBindings = currVar->AsNamespaceVariable()->GetExportBindings(); 2503 if (exportTSBindings != nullptr) { 2504 ArenaVector<binder::Variable *> findRes(Allocator()->Adapter()); 2505 util::StringView name = GetNameForMemberExpressionItem(members.front()); 2506 binder::Variable *v = exportTSBindings->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name); 2507 if (v != nullptr && IsInstantiatedNamespaceVariable(v)) { 2508 findRes.push_back(v); 2509 } 2510 v = exportTSBindings->FindExportTSVariable<binder::TSBindingType::ENUMLITERAL>(name); 2511 if (v != nullptr) { 2512 findRes.push_back(v); 2513 } 2514 v = exportTSBindings->FindExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name); 2515 if (v != nullptr) { 2516 findRes.push_back(v); 2517 } 2518 members.pop_front(); 2519 2520 for (auto itemVar : findRes) { 2521 if (VerifyMemberExpressionDeque(itemVar, members)) { 2522 return true; 2523 } 2524 } 2525 return false; 2526 } 2527 return false; 2528 } 2529 case binder::VariableFlags::IMPORT_EQUALS: { 2530 // Replace import_equal 2531 auto *node = currVar->Declaration()->Node()->Parent()->AsTSImportEqualsDeclaration()->ModuleReference(); 2532 while (node->IsTSQualifiedName()) { 2533 members.push_front(node->AsTSQualifiedName()->Right()->AsIdentifier()); 2534 node = node->AsTSQualifiedName()->Left(); 2535 } 2536 members.push_front(node->AsIdentifier()); 2537 2538 ArenaVector<binder::Variable *> findRes = FindFrontIdentifierTSVariables( 2539 members.front()->AsIdentifier(), currVar->AsImportEqualsVariable()->GetScope()); 2540 members.pop_front(); 2541 2542 for (auto itemVar : findRes) { 2543 if (VerifyMemberExpressionDeque(itemVar, members)) { 2544 return true; 2545 } 2546 } 2547 return false; 2548 } 2549 default: 2550 return false; 2551 } 2552 2553 return false; 2554} 2555 2556util::StringView Transformer::GetNameForMemberExpressionItem(const ir::Expression *node) const 2557{ 2558 util::StringView name {}; 2559 if (node->IsIdentifier()) { 2560 name = node->AsIdentifier()->Name(); 2561 } else if (node->IsStringLiteral()) { 2562 name = node->AsStringLiteral()->Str(); 2563 } else if (node->IsTemplateLiteral()) { 2564 name = node->AsTemplateLiteral()->Quasis().front()->Raw(); 2565 } 2566 return name; 2567} 2568 2569util::StringView Transformer::GetNameFromEnumMember(const ir::TSEnumMember *node) const 2570{ 2571 util::StringView name {}; 2572 if (node->Key()->IsIdentifier()) { 2573 name = node->Key()->AsIdentifier()->Name(); 2574 } else if (node->Key()->IsStringLiteral()) { 2575 name = node->Key()->AsStringLiteral()->Str(); 2576 } else if (node->Key()->IsTemplateLiteral()) { 2577 // Because enum does not support Tagged template literal, Quasis can only have one element 2578 name = node->Key()->AsTemplateLiteral()->Quasis().front()->Cooked(); 2579 } 2580 return name; 2581} 2582 2583binder::Scope *Transformer::FindEnumMemberScope(const util::StringView name) const 2584{ 2585 // Transform is required only if ident is an enumMember. 2586 auto scope = Scope(); 2587 while (scope != nullptr) { 2588 if (scope->InLocalTSBindings(name)) { 2589 return nullptr; 2590 } 2591 if (scope->IsTSModuleScope() && scope->AsTSModuleScope()->InExportBindings(name)) { 2592 return nullptr; 2593 } 2594 if (scope->IsTSEnumScope() && scope->AsTSEnumScope()->FindEnumMemberVariable(name)) { 2595 return scope; 2596 } 2597 if (scope->FindLocal(name)) { 2598 return nullptr; 2599 } 2600 2601 if (scope->IsTSModuleScope() || scope->IsTSEnumScope()) { 2602 scope = scope->Parent(); 2603 } 2604 scope = scope->Parent(); 2605 } 2606 2607 return nullptr; 2608} 2609 2610ir::MemberExpression *Transformer::CreateMemberExpressionFromIdentifier(binder::Scope *scope, ir::Identifier *node) 2611{ 2612 auto identName = node->Name(); 2613 auto moduleName = scope->IsTSEnumScope() ? FindTSEnumNameByScope(scope) : FindTSModuleNameByScope(scope); 2614 auto *id = CreateReferenceIdentifier(moduleName); 2615 auto *res = AllocNode<ir::MemberExpression>(id, AllocNode<ir::Identifier>(identName), 2616 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, 2617 false, false); 2618 SetOriginalNode(res, node); 2619 return res; 2620} 2621 2622void Transformer::CheckTransformedAstStructure(const Program *program) const 2623{ 2624 bool passed = true; 2625 CheckTransformedAstNodes(program->Ast(), &passed); 2626 if (passed) { 2627 std::cout << "Transformed AST structure check passed." << std::endl; 2628 } 2629} 2630 2631void Transformer::CheckTransformedAstNodes(const ir::AstNode *parent, bool *passed) const 2632{ 2633 parent->Iterate([this, parent, passed](auto *childNode) { CheckTransformedAstNode(parent, childNode, passed); }); 2634} 2635 2636void Transformer::CheckTransformedAstNode(const ir::AstNode *parent, ir::AstNode *childNode, bool *passed) const 2637{ 2638 if (!(*passed)) { 2639 return; 2640 } 2641 if (childNode->IsClassProperty() && 2642 (childNode->AsClassProperty()->IsStatic() || childNode->AsClassProperty()->Value() != nullptr)) { 2643 return; 2644 } 2645 if (childNode->IsMethodDefinition() && 2646 childNode->AsMethodDefinition()->Kind() == ir::MethodDefinitionKind::CONSTRUCTOR) { 2647 return; 2648 } 2649 if (childNode->IsDecorator()) { 2650 return; 2651 } 2652 if (childNode->Parent() != parent) { 2653 std::cout << "Illegal ast structure after transform." << std::endl; 2654 *passed = false; 2655 return; 2656 } 2657 CheckTransformedAstNodes(childNode, passed); 2658} 2659 2660void Transformer::ResetParentScopeForAstNodes(const ir::AstNode *parent, binder::Scope *parentScope) const 2661{ 2662 parent->Iterate([this, parentScope](auto *childNode) { ResetParentScopeForAstNode(childNode, parentScope); }); 2663} 2664 2665void Transformer::ResetParentScopeForAstNode(ir::AstNode *childNode, binder::Scope *parentScope) const 2666{ 2667 switch (childNode->Type()) { 2668 case ir::AstNodeType::SCRIPT_FUNCTION: { 2669 auto scope = childNode->AsScriptFunction()->Scope(); 2670 ASSERT(scope != nullptr); 2671 scope->SetParent(parentScope); 2672 break; 2673 } 2674 case ir::AstNodeType::CATCH_CLAUSE: { 2675 auto scope = childNode->AsCatchClause()->Scope(); 2676 ASSERT(scope != nullptr); 2677 scope->SetParent(parentScope); 2678 break; 2679 } 2680 case ir::AstNodeType::CLASS_DEFINITION: { 2681 auto scope = childNode->AsClassDefinition()->Scope(); 2682 ASSERT(scope != nullptr); 2683 scope->SetParent(parentScope); 2684 break; 2685 } 2686 case ir::AstNodeType::BLOCK_STATEMENT: { 2687 auto scope = childNode->AsBlockStatement()->Scope(); 2688 ASSERT(scope != nullptr); 2689 scope->SetParent(parentScope); 2690 break; 2691 } 2692 case ir::AstNodeType::DO_WHILE_STATEMENT: { 2693 auto scope = childNode->AsDoWhileStatement()->Scope(); 2694 ASSERT(scope != nullptr); 2695 scope->SetParent(parentScope); 2696 break; 2697 } 2698 case ir::AstNodeType::WHILE_STATEMENT: { 2699 auto scope = childNode->AsWhileStatement()->Scope(); 2700 ASSERT(scope != nullptr); 2701 scope->SetParent(parentScope); 2702 break; 2703 } 2704 case ir::AstNodeType::FOR_IN_STATEMENT: { 2705 auto scope = childNode->AsForInStatement()->Scope(); 2706 ASSERT(scope != nullptr); 2707 scope->SetParent(parentScope); 2708 break; 2709 } 2710 case ir::AstNodeType::FOR_OF_STATEMENT: { 2711 auto scope = childNode->AsForOfStatement()->Scope(); 2712 ASSERT(scope != nullptr); 2713 scope->SetParent(parentScope); 2714 break; 2715 } 2716 case ir::AstNodeType::FOR_UPDATE_STATEMENT: { 2717 auto scope = childNode->AsForUpdateStatement()->Scope(); 2718 ASSERT(scope != nullptr); 2719 scope->SetParent(parentScope); 2720 break; 2721 } 2722 case ir::AstNodeType::SWITCH_STATEMENT: { 2723 auto scope = childNode->AsSwitchStatement()->Scope(); 2724 ASSERT(scope != nullptr); 2725 scope->SetParent(parentScope); 2726 break; 2727 } 2728 case ir::AstNodeType::TS_ENUM_DECLARATION: { 2729 auto scope = childNode->AsTSEnumDeclaration()->Scope(); 2730 ASSERT(scope != nullptr); 2731 scope->SetParent(parentScope); 2732 break; 2733 } 2734 case ir::AstNodeType::TS_INTERFACE_DECLARATION: { 2735 auto scope = childNode->AsTSInterfaceDeclaration()->Scope(); 2736 ASSERT(scope != nullptr); 2737 scope->SetParent(parentScope); 2738 break; 2739 } 2740 case ir::AstNodeType::TS_METHOD_SIGNATURE: { 2741 auto scope = childNode->AsTSMethodSignature()->Scope(); 2742 ASSERT(scope != nullptr); 2743 scope->SetParent(parentScope); 2744 break; 2745 } 2746 case ir::AstNodeType::TS_MODULE_DECLARATION: { 2747 auto scope = childNode->AsTSModuleDeclaration()->Scope(); 2748 ASSERT(scope != nullptr); 2749 scope->SetParent(parentScope); 2750 break; 2751 } 2752 case ir::AstNodeType::TS_SIGNATURE_DECLARATION: { 2753 auto scope = childNode->AsTSSignatureDeclaration()->Scope(); 2754 ASSERT(scope != nullptr); 2755 scope->SetParent(parentScope); 2756 break; 2757 } 2758 case ir::AstNodeType::TS_TYPE_PARAMETER_DECLARATION: { 2759 auto scope = childNode->AsTSTypeParameterDeclaration()->Scope(); 2760 ASSERT(scope != nullptr); 2761 scope->SetParent(parentScope); 2762 break; 2763 } 2764 case ir::AstNodeType::TS_CONSTRUCTOR_TYPE: { 2765 auto scope = childNode->AsTSConstructorType()->Scope(); 2766 ASSERT(scope != nullptr); 2767 scope->SetParent(parentScope); 2768 break; 2769 } 2770 case ir::AstNodeType::TS_FUNCTION_TYPE: { 2771 auto scope = childNode->AsTSFunctionType()->Scope(); 2772 ASSERT(scope != nullptr); 2773 scope->SetParent(parentScope); 2774 break; 2775 } 2776 default: { 2777 ResetParentScopeForAstNodes(childNode, parentScope); 2778 break; 2779 } 2780 } 2781} 2782 2783bool Transformer::IsValueReference(ir::Identifier *node) 2784{ 2785 auto scope = Scope(); 2786 ASSERT(scope != nullptr); 2787 auto name = node->Name(); 2788 // If it's js value or enum, it won't be a type. 2789 // Const enum was processed as enum in es2abc, so we don't process it as type here. 2790 if (scope->FindLocal(name, binder::ResolveBindingOptions::BINDINGS) != nullptr || 2791 scope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(name) != nullptr) { 2792 return true; 2793 } 2794 2795 binder::Variable *var = nullptr; 2796 2797 var = scope->FindLocalTSVariable<binder::TSBindingType::NAMESPACE>(name); 2798 if (var != nullptr) { 2799 auto *decl = var->Declaration()->AsNamespaceDecl(); 2800 return decl->IsInstantiated(); 2801 } 2802 2803 var = scope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name); 2804 if (var != nullptr) { 2805 auto *node = var->Declaration()->Node()->AsTSImportEqualsDeclaration(); 2806 return IsInstantiatedImportEquals(node, scope); 2807 } 2808 2809 return false; 2810} 2811 2812void Transformer::RemoveDefaultLocalExportEntry() 2813{ 2814 auto *moduleRecord = GetSourceTextModuleRecord(); 2815 moduleRecord->RemoveDefaultLocalExportEntry(); 2816} 2817 2818} // namespace panda::es2panda::parser 2819