13af6ab5fSopenharmony_ci/*
23af6ab5fSopenharmony_ci * Copyright (c) 2021-2024 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 <utility>
173af6ab5fSopenharmony_ci#include "checker/ETSchecker.h"
183af6ab5fSopenharmony_ci
193af6ab5fSopenharmony_ci#include "compiler/lowering/util.h"
203af6ab5fSopenharmony_ci#include "varbinder/declaration.h"
213af6ab5fSopenharmony_ci#include "varbinder/varbinder.h"
223af6ab5fSopenharmony_ci#include "varbinder/ETSBinder.h"
233af6ab5fSopenharmony_ci#include "checker/types/ets/etsDynamicFunctionType.h"
243af6ab5fSopenharmony_ci#include "checker/ets/dynamic/dynamicCall.h"
253af6ab5fSopenharmony_ci#include "compiler/lowering/scopesInit/scopesInitPhase.h"
263af6ab5fSopenharmony_ci#include "ir/base/classProperty.h"
273af6ab5fSopenharmony_ci#include "ir/base/classStaticBlock.h"
283af6ab5fSopenharmony_ci#include "ir/base/methodDefinition.h"
293af6ab5fSopenharmony_ci#include "ir/base/scriptFunction.h"
303af6ab5fSopenharmony_ci#include "ir/expressions/assignmentExpression.h"
313af6ab5fSopenharmony_ci#include "ir/expressions/callExpression.h"
323af6ab5fSopenharmony_ci#include "ir/expressions/functionExpression.h"
333af6ab5fSopenharmony_ci#include "ir/expressions/identifier.h"
343af6ab5fSopenharmony_ci#include "ir/expressions/thisExpression.h"
353af6ab5fSopenharmony_ci#include "ir/expressions/memberExpression.h"
363af6ab5fSopenharmony_ci#include "ir/ets/etsPrimitiveType.h"
373af6ab5fSopenharmony_ci#include "ir/ts/tsAsExpression.h"
383af6ab5fSopenharmony_ci#include "ir/statements/blockStatement.h"
393af6ab5fSopenharmony_ci#include "ir/statements/classDeclaration.h"
403af6ab5fSopenharmony_ci#include "ir/statements/expressionStatement.h"
413af6ab5fSopenharmony_ci#include "ir/statements/returnStatement.h"
423af6ab5fSopenharmony_ci#include "parser/program/program.h"
433af6ab5fSopenharmony_ci#include "util/helpers.h"
443af6ab5fSopenharmony_ci#include "util/language.h"
453af6ab5fSopenharmony_ci#include "generated/signatures.h"
463af6ab5fSopenharmony_ci#include "ir/ets/etsParameterExpression.h"
473af6ab5fSopenharmony_ci
483af6ab5fSopenharmony_cinamespace ark::es2panda::checker {
493af6ab5fSopenharmony_ci
503af6ab5fSopenharmony_civoid ProcessCheckerNode(ETSChecker *checker, ir::AstNode *node)
513af6ab5fSopenharmony_ci{
523af6ab5fSopenharmony_ci    auto scope = compiler::NearestScope(node);
533af6ab5fSopenharmony_ci    if (scope->IsGlobalScope()) {
543af6ab5fSopenharmony_ci        // NOTE(aleksisch): All classes are contained in ETSGlobal class scope (not just Global scope),
553af6ab5fSopenharmony_ci        // however it's parent is ETSScript. It should be fixed
563af6ab5fSopenharmony_ci        scope = checker->VarBinder()->Program()->GlobalClassScope();
573af6ab5fSopenharmony_ci    }
583af6ab5fSopenharmony_ci
593af6ab5fSopenharmony_ci    auto expressionCtx = varbinder::LexicalScope<varbinder::Scope>::Enter(checker->VarBinder(), scope);
603af6ab5fSopenharmony_ci    checker->VarBinder()->AsETSBinder()->ResolveReference(node);
613af6ab5fSopenharmony_ci
623af6ab5fSopenharmony_ci    if (node->IsMethodDefinition()) {
633af6ab5fSopenharmony_ci        // NOTE(aleksisch): This should be done in varbinder,
643af6ab5fSopenharmony_ci        // however right now checker do it when called on ClassDefinition
653af6ab5fSopenharmony_ci        auto method = node->AsMethodDefinition();
663af6ab5fSopenharmony_ci        auto func = method->Value()->AsFunctionExpression()->Function();
673af6ab5fSopenharmony_ci        func->Id()->SetVariable(method->Id()->Variable());
683af6ab5fSopenharmony_ci    }
693af6ab5fSopenharmony_ci    ScopeContext checkerScope(checker, scope);
703af6ab5fSopenharmony_ci    node->Check(checker);
713af6ab5fSopenharmony_ci}
723af6ab5fSopenharmony_ci
733af6ab5fSopenharmony_civoid ProcessScopesNode(ETSChecker *checker, ir::AstNode *node)
743af6ab5fSopenharmony_ci{
753af6ab5fSopenharmony_ci    auto *scope = compiler::NearestScope(node);
763af6ab5fSopenharmony_ci    if (scope->IsGlobalScope()) {
773af6ab5fSopenharmony_ci        // NOTE(aleksisch): All classes are contained in ETSGlobal scope,
783af6ab5fSopenharmony_ci        // however it's parent is ETSScript (not ETSGlobal). It should be fixed
793af6ab5fSopenharmony_ci        scope = checker->VarBinder()->Program()->GlobalClassScope();
803af6ab5fSopenharmony_ci    }
813af6ab5fSopenharmony_ci    auto expressionCtx = varbinder::LexicalScope<varbinder::Scope>::Enter(checker->VarBinder(), scope);
823af6ab5fSopenharmony_ci    compiler::InitScopesPhaseETS::RunExternalNode(node, checker->VarBinder());
833af6ab5fSopenharmony_ci}
843af6ab5fSopenharmony_ci
853af6ab5fSopenharmony_ciir::ETSParameterExpression *ETSChecker::AddParam(util::StringView name, ir::TypeNode *type)
863af6ab5fSopenharmony_ci{
873af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
883af6ab5fSopenharmony_ci    auto *paramIdent = AllocNode<ir::Identifier>(name, Allocator());
893af6ab5fSopenharmony_ci    if (type != nullptr) {
903af6ab5fSopenharmony_ci        paramIdent->SetTsTypeAnnotation(type);
913af6ab5fSopenharmony_ci        type->SetParent(paramIdent);
923af6ab5fSopenharmony_ci    }
933af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
943af6ab5fSopenharmony_ci    return AllocNode<ir::ETSParameterExpression>(paramIdent, nullptr);
953af6ab5fSopenharmony_ci}
963af6ab5fSopenharmony_ci
973af6ab5fSopenharmony_citemplate <typename T>
983af6ab5fSopenharmony_ciir::MethodDefinition *ETSChecker::CreateDynamicCallIntrinsic(ir::Expression *callee, const ArenaVector<T *> &arguments,
993af6ab5fSopenharmony_ci                                                             Language lang)
1003af6ab5fSopenharmony_ci{
1013af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> params(Allocator()->Adapter());
1023af6ab5fSopenharmony_ci
1033af6ab5fSopenharmony_ci    auto dynamicTypeNode = AllocNode<ir::OpaqueTypeNode>(GlobalBuiltinDynamicType(lang));
1043af6ab5fSopenharmony_ci    auto intTypeNode = AllocNode<ir::ETSPrimitiveType>(ir::PrimitiveType::INT);
1053af6ab5fSopenharmony_ci
1063af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1073af6ab5fSopenharmony_ci    auto *objParam = AddParam("obj", dynamicTypeNode);
1083af6ab5fSopenharmony_ci    params.push_back(objParam);
1093af6ab5fSopenharmony_ci
1103af6ab5fSopenharmony_ci    ir::ETSParameterExpression *param2;
1113af6ab5fSopenharmony_ci    if (!DynamicCall::IsByValue(VarBinder()->AsETSBinder(), callee)) {
1123af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1133af6ab5fSopenharmony_ci        param2 = AddParam("qname_start", intTypeNode);
1143af6ab5fSopenharmony_ci        params.push_back(param2);
1153af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1163af6ab5fSopenharmony_ci        param2 = AddParam("qname_len", intTypeNode->Clone(Allocator(), nullptr));
1173af6ab5fSopenharmony_ci    } else {
1183af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1193af6ab5fSopenharmony_ci        param2 = AddParam("this", dynamicTypeNode->Clone(Allocator(), nullptr));
1203af6ab5fSopenharmony_ci    }
1213af6ab5fSopenharmony_ci
1223af6ab5fSopenharmony_ci    params.push_back(param2);
1233af6ab5fSopenharmony_ci
1243af6ab5fSopenharmony_ci    for (size_t i = 0; i < arguments.size(); i++) {
1253af6ab5fSopenharmony_ci        util::UString paramName("p" + std::to_string(i), Allocator());
1263af6ab5fSopenharmony_ci        auto paramType = arguments[i]->TsType()->IsLambdaObject()
1273af6ab5fSopenharmony_ci                             ? dynamicTypeNode->Clone(Allocator(), nullptr)
1283af6ab5fSopenharmony_ci                             : AllocNode<ir::OpaqueTypeNode>(arguments[i]->TsType());
1293af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1303af6ab5fSopenharmony_ci        params.emplace_back(AddParam(paramName.View(), paramType));
1313af6ab5fSopenharmony_ci    }
1323af6ab5fSopenharmony_ci
1333af6ab5fSopenharmony_ci    auto funcSignature =
1343af6ab5fSopenharmony_ci        ir::FunctionSignature(nullptr, std::move(params), dynamicTypeNode->Clone(Allocator(), nullptr));
1353af6ab5fSopenharmony_ci    auto *func = AllocNode<ir::ScriptFunction>(
1363af6ab5fSopenharmony_ci        Allocator(), ir::ScriptFunction::ScriptFunctionData {nullptr, std::move(funcSignature),
1373af6ab5fSopenharmony_ci                                                             ir::ScriptFunctionFlags::METHOD, ir::ModifierFlags::NONE});
1383af6ab5fSopenharmony_ci
1393af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1403af6ab5fSopenharmony_ci    auto *name = AllocNode<ir::Identifier>("invoke", Allocator());
1413af6ab5fSopenharmony_ci    func->SetIdent(name);
1423af6ab5fSopenharmony_ci
1433af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1443af6ab5fSopenharmony_ci    auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
1453af6ab5fSopenharmony_ci
1463af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1473af6ab5fSopenharmony_ci    auto *method = AllocNode<ir::MethodDefinition>(
1483af6ab5fSopenharmony_ci        ir::MethodDefinitionKind::METHOD, func->Id()->Clone(Allocator(), nullptr), funcExpr,
1493af6ab5fSopenharmony_ci        ir::ModifierFlags::PUBLIC | ir::ModifierFlags::NATIVE | ir::ModifierFlags::STATIC, Allocator(), false);
1503af6ab5fSopenharmony_ci    return method;
1513af6ab5fSopenharmony_ci}
1523af6ab5fSopenharmony_ci
1533af6ab5fSopenharmony_cistatic void ToString(ETSChecker *checker, const ArenaVector<ir::Expression *> &arguments, std::stringstream &ss)
1543af6ab5fSopenharmony_ci{
1553af6ab5fSopenharmony_ci    for (auto *arg : arguments) {
1563af6ab5fSopenharmony_ci        auto *type = arg->Check(checker);
1573af6ab5fSopenharmony_ci        ss << "-";
1583af6ab5fSopenharmony_ci        type->ToString(ss);
1593af6ab5fSopenharmony_ci    }
1603af6ab5fSopenharmony_ci}
1613af6ab5fSopenharmony_ci
1623af6ab5fSopenharmony_cistatic void ToString([[maybe_unused]] ETSChecker *checker, const ArenaVector<varbinder::LocalVariable *> &arguments,
1633af6ab5fSopenharmony_ci                     std::stringstream &ss)
1643af6ab5fSopenharmony_ci{
1653af6ab5fSopenharmony_ci    for (auto *arg : arguments) {
1663af6ab5fSopenharmony_ci        auto *type = arg->TsType();
1673af6ab5fSopenharmony_ci        ss << "-";
1683af6ab5fSopenharmony_ci        type->ToString(ss);
1693af6ab5fSopenharmony_ci    }
1703af6ab5fSopenharmony_ci}
1713af6ab5fSopenharmony_ci
1723af6ab5fSopenharmony_citemplate <typename T>
1733af6ab5fSopenharmony_ciSignature *ETSChecker::ResolveDynamicCallExpression(ir::Expression *callee, const ArenaVector<T *> &arguments,
1743af6ab5fSopenharmony_ci                                                    Language lang, bool isConstruct)
1753af6ab5fSopenharmony_ci{
1763af6ab5fSopenharmony_ci    auto &dynamicIntrinsics = *DynamicCallIntrinsics(isConstruct);
1773af6ab5fSopenharmony_ci
1783af6ab5fSopenharmony_ci    auto mapIt = dynamicIntrinsics.find(lang);
1793af6ab5fSopenharmony_ci    if (mapIt == dynamicIntrinsics.cend()) {
1803af6ab5fSopenharmony_ci        std::tie(mapIt, std::ignore) = dynamicIntrinsics.emplace(lang, Allocator()->Adapter());
1813af6ab5fSopenharmony_ci    }
1823af6ab5fSopenharmony_ci
1833af6ab5fSopenharmony_ci    auto &map = mapIt->second;
1843af6ab5fSopenharmony_ci
1853af6ab5fSopenharmony_ci    std::stringstream ss;
1863af6ab5fSopenharmony_ci    ss << "dyncall";
1873af6ab5fSopenharmony_ci    if (DynamicCall::IsByValue(VarBinder()->AsETSBinder(), callee)) {
1883af6ab5fSopenharmony_ci        ss << "-byvalue";
1893af6ab5fSopenharmony_ci    } else {
1903af6ab5fSopenharmony_ci        const auto callNames = DynamicCall::ResolveCall(VarBinder()->AsETSBinder(), callee);
1913af6ab5fSopenharmony_ci        DynamicCallNames(isConstruct)->try_emplace(callNames.name, 0);
1923af6ab5fSopenharmony_ci    }
1933af6ab5fSopenharmony_ci
1943af6ab5fSopenharmony_ci    ToString(this, arguments, ss);
1953af6ab5fSopenharmony_ci
1963af6ab5fSopenharmony_ci    auto key = ss.str();
1973af6ab5fSopenharmony_ci    auto it = map.find(util::StringView(key));
1983af6ab5fSopenharmony_ci    if (it == map.end()) {
1993af6ab5fSopenharmony_ci        auto klass = GetDynamicClass(lang, isConstruct);
2003af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
2013af6ab5fSopenharmony_ci        auto *method = CreateDynamicCallIntrinsic(callee, arguments, lang);
2023af6ab5fSopenharmony_ci        auto props = ArenaVector<ir::AstNode *>(Allocator()->Adapter());
2033af6ab5fSopenharmony_ci        props.emplace_back(method);
2043af6ab5fSopenharmony_ci        klass->Definition()->AddProperties(std::move(props));
2053af6ab5fSopenharmony_ci
2063af6ab5fSopenharmony_ci        {
2073af6ab5fSopenharmony_ci            auto prevClass = VarBinder()->AsETSBinder()->GetGlobalRecordTable()->ClassDefinition();
2083af6ab5fSopenharmony_ci            VarBinder()->AsETSBinder()->GetGlobalRecordTable()->SetClassDefinition(klass->Definition());
2093af6ab5fSopenharmony_ci            ProcessScopesNode(this, method);
2103af6ab5fSopenharmony_ci            ProcessCheckerNode(this, method);
2113af6ab5fSopenharmony_ci            VarBinder()->AsETSBinder()->GetGlobalRecordTable()->SetClassDefinition(prevClass);
2123af6ab5fSopenharmony_ci        }
2133af6ab5fSopenharmony_ci        method->Function()->Signature()->SetReturnType(GlobalBuiltinDynamicType(lang));
2143af6ab5fSopenharmony_ci
2153af6ab5fSopenharmony_ci        map.emplace(util::UString(key, Allocator()).View(), method->Function());
2163af6ab5fSopenharmony_ci        return method->Function()->Signature();
2173af6ab5fSopenharmony_ci    }
2183af6ab5fSopenharmony_ci
2193af6ab5fSopenharmony_ci    return it->second->Signature();
2203af6ab5fSopenharmony_ci}
2213af6ab5fSopenharmony_ci
2223af6ab5fSopenharmony_citemplate Signature *ETSChecker::ResolveDynamicCallExpression<ir::Expression>(
2233af6ab5fSopenharmony_ci    ir::Expression *callee, const ArenaVector<ir::Expression *> &arguments, Language lang, bool isConstruct);
2243af6ab5fSopenharmony_ci
2253af6ab5fSopenharmony_citemplate Signature *ETSChecker::ResolveDynamicCallExpression<varbinder::LocalVariable>(
2263af6ab5fSopenharmony_ci    ir::Expression *callee, const ArenaVector<varbinder::LocalVariable *> &arguments, Language lang, bool isConstruct);
2273af6ab5fSopenharmony_ci
2283af6ab5fSopenharmony_cistd::pair<ir::ScriptFunction *, ir::Identifier *> ETSChecker::CreateStaticScriptFunction(
2293af6ab5fSopenharmony_ci    ClassInitializerBuilder const &builder)
2303af6ab5fSopenharmony_ci{
2313af6ab5fSopenharmony_ci    ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
2323af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> params(Allocator()->Adapter());
2333af6ab5fSopenharmony_ci
2343af6ab5fSopenharmony_ci    ir::ScriptFunction *func;
2353af6ab5fSopenharmony_ci    ir::Identifier *id;
2363af6ab5fSopenharmony_ci
2373af6ab5fSopenharmony_ci    builder(&statements, nullptr);
2383af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
2393af6ab5fSopenharmony_ci    auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
2403af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
2413af6ab5fSopenharmony_ci    id = AllocNode<ir::Identifier>(compiler::Signatures::CCTOR, Allocator());
2423af6ab5fSopenharmony_ci    auto signature = ir::FunctionSignature(nullptr, std::move(params), nullptr);
2433af6ab5fSopenharmony_ci    // clang-format off
2443af6ab5fSopenharmony_ci    func = AllocNode<ir::ScriptFunction>(
2453af6ab5fSopenharmony_ci        Allocator(), ir::ScriptFunction::ScriptFunctionData {
2463af6ab5fSopenharmony_ci                        body,
2473af6ab5fSopenharmony_ci                        std::move(signature),
2483af6ab5fSopenharmony_ci                        ir::ScriptFunctionFlags::STATIC_BLOCK | ir::ScriptFunctionFlags::EXPRESSION,
2493af6ab5fSopenharmony_ci                        ir::ModifierFlags::STATIC,
2503af6ab5fSopenharmony_ci                     });
2513af6ab5fSopenharmony_ci    // clang-format on
2523af6ab5fSopenharmony_ci    func->SetIdent(id);
2533af6ab5fSopenharmony_ci
2543af6ab5fSopenharmony_ci    return std::make_pair(func, id);
2553af6ab5fSopenharmony_ci}
2563af6ab5fSopenharmony_ci
2573af6ab5fSopenharmony_cistd::pair<ir::ScriptFunction *, ir::Identifier *> ETSChecker::CreateScriptFunction(
2583af6ab5fSopenharmony_ci    ClassInitializerBuilder const &builder)
2593af6ab5fSopenharmony_ci{
2603af6ab5fSopenharmony_ci    ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
2613af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> params(Allocator()->Adapter());
2623af6ab5fSopenharmony_ci
2633af6ab5fSopenharmony_ci    ir::ScriptFunction *func;
2643af6ab5fSopenharmony_ci    ir::Identifier *id;
2653af6ab5fSopenharmony_ci
2663af6ab5fSopenharmony_ci    builder(&statements, &params);
2673af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
2683af6ab5fSopenharmony_ci    auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
2693af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
2703af6ab5fSopenharmony_ci    id = AllocNode<ir::Identifier>(compiler::Signatures::CTOR, Allocator());
2713af6ab5fSopenharmony_ci    auto funcSignature = ir::FunctionSignature(nullptr, std::move(params), nullptr);
2723af6ab5fSopenharmony_ci    func = AllocNode<ir::ScriptFunction>(Allocator(),
2733af6ab5fSopenharmony_ci                                         ir::ScriptFunction::ScriptFunctionData {
2743af6ab5fSopenharmony_ci                                             body, std::move(funcSignature),
2753af6ab5fSopenharmony_ci                                             ir::ScriptFunctionFlags::CONSTRUCTOR | ir::ScriptFunctionFlags::EXPRESSION,
2763af6ab5fSopenharmony_ci                                             ir::ModifierFlags::PUBLIC});
2773af6ab5fSopenharmony_ci    func->SetIdent(id);
2783af6ab5fSopenharmony_ci
2793af6ab5fSopenharmony_ci    return std::make_pair(func, id);
2803af6ab5fSopenharmony_ci}
2813af6ab5fSopenharmony_ci
2823af6ab5fSopenharmony_ciir::ClassStaticBlock *ETSChecker::CreateClassStaticInitializer(const ClassInitializerBuilder &builder,
2833af6ab5fSopenharmony_ci                                                               [[maybe_unused]] ETSObjectType *type)
2843af6ab5fSopenharmony_ci{
2853af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
2863af6ab5fSopenharmony_ci    auto [func, id] = CreateStaticScriptFunction(builder);
2873af6ab5fSopenharmony_ci
2883af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
2893af6ab5fSopenharmony_ci    auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
2903af6ab5fSopenharmony_ci
2913af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
2923af6ab5fSopenharmony_ci    auto *staticBlock = AllocNode<ir::ClassStaticBlock>(funcExpr, Allocator());
2933af6ab5fSopenharmony_ci    staticBlock->AddModifier(ir::ModifierFlags::STATIC);
2943af6ab5fSopenharmony_ci
2953af6ab5fSopenharmony_ci    return staticBlock;
2963af6ab5fSopenharmony_ci}
2973af6ab5fSopenharmony_ci
2983af6ab5fSopenharmony_ciir::MethodDefinition *ETSChecker::CreateClassInstanceInitializer(const ClassInitializerBuilder &builder,
2993af6ab5fSopenharmony_ci                                                                 [[maybe_unused]] ETSObjectType *type)
3003af6ab5fSopenharmony_ci{
3013af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
3023af6ab5fSopenharmony_ci    auto [func, id] = CreateScriptFunction(builder);
3033af6ab5fSopenharmony_ci
3043af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
3053af6ab5fSopenharmony_ci    auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
3063af6ab5fSopenharmony_ci
3073af6ab5fSopenharmony_ci    auto *ctor =
3083af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
3093af6ab5fSopenharmony_ci        AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::CONSTRUCTOR, id->Clone(Allocator(), nullptr),
3103af6ab5fSopenharmony_ci                                        funcExpr, ir::ModifierFlags::NONE, Allocator(), false);
3113af6ab5fSopenharmony_ci    return ctor;
3123af6ab5fSopenharmony_ci}
3133af6ab5fSopenharmony_ci
3143af6ab5fSopenharmony_ciir::ClassStaticBlock *ETSChecker::CreateDynamicCallClassInitializer(Language lang, bool isConstruct)
3153af6ab5fSopenharmony_ci{
3163af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
3173af6ab5fSopenharmony_ci    return CreateClassStaticInitializer([this, lang,
3183af6ab5fSopenharmony_ci                                         isConstruct](ArenaVector<ir::Statement *> *statements,
3193af6ab5fSopenharmony_ci                                                      [[maybe_unused]] ArenaVector<ir::Expression *> *params) {
3203af6ab5fSopenharmony_ci        auto [builtin_class_name, builtin_method_name] =
3213af6ab5fSopenharmony_ci            util::Helpers::SplitSignature(isConstruct ? compiler::Signatures::Dynamic::InitNewClassBuiltin(lang)
3223af6ab5fSopenharmony_ci                                                      : compiler::Signatures::Dynamic::InitCallClassBuiltin(lang));
3233af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
3243af6ab5fSopenharmony_ci        auto *classId = AllocNode<ir::Identifier>(builtin_class_name, Allocator());
3253af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
3263af6ab5fSopenharmony_ci        auto *methodId = AllocNode<ir::Identifier>(builtin_method_name, Allocator());
3273af6ab5fSopenharmony_ci        methodId->SetReference();
3283af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
3293af6ab5fSopenharmony_ci        auto *callee =
3303af6ab5fSopenharmony_ci            AllocNode<ir::MemberExpression>(classId, methodId, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false);
3313af6ab5fSopenharmony_ci
3323af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
3333af6ab5fSopenharmony_ci        auto *initCall = AllocNode<ir::CallExpression>(callee, ArenaVector<ir::Expression *>(Allocator()->Adapter()),
3343af6ab5fSopenharmony_ci                                                       nullptr, false);
3353af6ab5fSopenharmony_ci
3363af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
3373af6ab5fSopenharmony_ci        statements->push_back(AllocNode<ir::ExpressionStatement>(initCall));
3383af6ab5fSopenharmony_ci    });
3393af6ab5fSopenharmony_ci}
3403af6ab5fSopenharmony_ci
3413af6ab5fSopenharmony_ciir::ClassDeclaration *ETSChecker::BuildClass(util::StringView name, const ClassBuilder &builder)
3423af6ab5fSopenharmony_ci{
3433af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
3443af6ab5fSopenharmony_ci    auto *classId = AllocNode<ir::Identifier>(name, Allocator());
3453af6ab5fSopenharmony_ci
3463af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
3473af6ab5fSopenharmony_ci    auto *classDef = AllocNode<ir::ClassDefinition>(Allocator(), classId, ir::ClassDefinitionModifiers::CLASS_DECL,
3483af6ab5fSopenharmony_ci                                                    ir::ModifierFlags::NONE, Language(Language::Id::ETS));
3493af6ab5fSopenharmony_ci
3503af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
3513af6ab5fSopenharmony_ci    auto *classDecl = AllocNode<ir::ClassDeclaration>(classDef, Allocator());
3523af6ab5fSopenharmony_ci
3533af6ab5fSopenharmony_ci    VarBinder()->Program()->Ast()->Statements().push_back(classDecl);
3543af6ab5fSopenharmony_ci    classDecl->SetParent(VarBinder()->Program()->Ast());
3553af6ab5fSopenharmony_ci
3563af6ab5fSopenharmony_ci    varbinder::BoundContext boundCtx(VarBinder()->AsETSBinder()->GetGlobalRecordTable(), classDef);
3573af6ab5fSopenharmony_ci
3583af6ab5fSopenharmony_ci    ArenaVector<ir::AstNode *> classBody(Allocator()->Adapter());
3593af6ab5fSopenharmony_ci
3603af6ab5fSopenharmony_ci    builder(&classBody);
3613af6ab5fSopenharmony_ci
3623af6ab5fSopenharmony_ci    classDef->AddProperties(std::move(classBody));
3633af6ab5fSopenharmony_ci
3643af6ab5fSopenharmony_ci    ProcessScopesNode(this, classDecl);
3653af6ab5fSopenharmony_ci    ProcessCheckerNode(this, classDecl);
3663af6ab5fSopenharmony_ci    return classDecl;
3673af6ab5fSopenharmony_ci}
3683af6ab5fSopenharmony_ci
3693af6ab5fSopenharmony_ciir::ClassProperty *ETSChecker::CreateStaticReadonlyField(const char *name)
3703af6ab5fSopenharmony_ci{
3713af6ab5fSopenharmony_ci    auto *fieldIdent = AllocNode<ir::Identifier>(name, Allocator());
3723af6ab5fSopenharmony_ci    // NOTE: remove const when readonly is properly supported
3733af6ab5fSopenharmony_ci    auto flags =
3743af6ab5fSopenharmony_ci        ir::ModifierFlags::STATIC | ir::ModifierFlags::PRIVATE | ir::ModifierFlags::READONLY | ir::ModifierFlags::CONST;
3753af6ab5fSopenharmony_ci    auto *field = AllocNode<ir::ClassProperty>(
3763af6ab5fSopenharmony_ci        fieldIdent, nullptr, AllocNode<ir::ETSPrimitiveType>(ir::PrimitiveType::INT), flags, Allocator(), false);
3773af6ab5fSopenharmony_ci
3783af6ab5fSopenharmony_ci    return field;
3793af6ab5fSopenharmony_ci}
3803af6ab5fSopenharmony_ci
3813af6ab5fSopenharmony_ciir::ClassDeclaration *ETSChecker::GetDynamicClass(Language lang, bool isConstruct)
3823af6ab5fSopenharmony_ci{
3833af6ab5fSopenharmony_ci    auto &klasses = dynamicClasses_[static_cast<size_t>(isConstruct)];
3843af6ab5fSopenharmony_ci    if (klasses.count(lang) != 0U) {
3853af6ab5fSopenharmony_ci        return klasses[lang];
3863af6ab5fSopenharmony_ci    }
3873af6ab5fSopenharmony_ci    auto className =
3883af6ab5fSopenharmony_ci        isConstruct ? compiler::Signatures::Dynamic::NewClass(lang) : compiler::Signatures::Dynamic::CallClass(lang);
3893af6ab5fSopenharmony_ci    auto klass = BuildClass(className, [this, lang, isConstruct](ArenaVector<ir::AstNode *> *classBody) {
3903af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
3913af6ab5fSopenharmony_ci        classBody->push_back(CreateStaticReadonlyField("qname_start_from"));
3923af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
3933af6ab5fSopenharmony_ci        classBody->push_back(CreateDynamicCallClassInitializer(lang, isConstruct));
3943af6ab5fSopenharmony_ci    });
3953af6ab5fSopenharmony_ci    klasses.emplace(lang, klass);
3963af6ab5fSopenharmony_ci    return klass;
3973af6ab5fSopenharmony_ci}
3983af6ab5fSopenharmony_ci
3993af6ab5fSopenharmony_civoid ETSChecker::ClassInitializerFromImport(ir::ETSImportDeclaration *import, ArenaVector<ir::Statement *> *statements)
4003af6ab5fSopenharmony_ci{
4013af6ab5fSopenharmony_ci    auto builtin = compiler::Signatures::Dynamic::LoadModuleBuiltin(import->Language());
4023af6ab5fSopenharmony_ci    auto [builtin_class_name, builtin_method_name] = util::Helpers::SplitSignature(builtin);
4033af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
4043af6ab5fSopenharmony_ci    auto *classId = AllocNode<ir::Identifier>(builtin_class_name, Allocator());
4053af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
4063af6ab5fSopenharmony_ci    auto *methodId = AllocNode<ir::Identifier>(builtin_method_name, Allocator());
4073af6ab5fSopenharmony_ci    methodId->SetReference();
4083af6ab5fSopenharmony_ci    auto *callee =
4093af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
4103af6ab5fSopenharmony_ci        AllocNode<ir::MemberExpression>(classId, methodId, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false);
4113af6ab5fSopenharmony_ci
4123af6ab5fSopenharmony_ci    // Note(rsipka): this check could be avoided with appropriate language extensions
4133af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> callParams(Allocator()->Adapter());
4143af6ab5fSopenharmony_ci    if (ark::os::file::File::IsRegularFile(import->ResolvedSource()->Str().Mutf8())) {
4153af6ab5fSopenharmony_ci        callParams.push_back(AllocNode<ir::StringLiteral>(
4163af6ab5fSopenharmony_ci            util::UString(ark::os::RemoveExtension(import->ResolvedSource()->Str().Mutf8()), Allocator()).View()));
4173af6ab5fSopenharmony_ci    } else {
4183af6ab5fSopenharmony_ci        callParams.push_back(import->ResolvedSource());
4193af6ab5fSopenharmony_ci    }
4203af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
4213af6ab5fSopenharmony_ci    auto *loadCall = AllocNode<ir::CallExpression>(callee, std::move(callParams), nullptr, false);
4223af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
4233af6ab5fSopenharmony_ci    auto *moduleClassId = AllocNode<ir::Identifier>(compiler::Signatures::DYNAMIC_MODULE_CLASS, Allocator());
4243af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
4253af6ab5fSopenharmony_ci    auto *fieldId = AllocNode<ir::Identifier>(import->AssemblerName(), Allocator());
4263af6ab5fSopenharmony_ci    fieldId->SetReference();
4273af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
4283af6ab5fSopenharmony_ci    auto *property = AllocNode<ir::MemberExpression>(moduleClassId, fieldId, ir::MemberExpressionKind::PROPERTY_ACCESS,
4293af6ab5fSopenharmony_ci                                                     false, false);
4303af6ab5fSopenharmony_ci
4313af6ab5fSopenharmony_ci    auto *initializer =
4323af6ab5fSopenharmony_ci        AllocNode<ir::AssignmentExpression>(property, loadCall, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
4333af6ab5fSopenharmony_ci    statements->push_back(AllocNode<ir::ExpressionStatement>(initializer));
4343af6ab5fSopenharmony_ci}
4353af6ab5fSopenharmony_ci
4363af6ab5fSopenharmony_ciir::ClassStaticBlock *ETSChecker::CreateDynamicModuleClassInitializer(
4373af6ab5fSopenharmony_ci    const std::vector<ir::ETSImportDeclaration *> &imports)
4383af6ab5fSopenharmony_ci{
4393af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
4403af6ab5fSopenharmony_ci    return CreateClassStaticInitializer([this, imports](ArenaVector<ir::Statement *> *statements,
4413af6ab5fSopenharmony_ci                                                        [[maybe_unused]] ArenaVector<ir::Expression *> *params) {
4423af6ab5fSopenharmony_ci        for (auto *import : imports) {
4433af6ab5fSopenharmony_ci            ClassInitializerFromImport(import, statements);
4443af6ab5fSopenharmony_ci        }
4453af6ab5fSopenharmony_ci    });
4463af6ab5fSopenharmony_ci}
4473af6ab5fSopenharmony_ci
4483af6ab5fSopenharmony_ciir::MethodDefinition *ETSChecker::CreateClassMethod(const std::string_view name, ir::ScriptFunctionFlags funcFlags,
4493af6ab5fSopenharmony_ci                                                    ir::ModifierFlags modifierFlags, const MethodBuilder &builder)
4503af6ab5fSopenharmony_ci{
4513af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> params(Allocator()->Adapter());
4523af6ab5fSopenharmony_ci    auto *id = AllocNode<ir::Identifier>(name, Allocator());
4533af6ab5fSopenharmony_ci
4543af6ab5fSopenharmony_ci    ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
4553af6ab5fSopenharmony_ci    Type *returnType = nullptr;
4563af6ab5fSopenharmony_ci
4573af6ab5fSopenharmony_ci    builder(&statements, &params, &returnType);
4583af6ab5fSopenharmony_ci
4593af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
4603af6ab5fSopenharmony_ci    auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
4613af6ab5fSopenharmony_ci    auto funcSignature = ir::FunctionSignature(
4623af6ab5fSopenharmony_ci        nullptr, std::move(params), returnType == nullptr ? nullptr : AllocNode<ir::OpaqueTypeNode>(returnType));
4633af6ab5fSopenharmony_ci    auto *func = AllocNode<ir::ScriptFunction>(
4643af6ab5fSopenharmony_ci        Allocator(), ir::ScriptFunction::ScriptFunctionData {body, std::move(funcSignature), funcFlags, modifierFlags});
4653af6ab5fSopenharmony_ci
4663af6ab5fSopenharmony_ci    func->SetIdent(id);
4673af6ab5fSopenharmony_ci
4683af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
4693af6ab5fSopenharmony_ci    auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
4703af6ab5fSopenharmony_ci    auto *method =
4713af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHt resetint)
4723af6ab5fSopenharmony_ci        AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::METHOD, func->Id()->Clone(Allocator(), nullptr),
4733af6ab5fSopenharmony_ci                                        funcExpr, modifierFlags, Allocator(), false);
4743af6ab5fSopenharmony_ci
4753af6ab5fSopenharmony_ci    return method;
4763af6ab5fSopenharmony_ci}
4773af6ab5fSopenharmony_ci
4783af6ab5fSopenharmony_ciir::MethodDefinition *ETSChecker::CreateDynamicModuleClassInitMethod()
4793af6ab5fSopenharmony_ci{
4803af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
4813af6ab5fSopenharmony_ci    return CreateClassMethod(compiler::Signatures::DYNAMIC_MODULE_CLASS_INIT, ir::ScriptFunctionFlags::METHOD,
4823af6ab5fSopenharmony_ci                             ir::ModifierFlags::PUBLIC | ir::ModifierFlags::STATIC,
4833af6ab5fSopenharmony_ci                             [this]([[maybe_unused]] ArenaVector<ir::Statement *> *statements,
4843af6ab5fSopenharmony_ci                                    [[maybe_unused]] ArenaVector<ir::Expression *> *params,
4853af6ab5fSopenharmony_ci                                    Type **returnType) { *returnType = GlobalVoidType(); });
4863af6ab5fSopenharmony_ci}
4873af6ab5fSopenharmony_ci
4883af6ab5fSopenharmony_ciir::MethodDefinition *ETSChecker::CreateLambdaObjectClassInvokeMethod(Signature *invokeSignature,
4893af6ab5fSopenharmony_ci                                                                      ir::TypeNode *retTypeAnnotation)
4903af6ab5fSopenharmony_ci{
4913af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
4923af6ab5fSopenharmony_ci    return CreateClassMethod(
4933af6ab5fSopenharmony_ci        compiler::Signatures::LAMBDA_OBJECT_INVOKE, ir::ScriptFunctionFlags::METHOD, ir::ModifierFlags::PUBLIC,
4943af6ab5fSopenharmony_ci        [this, invokeSignature, retTypeAnnotation](ArenaVector<ir::Statement *> *statements,
4953af6ab5fSopenharmony_ci                                                   ArenaVector<ir::Expression *> *params, Type **returnType) {
4963af6ab5fSopenharmony_ci            util::UString thisParamName(std::string("this"), Allocator());
4973af6ab5fSopenharmony_ci            // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
4983af6ab5fSopenharmony_ci            ir::ETSParameterExpression *thisParam = AddParam(thisParamName.View(), nullptr);
4993af6ab5fSopenharmony_ci            params->push_back(thisParam);
5003af6ab5fSopenharmony_ci
5013af6ab5fSopenharmony_ci            ArenaVector<ir::Expression *> callParams(Allocator()->Adapter());
5023af6ab5fSopenharmony_ci            for (auto *invokeParam : invokeSignature->Params()) {
5033af6ab5fSopenharmony_ci                // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
5043af6ab5fSopenharmony_ci                auto paramName =
5053af6ab5fSopenharmony_ci                    util::UString(std::string("p") + std::to_string(callParams.size()), Allocator()).View();
5063af6ab5fSopenharmony_ci                auto *param = AddParam(paramName, AllocNode<ir::OpaqueTypeNode>(invokeParam->TsType()));
5073af6ab5fSopenharmony_ci                params->push_back(param);
5083af6ab5fSopenharmony_ci                callParams.push_back(param->Clone(Allocator(), nullptr));
5093af6ab5fSopenharmony_ci            }
5103af6ab5fSopenharmony_ci
5113af6ab5fSopenharmony_ci            // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
5123af6ab5fSopenharmony_ci            auto *properyId = AllocNode<ir::Identifier>("jsvalue_lambda", Allocator());
5133af6ab5fSopenharmony_ci            // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
5143af6ab5fSopenharmony_ci            auto *callee = AllocNode<ir::MemberExpression>(thisParam->Clone(Allocator(), nullptr), properyId,
5153af6ab5fSopenharmony_ci                                                           ir::MemberExpressionKind::PROPERTY_ACCESS, false, false);
5163af6ab5fSopenharmony_ci            // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
5173af6ab5fSopenharmony_ci            auto *callLambda = AllocNode<ir::CallExpression>(callee, std::move(callParams), nullptr, false);
5183af6ab5fSopenharmony_ci
5193af6ab5fSopenharmony_ci            auto *castToRetTypeExpr =
5203af6ab5fSopenharmony_ci                // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
5213af6ab5fSopenharmony_ci                AllocNode<ir::TSAsExpression>(callLambda, retTypeAnnotation->Clone(Allocator(), nullptr), false);
5223af6ab5fSopenharmony_ci            castToRetTypeExpr->SetTsType(invokeSignature->ReturnType());
5233af6ab5fSopenharmony_ci            // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
5243af6ab5fSopenharmony_ci            auto *retStatement = AllocNode<ir::ReturnStatement>(castToRetTypeExpr);
5253af6ab5fSopenharmony_ci            statements->push_back(retStatement);
5263af6ab5fSopenharmony_ci
5273af6ab5fSopenharmony_ci            *returnType = invokeSignature->ReturnType();
5283af6ab5fSopenharmony_ci        });
5293af6ab5fSopenharmony_ci}
5303af6ab5fSopenharmony_ci
5313af6ab5fSopenharmony_civoid ETSChecker::EmitDynamicModuleClassInitCall()
5323af6ab5fSopenharmony_ci{
5333af6ab5fSopenharmony_ci    auto *globalClass = VarBinder()->Program()->GlobalClass();
5343af6ab5fSopenharmony_ci    auto &body = globalClass->Body();
5353af6ab5fSopenharmony_ci    auto it = std::find_if(body.begin(), body.end(), [](ir::AstNode *node) { return node->IsClassStaticBlock(); });
5363af6ab5fSopenharmony_ci
5373af6ab5fSopenharmony_ci    ASSERT(it != body.end());
5383af6ab5fSopenharmony_ci
5393af6ab5fSopenharmony_ci    auto *staticBlock = (*it)->AsClassStaticBlock();
5403af6ab5fSopenharmony_ci    auto *cctorBody = staticBlock->Function()->Body()->AsBlockStatement();
5413af6ab5fSopenharmony_ci
5423af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
5433af6ab5fSopenharmony_ci    auto *classId = AllocNode<ir::Identifier>(compiler::Signatures::DYNAMIC_MODULE_CLASS, Allocator());
5443af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
5453af6ab5fSopenharmony_ci    auto *methodId = AllocNode<ir::Identifier>(compiler::Signatures::DYNAMIC_MODULE_CLASS_INIT, Allocator());
5463af6ab5fSopenharmony_ci    methodId->SetReference();
5473af6ab5fSopenharmony_ci    auto *callee =
5483af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
5493af6ab5fSopenharmony_ci        AllocNode<ir::MemberExpression>(classId, methodId, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false);
5503af6ab5fSopenharmony_ci
5513af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> callParams(Allocator()->Adapter());
5523af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
5533af6ab5fSopenharmony_ci    auto *initCall = AllocNode<ir::CallExpression>(callee, std::move(callParams), nullptr, false);
5543af6ab5fSopenharmony_ci
5553af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
5563af6ab5fSopenharmony_ci    auto *const node = AllocNode<ir::ExpressionStatement>(initCall);
5573af6ab5fSopenharmony_ci    node->SetParent(cctorBody);
5583af6ab5fSopenharmony_ci    cctorBody->Statements().push_back(node);
5593af6ab5fSopenharmony_ci
5603af6ab5fSopenharmony_ci    ProcessScopesNode(this, node);
5613af6ab5fSopenharmony_ci    ProcessCheckerNode(this, node);
5623af6ab5fSopenharmony_ci}
5633af6ab5fSopenharmony_ci
5643af6ab5fSopenharmony_civoid ETSChecker::BuildDynamicImportClass()
5653af6ab5fSopenharmony_ci{
5663af6ab5fSopenharmony_ci    auto dynamicImports = VarBinder()->AsETSBinder()->DynamicImports();
5673af6ab5fSopenharmony_ci    if (dynamicImports.empty()) {
5683af6ab5fSopenharmony_ci        return;
5693af6ab5fSopenharmony_ci    }
5703af6ab5fSopenharmony_ci
5713af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
5723af6ab5fSopenharmony_ci    BuildClass(
5733af6ab5fSopenharmony_ci        compiler::Signatures::DYNAMIC_MODULE_CLASS, [this, dynamicImports](ArenaVector<ir::AstNode *> *classBody) {
5743af6ab5fSopenharmony_ci            std::unordered_set<util::StringView> fields;
5753af6ab5fSopenharmony_ci            std::vector<ir::ETSImportDeclaration *> imports;
5763af6ab5fSopenharmony_ci
5773af6ab5fSopenharmony_ci            for (auto *import : dynamicImports) {
5783af6ab5fSopenharmony_ci                auto source = import->Source()->Str();
5793af6ab5fSopenharmony_ci                if (fields.find(source) != fields.cend()) {
5803af6ab5fSopenharmony_ci                    continue;
5813af6ab5fSopenharmony_ci                }
5823af6ab5fSopenharmony_ci
5833af6ab5fSopenharmony_ci                auto assemblyName = std::string(source);
5843af6ab5fSopenharmony_ci                std::replace_if(
5853af6ab5fSopenharmony_ci                    assemblyName.begin(), assemblyName.end(), [](char c) { return std::isalnum(c) == 0; }, '_');
5863af6ab5fSopenharmony_ci                assemblyName.append(std::to_string(fields.size()));
5873af6ab5fSopenharmony_ci
5883af6ab5fSopenharmony_ci                import->AssemblerName() = util::UString(assemblyName, Allocator()).View();
5893af6ab5fSopenharmony_ci                fields.insert(import->AssemblerName());
5903af6ab5fSopenharmony_ci                imports.push_back(import);
5913af6ab5fSopenharmony_ci
5923af6ab5fSopenharmony_ci                auto *fieldIdent = AllocNode<ir::Identifier>(import->AssemblerName(), Allocator());
5933af6ab5fSopenharmony_ci                // NOTE: remove const when readonly is properly supported
5943af6ab5fSopenharmony_ci                auto flags = ir::ModifierFlags::STATIC | ir::ModifierFlags::PUBLIC | ir::ModifierFlags::READONLY |
5953af6ab5fSopenharmony_ci                             ir::ModifierFlags::CONST;
5963af6ab5fSopenharmony_ci                auto *field = AllocNode<ir::ClassProperty>(
5973af6ab5fSopenharmony_ci                    fieldIdent, nullptr, AllocNode<ir::OpaqueTypeNode>(GlobalBuiltinDynamicType(import->Language())),
5983af6ab5fSopenharmony_ci                    flags, Allocator(), false);
5993af6ab5fSopenharmony_ci
6003af6ab5fSopenharmony_ci                classBody->push_back(field);
6013af6ab5fSopenharmony_ci            }
6023af6ab5fSopenharmony_ci
6033af6ab5fSopenharmony_ci            classBody->push_back(CreateDynamicModuleClassInitializer(imports));
6043af6ab5fSopenharmony_ci            classBody->push_back(CreateDynamicModuleClassInitMethod());
6053af6ab5fSopenharmony_ci        });
6063af6ab5fSopenharmony_ci    EmitDynamicModuleClassInitCall();
6073af6ab5fSopenharmony_ci}
6083af6ab5fSopenharmony_ci
6093af6ab5fSopenharmony_ciir::MethodDefinition *ETSChecker::CreateLambdaObjectClassInitializer(ETSObjectType *functionalInterface)
6103af6ab5fSopenharmony_ci{
6113af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
6123af6ab5fSopenharmony_ci    return CreateClassInstanceInitializer(
6133af6ab5fSopenharmony_ci        [this](ArenaVector<ir::Statement *> *statements, ArenaVector<ir::Expression *> *params) {
6143af6ab5fSopenharmony_ci            ir::ETSParameterExpression *thisParam = AddParam(varbinder::VarBinder::MANDATORY_PARAM_THIS, nullptr);
6153af6ab5fSopenharmony_ci            params->push_back(thisParam);
6163af6ab5fSopenharmony_ci
6173af6ab5fSopenharmony_ci            util::UString jsvalueParamName(std::string("jsvalue_param"), Allocator());
6183af6ab5fSopenharmony_ci            ir::ETSParameterExpression *jsvalueParam =
6193af6ab5fSopenharmony_ci                AddParam(jsvalueParamName.View(), AllocNode<ir::OpaqueTypeNode>(GlobalBuiltinJSValueType()));
6203af6ab5fSopenharmony_ci            params->push_back(jsvalueParam);
6213af6ab5fSopenharmony_ci            // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
6223af6ab5fSopenharmony_ci            auto *moduleClassId = AllocNode<ir::Identifier>(varbinder::VarBinder::MANDATORY_PARAM_THIS, Allocator());
6233af6ab5fSopenharmony_ci            // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
6243af6ab5fSopenharmony_ci            auto *fieldId = AllocNode<ir::Identifier>("jsvalue_lambda", Allocator());
6253af6ab5fSopenharmony_ci            // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
6263af6ab5fSopenharmony_ci            auto *property = AllocNode<ir::MemberExpression>(moduleClassId, fieldId,
6273af6ab5fSopenharmony_ci                                                             ir::MemberExpressionKind::PROPERTY_ACCESS, false, false);
6283af6ab5fSopenharmony_ci            // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
6293af6ab5fSopenharmony_ci            auto *initializer = AllocNode<ir::AssignmentExpression>(property, jsvalueParam->Clone(Allocator(), nullptr),
6303af6ab5fSopenharmony_ci                                                                    lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
6313af6ab5fSopenharmony_ci            // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
6323af6ab5fSopenharmony_ci            statements->push_back(AllocNode<ir::ExpressionStatement>(initializer));
6333af6ab5fSopenharmony_ci        },
6343af6ab5fSopenharmony_ci        functionalInterface);
6353af6ab5fSopenharmony_ci}
6363af6ab5fSopenharmony_ci
6373af6ab5fSopenharmony_civoid ETSChecker::BuildLambdaObjectClass(ETSObjectType *functionalInterface, ir::TypeNode *retTypeAnnotation)
6383af6ab5fSopenharmony_ci{
6393af6ab5fSopenharmony_ci    auto *invokeMethod = functionalInterface->GetOwnProperty<checker::PropertyType::INSTANCE_METHOD>("invoke");
6403af6ab5fSopenharmony_ci    auto *invokeSignature = invokeMethod->TsType()->AsETSFunctionType()->CallSignatures()[0];
6413af6ab5fSopenharmony_ci
6423af6ab5fSopenharmony_ci    std::stringstream ss;
6433af6ab5fSopenharmony_ci    ss << compiler::Signatures::LAMBDA_OBJECT;
6443af6ab5fSopenharmony_ci    ToString(this, invokeSignature->Params(), ss);
6453af6ab5fSopenharmony_ci    auto syntheticLambdaObjName = ss.str();
6463af6ab5fSopenharmony_ci    if (dynamicLambdaSignatureCache_.count(syntheticLambdaObjName) != 0) {
6473af6ab5fSopenharmony_ci        functionalInterface->AddConstructSignature(dynamicLambdaSignatureCache_[syntheticLambdaObjName]);
6483af6ab5fSopenharmony_ci        return;
6493af6ab5fSopenharmony_ci    }
6503af6ab5fSopenharmony_ci
6513af6ab5fSopenharmony_ci    auto buildBody = [this, invokeSignature, retTypeAnnotation,
6523af6ab5fSopenharmony_ci                      functionalInterface](ArenaVector<ir::AstNode *> *classBody) {
6533af6ab5fSopenharmony_ci        auto assemblyName = "jsvalue_lambda";
6543af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
6553af6ab5fSopenharmony_ci        auto *fieldIdent = AllocNode<ir::Identifier>(assemblyName, Allocator());
6563af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
6573af6ab5fSopenharmony_ci        auto *field =
6583af6ab5fSopenharmony_ci            AllocNode<ir::ClassProperty>(fieldIdent, nullptr, AllocNode<ir::OpaqueTypeNode>(GlobalBuiltinJSValueType()),
6593af6ab5fSopenharmony_ci                                         ir::ModifierFlags::PRIVATE, Allocator(), false);
6603af6ab5fSopenharmony_ci        classBody->push_back(field);
6613af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
6623af6ab5fSopenharmony_ci        classBody->push_back(CreateLambdaObjectClassInitializer(functionalInterface));
6633af6ab5fSopenharmony_ci        // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
6643af6ab5fSopenharmony_ci        classBody->push_back(CreateLambdaObjectClassInvokeMethod(invokeSignature, retTypeAnnotation));
6653af6ab5fSopenharmony_ci    };
6663af6ab5fSopenharmony_ci
6673af6ab5fSopenharmony_ci    // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
6683af6ab5fSopenharmony_ci    BuildClass(util::StringView(syntheticLambdaObjName), buildBody);
6693af6ab5fSopenharmony_ci
6703af6ab5fSopenharmony_ci    dynamicLambdaSignatureCache_[syntheticLambdaObjName] = functionalInterface->ConstructSignatures()[0];
6713af6ab5fSopenharmony_ci}
6723af6ab5fSopenharmony_ci
6733af6ab5fSopenharmony_ci}  // namespace ark::es2panda::checker
674