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 *> &params,
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 &param : 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