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, ¶ms); 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, ¶ms, &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