14d6c458bSopenharmony_ci/* 24d6c458bSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 34d6c458bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44d6c458bSopenharmony_ci * you may not use this file except in compliance with the License. 54d6c458bSopenharmony_ci * You may obtain a copy of the License at 64d6c458bSopenharmony_ci * 74d6c458bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84d6c458bSopenharmony_ci * 94d6c458bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104d6c458bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114d6c458bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124d6c458bSopenharmony_ci * See the License for the specific language governing permissions and 134d6c458bSopenharmony_ci * limitations under the License. 144d6c458bSopenharmony_ci */ 154d6c458bSopenharmony_ci 164d6c458bSopenharmony_ci#include "worker.h" 174d6c458bSopenharmony_ci 184d6c458bSopenharmony_ci#include "commonlibrary/ets_utils/js_sys_module/timer/timer.h" 194d6c458bSopenharmony_ci#include "helper/concurrent_helper.h" 204d6c458bSopenharmony_ci#include "helper/error_helper.h" 214d6c458bSopenharmony_ci#include "helper/hitrace_helper.h" 224d6c458bSopenharmony_ci#include "helper/path_helper.h" 234d6c458bSopenharmony_ci#include "tools/log.h" 244d6c458bSopenharmony_ci#if defined(OHOS_PLATFORM) 254d6c458bSopenharmony_ci#include "parameters.h" 264d6c458bSopenharmony_ci#endif 274d6c458bSopenharmony_ci 284d6c458bSopenharmony_cinamespace Commonlibrary::Concurrent::WorkerModule { 294d6c458bSopenharmony_ciusing namespace OHOS::JsSysModule; 304d6c458bSopenharmony_cistatic constexpr int8_t NUM_WORKER_ARGS = 2; 314d6c458bSopenharmony_cistatic constexpr uint8_t NUM_GLOBAL_CALL_ARGS = 3; 324d6c458bSopenharmony_cistatic std::list<Worker *> g_workers; 334d6c458bSopenharmony_cistatic constexpr int MAX_WORKERS = 8; 344d6c458bSopenharmony_cistatic constexpr int MAX_THREAD_WORKERS = 64; 354d6c458bSopenharmony_cistatic std::mutex g_workersMutex; 364d6c458bSopenharmony_cistatic std::list<Worker *> g_limitedworkers; 374d6c458bSopenharmony_cistatic constexpr int MAX_LIMITEDWORKERS = 16; 384d6c458bSopenharmony_cistatic std::mutex g_limitedworkersMutex; 394d6c458bSopenharmony_cistatic constexpr uint8_t BEGIN_INDEX_OF_ARGUMENTS = 2; 404d6c458bSopenharmony_cistatic constexpr uint32_t DEFAULT_TIMEOUT = 5000; 414d6c458bSopenharmony_cistatic constexpr uint32_t GLOBAL_CALL_ID_MAX = 4294967295; 424d6c458bSopenharmony_cistatic constexpr size_t GLOBAL_CALL_MAX_COUNT = 65535; 434d6c458bSopenharmony_ci 444d6c458bSopenharmony_ci#if defined(ENABLE_WORKER_EVENTHANDLER) 454d6c458bSopenharmony_cistd::shared_ptr<OHOS::AppExecFwk::EventHandler> Worker::GetMainThreadHandler() 464d6c458bSopenharmony_ci{ 474d6c458bSopenharmony_ci static std::shared_ptr<OHOS::AppExecFwk::EventHandler> mainThreadHandler; 484d6c458bSopenharmony_ci static std::mutex mainThreadHandlerMutex; 494d6c458bSopenharmony_ci if (mainThreadHandler == nullptr) { 504d6c458bSopenharmony_ci std::lock_guard<std::mutex> lock(mainThreadHandlerMutex); 514d6c458bSopenharmony_ci if (mainThreadHandler == nullptr) { 524d6c458bSopenharmony_ci mainThreadHandler = std::make_shared<OHOS::AppExecFwk::EventHandler>( 534d6c458bSopenharmony_ci OHOS::AppExecFwk::EventRunner::GetMainEventRunner()); 544d6c458bSopenharmony_ci } 554d6c458bSopenharmony_ci } 564d6c458bSopenharmony_ci return mainThreadHandler; 574d6c458bSopenharmony_ci} 584d6c458bSopenharmony_ci#endif 594d6c458bSopenharmony_ci 604d6c458bSopenharmony_ciWorker::Worker(napi_env env, napi_ref thisVar) 614d6c458bSopenharmony_ci : hostEnv_(env), workerRef_(thisVar) 624d6c458bSopenharmony_ci{} 634d6c458bSopenharmony_ci 644d6c458bSopenharmony_cinapi_value Worker::InitWorker(napi_env env, napi_value exports) 654d6c458bSopenharmony_ci{ 664d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 674d6c458bSopenharmony_ci napi_property_descriptor properties[] = { 684d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION("postMessage", PostMessage), 694d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION("postMessageWithSharedSendable", PostMessageWithSharedSendable), 704d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION("terminate", Terminate), 714d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION("on", On), 724d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION("registerGlobalCallObject", RegisterGlobalCallObject), 734d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION("unregisterGlobalCallObject", UnregisterGlobalCallObject), 744d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION("once", Once), 754d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION("off", Off), 764d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION("addEventListener", AddEventListener), 774d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION("dispatchEvent", DispatchEvent), 784d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION("removeEventListener", RemoveEventListener), 794d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION("removeAllListener", RemoveAllListener), 804d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION("cancelTasks", CancelTask), 814d6c458bSopenharmony_ci }; 824d6c458bSopenharmony_ci // for worker.ThreadWorker 834d6c458bSopenharmony_ci const char threadWorkerName[] = "ThreadWorker"; 844d6c458bSopenharmony_ci napi_value threadWorkerClazz = nullptr; 854d6c458bSopenharmony_ci napi_define_class(env, threadWorkerName, sizeof(threadWorkerName), Worker::ThreadWorkerConstructor, nullptr, 864d6c458bSopenharmony_ci sizeof(properties) / sizeof(properties[0]), properties, &threadWorkerClazz); 874d6c458bSopenharmony_ci napi_set_named_property(env, exports, "ThreadWorker", threadWorkerClazz); 884d6c458bSopenharmony_ci 894d6c458bSopenharmony_ci // for worker.Worker 904d6c458bSopenharmony_ci const char workerName[] = "Worker"; 914d6c458bSopenharmony_ci napi_value workerClazz = nullptr; 924d6c458bSopenharmony_ci napi_define_class(env, workerName, sizeof(workerName), Worker::WorkerConstructor, nullptr, 934d6c458bSopenharmony_ci sizeof(properties) / sizeof(properties[0]), properties, &workerClazz); 944d6c458bSopenharmony_ci napi_set_named_property(env, exports, "Worker", workerClazz); 954d6c458bSopenharmony_ci 964d6c458bSopenharmony_ci // for worker.LimitedWorker 974d6c458bSopenharmony_ci const char limitedWorkerName[] = "RestrictedWorker"; 984d6c458bSopenharmony_ci napi_value limitedWorkerClazz = nullptr; 994d6c458bSopenharmony_ci napi_define_class(env, limitedWorkerName, sizeof(limitedWorkerName), Worker::LimitedWorkerConstructor, nullptr, 1004d6c458bSopenharmony_ci sizeof(properties) / sizeof(properties[0]), properties, &limitedWorkerClazz); 1014d6c458bSopenharmony_ci napi_set_named_property(env, exports, "RestrictedWorker", limitedWorkerClazz); 1024d6c458bSopenharmony_ci return InitPort(env, exports); 1034d6c458bSopenharmony_ci} 1044d6c458bSopenharmony_ci 1054d6c458bSopenharmony_cinapi_value Worker::InitPort(napi_env env, napi_value exports) 1064d6c458bSopenharmony_ci{ 1074d6c458bSopenharmony_ci NativeEngine* engine = reinterpret_cast<NativeEngine*>(env); 1084d6c458bSopenharmony_ci Worker* worker = nullptr; 1094d6c458bSopenharmony_ci if (engine->IsRestrictedWorkerThread()) { 1104d6c458bSopenharmony_ci std::lock_guard<std::mutex> lock(g_limitedworkersMutex); 1114d6c458bSopenharmony_ci for (auto item = g_limitedworkers.begin(); item != g_limitedworkers.end(); item++) { 1124d6c458bSopenharmony_ci if ((*item)->IsSameWorkerEnv(env)) { 1134d6c458bSopenharmony_ci worker = *item; 1144d6c458bSopenharmony_ci } 1154d6c458bSopenharmony_ci } 1164d6c458bSopenharmony_ci } else if (engine->IsWorkerThread()) { 1174d6c458bSopenharmony_ci std::lock_guard<std::mutex> lock(g_workersMutex); 1184d6c458bSopenharmony_ci for (auto item = g_workers.begin(); item != g_workers.end(); item++) { 1194d6c458bSopenharmony_ci if ((*item)->IsSameWorkerEnv(env)) { 1204d6c458bSopenharmony_ci worker = *item; 1214d6c458bSopenharmony_ci } 1224d6c458bSopenharmony_ci } 1234d6c458bSopenharmony_ci } else { 1244d6c458bSopenharmony_ci return exports; 1254d6c458bSopenharmony_ci } 1264d6c458bSopenharmony_ci 1274d6c458bSopenharmony_ci if (worker == nullptr) { 1284d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "worker is null when InitWorker"); 1294d6c458bSopenharmony_ci return exports; 1304d6c458bSopenharmony_ci } 1314d6c458bSopenharmony_ci 1324d6c458bSopenharmony_ci napi_property_descriptor properties[] = { 1334d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION_WITH_DATA("postMessage", PostMessageToHost, worker), 1344d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION_WITH_DATA("postMessageWithSharedSendable", PostMessageWithSharedSendableToHost, worker), 1354d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION_WITH_DATA("callGlobalCallObjectMethod", GlobalCall, worker), 1364d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION_WITH_DATA("close", CloseWorker, worker), 1374d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION_WITH_DATA("cancelTasks", ParentPortCancelTask, worker), 1384d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION_WITH_DATA("addEventListener", ParentPortAddEventListener, worker), 1394d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION_WITH_DATA("dispatchEvent", ParentPortDispatchEvent, worker), 1404d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION_WITH_DATA("removeEventListener", ParentPortRemoveEventListener, worker), 1414d6c458bSopenharmony_ci DECLARE_NAPI_FUNCTION_WITH_DATA("removeAllListener", ParentPortRemoveAllListener, worker), 1424d6c458bSopenharmony_ci }; 1434d6c458bSopenharmony_ci napi_value workerPortObj = nullptr; 1444d6c458bSopenharmony_ci napi_create_object(env, &workerPortObj); 1454d6c458bSopenharmony_ci napi_define_properties(env, workerPortObj, sizeof(properties) / sizeof(properties[0]), properties); 1464d6c458bSopenharmony_ci 1474d6c458bSopenharmony_ci // 5. register worker name in DedicatedWorkerGlobalScope 1484d6c458bSopenharmony_ci std::string name = worker->GetName(); 1494d6c458bSopenharmony_ci if (!name.empty()) { 1504d6c458bSopenharmony_ci napi_value nameValue = nullptr; 1514d6c458bSopenharmony_ci napi_create_string_utf8(env, name.c_str(), name.length(), &nameValue); 1524d6c458bSopenharmony_ci napi_set_named_property(env, workerPortObj, "name", nameValue); 1534d6c458bSopenharmony_ci } 1544d6c458bSopenharmony_ci 1554d6c458bSopenharmony_ci napi_set_named_property(env, workerPortObj, "self", workerPortObj); 1564d6c458bSopenharmony_ci 1574d6c458bSopenharmony_ci if (worker->isNewVersion_) { 1584d6c458bSopenharmony_ci napi_set_named_property(env, exports, "workerPort", workerPortObj); 1594d6c458bSopenharmony_ci } else { 1604d6c458bSopenharmony_ci napi_set_named_property(env, exports, "parentPort", workerPortObj); 1614d6c458bSopenharmony_ci } 1624d6c458bSopenharmony_ci // register worker Port. 1634d6c458bSopenharmony_ci napi_create_reference(env, workerPortObj, 1, &worker->workerPort_); 1644d6c458bSopenharmony_ci#if defined(ENABLE_WORKER_EVENTHANDLER) 1654d6c458bSopenharmony_ci GetMainThreadHandler(); 1664d6c458bSopenharmony_ci#endif 1674d6c458bSopenharmony_ci return exports; 1684d6c458bSopenharmony_ci} 1694d6c458bSopenharmony_ci 1704d6c458bSopenharmony_cinapi_value Worker::LimitedWorkerConstructor(napi_env env, napi_callback_info cbinfo) 1714d6c458bSopenharmony_ci{ 1724d6c458bSopenharmony_ci if (CanCreateWorker(env, WorkerVersion::NEW)) { 1734d6c458bSopenharmony_ci return Constructor(env, cbinfo, true); 1744d6c458bSopenharmony_ci } 1754d6c458bSopenharmony_ci HILOG_ERROR("worker:: using both Worker and LimitedWorker is not supported"); 1764d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_INITIALIZATION, 1774d6c458bSopenharmony_ci "Using both Worker and LimitedWorker is not supported."); 1784d6c458bSopenharmony_ci return nullptr; 1794d6c458bSopenharmony_ci} 1804d6c458bSopenharmony_ci 1814d6c458bSopenharmony_cinapi_value Worker::ThreadWorkerConstructor(napi_env env, napi_callback_info cbinfo) 1824d6c458bSopenharmony_ci{ 1834d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME("ThreadWorkerConstructor: [Add Thread]"); 1844d6c458bSopenharmony_ci if (CanCreateWorker(env, WorkerVersion::NEW)) { 1854d6c458bSopenharmony_ci return Constructor(env, cbinfo, false, WorkerVersion::NEW); 1864d6c458bSopenharmony_ci } 1874d6c458bSopenharmony_ci HILOG_ERROR("worker:: ThreadWorker construct failed"); 1884d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_INITIALIZATION, 1894d6c458bSopenharmony_ci "Using both Worker and ThreadWorker is not supported."); 1904d6c458bSopenharmony_ci return nullptr; 1914d6c458bSopenharmony_ci} 1924d6c458bSopenharmony_ci 1934d6c458bSopenharmony_cinapi_value Worker::WorkerConstructor(napi_env env, napi_callback_info cbinfo) 1944d6c458bSopenharmony_ci{ 1954d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME("WorkerConstructor: [Add Thread]"); 1964d6c458bSopenharmony_ci if (CanCreateWorker(env, WorkerVersion::OLD)) { 1974d6c458bSopenharmony_ci return Constructor(env, cbinfo, false, WorkerVersion::OLD); 1984d6c458bSopenharmony_ci } 1994d6c458bSopenharmony_ci HILOG_ERROR("worker:: using both Worker and other Workers is not supported"); 2004d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_INITIALIZATION, 2014d6c458bSopenharmony_ci "Using both Worker and other Workers is not supported."); 2024d6c458bSopenharmony_ci return nullptr; 2034d6c458bSopenharmony_ci} 2044d6c458bSopenharmony_ci 2054d6c458bSopenharmony_cinapi_value Worker::Constructor(napi_env env, napi_callback_info cbinfo, bool limitSign, WorkerVersion version) 2064d6c458bSopenharmony_ci{ 2074d6c458bSopenharmony_ci napi_value thisVar = nullptr; 2084d6c458bSopenharmony_ci void* data = nullptr; 2094d6c458bSopenharmony_ci size_t argc = 2; // 2: max args number is 2 2104d6c458bSopenharmony_ci napi_value args[argc]; 2114d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, &data); 2124d6c458bSopenharmony_ci // check argv count 2134d6c458bSopenharmony_ci if (argc < 1) { 2144d6c458bSopenharmony_ci HILOG_ERROR("worker:: the number of create worker param must be more than 1 with new"); 2154d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the number of parameters must be more than 1."); 2164d6c458bSopenharmony_ci return nullptr; 2174d6c458bSopenharmony_ci } 2184d6c458bSopenharmony_ci // check 1st param is string 2194d6c458bSopenharmony_ci if (!NapiHelper::IsString(env, args[0])) { 2204d6c458bSopenharmony_ci HILOG_ERROR("worker:: the type of Worker 1st param must be string"); 2214d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 2224d6c458bSopenharmony_ci "the type of the first param must be string."); 2234d6c458bSopenharmony_ci return nullptr; 2244d6c458bSopenharmony_ci } 2254d6c458bSopenharmony_ci WorkerParams* workerParams = nullptr; 2264d6c458bSopenharmony_ci if (argc == 2) { // 2: max args number is 2 2274d6c458bSopenharmony_ci workerParams = CheckWorkerArgs(env, args[1]); 2284d6c458bSopenharmony_ci if (workerParams == nullptr) { 2294d6c458bSopenharmony_ci HILOG_ERROR("Worker:: arguments check failed."); 2304d6c458bSopenharmony_ci return nullptr; 2314d6c458bSopenharmony_ci } 2324d6c458bSopenharmony_ci } 2334d6c458bSopenharmony_ci Worker* worker = nullptr; 2344d6c458bSopenharmony_ci if (limitSign) { 2354d6c458bSopenharmony_ci std::lock_guard<std::mutex> lock(g_limitedworkersMutex); 2364d6c458bSopenharmony_ci if (static_cast<int>(g_limitedworkers.size()) >= MAX_LIMITEDWORKERS) { 2374d6c458bSopenharmony_ci HILOG_ERROR("worker:: the number of limiteworkers exceeds the maximum"); 2384d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, 2394d6c458bSopenharmony_ci ErrorHelper::ERR_WORKER_INITIALIZATION, "the number of limiteworkers exceeds the maximum."); 2404d6c458bSopenharmony_ci return nullptr; 2414d6c458bSopenharmony_ci } 2424d6c458bSopenharmony_ci 2434d6c458bSopenharmony_ci // 2. new worker instance 2444d6c458bSopenharmony_ci worker = new Worker(env, nullptr); 2454d6c458bSopenharmony_ci if (worker == nullptr) { 2464d6c458bSopenharmony_ci HILOG_ERROR("worker:: create worker error"); 2474d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_INITIALIZATION, "create worker error"); 2484d6c458bSopenharmony_ci return nullptr; 2494d6c458bSopenharmony_ci } 2504d6c458bSopenharmony_ci g_limitedworkers.push_back(worker); 2514d6c458bSopenharmony_ci HILOG_INFO("worker:: limited workers num %{public}zu", g_limitedworkers.size()); 2524d6c458bSopenharmony_ci } else { 2534d6c458bSopenharmony_ci int maxWorkers = (version == WorkerVersion::NEW) ? MAX_THREAD_WORKERS : MAX_WORKERS; 2544d6c458bSopenharmony_ci #if defined(OHOS_PLATFORM) 2554d6c458bSopenharmony_ci maxWorkers = OHOS::system::GetIntParameter<int>("persist.commonlibrary.maxworkers", maxWorkers); 2564d6c458bSopenharmony_ci #endif 2574d6c458bSopenharmony_ci std::lock_guard<std::mutex> lock(g_workersMutex); 2584d6c458bSopenharmony_ci if (static_cast<int>(g_workers.size()) >= maxWorkers) { 2594d6c458bSopenharmony_ci HILOG_ERROR("worker:: the number of workers exceeds the maximum"); 2604d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, 2614d6c458bSopenharmony_ci ErrorHelper::ERR_WORKER_INITIALIZATION, "the number of workers exceeds the maximum."); 2624d6c458bSopenharmony_ci return nullptr; 2634d6c458bSopenharmony_ci } 2644d6c458bSopenharmony_ci 2654d6c458bSopenharmony_ci // 2. new worker instance 2664d6c458bSopenharmony_ci worker = new Worker(env, nullptr); 2674d6c458bSopenharmony_ci if (worker == nullptr) { 2684d6c458bSopenharmony_ci HILOG_ERROR("worker:: create worker error"); 2694d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_INITIALIZATION, "create worker error"); 2704d6c458bSopenharmony_ci return nullptr; 2714d6c458bSopenharmony_ci } 2724d6c458bSopenharmony_ci g_workers.push_back(worker); 2734d6c458bSopenharmony_ci HILOG_INFO("worker:: workers num %{public}zu", g_workers.size()); 2744d6c458bSopenharmony_ci } 2754d6c458bSopenharmony_ci 2764d6c458bSopenharmony_ci if (workerParams != nullptr) { 2774d6c458bSopenharmony_ci if (!workerParams->name_.empty()) { 2784d6c458bSopenharmony_ci worker->name_ = workerParams->name_; 2794d6c458bSopenharmony_ci } 2804d6c458bSopenharmony_ci // default classic 2814d6c458bSopenharmony_ci worker->SetScriptMode(workerParams->type_); 2824d6c458bSopenharmony_ci CloseHelp::DeletePointer(workerParams, false); 2834d6c458bSopenharmony_ci workerParams = nullptr; 2844d6c458bSopenharmony_ci } 2854d6c458bSopenharmony_ci worker->isLimitedWorker_ = limitSign; 2864d6c458bSopenharmony_ci worker->isNewVersion_ = (version != WorkerVersion::OLD) ? true : false; 2874d6c458bSopenharmony_ci 2884d6c458bSopenharmony_ci // 3. execute in thread 2894d6c458bSopenharmony_ci char* script = NapiHelper::GetChars(env, args[0]); 2904d6c458bSopenharmony_ci if (script == nullptr) { 2914d6c458bSopenharmony_ci HILOG_ERROR("worker:: the file path is invaild, maybe path is null"); 2924d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, 2934d6c458bSopenharmony_ci ErrorHelper::ERR_WORKER_INVALID_FILEPATH, "the file path is invaild, maybe path is null."); 2944d6c458bSopenharmony_ci return nullptr; 2954d6c458bSopenharmony_ci } 2964d6c458bSopenharmony_ci napi_add_env_cleanup_hook(env, HostEnvCleanCallback, worker); 2974d6c458bSopenharmony_ci napi_wrap(env, thisVar, worker, WorkerDestructor, nullptr, &worker->workerRef_); 2984d6c458bSopenharmony_ci worker->StartExecuteInThread(env, script); 2994d6c458bSopenharmony_ci return thisVar; 3004d6c458bSopenharmony_ci} 3014d6c458bSopenharmony_ci 3024d6c458bSopenharmony_civoid Worker::WorkerDestructor(napi_env env, void *data, void *hint) 3034d6c458bSopenharmony_ci{ 3044d6c458bSopenharmony_ci Worker* worker = reinterpret_cast<Worker*>(data); 3054d6c458bSopenharmony_ci napi_remove_env_cleanup_hook(env, HostEnvCleanCallback, worker); 3064d6c458bSopenharmony_ci std::lock_guard<std::recursive_mutex> lock(worker->liveStatusLock_); 3074d6c458bSopenharmony_ci if (worker->isHostEnvExited_) { 3084d6c458bSopenharmony_ci HILOG_INFO("worker:: host env exit."); 3094d6c458bSopenharmony_ci return; 3104d6c458bSopenharmony_ci } 3114d6c458bSopenharmony_ci if (worker->UpdateHostState(INACTIVE)) { 3124d6c458bSopenharmony_ci#if defined(ENABLE_WORKER_EVENTHANDLER) 3134d6c458bSopenharmony_ci if (!worker->isMainThreadWorker_ || worker->isLimitedWorker_) { 3144d6c458bSopenharmony_ci worker->CloseHostHandle(); 3154d6c458bSopenharmony_ci } 3164d6c458bSopenharmony_ci#else 3174d6c458bSopenharmony_ci worker->CloseHostHandle(); 3184d6c458bSopenharmony_ci#endif 3194d6c458bSopenharmony_ci worker->ReleaseHostThreadContent(); 3204d6c458bSopenharmony_ci } 3214d6c458bSopenharmony_ci if (!worker->IsRunning()) { 3224d6c458bSopenharmony_ci HILOG_DEBUG("worker:: worker is not running"); 3234d6c458bSopenharmony_ci return; 3244d6c458bSopenharmony_ci } 3254d6c458bSopenharmony_ci worker->TerminateInner(); 3264d6c458bSopenharmony_ci} 3274d6c458bSopenharmony_ci 3284d6c458bSopenharmony_civoid Worker::HostEnvCleanCallback(void *data) 3294d6c458bSopenharmony_ci{ 3304d6c458bSopenharmony_ci Worker* worker = reinterpret_cast<Worker*>(data); 3314d6c458bSopenharmony_ci if (worker == nullptr) { 3324d6c458bSopenharmony_ci HILOG_INFO("worker:: worker is nullptr when host env exit."); 3334d6c458bSopenharmony_ci return; 3344d6c458bSopenharmony_ci } 3354d6c458bSopenharmony_ci if (!IsValidWorker(worker)) { 3364d6c458bSopenharmony_ci HILOG_INFO("worker:: worker is terminated when host env exit."); 3374d6c458bSopenharmony_ci return; 3384d6c458bSopenharmony_ci } 3394d6c458bSopenharmony_ci std::lock_guard<std::recursive_mutex> lock(worker->liveStatusLock_); 3404d6c458bSopenharmony_ci worker->isHostEnvExited_ = true; 3414d6c458bSopenharmony_ci#if defined(ENABLE_WORKER_EVENTHANDLER) 3424d6c458bSopenharmony_ci if (!worker->isMainThreadWorker_ || worker->isLimitedWorker_) { 3434d6c458bSopenharmony_ci worker->CloseHostHandle(); 3444d6c458bSopenharmony_ci } 3454d6c458bSopenharmony_ci#else 3464d6c458bSopenharmony_ci worker->CloseHostHandle(); 3474d6c458bSopenharmony_ci#endif 3484d6c458bSopenharmony_ci worker->ReleaseHostThreadContent(); 3494d6c458bSopenharmony_ci worker->RemoveAllListenerInner(); 3504d6c458bSopenharmony_ci worker->ClearGlobalCallObject(); 3514d6c458bSopenharmony_ci} 3524d6c458bSopenharmony_ci 3534d6c458bSopenharmony_ciWorker::WorkerParams* Worker::CheckWorkerArgs(napi_env env, napi_value argsValue) 3544d6c458bSopenharmony_ci{ 3554d6c458bSopenharmony_ci WorkerParams* workerParams = nullptr; 3564d6c458bSopenharmony_ci if (NapiHelper::IsObject(env, argsValue)) { 3574d6c458bSopenharmony_ci workerParams = new WorkerParams(); 3584d6c458bSopenharmony_ci napi_value nameValue = NapiHelper::GetNameProperty(env, argsValue, "name"); 3594d6c458bSopenharmony_ci if (NapiHelper::IsNotUndefined(env, nameValue)) { 3604d6c458bSopenharmony_ci if (!NapiHelper::IsString(env, nameValue)) { 3614d6c458bSopenharmony_ci CloseHelp::DeletePointer(workerParams, false); 3624d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::TYPE_ERROR, "the type of name must be string."); 3634d6c458bSopenharmony_ci return nullptr; 3644d6c458bSopenharmony_ci } 3654d6c458bSopenharmony_ci char* nameStr = NapiHelper::GetChars(env, nameValue); 3664d6c458bSopenharmony_ci if (nameStr == nullptr) { 3674d6c458bSopenharmony_ci CloseHelp::DeletePointer(workerParams, false); 3684d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_INITIALIZATION, "the name of worker is null."); 3694d6c458bSopenharmony_ci return nullptr; 3704d6c458bSopenharmony_ci } 3714d6c458bSopenharmony_ci workerParams->name_ = std::string(nameStr); 3724d6c458bSopenharmony_ci CloseHelp::DeletePointer(nameStr, true); 3734d6c458bSopenharmony_ci } 3744d6c458bSopenharmony_ci napi_value typeValue = NapiHelper::GetNameProperty(env, argsValue, "type"); 3754d6c458bSopenharmony_ci if (NapiHelper::IsNotUndefined(env, typeValue)) { 3764d6c458bSopenharmony_ci if (!NapiHelper::IsString(env, typeValue)) { 3774d6c458bSopenharmony_ci CloseHelp::DeletePointer(workerParams, false); 3784d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::TYPE_ERROR, 3794d6c458bSopenharmony_ci "the type of type's value must be string."); 3804d6c458bSopenharmony_ci return nullptr; 3814d6c458bSopenharmony_ci } 3824d6c458bSopenharmony_ci char* typeStr = NapiHelper::GetChars(env, typeValue); 3834d6c458bSopenharmony_ci if (typeStr == nullptr) { 3844d6c458bSopenharmony_ci CloseHelp::DeletePointer(workerParams, false); 3854d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_INITIALIZATION, "the type of worker is null."); 3864d6c458bSopenharmony_ci return nullptr; 3874d6c458bSopenharmony_ci } 3884d6c458bSopenharmony_ci if (strcmp("classic", typeStr) == 0) { 3894d6c458bSopenharmony_ci workerParams->type_ = CLASSIC; 3904d6c458bSopenharmony_ci CloseHelp::DeletePointer(typeStr, true); 3914d6c458bSopenharmony_ci } else { 3924d6c458bSopenharmony_ci CloseHelp::DeletePointer(workerParams, false); 3934d6c458bSopenharmony_ci CloseHelp::DeletePointer(typeStr, true); 3944d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 3954d6c458bSopenharmony_ci "the type must be classic, unsupport others now."); 3964d6c458bSopenharmony_ci return nullptr; 3974d6c458bSopenharmony_ci } 3984d6c458bSopenharmony_ci } 3994d6c458bSopenharmony_ci } 4004d6c458bSopenharmony_ci return workerParams; 4014d6c458bSopenharmony_ci} 4024d6c458bSopenharmony_ci 4034d6c458bSopenharmony_cinapi_value Worker::PostMessage(napi_env env, napi_callback_info cbinfo) 4044d6c458bSopenharmony_ci{ 4054d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 4064d6c458bSopenharmony_ci return CommonPostMessage(env, cbinfo, true); 4074d6c458bSopenharmony_ci} 4084d6c458bSopenharmony_ci 4094d6c458bSopenharmony_cinapi_value Worker::PostMessageWithSharedSendable(napi_env env, napi_callback_info cbinfo) 4104d6c458bSopenharmony_ci{ 4114d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 4124d6c458bSopenharmony_ci return CommonPostMessage(env, cbinfo, false); 4134d6c458bSopenharmony_ci} 4144d6c458bSopenharmony_ci 4154d6c458bSopenharmony_cinapi_value Worker::CommonPostMessage(napi_env env, napi_callback_info cbinfo, bool cloneSendable) 4164d6c458bSopenharmony_ci{ 4174d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 4184d6c458bSopenharmony_ci size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo); 4194d6c458bSopenharmony_ci if (argc < 1) { 4204d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 4214d6c458bSopenharmony_ci "Worker messageObject must be not null with postMessage"); 4224d6c458bSopenharmony_ci return nullptr; 4234d6c458bSopenharmony_ci } 4244d6c458bSopenharmony_ci napi_value* argv = new napi_value[argc]; 4254d6c458bSopenharmony_ci ObjectScope<napi_value> scope(argv, true); 4264d6c458bSopenharmony_ci napi_value thisVar = nullptr; 4274d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr); 4284d6c458bSopenharmony_ci Worker* worker = nullptr; 4294d6c458bSopenharmony_ci napi_unwrap(env, thisVar, reinterpret_cast<void**>(&worker)); 4304d6c458bSopenharmony_ci 4314d6c458bSopenharmony_ci if (worker == nullptr || worker->IsTerminated() || worker->IsTerminating()) { 4324d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker is nullptr when PostMessage, maybe worker is terminated"); 4334d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "maybe worker is terminated when PostMessage"); 4344d6c458bSopenharmony_ci return nullptr; 4354d6c458bSopenharmony_ci } 4364d6c458bSopenharmony_ci 4374d6c458bSopenharmony_ci MessageDataType data = nullptr; 4384d6c458bSopenharmony_ci napi_status serializeStatus = napi_ok; 4394d6c458bSopenharmony_ci bool defaultClone = cloneSendable ? true : false; 4404d6c458bSopenharmony_ci napi_value undefined = NapiHelper::GetUndefinedValue(env); 4414d6c458bSopenharmony_ci if (argc >= NUM_WORKER_ARGS) { 4424d6c458bSopenharmony_ci if (!NapiHelper::IsArray(env, argv[1])) { 4434d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 4444d6c458bSopenharmony_ci "the type of the transfer list must be an array."); 4454d6c458bSopenharmony_ci return nullptr; 4464d6c458bSopenharmony_ci } 4474d6c458bSopenharmony_ci serializeStatus = napi_serialize_inner(env, argv[0], argv[1], undefined, false, defaultClone, &data); 4484d6c458bSopenharmony_ci } else { 4494d6c458bSopenharmony_ci serializeStatus = napi_serialize_inner(env, argv[0], undefined, undefined, false, defaultClone, &data); 4504d6c458bSopenharmony_ci } 4514d6c458bSopenharmony_ci if (serializeStatus != napi_ok || data == nullptr) { 4524d6c458bSopenharmony_ci worker->HostOnMessageErrorInner(); 4534d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, "failed to serialize message."); 4544d6c458bSopenharmony_ci return nullptr; 4554d6c458bSopenharmony_ci } 4564d6c458bSopenharmony_ci worker->PostMessageInner(data); 4574d6c458bSopenharmony_ci return NapiHelper::GetUndefinedValue(env); 4584d6c458bSopenharmony_ci} 4594d6c458bSopenharmony_ci 4604d6c458bSopenharmony_cinapi_value Worker::Terminate(napi_env env, napi_callback_info cbinfo) 4614d6c458bSopenharmony_ci{ 4624d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 4634d6c458bSopenharmony_ci napi_value thisVar = nullptr; 4644d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr); 4654d6c458bSopenharmony_ci Worker* worker = nullptr; 4664d6c458bSopenharmony_ci napi_unwrap(env, thisVar, reinterpret_cast<void**>(&worker)); 4674d6c458bSopenharmony_ci if (worker == nullptr) { 4684d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker is nullptr when Terminate, maybe worker is terminated"); 4694d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "worker is nullptr when Terminate"); 4704d6c458bSopenharmony_ci return nullptr; 4714d6c458bSopenharmony_ci } 4724d6c458bSopenharmony_ci bool expected = false; 4734d6c458bSopenharmony_ci if (worker->isTerminated_.compare_exchange_weak(expected, true)) { 4744d6c458bSopenharmony_ci HILOG_DEBUG("worker:: Terminate worker"); 4754d6c458bSopenharmony_ci } else { 4764d6c458bSopenharmony_ci HILOG_DEBUG("worker:: worker is terminated when Terminate"); 4774d6c458bSopenharmony_ci return nullptr; 4784d6c458bSopenharmony_ci } 4794d6c458bSopenharmony_ci if (worker->IsTerminated() || worker->IsTerminating()) { 4804d6c458bSopenharmony_ci HILOG_DEBUG("worker:: worker is not in running when Terminate"); 4814d6c458bSopenharmony_ci return nullptr; 4824d6c458bSopenharmony_ci } 4834d6c458bSopenharmony_ci worker->TerminateInner(); 4844d6c458bSopenharmony_ci return NapiHelper::GetUndefinedValue(env); 4854d6c458bSopenharmony_ci} 4864d6c458bSopenharmony_ci 4874d6c458bSopenharmony_cinapi_value Worker::On(napi_env env, napi_callback_info cbinfo) 4884d6c458bSopenharmony_ci{ 4894d6c458bSopenharmony_ci return AddListener(env, cbinfo, PERMANENT); 4904d6c458bSopenharmony_ci} 4914d6c458bSopenharmony_ci 4924d6c458bSopenharmony_cinapi_value Worker::Once(napi_env env, napi_callback_info cbinfo) 4934d6c458bSopenharmony_ci{ 4944d6c458bSopenharmony_ci return AddListener(env, cbinfo, ONCE); 4954d6c458bSopenharmony_ci} 4964d6c458bSopenharmony_ci 4974d6c458bSopenharmony_cinapi_value Worker::RegisterGlobalCallObject(napi_env env, napi_callback_info cbinfo) 4984d6c458bSopenharmony_ci{ 4994d6c458bSopenharmony_ci size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo); 5004d6c458bSopenharmony_ci if (argc != NUM_WORKER_ARGS) { 5014d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, 5024d6c458bSopenharmony_ci ErrorHelper::TYPE_ERROR, "the number of parameters must be 2."); 5034d6c458bSopenharmony_ci return nullptr; 5044d6c458bSopenharmony_ci } 5054d6c458bSopenharmony_ci // check 1st param is string 5064d6c458bSopenharmony_ci napi_value thisVar = nullptr; 5074d6c458bSopenharmony_ci void* data = nullptr; 5084d6c458bSopenharmony_ci napi_value* args = new napi_value[argc]; 5094d6c458bSopenharmony_ci ObjectScope<napi_value> scope(args, true); 5104d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, &data); 5114d6c458bSopenharmony_ci if (!NapiHelper::IsString(env, args[0])) { 5124d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 5134d6c458bSopenharmony_ci "the type of instanceName must be string."); 5144d6c458bSopenharmony_ci return nullptr; 5154d6c458bSopenharmony_ci } 5164d6c458bSopenharmony_ci std::string instanceName = NapiHelper::GetString(env, args[0]); 5174d6c458bSopenharmony_ci 5184d6c458bSopenharmony_ci Worker* worker = nullptr; 5194d6c458bSopenharmony_ci napi_unwrap(env, thisVar, (void**)&worker); 5204d6c458bSopenharmony_ci if (worker == nullptr) { 5214d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "maybe worker is terminated"); 5224d6c458bSopenharmony_ci return nullptr; 5234d6c458bSopenharmony_ci } 5244d6c458bSopenharmony_ci napi_ref obj = NapiHelper::CreateReference(env, args[1], 1); 5254d6c458bSopenharmony_ci worker->AddGlobalCallObject(instanceName, obj); 5264d6c458bSopenharmony_ci return nullptr; 5274d6c458bSopenharmony_ci} 5284d6c458bSopenharmony_ci 5294d6c458bSopenharmony_cinapi_value Worker::UnregisterGlobalCallObject(napi_env env, napi_callback_info cbinfo) 5304d6c458bSopenharmony_ci{ 5314d6c458bSopenharmony_ci size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo); 5324d6c458bSopenharmony_ci if (argc > 1) { 5334d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, 5344d6c458bSopenharmony_ci ErrorHelper::TYPE_ERROR, "the number of the parameters must be 1 or 0."); 5354d6c458bSopenharmony_ci return nullptr; 5364d6c458bSopenharmony_ci } 5374d6c458bSopenharmony_ci napi_value thisVar = nullptr; 5384d6c458bSopenharmony_ci void* data = nullptr; 5394d6c458bSopenharmony_ci napi_value* args = new napi_value[argc]; 5404d6c458bSopenharmony_ci ObjectScope<napi_value> scope(args, true); 5414d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, &data); 5424d6c458bSopenharmony_ci Worker* worker = nullptr; 5434d6c458bSopenharmony_ci napi_unwrap(env, thisVar, (void**)&worker); 5444d6c458bSopenharmony_ci if (worker == nullptr) { 5454d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "maybe worker is terminated"); 5464d6c458bSopenharmony_ci return nullptr; 5474d6c458bSopenharmony_ci } 5484d6c458bSopenharmony_ci if (argc == 0) { 5494d6c458bSopenharmony_ci worker->ClearGlobalCallObject(); 5504d6c458bSopenharmony_ci HILOG_DEBUG("worker:: clear all registered globalCallObject"); 5514d6c458bSopenharmony_ci return nullptr; 5524d6c458bSopenharmony_ci } 5534d6c458bSopenharmony_ci // check 1st param is string 5544d6c458bSopenharmony_ci if (!NapiHelper::IsString(env, args[0])) { 5554d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 5564d6c458bSopenharmony_ci "the type of instanceName must be string."); 5574d6c458bSopenharmony_ci return nullptr; 5584d6c458bSopenharmony_ci } 5594d6c458bSopenharmony_ci std::string instanceName = NapiHelper::GetString(env, args[0]); 5604d6c458bSopenharmony_ci if (!worker->RemoveGlobalCallObject(instanceName)) { 5614d6c458bSopenharmony_ci HILOG_ERROR("worker:: unregister unexist globalCallObject"); 5624d6c458bSopenharmony_ci } 5634d6c458bSopenharmony_ci return nullptr; 5644d6c458bSopenharmony_ci} 5654d6c458bSopenharmony_ci 5664d6c458bSopenharmony_cinapi_value Worker::Off(napi_env env, napi_callback_info cbinfo) 5674d6c458bSopenharmony_ci{ 5684d6c458bSopenharmony_ci return RemoveListener(env, cbinfo); 5694d6c458bSopenharmony_ci} 5704d6c458bSopenharmony_ci 5714d6c458bSopenharmony_cinapi_value Worker::RemoveEventListener(napi_env env, napi_callback_info cbinfo) 5724d6c458bSopenharmony_ci{ 5734d6c458bSopenharmony_ci return RemoveListener(env, cbinfo); 5744d6c458bSopenharmony_ci} 5754d6c458bSopenharmony_ci 5764d6c458bSopenharmony_cinapi_value Worker::AddEventListener(napi_env env, napi_callback_info cbinfo) 5774d6c458bSopenharmony_ci{ 5784d6c458bSopenharmony_ci return AddListener(env, cbinfo, PERMANENT); 5794d6c458bSopenharmony_ci} 5804d6c458bSopenharmony_ci 5814d6c458bSopenharmony_cinapi_value Worker::AddListener(napi_env env, napi_callback_info cbinfo, ListenerMode mode) 5824d6c458bSopenharmony_ci{ 5834d6c458bSopenharmony_ci size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo); 5844d6c458bSopenharmony_ci if (argc < NUM_WORKER_ARGS) { 5854d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 5864d6c458bSopenharmony_ci "the number of listener parameters is not less than 2."); 5874d6c458bSopenharmony_ci return nullptr; 5884d6c458bSopenharmony_ci } 5894d6c458bSopenharmony_ci // check 1st param is string 5904d6c458bSopenharmony_ci napi_value thisVar = nullptr; 5914d6c458bSopenharmony_ci void* data = nullptr; 5924d6c458bSopenharmony_ci napi_value* args = new napi_value[argc]; 5934d6c458bSopenharmony_ci ObjectScope<napi_value> scope(args, true); 5944d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, &data); 5954d6c458bSopenharmony_ci if (!NapiHelper::IsString(env, args[0])) { 5964d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 5974d6c458bSopenharmony_ci "the type of listener first param must be string."); 5984d6c458bSopenharmony_ci return nullptr; 5994d6c458bSopenharmony_ci } 6004d6c458bSopenharmony_ci if (!NapiHelper::IsCallable(env, args[1])) { 6014d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 6024d6c458bSopenharmony_ci "the type of listener the second param must be callable."); 6034d6c458bSopenharmony_ci return nullptr; 6044d6c458bSopenharmony_ci } 6054d6c458bSopenharmony_ci Worker* worker = nullptr; 6064d6c458bSopenharmony_ci napi_unwrap(env, thisVar, (void**)&worker); 6074d6c458bSopenharmony_ci if (worker == nullptr) { 6084d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker is nullptr when addListener, maybe worker is terminated"); 6094d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "maybe worker is terminated"); 6104d6c458bSopenharmony_ci return nullptr; 6114d6c458bSopenharmony_ci } 6124d6c458bSopenharmony_ci 6134d6c458bSopenharmony_ci napi_ref callback = NapiHelper::CreateReference(env, args[1], 1); 6144d6c458bSopenharmony_ci auto listener = new WorkerListener(env, callback, mode); 6154d6c458bSopenharmony_ci if (mode == ONCE && argc > NUM_WORKER_ARGS) { 6164d6c458bSopenharmony_ci if (NapiHelper::IsObject(env, args[NUM_WORKER_ARGS])) { 6174d6c458bSopenharmony_ci napi_value onceValue = NapiHelper::GetNameProperty(env, args[NUM_WORKER_ARGS], "once"); 6184d6c458bSopenharmony_ci bool isOnce = NapiHelper::GetBooleanValue(env, onceValue); 6194d6c458bSopenharmony_ci if (!isOnce) { 6204d6c458bSopenharmony_ci listener->SetMode(PERMANENT); 6214d6c458bSopenharmony_ci } 6224d6c458bSopenharmony_ci } 6234d6c458bSopenharmony_ci } 6244d6c458bSopenharmony_ci char* typeStr = NapiHelper::GetChars(env, args[0]); 6254d6c458bSopenharmony_ci worker->AddListenerInner(env, typeStr, listener); 6264d6c458bSopenharmony_ci CloseHelp::DeletePointer(typeStr, true); 6274d6c458bSopenharmony_ci return NapiHelper::GetUndefinedValue(env); 6284d6c458bSopenharmony_ci} 6294d6c458bSopenharmony_ci 6304d6c458bSopenharmony_cinapi_value Worker::RemoveListener(napi_env env, napi_callback_info cbinfo) 6314d6c458bSopenharmony_ci{ 6324d6c458bSopenharmony_ci size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo); 6334d6c458bSopenharmony_ci if (argc < 1) { 6344d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 6354d6c458bSopenharmony_ci "the number of parameters is not less than 1."); 6364d6c458bSopenharmony_ci return nullptr; 6374d6c458bSopenharmony_ci } 6384d6c458bSopenharmony_ci // check 1st param is string 6394d6c458bSopenharmony_ci napi_value thisVar = nullptr; 6404d6c458bSopenharmony_ci void* data = nullptr; 6414d6c458bSopenharmony_ci napi_value* args = new napi_value[argc]; 6424d6c458bSopenharmony_ci ObjectScope<napi_value> scope(args, true); 6434d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, &data); 6444d6c458bSopenharmony_ci if (!NapiHelper::IsString(env, args[0])) { 6454d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 6464d6c458bSopenharmony_ci "the type of removelistener the first param must be string."); 6474d6c458bSopenharmony_ci return nullptr; 6484d6c458bSopenharmony_ci } 6494d6c458bSopenharmony_ci 6504d6c458bSopenharmony_ci Worker* worker = nullptr; 6514d6c458bSopenharmony_ci napi_unwrap(env, thisVar, reinterpret_cast<void**>(&worker)); 6524d6c458bSopenharmony_ci if (worker == nullptr) { 6534d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker is nullptr when RemoveListener, maybe worker is terminated"); 6544d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "maybe worker is terminated"); 6554d6c458bSopenharmony_ci return nullptr; 6564d6c458bSopenharmony_ci } 6574d6c458bSopenharmony_ci 6584d6c458bSopenharmony_ci if (argc > 1 && !NapiHelper::IsCallable(env, args[1])) { 6594d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 6604d6c458bSopenharmony_ci "the type of removelistener the second param must be callable."); 6614d6c458bSopenharmony_ci return nullptr; 6624d6c458bSopenharmony_ci } 6634d6c458bSopenharmony_ci 6644d6c458bSopenharmony_ci char* typeStr = NapiHelper::GetChars(env, args[0]); 6654d6c458bSopenharmony_ci if (typeStr == nullptr) { 6664d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of remove listener type must be not null"); 6674d6c458bSopenharmony_ci return nullptr; 6684d6c458bSopenharmony_ci } 6694d6c458bSopenharmony_ci 6704d6c458bSopenharmony_ci napi_ref callback = nullptr; 6714d6c458bSopenharmony_ci if (argc > 1 && NapiHelper::IsCallable(env, args[1])) { 6724d6c458bSopenharmony_ci napi_create_reference(env, args[1], 1, &callback); 6734d6c458bSopenharmony_ci } 6744d6c458bSopenharmony_ci worker->RemoveListenerInner(env, typeStr, callback); 6754d6c458bSopenharmony_ci CloseHelp::DeletePointer(typeStr, true); 6764d6c458bSopenharmony_ci NapiHelper::DeleteReference(env, callback); 6774d6c458bSopenharmony_ci return NapiHelper::GetUndefinedValue(env); 6784d6c458bSopenharmony_ci} 6794d6c458bSopenharmony_ci 6804d6c458bSopenharmony_civoid CallWorkCallback(napi_env env, napi_value recv, size_t argc, const napi_value* argv, const char* type) 6814d6c458bSopenharmony_ci{ 6824d6c458bSopenharmony_ci napi_value callback = nullptr; 6834d6c458bSopenharmony_ci napi_get_named_property(env, recv, type, &callback); 6844d6c458bSopenharmony_ci if (NapiHelper::IsCallable(env, callback)) { 6854d6c458bSopenharmony_ci napi_value callbackResult = nullptr; 6864d6c458bSopenharmony_ci napi_call_function(env, recv, callback, argc, argv, &callbackResult); 6874d6c458bSopenharmony_ci } 6884d6c458bSopenharmony_ci} 6894d6c458bSopenharmony_ci 6904d6c458bSopenharmony_cinapi_value Worker::DispatchEvent(napi_env env, napi_callback_info cbinfo) 6914d6c458bSopenharmony_ci{ 6924d6c458bSopenharmony_ci size_t argc = 1; 6934d6c458bSopenharmony_ci napi_value args[1]; 6944d6c458bSopenharmony_ci napi_value thisVar = nullptr; 6954d6c458bSopenharmony_ci void* data = nullptr; 6964d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, &argc, args, &thisVar, &data); 6974d6c458bSopenharmony_ci if (argc < 1) { 6984d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the number of the parameters must be more than 1."); 6994d6c458bSopenharmony_ci return NapiHelper::CreateBooleanValue(env, false); 7004d6c458bSopenharmony_ci } 7014d6c458bSopenharmony_ci 7024d6c458bSopenharmony_ci // check 1st param is event 7034d6c458bSopenharmony_ci if (!NapiHelper::IsObject(env, args[0])) { 7044d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 7054d6c458bSopenharmony_ci "the type of DispatchEvent first param must be event object."); 7064d6c458bSopenharmony_ci return NapiHelper::CreateBooleanValue(env, false); 7074d6c458bSopenharmony_ci } 7084d6c458bSopenharmony_ci 7094d6c458bSopenharmony_ci Worker* worker = nullptr; 7104d6c458bSopenharmony_ci napi_unwrap(env, thisVar, reinterpret_cast<void**>(&worker)); 7114d6c458bSopenharmony_ci if (worker == nullptr) { 7124d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker is nullptr when DispatchEvent, maybe worker is terminated"); 7134d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "maybe worker has been terminated"); 7144d6c458bSopenharmony_ci return NapiHelper::CreateBooleanValue(env, false); 7154d6c458bSopenharmony_ci } 7164d6c458bSopenharmony_ci 7174d6c458bSopenharmony_ci napi_value typeValue = NapiHelper::GetNameProperty(env, args[0], "type"); 7184d6c458bSopenharmony_ci if (!NapiHelper::IsString(env, typeValue)) { 7194d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 7204d6c458bSopenharmony_ci "the type of event type must be string."); 7214d6c458bSopenharmony_ci return NapiHelper::CreateBooleanValue(env, false); 7224d6c458bSopenharmony_ci } 7234d6c458bSopenharmony_ci 7244d6c458bSopenharmony_ci napi_value obj = NapiHelper::GetReferenceValue(env, worker->workerRef_); 7254d6c458bSopenharmony_ci 7264d6c458bSopenharmony_ci char* typeStr = NapiHelper::GetChars(env, typeValue); 7274d6c458bSopenharmony_ci if (typeStr == nullptr) { 7284d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "dispatchEvent event type must be not null"); 7294d6c458bSopenharmony_ci return NapiHelper::CreateBooleanValue(env, false); 7304d6c458bSopenharmony_ci } 7314d6c458bSopenharmony_ci if (strcmp(typeStr, "error") == 0) { 7324d6c458bSopenharmony_ci CallWorkCallback(env, obj, 1, args, "onerror"); 7334d6c458bSopenharmony_ci } else if (strcmp(typeStr, "messageerror") == 0) { 7344d6c458bSopenharmony_ci CallWorkCallback(env, obj, 1, args, "onmessageerror"); 7354d6c458bSopenharmony_ci } else if (strcmp(typeStr, "message") == 0) { 7364d6c458bSopenharmony_ci CallWorkCallback(env, obj, 1, args, "onmessage"); 7374d6c458bSopenharmony_ci } 7384d6c458bSopenharmony_ci 7394d6c458bSopenharmony_ci worker->HandleEventListeners(env, obj, 1, args, typeStr); 7404d6c458bSopenharmony_ci 7414d6c458bSopenharmony_ci CloseHelp::DeletePointer(typeStr, true); 7424d6c458bSopenharmony_ci return NapiHelper::CreateBooleanValue(env, true); 7434d6c458bSopenharmony_ci} 7444d6c458bSopenharmony_ci 7454d6c458bSopenharmony_cinapi_value Worker::RemoveAllListener(napi_env env, napi_callback_info cbinfo) 7464d6c458bSopenharmony_ci{ 7474d6c458bSopenharmony_ci napi_value thisVar = nullptr; 7484d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr); 7494d6c458bSopenharmony_ci Worker* worker = nullptr; 7504d6c458bSopenharmony_ci napi_unwrap(env, thisVar, reinterpret_cast<void**>(&worker)); 7514d6c458bSopenharmony_ci if (worker == nullptr) { 7524d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker is nullptr when RemoveAllListener, maybe worker is terminated"); 7534d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "maybe worker is terminated"); 7544d6c458bSopenharmony_ci return nullptr; 7554d6c458bSopenharmony_ci } 7564d6c458bSopenharmony_ci 7574d6c458bSopenharmony_ci worker->RemoveAllListenerInner(); 7584d6c458bSopenharmony_ci return NapiHelper::GetUndefinedValue(env); 7594d6c458bSopenharmony_ci} 7604d6c458bSopenharmony_ci 7614d6c458bSopenharmony_cinapi_value Worker::CancelTask(napi_env env, napi_callback_info cbinfo) 7624d6c458bSopenharmony_ci{ 7634d6c458bSopenharmony_ci napi_value thisVar = nullptr; 7644d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr); 7654d6c458bSopenharmony_ci Worker* worker = nullptr; 7664d6c458bSopenharmony_ci napi_unwrap(env, thisVar, reinterpret_cast<void**>(&worker)); 7674d6c458bSopenharmony_ci if (worker == nullptr) { 7684d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker is nullptr when CancelTask, maybe worker is terminated"); 7694d6c458bSopenharmony_ci return nullptr; 7704d6c458bSopenharmony_ci } 7714d6c458bSopenharmony_ci 7724d6c458bSopenharmony_ci if (worker->IsTerminated() || worker->IsTerminating()) { 7734d6c458bSopenharmony_ci HILOG_INFO("worker:: worker is not in running"); 7744d6c458bSopenharmony_ci return nullptr; 7754d6c458bSopenharmony_ci } 7764d6c458bSopenharmony_ci 7774d6c458bSopenharmony_ci if (!worker->ClearWorkerTasks()) { 7784d6c458bSopenharmony_ci HILOG_ERROR("worker:: clear worker task error"); 7794d6c458bSopenharmony_ci } 7804d6c458bSopenharmony_ci return NapiHelper::GetUndefinedValue(env); 7814d6c458bSopenharmony_ci} 7824d6c458bSopenharmony_ci 7834d6c458bSopenharmony_cinapi_value Worker::PostMessageToHost(napi_env env, napi_callback_info cbinfo) 7844d6c458bSopenharmony_ci{ 7854d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 7864d6c458bSopenharmony_ci return CommonPostMessageToHost(env, cbinfo, true); 7874d6c458bSopenharmony_ci} 7884d6c458bSopenharmony_ci 7894d6c458bSopenharmony_cinapi_value Worker::PostMessageWithSharedSendableToHost(napi_env env, napi_callback_info cbinfo) 7904d6c458bSopenharmony_ci{ 7914d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 7924d6c458bSopenharmony_ci return CommonPostMessageToHost(env, cbinfo, false); 7934d6c458bSopenharmony_ci} 7944d6c458bSopenharmony_ci 7954d6c458bSopenharmony_cinapi_value Worker::CommonPostMessageToHost(napi_env env, napi_callback_info cbinfo, bool cloneSendable) 7964d6c458bSopenharmony_ci{ 7974d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 7984d6c458bSopenharmony_ci size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo); 7994d6c458bSopenharmony_ci if (argc < 1) { 8004d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the number of parameters must be more than 1."); 8014d6c458bSopenharmony_ci return nullptr; 8024d6c458bSopenharmony_ci } 8034d6c458bSopenharmony_ci napi_value* argv = new napi_value[argc]; 8044d6c458bSopenharmony_ci ObjectScope<napi_value> scope(argv, true); 8054d6c458bSopenharmony_ci Worker* worker = nullptr; 8064d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, &argc, argv, nullptr, reinterpret_cast<void**>(&worker)); 8074d6c458bSopenharmony_ci 8084d6c458bSopenharmony_ci if (worker == nullptr) { 8094d6c458bSopenharmony_ci HILOG_ERROR("worker:: when post message to host occur worker is nullptr"); 8104d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "worker is nullptr when post message to host"); 8114d6c458bSopenharmony_ci return nullptr; 8124d6c458bSopenharmony_ci } 8134d6c458bSopenharmony_ci 8144d6c458bSopenharmony_ci if (!worker->IsRunning()) { 8154d6c458bSopenharmony_ci // if worker is not running, don't send any message to host thread 8164d6c458bSopenharmony_ci HILOG_DEBUG("worker:: when post message to host occur worker is not in running."); 8174d6c458bSopenharmony_ci return nullptr; 8184d6c458bSopenharmony_ci } 8194d6c458bSopenharmony_ci 8204d6c458bSopenharmony_ci MessageDataType data = nullptr; 8214d6c458bSopenharmony_ci napi_status serializeStatus = napi_ok; 8224d6c458bSopenharmony_ci bool defaultClone = cloneSendable ? true : false; 8234d6c458bSopenharmony_ci napi_value undefined = NapiHelper::GetUndefinedValue(env); 8244d6c458bSopenharmony_ci if (argc >= NUM_WORKER_ARGS) { 8254d6c458bSopenharmony_ci if (!NapiHelper::IsArray(env, argv[1])) { 8264d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "Transfer list must be an Array"); 8274d6c458bSopenharmony_ci return nullptr; 8284d6c458bSopenharmony_ci } 8294d6c458bSopenharmony_ci serializeStatus = napi_serialize_inner(env, argv[0], argv[1], undefined, false, defaultClone, &data); 8304d6c458bSopenharmony_ci } else { 8314d6c458bSopenharmony_ci napi_value undefined = NapiHelper::GetUndefinedValue(env); 8324d6c458bSopenharmony_ci serializeStatus = napi_serialize_inner(env, argv[0], undefined, undefined, false, defaultClone, &data); 8334d6c458bSopenharmony_ci } 8344d6c458bSopenharmony_ci 8354d6c458bSopenharmony_ci if (serializeStatus != napi_ok || data == nullptr) { 8364d6c458bSopenharmony_ci worker->WorkerOnMessageErrorInner(); 8374d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, "failed to serialize message."); 8384d6c458bSopenharmony_ci return nullptr; 8394d6c458bSopenharmony_ci } 8404d6c458bSopenharmony_ci worker->PostMessageToHostInner(data); 8414d6c458bSopenharmony_ci return NapiHelper::GetUndefinedValue(env); 8424d6c458bSopenharmony_ci} 8434d6c458bSopenharmony_ci 8444d6c458bSopenharmony_cinapi_value Worker::GlobalCall(napi_env env, napi_callback_info cbinfo) 8454d6c458bSopenharmony_ci{ 8464d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 8474d6c458bSopenharmony_ci size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo); 8484d6c458bSopenharmony_ci if (argc < NUM_GLOBAL_CALL_ARGS) { 8494d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 8504d6c458bSopenharmony_ci "the number of parameters must be equal or more than 3."); 8514d6c458bSopenharmony_ci return nullptr; 8524d6c458bSopenharmony_ci } 8534d6c458bSopenharmony_ci napi_value* args = new napi_value[argc]; 8544d6c458bSopenharmony_ci ObjectScope<napi_value> scope(args, true); 8554d6c458bSopenharmony_ci Worker* worker = nullptr; 8564d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, &argc, args, nullptr, reinterpret_cast<void**>(&worker)); 8574d6c458bSopenharmony_ci if (worker == nullptr) { 8584d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker is null when callGlobalCallObjectMethod to host"); 8594d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, 8604d6c458bSopenharmony_ci "worker is null when callGlobalCallObjectMethod to host"); 8614d6c458bSopenharmony_ci return nullptr; 8624d6c458bSopenharmony_ci } 8634d6c458bSopenharmony_ci 8644d6c458bSopenharmony_ci if (!worker->IsRunning()) { 8654d6c458bSopenharmony_ci // if worker is not running, don't send any message to host thread 8664d6c458bSopenharmony_ci HILOG_DEBUG("worker:: when post message to host occur worker is not in running."); 8674d6c458bSopenharmony_ci return nullptr; 8684d6c458bSopenharmony_ci } 8694d6c458bSopenharmony_ci 8704d6c458bSopenharmony_ci if (!NapiHelper::IsString(env, args[0])) { 8714d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 8724d6c458bSopenharmony_ci "the type of instanceName must be string."); 8734d6c458bSopenharmony_ci return nullptr; 8744d6c458bSopenharmony_ci } 8754d6c458bSopenharmony_ci if (!NapiHelper::IsString(env, args[1])) { 8764d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 8774d6c458bSopenharmony_ci "the type of methodname must be string."); 8784d6c458bSopenharmony_ci return nullptr; 8794d6c458bSopenharmony_ci } 8804d6c458bSopenharmony_ci if (!NapiHelper::IsNumber(env, args[2])) { // 2: the index of argument "timeout" 8814d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 8824d6c458bSopenharmony_ci "the type of timeout must be number."); 8834d6c458bSopenharmony_ci return nullptr; 8844d6c458bSopenharmony_ci } 8854d6c458bSopenharmony_ci 8864d6c458bSopenharmony_ci napi_status serializeStatus = napi_ok; 8874d6c458bSopenharmony_ci MessageDataType data = nullptr; 8884d6c458bSopenharmony_ci napi_value argsArray; 8894d6c458bSopenharmony_ci napi_create_array_with_length(env, argc - 1, &argsArray); 8904d6c458bSopenharmony_ci size_t index = 0; 8914d6c458bSopenharmony_ci uint32_t timeout = 0; 8924d6c458bSopenharmony_ci for (size_t i = 0; i < argc; i++) { 8934d6c458bSopenharmony_ci if (i == 2) { // 2: index of time limitation arg 8944d6c458bSopenharmony_ci timeout = NapiHelper::GetUint32Value(env, args[i]); 8954d6c458bSopenharmony_ci continue; 8964d6c458bSopenharmony_ci } 8974d6c458bSopenharmony_ci napi_set_element(env, argsArray, index, args[i]); 8984d6c458bSopenharmony_ci index++; 8994d6c458bSopenharmony_ci } 9004d6c458bSopenharmony_ci if (timeout <= 0 || timeout > DEFAULT_TIMEOUT) { 9014d6c458bSopenharmony_ci timeout = DEFAULT_TIMEOUT; 9024d6c458bSopenharmony_ci } 9034d6c458bSopenharmony_ci 9044d6c458bSopenharmony_ci // defautly not transfer 9054d6c458bSopenharmony_ci napi_value undefined = NapiHelper::GetUndefinedValue(env); 9064d6c458bSopenharmony_ci // meaningless to copy sendable object when call globalObject 9074d6c458bSopenharmony_ci bool defaultClone = true; 9084d6c458bSopenharmony_ci bool defaultTransfer = false; 9094d6c458bSopenharmony_ci serializeStatus = napi_serialize_inner(env, argsArray, undefined, undefined, defaultTransfer, defaultClone, &data); 9104d6c458bSopenharmony_ci if (serializeStatus != napi_ok || data == nullptr) { 9114d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, "failed to serialize message."); 9124d6c458bSopenharmony_ci return nullptr; 9134d6c458bSopenharmony_ci } 9144d6c458bSopenharmony_ci worker->hostGlobalCallQueue_.Push(worker->globalCallId_, data); 9154d6c458bSopenharmony_ci 9164d6c458bSopenharmony_ci std::lock_guard<std::recursive_mutex> lock(worker->liveStatusLock_); 9174d6c458bSopenharmony_ci if (env != nullptr && !worker->HostIsStop() && !worker->isHostEnvExited_) { 9184d6c458bSopenharmony_ci worker->InitGlobalCallStatus(env); 9194d6c458bSopenharmony_ci#if defined(ENABLE_WORKER_EVENTHANDLER) 9204d6c458bSopenharmony_ci if (worker->isMainThreadWorker_ && !worker->isLimitedWorker_) { 9214d6c458bSopenharmony_ci worker->PostWorkerGlobalCallTask(); 9224d6c458bSopenharmony_ci } else { 9234d6c458bSopenharmony_ci uv_async_send(worker->hostOnGlobalCallSignal_); 9244d6c458bSopenharmony_ci } 9254d6c458bSopenharmony_ci#else 9264d6c458bSopenharmony_ci uv_async_send(worker->hostOnGlobalCallSignal_); 9274d6c458bSopenharmony_ci#endif 9284d6c458bSopenharmony_ci } else { 9294d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker host engine is nullptr when callGloballCallObjectMethod."); 9304d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "worker is null"); 9314d6c458bSopenharmony_ci return nullptr; 9324d6c458bSopenharmony_ci } 9334d6c458bSopenharmony_ci 9344d6c458bSopenharmony_ci { 9354d6c458bSopenharmony_ci std::unique_lock lock(worker->globalCallMutex_); 9364d6c458bSopenharmony_ci if (!worker->cv_.wait_for(lock, std::chrono::milliseconds(timeout), [worker]() { 9374d6c458bSopenharmony_ci return !worker->workerGlobalCallQueue_.IsEmpty() || !worker->globalCallSuccess_; 9384d6c458bSopenharmony_ci })) { 9394d6c458bSopenharmony_ci worker->IncreaseGlobalCallId(); 9404d6c458bSopenharmony_ci HILOG_ERROR("worker:: callGlobalCallObjectMethod has exceeded the waiting time limitation, skip this turn"); 9414d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_GLOBAL_CALL_TIMEOUT); 9424d6c458bSopenharmony_ci return nullptr; 9434d6c458bSopenharmony_ci } 9444d6c458bSopenharmony_ci } 9454d6c458bSopenharmony_ci worker->IncreaseGlobalCallId(); 9464d6c458bSopenharmony_ci if (!worker->globalCallSuccess_) { 9474d6c458bSopenharmony_ci worker->HandleGlobalCallError(env); 9484d6c458bSopenharmony_ci return nullptr; 9494d6c458bSopenharmony_ci } 9504d6c458bSopenharmony_ci if (!worker->workerGlobalCallQueue_.DeQueue(&data)) { 9514d6c458bSopenharmony_ci HILOG_ERROR("worker:: message returned from host is empty when callGloballCallObjectMethod"); 9524d6c458bSopenharmony_ci return nullptr; 9534d6c458bSopenharmony_ci } 9544d6c458bSopenharmony_ci napi_value res = nullptr; 9554d6c458bSopenharmony_ci serializeStatus = napi_deserialize(env, data, &res); 9564d6c458bSopenharmony_ci napi_delete_serialization_data(env, data); 9574d6c458bSopenharmony_ci if (serializeStatus != napi_ok || res == nullptr) { 9584d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_SERIALIZATION, "failed to serialize message."); 9594d6c458bSopenharmony_ci return nullptr; 9604d6c458bSopenharmony_ci } 9614d6c458bSopenharmony_ci return res; 9624d6c458bSopenharmony_ci} 9634d6c458bSopenharmony_ci 9644d6c458bSopenharmony_civoid Worker::InitGlobalCallStatus(napi_env env) 9654d6c458bSopenharmony_ci{ 9664d6c458bSopenharmony_ci // worker side event data queue shall be empty before uv_async_send 9674d6c458bSopenharmony_ci workerGlobalCallQueue_.Clear(env); 9684d6c458bSopenharmony_ci ClearGlobalCallError(env); 9694d6c458bSopenharmony_ci globalCallSuccess_ = true; 9704d6c458bSopenharmony_ci} 9714d6c458bSopenharmony_ci 9724d6c458bSopenharmony_civoid Worker::IncreaseGlobalCallId() 9734d6c458bSopenharmony_ci{ 9744d6c458bSopenharmony_ci if (UNLIKELY(globalCallId_ == GLOBAL_CALL_ID_MAX)) { 9754d6c458bSopenharmony_ci globalCallId_ = 1; 9764d6c458bSopenharmony_ci } else { 9774d6c458bSopenharmony_ci globalCallId_++; 9784d6c458bSopenharmony_ci } 9794d6c458bSopenharmony_ci} 9804d6c458bSopenharmony_ci 9814d6c458bSopenharmony_cinapi_value Worker::CloseWorker(napi_env env, napi_callback_info cbinfo) 9824d6c458bSopenharmony_ci{ 9834d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 9844d6c458bSopenharmony_ci Worker* worker = nullptr; 9854d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, nullptr, nullptr, nullptr, (void**)&worker); 9864d6c458bSopenharmony_ci if (worker != nullptr) { 9874d6c458bSopenharmony_ci worker->CloseInner(); 9884d6c458bSopenharmony_ci } else { 9894d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "worker is null"); 9904d6c458bSopenharmony_ci return nullptr; 9914d6c458bSopenharmony_ci } 9924d6c458bSopenharmony_ci return NapiHelper::GetUndefinedValue(env); 9934d6c458bSopenharmony_ci} 9944d6c458bSopenharmony_ci 9954d6c458bSopenharmony_cinapi_value Worker::ParentPortCancelTask(napi_env env, napi_callback_info cbinfo) 9964d6c458bSopenharmony_ci{ 9974d6c458bSopenharmony_ci Worker* worker = nullptr; 9984d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, nullptr, nullptr, nullptr, reinterpret_cast<void**>(&worker)); 9994d6c458bSopenharmony_ci if (worker == nullptr) { 10004d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker is nullptr when CancelTask, maybe worker is terminated"); 10014d6c458bSopenharmony_ci return nullptr; 10024d6c458bSopenharmony_ci } 10034d6c458bSopenharmony_ci 10044d6c458bSopenharmony_ci if (worker->IsTerminated() || worker->IsTerminating()) { 10054d6c458bSopenharmony_ci HILOG_INFO("worker:: worker is not in running"); 10064d6c458bSopenharmony_ci return nullptr; 10074d6c458bSopenharmony_ci } 10084d6c458bSopenharmony_ci 10094d6c458bSopenharmony_ci if (!worker->ClearWorkerTasks()) { 10104d6c458bSopenharmony_ci HILOG_ERROR("worker:: clear worker task error"); 10114d6c458bSopenharmony_ci } 10124d6c458bSopenharmony_ci return NapiHelper::GetUndefinedValue(env); 10134d6c458bSopenharmony_ci} 10144d6c458bSopenharmony_ci 10154d6c458bSopenharmony_cinapi_value Worker::ParentPortAddEventListener(napi_env env, napi_callback_info cbinfo) 10164d6c458bSopenharmony_ci{ 10174d6c458bSopenharmony_ci size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo); 10184d6c458bSopenharmony_ci if (argc < NUM_WORKER_ARGS) { 10194d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, 10204d6c458bSopenharmony_ci ErrorHelper::TYPE_ERROR, "worker listener param count must be more than WORKPARAMNUM."); 10214d6c458bSopenharmony_ci return nullptr; 10224d6c458bSopenharmony_ci } 10234d6c458bSopenharmony_ci 10244d6c458bSopenharmony_ci napi_value* args = new napi_value[argc]; 10254d6c458bSopenharmony_ci ObjectScope<napi_value> scope(args, true); 10264d6c458bSopenharmony_ci Worker* worker = nullptr; 10274d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, &argc, args, nullptr, reinterpret_cast<void**>(&worker)); 10284d6c458bSopenharmony_ci 10294d6c458bSopenharmony_ci if (!NapiHelper::IsString(env, args[0])) { 10304d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 10314d6c458bSopenharmony_ci "the type of worker listener first param must be string."); 10324d6c458bSopenharmony_ci return nullptr; 10334d6c458bSopenharmony_ci } 10344d6c458bSopenharmony_ci 10354d6c458bSopenharmony_ci if (!NapiHelper::IsCallable(env, args[1])) { 10364d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 10374d6c458bSopenharmony_ci "the type of worker listener second param must be callable."); 10384d6c458bSopenharmony_ci return nullptr; 10394d6c458bSopenharmony_ci } 10404d6c458bSopenharmony_ci 10414d6c458bSopenharmony_ci if (worker == nullptr || !worker->IsNotTerminate()) { 10424d6c458bSopenharmony_ci HILOG_ERROR("worker:: when post message to host occur worker is nullptr"); 10434d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "worker is not running."); 10444d6c458bSopenharmony_ci return nullptr; 10454d6c458bSopenharmony_ci } 10464d6c458bSopenharmony_ci 10474d6c458bSopenharmony_ci napi_ref callback = NapiHelper::CreateReference(env, args[1], 1); 10484d6c458bSopenharmony_ci auto listener = new WorkerListener(env, callback, PERMANENT); 10494d6c458bSopenharmony_ci if (argc > NUM_WORKER_ARGS && NapiHelper::IsObject(env, args[NUM_WORKER_ARGS])) { 10504d6c458bSopenharmony_ci napi_value onceValue = NapiHelper::GetNameProperty(env, args[NUM_WORKER_ARGS], "once"); 10514d6c458bSopenharmony_ci bool isOnce = NapiHelper::GetBooleanValue(env, onceValue); 10524d6c458bSopenharmony_ci if (isOnce) { 10534d6c458bSopenharmony_ci listener->SetMode(ONCE); 10544d6c458bSopenharmony_ci } 10554d6c458bSopenharmony_ci } 10564d6c458bSopenharmony_ci char* typeStr = NapiHelper::GetChars(env, args[0]); 10574d6c458bSopenharmony_ci worker->ParentPortAddListenerInner(env, typeStr, listener); 10584d6c458bSopenharmony_ci CloseHelp::DeletePointer(typeStr, true); 10594d6c458bSopenharmony_ci return NapiHelper::GetUndefinedValue(env); 10604d6c458bSopenharmony_ci} 10614d6c458bSopenharmony_ci 10624d6c458bSopenharmony_cinapi_value Worker::ParentPortDispatchEvent(napi_env env, napi_callback_info cbinfo) 10634d6c458bSopenharmony_ci{ 10644d6c458bSopenharmony_ci size_t argc = 1; 10654d6c458bSopenharmony_ci napi_value args[1]; 10664d6c458bSopenharmony_ci Worker* worker = nullptr; 10674d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, &argc, args, nullptr, reinterpret_cast<void**>(&worker)); 10684d6c458bSopenharmony_ci if (argc < 1) { 10694d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "DispatchEvent param count must be more than 1."); 10704d6c458bSopenharmony_ci return NapiHelper::CreateBooleanValue(env, false); 10714d6c458bSopenharmony_ci } 10724d6c458bSopenharmony_ci 10734d6c458bSopenharmony_ci if (!NapiHelper::IsObject(env, args[0])) { 10744d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 10754d6c458bSopenharmony_ci "the type of worker DispatchEvent first param must be Event."); 10764d6c458bSopenharmony_ci return NapiHelper::CreateBooleanValue(env, false); 10774d6c458bSopenharmony_ci } 10784d6c458bSopenharmony_ci 10794d6c458bSopenharmony_ci napi_value typeValue = NapiHelper::GetNameProperty(env, args[0], "type"); 10804d6c458bSopenharmony_ci if (!NapiHelper::IsString(env, typeValue)) { 10814d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 10824d6c458bSopenharmony_ci "the type of worker event must be string."); 10834d6c458bSopenharmony_ci return NapiHelper::CreateBooleanValue(env, false); 10844d6c458bSopenharmony_ci } 10854d6c458bSopenharmony_ci 10864d6c458bSopenharmony_ci if (worker == nullptr || !worker->IsNotTerminate()) { 10874d6c458bSopenharmony_ci HILOG_ERROR("worker:: when post message to host occur worker is nullptr"); 10884d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "worker is nullptr."); 10894d6c458bSopenharmony_ci return NapiHelper::CreateBooleanValue(env, false); 10904d6c458bSopenharmony_ci } 10914d6c458bSopenharmony_ci 10924d6c458bSopenharmony_ci char* typeStr = NapiHelper::GetChars(env, typeValue); 10934d6c458bSopenharmony_ci if (typeStr == nullptr) { 10944d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "worker listener type must be not null."); 10954d6c458bSopenharmony_ci return NapiHelper::CreateBooleanValue(env, false); 10964d6c458bSopenharmony_ci } 10974d6c458bSopenharmony_ci 10984d6c458bSopenharmony_ci napi_value obj = NapiHelper::GetReferenceValue(env, worker->workerPort_); 10994d6c458bSopenharmony_ci 11004d6c458bSopenharmony_ci if (strcmp(typeStr, "error") == 0) { 11014d6c458bSopenharmony_ci CallWorkCallback(env, obj, 1, args, "onerror"); 11024d6c458bSopenharmony_ci } else if (strcmp(typeStr, "messageerror") == 0) { 11034d6c458bSopenharmony_ci CallWorkCallback(env, obj, 1, args, "onmessageerror"); 11044d6c458bSopenharmony_ci } else if (strcmp(typeStr, "message") == 0) { 11054d6c458bSopenharmony_ci CallWorkCallback(env, obj, 1, args, "onmessage"); 11064d6c458bSopenharmony_ci } 11074d6c458bSopenharmony_ci 11084d6c458bSopenharmony_ci worker->ParentPortHandleEventListeners(env, obj, 1, args, typeStr, true); 11094d6c458bSopenharmony_ci 11104d6c458bSopenharmony_ci CloseHelp::DeletePointer(typeStr, true); 11114d6c458bSopenharmony_ci return NapiHelper::CreateBooleanValue(env, true); 11124d6c458bSopenharmony_ci} 11134d6c458bSopenharmony_ci 11144d6c458bSopenharmony_cinapi_value Worker::ParentPortRemoveEventListener(napi_env env, napi_callback_info cbinfo) 11154d6c458bSopenharmony_ci{ 11164d6c458bSopenharmony_ci size_t argc = NapiHelper::GetCallbackInfoArgc(env, cbinfo); 11174d6c458bSopenharmony_ci if (argc < 1) { 11184d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the number of parameters must be more than 2."); 11194d6c458bSopenharmony_ci return nullptr; 11204d6c458bSopenharmony_ci } 11214d6c458bSopenharmony_ci 11224d6c458bSopenharmony_ci napi_value* args = new napi_value[argc]; 11234d6c458bSopenharmony_ci ObjectScope<napi_value> scope(args, true); 11244d6c458bSopenharmony_ci Worker* worker = nullptr; 11254d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, &argc, args, nullptr, reinterpret_cast<void**>(&worker)); 11264d6c458bSopenharmony_ci 11274d6c458bSopenharmony_ci if (!NapiHelper::IsString(env, args[0])) { 11284d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "the type of worker listener 1st param must be string."); 11294d6c458bSopenharmony_ci return nullptr; 11304d6c458bSopenharmony_ci } 11314d6c458bSopenharmony_ci 11324d6c458bSopenharmony_ci if (argc > 1 && !NapiHelper::IsCallable(env, args[1])) { 11334d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, 11344d6c458bSopenharmony_ci "the type of worker listener second param must be callable."); 11354d6c458bSopenharmony_ci return nullptr; 11364d6c458bSopenharmony_ci } 11374d6c458bSopenharmony_ci 11384d6c458bSopenharmony_ci if (worker == nullptr || !worker->IsNotTerminate()) { 11394d6c458bSopenharmony_ci HILOG_ERROR("worker:: when post message to host occur worker is nullptr"); 11404d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "worker is not running."); 11414d6c458bSopenharmony_ci return nullptr; 11424d6c458bSopenharmony_ci } 11434d6c458bSopenharmony_ci 11444d6c458bSopenharmony_ci napi_ref callback = nullptr; 11454d6c458bSopenharmony_ci if (argc > 1 && NapiHelper::IsCallable(env, args[1])) { 11464d6c458bSopenharmony_ci napi_create_reference(env, args[1], 1, &callback); 11474d6c458bSopenharmony_ci } 11484d6c458bSopenharmony_ci 11494d6c458bSopenharmony_ci char* typeStr = NapiHelper::GetChars(env, args[0]); 11504d6c458bSopenharmony_ci if (typeStr == nullptr) { 11514d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::TYPE_ERROR, "worker listener type must be not null."); 11524d6c458bSopenharmony_ci return nullptr; 11534d6c458bSopenharmony_ci } 11544d6c458bSopenharmony_ci worker->ParentPortRemoveListenerInner(env, typeStr, callback); 11554d6c458bSopenharmony_ci CloseHelp::DeletePointer(typeStr, true); 11564d6c458bSopenharmony_ci NapiHelper::DeleteReference(env, callback); 11574d6c458bSopenharmony_ci return NapiHelper::GetUndefinedValue(env); 11584d6c458bSopenharmony_ci} 11594d6c458bSopenharmony_ci 11604d6c458bSopenharmony_cinapi_value Worker::ParentPortRemoveAllListener(napi_env env, napi_callback_info cbinfo) 11614d6c458bSopenharmony_ci{ 11624d6c458bSopenharmony_ci Worker* worker = nullptr; 11634d6c458bSopenharmony_ci napi_get_cb_info(env, cbinfo, nullptr, nullptr, nullptr, reinterpret_cast<void**>(&worker)); 11644d6c458bSopenharmony_ci 11654d6c458bSopenharmony_ci if (worker == nullptr || !worker->IsNotTerminate()) { 11664d6c458bSopenharmony_ci HILOG_ERROR("worker:: when post message to host occur worker is nullptr"); 11674d6c458bSopenharmony_ci WorkerThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, 11684d6c458bSopenharmony_ci "worker is nullptr when ParentPortRemoveAllListener"); 11694d6c458bSopenharmony_ci return nullptr; 11704d6c458bSopenharmony_ci } 11714d6c458bSopenharmony_ci 11724d6c458bSopenharmony_ci worker->ParentPortRemoveAllListenerInner(); 11734d6c458bSopenharmony_ci return NapiHelper::GetUndefinedValue(env); 11744d6c458bSopenharmony_ci} 11754d6c458bSopenharmony_ci 11764d6c458bSopenharmony_civoid Worker::GetContainerScopeId(napi_env env) 11774d6c458bSopenharmony_ci{ 11784d6c458bSopenharmony_ci NativeEngine* hostEngine = reinterpret_cast<NativeEngine*>(env); 11794d6c458bSopenharmony_ci scopeId_ = hostEngine->GetContainerScopeIdFunc(); 11804d6c458bSopenharmony_ci} 11814d6c458bSopenharmony_ci 11824d6c458bSopenharmony_civoid Worker::AddGlobalCallObject(const std::string &instanceName, napi_ref obj) 11834d6c458bSopenharmony_ci{ 11844d6c458bSopenharmony_ci globalCallObjects_.insert_or_assign(instanceName, obj); 11854d6c458bSopenharmony_ci} 11864d6c458bSopenharmony_ci 11874d6c458bSopenharmony_cibool Worker::RemoveGlobalCallObject(const std::string &instanceName) 11884d6c458bSopenharmony_ci{ 11894d6c458bSopenharmony_ci for (auto iter = globalCallObjects_.begin(); iter != globalCallObjects_.end(); iter++) { 11904d6c458bSopenharmony_ci if (iter->first == instanceName) { 11914d6c458bSopenharmony_ci NapiHelper::DeleteReference(hostEnv_, iter->second); 11924d6c458bSopenharmony_ci globalCallObjects_.erase(iter); 11934d6c458bSopenharmony_ci return true; 11944d6c458bSopenharmony_ci } 11954d6c458bSopenharmony_ci } 11964d6c458bSopenharmony_ci return false; 11974d6c458bSopenharmony_ci} 11984d6c458bSopenharmony_ci 11994d6c458bSopenharmony_civoid Worker::ClearGlobalCallObject() 12004d6c458bSopenharmony_ci{ 12014d6c458bSopenharmony_ci for (auto iter = globalCallObjects_.begin(); iter != globalCallObjects_.end(); iter++) { 12024d6c458bSopenharmony_ci napi_ref objRef = iter->second; 12034d6c458bSopenharmony_ci NapiHelper::DeleteReference(hostEnv_, objRef); 12044d6c458bSopenharmony_ci } 12054d6c458bSopenharmony_ci globalCallObjects_.clear(); 12064d6c458bSopenharmony_ci} 12074d6c458bSopenharmony_ci 12084d6c458bSopenharmony_civoid Worker::StartExecuteInThread(napi_env env, const char* script) 12094d6c458bSopenharmony_ci{ 12104d6c458bSopenharmony_ci HILOG_INFO("worker:: Start execute in the thread!"); 12114d6c458bSopenharmony_ci // 1. init hostHandle in host loop 12124d6c458bSopenharmony_ci uv_loop_t* loop = NapiHelper::GetLibUV(env); 12134d6c458bSopenharmony_ci if (loop == nullptr) { 12144d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "engine loop is null"); 12154d6c458bSopenharmony_ci CloseHelp::DeletePointer(script, true); 12164d6c458bSopenharmony_ci return; 12174d6c458bSopenharmony_ci } 12184d6c458bSopenharmony_ci GetContainerScopeId(env); 12194d6c458bSopenharmony_ci#if defined(ENABLE_WORKER_EVENTHANDLER) 12204d6c458bSopenharmony_ci if (!OHOS::AppExecFwk::EventRunner::IsAppMainThread()) { 12214d6c458bSopenharmony_ci isMainThreadWorker_ = false; 12224d6c458bSopenharmony_ci InitHostHandle(loop); 12234d6c458bSopenharmony_ci } else if (isLimitedWorker_) { 12244d6c458bSopenharmony_ci InitHostHandle(loop); 12254d6c458bSopenharmony_ci } 12264d6c458bSopenharmony_ci#else 12274d6c458bSopenharmony_ci InitHostHandle(loop); 12284d6c458bSopenharmony_ci#endif 12294d6c458bSopenharmony_ci 12304d6c458bSopenharmony_ci // 2. copy the script 12314d6c458bSopenharmony_ci script_ = std::string(script); 12324d6c458bSopenharmony_ci // isBundle : FA mode and BundlePack. 12334d6c458bSopenharmony_ci bool isBundle = reinterpret_cast<NativeEngine*>(env)->GetIsBundle(); 12344d6c458bSopenharmony_ci // if worker file is packed in har, need find moduleName in hostVM, and concat new recordName. 12354d6c458bSopenharmony_ci bool isHar = script_.find_first_of(PathHelper::NAME_SPACE_TAG) == 0; 12364d6c458bSopenharmony_ci if ((isHar && script_.find(PathHelper::PREFIX_BUNDLE) == std::string::npos) || 12374d6c458bSopenharmony_ci (!isBundle && script_.find_first_of(PathHelper::POINT_TAG) == 0)) { 12384d6c458bSopenharmony_ci PathHelper::ConcatFileNameForWorker(env, script_, fileName_, isRelativePath_); 12394d6c458bSopenharmony_ci HILOG_INFO("worker:: Concated worker recordName: %{public}s, fileName: %{public}s", 12404d6c458bSopenharmony_ci script_.c_str(), fileName_.c_str()); 12414d6c458bSopenharmony_ci } 12424d6c458bSopenharmony_ci // check the path is vaild. 12434d6c458bSopenharmony_ci if (!isBundle) { 12444d6c458bSopenharmony_ci if (!PathHelper::CheckWorkerPath(env, script_, fileName_, isRelativePath_)) { 12454d6c458bSopenharmony_ci EraseWorker(); 12464d6c458bSopenharmony_ci HILOG_ERROR("worker:: the file path is invaild, can't find the file : %{public}s.", script); 12474d6c458bSopenharmony_ci CloseHelp::DeletePointer(script, true); 12484d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_INVALID_FILEPATH, 12494d6c458bSopenharmony_ci "the file path is invaild, can't find the file."); 12504d6c458bSopenharmony_ci return; 12514d6c458bSopenharmony_ci } 12524d6c458bSopenharmony_ci } 12534d6c458bSopenharmony_ci 12544d6c458bSopenharmony_ci // 3. create WorkerRunner to Execute 12554d6c458bSopenharmony_ci if (!runner_) { 12564d6c458bSopenharmony_ci runner_ = std::make_unique<WorkerRunner>(WorkerStartCallback(ExecuteInThread, this)); 12574d6c458bSopenharmony_ci } 12584d6c458bSopenharmony_ci if (runner_) { 12594d6c458bSopenharmony_ci runner_->Execute(); // start a new thread 12604d6c458bSopenharmony_ci } else { 12614d6c458bSopenharmony_ci HILOG_ERROR("runner_ is nullptr"); 12624d6c458bSopenharmony_ci } 12634d6c458bSopenharmony_ci CloseHelp::DeletePointer(script, true); 12644d6c458bSopenharmony_ci} 12654d6c458bSopenharmony_ci 12664d6c458bSopenharmony_civoid Worker::ExecuteInThread(const void* data) 12674d6c458bSopenharmony_ci{ 12684d6c458bSopenharmony_ci HITRACE_HELPER_START_TRACE(__PRETTY_FUNCTION__); 12694d6c458bSopenharmony_ci auto worker = reinterpret_cast<Worker*>(const_cast<void*>(data)); 12704d6c458bSopenharmony_ci // 1. create a runtime, nativeengine 12714d6c458bSopenharmony_ci napi_env workerEnv = nullptr; 12724d6c458bSopenharmony_ci { 12734d6c458bSopenharmony_ci std::lock_guard<std::recursive_mutex> lock(worker->liveStatusLock_); 12744d6c458bSopenharmony_ci if (worker->HostIsStop() || worker->isHostEnvExited_) { 12754d6c458bSopenharmony_ci HILOG_ERROR("worker:: host thread is stop"); 12764d6c458bSopenharmony_ci CloseHelp::DeletePointer(worker, false); 12774d6c458bSopenharmony_ci return; 12784d6c458bSopenharmony_ci } 12794d6c458bSopenharmony_ci napi_env env = worker->GetHostEnv(); 12804d6c458bSopenharmony_ci if (worker->isLimitedWorker_) { 12814d6c458bSopenharmony_ci napi_create_limit_runtime(env, &workerEnv); 12824d6c458bSopenharmony_ci } else { 12834d6c458bSopenharmony_ci napi_create_runtime(env, &workerEnv); 12844d6c458bSopenharmony_ci } 12854d6c458bSopenharmony_ci if (workerEnv == nullptr) { 12864d6c458bSopenharmony_ci HILOG_ERROR("worker:: Worker create runtime error"); 12874d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, ErrorHelper::ERR_WORKER_NOT_RUNNING, "Worker create runtime error"); 12884d6c458bSopenharmony_ci return; 12894d6c458bSopenharmony_ci } 12904d6c458bSopenharmony_ci if (worker->isLimitedWorker_) { 12914d6c458bSopenharmony_ci reinterpret_cast<NativeEngine*>(workerEnv)->MarkRestrictedWorkerThread(); 12924d6c458bSopenharmony_ci } else { 12934d6c458bSopenharmony_ci // mark worker env is workerThread 12944d6c458bSopenharmony_ci reinterpret_cast<NativeEngine*>(workerEnv)->MarkWorkerThread(); 12954d6c458bSopenharmony_ci } 12964d6c458bSopenharmony_ci // for load balance in taskpool 12974d6c458bSopenharmony_ci reinterpret_cast<NativeEngine*>(env)->IncreaseSubEnvCounter(); 12984d6c458bSopenharmony_ci 12994d6c458bSopenharmony_ci worker->SetWorkerEnv(workerEnv); 13004d6c458bSopenharmony_ci } 13014d6c458bSopenharmony_ci 13024d6c458bSopenharmony_ci uv_loop_t* loop = worker->GetWorkerLoop(); 13034d6c458bSopenharmony_ci if (loop == nullptr) { 13044d6c458bSopenharmony_ci HILOG_ERROR("worker:: Worker loop is nullptr"); 13054d6c458bSopenharmony_ci return; 13064d6c458bSopenharmony_ci } 13074d6c458bSopenharmony_ci 13084d6c458bSopenharmony_ci // 2. add some preparation for the worker 13094d6c458bSopenharmony_ci if (worker->PrepareForWorkerInstance()) { 13104d6c458bSopenharmony_ci worker->workerOnMessageSignal_ = new uv_async_t; 13114d6c458bSopenharmony_ci uv_async_init(loop, worker->workerOnMessageSignal_, reinterpret_cast<uv_async_cb>(Worker::WorkerOnMessage)); 13124d6c458bSopenharmony_ci worker->workerOnMessageSignal_->data = worker; 13134d6c458bSopenharmony_ci#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) 13144d6c458bSopenharmony_ci uv_async_init(loop, &worker->debuggerOnPostTaskSignal_, reinterpret_cast<uv_async_cb>( 13154d6c458bSopenharmony_ci Worker::HandleDebuggerTask)); 13164d6c458bSopenharmony_ci#endif 13174d6c458bSopenharmony_ci worker->UpdateWorkerState(RUNNING); 13184d6c458bSopenharmony_ci // in order to invoke worker send before subThread start 13194d6c458bSopenharmony_ci uv_async_send(worker->workerOnMessageSignal_); 13204d6c458bSopenharmony_ci HITRACE_HELPER_FINISH_TRACE; 13214d6c458bSopenharmony_ci // 3. start worker loop 13224d6c458bSopenharmony_ci worker->Loop(); 13234d6c458bSopenharmony_ci } else { 13244d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker PrepareForWorkerInstance fail"); 13254d6c458bSopenharmony_ci worker->UpdateWorkerState(TERMINATED); 13264d6c458bSopenharmony_ci HITRACE_HELPER_FINISH_TRACE; 13274d6c458bSopenharmony_ci } 13284d6c458bSopenharmony_ci worker->ReleaseWorkerThreadContent(); 13294d6c458bSopenharmony_ci std::lock_guard<std::recursive_mutex> lock(worker->liveStatusLock_); 13304d6c458bSopenharmony_ci if (worker->HostIsStop() || worker->isHostEnvExited_) { 13314d6c458bSopenharmony_ci HILOG_INFO("worker:: host is stopped"); 13324d6c458bSopenharmony_ci CloseHelp::DeletePointer(worker, false); 13334d6c458bSopenharmony_ci } else { 13344d6c458bSopenharmony_ci worker->PublishWorkerOverSignal(); 13354d6c458bSopenharmony_ci } 13364d6c458bSopenharmony_ci} 13374d6c458bSopenharmony_ci 13384d6c458bSopenharmony_cibool Worker::PrepareForWorkerInstance() 13394d6c458bSopenharmony_ci{ 13404d6c458bSopenharmony_ci std::string rawFileName = script_; 13414d6c458bSopenharmony_ci uint8_t* scriptContent = nullptr; 13424d6c458bSopenharmony_ci size_t scriptContentSize = 0; 13434d6c458bSopenharmony_ci std::vector<uint8_t> content; 13444d6c458bSopenharmony_ci std::string workerAmi; 13454d6c458bSopenharmony_ci { 13464d6c458bSopenharmony_ci std::lock_guard<std::recursive_mutex> lock(liveStatusLock_); 13474d6c458bSopenharmony_ci if (HostIsStop() || isHostEnvExited_) { 13484d6c458bSopenharmony_ci HILOG_INFO("worker:: host is stopped"); 13494d6c458bSopenharmony_ci return false; 13504d6c458bSopenharmony_ci } 13514d6c458bSopenharmony_ci auto workerEngine = reinterpret_cast<NativeEngine*>(workerEnv_); 13524d6c458bSopenharmony_ci auto hostEngine = reinterpret_cast<NativeEngine*>(hostEnv_); 13534d6c458bSopenharmony_ci // 1. init worker environment 13544d6c458bSopenharmony_ci#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) 13554d6c458bSopenharmony_ci workerEngine->SetDebuggerPostTaskFunc([this](std::function<void()>&& task) { 13564d6c458bSopenharmony_ci this->DebuggerOnPostTask(std::move(task)); 13574d6c458bSopenharmony_ci }); 13584d6c458bSopenharmony_ci#endif 13594d6c458bSopenharmony_ci if (!hostEngine->CallInitWorkerFunc(workerEngine)) { 13604d6c458bSopenharmony_ci HILOG_ERROR("worker:: CallInitWorkerFunc error"); 13614d6c458bSopenharmony_ci return false; 13624d6c458bSopenharmony_ci } 13634d6c458bSopenharmony_ci // 2. get uril content 13644d6c458bSopenharmony_ci if (isRelativePath_) { 13654d6c458bSopenharmony_ci rawFileName = fileName_; 13664d6c458bSopenharmony_ci } 13674d6c458bSopenharmony_ci if (!hostEngine->GetAbcBuffer(rawFileName.c_str(), &scriptContent, &scriptContentSize, content, workerAmi)) { 13684d6c458bSopenharmony_ci HILOG_ERROR("worker:: GetAbcBuffer error"); 13694d6c458bSopenharmony_ci return false; 13704d6c458bSopenharmony_ci } 13714d6c458bSopenharmony_ci } 13724d6c458bSopenharmony_ci // add timer interface 13734d6c458bSopenharmony_ci Timer::RegisterTime(workerEnv_); 13744d6c458bSopenharmony_ci HILOG_DEBUG("worker:: stringContent size is %{public}zu", scriptContentSize); 13754d6c458bSopenharmony_ci napi_value execScriptResult = nullptr; 13764d6c458bSopenharmony_ci napi_status status = napi_run_actor(workerEnv_, scriptContent, scriptContentSize, 13774d6c458bSopenharmony_ci workerAmi.c_str(), &execScriptResult, const_cast<char*>(script_.c_str())); 13784d6c458bSopenharmony_ci if (status != napi_ok || execScriptResult == nullptr) { 13794d6c458bSopenharmony_ci // An exception occurred when running the script. 13804d6c458bSopenharmony_ci HILOG_ERROR("worker:: run script exception occurs, will handle exception"); 13814d6c458bSopenharmony_ci HandleException(); 13824d6c458bSopenharmony_ci return false; 13834d6c458bSopenharmony_ci } 13844d6c458bSopenharmony_ci 13854d6c458bSopenharmony_ci // 4. register worker name in DedicatedWorkerGlobalScope 13864d6c458bSopenharmony_ci if (!name_.empty()) { 13874d6c458bSopenharmony_ci napi_value nameValue = nullptr; 13884d6c458bSopenharmony_ci napi_create_string_utf8(workerEnv_, name_.c_str(), name_.length(), &nameValue); 13894d6c458bSopenharmony_ci NapiHelper::SetNamePropertyInGlobal(workerEnv_, "name", nameValue); 13904d6c458bSopenharmony_ci } 13914d6c458bSopenharmony_ci return true; 13924d6c458bSopenharmony_ci} 13934d6c458bSopenharmony_ci 13944d6c458bSopenharmony_civoid Worker::HostOnMessage(const uv_async_t* req) 13954d6c458bSopenharmony_ci{ 13964d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 13974d6c458bSopenharmony_ci Worker* worker = static_cast<Worker*>(req->data); 13984d6c458bSopenharmony_ci if (worker == nullptr) { 13994d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker is null when host onmessage."); 14004d6c458bSopenharmony_ci return; 14014d6c458bSopenharmony_ci } 14024d6c458bSopenharmony_ci worker->HostOnMessageInner(); 14034d6c458bSopenharmony_ci} 14044d6c458bSopenharmony_ci 14054d6c458bSopenharmony_civoid Worker::HostOnMessageInner() 14064d6c458bSopenharmony_ci{ 14074d6c458bSopenharmony_ci if (hostEnv_ == nullptr || HostIsStop()) { 14084d6c458bSopenharmony_ci HILOG_ERROR("worker:: host thread maybe is over when host onmessage."); 14094d6c458bSopenharmony_ci return; 14104d6c458bSopenharmony_ci } 14114d6c458bSopenharmony_ci 14124d6c458bSopenharmony_ci NativeEngine* engine = reinterpret_cast<NativeEngine*>(hostEnv_); 14134d6c458bSopenharmony_ci if (!engine->InitContainerScopeFunc(scopeId_)) { 14144d6c458bSopenharmony_ci HILOG_WARN("worker:: InitContainerScopeFunc error when HostOnMessageInner begin(only stage model)"); 14154d6c458bSopenharmony_ci } 14164d6c458bSopenharmony_ci 14174d6c458bSopenharmony_ci napi_value obj = NapiHelper::GetReferenceValue(hostEnv_, workerRef_); 14184d6c458bSopenharmony_ci napi_value callback = NapiHelper::GetNameProperty(hostEnv_, obj, "onmessage"); 14194d6c458bSopenharmony_ci bool isCallable = NapiHelper::IsCallable(hostEnv_, callback); 14204d6c458bSopenharmony_ci 14214d6c458bSopenharmony_ci MessageDataType data = nullptr; 14224d6c458bSopenharmony_ci while (hostMessageQueue_.DeQueue(&data)) { 14234d6c458bSopenharmony_ci // receive close signal. 14244d6c458bSopenharmony_ci if (data == nullptr) { 14254d6c458bSopenharmony_ci HILOG_DEBUG("worker:: worker received close signal"); 14264d6c458bSopenharmony_ci#if defined(ENABLE_WORKER_EVENTHANDLER) 14274d6c458bSopenharmony_ci if ((!isMainThreadWorker_ || isLimitedWorker_) && !isHostEnvExited_) { 14284d6c458bSopenharmony_ci CloseHostHandle(); 14294d6c458bSopenharmony_ci } 14304d6c458bSopenharmony_ci#else 14314d6c458bSopenharmony_ci if (!isHostEnvExited_) { 14324d6c458bSopenharmony_ci CloseHostHandle(); 14334d6c458bSopenharmony_ci } 14344d6c458bSopenharmony_ci#endif 14354d6c458bSopenharmony_ci CloseHostCallback(); 14364d6c458bSopenharmony_ci return; 14374d6c458bSopenharmony_ci } 14384d6c458bSopenharmony_ci // handle data, call worker onMessage function to handle. 14394d6c458bSopenharmony_ci napi_status status = napi_ok; 14404d6c458bSopenharmony_ci HandleScope scope(hostEnv_, status); 14414d6c458bSopenharmony_ci NAPI_CALL_RETURN_VOID(hostEnv_, status); 14424d6c458bSopenharmony_ci napi_value result = nullptr; 14434d6c458bSopenharmony_ci status = napi_deserialize(hostEnv_, data, &result); 14444d6c458bSopenharmony_ci napi_delete_serialization_data(hostEnv_, data); 14454d6c458bSopenharmony_ci if (status != napi_ok || result == nullptr) { 14464d6c458bSopenharmony_ci HostOnMessageErrorInner(); 14474d6c458bSopenharmony_ci continue; 14484d6c458bSopenharmony_ci } 14494d6c458bSopenharmony_ci napi_value event = nullptr; 14504d6c458bSopenharmony_ci napi_create_object(hostEnv_, &event); 14514d6c458bSopenharmony_ci napi_set_named_property(hostEnv_, event, "data", result); 14524d6c458bSopenharmony_ci napi_value argv[1] = { event }; 14534d6c458bSopenharmony_ci if (isCallable) { 14544d6c458bSopenharmony_ci napi_value callbackResult = nullptr; 14554d6c458bSopenharmony_ci napi_call_function(hostEnv_, obj, callback, 1, argv, &callbackResult); 14564d6c458bSopenharmony_ci } 14574d6c458bSopenharmony_ci // handle listeners. 14584d6c458bSopenharmony_ci HandleEventListeners(hostEnv_, obj, 1, argv, "message"); 14594d6c458bSopenharmony_ci HandleHostException(); 14604d6c458bSopenharmony_ci } 14614d6c458bSopenharmony_ci if (!engine->FinishContainerScopeFunc(scopeId_)) { 14624d6c458bSopenharmony_ci HILOG_WARN("worker:: FinishContainerScopeFunc error when HostOnMessageInner end(only stage model)"); 14634d6c458bSopenharmony_ci } 14644d6c458bSopenharmony_ci} 14654d6c458bSopenharmony_ci 14664d6c458bSopenharmony_civoid Worker::HostOnGlobalCall(const uv_async_t* req) 14674d6c458bSopenharmony_ci{ 14684d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 14694d6c458bSopenharmony_ci Worker* worker = static_cast<Worker*>(req->data); 14704d6c458bSopenharmony_ci if (worker == nullptr) { 14714d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker is null"); 14724d6c458bSopenharmony_ci return; 14734d6c458bSopenharmony_ci } 14744d6c458bSopenharmony_ci worker->HostOnGlobalCallInner(); 14754d6c458bSopenharmony_ci} 14764d6c458bSopenharmony_ci 14774d6c458bSopenharmony_civoid Worker::HostOnGlobalCallInner() 14784d6c458bSopenharmony_ci{ 14794d6c458bSopenharmony_ci if (hostEnv_ == nullptr || HostIsStop()) { 14804d6c458bSopenharmony_ci HILOG_ERROR("worker:: host thread maybe is over when host onmessage."); 14814d6c458bSopenharmony_ci globalCallSuccess_ = false; 14824d6c458bSopenharmony_ci cv_.notify_one(); 14834d6c458bSopenharmony_ci return; 14844d6c458bSopenharmony_ci } 14854d6c458bSopenharmony_ci 14864d6c458bSopenharmony_ci NativeEngine* engine = reinterpret_cast<NativeEngine*>(hostEnv_); 14874d6c458bSopenharmony_ci if (!engine->InitContainerScopeFunc(scopeId_)) { 14884d6c458bSopenharmony_ci HILOG_WARN("worker:: InitContainerScopeFunc error when HostOnMessageInner begin(only stage model)"); 14894d6c458bSopenharmony_ci } 14904d6c458bSopenharmony_ci 14914d6c458bSopenharmony_ci if (hostGlobalCallQueue_.IsEmpty()) { 14924d6c458bSopenharmony_ci HILOG_ERROR("worker:: message queue is empty when HostOnGlobalCallInner"); 14934d6c458bSopenharmony_ci globalCallSuccess_ = false; 14944d6c458bSopenharmony_ci cv_.notify_one(); 14954d6c458bSopenharmony_ci return; 14964d6c458bSopenharmony_ci } 14974d6c458bSopenharmony_ci MessageDataType data = nullptr; 14984d6c458bSopenharmony_ci uint32_t currentCallId = 0; 14994d6c458bSopenharmony_ci size_t size = hostGlobalCallQueue_.GetSize(); 15004d6c458bSopenharmony_ci if (size < 0 || size > GLOBAL_CALL_MAX_COUNT) { 15014d6c458bSopenharmony_ci HILOG_ERROR("worker:: hostGlobalCallQueue_ size error"); 15024d6c458bSopenharmony_ci globalCallSuccess_ = false; 15034d6c458bSopenharmony_ci cv_.notify_one(); 15044d6c458bSopenharmony_ci return; 15054d6c458bSopenharmony_ci } 15064d6c458bSopenharmony_ci for (size_t i = 0; i < size; i++) { 15074d6c458bSopenharmony_ci std::pair<uint32_t, MessageDataType> pair = hostGlobalCallQueue_.Front(); 15084d6c458bSopenharmony_ci hostGlobalCallQueue_.Pop(); 15094d6c458bSopenharmony_ci if (pair.first == globalCallId_) { 15104d6c458bSopenharmony_ci currentCallId = pair.first; 15114d6c458bSopenharmony_ci data = pair.second; 15124d6c458bSopenharmony_ci break; 15134d6c458bSopenharmony_ci } 15144d6c458bSopenharmony_ci napi_delete_serialization_data(hostEnv_, pair.second); 15154d6c458bSopenharmony_ci } 15164d6c458bSopenharmony_ci napi_value argsArray = nullptr; 15174d6c458bSopenharmony_ci napi_status status = napi_ok; 15184d6c458bSopenharmony_ci status = napi_deserialize(hostEnv_, data, &argsArray); 15194d6c458bSopenharmony_ci napi_delete_serialization_data(hostEnv_, data); 15204d6c458bSopenharmony_ci if (status != napi_ok || argsArray == nullptr) { 15214d6c458bSopenharmony_ci AddGlobalCallError(ErrorHelper::ERR_WORKER_SERIALIZATION); 15224d6c458bSopenharmony_ci globalCallSuccess_ = false; 15234d6c458bSopenharmony_ci cv_.notify_one(); 15244d6c458bSopenharmony_ci return; 15254d6c458bSopenharmony_ci } 15264d6c458bSopenharmony_ci napi_value instanceName = nullptr; 15274d6c458bSopenharmony_ci napi_get_element(hostEnv_, argsArray, 0, &instanceName); 15284d6c458bSopenharmony_ci napi_value methodName = nullptr; 15294d6c458bSopenharmony_ci napi_get_element(hostEnv_, argsArray, 1, &methodName); 15304d6c458bSopenharmony_ci 15314d6c458bSopenharmony_ci std::string instanceNameStr = NapiHelper::GetString(hostEnv_, instanceName); 15324d6c458bSopenharmony_ci auto iter = globalCallObjects_.find(instanceNameStr); 15334d6c458bSopenharmony_ci if (iter == globalCallObjects_.end()) { 15344d6c458bSopenharmony_ci HILOG_ERROR("worker:: there is no instance: %{public}s registered for global call", instanceNameStr.c_str()); 15354d6c458bSopenharmony_ci AddGlobalCallError(ErrorHelper::ERR_TRIGGER_NONEXIST_EVENT); 15364d6c458bSopenharmony_ci globalCallSuccess_ = false; 15374d6c458bSopenharmony_ci cv_.notify_one(); 15384d6c458bSopenharmony_ci return; 15394d6c458bSopenharmony_ci } 15404d6c458bSopenharmony_ci napi_ref objRef = iter->second; 15414d6c458bSopenharmony_ci napi_value obj = NapiHelper::GetReferenceValue(hostEnv_, objRef); 15424d6c458bSopenharmony_ci bool hasProperty = false; 15434d6c458bSopenharmony_ci napi_has_property(hostEnv_, obj, methodName, &hasProperty); 15444d6c458bSopenharmony_ci if (!hasProperty) { 15454d6c458bSopenharmony_ci std::string methodNameStr = NapiHelper::GetString(hostEnv_, methodName); 15464d6c458bSopenharmony_ci HILOG_ERROR("worker:: registered obj for global call has no method: %{public}s", methodNameStr.c_str()); 15474d6c458bSopenharmony_ci AddGlobalCallError(ErrorHelper::ERR_CALL_METHOD_ON_BINDING_OBJ); 15484d6c458bSopenharmony_ci globalCallSuccess_ = false; 15494d6c458bSopenharmony_ci cv_.notify_one(); 15504d6c458bSopenharmony_ci return; 15514d6c458bSopenharmony_ci } 15524d6c458bSopenharmony_ci napi_value method = nullptr; 15534d6c458bSopenharmony_ci napi_get_property(hostEnv_, obj, methodName, &method); 15544d6c458bSopenharmony_ci // call method must not be generator function or async function 15554d6c458bSopenharmony_ci bool validMethod = NapiHelper::IsCallable(hostEnv_, method) && !NapiHelper::IsAsyncFunction(hostEnv_, method) && 15564d6c458bSopenharmony_ci !NapiHelper::IsGeneratorFunction(hostEnv_, method); 15574d6c458bSopenharmony_ci if (!validMethod) { 15584d6c458bSopenharmony_ci std::string methodNameStr = NapiHelper::GetString(hostEnv_, methodName); 15594d6c458bSopenharmony_ci HILOG_ERROR("worker:: method %{public}s shall be callable and not async or generator method", 15604d6c458bSopenharmony_ci methodNameStr.c_str()); 15614d6c458bSopenharmony_ci AddGlobalCallError(ErrorHelper::ERR_CALL_METHOD_ON_BINDING_OBJ); 15624d6c458bSopenharmony_ci globalCallSuccess_ = false; 15634d6c458bSopenharmony_ci cv_.notify_one(); 15644d6c458bSopenharmony_ci return; 15654d6c458bSopenharmony_ci } 15664d6c458bSopenharmony_ci uint32_t argc = 0; 15674d6c458bSopenharmony_ci napi_get_array_length(hostEnv_, argsArray, &argc); 15684d6c458bSopenharmony_ci napi_value* args = nullptr; 15694d6c458bSopenharmony_ci ObjectScope<napi_value> scope(args, true); 15704d6c458bSopenharmony_ci if (argc > BEGIN_INDEX_OF_ARGUMENTS) { 15714d6c458bSopenharmony_ci args = new napi_value[argc - BEGIN_INDEX_OF_ARGUMENTS]; 15724d6c458bSopenharmony_ci for (uint32_t index = 0; index < argc - BEGIN_INDEX_OF_ARGUMENTS; index++) { 15734d6c458bSopenharmony_ci napi_get_element(hostEnv_, argsArray, index + BEGIN_INDEX_OF_ARGUMENTS, &args[index]); 15744d6c458bSopenharmony_ci } 15754d6c458bSopenharmony_ci } 15764d6c458bSopenharmony_ci 15774d6c458bSopenharmony_ci napi_value res = nullptr; 15784d6c458bSopenharmony_ci napi_call_function(hostEnv_, obj, method, argc - BEGIN_INDEX_OF_ARGUMENTS, args, &res); 15794d6c458bSopenharmony_ci bool hasPendingException = NapiHelper::IsExceptionPending(hostEnv_); 15804d6c458bSopenharmony_ci if (hasPendingException) { 15814d6c458bSopenharmony_ci napi_value exception = nullptr; 15824d6c458bSopenharmony_ci napi_get_and_clear_last_exception(hostEnv_, &exception); 15834d6c458bSopenharmony_ci napi_throw(hostEnv_, exception); 15844d6c458bSopenharmony_ci globalCallSuccess_ = false; 15854d6c458bSopenharmony_ci cv_.notify_one(); 15864d6c458bSopenharmony_ci return; 15874d6c458bSopenharmony_ci } 15884d6c458bSopenharmony_ci // defautly not transfer 15894d6c458bSopenharmony_ci napi_value undefined = NapiHelper::GetUndefinedValue(hostEnv_); 15904d6c458bSopenharmony_ci // meaningless to copy sendable object when call globalObject 15914d6c458bSopenharmony_ci bool defaultClone = true; 15924d6c458bSopenharmony_ci bool defaultTransfer = false; 15934d6c458bSopenharmony_ci status = napi_serialize_inner(hostEnv_, res, undefined, undefined, defaultTransfer, defaultClone, &data); 15944d6c458bSopenharmony_ci if (status != napi_ok || data == nullptr) { 15954d6c458bSopenharmony_ci AddGlobalCallError(ErrorHelper::ERR_WORKER_SERIALIZATION); 15964d6c458bSopenharmony_ci globalCallSuccess_ = false; 15974d6c458bSopenharmony_ci cv_.notify_one(); 15984d6c458bSopenharmony_ci return; 15994d6c458bSopenharmony_ci } 16004d6c458bSopenharmony_ci // drop and destruct result if timeout 16014d6c458bSopenharmony_ci if (currentCallId != globalCallId_ || currentCallId == 0) { 16024d6c458bSopenharmony_ci napi_delete_serialization_data(hostEnv_, data); 16034d6c458bSopenharmony_ci cv_.notify_one(); 16044d6c458bSopenharmony_ci return; 16054d6c458bSopenharmony_ci } 16064d6c458bSopenharmony_ci workerGlobalCallQueue_.EnQueue(data); 16074d6c458bSopenharmony_ci globalCallSuccess_ = true; 16084d6c458bSopenharmony_ci cv_.notify_one(); 16094d6c458bSopenharmony_ci} 16104d6c458bSopenharmony_ci 16114d6c458bSopenharmony_civoid Worker::AddGlobalCallError(int32_t errCode, napi_value errData) 16124d6c458bSopenharmony_ci{ 16134d6c458bSopenharmony_ci globalCallErrors_.push({errCode, errData}); 16144d6c458bSopenharmony_ci} 16154d6c458bSopenharmony_ci 16164d6c458bSopenharmony_civoid Worker::HandleGlobalCallError(napi_env env) 16174d6c458bSopenharmony_ci{ 16184d6c458bSopenharmony_ci while (!globalCallErrors_.empty()) { 16194d6c458bSopenharmony_ci std::pair<int32_t, napi_value> pair = globalCallErrors_.front(); 16204d6c458bSopenharmony_ci globalCallErrors_.pop(); 16214d6c458bSopenharmony_ci int32_t errCode = pair.first; 16224d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, errCode); 16234d6c458bSopenharmony_ci } 16244d6c458bSopenharmony_ci} 16254d6c458bSopenharmony_ci 16264d6c458bSopenharmony_civoid Worker::ClearGlobalCallError(napi_env env) 16274d6c458bSopenharmony_ci{ 16284d6c458bSopenharmony_ci while (!globalCallErrors_.empty()) { 16294d6c458bSopenharmony_ci std::pair<int32_t, napi_value> pair = globalCallErrors_.front(); 16304d6c458bSopenharmony_ci globalCallErrors_.pop(); 16314d6c458bSopenharmony_ci if (pair.second != nullptr) { 16324d6c458bSopenharmony_ci napi_delete_serialization_data(env, pair.second); 16334d6c458bSopenharmony_ci } 16344d6c458bSopenharmony_ci } 16354d6c458bSopenharmony_ci} 16364d6c458bSopenharmony_ci 16374d6c458bSopenharmony_civoid Worker::CallHostFunction(size_t argc, const napi_value* argv, const char* methodName) const 16384d6c458bSopenharmony_ci{ 16394d6c458bSopenharmony_ci if (hostEnv_ == nullptr) { 16404d6c458bSopenharmony_ci HILOG_ERROR("worker:: host thread maybe is over"); 16414d6c458bSopenharmony_ci return; 16424d6c458bSopenharmony_ci } 16434d6c458bSopenharmony_ci if (HostIsStop()) { 16444d6c458bSopenharmony_ci HILOG_ERROR("worker:: host thread maybe is over"); 16454d6c458bSopenharmony_ci WorkerThrowError(hostEnv_, ErrorHelper::ERR_WORKER_NOT_RUNNING, 16464d6c458bSopenharmony_ci "host thread maybe is over when CallHostFunction"); 16474d6c458bSopenharmony_ci return; 16484d6c458bSopenharmony_ci } 16494d6c458bSopenharmony_ci napi_value obj = NapiHelper::GetReferenceValue(hostEnv_, workerRef_); 16504d6c458bSopenharmony_ci napi_value callback = NapiHelper::GetNameProperty(hostEnv_, obj, methodName); 16514d6c458bSopenharmony_ci bool isCallable = NapiHelper::IsCallable(hostEnv_, callback); 16524d6c458bSopenharmony_ci if (!isCallable) { 16534d6c458bSopenharmony_ci HILOG_DEBUG("worker:: host thread %{public}s is not Callable", methodName); 16544d6c458bSopenharmony_ci return; 16554d6c458bSopenharmony_ci } 16564d6c458bSopenharmony_ci napi_value callbackResult = nullptr; 16574d6c458bSopenharmony_ci napi_call_function(hostEnv_, obj, callback, argc, argv, &callbackResult); 16584d6c458bSopenharmony_ci HandleHostException(); 16594d6c458bSopenharmony_ci} 16604d6c458bSopenharmony_ci 16614d6c458bSopenharmony_civoid Worker::CloseHostCallback() 16624d6c458bSopenharmony_ci{ 16634d6c458bSopenharmony_ci { 16644d6c458bSopenharmony_ci napi_status status = napi_ok; 16654d6c458bSopenharmony_ci HandleScope scope(hostEnv_, status); 16664d6c458bSopenharmony_ci NAPI_CALL_RETURN_VOID(hostEnv_, status); 16674d6c458bSopenharmony_ci napi_value exitValue = nullptr; 16684d6c458bSopenharmony_ci if (isErrorExit_) { 16694d6c458bSopenharmony_ci napi_create_int32(hostEnv_, 1, &exitValue); // 1 : exit because of error 16704d6c458bSopenharmony_ci } else { 16714d6c458bSopenharmony_ci napi_create_int32(hostEnv_, 0, &exitValue); // 0 : exit normally 16724d6c458bSopenharmony_ci } 16734d6c458bSopenharmony_ci napi_value argv[1] = { exitValue }; 16744d6c458bSopenharmony_ci CallHostFunction(1, argv, "onexit"); 16754d6c458bSopenharmony_ci napi_value obj = NapiHelper::GetReferenceValue(hostEnv_, workerRef_); 16764d6c458bSopenharmony_ci // handle listeners 16774d6c458bSopenharmony_ci HandleEventListeners(hostEnv_, obj, 1, argv, "exit"); 16784d6c458bSopenharmony_ci } 16794d6c458bSopenharmony_ci EraseWorker(); 16804d6c458bSopenharmony_ci CloseHelp::DeletePointer(this, false); 16814d6c458bSopenharmony_ci} 16824d6c458bSopenharmony_ci 16834d6c458bSopenharmony_civoid Worker::HostOnError(const uv_async_t* req) 16844d6c458bSopenharmony_ci{ 16854d6c458bSopenharmony_ci Worker* worker = static_cast<Worker*>(req->data); 16864d6c458bSopenharmony_ci if (worker == nullptr) { 16874d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker is null"); 16884d6c458bSopenharmony_ci return; 16894d6c458bSopenharmony_ci } 16904d6c458bSopenharmony_ci worker->HostOnErrorInner(); 16914d6c458bSopenharmony_ci worker->TerminateInner(); 16924d6c458bSopenharmony_ci} 16934d6c458bSopenharmony_ci 16944d6c458bSopenharmony_civoid Worker::HostOnErrorInner() 16954d6c458bSopenharmony_ci{ 16964d6c458bSopenharmony_ci if (hostEnv_ == nullptr || HostIsStop()) { 16974d6c458bSopenharmony_ci HILOG_ERROR("worker:: host thread maybe is over when host onerror."); 16984d6c458bSopenharmony_ci return; 16994d6c458bSopenharmony_ci } 17004d6c458bSopenharmony_ci napi_status status = napi_ok; 17014d6c458bSopenharmony_ci HandleScope scope(hostEnv_, status); 17024d6c458bSopenharmony_ci NAPI_CALL_RETURN_VOID(hostEnv_, status); 17034d6c458bSopenharmony_ci NativeEngine* hostEngine = reinterpret_cast<NativeEngine*>(hostEnv_); 17044d6c458bSopenharmony_ci if (!hostEngine->InitContainerScopeFunc(scopeId_)) { 17054d6c458bSopenharmony_ci HILOG_WARN("worker:: InitContainerScopeFunc error when onerror begin(only stage model)"); 17064d6c458bSopenharmony_ci } 17074d6c458bSopenharmony_ci 17084d6c458bSopenharmony_ci napi_value obj = NapiHelper::GetReferenceValue(hostEnv_, workerRef_); 17094d6c458bSopenharmony_ci napi_value callback = NapiHelper::GetNameProperty(hostEnv_, obj, "onerror"); 17104d6c458bSopenharmony_ci bool isCallable = NapiHelper::IsCallable(hostEnv_, callback); 17114d6c458bSopenharmony_ci 17124d6c458bSopenharmony_ci MessageDataType data; 17134d6c458bSopenharmony_ci while (errorQueue_.DeQueue(&data)) { 17144d6c458bSopenharmony_ci napi_value result = nullptr; 17154d6c458bSopenharmony_ci napi_deserialize(hostEnv_, data, &result); 17164d6c458bSopenharmony_ci napi_delete_serialization_data(hostEnv_, data); 17174d6c458bSopenharmony_ci 17184d6c458bSopenharmony_ci napi_value argv[1] = { result }; 17194d6c458bSopenharmony_ci if (isCallable) { 17204d6c458bSopenharmony_ci napi_value callbackResult = nullptr; 17214d6c458bSopenharmony_ci napi_call_function(hostEnv_, obj, callback, 1, argv, &callbackResult); 17224d6c458bSopenharmony_ci } 17234d6c458bSopenharmony_ci // handle listeners 17244d6c458bSopenharmony_ci bool isHandle = HandleEventListeners(hostEnv_, obj, 1, argv, "error"); 17254d6c458bSopenharmony_ci if (!isCallable && !isHandle) { 17264d6c458bSopenharmony_ci napi_value businessError = ErrorHelper::ObjectToError(hostEnv_, result); 17274d6c458bSopenharmony_ci napi_throw(hostEnv_, businessError); 17284d6c458bSopenharmony_ci HandleHostException(); 17294d6c458bSopenharmony_ci return; 17304d6c458bSopenharmony_ci } 17314d6c458bSopenharmony_ci HandleHostException(); 17324d6c458bSopenharmony_ci } 17334d6c458bSopenharmony_ci if (!hostEngine->FinishContainerScopeFunc(scopeId_)) { 17344d6c458bSopenharmony_ci HILOG_WARN("worker:: FinishContainerScopeFunc error when onerror end(only stage model)"); 17354d6c458bSopenharmony_ci } 17364d6c458bSopenharmony_ci} 17374d6c458bSopenharmony_ci 17384d6c458bSopenharmony_civoid Worker::PostMessageInner(MessageDataType data) 17394d6c458bSopenharmony_ci{ 17404d6c458bSopenharmony_ci if (IsTerminated()) { 17414d6c458bSopenharmony_ci HILOG_DEBUG("worker:: worker has been terminated when PostMessageInner."); 17424d6c458bSopenharmony_ci return; 17434d6c458bSopenharmony_ci } 17444d6c458bSopenharmony_ci workerMessageQueue_.EnQueue(data); 17454d6c458bSopenharmony_ci std::lock_guard<std::mutex> lock(workerOnmessageMutex_); 17464d6c458bSopenharmony_ci if (workerOnMessageSignal_ != nullptr && !uv_is_closing((uv_handle_t*)workerOnMessageSignal_)) { 17474d6c458bSopenharmony_ci uv_async_send(workerOnMessageSignal_); 17484d6c458bSopenharmony_ci } 17494d6c458bSopenharmony_ci} 17504d6c458bSopenharmony_ci 17514d6c458bSopenharmony_civoid Worker::HostOnMessageErrorInner() 17524d6c458bSopenharmony_ci{ 17534d6c458bSopenharmony_ci if (hostEnv_ == nullptr || HostIsStop()) { 17544d6c458bSopenharmony_ci HILOG_ERROR("worker:: host thread maybe is over"); 17554d6c458bSopenharmony_ci return; 17564d6c458bSopenharmony_ci } 17574d6c458bSopenharmony_ci napi_value obj = NapiHelper::GetReferenceValue(hostEnv_, workerRef_); 17584d6c458bSopenharmony_ci CallHostFunction(0, nullptr, "onmessageerror"); 17594d6c458bSopenharmony_ci // handle listeners 17604d6c458bSopenharmony_ci HandleEventListeners(hostEnv_, obj, 0, nullptr, "messageerror"); 17614d6c458bSopenharmony_ci} 17624d6c458bSopenharmony_ci 17634d6c458bSopenharmony_civoid Worker::TerminateInner() 17644d6c458bSopenharmony_ci{ 17654d6c458bSopenharmony_ci if (IsTerminated() || IsTerminating()) { 17664d6c458bSopenharmony_ci HILOG_INFO("worker:: worker is not in running when TerminateInner"); 17674d6c458bSopenharmony_ci return; 17684d6c458bSopenharmony_ci } 17694d6c458bSopenharmony_ci // 1. Update State 17704d6c458bSopenharmony_ci UpdateWorkerState(TERMINATEING); 17714d6c458bSopenharmony_ci // 2. send null signal 17724d6c458bSopenharmony_ci PostMessageInner(nullptr); 17734d6c458bSopenharmony_ci} 17744d6c458bSopenharmony_ci 17754d6c458bSopenharmony_civoid Worker::CloseInner() 17764d6c458bSopenharmony_ci{ 17774d6c458bSopenharmony_ci bool expected = false; 17784d6c458bSopenharmony_ci if (isTerminated_.compare_exchange_weak(expected, true)) { 17794d6c458bSopenharmony_ci HILOG_INFO("worker:: Close worker"); 17804d6c458bSopenharmony_ci } else { 17814d6c458bSopenharmony_ci HILOG_DEBUG("worker:: worker is terminated when Close"); 17824d6c458bSopenharmony_ci return; 17834d6c458bSopenharmony_ci } 17844d6c458bSopenharmony_ci UpdateWorkerState(TERMINATEING); 17854d6c458bSopenharmony_ci TerminateWorker(); 17864d6c458bSopenharmony_ci} 17874d6c458bSopenharmony_ci 17884d6c458bSopenharmony_cibool Worker::UpdateWorkerState(RunnerState state) 17894d6c458bSopenharmony_ci{ 17904d6c458bSopenharmony_ci bool done = false; 17914d6c458bSopenharmony_ci do { 17924d6c458bSopenharmony_ci RunnerState oldState = runnerState_.load(std::memory_order_acquire); 17934d6c458bSopenharmony_ci if (oldState >= state) { 17944d6c458bSopenharmony_ci // make sure state sequence is start, running, terminating, terminated 17954d6c458bSopenharmony_ci return false; 17964d6c458bSopenharmony_ci } 17974d6c458bSopenharmony_ci done = runnerState_.compare_exchange_strong(oldState, state); 17984d6c458bSopenharmony_ci } while (!done); 17994d6c458bSopenharmony_ci return true; 18004d6c458bSopenharmony_ci} 18014d6c458bSopenharmony_ci 18024d6c458bSopenharmony_cibool Worker::UpdateHostState(HostState state) 18034d6c458bSopenharmony_ci{ 18044d6c458bSopenharmony_ci bool done = false; 18054d6c458bSopenharmony_ci do { 18064d6c458bSopenharmony_ci HostState oldState = hostState_.load(std::memory_order_acquire); 18074d6c458bSopenharmony_ci if (oldState >= state) { 18084d6c458bSopenharmony_ci // make sure state sequence is ACTIVE, INACTIVE 18094d6c458bSopenharmony_ci return false; 18104d6c458bSopenharmony_ci } 18114d6c458bSopenharmony_ci done = hostState_.compare_exchange_strong(oldState, state); 18124d6c458bSopenharmony_ci } while (!done); 18134d6c458bSopenharmony_ci return true; 18144d6c458bSopenharmony_ci} 18154d6c458bSopenharmony_ci 18164d6c458bSopenharmony_civoid Worker::TerminateWorker() 18174d6c458bSopenharmony_ci{ 18184d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 18194d6c458bSopenharmony_ci // when there is no active handle, worker loop will stop automatic. 18204d6c458bSopenharmony_ci { 18214d6c458bSopenharmony_ci std::lock_guard<std::mutex> lock(workerOnmessageMutex_); 18224d6c458bSopenharmony_ci uv_close(reinterpret_cast<uv_handle_t*>(workerOnMessageSignal_), [](uv_handle_t* handle) { 18234d6c458bSopenharmony_ci delete reinterpret_cast<uv_async_t*>(handle); 18244d6c458bSopenharmony_ci handle = nullptr; 18254d6c458bSopenharmony_ci }); 18264d6c458bSopenharmony_ci } 18274d6c458bSopenharmony_ci#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) 18284d6c458bSopenharmony_ci uv_close(reinterpret_cast<uv_handle_t*>(&debuggerOnPostTaskSignal_), nullptr); 18294d6c458bSopenharmony_ci#endif 18304d6c458bSopenharmony_ci CloseWorkerCallback(); 18314d6c458bSopenharmony_ci uv_loop_t* loop = GetWorkerLoop(); 18324d6c458bSopenharmony_ci if (loop != nullptr) { 18334d6c458bSopenharmony_ci Timer::ClearEnvironmentTimer(workerEnv_); 18344d6c458bSopenharmony_ci uv_stop(loop); 18354d6c458bSopenharmony_ci } 18364d6c458bSopenharmony_ci UpdateWorkerState(TERMINATED); 18374d6c458bSopenharmony_ci} 18384d6c458bSopenharmony_ci 18394d6c458bSopenharmony_civoid Worker::PublishWorkerOverSignal() 18404d6c458bSopenharmony_ci{ 18414d6c458bSopenharmony_ci if (HostIsStop()) { 18424d6c458bSopenharmony_ci return; 18434d6c458bSopenharmony_ci } 18444d6c458bSopenharmony_ci // post nullptr tell host worker is not running 18454d6c458bSopenharmony_ci hostMessageQueue_.EnQueue(nullptr); 18464d6c458bSopenharmony_ci#if defined(ENABLE_WORKER_EVENTHANDLER) 18474d6c458bSopenharmony_ci if (isMainThreadWorker_ && !isLimitedWorker_) { 18484d6c458bSopenharmony_ci PostWorkerOverTask(); 18494d6c458bSopenharmony_ci } else { 18504d6c458bSopenharmony_ci uv_async_send(hostOnMessageSignal_); 18514d6c458bSopenharmony_ci } 18524d6c458bSopenharmony_ci#else 18534d6c458bSopenharmony_ci uv_async_send(hostOnMessageSignal_); 18544d6c458bSopenharmony_ci#endif 18554d6c458bSopenharmony_ci} 18564d6c458bSopenharmony_ci 18574d6c458bSopenharmony_ci#if defined(ENABLE_WORKER_EVENTHANDLER) 18584d6c458bSopenharmony_civoid Worker::PostWorkerOverTask() 18594d6c458bSopenharmony_ci{ 18604d6c458bSopenharmony_ci auto hostOnOverSignalTask = [this]() { 18614d6c458bSopenharmony_ci if (IsValidWorker(this)) { 18624d6c458bSopenharmony_ci HILOG_INFO("worker:: host thread receive terminate signal."); 18634d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME("Worker:: HostOnTerminateSignal"); 18644d6c458bSopenharmony_ci this->HostOnMessageInner(); 18654d6c458bSopenharmony_ci } 18664d6c458bSopenharmony_ci }; 18674d6c458bSopenharmony_ci GetMainThreadHandler()->PostTask(hostOnOverSignalTask, "WorkerHostOnOverSignalTask", 18684d6c458bSopenharmony_ci 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH); 18694d6c458bSopenharmony_ci} 18704d6c458bSopenharmony_ci 18714d6c458bSopenharmony_civoid Worker::PostWorkerErrorTask() 18724d6c458bSopenharmony_ci{ 18734d6c458bSopenharmony_ci auto hostOnErrorTask = [this]() { 18744d6c458bSopenharmony_ci if (IsValidWorker(this)) { 18754d6c458bSopenharmony_ci HILOG_INFO("worker:: host thread receive error message."); 18764d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME("Worker:: HostOnErrorMessage"); 18774d6c458bSopenharmony_ci this->HostOnErrorInner(); 18784d6c458bSopenharmony_ci this->TerminateInner(); 18794d6c458bSopenharmony_ci } 18804d6c458bSopenharmony_ci }; 18814d6c458bSopenharmony_ci GetMainThreadHandler()->PostTask(hostOnErrorTask, "WorkerHostOnErrorTask", 18824d6c458bSopenharmony_ci 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH); 18834d6c458bSopenharmony_ci} 18844d6c458bSopenharmony_ci 18854d6c458bSopenharmony_civoid Worker::PostWorkerMessageTask() 18864d6c458bSopenharmony_ci{ 18874d6c458bSopenharmony_ci auto hostOnMessageTask = [this]() { 18884d6c458bSopenharmony_ci if (IsValidWorker(this)) { 18894d6c458bSopenharmony_ci HILOG_DEBUG("worker:: host thread receive message."); 18904d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME("Worker:: HostOnMessage"); 18914d6c458bSopenharmony_ci this->HostOnMessageInner(); 18924d6c458bSopenharmony_ci } 18934d6c458bSopenharmony_ci }; 18944d6c458bSopenharmony_ci GetMainThreadHandler()->PostTask(hostOnMessageTask, "WorkerHostOnMessageTask", 18954d6c458bSopenharmony_ci 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH); 18964d6c458bSopenharmony_ci} 18974d6c458bSopenharmony_ci 18984d6c458bSopenharmony_civoid Worker::PostWorkerGlobalCallTask() 18994d6c458bSopenharmony_ci{ 19004d6c458bSopenharmony_ci auto hostOnGlobalCallTask = [this]() { 19014d6c458bSopenharmony_ci if (IsValidWorker(this)) { 19024d6c458bSopenharmony_ci HILOG_DEBUG("worker:: host thread receive globalCall signal."); 19034d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME("Worker:: HostOnGlobalCallSignal"); 19044d6c458bSopenharmony_ci this->HostOnGlobalCallInner(); 19054d6c458bSopenharmony_ci } 19064d6c458bSopenharmony_ci }; 19074d6c458bSopenharmony_ci GetMainThreadHandler()->PostTask(hostOnGlobalCallTask, "WorkerHostOnGlobalCallTask", 19084d6c458bSopenharmony_ci 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH); 19094d6c458bSopenharmony_ci} 19104d6c458bSopenharmony_ci#endif 19114d6c458bSopenharmony_ci 19124d6c458bSopenharmony_cibool Worker::IsValidWorker(Worker* worker) 19134d6c458bSopenharmony_ci{ 19144d6c458bSopenharmony_ci std::lock_guard<std::mutex> lock(g_workersMutex); 19154d6c458bSopenharmony_ci std::list<Worker*>::iterator it = std::find(g_workers.begin(), g_workers.end(), worker); 19164d6c458bSopenharmony_ci if (it == g_workers.end()) { 19174d6c458bSopenharmony_ci return false; 19184d6c458bSopenharmony_ci } 19194d6c458bSopenharmony_ci return true; 19204d6c458bSopenharmony_ci} 19214d6c458bSopenharmony_ci 19224d6c458bSopenharmony_civoid Worker::WorkerOnMessage(const uv_async_t* req) 19234d6c458bSopenharmony_ci{ 19244d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 19254d6c458bSopenharmony_ci Worker* worker = static_cast<Worker*>(req->data); 19264d6c458bSopenharmony_ci if (worker == nullptr) { 19274d6c458bSopenharmony_ci HILOG_ERROR("worker::worker is null"); 19284d6c458bSopenharmony_ci return; 19294d6c458bSopenharmony_ci } 19304d6c458bSopenharmony_ci worker->WorkerOnMessageInner(); 19314d6c458bSopenharmony_ci} 19324d6c458bSopenharmony_ci 19334d6c458bSopenharmony_civoid Worker::WorkerOnMessageInner() 19344d6c458bSopenharmony_ci{ 19354d6c458bSopenharmony_ci if (IsTerminated()) { 19364d6c458bSopenharmony_ci return; 19374d6c458bSopenharmony_ci } 19384d6c458bSopenharmony_ci napi_status status; 19394d6c458bSopenharmony_ci napi_handle_scope scope = nullptr; 19404d6c458bSopenharmony_ci status = napi_open_handle_scope(workerEnv_, &scope); 19414d6c458bSopenharmony_ci if (status != napi_ok || scope == nullptr) { 19424d6c458bSopenharmony_ci HILOG_ERROR("worker:: WorkerOnMessage open handle scope failed."); 19434d6c458bSopenharmony_ci return; 19444d6c458bSopenharmony_ci } 19454d6c458bSopenharmony_ci MessageDataType data = nullptr; 19464d6c458bSopenharmony_ci while (!IsTerminated() && workerMessageQueue_.DeQueue(&data)) { 19474d6c458bSopenharmony_ci if (data == nullptr) { 19484d6c458bSopenharmony_ci HILOG_DEBUG("worker:: worker reveive terminate signal"); 19494d6c458bSopenharmony_ci // Close handlescope need before TerminateWorker 19504d6c458bSopenharmony_ci napi_close_handle_scope(workerEnv_, scope); 19514d6c458bSopenharmony_ci TerminateWorker(); 19524d6c458bSopenharmony_ci return; 19534d6c458bSopenharmony_ci } 19544d6c458bSopenharmony_ci napi_value result = nullptr; 19554d6c458bSopenharmony_ci status = napi_deserialize(workerEnv_, data, &result); 19564d6c458bSopenharmony_ci napi_delete_serialization_data(workerEnv_, data); 19574d6c458bSopenharmony_ci if (status != napi_ok || result == nullptr) { 19584d6c458bSopenharmony_ci WorkerOnMessageErrorInner(); 19594d6c458bSopenharmony_ci continue; 19604d6c458bSopenharmony_ci } 19614d6c458bSopenharmony_ci 19624d6c458bSopenharmony_ci napi_value event = nullptr; 19634d6c458bSopenharmony_ci napi_create_object(workerEnv_, &event); 19644d6c458bSopenharmony_ci napi_set_named_property(workerEnv_, event, "data", result); 19654d6c458bSopenharmony_ci napi_value argv[1] = { event }; 19664d6c458bSopenharmony_ci CallWorkerFunction(1, argv, "onmessage", true); 19674d6c458bSopenharmony_ci 19684d6c458bSopenharmony_ci napi_value obj = NapiHelper::GetReferenceValue(workerEnv_, this->workerPort_); 19694d6c458bSopenharmony_ci ParentPortHandleEventListeners(workerEnv_, obj, 1, argv, "message", true); 19704d6c458bSopenharmony_ci } 19714d6c458bSopenharmony_ci napi_close_handle_scope(workerEnv_, scope); 19724d6c458bSopenharmony_ci} 19734d6c458bSopenharmony_ci 19744d6c458bSopenharmony_cibool Worker::HandleEventListeners(napi_env env, napi_value recv, size_t argc, const napi_value* argv, const char* type) 19754d6c458bSopenharmony_ci{ 19764d6c458bSopenharmony_ci std::string listener(type); 19774d6c458bSopenharmony_ci auto iter = eventListeners_.find(listener); 19784d6c458bSopenharmony_ci if (iter == eventListeners_.end()) { 19794d6c458bSopenharmony_ci HILOG_DEBUG("worker:: there is no listener for type %{public}s in host thread", type); 19804d6c458bSopenharmony_ci return false; 19814d6c458bSopenharmony_ci } 19824d6c458bSopenharmony_ci 19834d6c458bSopenharmony_ci std::list<WorkerListener*>& listeners = iter->second; 19844d6c458bSopenharmony_ci std::list<WorkerListener*>::iterator it = listeners.begin(); 19854d6c458bSopenharmony_ci while (it != listeners.end()) { 19864d6c458bSopenharmony_ci WorkerListener* data = *it++; 19874d6c458bSopenharmony_ci napi_value callbackObj = NapiHelper::GetReferenceValue(env, data->callback_); 19884d6c458bSopenharmony_ci if (!NapiHelper::IsCallable(env, callbackObj)) { 19894d6c458bSopenharmony_ci HILOG_WARN("worker:: host thread listener %{public}s is not callable", type); 19904d6c458bSopenharmony_ci return false; 19914d6c458bSopenharmony_ci } 19924d6c458bSopenharmony_ci napi_value callbackResult = nullptr; 19934d6c458bSopenharmony_ci napi_call_function(env, recv, callbackObj, argc, argv, &callbackResult); 19944d6c458bSopenharmony_ci if (!data->NextIsAvailable()) { 19954d6c458bSopenharmony_ci listeners.remove(data); 19964d6c458bSopenharmony_ci CloseHelp::DeletePointer(data, false); 19974d6c458bSopenharmony_ci } 19984d6c458bSopenharmony_ci } 19994d6c458bSopenharmony_ci return true; 20004d6c458bSopenharmony_ci} 20014d6c458bSopenharmony_ci 20024d6c458bSopenharmony_civoid Worker::HandleHostException() const 20034d6c458bSopenharmony_ci{ 20044d6c458bSopenharmony_ci if (!NapiHelper::IsExceptionPending(hostEnv_)) { 20054d6c458bSopenharmony_ci return; 20064d6c458bSopenharmony_ci } 20074d6c458bSopenharmony_ci auto hostEngine = reinterpret_cast<NativeEngine*>(hostEnv_); 20084d6c458bSopenharmony_ci hostEngine->HandleUncaughtException(); 20094d6c458bSopenharmony_ci} 20104d6c458bSopenharmony_ci 20114d6c458bSopenharmony_civoid Worker::HandleException() 20124d6c458bSopenharmony_ci{ 20134d6c458bSopenharmony_ci if (!NapiHelper::IsExceptionPending(workerEnv_)) { 20144d6c458bSopenharmony_ci return; 20154d6c458bSopenharmony_ci } 20164d6c458bSopenharmony_ci 20174d6c458bSopenharmony_ci napi_status status = napi_ok; 20184d6c458bSopenharmony_ci HandleScope scope(workerEnv_, status); 20194d6c458bSopenharmony_ci NAPI_CALL_RETURN_VOID(workerEnv_, status); 20204d6c458bSopenharmony_ci napi_value exception; 20214d6c458bSopenharmony_ci napi_get_and_clear_last_exception(workerEnv_, &exception); 20224d6c458bSopenharmony_ci if (exception == nullptr) { 20234d6c458bSopenharmony_ci return; 20244d6c458bSopenharmony_ci } 20254d6c458bSopenharmony_ci 20264d6c458bSopenharmony_ci HandleUncaughtException(exception); 20274d6c458bSopenharmony_ci} 20284d6c458bSopenharmony_ci 20294d6c458bSopenharmony_civoid Worker::HandleUncaughtException(napi_value exception) 20304d6c458bSopenharmony_ci{ 20314d6c458bSopenharmony_ci napi_value obj = ErrorHelper::TranslateErrorEvent(workerEnv_, exception); 20324d6c458bSopenharmony_ci 20334d6c458bSopenharmony_ci // WorkerGlobalScope onerror 20344d6c458bSopenharmony_ci WorkerOnErrorInner(obj); 20354d6c458bSopenharmony_ci 20364d6c458bSopenharmony_ci if (hostEnv_ == nullptr) { 20374d6c458bSopenharmony_ci HILOG_ERROR("worker:: host engine is nullptr."); 20384d6c458bSopenharmony_ci return; 20394d6c458bSopenharmony_ci } 20404d6c458bSopenharmony_ci MessageDataType data = nullptr; 20414d6c458bSopenharmony_ci napi_value undefined = NapiHelper::GetUndefinedValue(workerEnv_); 20424d6c458bSopenharmony_ci napi_serialize_inner(workerEnv_, obj, undefined, undefined, false, true, &data); 20434d6c458bSopenharmony_ci { 20444d6c458bSopenharmony_ci std::lock_guard<std::recursive_mutex> lock(liveStatusLock_); 20454d6c458bSopenharmony_ci if (HostIsStop() || isHostEnvExited_) { 20464d6c458bSopenharmony_ci return; 20474d6c458bSopenharmony_ci } 20484d6c458bSopenharmony_ci errorQueue_.EnQueue(data); 20494d6c458bSopenharmony_ci#if defined(ENABLE_WORKER_EVENTHANDLER) 20504d6c458bSopenharmony_ci if (isMainThreadWorker_ && !isLimitedWorker_) { 20514d6c458bSopenharmony_ci PostWorkerErrorTask(); 20524d6c458bSopenharmony_ci } else { 20534d6c458bSopenharmony_ci uv_async_send(hostOnErrorSignal_); 20544d6c458bSopenharmony_ci } 20554d6c458bSopenharmony_ci#else 20564d6c458bSopenharmony_ci uv_async_send(hostOnErrorSignal_); 20574d6c458bSopenharmony_ci#endif 20584d6c458bSopenharmony_ci } 20594d6c458bSopenharmony_ci} 20604d6c458bSopenharmony_ci 20614d6c458bSopenharmony_civoid Worker::WorkerOnMessageErrorInner() 20624d6c458bSopenharmony_ci{ 20634d6c458bSopenharmony_ci isErrorExit_ = true; 20644d6c458bSopenharmony_ci CallWorkerFunction(0, nullptr, "onmessageerror", true); 20654d6c458bSopenharmony_ci napi_value obj = NapiHelper::GetReferenceValue(workerEnv_, this->workerPort_); 20664d6c458bSopenharmony_ci ParentPortHandleEventListeners(workerEnv_, obj, 0, nullptr, "messageerror", true); 20674d6c458bSopenharmony_ci} 20684d6c458bSopenharmony_ci 20694d6c458bSopenharmony_civoid Worker::PostMessageToHostInner(MessageDataType data) 20704d6c458bSopenharmony_ci{ 20714d6c458bSopenharmony_ci std::lock_guard<std::recursive_mutex> lock(liveStatusLock_); 20724d6c458bSopenharmony_ci if (hostEnv_ != nullptr && !HostIsStop() && !isHostEnvExited_) { 20734d6c458bSopenharmony_ci hostMessageQueue_.EnQueue(data); 20744d6c458bSopenharmony_ci#if defined(ENABLE_WORKER_EVENTHANDLER) 20754d6c458bSopenharmony_ci if (isMainThreadWorker_ && !isLimitedWorker_) { 20764d6c458bSopenharmony_ci PostWorkerMessageTask(); 20774d6c458bSopenharmony_ci } else { 20784d6c458bSopenharmony_ci uv_async_send(hostOnMessageSignal_); 20794d6c458bSopenharmony_ci } 20804d6c458bSopenharmony_ci#else 20814d6c458bSopenharmony_ci uv_async_send(hostOnMessageSignal_); 20824d6c458bSopenharmony_ci#endif 20834d6c458bSopenharmony_ci } else { 20844d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker host engine is nullptr when PostMessageToHostInner."); 20854d6c458bSopenharmony_ci } 20864d6c458bSopenharmony_ci} 20874d6c458bSopenharmony_ci 20884d6c458bSopenharmony_cibool Worker::WorkerListener::operator==(const WorkerListener& listener) const 20894d6c458bSopenharmony_ci{ 20904d6c458bSopenharmony_ci napi_value obj = NapiHelper::GetReferenceValue(listener.env_, listener.callback_); 20914d6c458bSopenharmony_ci napi_value compareObj = NapiHelper::GetReferenceValue(env_, callback_); 20924d6c458bSopenharmony_ci // the env of listener and cmp listener must be same env because of Synchronization method 20934d6c458bSopenharmony_ci return NapiHelper::StrictEqual(env_, compareObj, obj); 20944d6c458bSopenharmony_ci} 20954d6c458bSopenharmony_ci 20964d6c458bSopenharmony_civoid Worker::AddListenerInner(napi_env env, const char* type, const WorkerListener* listener) 20974d6c458bSopenharmony_ci{ 20984d6c458bSopenharmony_ci std::string typestr(type); 20994d6c458bSopenharmony_ci auto iter = eventListeners_.find(typestr); 21004d6c458bSopenharmony_ci if (iter == eventListeners_.end()) { 21014d6c458bSopenharmony_ci std::list<WorkerListener*> listeners; 21024d6c458bSopenharmony_ci listeners.emplace_back(const_cast<WorkerListener*>(listener)); 21034d6c458bSopenharmony_ci eventListeners_[typestr] = listeners; 21044d6c458bSopenharmony_ci } else { 21054d6c458bSopenharmony_ci std::list<WorkerListener*>& listenerList = iter->second; 21064d6c458bSopenharmony_ci std::list<WorkerListener*>::iterator it = std::find_if( 21074d6c458bSopenharmony_ci listenerList.begin(), listenerList.end(), Worker::FindWorkerListener(env, listener->callback_)); 21084d6c458bSopenharmony_ci if (it != listenerList.end()) { 21094d6c458bSopenharmony_ci return; 21104d6c458bSopenharmony_ci } 21114d6c458bSopenharmony_ci listenerList.emplace_back(const_cast<WorkerListener*>(listener)); 21124d6c458bSopenharmony_ci } 21134d6c458bSopenharmony_ci} 21144d6c458bSopenharmony_ci 21154d6c458bSopenharmony_civoid Worker::RemoveListenerInner(napi_env env, const char* type, napi_ref callback) 21164d6c458bSopenharmony_ci{ 21174d6c458bSopenharmony_ci std::string typestr(type); 21184d6c458bSopenharmony_ci auto iter = eventListeners_.find(typestr); 21194d6c458bSopenharmony_ci if (iter == eventListeners_.end()) { 21204d6c458bSopenharmony_ci return; 21214d6c458bSopenharmony_ci } 21224d6c458bSopenharmony_ci std::list<WorkerListener*>& listenerList = iter->second; 21234d6c458bSopenharmony_ci if (callback != nullptr) { 21244d6c458bSopenharmony_ci std::list<WorkerListener*>::iterator it = 21254d6c458bSopenharmony_ci std::find_if(listenerList.begin(), listenerList.end(), Worker::FindWorkerListener(env, callback)); 21264d6c458bSopenharmony_ci if (it != listenerList.end()) { 21274d6c458bSopenharmony_ci CloseHelp::DeletePointer(*it, false); 21284d6c458bSopenharmony_ci listenerList.erase(it); 21294d6c458bSopenharmony_ci } 21304d6c458bSopenharmony_ci } else { 21314d6c458bSopenharmony_ci for (auto it = listenerList.begin(); it != listenerList.end(); it++) { 21324d6c458bSopenharmony_ci CloseHelp::DeletePointer(*it, false); 21334d6c458bSopenharmony_ci } 21344d6c458bSopenharmony_ci eventListeners_.erase(typestr); 21354d6c458bSopenharmony_ci } 21364d6c458bSopenharmony_ci} 21374d6c458bSopenharmony_ci 21384d6c458bSopenharmony_ciWorker::~Worker() 21394d6c458bSopenharmony_ci{ 21404d6c458bSopenharmony_ci std::lock_guard<std::recursive_mutex> lock(liveStatusLock_); 21414d6c458bSopenharmony_ci if (!HostIsStop() && !isHostEnvExited_) { 21424d6c458bSopenharmony_ci ReleaseHostThreadContent(); 21434d6c458bSopenharmony_ci RemoveAllListenerInner(); 21444d6c458bSopenharmony_ci ClearGlobalCallObject(); 21454d6c458bSopenharmony_ci } 21464d6c458bSopenharmony_ci} 21474d6c458bSopenharmony_ci 21484d6c458bSopenharmony_civoid Worker::RemoveAllListenerInner() 21494d6c458bSopenharmony_ci{ 21504d6c458bSopenharmony_ci for (auto iter = eventListeners_.begin(); iter != eventListeners_.end(); iter++) { 21514d6c458bSopenharmony_ci std::list<WorkerListener*>& listeners = iter->second; 21524d6c458bSopenharmony_ci for (auto item = listeners.begin(); item != listeners.end(); item++) { 21534d6c458bSopenharmony_ci WorkerListener* listener = *item; 21544d6c458bSopenharmony_ci CloseHelp::DeletePointer(listener, false); 21554d6c458bSopenharmony_ci } 21564d6c458bSopenharmony_ci } 21574d6c458bSopenharmony_ci eventListeners_.clear(); 21584d6c458bSopenharmony_ci} 21594d6c458bSopenharmony_ci 21604d6c458bSopenharmony_civoid Worker::ReleaseHostThreadContent() 21614d6c458bSopenharmony_ci{ 21624d6c458bSopenharmony_ci ClearHostMessage(hostEnv_); 21634d6c458bSopenharmony_ci if (!HostIsStop()) { 21644d6c458bSopenharmony_ci napi_status status = napi_ok; 21654d6c458bSopenharmony_ci HandleScope scope(hostEnv_, status); 21664d6c458bSopenharmony_ci NAPI_CALL_RETURN_VOID(hostEnv_, status); 21674d6c458bSopenharmony_ci // 3. set thisVar's nativepointer be null 21684d6c458bSopenharmony_ci napi_value thisVar = NapiHelper::GetReferenceValue(hostEnv_, workerRef_); 21694d6c458bSopenharmony_ci Worker* worker = nullptr; 21704d6c458bSopenharmony_ci napi_remove_wrap(hostEnv_, thisVar, reinterpret_cast<void**>(&worker)); 21714d6c458bSopenharmony_ci hostEnv_ = nullptr; 21724d6c458bSopenharmony_ci // 4. set workerRef_ be null 21734d6c458bSopenharmony_ci workerRef_ = nullptr; 21744d6c458bSopenharmony_ci } 21754d6c458bSopenharmony_ci} 21764d6c458bSopenharmony_ci 21774d6c458bSopenharmony_civoid Worker::WorkerOnErrorInner(napi_value error) 21784d6c458bSopenharmony_ci{ 21794d6c458bSopenharmony_ci isErrorExit_ = true; 21804d6c458bSopenharmony_ci napi_value argv[1] = { error }; 21814d6c458bSopenharmony_ci CallWorkerFunction(1, argv, "onerror", false); 21824d6c458bSopenharmony_ci napi_value obj = NapiHelper::GetReferenceValue(workerEnv_, this->workerPort_); 21834d6c458bSopenharmony_ci ParentPortHandleEventListeners(workerEnv_, obj, 1, argv, "error", false); 21844d6c458bSopenharmony_ci} 21854d6c458bSopenharmony_ci 21864d6c458bSopenharmony_cibool Worker::CallWorkerFunction(size_t argc, const napi_value* argv, const char* methodName, bool tryCatch) 21874d6c458bSopenharmony_ci{ 21884d6c458bSopenharmony_ci if (workerEnv_ == nullptr) { 21894d6c458bSopenharmony_ci HILOG_ERROR("Worker:: worker is not running when call workerPort.%{public}s.", methodName); 21904d6c458bSopenharmony_ci return false; 21914d6c458bSopenharmony_ci } 21924d6c458bSopenharmony_ci napi_value callback = NapiHelper::GetNamePropertyInParentPort(workerEnv_, workerPort_, methodName); 21934d6c458bSopenharmony_ci bool isCallable = NapiHelper::IsCallable(workerEnv_, callback); 21944d6c458bSopenharmony_ci if (!isCallable) { 21954d6c458bSopenharmony_ci HILOG_WARN("worker:: workerPort.%{public}s is not Callable", methodName); 21964d6c458bSopenharmony_ci return false; 21974d6c458bSopenharmony_ci } 21984d6c458bSopenharmony_ci napi_value workerPortObj = NapiHelper::GetReferenceValue(workerEnv_, workerPort_); 21994d6c458bSopenharmony_ci napi_value callbackResult = nullptr; 22004d6c458bSopenharmony_ci napi_call_function(workerEnv_, workerPortObj, callback, argc, argv, &callbackResult); 22014d6c458bSopenharmony_ci if (tryCatch && callbackResult == nullptr) { 22024d6c458bSopenharmony_ci HILOG_ERROR("worker:: workerPort.%{public}s handle exception", methodName); 22034d6c458bSopenharmony_ci HandleException(); 22044d6c458bSopenharmony_ci return false; 22054d6c458bSopenharmony_ci } 22064d6c458bSopenharmony_ci return true; 22074d6c458bSopenharmony_ci} 22084d6c458bSopenharmony_ci 22094d6c458bSopenharmony_civoid Worker::CloseWorkerCallback() 22104d6c458bSopenharmony_ci{ 22114d6c458bSopenharmony_ci CallWorkerFunction(0, nullptr, "onclose", true); 22124d6c458bSopenharmony_ci // off worker inited environment 22134d6c458bSopenharmony_ci { 22144d6c458bSopenharmony_ci std::lock_guard<std::recursive_mutex> lock(liveStatusLock_); 22154d6c458bSopenharmony_ci if (HostIsStop() || isHostEnvExited_) { 22164d6c458bSopenharmony_ci return; 22174d6c458bSopenharmony_ci } 22184d6c458bSopenharmony_ci auto hostEngine = reinterpret_cast<NativeEngine*>(hostEnv_); 22194d6c458bSopenharmony_ci if (!hostEngine->CallOffWorkerFunc(reinterpret_cast<NativeEngine*>(workerEnv_))) { 22204d6c458bSopenharmony_ci HILOG_ERROR("worker:: CallOffWorkerFunc error"); 22214d6c458bSopenharmony_ci } 22224d6c458bSopenharmony_ci } 22234d6c458bSopenharmony_ci} 22244d6c458bSopenharmony_ci 22254d6c458bSopenharmony_civoid Worker::ReleaseWorkerThreadContent() 22264d6c458bSopenharmony_ci{ 22274d6c458bSopenharmony_ci HITRACE_HELPER_METER_NAME(__PRETTY_FUNCTION__); 22284d6c458bSopenharmony_ci { 22294d6c458bSopenharmony_ci std::lock_guard<std::recursive_mutex> lock(liveStatusLock_); 22304d6c458bSopenharmony_ci if (!HostIsStop() && !isHostEnvExited_) { 22314d6c458bSopenharmony_ci auto hostEngine = reinterpret_cast<NativeEngine*>(hostEnv_); 22324d6c458bSopenharmony_ci auto workerEngine = reinterpret_cast<NativeEngine*>(workerEnv_); 22334d6c458bSopenharmony_ci if (hostEngine != nullptr && workerEngine != nullptr) { 22344d6c458bSopenharmony_ci if (!hostEngine->DeleteWorker(workerEngine)) { 22354d6c458bSopenharmony_ci HILOG_ERROR("worker:: DeleteWorker error"); 22364d6c458bSopenharmony_ci } 22374d6c458bSopenharmony_ci hostEngine->DecreaseSubEnvCounter(); 22384d6c458bSopenharmony_ci } 22394d6c458bSopenharmony_ci } 22404d6c458bSopenharmony_ci if (isHostEnvExited_) { 22414d6c458bSopenharmony_ci EraseWorker(); 22424d6c458bSopenharmony_ci } 22434d6c458bSopenharmony_ci } 22444d6c458bSopenharmony_ci // 1. delete worker listener 22454d6c458bSopenharmony_ci ParentPortRemoveAllListenerInner(); 22464d6c458bSopenharmony_ci 22474d6c458bSopenharmony_ci // 2. delete worker's parentPort 22484d6c458bSopenharmony_ci NapiHelper::DeleteReference(workerEnv_, workerPort_); 22494d6c458bSopenharmony_ci workerPort_ = nullptr; 22504d6c458bSopenharmony_ci 22514d6c458bSopenharmony_ci // 3. clear message send to worker thread 22524d6c458bSopenharmony_ci workerMessageQueue_.Clear(workerEnv_); 22534d6c458bSopenharmony_ci workerGlobalCallQueue_.Clear(workerEnv_); 22544d6c458bSopenharmony_ci CloseHelp::DeletePointer(reinterpret_cast<NativeEngine*>(workerEnv_), false); 22554d6c458bSopenharmony_ci workerEnv_ = nullptr; 22564d6c458bSopenharmony_ci} 22574d6c458bSopenharmony_ci 22584d6c458bSopenharmony_civoid Worker::ParentPortAddListenerInner(napi_env env, const char* type, const WorkerListener* listener) 22594d6c458bSopenharmony_ci{ 22604d6c458bSopenharmony_ci std::string typestr(type); 22614d6c458bSopenharmony_ci auto iter = parentPortEventListeners_.find(typestr); 22624d6c458bSopenharmony_ci if (iter == parentPortEventListeners_.end()) { 22634d6c458bSopenharmony_ci std::list<WorkerListener*> listeners; 22644d6c458bSopenharmony_ci listeners.emplace_back(const_cast<WorkerListener*>(listener)); 22654d6c458bSopenharmony_ci parentPortEventListeners_[typestr] = listeners; 22664d6c458bSopenharmony_ci } else { 22674d6c458bSopenharmony_ci std::list<WorkerListener*>& listenerList = iter->second; 22684d6c458bSopenharmony_ci std::list<WorkerListener*>::iterator it = std::find_if( 22694d6c458bSopenharmony_ci listenerList.begin(), listenerList.end(), Worker::FindWorkerListener(env, listener->callback_)); 22704d6c458bSopenharmony_ci if (it != listenerList.end()) { 22714d6c458bSopenharmony_ci return; 22724d6c458bSopenharmony_ci } 22734d6c458bSopenharmony_ci listenerList.emplace_back(const_cast<WorkerListener*>(listener)); 22744d6c458bSopenharmony_ci } 22754d6c458bSopenharmony_ci} 22764d6c458bSopenharmony_ci 22774d6c458bSopenharmony_civoid Worker::ParentPortRemoveAllListenerInner() 22784d6c458bSopenharmony_ci{ 22794d6c458bSopenharmony_ci for (auto iter = parentPortEventListeners_.begin(); iter != parentPortEventListeners_.end(); iter++) { 22804d6c458bSopenharmony_ci std::list<WorkerListener*>& listeners = iter->second; 22814d6c458bSopenharmony_ci for (auto item = listeners.begin(); item != listeners.end(); item++) { 22824d6c458bSopenharmony_ci WorkerListener* listener = *item; 22834d6c458bSopenharmony_ci CloseHelp::DeletePointer(listener, false); 22844d6c458bSopenharmony_ci } 22854d6c458bSopenharmony_ci } 22864d6c458bSopenharmony_ci parentPortEventListeners_.clear(); 22874d6c458bSopenharmony_ci} 22884d6c458bSopenharmony_ci 22894d6c458bSopenharmony_civoid Worker::ParentPortRemoveListenerInner(napi_env env, const char* type, napi_ref callback) 22904d6c458bSopenharmony_ci{ 22914d6c458bSopenharmony_ci std::string typestr(type); 22924d6c458bSopenharmony_ci auto iter = parentPortEventListeners_.find(typestr); 22934d6c458bSopenharmony_ci if (iter == parentPortEventListeners_.end()) { 22944d6c458bSopenharmony_ci return; 22954d6c458bSopenharmony_ci } 22964d6c458bSopenharmony_ci std::list<WorkerListener*>& listenerList = iter->second; 22974d6c458bSopenharmony_ci if (callback != nullptr) { 22984d6c458bSopenharmony_ci std::list<WorkerListener*>::iterator it = 22994d6c458bSopenharmony_ci std::find_if(listenerList.begin(), listenerList.end(), Worker::FindWorkerListener(env, callback)); 23004d6c458bSopenharmony_ci if (it != listenerList.end()) { 23014d6c458bSopenharmony_ci CloseHelp::DeletePointer(*it, false); 23024d6c458bSopenharmony_ci listenerList.erase(it); 23034d6c458bSopenharmony_ci } 23044d6c458bSopenharmony_ci } else { 23054d6c458bSopenharmony_ci for (auto it = listenerList.begin(); it != listenerList.end(); it++) { 23064d6c458bSopenharmony_ci CloseHelp::DeletePointer(*it, false); 23074d6c458bSopenharmony_ci } 23084d6c458bSopenharmony_ci parentPortEventListeners_.erase(typestr); 23094d6c458bSopenharmony_ci } 23104d6c458bSopenharmony_ci} 23114d6c458bSopenharmony_ci 23124d6c458bSopenharmony_civoid Worker::ParentPortHandleEventListeners(napi_env env, napi_value recv, size_t argc, 23134d6c458bSopenharmony_ci const napi_value* argv, const char* type, bool tryCatch) 23144d6c458bSopenharmony_ci{ 23154d6c458bSopenharmony_ci std::string listener(type); 23164d6c458bSopenharmony_ci auto iter = parentPortEventListeners_.find(listener); 23174d6c458bSopenharmony_ci if (iter == parentPortEventListeners_.end()) { 23184d6c458bSopenharmony_ci HILOG_DEBUG("worker:: there is no listener for type %{public}s in worker thread", type); 23194d6c458bSopenharmony_ci return; 23204d6c458bSopenharmony_ci } 23214d6c458bSopenharmony_ci 23224d6c458bSopenharmony_ci std::list<WorkerListener*>& listeners = iter->second; 23234d6c458bSopenharmony_ci std::list<WorkerListener*>::iterator it = listeners.begin(); 23244d6c458bSopenharmony_ci while (it != listeners.end()) { 23254d6c458bSopenharmony_ci WorkerListener* data = *it++; 23264d6c458bSopenharmony_ci napi_value callbackObj = NapiHelper::GetReferenceValue(env, data->callback_); 23274d6c458bSopenharmony_ci if (!NapiHelper::IsCallable(env, callbackObj)) { 23284d6c458bSopenharmony_ci HILOG_WARN("worker:: workerPort.addEventListener %{public}s is not callable", type); 23294d6c458bSopenharmony_ci return; 23304d6c458bSopenharmony_ci } 23314d6c458bSopenharmony_ci napi_value callbackResult = nullptr; 23324d6c458bSopenharmony_ci napi_call_function(env, recv, callbackObj, argc, argv, &callbackResult); 23334d6c458bSopenharmony_ci if (!data->NextIsAvailable()) { 23344d6c458bSopenharmony_ci listeners.remove(data); 23354d6c458bSopenharmony_ci CloseHelp::DeletePointer(data, false); 23364d6c458bSopenharmony_ci } 23374d6c458bSopenharmony_ci if (tryCatch && callbackResult == nullptr) { 23384d6c458bSopenharmony_ci HandleException(); 23394d6c458bSopenharmony_ci return; 23404d6c458bSopenharmony_ci } 23414d6c458bSopenharmony_ci } 23424d6c458bSopenharmony_ci} 23434d6c458bSopenharmony_ci 23444d6c458bSopenharmony_civoid Worker::WorkerThrowError(napi_env env, int32_t errCode, const char* errMessage) 23454d6c458bSopenharmony_ci{ 23464d6c458bSopenharmony_ci auto mainThreadEngine = NativeEngine::GetMainThreadEngine(); 23474d6c458bSopenharmony_ci if (mainThreadEngine == nullptr) { 23484d6c458bSopenharmony_ci HILOG_ERROR("worker:: mainThreadEngine is nullptr"); 23494d6c458bSopenharmony_ci return; 23504d6c458bSopenharmony_ci } 23514d6c458bSopenharmony_ci if (mainThreadEngine->IsTargetWorkerVersion(WorkerVersion::NEW)) { 23524d6c458bSopenharmony_ci ErrorHelper::ThrowError(env, errCode, errMessage); 23534d6c458bSopenharmony_ci } 23544d6c458bSopenharmony_ci} 23554d6c458bSopenharmony_ci 23564d6c458bSopenharmony_cibool Worker::CanCreateWorker(napi_env env, WorkerVersion target) 23574d6c458bSopenharmony_ci{ 23584d6c458bSopenharmony_ci auto mainThreadEngine = NativeEngine::GetMainThreadEngine(); 23594d6c458bSopenharmony_ci if (mainThreadEngine == nullptr) { 23604d6c458bSopenharmony_ci HILOG_ERROR("worker:: mainThreadEngine is nullptr"); 23614d6c458bSopenharmony_ci return false; 23624d6c458bSopenharmony_ci } 23634d6c458bSopenharmony_ci if (mainThreadEngine->CheckAndSetWorkerVersion(WorkerVersion::NONE, target) || 23644d6c458bSopenharmony_ci mainThreadEngine->IsTargetWorkerVersion(target)) { 23654d6c458bSopenharmony_ci return true; 23664d6c458bSopenharmony_ci } 23674d6c458bSopenharmony_ci return false; 23684d6c458bSopenharmony_ci} 23694d6c458bSopenharmony_ci 23704d6c458bSopenharmony_ci#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) 23714d6c458bSopenharmony_civoid Worker::HandleDebuggerTask(const uv_async_t* req) 23724d6c458bSopenharmony_ci{ 23734d6c458bSopenharmony_ci Worker* worker = DereferenceHelp::DereferenceOf(&Worker::debuggerOnPostTaskSignal_, req); 23744d6c458bSopenharmony_ci if (worker == nullptr) { 23754d6c458bSopenharmony_ci HILOG_ERROR("worker::worker is null"); 23764d6c458bSopenharmony_ci return; 23774d6c458bSopenharmony_ci } 23784d6c458bSopenharmony_ci 23794d6c458bSopenharmony_ci worker->debuggerMutex_.lock(); 23804d6c458bSopenharmony_ci auto task = std::move(worker->debuggerQueue_.front()); 23814d6c458bSopenharmony_ci worker->debuggerQueue_.pop(); 23824d6c458bSopenharmony_ci worker->debuggerMutex_.unlock(); 23834d6c458bSopenharmony_ci task(); 23844d6c458bSopenharmony_ci} 23854d6c458bSopenharmony_ci 23864d6c458bSopenharmony_civoid Worker::DebuggerOnPostTask(std::function<void()>&& task) 23874d6c458bSopenharmony_ci{ 23884d6c458bSopenharmony_ci if (IsTerminated()) { 23894d6c458bSopenharmony_ci HILOG_ERROR("worker:: worker has been terminated."); 23904d6c458bSopenharmony_ci return; 23914d6c458bSopenharmony_ci } 23924d6c458bSopenharmony_ci if (!uv_is_closing((uv_handle_t*)&debuggerOnPostTaskSignal_)) { 23934d6c458bSopenharmony_ci std::lock_guard<std::mutex> lock(debuggerMutex_); 23944d6c458bSopenharmony_ci debuggerQueue_.push(std::move(task)); 23954d6c458bSopenharmony_ci uv_async_send(&debuggerOnPostTaskSignal_); 23964d6c458bSopenharmony_ci } 23974d6c458bSopenharmony_ci} 23984d6c458bSopenharmony_ci#endif 23994d6c458bSopenharmony_ci 24004d6c458bSopenharmony_civoid Worker::InitHostHandle(uv_loop_t* loop) 24014d6c458bSopenharmony_ci{ 24024d6c458bSopenharmony_ci hostOnMessageSignal_ = new uv_async_t; 24034d6c458bSopenharmony_ci uv_async_init(loop, hostOnMessageSignal_, reinterpret_cast<uv_async_cb>(Worker::HostOnMessage)); 24044d6c458bSopenharmony_ci hostOnMessageSignal_->data = this; 24054d6c458bSopenharmony_ci hostOnErrorSignal_ = new uv_async_t; 24064d6c458bSopenharmony_ci uv_async_init(loop, hostOnErrorSignal_, reinterpret_cast<uv_async_cb>(Worker::HostOnError)); 24074d6c458bSopenharmony_ci hostOnErrorSignal_->data = this; 24084d6c458bSopenharmony_ci hostOnGlobalCallSignal_ = new uv_async_t; 24094d6c458bSopenharmony_ci uv_async_init(loop, hostOnGlobalCallSignal_, reinterpret_cast<uv_async_cb>(Worker::HostOnGlobalCall)); 24104d6c458bSopenharmony_ci hostOnGlobalCallSignal_->data = this; 24114d6c458bSopenharmony_ci} 24124d6c458bSopenharmony_ci 24134d6c458bSopenharmony_civoid Worker::CloseHostHandle() 24144d6c458bSopenharmony_ci{ 24154d6c458bSopenharmony_ci if (hostOnMessageSignal_ != nullptr && !uv_is_closing(reinterpret_cast<uv_handle_t*>(hostOnMessageSignal_))) { 24164d6c458bSopenharmony_ci uv_close(reinterpret_cast<uv_handle_t*>(hostOnMessageSignal_), [](uv_handle_t* handle) { 24174d6c458bSopenharmony_ci delete reinterpret_cast<uv_async_t*>(handle); 24184d6c458bSopenharmony_ci handle = nullptr; 24194d6c458bSopenharmony_ci }); 24204d6c458bSopenharmony_ci } 24214d6c458bSopenharmony_ci if (hostOnErrorSignal_ != nullptr && !uv_is_closing(reinterpret_cast<uv_handle_t*>(hostOnErrorSignal_))) { 24224d6c458bSopenharmony_ci uv_close(reinterpret_cast<uv_handle_t*>(hostOnErrorSignal_), [](uv_handle_t* handle) { 24234d6c458bSopenharmony_ci delete reinterpret_cast<uv_async_t*>(handle); 24244d6c458bSopenharmony_ci handle = nullptr; 24254d6c458bSopenharmony_ci }); 24264d6c458bSopenharmony_ci } 24274d6c458bSopenharmony_ci if (hostOnGlobalCallSignal_ != nullptr && !uv_is_closing(reinterpret_cast<uv_handle_t*>(hostOnGlobalCallSignal_))) { 24284d6c458bSopenharmony_ci uv_close(reinterpret_cast<uv_handle_t*>(hostOnGlobalCallSignal_), [](uv_handle_t* handle) { 24294d6c458bSopenharmony_ci delete reinterpret_cast<uv_async_t*>(handle); 24304d6c458bSopenharmony_ci handle = nullptr; 24314d6c458bSopenharmony_ci }); 24324d6c458bSopenharmony_ci } 24334d6c458bSopenharmony_ci} 24344d6c458bSopenharmony_ci 24354d6c458bSopenharmony_civoid Worker::EraseWorker() 24364d6c458bSopenharmony_ci{ 24374d6c458bSopenharmony_ci if (!isLimitedWorker_) { 24384d6c458bSopenharmony_ci std::lock_guard<std::mutex> lock(g_workersMutex); 24394d6c458bSopenharmony_ci std::list<Worker*>::iterator it = std::find(g_workers.begin(), g_workers.end(), this); 24404d6c458bSopenharmony_ci if (it != g_workers.end()) { 24414d6c458bSopenharmony_ci g_workers.erase(it); 24424d6c458bSopenharmony_ci } 24434d6c458bSopenharmony_ci } else { 24444d6c458bSopenharmony_ci std::lock_guard<std::mutex> lock(g_limitedworkersMutex); 24454d6c458bSopenharmony_ci std::list<Worker*>::iterator it = std::find(g_limitedworkers.begin(), g_limitedworkers.end(), this); 24464d6c458bSopenharmony_ci if (it != g_limitedworkers.end()) { 24474d6c458bSopenharmony_ci g_limitedworkers.erase(it); 24484d6c458bSopenharmony_ci } 24494d6c458bSopenharmony_ci } 24504d6c458bSopenharmony_ci} 24514d6c458bSopenharmony_ci 24524d6c458bSopenharmony_civoid Worker::ClearHostMessage(napi_env env) 24534d6c458bSopenharmony_ci{ 24544d6c458bSopenharmony_ci hostMessageQueue_.Clear(env); 24554d6c458bSopenharmony_ci hostGlobalCallQueue_.Clear(env); 24564d6c458bSopenharmony_ci errorQueue_.Clear(env); 24574d6c458bSopenharmony_ci} 24584d6c458bSopenharmony_ci} // namespace Commonlibrary::Concurrent::WorkerModule 2459