13af6ab5fSopenharmony_ci/**
23af6ab5fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#include "binder.h"
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ci#include "binder/scope.h"
193af6ab5fSopenharmony_ci#include "binder/tsBinding.h"
203af6ab5fSopenharmony_ci#include "es2panda.h"
213af6ab5fSopenharmony_ci#include "ir/astNode.h"
223af6ab5fSopenharmony_ci#include "ir/base/annotation.h"
233af6ab5fSopenharmony_ci#include "ir/base/catchClause.h"
243af6ab5fSopenharmony_ci#include "ir/base/classDefinition.h"
253af6ab5fSopenharmony_ci#include "ir/base/classProperty.h"
263af6ab5fSopenharmony_ci#include "ir/base/methodDefinition.h"
273af6ab5fSopenharmony_ci#include "ir/base/property.h"
283af6ab5fSopenharmony_ci#include "ir/base/scriptFunction.h"
293af6ab5fSopenharmony_ci#include "ir/base/spreadElement.h"
303af6ab5fSopenharmony_ci#include "ir/expressions/arrayExpression.h"
313af6ab5fSopenharmony_ci#include "ir/expressions/assignmentExpression.h"
323af6ab5fSopenharmony_ci#include "ir/expressions/callExpression.h"
333af6ab5fSopenharmony_ci#include "ir/expressions/identifier.h"
343af6ab5fSopenharmony_ci#include "ir/expressions/objectExpression.h"
353af6ab5fSopenharmony_ci#include "ir/expressions/privateIdentifier.h"
363af6ab5fSopenharmony_ci#include "ir/expressions/literals/numberLiteral.h"
373af6ab5fSopenharmony_ci#include "ir/module/exportNamedDeclaration.h"
383af6ab5fSopenharmony_ci#include "ir/module/exportSpecifier.h"
393af6ab5fSopenharmony_ci#include "ir/statements/blockStatement.h"
403af6ab5fSopenharmony_ci#include "ir/statements/classDeclaration.h"
413af6ab5fSopenharmony_ci#include "ir/statements/doWhileStatement.h"
423af6ab5fSopenharmony_ci#include "ir/statements/forInStatement.h"
433af6ab5fSopenharmony_ci#include "ir/statements/forOfStatement.h"
443af6ab5fSopenharmony_ci#include "ir/statements/forUpdateStatement.h"
453af6ab5fSopenharmony_ci#include "ir/statements/ifStatement.h"
463af6ab5fSopenharmony_ci#include "ir/statements/switchCaseStatement.h"
473af6ab5fSopenharmony_ci#include "ir/statements/switchStatement.h"
483af6ab5fSopenharmony_ci#include "ir/statements/variableDeclaration.h"
493af6ab5fSopenharmony_ci#include "ir/statements/variableDeclarator.h"
503af6ab5fSopenharmony_ci#include "ir/statements/whileStatement.h"
513af6ab5fSopenharmony_ci#include "ir/ts/tsClassImplements.h"
523af6ab5fSopenharmony_ci#include "ir/ts/tsConstructorType.h"
533af6ab5fSopenharmony_ci#include "ir/ts/tsEnumDeclaration.h"
543af6ab5fSopenharmony_ci#include "ir/ts/tsFunctionType.h"
553af6ab5fSopenharmony_ci#include "ir/ts/tsIndexSignature.h"
563af6ab5fSopenharmony_ci#include "ir/ts/tsMethodSignature.h"
573af6ab5fSopenharmony_ci#include "ir/ts/tsModuleBlock.h"
583af6ab5fSopenharmony_ci#include "ir/ts/tsModuleDeclaration.h"
593af6ab5fSopenharmony_ci#include "ir/ts/tsSignatureDeclaration.h"
603af6ab5fSopenharmony_ci#include "ir/ts/tsTypeParameterDeclaration.h"
613af6ab5fSopenharmony_ci#include "ir/ts/tsTypeParameterInstantiation.h"
623af6ab5fSopenharmony_ci#include "util/concurrent.h"
633af6ab5fSopenharmony_ci#include "util/patchFix.h"
643af6ab5fSopenharmony_ci
653af6ab5fSopenharmony_cinamespace panda::es2panda::binder {
663af6ab5fSopenharmony_civoid Binder::InitTopScope()
673af6ab5fSopenharmony_ci{
683af6ab5fSopenharmony_ci    if (program_->Kind() == parser::ScriptKind::MODULE) {
693af6ab5fSopenharmony_ci        topScope_ = Allocator()->New<ModuleScope>(Allocator(), program_);
703af6ab5fSopenharmony_ci    } else {
713af6ab5fSopenharmony_ci        topScope_ = Allocator()->New<GlobalScope>(Allocator());
723af6ab5fSopenharmony_ci    }
733af6ab5fSopenharmony_ci
743af6ab5fSopenharmony_ci    scope_ = topScope_;
753af6ab5fSopenharmony_ci}
763af6ab5fSopenharmony_ci
773af6ab5fSopenharmony_ciParameterDecl *Binder::AddParamDecl(const ir::AstNode *param)
783af6ab5fSopenharmony_ci{
793af6ab5fSopenharmony_ci    ASSERT(scope_->IsFunctionParamScope() || scope_->IsCatchParamScope());
803af6ab5fSopenharmony_ci    auto [decl, node] = static_cast<ParamScope *>(scope_)->AddParamDecl(Allocator(), param);
813af6ab5fSopenharmony_ci
823af6ab5fSopenharmony_ci    if (!node) {
833af6ab5fSopenharmony_ci        return decl;
843af6ab5fSopenharmony_ci    }
853af6ab5fSopenharmony_ci
863af6ab5fSopenharmony_ci    ThrowRedeclaration(node->Start(), decl->Name());
873af6ab5fSopenharmony_ci}
883af6ab5fSopenharmony_ci
893af6ab5fSopenharmony_civoid Binder::ThrowRedeclaration(const lexer::SourcePosition &pos, const util::StringView &name)
903af6ab5fSopenharmony_ci{
913af6ab5fSopenharmony_ci    lexer::LineIndex index(program_->SourceCode());
923af6ab5fSopenharmony_ci    lexer::SourceLocation loc = index.GetLocation(pos);
933af6ab5fSopenharmony_ci
943af6ab5fSopenharmony_ci    std::stringstream ss;
953af6ab5fSopenharmony_ci    ss << "Variable '" << name << "' has already been declared.";
963af6ab5fSopenharmony_ci    throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col);
973af6ab5fSopenharmony_ci}
983af6ab5fSopenharmony_ci
993af6ab5fSopenharmony_civoid Binder::ThrowUndeclaredExport(const lexer::SourcePosition &pos, const util::StringView &name)
1003af6ab5fSopenharmony_ci{
1013af6ab5fSopenharmony_ci    lexer::LineIndex index(program_->SourceCode());
1023af6ab5fSopenharmony_ci    lexer::SourceLocation loc = index.GetLocation(pos);
1033af6ab5fSopenharmony_ci
1043af6ab5fSopenharmony_ci    std::stringstream ss;
1053af6ab5fSopenharmony_ci    ss << "Export name '" << name << "' is not defined.";
1063af6ab5fSopenharmony_ci    throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col);
1073af6ab5fSopenharmony_ci}
1083af6ab5fSopenharmony_ci
1093af6ab5fSopenharmony_civoid Binder::ThrowInvalidDstrTarget(const lexer::SourcePosition &pos, const util::StringView &name)
1103af6ab5fSopenharmony_ci{
1113af6ab5fSopenharmony_ci    lexer::LineIndex index(program_->SourceCode());
1123af6ab5fSopenharmony_ci    lexer::SourceLocation loc = index.GetLocation(pos);
1133af6ab5fSopenharmony_ci
1143af6ab5fSopenharmony_ci    std::stringstream ss;
1153af6ab5fSopenharmony_ci    ss << "Invalid destructuring assignment target: " << name;
1163af6ab5fSopenharmony_ci    throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col);
1173af6ab5fSopenharmony_ci}
1183af6ab5fSopenharmony_ci
1193af6ab5fSopenharmony_civoid Binder::ThrowInvalidAnnotationDeclaration(const lexer::SourcePosition &pos, const util::StringView &name)
1203af6ab5fSopenharmony_ci{
1213af6ab5fSopenharmony_ci    lexer::LineIndex index(program_->SourceCode());
1223af6ab5fSopenharmony_ci    lexer::SourceLocation loc = index.GetLocation(pos);
1233af6ab5fSopenharmony_ci
1243af6ab5fSopenharmony_ci    std::stringstream ss;
1253af6ab5fSopenharmony_ci    ss << "Invalid annotation declaration: " << name;
1263af6ab5fSopenharmony_ci    throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col);
1273af6ab5fSopenharmony_ci}
1283af6ab5fSopenharmony_ci
1293af6ab5fSopenharmony_civoid Binder::CheckMandatoryArguments(const ir::Identifier *ident)
1303af6ab5fSopenharmony_ci{
1313af6ab5fSopenharmony_ci    const auto *iter = static_cast<const ir::AstNode *>(ident);
1323af6ab5fSopenharmony_ci    bool isPatternMember = false;
1333af6ab5fSopenharmony_ci    while (iter) {
1343af6ab5fSopenharmony_ci        if (iter->IsArrayExpression() || iter->IsArrayPattern()) {
1353af6ab5fSopenharmony_ci            isPatternMember = true;
1363af6ab5fSopenharmony_ci            break;
1373af6ab5fSopenharmony_ci        }
1383af6ab5fSopenharmony_ci
1393af6ab5fSopenharmony_ci        if (iter->IsObjectExpression() || iter->IsObjectPattern()) {
1403af6ab5fSopenharmony_ci            auto &properties = iter->IsObjectExpression() ? iter->AsObjectExpression()->Properties() :
1413af6ab5fSopenharmony_ci                                                            iter->AsObjectPattern()->Properties();
1423af6ab5fSopenharmony_ci            isPatternMember = util::Helpers::IsObjectPropertyValue(properties, ident);
1433af6ab5fSopenharmony_ci            break;
1443af6ab5fSopenharmony_ci        }
1453af6ab5fSopenharmony_ci        iter = iter->Parent();
1463af6ab5fSopenharmony_ci    }
1473af6ab5fSopenharmony_ci
1483af6ab5fSopenharmony_ci    if (!isPatternMember) {
1493af6ab5fSopenharmony_ci        return;
1503af6ab5fSopenharmony_ci    }
1513af6ab5fSopenharmony_ci
1523af6ab5fSopenharmony_ci    auto *patternNode = iter;
1533af6ab5fSopenharmony_ci
1543af6ab5fSopenharmony_ci    while (iter) {
1553af6ab5fSopenharmony_ci        if (iter->IsAssignmentExpression() || iter->IsVariableDeclarator() || iter->IsForInStatement() ||
1563af6ab5fSopenharmony_ci            iter->IsForOfStatement()) {
1573af6ab5fSopenharmony_ci            break;
1583af6ab5fSopenharmony_ci        }
1593af6ab5fSopenharmony_ci
1603af6ab5fSopenharmony_ci        iter = iter->Parent();
1613af6ab5fSopenharmony_ci    }
1623af6ab5fSopenharmony_ci
1633af6ab5fSopenharmony_ci    if (!iter) {
1643af6ab5fSopenharmony_ci        return;
1653af6ab5fSopenharmony_ci    }
1663af6ab5fSopenharmony_ci
1673af6ab5fSopenharmony_ci    const ir::AstNode *potentialParent = iter;
1683af6ab5fSopenharmony_ci
1693af6ab5fSopenharmony_ci    if (iter->IsAssignmentExpression()) {
1703af6ab5fSopenharmony_ci        potentialParent = iter->AsAssignmentExpression()->Left();
1713af6ab5fSopenharmony_ci    } else if (iter->IsVariableDeclarator()) {
1723af6ab5fSopenharmony_ci        potentialParent = iter->AsVariableDeclarator()->Id();
1733af6ab5fSopenharmony_ci    } else {
1743af6ab5fSopenharmony_ci        potentialParent = iter->IsForInStatement() ? iter->AsForInStatement()->Left() :
1753af6ab5fSopenharmony_ci                                                     iter->AsForOfStatement()->Left();
1763af6ab5fSopenharmony_ci    }
1773af6ab5fSopenharmony_ci
1783af6ab5fSopenharmony_ci    if (!util::Helpers::IsChild(potentialParent, patternNode)) {
1793af6ab5fSopenharmony_ci        return;
1803af6ab5fSopenharmony_ci    }
1813af6ab5fSopenharmony_ci
1823af6ab5fSopenharmony_ci    ThrowInvalidDstrTarget(ident->Start(), ident->Name());
1833af6ab5fSopenharmony_ci}
1843af6ab5fSopenharmony_ci
1853af6ab5fSopenharmony_civoid Binder::AssignIndexToModuleVariable()
1863af6ab5fSopenharmony_ci{
1873af6ab5fSopenharmony_ci    ASSERT(program_->ModuleRecord());
1883af6ab5fSopenharmony_ci    program_->ModuleRecord()->AssignIndexToModuleVariable(topScope_->AsModuleScope());
1893af6ab5fSopenharmony_ci}
1903af6ab5fSopenharmony_ci
1913af6ab5fSopenharmony_civoid Binder::IdentifierAnalysis(ResolveBindingFlags flags)
1923af6ab5fSopenharmony_ci{
1933af6ab5fSopenharmony_ci    ASSERT(program_->Ast());
1943af6ab5fSopenharmony_ci    ASSERT(scope_ == topScope_);
1953af6ab5fSopenharmony_ci
1963af6ab5fSopenharmony_ci    bindingFlags_ = flags;
1973af6ab5fSopenharmony_ci    // Bind function main0 first to determine whether a lexical variable is in it or not under hot-reload mode
1983af6ab5fSopenharmony_ci    if (bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM) {
1993af6ab5fSopenharmony_ci        BuildFunction(topScope_, MAIN_FUNC_NAME);
2003af6ab5fSopenharmony_ci        ResolveReferences(program_->Ast());
2013af6ab5fSopenharmony_ci    } else if (bindingFlags_ & ResolveBindingFlags::TS_AFTER_TRANSFORM) {
2023af6ab5fSopenharmony_ci        // Basically same as js, except of function main0 will not be bound after transform
2033af6ab5fSopenharmony_ci        ResolveReferences(program_->Ast());
2043af6ab5fSopenharmony_ci        AddMandatoryParams();
2053af6ab5fSopenharmony_ci        if (topScope_->IsModuleScope()) {
2063af6ab5fSopenharmony_ci            AssignIndexToModuleVariable();
2073af6ab5fSopenharmony_ci        }
2083af6ab5fSopenharmony_ci    } else if (bindingFlags_ & ResolveBindingFlags::ALL) {
2093af6ab5fSopenharmony_ci        BuildFunction(topScope_, MAIN_FUNC_NAME);
2103af6ab5fSopenharmony_ci        ResolveReferences(program_->Ast());
2113af6ab5fSopenharmony_ci        AddMandatoryParams();
2123af6ab5fSopenharmony_ci        if (topScope_->IsModuleScope()) {
2133af6ab5fSopenharmony_ci            AssignIndexToModuleVariable();
2143af6ab5fSopenharmony_ci        }
2153af6ab5fSopenharmony_ci    }
2163af6ab5fSopenharmony_ci}
2173af6ab5fSopenharmony_ci
2183af6ab5fSopenharmony_civoid Binder::ValidateExportDecl(const ir::ExportNamedDeclaration *exportDecl)
2193af6ab5fSopenharmony_ci{
2203af6ab5fSopenharmony_ci    if (exportDecl->Source() != nullptr || exportDecl->Decl() != nullptr || exportDecl->IsType()) {
2213af6ab5fSopenharmony_ci        return;
2223af6ab5fSopenharmony_ci    }
2233af6ab5fSopenharmony_ci
2243af6ab5fSopenharmony_ci    ASSERT(topScope_->IsModuleScope());
2253af6ab5fSopenharmony_ci    for (auto *it : exportDecl->Specifiers()) {
2263af6ab5fSopenharmony_ci        if (it->AsExportSpecifier()->IsType()) {
2273af6ab5fSopenharmony_ci            continue;
2283af6ab5fSopenharmony_ci        }
2293af6ab5fSopenharmony_ci
2303af6ab5fSopenharmony_ci        auto localName = it->AsExportSpecifier()->Local()->Name();
2313af6ab5fSopenharmony_ci        if (scope_->IsTSModuleScope()) {
2323af6ab5fSopenharmony_ci            auto currentScope = scope_;
2333af6ab5fSopenharmony_ci            while (currentScope != nullptr) {
2343af6ab5fSopenharmony_ci                if (currentScope->FindLocal(localName, ResolveBindingOptions::ALL) != nullptr ||
2353af6ab5fSopenharmony_ci                    (currentScope->IsTSModuleScope() && (currentScope->InLocalTSBindings(localName) ||
2363af6ab5fSopenharmony_ci                    currentScope->AsTSModuleScope()->InExportBindings(localName)))) {
2373af6ab5fSopenharmony_ci                    break;
2383af6ab5fSopenharmony_ci                }
2393af6ab5fSopenharmony_ci                currentScope = currentScope->Parent();
2403af6ab5fSopenharmony_ci            }
2413af6ab5fSopenharmony_ci            if (currentScope != nullptr) {
2423af6ab5fSopenharmony_ci                continue;
2433af6ab5fSopenharmony_ci            }
2443af6ab5fSopenharmony_ci            ThrowUndeclaredExport(it->AsExportSpecifier()->Local()->Start(), localName);
2453af6ab5fSopenharmony_ci        }
2463af6ab5fSopenharmony_ci        ASSERT(topScope_ == scope_);
2473af6ab5fSopenharmony_ci        if (scope_->FindLocal(localName) == nullptr) {
2483af6ab5fSopenharmony_ci            // The declaration of ts cannot correspond to the variables of ts before transform,
2493af6ab5fSopenharmony_ci            // After the transform, they are all js variables. So it can return directly here.
2503af6ab5fSopenharmony_ci            if (scope_->InLocalTSBindings(localName) ||
2513af6ab5fSopenharmony_ci                scope_->FindLocal(localName, ResolveBindingOptions::INTERFACES)) {
2523af6ab5fSopenharmony_ci                continue;
2533af6ab5fSopenharmony_ci            }
2543af6ab5fSopenharmony_ci            ThrowUndeclaredExport(it->AsExportSpecifier()->Local()->Start(), localName);
2553af6ab5fSopenharmony_ci        }
2563af6ab5fSopenharmony_ci        scope_->AsModuleScope()->ConvertLocalVariableToModuleVariable(Allocator(), localName);
2573af6ab5fSopenharmony_ci    }
2583af6ab5fSopenharmony_ci}
2593af6ab5fSopenharmony_ci
2603af6ab5fSopenharmony_civoid Binder::LookupReference(const util::StringView &name)
2613af6ab5fSopenharmony_ci{
2623af6ab5fSopenharmony_ci    ScopeFindResult res = scope_->Find(name);
2633af6ab5fSopenharmony_ci    if (res.level == 0) {
2643af6ab5fSopenharmony_ci        return;
2653af6ab5fSopenharmony_ci    }
2663af6ab5fSopenharmony_ci
2673af6ab5fSopenharmony_ci    ASSERT(res.variable);
2683af6ab5fSopenharmony_ci    res.variable->SetLexical(res.scope, program_->PatchFixHelper());
2693af6ab5fSopenharmony_ci}
2703af6ab5fSopenharmony_ci
2713af6ab5fSopenharmony_civoid Binder::InstantiateArguments()
2723af6ab5fSopenharmony_ci{
2733af6ab5fSopenharmony_ci    auto *iter = scope_;
2743af6ab5fSopenharmony_ci    while (true) {
2753af6ab5fSopenharmony_ci        Scope *scope = iter->IsFunctionParamScope() ? iter : iter->EnclosingVariableScope();
2763af6ab5fSopenharmony_ci        CHECK_NOT_NULL(scope);
2773af6ab5fSopenharmony_ci
2783af6ab5fSopenharmony_ci        const auto *node = scope->Node();
2793af6ab5fSopenharmony_ci
2803af6ab5fSopenharmony_ci        if (scope->IsLoopScope()) {
2813af6ab5fSopenharmony_ci            iter = scope->Parent();
2823af6ab5fSopenharmony_ci            continue;
2833af6ab5fSopenharmony_ci        }
2843af6ab5fSopenharmony_ci
2853af6ab5fSopenharmony_ci        if (!node->IsScriptFunction()) {
2863af6ab5fSopenharmony_ci            break;
2873af6ab5fSopenharmony_ci        }
2883af6ab5fSopenharmony_ci
2893af6ab5fSopenharmony_ci        if (!node->AsScriptFunction()->IsArrow()) {
2903af6ab5fSopenharmony_ci            auto *argumentsVariable =
2913af6ab5fSopenharmony_ci                scope->AddDecl<ConstDecl, LocalVariable>(Allocator(), FUNCTION_ARGUMENTS, VariableFlags::INITIALIZED);
2923af6ab5fSopenharmony_ci
2933af6ab5fSopenharmony_ci            if (iter->IsFunctionParamScope()) {
2943af6ab5fSopenharmony_ci                if (!argumentsVariable) {
2953af6ab5fSopenharmony_ci                    break;
2963af6ab5fSopenharmony_ci                }
2973af6ab5fSopenharmony_ci
2983af6ab5fSopenharmony_ci                scope = iter->AsFunctionParamScope()->GetFunctionScope();
2993af6ab5fSopenharmony_ci                scope->Bindings().insert({argumentsVariable->Name(), argumentsVariable});
3003af6ab5fSopenharmony_ci            }
3013af6ab5fSopenharmony_ci
3023af6ab5fSopenharmony_ci            scope->AsVariableScope()->AddFlag(VariableScopeFlags::USE_ARGS);
3033af6ab5fSopenharmony_ci
3043af6ab5fSopenharmony_ci            break;
3053af6ab5fSopenharmony_ci        }
3063af6ab5fSopenharmony_ci
3073af6ab5fSopenharmony_ci        iter = scope->Parent();
3083af6ab5fSopenharmony_ci    }
3093af6ab5fSopenharmony_ci}
3103af6ab5fSopenharmony_ci
3113af6ab5fSopenharmony_civoid Binder::LookupIdentReference(ir::Identifier *ident)
3123af6ab5fSopenharmony_ci{
3133af6ab5fSopenharmony_ci    if (ident->Name().Is(FUNCTION_ARGUMENTS)) {
3143af6ab5fSopenharmony_ci        InstantiateArguments();
3153af6ab5fSopenharmony_ci    }
3163af6ab5fSopenharmony_ci
3173af6ab5fSopenharmony_ci    ScopeFindResult res;
3183af6ab5fSopenharmony_ci    if (bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM) {
3193af6ab5fSopenharmony_ci        ident->SetTSVariables(FindIdentifierTSVariables(ident, scope_, res));
3203af6ab5fSopenharmony_ci    } else {
3213af6ab5fSopenharmony_ci        if (ident->Parent()->IsTSTypeReference()) {
3223af6ab5fSopenharmony_ci            res = scope_->Find(ident->Name(), ResolveBindingOptions::ALL);
3233af6ab5fSopenharmony_ci        } else {
3243af6ab5fSopenharmony_ci            res = scope_->Find(ident->Name(), ResolveBindingOptions::BINDINGS);
3253af6ab5fSopenharmony_ci        }
3263af6ab5fSopenharmony_ci    }
3273af6ab5fSopenharmony_ci
3283af6ab5fSopenharmony_ci    if (res.variable == nullptr) {
3293af6ab5fSopenharmony_ci        return;
3303af6ab5fSopenharmony_ci    }
3313af6ab5fSopenharmony_ci
3323af6ab5fSopenharmony_ci    if (res.level != 0) {
3333af6ab5fSopenharmony_ci        if (!res.variable->Declaration()->IsDeclare() && !ident->Parent()->IsTSTypeReference() &&
3343af6ab5fSopenharmony_ci            !ident->Parent()->IsTSTypeQuery() && !(bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM)) {
3353af6ab5fSopenharmony_ci            util::Concurrent::ProcessConcurrent(Program()->GetLineIndex(), ident, res, program_);
3363af6ab5fSopenharmony_ci            res.variable->SetLexical(res.scope, program_->PatchFixHelper());
3373af6ab5fSopenharmony_ci        }
3383af6ab5fSopenharmony_ci    }
3393af6ab5fSopenharmony_ci
3403af6ab5fSopenharmony_ci    auto decl = res.variable->Declaration();
3413af6ab5fSopenharmony_ci    if (decl->IsLetOrConstOrClassDecl() && !decl->HasFlag(DeclarationFlags::NAMESPACE_IMPORT) &&
3423af6ab5fSopenharmony_ci        !res.variable->HasFlag(VariableFlags::INITIALIZED)) {
3433af6ab5fSopenharmony_ci        ident->SetTdz();
3443af6ab5fSopenharmony_ci    }
3453af6ab5fSopenharmony_ci    // in release mode, replace const reference with its initialization
3463af6ab5fSopenharmony_ci    if (!this->Program()->IsDebug() && decl->IsConstDecl()) {
3473af6ab5fSopenharmony_ci        ReplaceConstReferenceWithInitialization(ident, decl);
3483af6ab5fSopenharmony_ci    }
3493af6ab5fSopenharmony_ci
3503af6ab5fSopenharmony_ci    ident->SetVariable(res.variable);
3513af6ab5fSopenharmony_ci}
3523af6ab5fSopenharmony_ci
3533af6ab5fSopenharmony_civoid Binder::StoreAndCheckSpecialFunctionName(std::string &internalNameStr, std::string recordName)
3543af6ab5fSopenharmony_ci{
3553af6ab5fSopenharmony_ci    if (program_->PatchFixHelper()) {
3563af6ab5fSopenharmony_ci        if (program_->PatchFixHelper()->IsDumpSymbolTable()) {
3573af6ab5fSopenharmony_ci            // anonymous, special-name and duplicate function index started from 1
3583af6ab5fSopenharmony_ci            specialFuncNameIndexMap_.insert({internalNameStr, std::to_string(++globalIndexForSpecialFunc_)});
3593af6ab5fSopenharmony_ci            return;
3603af6ab5fSopenharmony_ci        }
3613af6ab5fSopenharmony_ci        if (program_->PatchFixHelper()->IsHotFix()) {
3623af6ab5fSopenharmony_ci            // Adding/removing anonymous, special or duplicate functions is supported for hotReload and coldFix mode,
3633af6ab5fSopenharmony_ci            // but forbidden in hotFix mode
3643af6ab5fSopenharmony_ci            program_->PatchFixHelper()->CheckAndRestoreSpecialFunctionName(++globalIndexForSpecialFunc_,
3653af6ab5fSopenharmony_ci                internalNameStr, recordName);
3663af6ab5fSopenharmony_ci            return;
3673af6ab5fSopenharmony_ci        }
3683af6ab5fSopenharmony_ci        // else: must be coldfix or hotreload mode or coldreload mode
3693af6ab5fSopenharmony_ci        ASSERT(program_->PatchFixHelper()->IsColdFix() || program_->PatchFixHelper()->IsHotReload() ||
3703af6ab5fSopenharmony_ci               program_->PatchFixHelper()->IsColdReload());
3713af6ab5fSopenharmony_ci    }
3723af6ab5fSopenharmony_ci}
3733af6ab5fSopenharmony_ci
3743af6ab5fSopenharmony_civoid Binder::BuildFunction(FunctionScope *funcScope, util::StringView name, const ir::ScriptFunction *func)
3753af6ab5fSopenharmony_ci{
3763af6ab5fSopenharmony_ci    if (funcScope->InFunctionScopes()) {
3773af6ab5fSopenharmony_ci        return;
3783af6ab5fSopenharmony_ci    }
3793af6ab5fSopenharmony_ci    functionScopes_.push_back(funcScope);
3803af6ab5fSopenharmony_ci    funcScope->SetInFunctionScopes();
3813af6ab5fSopenharmony_ci    if (!util::Helpers::IsDefaultApiVersion(Program()->TargetApiVersion(), Program()->GetTargetApiSubVersion())) {
3823af6ab5fSopenharmony_ci        funcScope->SetSelfScopeName(name);
3833af6ab5fSopenharmony_ci        auto recordName = program_->FormatedRecordName().Mutf8();
3843af6ab5fSopenharmony_ci        funcScope->BindNameWithScopeInfo(name, util::UString(recordName, Allocator()).View());
3853af6ab5fSopenharmony_ci        if (func && (name == ANONYMOUS_FUNC_NAME)) {
3863af6ab5fSopenharmony_ci            anonymousFunctionNames_[func] = util::UString(funcScope->InternalName().Mutf8(), Allocator()).View();
3873af6ab5fSopenharmony_ci        }
3883af6ab5fSopenharmony_ci    } else {
3893af6ab5fSopenharmony_ci        LegacyBuildFunction(funcScope, name, func);
3903af6ab5fSopenharmony_ci    }
3913af6ab5fSopenharmony_ci}
3923af6ab5fSopenharmony_ci
3933af6ab5fSopenharmony_civoid Binder::LegacyBuildFunction(FunctionScope *funcScope, util::StringView name, const ir::ScriptFunction *func)
3943af6ab5fSopenharmony_ci{
3953af6ab5fSopenharmony_ci    bool funcNameWithoutDot = (name.Find(".") == std::string::npos);
3963af6ab5fSopenharmony_ci    bool funcNameWithoutBackslash = (name.Find("\\") == std::string::npos);
3973af6ab5fSopenharmony_ci    if (name != ANONYMOUS_FUNC_NAME && funcNameWithoutDot &&
3983af6ab5fSopenharmony_ci        funcNameWithoutBackslash && !functionNames_.count(name)) {
3993af6ab5fSopenharmony_ci        // function with normal name, and hasn't been recorded
4003af6ab5fSopenharmony_ci        auto internalName = std::string(program_->FormatedRecordName()) + std::string(name);
4013af6ab5fSopenharmony_ci        functionNames_.insert(name);
4023af6ab5fSopenharmony_ci        funcScope->BindName(name, util::UString(internalName, Allocator()).View());
4033af6ab5fSopenharmony_ci        return;
4043af6ab5fSopenharmony_ci    }
4053af6ab5fSopenharmony_ci
4063af6ab5fSopenharmony_ci    std::stringstream ss;
4073af6ab5fSopenharmony_ci    ss << std::string(program_->FormatedRecordName());
4083af6ab5fSopenharmony_ci
4093af6ab5fSopenharmony_ci    ASSERT(func != nullptr);
4103af6ab5fSopenharmony_ci
4113af6ab5fSopenharmony_ci    // For anonymous, special-name and duplicate function, get its source and name, make hash code,
4123af6ab5fSopenharmony_ci    // and make #hash_duplicateHashTime#name as its name;
4133af6ab5fSopenharmony_ci    auto funcContentNameStr = func->SourceCode(this).Mutf8() + name.Mutf8();
4143af6ab5fSopenharmony_ci    ss << ANONYMOUS_SPECIAL_DUPLICATE_FUNCTION_SPECIFIER << util::Helpers::GetHashString(funcContentNameStr);
4153af6ab5fSopenharmony_ci
4163af6ab5fSopenharmony_ci    auto res = functionHashNames_.find(funcContentNameStr);
4173af6ab5fSopenharmony_ci    if (res != functionHashNames_.end()) {
4183af6ab5fSopenharmony_ci        ss << "_" << res->second++;
4193af6ab5fSopenharmony_ci    } else {
4203af6ab5fSopenharmony_ci        functionHashNames_.insert({funcContentNameStr, 1});
4213af6ab5fSopenharmony_ci    }
4223af6ab5fSopenharmony_ci    ss << ANONYMOUS_SPECIAL_DUPLICATE_FUNCTION_SPECIFIER;
4233af6ab5fSopenharmony_ci
4243af6ab5fSopenharmony_ci    if (name == ANONYMOUS_FUNC_NAME) {
4253af6ab5fSopenharmony_ci        anonymousFunctionNames_[func] = util::UString(ss.str(), Allocator()).View();
4263af6ab5fSopenharmony_ci    }
4273af6ab5fSopenharmony_ci    if (funcNameWithoutDot && funcNameWithoutBackslash) {
4283af6ab5fSopenharmony_ci        ss << name;
4293af6ab5fSopenharmony_ci    }
4303af6ab5fSopenharmony_ci    std::string internalNameStr = ss.str();
4313af6ab5fSopenharmony_ci    StoreAndCheckSpecialFunctionName(internalNameStr, program_->RecordName().Mutf8());
4323af6ab5fSopenharmony_ci    funcScope->BindName(name, util::UString(internalNameStr, Allocator()).View());
4333af6ab5fSopenharmony_ci}
4343af6ab5fSopenharmony_ci
4353af6ab5fSopenharmony_civoid Binder::BuildScriptFunction(Scope *outerScope, const ir::ScriptFunction *scriptFunc)
4363af6ab5fSopenharmony_ci{
4373af6ab5fSopenharmony_ci    if (bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM) {
4383af6ab5fSopenharmony_ci        return;
4393af6ab5fSopenharmony_ci    }
4403af6ab5fSopenharmony_ci
4413af6ab5fSopenharmony_ci    auto *funcScope = scriptFunc->Scope();
4423af6ab5fSopenharmony_ci    funcScope->ParamScope()->SetParent(outerScope);
4433af6ab5fSopenharmony_ci
4443af6ab5fSopenharmony_ci    if (scriptFunc->IsArrow()) {
4453af6ab5fSopenharmony_ci        const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(scriptFunc);
4463af6ab5fSopenharmony_ci        if (ctor) {
4473af6ab5fSopenharmony_ci            ctor->Scope()->AddFlag(VariableScopeFlags::INNER_ARROW);
4483af6ab5fSopenharmony_ci        }
4493af6ab5fSopenharmony_ci    }
4503af6ab5fSopenharmony_ci
4513af6ab5fSopenharmony_ci    ASSERT(scope_->IsFunctionScope() || scope_->IsTSModuleScope() || scope_->IsTSEnumScope());
4523af6ab5fSopenharmony_ci    BuildFunction(scope_->AsFunctionVariableScope(), util::Helpers::FunctionName(Allocator(), scriptFunc), scriptFunc);
4533af6ab5fSopenharmony_ci}
4543af6ab5fSopenharmony_ci
4553af6ab5fSopenharmony_civoid Binder::BuildVarDeclaratorId(const ir::AstNode *parent, ir::AstNode *childNode)
4563af6ab5fSopenharmony_ci{
4573af6ab5fSopenharmony_ci    childNode->SetParent(parent);
4583af6ab5fSopenharmony_ci
4593af6ab5fSopenharmony_ci    switch (childNode->Type()) {
4603af6ab5fSopenharmony_ci        case ir::AstNodeType::IDENTIFIER: {
4613af6ab5fSopenharmony_ci            auto *ident = childNode->AsIdentifier();
4623af6ab5fSopenharmony_ci            const auto &name = ident->Name();
4633af6ab5fSopenharmony_ci            if (name.Is(FUNCTION_ARGUMENTS)) {
4643af6ab5fSopenharmony_ci                CheckMandatoryArguments(ident);
4653af6ab5fSopenharmony_ci            }
4663af6ab5fSopenharmony_ci
4673af6ab5fSopenharmony_ci            if (util::Helpers::IsGlobalIdentifier(name)) {
4683af6ab5fSopenharmony_ci                break;
4693af6ab5fSopenharmony_ci            }
4703af6ab5fSopenharmony_ci
4713af6ab5fSopenharmony_ci            auto *variable = scope_->FindLocal(name, ResolveBindingOptions::BINDINGS);
4723af6ab5fSopenharmony_ci
4733af6ab5fSopenharmony_ci            if (Program()->Extension() == ScriptExtension::TS) {
4743af6ab5fSopenharmony_ci                ident->SetVariable(variable);
4753af6ab5fSopenharmony_ci                BuildTSSignatureDeclarationBaseParamsWithParent(ident, ident->TypeAnnotation());
4763af6ab5fSopenharmony_ci            }
4773af6ab5fSopenharmony_ci
4783af6ab5fSopenharmony_ci            variable->AddFlag(VariableFlags::INITIALIZED);
4793af6ab5fSopenharmony_ci            break;
4803af6ab5fSopenharmony_ci        }
4813af6ab5fSopenharmony_ci        case ir::AstNodeType::OBJECT_PATTERN: {
4823af6ab5fSopenharmony_ci            auto *objPattern = childNode->AsObjectPattern();
4833af6ab5fSopenharmony_ci
4843af6ab5fSopenharmony_ci            for (auto *prop : objPattern->Properties()) {
4853af6ab5fSopenharmony_ci                BuildVarDeclaratorId(childNode, prop);
4863af6ab5fSopenharmony_ci            }
4873af6ab5fSopenharmony_ci
4883af6ab5fSopenharmony_ci            BuildTSSignatureDeclarationBaseParamsWithParent(objPattern, objPattern->TypeAnnotation());
4893af6ab5fSopenharmony_ci            break;
4903af6ab5fSopenharmony_ci        }
4913af6ab5fSopenharmony_ci        case ir::AstNodeType::ARRAY_PATTERN: {
4923af6ab5fSopenharmony_ci            auto *arrayPattern = childNode->AsArrayPattern();
4933af6ab5fSopenharmony_ci
4943af6ab5fSopenharmony_ci            for (auto *element : childNode->AsArrayPattern()->Elements()) {
4953af6ab5fSopenharmony_ci                BuildVarDeclaratorId(childNode, element);
4963af6ab5fSopenharmony_ci            }
4973af6ab5fSopenharmony_ci
4983af6ab5fSopenharmony_ci            BuildTSSignatureDeclarationBaseParamsWithParent(arrayPattern, arrayPattern->TypeAnnotation());
4993af6ab5fSopenharmony_ci            break;
5003af6ab5fSopenharmony_ci        }
5013af6ab5fSopenharmony_ci        case ir::AstNodeType::ASSIGNMENT_PATTERN: {
5023af6ab5fSopenharmony_ci            ResolveReference(childNode, childNode->AsAssignmentPattern()->Right());
5033af6ab5fSopenharmony_ci            BuildVarDeclaratorId(childNode, childNode->AsAssignmentPattern()->Left());
5043af6ab5fSopenharmony_ci            break;
5053af6ab5fSopenharmony_ci        }
5063af6ab5fSopenharmony_ci        case ir::AstNodeType::PROPERTY: {
5073af6ab5fSopenharmony_ci            ResolveReference(childNode, childNode->AsProperty()->Key());
5083af6ab5fSopenharmony_ci            BuildVarDeclaratorId(childNode, childNode->AsProperty()->Value());
5093af6ab5fSopenharmony_ci            break;
5103af6ab5fSopenharmony_ci        }
5113af6ab5fSopenharmony_ci        case ir::AstNodeType::REST_ELEMENT: {
5123af6ab5fSopenharmony_ci            BuildVarDeclaratorId(childNode, childNode->AsRestElement()->Argument());
5133af6ab5fSopenharmony_ci            break;
5143af6ab5fSopenharmony_ci        }
5153af6ab5fSopenharmony_ci        default:
5163af6ab5fSopenharmony_ci            break;
5173af6ab5fSopenharmony_ci    }
5183af6ab5fSopenharmony_ci}
5193af6ab5fSopenharmony_ci
5203af6ab5fSopenharmony_civoid Binder::BuildTSSignatureDeclarationBaseParamsWithParent(const ir::AstNode *parent, ir::AstNode *typeNode)
5213af6ab5fSopenharmony_ci{
5223af6ab5fSopenharmony_ci    if (!typeNode) {
5233af6ab5fSopenharmony_ci        return;
5243af6ab5fSopenharmony_ci    }
5253af6ab5fSopenharmony_ci    typeNode->SetParent(parent);
5263af6ab5fSopenharmony_ci    BuildTSSignatureDeclarationBaseParams(typeNode);
5273af6ab5fSopenharmony_ci}
5283af6ab5fSopenharmony_ci
5293af6ab5fSopenharmony_civoid Binder::BuildTSSignatureDeclarationBaseParams(const ir::AstNode *typeNode)
5303af6ab5fSopenharmony_ci{
5313af6ab5fSopenharmony_ci    ASSERT(typeNode != nullptr);
5323af6ab5fSopenharmony_ci
5333af6ab5fSopenharmony_ci    Scope *scope = nullptr;
5343af6ab5fSopenharmony_ci
5353af6ab5fSopenharmony_ci    switch (typeNode->Type()) {
5363af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_FUNCTION_TYPE: {
5373af6ab5fSopenharmony_ci            scope = typeNode->AsTSFunctionType()->Scope();
5383af6ab5fSopenharmony_ci            break;
5393af6ab5fSopenharmony_ci        }
5403af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_CONSTRUCTOR_TYPE: {
5413af6ab5fSopenharmony_ci            scope = typeNode->AsTSConstructorType()->Scope();
5423af6ab5fSopenharmony_ci            break;
5433af6ab5fSopenharmony_ci        }
5443af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_SIGNATURE_DECLARATION: {
5453af6ab5fSopenharmony_ci            scope = typeNode->AsTSSignatureDeclaration()->Scope();
5463af6ab5fSopenharmony_ci            break;
5473af6ab5fSopenharmony_ci        }
5483af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_METHOD_SIGNATURE: {
5493af6ab5fSopenharmony_ci            scope = typeNode->AsTSMethodSignature()->Scope();
5503af6ab5fSopenharmony_ci            break;
5513af6ab5fSopenharmony_ci        }
5523af6ab5fSopenharmony_ci        default: {
5533af6ab5fSopenharmony_ci            ResolveReferences(typeNode);
5543af6ab5fSopenharmony_ci            return;
5553af6ab5fSopenharmony_ci        }
5563af6ab5fSopenharmony_ci    }
5573af6ab5fSopenharmony_ci
5583af6ab5fSopenharmony_ci    ASSERT(scope && scope->IsFunctionParamScope());
5593af6ab5fSopenharmony_ci
5603af6ab5fSopenharmony_ci    auto scopeCtx = LexicalScope<FunctionParamScope>::Enter(this, scope->AsFunctionParamScope());
5613af6ab5fSopenharmony_ci    ResolveReferences(typeNode);
5623af6ab5fSopenharmony_ci}
5633af6ab5fSopenharmony_ci
5643af6ab5fSopenharmony_civoid Binder::BuildVarDeclarator(ir::VariableDeclarator *varDecl)
5653af6ab5fSopenharmony_ci{
5663af6ab5fSopenharmony_ci    if (varDecl->Parent()->AsVariableDeclaration()->Kind() == ir::VariableDeclaration::VariableDeclarationKind::VAR) {
5673af6ab5fSopenharmony_ci        ResolveReferences(varDecl);
5683af6ab5fSopenharmony_ci        return;
5693af6ab5fSopenharmony_ci    }
5703af6ab5fSopenharmony_ci
5713af6ab5fSopenharmony_ci    if (varDecl->Init()) {
5723af6ab5fSopenharmony_ci        ResolveReference(varDecl, varDecl->Init());
5733af6ab5fSopenharmony_ci    }
5743af6ab5fSopenharmony_ci
5753af6ab5fSopenharmony_ci    BuildVarDeclaratorId(varDecl, varDecl->Id());
5763af6ab5fSopenharmony_ci}
5773af6ab5fSopenharmony_ci
5783af6ab5fSopenharmony_civoid Binder::BuildClassDefinition(ir::ClassDefinition *classDef)
5793af6ab5fSopenharmony_ci{
5803af6ab5fSopenharmony_ci    if (classDef->Parent()->IsClassDeclaration()) {
5813af6ab5fSopenharmony_ci        util::StringView className = classDef->GetName();
5823af6ab5fSopenharmony_ci        ASSERT(!className.Empty());
5833af6ab5fSopenharmony_ci        ScopeFindResult res = scope_->Find(className);
5843af6ab5fSopenharmony_ci
5853af6ab5fSopenharmony_ci        ASSERT(res.variable && (res.variable->Declaration()->IsClassDecl() ||
5863af6ab5fSopenharmony_ci               (res.variable->Declaration()->IsFunctionDecl() &&
5873af6ab5fSopenharmony_ci               res.variable->Declaration()->AsFunctionDecl()->GetDeclClass() != nullptr)));
5883af6ab5fSopenharmony_ci        res.variable->AddFlag(VariableFlags::INITIALIZED);
5893af6ab5fSopenharmony_ci    }
5903af6ab5fSopenharmony_ci
5913af6ab5fSopenharmony_ci    auto scopeCtx = LexicalScope<ClassScope>::Enter(this, classDef->Scope());
5923af6ab5fSopenharmony_ci
5933af6ab5fSopenharmony_ci    if (classDef->TypeParams()) {
5943af6ab5fSopenharmony_ci        ResolveReference(classDef, classDef->TypeParams());
5953af6ab5fSopenharmony_ci    }
5963af6ab5fSopenharmony_ci
5973af6ab5fSopenharmony_ci    if (classDef->Super()) {
5983af6ab5fSopenharmony_ci        ResolveReference(classDef, classDef->Super());
5993af6ab5fSopenharmony_ci    }
6003af6ab5fSopenharmony_ci
6013af6ab5fSopenharmony_ci    if (classDef->SuperTypeParams()) {
6023af6ab5fSopenharmony_ci        ResolveReference(classDef, classDef->SuperTypeParams());
6033af6ab5fSopenharmony_ci    }
6043af6ab5fSopenharmony_ci
6053af6ab5fSopenharmony_ci    for (auto *iter : classDef->Implements()) {
6063af6ab5fSopenharmony_ci        ResolveReference(classDef, iter);
6073af6ab5fSopenharmony_ci    }
6083af6ab5fSopenharmony_ci
6093af6ab5fSopenharmony_ci    // new class features in ecma2022 are only supported for api11 and above
6103af6ab5fSopenharmony_ci    if (Program()->TargetApiVersion() > 10 && !(bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM)) {
6113af6ab5fSopenharmony_ci        classDef->BuildClassEnvironment(program_->UseDefineSemantic());
6123af6ab5fSopenharmony_ci    }
6133af6ab5fSopenharmony_ci
6143af6ab5fSopenharmony_ci    if (classDef->Ident()) {
6153af6ab5fSopenharmony_ci        ScopeFindResult res = scope_->Find(classDef->Ident()->Name());
6163af6ab5fSopenharmony_ci
6173af6ab5fSopenharmony_ci        ASSERT(res.variable && res.variable->Declaration()->IsConstDecl());
6183af6ab5fSopenharmony_ci        res.variable->AddFlag(VariableFlags::INITIALIZED);
6193af6ab5fSopenharmony_ci
6203af6ab5fSopenharmony_ci        classDef->Ident()->SetParent(classDef);
6213af6ab5fSopenharmony_ci    }
6223af6ab5fSopenharmony_ci    bool previousInSendableClass = inSendableClass_;
6233af6ab5fSopenharmony_ci
6243af6ab5fSopenharmony_ci    if (!(classDef->Parent()->IsClassDeclaration() && classDef->Parent()->AsClassDeclaration()->IsAnnotationDecl())) {
6253af6ab5fSopenharmony_ci        ResolveReference(classDef, classDef->Ctor());
6263af6ab5fSopenharmony_ci    }
6273af6ab5fSopenharmony_ci
6283af6ab5fSopenharmony_ci    if (classDef->NeedStaticInitializer()) {
6293af6ab5fSopenharmony_ci        ResolveReference(classDef, classDef->StaticInitializer());
6303af6ab5fSopenharmony_ci    }
6313af6ab5fSopenharmony_ci
6323af6ab5fSopenharmony_ci    if (classDef->NeedInstanceInitializer()) {
6333af6ab5fSopenharmony_ci        ResolveReference(classDef, classDef->InstanceInitializer());
6343af6ab5fSopenharmony_ci    }
6353af6ab5fSopenharmony_ci
6363af6ab5fSopenharmony_ci    for (auto *stmt : classDef->Body()) {
6373af6ab5fSopenharmony_ci        ResolveReference(classDef, stmt);
6383af6ab5fSopenharmony_ci    }
6393af6ab5fSopenharmony_ci
6403af6ab5fSopenharmony_ci    for (auto *iter : classDef->IndexSignatures()) {
6413af6ab5fSopenharmony_ci        ResolveReference(classDef, iter);
6423af6ab5fSopenharmony_ci    }
6433af6ab5fSopenharmony_ci    inSendableClass_ = previousInSendableClass;
6443af6ab5fSopenharmony_ci}
6453af6ab5fSopenharmony_ci
6463af6ab5fSopenharmony_civoid Binder::BuildForUpdateLoop(ir::ForUpdateStatement *forUpdateStmt)
6473af6ab5fSopenharmony_ci{
6483af6ab5fSopenharmony_ci    auto *loopScope = forUpdateStmt->Scope();
6493af6ab5fSopenharmony_ci
6503af6ab5fSopenharmony_ci    auto loopCtx = LexicalScope<LoopScope>::Enter(this, loopScope);
6513af6ab5fSopenharmony_ci
6523af6ab5fSopenharmony_ci    if (forUpdateStmt->Init()) {
6533af6ab5fSopenharmony_ci        ResolveReference(forUpdateStmt, forUpdateStmt->Init());
6543af6ab5fSopenharmony_ci    }
6553af6ab5fSopenharmony_ci
6563af6ab5fSopenharmony_ci    if (forUpdateStmt->Update()) {
6573af6ab5fSopenharmony_ci        ResolveReference(forUpdateStmt, forUpdateStmt->Update());
6583af6ab5fSopenharmony_ci    }
6593af6ab5fSopenharmony_ci
6603af6ab5fSopenharmony_ci    if (forUpdateStmt->Test()) {
6613af6ab5fSopenharmony_ci        ResolveReference(forUpdateStmt, forUpdateStmt->Test());
6623af6ab5fSopenharmony_ci    }
6633af6ab5fSopenharmony_ci
6643af6ab5fSopenharmony_ci    ResolveReference(forUpdateStmt, forUpdateStmt->Body());
6653af6ab5fSopenharmony_ci
6663af6ab5fSopenharmony_ci    loopCtx.GetScope()->InitVariable();
6673af6ab5fSopenharmony_ci}
6683af6ab5fSopenharmony_ci
6693af6ab5fSopenharmony_civoid Binder::BuildForInOfLoop(const ir::Statement *parent, binder::LoopScope *loopScope, ir::AstNode *left,
6703af6ab5fSopenharmony_ci                              ir::Expression *right, ir::Statement *body)
6713af6ab5fSopenharmony_ci{
6723af6ab5fSopenharmony_ci    auto loopCtx = LexicalScope<LoopScope>::Enter(this, loopScope);
6733af6ab5fSopenharmony_ci
6743af6ab5fSopenharmony_ci    ResolveReference(parent, right);
6753af6ab5fSopenharmony_ci    ResolveReference(parent, left);
6763af6ab5fSopenharmony_ci
6773af6ab5fSopenharmony_ci    ResolveReference(parent, body);
6783af6ab5fSopenharmony_ci    loopCtx.GetScope()->InitVariable();
6793af6ab5fSopenharmony_ci}
6803af6ab5fSopenharmony_ci
6813af6ab5fSopenharmony_civoid Binder::BuildCatchClause(ir::CatchClause *catchClauseStmt)
6823af6ab5fSopenharmony_ci{
6833af6ab5fSopenharmony_ci    if (catchClauseStmt->Param()) {
6843af6ab5fSopenharmony_ci        auto paramScopeCtx = LexicalScope<CatchParamScope>::Enter(this, catchClauseStmt->Scope()->ParamScope());
6853af6ab5fSopenharmony_ci        ResolveReference(catchClauseStmt, catchClauseStmt->Param());
6863af6ab5fSopenharmony_ci    }
6873af6ab5fSopenharmony_ci
6883af6ab5fSopenharmony_ci    auto scopeCtx = LexicalScope<CatchScope>::Enter(this, catchClauseStmt->Scope());
6893af6ab5fSopenharmony_ci    ResolveReference(catchClauseStmt, catchClauseStmt->Body());
6903af6ab5fSopenharmony_ci}
6913af6ab5fSopenharmony_ci
6923af6ab5fSopenharmony_civoid Binder::ResolveReference(const ir::AstNode *parent, ir::AstNode *childNode)
6933af6ab5fSopenharmony_ci{
6943af6ab5fSopenharmony_ci    childNode->SetParent(parent);
6953af6ab5fSopenharmony_ci
6963af6ab5fSopenharmony_ci    ClassTdz classTdz(parent, childNode, scope_);
6973af6ab5fSopenharmony_ci
6983af6ab5fSopenharmony_ci    switch (childNode->Type()) {
6993af6ab5fSopenharmony_ci        case ir::AstNodeType::IDENTIFIER: {
7003af6ab5fSopenharmony_ci            auto *ident = childNode->AsIdentifier();
7013af6ab5fSopenharmony_ci
7023af6ab5fSopenharmony_ci            if (ident->Name().Is(FUNCTION_ARGUMENTS)) {
7033af6ab5fSopenharmony_ci                CheckMandatoryArguments(ident);
7043af6ab5fSopenharmony_ci            }
7053af6ab5fSopenharmony_ci
7063af6ab5fSopenharmony_ci            if (ident->IsReference()) {
7073af6ab5fSopenharmony_ci                LookupIdentReference(ident);
7083af6ab5fSopenharmony_ci            }
7093af6ab5fSopenharmony_ci
7103af6ab5fSopenharmony_ci            /* During ts to js transformation, a non-empty namespace in ts file will be transformed
7113af6ab5fSopenharmony_ci               into a anonymous function while empty namespace will be removed. So the name for the
7123af6ab5fSopenharmony_ci               namespace need to be stored before the transformation.*/
7133af6ab5fSopenharmony_ci            if (scope_->Type() == ScopeType::TSMODULE) {
7143af6ab5fSopenharmony_ci                scope_->SetSelfScopeName(ident->Name());
7153af6ab5fSopenharmony_ci            }
7163af6ab5fSopenharmony_ci
7173af6ab5fSopenharmony_ci            ResolveReferences(childNode);
7183af6ab5fSopenharmony_ci            break;
7193af6ab5fSopenharmony_ci        }
7203af6ab5fSopenharmony_ci        case ir::AstNodeType::ANNOTATION: {
7213af6ab5fSopenharmony_ci            auto *annotation = childNode->AsAnnotation();
7223af6ab5fSopenharmony_ci            std::string annoName{annotation->Name()};
7233af6ab5fSopenharmony_ci            ScopeFindResult res = scope_->Find(annotation->Name(), bindingOptions_);
7243af6ab5fSopenharmony_ci            if (res.variable != nullptr) {
7253af6ab5fSopenharmony_ci                if (res.variable->Declaration()->Node()->IsImportSpecifier()) {
7263af6ab5fSopenharmony_ci                    annotation->SetIsImported();
7273af6ab5fSopenharmony_ci                } else if (!res.variable->Declaration()->Node()->IsClassDefinition()) {
7283af6ab5fSopenharmony_ci                    ThrowInvalidAnnotationDeclaration(annotation->Start(), annotation->Name());
7293af6ab5fSopenharmony_ci                }
7303af6ab5fSopenharmony_ci            } else if (annoName.find_first_of(".") != std::string::npos) {
7313af6ab5fSopenharmony_ci                auto importName = annoName.substr(0, annoName.find_first_of("."));
7323af6ab5fSopenharmony_ci                ScopeFindResult res = scope_->Find(util::StringView(importName), bindingOptions_);
7333af6ab5fSopenharmony_ci                if (res.variable != nullptr && res.variable->Declaration()->Node()->IsImportNamespaceSpecifier()) {
7343af6ab5fSopenharmony_ci                    annotation->SetIsImported();
7353af6ab5fSopenharmony_ci                } else {
7363af6ab5fSopenharmony_ci                    ThrowInvalidAnnotationDeclaration(annotation->Start(), annotation->Name());
7373af6ab5fSopenharmony_ci                }
7383af6ab5fSopenharmony_ci            } else {
7393af6ab5fSopenharmony_ci                ThrowInvalidAnnotationDeclaration(annotation->Start(), annotation->Name());
7403af6ab5fSopenharmony_ci            }
7413af6ab5fSopenharmony_ci            ResolveReferences(childNode);
7423af6ab5fSopenharmony_ci            break;
7433af6ab5fSopenharmony_ci        }
7443af6ab5fSopenharmony_ci        case ir::AstNodeType::PRIVATE_IDENTIFIER: {
7453af6ab5fSopenharmony_ci            if (Program()->Extension() == ScriptExtension::JS) {
7463af6ab5fSopenharmony_ci                CheckPrivateDeclaration(childNode->AsPrivateIdentifier());
7473af6ab5fSopenharmony_ci            } else if (Program()->Extension() == ScriptExtension::TS &&
7483af6ab5fSopenharmony_ci                       bindingFlags_ == ResolveBindingFlags::TS_AFTER_TRANSFORM) {
7493af6ab5fSopenharmony_ci                CheckPrivateDeclaration(childNode->AsPrivateIdentifier());
7503af6ab5fSopenharmony_ci            }
7513af6ab5fSopenharmony_ci            break;
7523af6ab5fSopenharmony_ci        }
7533af6ab5fSopenharmony_ci        case ir::AstNodeType::SUPER_EXPRESSION: {
7543af6ab5fSopenharmony_ci            VariableScope *varScope = scope_->EnclosingVariableScope();
7553af6ab5fSopenharmony_ci            varScope->AddFlag(VariableScopeFlags::USE_SUPER);
7563af6ab5fSopenharmony_ci
7573af6ab5fSopenharmony_ci            ResolveReferences(childNode);
7583af6ab5fSopenharmony_ci            break;
7593af6ab5fSopenharmony_ci        }
7603af6ab5fSopenharmony_ci        case ir::AstNodeType::SCRIPT_FUNCTION: {
7613af6ab5fSopenharmony_ci            bool previousInSendableFunction = inSendableFunction_;
7623af6ab5fSopenharmony_ci            auto *scriptFunc = childNode->AsScriptFunction();
7633af6ab5fSopenharmony_ci            // Static initializer only be executed once. Treat it as unshared method.
7643af6ab5fSopenharmony_ci            if ((inSendableClass_ && !scriptFunc->IsStaticInitializer()) || inSendableFunction_) {
7653af6ab5fSopenharmony_ci                scriptFunc->SetInSendable();
7663af6ab5fSopenharmony_ci            }
7673af6ab5fSopenharmony_ci            bool enableSendableClass = program_->TargetApiVersion() >=
7683af6ab5fSopenharmony_ci                util::Helpers::SENDABLE_CLASS_MIN_SUPPORTED_API_VERSION;
7693af6ab5fSopenharmony_ci            util::Helpers::ScanDirectives(const_cast<ir::ScriptFunction *>(scriptFunc), Program()->GetLineIndex(),
7703af6ab5fSopenharmony_ci                enableSendableClass,
7713af6ab5fSopenharmony_ci                !util::Helpers::IsDefaultApiVersion(program_->TargetApiVersion(), program_->GetTargetApiSubVersion()));
7723af6ab5fSopenharmony_ci
7733af6ab5fSopenharmony_ci            if (scriptFunc->IsConstructor() && util::Helpers::GetClassDefiniton(scriptFunc)->IsSendable()) {
7743af6ab5fSopenharmony_ci                scriptFunc->SetInSendable();
7753af6ab5fSopenharmony_ci                inSendableClass_ = true;
7763af6ab5fSopenharmony_ci            } else if (scriptFunc->IsSendable()) {
7773af6ab5fSopenharmony_ci                scriptFunc->SetInSendable();
7783af6ab5fSopenharmony_ci                inSendableFunction_ = true;
7793af6ab5fSopenharmony_ci            }
7803af6ab5fSopenharmony_ci
7813af6ab5fSopenharmony_ci            auto *funcScope = scriptFunc->Scope();
7823af6ab5fSopenharmony_ci
7833af6ab5fSopenharmony_ci            auto *outerScope = scope_;
7843af6ab5fSopenharmony_ci
7853af6ab5fSopenharmony_ci            if (scriptFunc->Id() != nullptr) {
7863af6ab5fSopenharmony_ci                scriptFunc->Id()->SetParent(scriptFunc);
7873af6ab5fSopenharmony_ci            }
7883af6ab5fSopenharmony_ci
7893af6ab5fSopenharmony_ci            {
7903af6ab5fSopenharmony_ci                auto paramScopeCtx = LexicalScope<FunctionParamScope>::Enter(this, funcScope->ParamScope());
7913af6ab5fSopenharmony_ci
7923af6ab5fSopenharmony_ci                if (Program()->Extension() == ScriptExtension::TS) {
7933af6ab5fSopenharmony_ci                    if (scriptFunc->TypeParams() != nullptr) {
7943af6ab5fSopenharmony_ci                        ResolveReference(scriptFunc, scriptFunc->TypeParams());
7953af6ab5fSopenharmony_ci                    }
7963af6ab5fSopenharmony_ci                    if (scriptFunc->ThisParams() != nullptr) {
7973af6ab5fSopenharmony_ci                        ResolveReference(scriptFunc, scriptFunc->ThisParams());
7983af6ab5fSopenharmony_ci                    }
7993af6ab5fSopenharmony_ci                }
8003af6ab5fSopenharmony_ci
8013af6ab5fSopenharmony_ci                for (auto *param : scriptFunc->Params()) {
8023af6ab5fSopenharmony_ci                    ResolveReference(scriptFunc, param);
8033af6ab5fSopenharmony_ci                }
8043af6ab5fSopenharmony_ci            }
8053af6ab5fSopenharmony_ci
8063af6ab5fSopenharmony_ci            if (Program()->Extension() == ScriptExtension::TS) {
8073af6ab5fSopenharmony_ci                if (scriptFunc->ReturnTypeAnnotation()) {
8083af6ab5fSopenharmony_ci                    ResolveReference(scriptFunc, scriptFunc->ReturnTypeAnnotation());
8093af6ab5fSopenharmony_ci                }
8103af6ab5fSopenharmony_ci
8113af6ab5fSopenharmony_ci                if (scriptFunc->IsOverload() || scriptFunc->Declare()) {
8123af6ab5fSopenharmony_ci                    break;
8133af6ab5fSopenharmony_ci                }
8143af6ab5fSopenharmony_ci            }
8153af6ab5fSopenharmony_ci
8163af6ab5fSopenharmony_ci            auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
8173af6ab5fSopenharmony_ci
8183af6ab5fSopenharmony_ci            BuildScriptFunction(outerScope, scriptFunc);
8193af6ab5fSopenharmony_ci
8203af6ab5fSopenharmony_ci            ResolveReference(scriptFunc, scriptFunc->Body());
8213af6ab5fSopenharmony_ci            inSendableFunction_ = previousInSendableFunction;
8223af6ab5fSopenharmony_ci            break;
8233af6ab5fSopenharmony_ci        }
8243af6ab5fSopenharmony_ci        case ir::AstNodeType::VARIABLE_DECLARATOR: {
8253af6ab5fSopenharmony_ci            BuildVarDeclarator(childNode->AsVariableDeclarator());
8263af6ab5fSopenharmony_ci
8273af6ab5fSopenharmony_ci            break;
8283af6ab5fSopenharmony_ci        }
8293af6ab5fSopenharmony_ci        case ir::AstNodeType::CLASS_DEFINITION: {
8303af6ab5fSopenharmony_ci            auto *classScope = childNode->AsClassDefinition()->Scope();
8313af6ab5fSopenharmony_ci            classScope->SetParent(scope_);
8323af6ab5fSopenharmony_ci            BuildClassDefinition(childNode->AsClassDefinition());
8333af6ab5fSopenharmony_ci
8343af6ab5fSopenharmony_ci            break;
8353af6ab5fSopenharmony_ci        }
8363af6ab5fSopenharmony_ci        case ir::AstNodeType::CLASS_PROPERTY: {
8373af6ab5fSopenharmony_ci            /* for ts tranformer cases, all class properties are implemented by transformer in api10 and
8383af6ab5fSopenharmony_ci             * only public instance class properties are implemented by transformer in api11*/
8393af6ab5fSopenharmony_ci            auto *prop = childNode->AsClassProperty();
8403af6ab5fSopenharmony_ci            if (Program()->Extension() == ScriptExtension::TS && (Program()->TargetApiVersion() < 11 ||
8413af6ab5fSopenharmony_ci                (!prop->IsStatic() && !prop->IsPrivate()))) {
8423af6ab5fSopenharmony_ci                const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(prop);
8433af6ab5fSopenharmony_ci                auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, ctor->Scope());
8443af6ab5fSopenharmony_ci                ResolveReferences(childNode);
8453af6ab5fSopenharmony_ci                break;
8463af6ab5fSopenharmony_ci            }
8473af6ab5fSopenharmony_ci
8483af6ab5fSopenharmony_ci            ResolveReference(prop, prop->Key());
8493af6ab5fSopenharmony_ci            if (prop->Value() != nullptr) {
8503af6ab5fSopenharmony_ci                ASSERT(parent->IsClassDefinition());
8513af6ab5fSopenharmony_ci                const auto *classDef = parent->AsClassDefinition();
8523af6ab5fSopenharmony_ci                const ir::MethodDefinition *method = prop->IsStatic() ? classDef->StaticInitializer() :
8533af6ab5fSopenharmony_ci                                                     classDef->InstanceInitializer();
8543af6ab5fSopenharmony_ci                auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, method->Function()->Scope());
8553af6ab5fSopenharmony_ci                ResolveReference(prop, prop->Value());
8563af6ab5fSopenharmony_ci            }
8573af6ab5fSopenharmony_ci            break;
8583af6ab5fSopenharmony_ci        }
8593af6ab5fSopenharmony_ci        case ir::AstNodeType::BLOCK_STATEMENT: {
8603af6ab5fSopenharmony_ci            auto scope = childNode->AsBlockStatement()->Scope();
8613af6ab5fSopenharmony_ci            auto scopeCtx = scope != nullptr ?
8623af6ab5fSopenharmony_ci                LexicalScope<Scope>::Enter(this, scope) :
8633af6ab5fSopenharmony_ci                LexicalScope<Scope>::Enter(this, GetScope());
8643af6ab5fSopenharmony_ci
8653af6ab5fSopenharmony_ci            ResolveReferences(childNode);
8663af6ab5fSopenharmony_ci            break;
8673af6ab5fSopenharmony_ci        }
8683af6ab5fSopenharmony_ci        case ir::AstNodeType::SWITCH_STATEMENT: {
8693af6ab5fSopenharmony_ci            auto *switchStatement = childNode->AsSwitchStatement();
8703af6ab5fSopenharmony_ci            ResolveReference(switchStatement, switchStatement->Discriminant());
8713af6ab5fSopenharmony_ci
8723af6ab5fSopenharmony_ci            auto scopeCtx = LexicalScope<LocalScope>::Enter(this, childNode->AsSwitchStatement()->Scope());
8733af6ab5fSopenharmony_ci            for (auto *it : switchStatement->Cases()) {
8743af6ab5fSopenharmony_ci                ResolveReference(switchStatement, it);
8753af6ab5fSopenharmony_ci            }
8763af6ab5fSopenharmony_ci            break;
8773af6ab5fSopenharmony_ci        }
8783af6ab5fSopenharmony_ci        case ir::AstNodeType::DO_WHILE_STATEMENT: {
8793af6ab5fSopenharmony_ci            auto *doWhileStatement = childNode->AsDoWhileStatement();
8803af6ab5fSopenharmony_ci
8813af6ab5fSopenharmony_ci            {
8823af6ab5fSopenharmony_ci                auto loopScopeCtx = LexicalScope<LoopScope>::Enter(this, doWhileStatement->Scope());
8833af6ab5fSopenharmony_ci                ResolveReference(doWhileStatement, doWhileStatement->Body());
8843af6ab5fSopenharmony_ci                loopScopeCtx.GetScope()->InitVariable();
8853af6ab5fSopenharmony_ci            }
8863af6ab5fSopenharmony_ci
8873af6ab5fSopenharmony_ci            ResolveReference(doWhileStatement, doWhileStatement->Test());
8883af6ab5fSopenharmony_ci            break;
8893af6ab5fSopenharmony_ci        }
8903af6ab5fSopenharmony_ci        case ir::AstNodeType::WHILE_STATEMENT: {
8913af6ab5fSopenharmony_ci            auto *whileStatement = childNode->AsWhileStatement();
8923af6ab5fSopenharmony_ci            ResolveReference(whileStatement, whileStatement->Test());
8933af6ab5fSopenharmony_ci
8943af6ab5fSopenharmony_ci            auto loopScopeCtx = LexicalScope<LoopScope>::Enter(this, whileStatement->Scope());
8953af6ab5fSopenharmony_ci            ResolveReference(whileStatement, whileStatement->Body());
8963af6ab5fSopenharmony_ci            loopScopeCtx.GetScope()->InitVariable();
8973af6ab5fSopenharmony_ci            break;
8983af6ab5fSopenharmony_ci        }
8993af6ab5fSopenharmony_ci        case ir::AstNodeType::FOR_UPDATE_STATEMENT: {
9003af6ab5fSopenharmony_ci            BuildForUpdateLoop(childNode->AsForUpdateStatement());
9013af6ab5fSopenharmony_ci            break;
9023af6ab5fSopenharmony_ci        }
9033af6ab5fSopenharmony_ci        case ir::AstNodeType::FOR_IN_STATEMENT: {
9043af6ab5fSopenharmony_ci            auto *forInStmt = childNode->AsForInStatement();
9053af6ab5fSopenharmony_ci            BuildForInOfLoop(forInStmt, forInStmt->Scope(), forInStmt->Left(), forInStmt->Right(), forInStmt->Body());
9063af6ab5fSopenharmony_ci
9073af6ab5fSopenharmony_ci            break;
9083af6ab5fSopenharmony_ci        }
9093af6ab5fSopenharmony_ci        case ir::AstNodeType::FOR_OF_STATEMENT: {
9103af6ab5fSopenharmony_ci            auto *forOfStmt = childNode->AsForOfStatement();
9113af6ab5fSopenharmony_ci            BuildForInOfLoop(forOfStmt, forOfStmt->Scope(), forOfStmt->Left(), forOfStmt->Right(), forOfStmt->Body());
9123af6ab5fSopenharmony_ci            break;
9133af6ab5fSopenharmony_ci        }
9143af6ab5fSopenharmony_ci        case ir::AstNodeType::CATCH_CLAUSE: {
9153af6ab5fSopenharmony_ci            BuildCatchClause(childNode->AsCatchClause());
9163af6ab5fSopenharmony_ci            break;
9173af6ab5fSopenharmony_ci        }
9183af6ab5fSopenharmony_ci        case ir::AstNodeType::EXPORT_NAMED_DECLARATION: {
9193af6ab5fSopenharmony_ci            ValidateExportDecl(childNode->AsExportNamedDeclaration());
9203af6ab5fSopenharmony_ci
9213af6ab5fSopenharmony_ci            ResolveReferences(childNode);
9223af6ab5fSopenharmony_ci            break;
9233af6ab5fSopenharmony_ci        }
9243af6ab5fSopenharmony_ci        // TypeScript specific part
9253af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_FUNCTION_TYPE:
9263af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_CONSTRUCTOR_TYPE:
9273af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_METHOD_SIGNATURE:
9283af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_SIGNATURE_DECLARATION: {
9293af6ab5fSopenharmony_ci            BuildTSSignatureDeclarationBaseParams(childNode);
9303af6ab5fSopenharmony_ci            break;
9313af6ab5fSopenharmony_ci        }
9323af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_MODULE_DECLARATION: {
9333af6ab5fSopenharmony_ci            auto scopeCtx = LexicalScope<Scope>::Enter(this, childNode->AsTSModuleDeclaration()->Scope());
9343af6ab5fSopenharmony_ci            ResolveReferences(childNode);
9353af6ab5fSopenharmony_ci            break;
9363af6ab5fSopenharmony_ci        }
9373af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_ENUM_DECLARATION: {
9383af6ab5fSopenharmony_ci            auto scopeCtx = LexicalScope<Scope>::Enter(this, childNode->AsTSEnumDeclaration()->Scope());
9393af6ab5fSopenharmony_ci            ResolveReferences(childNode);
9403af6ab5fSopenharmony_ci            break;
9413af6ab5fSopenharmony_ci        }
9423af6ab5fSopenharmony_ci        default: {
9433af6ab5fSopenharmony_ci            ResolveReferences(childNode);
9443af6ab5fSopenharmony_ci            break;
9453af6ab5fSopenharmony_ci        }
9463af6ab5fSopenharmony_ci    }
9473af6ab5fSopenharmony_ci}
9483af6ab5fSopenharmony_civoid Binder::ResolveReferences(const ir::AstNode *parent)
9493af6ab5fSopenharmony_ci{
9503af6ab5fSopenharmony_ci    parent->Iterate([this, parent](auto *childNode) { ResolveReference(parent, childNode); });
9513af6ab5fSopenharmony_ci}
9523af6ab5fSopenharmony_ci
9533af6ab5fSopenharmony_civoid Binder::AddMandatoryParam(const std::string_view &name)
9543af6ab5fSopenharmony_ci{
9553af6ab5fSopenharmony_ci    ASSERT(scope_->IsFunctionVariableScope());
9563af6ab5fSopenharmony_ci
9573af6ab5fSopenharmony_ci    auto *decl = Allocator()->New<ParameterDecl>(name);
9583af6ab5fSopenharmony_ci    auto *param = Allocator()->New<LocalVariable>(decl, VariableFlags::VAR);
9593af6ab5fSopenharmony_ci
9603af6ab5fSopenharmony_ci    auto &funcParams = scope_->AsFunctionVariableScope()->ParamScope()->Params();
9613af6ab5fSopenharmony_ci    funcParams.insert(funcParams.begin(), param);
9623af6ab5fSopenharmony_ci    scope_->AsFunctionVariableScope()->ParamScope()->Bindings().insert({decl->Name(), param});
9633af6ab5fSopenharmony_ci    scope_->AsFunctionVariableScope()->Bindings().insert({decl->Name(), param});
9643af6ab5fSopenharmony_ci}
9653af6ab5fSopenharmony_ci
9663af6ab5fSopenharmony_civoid Binder::AddMandatoryParams()
9673af6ab5fSopenharmony_ci{
9683af6ab5fSopenharmony_ci    ASSERT(scope_ == topScope_);
9693af6ab5fSopenharmony_ci    ASSERT(!functionScopes_.empty());
9703af6ab5fSopenharmony_ci    auto iter = functionScopes_.begin();
9713af6ab5fSopenharmony_ci    [[maybe_unused]] auto *funcScope = *iter++;
9723af6ab5fSopenharmony_ci
9733af6ab5fSopenharmony_ci    ASSERT(funcScope->IsGlobalScope() || funcScope->IsModuleScope());
9743af6ab5fSopenharmony_ci
9753af6ab5fSopenharmony_ci    if (program_->Kind() == parser::ScriptKind::COMMONJS) {
9763af6ab5fSopenharmony_ci        AddMandatoryParams(CJS_MAINFUNC_MANDATORY_PARAMS);
9773af6ab5fSopenharmony_ci    } else {
9783af6ab5fSopenharmony_ci        AddMandatoryParams(FUNCTION_MANDATORY_PARAMS);
9793af6ab5fSopenharmony_ci    }
9803af6ab5fSopenharmony_ci
9813af6ab5fSopenharmony_ci    for (; iter != functionScopes_.end(); iter++) {
9823af6ab5fSopenharmony_ci        funcScope = *iter;
9833af6ab5fSopenharmony_ci        const auto *scriptFunc = funcScope->Node()->AsScriptFunction();
9843af6ab5fSopenharmony_ci
9853af6ab5fSopenharmony_ci        auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
9863af6ab5fSopenharmony_ci
9873af6ab5fSopenharmony_ci        if (!scriptFunc->IsArrow()) {
9883af6ab5fSopenharmony_ci            AddMandatoryParams(FUNCTION_MANDATORY_PARAMS);
9893af6ab5fSopenharmony_ci            continue;
9903af6ab5fSopenharmony_ci        }
9913af6ab5fSopenharmony_ci
9923af6ab5fSopenharmony_ci        const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(scriptFunc);
9933af6ab5fSopenharmony_ci        bool lexicalFunctionObject {};
9943af6ab5fSopenharmony_ci
9953af6ab5fSopenharmony_ci        if (ctor && util::Helpers::GetClassDefiniton(ctor)->Super() &&
9963af6ab5fSopenharmony_ci            funcScope->HasFlag(VariableScopeFlags::USE_SUPER)) {
9973af6ab5fSopenharmony_ci            ASSERT(ctor->Scope()->HasFlag(VariableScopeFlags::INNER_ARROW));
9983af6ab5fSopenharmony_ci            ctor->Scope()->AddFlag(VariableScopeFlags::SET_LEXICAL_FUNCTION);
9993af6ab5fSopenharmony_ci            lexicalFunctionObject = true;
10003af6ab5fSopenharmony_ci            AddMandatoryParams(CTOR_ARROW_MANDATORY_PARAMS);
10013af6ab5fSopenharmony_ci        } else {
10023af6ab5fSopenharmony_ci            AddMandatoryParams(ARROW_MANDATORY_PARAMS);
10033af6ab5fSopenharmony_ci        }
10043af6ab5fSopenharmony_ci
10053af6ab5fSopenharmony_ci        LookupReference(MANDATORY_PARAM_NEW_TARGET);
10063af6ab5fSopenharmony_ci        LookupReference(MANDATORY_PARAM_THIS);
10073af6ab5fSopenharmony_ci
10083af6ab5fSopenharmony_ci        if (funcScope->HasFlag(VariableScopeFlags::USE_ARGS)) {
10093af6ab5fSopenharmony_ci            LookupReference(FUNCTION_ARGUMENTS);
10103af6ab5fSopenharmony_ci        }
10113af6ab5fSopenharmony_ci
10123af6ab5fSopenharmony_ci        if (lexicalFunctionObject) {
10133af6ab5fSopenharmony_ci            LookupReference(MANDATORY_PARAM_FUNC);
10143af6ab5fSopenharmony_ci        }
10153af6ab5fSopenharmony_ci    }
10163af6ab5fSopenharmony_ci}
10173af6ab5fSopenharmony_ci
10183af6ab5fSopenharmony_civoid Binder::AddDeclarationName(const util::StringView &name, DeclType type)
10193af6ab5fSopenharmony_ci{
10203af6ab5fSopenharmony_ci    if (extension_ != ScriptExtension::TS) {
10213af6ab5fSopenharmony_ci        return;
10223af6ab5fSopenharmony_ci    }
10233af6ab5fSopenharmony_ci    variableNames_.insert(name);
10243af6ab5fSopenharmony_ci
10253af6ab5fSopenharmony_ci    if (type == DeclType::ENUM) {
10263af6ab5fSopenharmony_ci        return;
10273af6ab5fSopenharmony_ci    }
10283af6ab5fSopenharmony_ci    auto *scope = GetScope();
10293af6ab5fSopenharmony_ci    while (scope != nullptr) {
10303af6ab5fSopenharmony_ci        if (scope->IsTSModuleScope()) {
10313af6ab5fSopenharmony_ci            scope->AsTSModuleScope()->AddDeclarationName(name);
10323af6ab5fSopenharmony_ci        }
10333af6ab5fSopenharmony_ci        if (scope->IsTSEnumScope()) {
10343af6ab5fSopenharmony_ci            scope->AsTSEnumScope()->AddDeclarationName(name);
10353af6ab5fSopenharmony_ci        }
10363af6ab5fSopenharmony_ci        scope = scope->Parent();
10373af6ab5fSopenharmony_ci    }
10383af6ab5fSopenharmony_ci}
10393af6ab5fSopenharmony_ci
10403af6ab5fSopenharmony_cibool Binder::HasVariableName(const util::StringView &name) const
10413af6ab5fSopenharmony_ci{
10423af6ab5fSopenharmony_ci    return variableNames_.find(name) != variableNames_.end();
10433af6ab5fSopenharmony_ci}
10443af6ab5fSopenharmony_ci
10453af6ab5fSopenharmony_cistd::vector<Variable *> Binder::FindIdentifierTSVariables(const ir::Identifier *identifier, Scope *scope,
10463af6ab5fSopenharmony_ci    ScopeFindResult &res)
10473af6ab5fSopenharmony_ci{
10483af6ab5fSopenharmony_ci    const auto &name = identifier->Name();
10493af6ab5fSopenharmony_ci    std::vector<binder::Variable *> findRes;
10503af6ab5fSopenharmony_ci
10513af6ab5fSopenharmony_ci    auto currentScope = scope;
10523af6ab5fSopenharmony_ci    while (currentScope != nullptr) {
10533af6ab5fSopenharmony_ci        // Find ts variables
10543af6ab5fSopenharmony_ci        auto fn = [&findRes](Variable *variable) {
10553af6ab5fSopenharmony_ci            if (variable != nullptr) {
10563af6ab5fSopenharmony_ci                findRes.emplace_back(variable);
10573af6ab5fSopenharmony_ci            }
10583af6ab5fSopenharmony_ci        };
10593af6ab5fSopenharmony_ci
10603af6ab5fSopenharmony_ci        fn(currentScope->FindLocalTSVariable<binder::TSBindingType::NAMESPACE>(name));
10613af6ab5fSopenharmony_ci        fn(currentScope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(name));
10623af6ab5fSopenharmony_ci        fn(currentScope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name));
10633af6ab5fSopenharmony_ci        if (currentScope->IsTSModuleScope()) {
10643af6ab5fSopenharmony_ci            fn(currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name));
10653af6ab5fSopenharmony_ci            fn(currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::ENUMLITERAL>(name));
10663af6ab5fSopenharmony_ci            fn(currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name));
10673af6ab5fSopenharmony_ci        }
10683af6ab5fSopenharmony_ci
10693af6ab5fSopenharmony_ci        // Find js variable
10703af6ab5fSopenharmony_ci        if (currentScope->FindLocal(name, bindingOptions_) != nullptr) {
10713af6ab5fSopenharmony_ci            res = scope->Find(name, bindingOptions_);
10723af6ab5fSopenharmony_ci            break;
10733af6ab5fSopenharmony_ci        }
10743af6ab5fSopenharmony_ci
10753af6ab5fSopenharmony_ci        if (!findRes.empty()) {
10763af6ab5fSopenharmony_ci            break;
10773af6ab5fSopenharmony_ci        }
10783af6ab5fSopenharmony_ci
10793af6ab5fSopenharmony_ci        currentScope = currentScope->Parent();
10803af6ab5fSopenharmony_ci    }
10813af6ab5fSopenharmony_ci
10823af6ab5fSopenharmony_ci    return findRes;
10833af6ab5fSopenharmony_ci}
10843af6ab5fSopenharmony_ci
10853af6ab5fSopenharmony_civoid Binder::ReplaceConstReferenceWithInitialization(const ir::Identifier *ident, const Decl *decl)
10863af6ab5fSopenharmony_ci{
10873af6ab5fSopenharmony_ci    bool isValidAssignmentExpr = ident->Parent()->IsAssignmentExpression() &&
10883af6ab5fSopenharmony_ci        ident->Parent()->AsAssignmentExpression()->Right() == ident;
10893af6ab5fSopenharmony_ci    bool isBinaryExpr = ident->Parent()->IsBinaryExpression();
10903af6ab5fSopenharmony_ci    bool isVariableDecl = ident->Parent()->IsVariableDeclarator() &&
10913af6ab5fSopenharmony_ci        ident->Parent()->AsVariableDeclarator()->Init() == ident;
10923af6ab5fSopenharmony_ci    if (!isValidAssignmentExpr && !isBinaryExpr && !isVariableDecl) {
10933af6ab5fSopenharmony_ci        return;
10943af6ab5fSopenharmony_ci    }
10953af6ab5fSopenharmony_ci
10963af6ab5fSopenharmony_ci    if (decl->Node() == nullptr || decl->Node()->Parent() == nullptr ||
10973af6ab5fSopenharmony_ci        !decl->Node()->Parent()->IsVariableDeclarator()) {
10983af6ab5fSopenharmony_ci        return;
10993af6ab5fSopenharmony_ci    }
11003af6ab5fSopenharmony_ci
11013af6ab5fSopenharmony_ci    const ir::AstNode *initialization = static_cast<const ir::AstNode *>(
11023af6ab5fSopenharmony_ci        decl->Node()->Parent()->AsVariableDeclarator()->Init());
11033af6ab5fSopenharmony_ci    if (initialization == nullptr || !initialization->IsNumberLiteral()) {
11043af6ab5fSopenharmony_ci        return;
11053af6ab5fSopenharmony_ci    }
11063af6ab5fSopenharmony_ci
11073af6ab5fSopenharmony_ci    auto newNode = Allocator()->New<ir::NumberLiteral>(initialization->AsNumberLiteral()->Number());
11083af6ab5fSopenharmony_ci    if (newNode == nullptr) {
11093af6ab5fSopenharmony_ci        throw Error(ErrorType::GENERIC, "Unsuccessful allocation during replacing const reference node");
11103af6ab5fSopenharmony_ci    }
11113af6ab5fSopenharmony_ci    // Make sure the new node get the correct line number
11123af6ab5fSopenharmony_ci    // Column number may be incorrect, but it doesn't matter in release mode
11133af6ab5fSopenharmony_ci    newNode->SetRange(ident->Range());
11143af6ab5fSopenharmony_ci
11153af6ab5fSopenharmony_ci    auto *parentNode = const_cast<panda::es2panda::ir::AstNode *>(ident->Parent());
11163af6ab5fSopenharmony_ci    // update the reference node with initialization node
11173af6ab5fSopenharmony_ci    parentNode->UpdateSelf([=](auto *childNode) {
11183af6ab5fSopenharmony_ci            if (childNode == ident) {
11193af6ab5fSopenharmony_ci                return static_cast<ir::AstNode *>(newNode);
11203af6ab5fSopenharmony_ci            }
11213af6ab5fSopenharmony_ci            return childNode;
11223af6ab5fSopenharmony_ci        }, this);
11233af6ab5fSopenharmony_ci}
11243af6ab5fSopenharmony_ci
11253af6ab5fSopenharmony_civoid Binder::CheckPrivateDeclaration(const ir::PrivateIdentifier *privateIdent)
11263af6ab5fSopenharmony_ci{
11273af6ab5fSopenharmony_ci    auto name = privateIdent->Name();
11283af6ab5fSopenharmony_ci    auto scope = scope_;
11293af6ab5fSopenharmony_ci    while (scope != nullptr) {
11303af6ab5fSopenharmony_ci        if (scope->Type() == ScopeType::CLASS) {
11313af6ab5fSopenharmony_ci            const auto *classScope = scope->AsClassScope();
11323af6ab5fSopenharmony_ci            if (classScope->HasPrivateName(name)) {
11333af6ab5fSopenharmony_ci                return;
11343af6ab5fSopenharmony_ci            }
11353af6ab5fSopenharmony_ci        }
11363af6ab5fSopenharmony_ci        scope = scope->Parent();
11373af6ab5fSopenharmony_ci    }
11383af6ab5fSopenharmony_ci
11393af6ab5fSopenharmony_ci    auto pos = privateIdent->Start();
11403af6ab5fSopenharmony_ci    lexer::LineIndex index(program_->SourceCode());
11413af6ab5fSopenharmony_ci    lexer::SourceLocation loc = index.GetLocation(pos);
11423af6ab5fSopenharmony_ci
11433af6ab5fSopenharmony_ci    throw Error{ErrorType::SYNTAX, "Use private property before declaration", loc.line, loc.col};
11443af6ab5fSopenharmony_ci}
11453af6ab5fSopenharmony_ci
11463af6ab5fSopenharmony_ciClassTdz::ClassTdz(const ir::AstNode *parent, const ir::AstNode *childNode, Scope *scope)
11473af6ab5fSopenharmony_ci{
11483af6ab5fSopenharmony_ci    /* In ES2022, class element name's evaluation is before class's initialization.
11493af6ab5fSopenharmony_ci     * So a computed property name can not access class object which leads to a reference error.
11503af6ab5fSopenharmony_ci     * For example:
11513af6ab5fSopenharmony_ci     * class A {
11523af6ab5fSopenharmony_ci     *   [A]
11533af6ab5fSopenharmony_ci     * }
11543af6ab5fSopenharmony_ci     */
11553af6ab5fSopenharmony_ci    bool isClassTdz = (parent->IsClassProperty() && childNode == parent->AsClassProperty()->Key()) ||
11563af6ab5fSopenharmony_ci        (parent->IsMethodDefinition() && childNode == parent->AsMethodDefinition()->Key());
11573af6ab5fSopenharmony_ci    if (!isClassTdz) {
11583af6ab5fSopenharmony_ci        return;
11593af6ab5fSopenharmony_ci    }
11603af6ab5fSopenharmony_ci
11613af6ab5fSopenharmony_ci    ASSERT(parent->Parent()->IsClassDefinition());
11623af6ab5fSopenharmony_ci    auto classDef = parent->Parent()->AsClassDefinition();
11633af6ab5fSopenharmony_ci    if (!classDef->Ident()) {
11643af6ab5fSopenharmony_ci        return;
11653af6ab5fSopenharmony_ci    }
11663af6ab5fSopenharmony_ci
11673af6ab5fSopenharmony_ci    ScopeFindResult res = scope->Find(classDef->Ident()->Name());
11683af6ab5fSopenharmony_ci    ASSERT(res.variable && res.variable->Declaration()->IsConstDecl());
11693af6ab5fSopenharmony_ci    variable_ = res.variable;
11703af6ab5fSopenharmony_ci    variable_->RemoveFlag(VariableFlags::INITIALIZED);
11713af6ab5fSopenharmony_ci}
11723af6ab5fSopenharmony_ci
11733af6ab5fSopenharmony_ci}  // namespace panda::es2panda::binder
1174