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