133eb0b6dSopenharmony_ci/*
233eb0b6dSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
333eb0b6dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
433eb0b6dSopenharmony_ci * you may not use this file except in compliance with the License.
533eb0b6dSopenharmony_ci * You may obtain a copy of the License at
633eb0b6dSopenharmony_ci *
733eb0b6dSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
833eb0b6dSopenharmony_ci *
933eb0b6dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1033eb0b6dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1133eb0b6dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1233eb0b6dSopenharmony_ci * See the License for the specific language governing permissions and
1333eb0b6dSopenharmony_ci * limitations under the License.
1433eb0b6dSopenharmony_ci */
1533eb0b6dSopenharmony_ci
1633eb0b6dSopenharmony_ci#include "native_engine/native_engine.h"
1733eb0b6dSopenharmony_ci
1833eb0b6dSopenharmony_ci#include <uv.h>
1933eb0b6dSopenharmony_ci#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(IOS_PLATFORM) && !defined(LINUX_PLATFORM)
2033eb0b6dSopenharmony_ci#include <sys/epoll.h>
2133eb0b6dSopenharmony_ci#endif
2233eb0b6dSopenharmony_ci#ifdef IOS_PLATFORM
2333eb0b6dSopenharmony_ci#include <sys/event.h>
2433eb0b6dSopenharmony_ci#endif
2533eb0b6dSopenharmony_ci
2633eb0b6dSopenharmony_ci#include "ecmascript/napi/include/jsnapi.h"
2733eb0b6dSopenharmony_ci#include "native_engine/native_utils.h"
2833eb0b6dSopenharmony_ci#include "unicode/ucnv.h"
2933eb0b6dSopenharmony_ci#include "utils/log.h"
3033eb0b6dSopenharmony_ci
3133eb0b6dSopenharmony_ciconstexpr size_t NAME_BUFFER_SIZE = 64;
3233eb0b6dSopenharmony_cistatic constexpr auto PANDA_MAIN_FUNCTION = "_GLOBAL::func_main_0";
3333eb0b6dSopenharmony_cistatic constexpr int32_t API11 = 11;
3433eb0b6dSopenharmony_ci
3533eb0b6dSopenharmony_ciusing panda::JSValueRef;
3633eb0b6dSopenharmony_ciusing panda::Local;
3733eb0b6dSopenharmony_ciusing panda::LocalScope;
3833eb0b6dSopenharmony_ciusing panda::ObjectRef;
3933eb0b6dSopenharmony_ciusing panda::StringRef;
4033eb0b6dSopenharmony_ci
4133eb0b6dSopenharmony_cinamespace {
4233eb0b6dSopenharmony_ciconst char* g_errorMessages[] = {
4333eb0b6dSopenharmony_ci    nullptr,
4433eb0b6dSopenharmony_ci    "Invalid parameter",
4533eb0b6dSopenharmony_ci    "Need object",
4633eb0b6dSopenharmony_ci    "Need string",
4733eb0b6dSopenharmony_ci    "Need string or symbol",
4833eb0b6dSopenharmony_ci    "Need function",
4933eb0b6dSopenharmony_ci    "Need number",
5033eb0b6dSopenharmony_ci    "Need boolean",
5133eb0b6dSopenharmony_ci    "Need array",
5233eb0b6dSopenharmony_ci    "Generic failure",
5333eb0b6dSopenharmony_ci    "An exception is blocking",
5433eb0b6dSopenharmony_ci    "Asynchronous work cancelled",
5533eb0b6dSopenharmony_ci    "Escape called twice",
5633eb0b6dSopenharmony_ci    "Handle scope mismatch",
5733eb0b6dSopenharmony_ci    "Callback scope mismatch",
5833eb0b6dSopenharmony_ci    "Asynchronous work queue is full",
5933eb0b6dSopenharmony_ci    "Asynchronous work handle is closing",
6033eb0b6dSopenharmony_ci    "Need bigint",
6133eb0b6dSopenharmony_ci    "Need date",
6233eb0b6dSopenharmony_ci    "Need arraybuffer",
6333eb0b6dSopenharmony_ci    "Need detachable arraybuffer",
6433eb0b6dSopenharmony_ci};
6533eb0b6dSopenharmony_ci} // namespace
6633eb0b6dSopenharmony_ci
6733eb0b6dSopenharmony_cithread_local static GetContainerScopeIdCallback g_getContainerScopeIdFunc;
6833eb0b6dSopenharmony_cithread_local static ContainerScopeCallback g_initContainerScopeFunc;
6933eb0b6dSopenharmony_cithread_local static ContainerScopeCallback g_finishContainerScopeFunc;
7033eb0b6dSopenharmony_ci
7133eb0b6dSopenharmony_cistd::mutex NativeEngine::g_alivedEngineMutex_;
7233eb0b6dSopenharmony_cistd::unordered_set<NativeEngine*> NativeEngine::g_alivedEngine_;
7333eb0b6dSopenharmony_ciuint64_t NativeEngine::g_lastEngineId_ = 1;
7433eb0b6dSopenharmony_cistd::mutex NativeEngine::g_mainThreadEngineMutex_;
7533eb0b6dSopenharmony_ciNativeEngine* NativeEngine::g_mainThreadEngine_;
7633eb0b6dSopenharmony_ci
7733eb0b6dSopenharmony_ciNativeEngine::NativeEngine(void* jsEngine) : jsEngine_(jsEngine)
7833eb0b6dSopenharmony_ci{
7933eb0b6dSopenharmony_ci    SetMainThreadEngine(this);
8033eb0b6dSopenharmony_ci    SetAlived();
8133eb0b6dSopenharmony_ci    InitUvField();
8233eb0b6dSopenharmony_ci}
8333eb0b6dSopenharmony_ci
8433eb0b6dSopenharmony_ciNativeEngine::NativeEngine(void* jsEngine, EcmaVM* vm) : jsEngine_(jsEngine), vm_(vm)
8533eb0b6dSopenharmony_ci{
8633eb0b6dSopenharmony_ci    SetMainThreadEngine(this);
8733eb0b6dSopenharmony_ci    SetAlived();
8833eb0b6dSopenharmony_ci    InitUvField();
8933eb0b6dSopenharmony_ci}
9033eb0b6dSopenharmony_ci
9133eb0b6dSopenharmony_civoid NativeEngine::InitUvField()
9233eb0b6dSopenharmony_ci{
9333eb0b6dSopenharmony_ci    if (memset_s(&uvAsync_, sizeof(uvAsync_), 0, sizeof(uvAsync_)) != EOK) {
9433eb0b6dSopenharmony_ci        HILOG_ERROR("failed to init uvAsync_");
9533eb0b6dSopenharmony_ci        return;
9633eb0b6dSopenharmony_ci    }
9733eb0b6dSopenharmony_ci    if (memset_s(&uvSem_, sizeof(uvSem_), 0, sizeof(uvSem_)) != EOK) {
9833eb0b6dSopenharmony_ci        HILOG_ERROR("failed to init uvSem_");
9933eb0b6dSopenharmony_ci        return;
10033eb0b6dSopenharmony_ci    }
10133eb0b6dSopenharmony_ci#if !defined(PREVIEW)
10233eb0b6dSopenharmony_ci    if (memset_s(&uvThread_, sizeof(uvThread_), 0, sizeof(uvThread_)) != EOK) {
10333eb0b6dSopenharmony_ci        HILOG_ERROR("failed to init uvThread_");
10433eb0b6dSopenharmony_ci        return;
10533eb0b6dSopenharmony_ci    }
10633eb0b6dSopenharmony_ci#endif
10733eb0b6dSopenharmony_ci}
10833eb0b6dSopenharmony_ci
10933eb0b6dSopenharmony_ciNativeEngine::~NativeEngine()
11033eb0b6dSopenharmony_ci{
11133eb0b6dSopenharmony_ci    HILOG_INFO("NativeEngine::~NativeEngine");
11233eb0b6dSopenharmony_ci    isInDestructor_ = true;
11333eb0b6dSopenharmony_ci    if (cleanEnv_ != nullptr) {
11433eb0b6dSopenharmony_ci        cleanEnv_();
11533eb0b6dSopenharmony_ci    }
11633eb0b6dSopenharmony_ci    std::lock_guard<std::mutex> insLock(instanceDataLock_);
11733eb0b6dSopenharmony_ci    FinalizerInstanceData();
11833eb0b6dSopenharmony_ci    vm_ = nullptr;
11933eb0b6dSopenharmony_ci}
12033eb0b6dSopenharmony_ci
12133eb0b6dSopenharmony_cistatic void ThreadSafeCallback(napi_env env, napi_value jsCallback, void* context, void* data)
12233eb0b6dSopenharmony_ci{
12333eb0b6dSopenharmony_ci    if (data != nullptr) {
12433eb0b6dSopenharmony_ci        CallbackWrapper *cbw = static_cast<CallbackWrapper *>(data);
12533eb0b6dSopenharmony_ci        cbw->cb();
12633eb0b6dSopenharmony_ci        delete cbw;
12733eb0b6dSopenharmony_ci        cbw = nullptr;
12833eb0b6dSopenharmony_ci        data = nullptr;
12933eb0b6dSopenharmony_ci    }
13033eb0b6dSopenharmony_ci}
13133eb0b6dSopenharmony_ci
13233eb0b6dSopenharmony_civoid NativeEngine::CreateDefaultFunction(void)
13333eb0b6dSopenharmony_ci{
13433eb0b6dSopenharmony_ci    std::unique_lock<std::shared_mutex> writeLock(eventMutex_);
13533eb0b6dSopenharmony_ci    if (defaultFunc_) {
13633eb0b6dSopenharmony_ci        return;
13733eb0b6dSopenharmony_ci    }
13833eb0b6dSopenharmony_ci    napi_env env = reinterpret_cast<napi_env>(this);
13933eb0b6dSopenharmony_ci    napi_value resourceName = nullptr;
14033eb0b6dSopenharmony_ci    napi_create_string_utf8(env, "call_default_threadsafe_function", NAPI_AUTO_LENGTH, &resourceName);
14133eb0b6dSopenharmony_ci    napi_create_threadsafe_function(env, nullptr, nullptr, resourceName, 0, 1,
14233eb0b6dSopenharmony_ci        nullptr, nullptr, nullptr, ThreadSafeCallback, &defaultFunc_);
14333eb0b6dSopenharmony_ci}
14433eb0b6dSopenharmony_ci
14533eb0b6dSopenharmony_civoid NativeEngine::DestoryDefaultFunction(bool release)
14633eb0b6dSopenharmony_ci{
14733eb0b6dSopenharmony_ci    std::unique_lock<std::shared_mutex> writeLock(eventMutex_);
14833eb0b6dSopenharmony_ci    if (!defaultFunc_) {
14933eb0b6dSopenharmony_ci        return;
15033eb0b6dSopenharmony_ci    }
15133eb0b6dSopenharmony_ci    if (release) {
15233eb0b6dSopenharmony_ci        napi_release_threadsafe_function(defaultFunc_, napi_tsfn_abort);
15333eb0b6dSopenharmony_ci    } else {
15433eb0b6dSopenharmony_ci        NativeSafeAsyncWork* work = reinterpret_cast<NativeSafeAsyncWork*>(defaultFunc_);
15533eb0b6dSopenharmony_ci        delete work; // only free mem due to uv_loop is invalid
15633eb0b6dSopenharmony_ci    }
15733eb0b6dSopenharmony_ci    defaultFunc_ = nullptr;
15833eb0b6dSopenharmony_ci}
15933eb0b6dSopenharmony_ci
16033eb0b6dSopenharmony_civoid NativeEngine::Init()
16133eb0b6dSopenharmony_ci{
16233eb0b6dSopenharmony_ci    HILOG_DEBUG("NativeEngine::Init");
16333eb0b6dSopenharmony_ci    moduleManager_ = NativeModuleManager::GetInstance();
16433eb0b6dSopenharmony_ci    referenceManager_ = new NativeReferenceManager();
16533eb0b6dSopenharmony_ci    callbackScopeManager_ = new NativeCallbackScopeManager();
16633eb0b6dSopenharmony_ci    tid_ = pthread_self();
16733eb0b6dSopenharmony_ci    sysTid_ = GetCurSysTid();
16833eb0b6dSopenharmony_ci
16933eb0b6dSopenharmony_ci    loop_ = new (std::nothrow)uv_loop_t;
17033eb0b6dSopenharmony_ci    if (loop_ == nullptr) {
17133eb0b6dSopenharmony_ci        HILOG_ERROR("failed to create uv_loop, async task interface would not work");
17233eb0b6dSopenharmony_ci        return;
17333eb0b6dSopenharmony_ci    }
17433eb0b6dSopenharmony_ci    if (uv_loop_init(loop_) != EOK) {
17533eb0b6dSopenharmony_ci        HILOG_ERROR("failed to init uv_loop, async task interface would not work");
17633eb0b6dSopenharmony_ci        delete loop_;
17733eb0b6dSopenharmony_ci        loop_ = nullptr;
17833eb0b6dSopenharmony_ci        return;
17933eb0b6dSopenharmony_ci    }
18033eb0b6dSopenharmony_ci    uv_async_init(loop_, &uvAsync_, nullptr);
18133eb0b6dSopenharmony_ci    uv_sem_init(&uvSem_, 0);
18233eb0b6dSopenharmony_ci    CreateDefaultFunction();
18333eb0b6dSopenharmony_ci}
18433eb0b6dSopenharmony_ci
18533eb0b6dSopenharmony_civoid NativeEngine::Deinit()
18633eb0b6dSopenharmony_ci{
18733eb0b6dSopenharmony_ci    HILOG_INFO("NativeEngine::Deinit");
18833eb0b6dSopenharmony_ci    if (loop_ != nullptr) {
18933eb0b6dSopenharmony_ci        DestoryDefaultFunction(true);
19033eb0b6dSopenharmony_ci        uv_sem_destroy(&uvSem_);
19133eb0b6dSopenharmony_ci        uv_close((uv_handle_t*)&uvAsync_, nullptr);
19233eb0b6dSopenharmony_ci    }
19333eb0b6dSopenharmony_ci
19433eb0b6dSopenharmony_ci    RunCleanup();
19533eb0b6dSopenharmony_ci    if (referenceManager_ != nullptr) {
19633eb0b6dSopenharmony_ci        delete referenceManager_;
19733eb0b6dSopenharmony_ci        referenceManager_ = nullptr;
19833eb0b6dSopenharmony_ci    }
19933eb0b6dSopenharmony_ci
20033eb0b6dSopenharmony_ci    SetUnalived();
20133eb0b6dSopenharmony_ci    SetStopping(true);
20233eb0b6dSopenharmony_ci    if (loop_ == nullptr) {
20333eb0b6dSopenharmony_ci        return;
20433eb0b6dSopenharmony_ci    }
20533eb0b6dSopenharmony_ci    if (uv_loop_close(loop_) != EOK) {
20633eb0b6dSopenharmony_ci        HILOG_WARN("faild to close uv_loop, rerun it.");
20733eb0b6dSopenharmony_ci        // execute works posted from finalize_cb
20833eb0b6dSopenharmony_ci        uv_run(loop_, UV_RUN_DEFAULT);
20933eb0b6dSopenharmony_ci        if (uv_loop_close(loop_) != EOK) {
21033eb0b6dSopenharmony_ci            // it maybe up to fatal level later
21133eb0b6dSopenharmony_ci            HILOG_ERROR("faild to close uv_loop, after reran.");
21233eb0b6dSopenharmony_ci        }
21333eb0b6dSopenharmony_ci    };
21433eb0b6dSopenharmony_ci    delete loop_;
21533eb0b6dSopenharmony_ci    loop_ = nullptr;
21633eb0b6dSopenharmony_ci}
21733eb0b6dSopenharmony_ci
21833eb0b6dSopenharmony_ciNativeReferenceManager* NativeEngine::GetReferenceManager()
21933eb0b6dSopenharmony_ci{
22033eb0b6dSopenharmony_ci    return referenceManager_;
22133eb0b6dSopenharmony_ci}
22233eb0b6dSopenharmony_ci
22333eb0b6dSopenharmony_ciNativeModuleManager* NativeEngine::GetModuleManager()
22433eb0b6dSopenharmony_ci{
22533eb0b6dSopenharmony_ci    return moduleManager_;
22633eb0b6dSopenharmony_ci}
22733eb0b6dSopenharmony_ci
22833eb0b6dSopenharmony_ciNativeCallbackScopeManager* NativeEngine::GetCallbackScopeManager()
22933eb0b6dSopenharmony_ci{
23033eb0b6dSopenharmony_ci    return callbackScopeManager_;
23133eb0b6dSopenharmony_ci}
23233eb0b6dSopenharmony_ci
23333eb0b6dSopenharmony_ciuv_loop_t* NativeEngine::GetUVLoop() const
23433eb0b6dSopenharmony_ci{
23533eb0b6dSopenharmony_ci    return loop_;
23633eb0b6dSopenharmony_ci}
23733eb0b6dSopenharmony_ci
23833eb0b6dSopenharmony_cipthread_t NativeEngine::GetTid() const
23933eb0b6dSopenharmony_ci{
24033eb0b6dSopenharmony_ci    return tid_;
24133eb0b6dSopenharmony_ci}
24233eb0b6dSopenharmony_ci
24333eb0b6dSopenharmony_ciThreadId NativeEngine::GetCurSysTid()
24433eb0b6dSopenharmony_ci{
24533eb0b6dSopenharmony_ci    return reinterpret_cast<ThreadId>(panda::JSNApi::GetCurrentThreadId());
24633eb0b6dSopenharmony_ci}
24733eb0b6dSopenharmony_ci
24833eb0b6dSopenharmony_ci// should only be called if process is forked, other case would cause fd_leak
24933eb0b6dSopenharmony_cibool NativeEngine::ReinitUVLoop()
25033eb0b6dSopenharmony_ci{
25133eb0b6dSopenharmony_ci    if (defaultFunc_ != nullptr) {
25233eb0b6dSopenharmony_ci        DestoryDefaultFunction(false);
25333eb0b6dSopenharmony_ci    }
25433eb0b6dSopenharmony_ci
25533eb0b6dSopenharmony_ci    if (loop_ != nullptr) {
25633eb0b6dSopenharmony_ci        delete loop_;  // only free mem due to uv_loop is invalid
25733eb0b6dSopenharmony_ci        loop_ = nullptr;
25833eb0b6dSopenharmony_ci    }
25933eb0b6dSopenharmony_ci
26033eb0b6dSopenharmony_ci    tid_ = pthread_self();
26133eb0b6dSopenharmony_ci    sysTid_ = GetCurSysTid();
26233eb0b6dSopenharmony_ci
26333eb0b6dSopenharmony_ci    loop_ = new (std::nothrow)uv_loop_t;
26433eb0b6dSopenharmony_ci    if (loop_ == nullptr) {
26533eb0b6dSopenharmony_ci        HILOG_ERROR("failed to create uv_loop, async task interface would not work");
26633eb0b6dSopenharmony_ci        return false;
26733eb0b6dSopenharmony_ci    }
26833eb0b6dSopenharmony_ci    if (uv_loop_init(loop_) != EOK) {
26933eb0b6dSopenharmony_ci        HILOG_ERROR("failed to init uv_loop, async task interface would not work");
27033eb0b6dSopenharmony_ci        delete loop_;
27133eb0b6dSopenharmony_ci        loop_ = nullptr;
27233eb0b6dSopenharmony_ci        return false;
27333eb0b6dSopenharmony_ci    }
27433eb0b6dSopenharmony_ci
27533eb0b6dSopenharmony_ci    uv_async_init(loop_, &uvAsync_, nullptr);
27633eb0b6dSopenharmony_ci    uv_sem_init(&uvSem_, 0);
27733eb0b6dSopenharmony_ci    CreateDefaultFunction();
27833eb0b6dSopenharmony_ci
27933eb0b6dSopenharmony_ci    return true;
28033eb0b6dSopenharmony_ci}
28133eb0b6dSopenharmony_ci
28233eb0b6dSopenharmony_civoid NativeEngine::Loop(LoopMode mode, bool needSync)
28333eb0b6dSopenharmony_ci{
28433eb0b6dSopenharmony_ci    if (loop_ == nullptr) {
28533eb0b6dSopenharmony_ci        HILOG_ERROR("uv loop is nullptr");
28633eb0b6dSopenharmony_ci        return;
28733eb0b6dSopenharmony_ci    }
28833eb0b6dSopenharmony_ci    bool more = true;
28933eb0b6dSopenharmony_ci    switch (mode) {
29033eb0b6dSopenharmony_ci        case LoopMode::LOOP_DEFAULT:
29133eb0b6dSopenharmony_ci            more = uv_run(loop_, UV_RUN_DEFAULT);
29233eb0b6dSopenharmony_ci            break;
29333eb0b6dSopenharmony_ci        case LoopMode::LOOP_ONCE:
29433eb0b6dSopenharmony_ci            more = uv_run(loop_, UV_RUN_ONCE);
29533eb0b6dSopenharmony_ci            break;
29633eb0b6dSopenharmony_ci        case LoopMode::LOOP_NOWAIT:
29733eb0b6dSopenharmony_ci            more = uv_run(loop_, UV_RUN_NOWAIT);
29833eb0b6dSopenharmony_ci            break;
29933eb0b6dSopenharmony_ci        default:
30033eb0b6dSopenharmony_ci            return;
30133eb0b6dSopenharmony_ci    }
30233eb0b6dSopenharmony_ci    if (more == false) {
30333eb0b6dSopenharmony_ci        uv_loop_alive(loop_);
30433eb0b6dSopenharmony_ci    }
30533eb0b6dSopenharmony_ci
30633eb0b6dSopenharmony_ci    if (needSync) {
30733eb0b6dSopenharmony_ci        uv_sem_post(&uvSem_);
30833eb0b6dSopenharmony_ci    }
30933eb0b6dSopenharmony_ci}
31033eb0b6dSopenharmony_ci
31133eb0b6dSopenharmony_ci// should only call once in life cycle of ArkNativeEngine(NativeEngine)
31233eb0b6dSopenharmony_civoid NativeEngine::SetAlived()
31333eb0b6dSopenharmony_ci{
31433eb0b6dSopenharmony_ci    if (id_ != 0) {
31533eb0b6dSopenharmony_ci        HILOG_FATAL("id of native engine cannot set twice");
31633eb0b6dSopenharmony_ci    }
31733eb0b6dSopenharmony_ci    std::lock_guard<std::mutex> alivedEngLock(g_alivedEngineMutex_);
31833eb0b6dSopenharmony_ci    g_alivedEngine_.emplace(this);
31933eb0b6dSopenharmony_ci    // must be protected by g_alivedEngineMutex_
32033eb0b6dSopenharmony_ci    id_ = g_lastEngineId_++;
32133eb0b6dSopenharmony_ci    return;
32233eb0b6dSopenharmony_ci}
32333eb0b6dSopenharmony_ci
32433eb0b6dSopenharmony_ciNativeAsyncWork* NativeEngine::CreateAsyncWork(napi_value asyncResource, napi_value asyncResourceName,
32533eb0b6dSopenharmony_ci    NativeAsyncExecuteCallback execute, NativeAsyncCompleteCallback complete, void* data)
32633eb0b6dSopenharmony_ci{
32733eb0b6dSopenharmony_ci    (void)asyncResource;
32833eb0b6dSopenharmony_ci    (void)asyncResourceName;
32933eb0b6dSopenharmony_ci    char name[NAME_BUFFER_SIZE] = {0};
33033eb0b6dSopenharmony_ci    if (asyncResourceName != nullptr) {
33133eb0b6dSopenharmony_ci        auto val = LocalValueFromJsValue(asyncResourceName);
33233eb0b6dSopenharmony_ci        [[maybe_unused]] size_t strLength = 0;
33333eb0b6dSopenharmony_ci        auto vm = GetEcmaVm();
33433eb0b6dSopenharmony_ci        LocalScope scope(vm);
33533eb0b6dSopenharmony_ci        auto str = val->ToString(vm);
33633eb0b6dSopenharmony_ci        char* buffer = name;
33733eb0b6dSopenharmony_ci        if (buffer == nullptr) {
33833eb0b6dSopenharmony_ci            strLength = static_cast<size_t>(str->Utf8Length(vm, true) - 1);
33933eb0b6dSopenharmony_ci        } else if (NAME_BUFFER_SIZE != 0) {
34033eb0b6dSopenharmony_ci            uint32_t copied = str->WriteUtf8(vm, buffer, NAME_BUFFER_SIZE - 1, true) - 1;
34133eb0b6dSopenharmony_ci            buffer[copied] = '\0';
34233eb0b6dSopenharmony_ci            strLength = copied;
34333eb0b6dSopenharmony_ci        } else {
34433eb0b6dSopenharmony_ci            strLength = 0;
34533eb0b6dSopenharmony_ci        }
34633eb0b6dSopenharmony_ci    }
34733eb0b6dSopenharmony_ci    return new NativeAsyncWork(this, execute, complete, name, data);
34833eb0b6dSopenharmony_ci}
34933eb0b6dSopenharmony_ci
35033eb0b6dSopenharmony_ciNativeAsyncWork* NativeEngine::CreateAsyncWork(const std::string& asyncResourceName, NativeAsyncExecuteCallback execute,
35133eb0b6dSopenharmony_ci    NativeAsyncCompleteCallback complete, void* data)
35233eb0b6dSopenharmony_ci{
35333eb0b6dSopenharmony_ci    return new NativeAsyncWork(this, execute, complete, asyncResourceName, data);
35433eb0b6dSopenharmony_ci}
35533eb0b6dSopenharmony_ci
35633eb0b6dSopenharmony_ciNativeSafeAsyncWork* NativeEngine::CreateSafeAsyncWork(napi_value func, napi_value asyncResource,
35733eb0b6dSopenharmony_ci    napi_value asyncResourceName, size_t maxQueueSize, size_t threadCount, void* finalizeData,
35833eb0b6dSopenharmony_ci    NativeFinalize finalizeCallback, void* context, NativeThreadSafeFunctionCallJs callJsCallback)
35933eb0b6dSopenharmony_ci{
36033eb0b6dSopenharmony_ci    return new NativeSafeAsyncWork(this, func, asyncResource, asyncResourceName, maxQueueSize, threadCount,
36133eb0b6dSopenharmony_ci        finalizeData, finalizeCallback, context, callJsCallback);
36233eb0b6dSopenharmony_ci}
36333eb0b6dSopenharmony_ci
36433eb0b6dSopenharmony_ciNativeErrorExtendedInfo* NativeEngine::GetLastError()
36533eb0b6dSopenharmony_ci{
36633eb0b6dSopenharmony_ci    return &lastError_;
36733eb0b6dSopenharmony_ci}
36833eb0b6dSopenharmony_ci
36933eb0b6dSopenharmony_civoid NativeEngine::SetLastError(int errorCode, uint32_t engineErrorCode, void* engineReserved)
37033eb0b6dSopenharmony_ci{
37133eb0b6dSopenharmony_ci    lastError_.errorCode = errorCode;
37233eb0b6dSopenharmony_ci    lastError_.engineErrorCode = engineErrorCode;
37333eb0b6dSopenharmony_ci    lastError_.message = g_errorMessages[lastError_.errorCode];
37433eb0b6dSopenharmony_ci    lastError_.reserved = engineReserved;
37533eb0b6dSopenharmony_ci}
37633eb0b6dSopenharmony_ci
37733eb0b6dSopenharmony_cistatic void SubEncodeToUtf8(const EcmaVM* vm,
37833eb0b6dSopenharmony_ci                            Local<JSValueRef>& nativeValue,
37933eb0b6dSopenharmony_ci                            Local<StringRef>& nativeString,
38033eb0b6dSopenharmony_ci                            char* buffer,
38133eb0b6dSopenharmony_ci                            uint32_t* written,
38233eb0b6dSopenharmony_ci                            size_t bufferSize,
38333eb0b6dSopenharmony_ci                            int32_t* nchars)
38433eb0b6dSopenharmony_ci{
38533eb0b6dSopenharmony_ci    int32_t length = static_cast<int32_t>(nativeString->Length(vm));
38633eb0b6dSopenharmony_ci    uint32_t pos = 0;
38733eb0b6dSopenharmony_ci    uint32_t writableSize = bufferSize;
38833eb0b6dSopenharmony_ci    int32_t i = 0;
38933eb0b6dSopenharmony_ci    panda::Local<ObjectRef> strObj = nativeValue->ToObject(vm);
39033eb0b6dSopenharmony_ci    for (; i < length; i++) {
39133eb0b6dSopenharmony_ci        panda::Local<StringRef> str = strObj->Get(vm, i)->ToString(vm);
39233eb0b6dSopenharmony_ci        // return value of Uft8Length >= 1
39333eb0b6dSopenharmony_ci        uint32_t len = str->Utf8Length(vm) - 1;
39433eb0b6dSopenharmony_ci        if (len > writableSize) {
39533eb0b6dSopenharmony_ci            break;
39633eb0b6dSopenharmony_ci        }
39733eb0b6dSopenharmony_ci        str->WriteUtf8(vm, (buffer + pos), writableSize);
39833eb0b6dSopenharmony_ci        writableSize -= len;
39933eb0b6dSopenharmony_ci        pos += len;
40033eb0b6dSopenharmony_ci    }
40133eb0b6dSopenharmony_ci    *nchars = i;
40233eb0b6dSopenharmony_ci    HILOG_DEBUG("EncodeWriteUtf8 the result of buffer: %{public}s", buffer);
40333eb0b6dSopenharmony_ci    *written = pos;
40433eb0b6dSopenharmony_ci}
40533eb0b6dSopenharmony_ci
40633eb0b6dSopenharmony_civoid NativeEngine::EncodeToUtf8(napi_value value, char* buffer, uint32_t* written, size_t bufferSize, int32_t* nchars)
40733eb0b6dSopenharmony_ci{
40833eb0b6dSopenharmony_ci    auto nativeValue = LocalValueFromJsValue(value);
40933eb0b6dSopenharmony_ci    if (nativeValue->IsNull() || nchars == nullptr || written == nullptr) {
41033eb0b6dSopenharmony_ci        HILOG_ERROR("NativeEngine EncodeToUtf8 args is nullptr");
41133eb0b6dSopenharmony_ci        return;
41233eb0b6dSopenharmony_ci    }
41333eb0b6dSopenharmony_ci
41433eb0b6dSopenharmony_ci    auto vm = GetEcmaVm();
41533eb0b6dSopenharmony_ci    LocalScope scope(vm);
41633eb0b6dSopenharmony_ci    auto nativeString = nativeValue->ToString(vm);
41733eb0b6dSopenharmony_ci    if (!nativeString->IsString(vm)) {
41833eb0b6dSopenharmony_ci        HILOG_ERROR("nativeValue not is string");
41933eb0b6dSopenharmony_ci        return;
42033eb0b6dSopenharmony_ci    }
42133eb0b6dSopenharmony_ci
42233eb0b6dSopenharmony_ci    if (buffer == nullptr) {
42333eb0b6dSopenharmony_ci        HILOG_ERROR("buffer is null");
42433eb0b6dSopenharmony_ci        return;
42533eb0b6dSopenharmony_ci    }
42633eb0b6dSopenharmony_ci
42733eb0b6dSopenharmony_ci    SubEncodeToUtf8(vm, nativeValue, nativeString, buffer, written, bufferSize, nchars);
42833eb0b6dSopenharmony_ci}
42933eb0b6dSopenharmony_ci
43033eb0b6dSopenharmony_cistatic void SubEncodeToChinese(const EcmaVM* vm,
43133eb0b6dSopenharmony_ci                               Local<JSValueRef>& nativeValue,
43233eb0b6dSopenharmony_ci                               Local<StringRef>& nativeString,
43333eb0b6dSopenharmony_ci                               std::string& buffer,
43433eb0b6dSopenharmony_ci                               const char* encode)
43533eb0b6dSopenharmony_ci{
43633eb0b6dSopenharmony_ci    uint32_t length = nativeString->Length(vm);
43733eb0b6dSopenharmony_ci    uint32_t pos = 0;
43833eb0b6dSopenharmony_ci    const int32_t writableSize = 22; // 22 : encode max bytes of the ucnv_convent function;
43933eb0b6dSopenharmony_ci    std::string tempBuf = "";
44033eb0b6dSopenharmony_ci    tempBuf.resize(writableSize + 1);
44133eb0b6dSopenharmony_ci    UErrorCode errorCode = U_ZERO_ERROR;
44233eb0b6dSopenharmony_ci    const char* encFrom = "utf8";
44333eb0b6dSopenharmony_ci    panda::Local<ObjectRef> strObj = nativeValue->ToObject(vm);
44433eb0b6dSopenharmony_ci    for (uint32_t i = 0; i < length; i++) {
44533eb0b6dSopenharmony_ci        panda::Local<StringRef> str = strObj->Get(vm, i)->ToString(vm);
44633eb0b6dSopenharmony_ci        // return value of Utf8Length >= 1
44733eb0b6dSopenharmony_ci        uint32_t len = str->Utf8Length(vm) - 1;
44833eb0b6dSopenharmony_ci        if ((pos + len) >= writableSize) {
44933eb0b6dSopenharmony_ci            char outBuf[writableSize] = {0};
45033eb0b6dSopenharmony_ci            ucnv_convert(encode, encFrom, outBuf, writableSize, tempBuf.c_str(), pos, &errorCode);
45133eb0b6dSopenharmony_ci            if (errorCode != U_ZERO_ERROR) {
45233eb0b6dSopenharmony_ci                HILOG_ERROR("ucnv_convert is failed : ErrorCode = %{public}d", static_cast<int32_t>(errorCode));
45333eb0b6dSopenharmony_ci                return;
45433eb0b6dSopenharmony_ci            }
45533eb0b6dSopenharmony_ci            buffer += outBuf;
45633eb0b6dSopenharmony_ci            tempBuf.clear();
45733eb0b6dSopenharmony_ci            pos = 0;
45833eb0b6dSopenharmony_ci        }
45933eb0b6dSopenharmony_ci        str->WriteUtf8(vm, (tempBuf.data() + pos), pos + len + 1);
46033eb0b6dSopenharmony_ci        pos += len;
46133eb0b6dSopenharmony_ci    }
46233eb0b6dSopenharmony_ci    if (pos > 0) {
46333eb0b6dSopenharmony_ci        char outBuf[writableSize] = {0};
46433eb0b6dSopenharmony_ci        ucnv_convert(encode, encFrom, outBuf, writableSize, tempBuf.c_str(), pos, &errorCode);
46533eb0b6dSopenharmony_ci        if (errorCode != U_ZERO_ERROR) {
46633eb0b6dSopenharmony_ci            HILOG_ERROR("ucnv_convert is failed : ErrorCode = %{public}d", static_cast<int32_t>(errorCode));
46733eb0b6dSopenharmony_ci            return;
46833eb0b6dSopenharmony_ci        }
46933eb0b6dSopenharmony_ci        buffer += outBuf;
47033eb0b6dSopenharmony_ci    }
47133eb0b6dSopenharmony_ci}
47233eb0b6dSopenharmony_ci
47333eb0b6dSopenharmony_civoid NativeEngine::EncodeToChinese(napi_value value, std::string& buffer, const std::string& encoding)
47433eb0b6dSopenharmony_ci{
47533eb0b6dSopenharmony_ci    if (value == nullptr) {
47633eb0b6dSopenharmony_ci        HILOG_ERROR("nativeValue GetInterface is nullptr");
47733eb0b6dSopenharmony_ci        return;
47833eb0b6dSopenharmony_ci    }
47933eb0b6dSopenharmony_ci
48033eb0b6dSopenharmony_ci    auto nativeValue = LocalValueFromJsValue(value);
48133eb0b6dSopenharmony_ci    auto vm = GetEcmaVm();
48233eb0b6dSopenharmony_ci    LocalScope scope(vm);
48333eb0b6dSopenharmony_ci    auto nativeString = nativeValue->ToString(vm);
48433eb0b6dSopenharmony_ci    if (!nativeString->IsString(vm)) {
48533eb0b6dSopenharmony_ci        HILOG_ERROR("nativeValue not is string");
48633eb0b6dSopenharmony_ci        return;
48733eb0b6dSopenharmony_ci    }
48833eb0b6dSopenharmony_ci
48933eb0b6dSopenharmony_ci    auto encode = encoding.c_str();
49033eb0b6dSopenharmony_ci    if (encode == nullptr) {
49133eb0b6dSopenharmony_ci        HILOG_ERROR("encoding is nullptr");
49233eb0b6dSopenharmony_ci        return;
49333eb0b6dSopenharmony_ci    }
49433eb0b6dSopenharmony_ci
49533eb0b6dSopenharmony_ci    SubEncodeToChinese(vm, nativeValue, nativeString, buffer, encode);
49633eb0b6dSopenharmony_ci}
49733eb0b6dSopenharmony_ci
49833eb0b6dSopenharmony_ci#if !defined(PREVIEW)
49933eb0b6dSopenharmony_civoid NativeEngine::CheckUVLoop()
50033eb0b6dSopenharmony_ci{
50133eb0b6dSopenharmony_ci    checkUVLoop_ = true;
50233eb0b6dSopenharmony_ci    uv_thread_create(&uvThread_, NativeEngine::UVThreadRunner, this);
50333eb0b6dSopenharmony_ci}
50433eb0b6dSopenharmony_ci
50533eb0b6dSopenharmony_civoid NativeEngine::UVThreadRunner(void* nativeEngine)
50633eb0b6dSopenharmony_ci{
50733eb0b6dSopenharmony_ci    std::string name("UVLoop");
50833eb0b6dSopenharmony_ci#ifdef IOS_PLATFORM
50933eb0b6dSopenharmony_ci    pthread_setname_np(name.c_str());
51033eb0b6dSopenharmony_ci#else
51133eb0b6dSopenharmony_ci    pthread_setname_np(pthread_self(), name.c_str());
51233eb0b6dSopenharmony_ci#endif
51333eb0b6dSopenharmony_ci    auto engine = static_cast<NativeEngine*>(nativeEngine);
51433eb0b6dSopenharmony_ci    engine->PostLoopTask();
51533eb0b6dSopenharmony_ci    while (engine->checkUVLoop_) {
51633eb0b6dSopenharmony_ci        int32_t fd = uv_backend_fd(engine->loop_);
51733eb0b6dSopenharmony_ci        int32_t timeout = uv_backend_timeout(engine->loop_);
51833eb0b6dSopenharmony_ci        int32_t result = -1;
51933eb0b6dSopenharmony_ci#ifdef IOS_PLATFORM
52033eb0b6dSopenharmony_ci        struct kevent events[1];
52133eb0b6dSopenharmony_ci        struct timespec spec;
52233eb0b6dSopenharmony_ci        static const int32_t mSec = 1000;
52333eb0b6dSopenharmony_ci        static const int32_t uSec = 1000000;
52433eb0b6dSopenharmony_ci        if (timeout != -1) {
52533eb0b6dSopenharmony_ci            spec.tv_sec = timeout / mSec;
52633eb0b6dSopenharmony_ci            spec.tv_nsec = (timeout % mSec) * uSec;
52733eb0b6dSopenharmony_ci        }
52833eb0b6dSopenharmony_ci        result = kevent(fd, NULL, 0, events, 1, timeout == -1 ? NULL : &spec);
52933eb0b6dSopenharmony_ci
53033eb0b6dSopenharmony_ci#else
53133eb0b6dSopenharmony_ci        struct epoll_event ev;
53233eb0b6dSopenharmony_ci        result = epoll_wait(fd, &ev, 1, timeout);
53333eb0b6dSopenharmony_ci#endif
53433eb0b6dSopenharmony_ci
53533eb0b6dSopenharmony_ci        if (!engine->checkUVLoop_) {
53633eb0b6dSopenharmony_ci            HILOG_INFO("break thread after epoll wait");
53733eb0b6dSopenharmony_ci            break;
53833eb0b6dSopenharmony_ci        }
53933eb0b6dSopenharmony_ci        if (result >= 0) {
54033eb0b6dSopenharmony_ci            engine->PostLoopTask();
54133eb0b6dSopenharmony_ci        } else {
54233eb0b6dSopenharmony_ci            HILOG_ERROR("epoll wait fail: result: %{public}d, errno: %{public}d", result, errno);
54333eb0b6dSopenharmony_ci        }
54433eb0b6dSopenharmony_ci        if (!engine->checkUVLoop_) {
54533eb0b6dSopenharmony_ci            HILOG_INFO("break thread after post loop task");
54633eb0b6dSopenharmony_ci            break;
54733eb0b6dSopenharmony_ci        }
54833eb0b6dSopenharmony_ci    }
54933eb0b6dSopenharmony_ci}
55033eb0b6dSopenharmony_ci
55133eb0b6dSopenharmony_civoid NativeEngine::CancelCheckUVLoop()
55233eb0b6dSopenharmony_ci{
55333eb0b6dSopenharmony_ci    checkUVLoop_ = false;
55433eb0b6dSopenharmony_ci    uv_async_send(&uvAsync_);
55533eb0b6dSopenharmony_ci    uv_sem_post(&uvSem_);
55633eb0b6dSopenharmony_ci    uv_thread_join(&uvThread_);
55733eb0b6dSopenharmony_ci}
55833eb0b6dSopenharmony_ci
55933eb0b6dSopenharmony_civoid NativeEngine::PostLoopTask()
56033eb0b6dSopenharmony_ci{
56133eb0b6dSopenharmony_ci    postTask_(true);
56233eb0b6dSopenharmony_ci    uv_sem_wait(&uvSem_);
56333eb0b6dSopenharmony_ci}
56433eb0b6dSopenharmony_ci#endif
56533eb0b6dSopenharmony_ci
56633eb0b6dSopenharmony_civoid NativeEngine::SetPostTask(PostTask postTask)
56733eb0b6dSopenharmony_ci{
56833eb0b6dSopenharmony_ci    postTask_ = postTask;
56933eb0b6dSopenharmony_ci}
57033eb0b6dSopenharmony_ci
57133eb0b6dSopenharmony_civoid NativeEngine::TriggerPostTask()
57233eb0b6dSopenharmony_ci{
57333eb0b6dSopenharmony_ci    if (postTask_ == nullptr) {
57433eb0b6dSopenharmony_ci        HILOG_ERROR("postTask_ is nullptr");
57533eb0b6dSopenharmony_ci        return;
57633eb0b6dSopenharmony_ci    }
57733eb0b6dSopenharmony_ci    postTask_(false);
57833eb0b6dSopenharmony_ci}
57933eb0b6dSopenharmony_ci
58033eb0b6dSopenharmony_civoid* NativeEngine::GetJsEngine()
58133eb0b6dSopenharmony_ci{
58233eb0b6dSopenharmony_ci    return jsEngine_;
58333eb0b6dSopenharmony_ci}
58433eb0b6dSopenharmony_ci
58533eb0b6dSopenharmony_ci// register init worker func
58633eb0b6dSopenharmony_civoid NativeEngine::SetInitWorkerFunc(InitWorkerFunc func)
58733eb0b6dSopenharmony_ci{
58833eb0b6dSopenharmony_ci    initWorkerFunc_ = func;
58933eb0b6dSopenharmony_ci}
59033eb0b6dSopenharmony_ciInitWorkerFunc NativeEngine::GetInitWorkerFunc() const
59133eb0b6dSopenharmony_ci{
59233eb0b6dSopenharmony_ci    return initWorkerFunc_;
59333eb0b6dSopenharmony_ci}
59433eb0b6dSopenharmony_civoid NativeEngine::SetGetAssetFunc(GetAssetFunc func)
59533eb0b6dSopenharmony_ci{
59633eb0b6dSopenharmony_ci    getAssetFunc_ = func;
59733eb0b6dSopenharmony_ci}
59833eb0b6dSopenharmony_ciGetAssetFunc NativeEngine::GetGetAssetFunc() const
59933eb0b6dSopenharmony_ci{
60033eb0b6dSopenharmony_ci    return getAssetFunc_;
60133eb0b6dSopenharmony_ci}
60233eb0b6dSopenharmony_civoid NativeEngine::SetOffWorkerFunc(OffWorkerFunc func)
60333eb0b6dSopenharmony_ci{
60433eb0b6dSopenharmony_ci    offWorkerFunc_ = func;
60533eb0b6dSopenharmony_ci}
60633eb0b6dSopenharmony_ciOffWorkerFunc NativeEngine::GetOffWorkerFunc() const
60733eb0b6dSopenharmony_ci{
60833eb0b6dSopenharmony_ci    return offWorkerFunc_;
60933eb0b6dSopenharmony_ci}
61033eb0b6dSopenharmony_ci
61133eb0b6dSopenharmony_ci// call init worker func
61233eb0b6dSopenharmony_cibool NativeEngine::CallInitWorkerFunc(NativeEngine* engine)
61333eb0b6dSopenharmony_ci{
61433eb0b6dSopenharmony_ci    if (initWorkerFunc_ != nullptr) {
61533eb0b6dSopenharmony_ci        initWorkerFunc_(engine);
61633eb0b6dSopenharmony_ci        return true;
61733eb0b6dSopenharmony_ci    }
61833eb0b6dSopenharmony_ci    return false;
61933eb0b6dSopenharmony_ci}
62033eb0b6dSopenharmony_ci
62133eb0b6dSopenharmony_cibool NativeEngine::CallGetAssetFunc(const std::string& uri, uint8_t** buffer, size_t* bufferSize,
62233eb0b6dSopenharmony_ci    std::vector<uint8_t>& content, std::string& ami, bool &useSecureMem, bool isRestrictedWorker)
62333eb0b6dSopenharmony_ci{
62433eb0b6dSopenharmony_ci    if (getAssetFunc_ != nullptr) {
62533eb0b6dSopenharmony_ci        getAssetFunc_(uri, buffer, bufferSize, content, ami, useSecureMem, isRestrictedWorker);
62633eb0b6dSopenharmony_ci        return true;
62733eb0b6dSopenharmony_ci    }
62833eb0b6dSopenharmony_ci    return false;
62933eb0b6dSopenharmony_ci}
63033eb0b6dSopenharmony_ci
63133eb0b6dSopenharmony_cibool NativeEngine::CallOffWorkerFunc(NativeEngine* engine)
63233eb0b6dSopenharmony_ci{
63333eb0b6dSopenharmony_ci    if (offWorkerFunc_ != nullptr) {
63433eb0b6dSopenharmony_ci        offWorkerFunc_(engine);
63533eb0b6dSopenharmony_ci        return true;
63633eb0b6dSopenharmony_ci    }
63733eb0b6dSopenharmony_ci    return false;
63833eb0b6dSopenharmony_ci}
63933eb0b6dSopenharmony_ci
64033eb0b6dSopenharmony_ci// adapt worker to ace container
64133eb0b6dSopenharmony_civoid NativeEngine::SetGetContainerScopeIdFunc(GetContainerScopeIdCallback func)
64233eb0b6dSopenharmony_ci{
64333eb0b6dSopenharmony_ci    g_getContainerScopeIdFunc = func;
64433eb0b6dSopenharmony_ci}
64533eb0b6dSopenharmony_civoid NativeEngine::SetInitContainerScopeFunc(ContainerScopeCallback func)
64633eb0b6dSopenharmony_ci{
64733eb0b6dSopenharmony_ci    g_initContainerScopeFunc = func;
64833eb0b6dSopenharmony_ci}
64933eb0b6dSopenharmony_civoid NativeEngine::SetFinishContainerScopeFunc(ContainerScopeCallback func)
65033eb0b6dSopenharmony_ci{
65133eb0b6dSopenharmony_ci    g_finishContainerScopeFunc = func;
65233eb0b6dSopenharmony_ci}
65333eb0b6dSopenharmony_ciint32_t NativeEngine::GetContainerScopeIdFunc()
65433eb0b6dSopenharmony_ci{
65533eb0b6dSopenharmony_ci    int32_t scopeId = -1;
65633eb0b6dSopenharmony_ci    if (g_getContainerScopeIdFunc != nullptr) {
65733eb0b6dSopenharmony_ci        scopeId = g_getContainerScopeIdFunc();
65833eb0b6dSopenharmony_ci    }
65933eb0b6dSopenharmony_ci    return scopeId;
66033eb0b6dSopenharmony_ci}
66133eb0b6dSopenharmony_cibool NativeEngine::InitContainerScopeFunc(int32_t id)
66233eb0b6dSopenharmony_ci{
66333eb0b6dSopenharmony_ci    if (g_initContainerScopeFunc != nullptr) {
66433eb0b6dSopenharmony_ci        g_initContainerScopeFunc(id);
66533eb0b6dSopenharmony_ci        return true;
66633eb0b6dSopenharmony_ci    }
66733eb0b6dSopenharmony_ci    return false;
66833eb0b6dSopenharmony_ci}
66933eb0b6dSopenharmony_cibool NativeEngine::FinishContainerScopeFunc(int32_t id)
67033eb0b6dSopenharmony_ci{
67133eb0b6dSopenharmony_ci    if (g_finishContainerScopeFunc != nullptr) {
67233eb0b6dSopenharmony_ci        g_finishContainerScopeFunc(id);
67333eb0b6dSopenharmony_ci        return true;
67433eb0b6dSopenharmony_ci    }
67533eb0b6dSopenharmony_ci    return false;
67633eb0b6dSopenharmony_ci}
67733eb0b6dSopenharmony_ci
67833eb0b6dSopenharmony_ci#if !defined(PREVIEW)
67933eb0b6dSopenharmony_civoid NativeEngine::CallDebuggerPostTaskFunc(std::function<void()>&& task)
68033eb0b6dSopenharmony_ci{
68133eb0b6dSopenharmony_ci    if (debuggerPostTaskFunc_ != nullptr) {
68233eb0b6dSopenharmony_ci        debuggerPostTaskFunc_(std::move(task));
68333eb0b6dSopenharmony_ci    }
68433eb0b6dSopenharmony_ci}
68533eb0b6dSopenharmony_ci
68633eb0b6dSopenharmony_civoid NativeEngine::SetDebuggerPostTaskFunc(DebuggerPostTask func)
68733eb0b6dSopenharmony_ci{
68833eb0b6dSopenharmony_ci    debuggerPostTaskFunc_ = func;
68933eb0b6dSopenharmony_ci}
69033eb0b6dSopenharmony_ci#endif
69133eb0b6dSopenharmony_ci
69233eb0b6dSopenharmony_civoid NativeEngine::SetHostEngine(NativeEngine* engine)
69333eb0b6dSopenharmony_ci{
69433eb0b6dSopenharmony_ci    hostEngine_ = engine;
69533eb0b6dSopenharmony_ci}
69633eb0b6dSopenharmony_ci
69733eb0b6dSopenharmony_ciNativeEngine* NativeEngine::GetHostEngine() const
69833eb0b6dSopenharmony_ci{
69933eb0b6dSopenharmony_ci    return hostEngine_;
70033eb0b6dSopenharmony_ci}
70133eb0b6dSopenharmony_ci
70233eb0b6dSopenharmony_civoid NativeEngine::SetApiVersion(int32_t apiVersion)
70333eb0b6dSopenharmony_ci{
70433eb0b6dSopenharmony_ci    apiVersion_ = apiVersion;
70533eb0b6dSopenharmony_ci}
70633eb0b6dSopenharmony_ci
70733eb0b6dSopenharmony_ciint32_t NativeEngine::GetApiVersion()
70833eb0b6dSopenharmony_ci{
70933eb0b6dSopenharmony_ci    return apiVersion_;
71033eb0b6dSopenharmony_ci}
71133eb0b6dSopenharmony_ci
71233eb0b6dSopenharmony_cibool NativeEngine::IsApplicationApiVersionAPI11Plus()
71333eb0b6dSopenharmony_ci{
71433eb0b6dSopenharmony_ci    return apiVersion_ > API11;
71533eb0b6dSopenharmony_ci}
71633eb0b6dSopenharmony_ci
71733eb0b6dSopenharmony_cinapi_status NativeEngine::AddCleanupHook(CleanupCallback fun, void* arg)
71833eb0b6dSopenharmony_ci{
71933eb0b6dSopenharmony_ci    auto insertion_info = cleanupHooks_.emplace(arg,
72033eb0b6dSopenharmony_ci        std::pair<CleanupCallback, uint64_t>(fun, cleanupHookCounter_++));
72133eb0b6dSopenharmony_ci    if (insertion_info.second != true) {
72233eb0b6dSopenharmony_ci        HILOG_ERROR("AddCleanupHook Failed.");
72333eb0b6dSopenharmony_ci        return napi_generic_failure;
72433eb0b6dSopenharmony_ci    }
72533eb0b6dSopenharmony_ci    return napi_ok;
72633eb0b6dSopenharmony_ci}
72733eb0b6dSopenharmony_ci
72833eb0b6dSopenharmony_cinapi_status NativeEngine::RemoveCleanupHook(CleanupCallback fun, void* arg)
72933eb0b6dSopenharmony_ci{
73033eb0b6dSopenharmony_ci    auto cleanupHook = cleanupHooks_.find(arg);
73133eb0b6dSopenharmony_ci    if (cleanupHook != cleanupHooks_.end() && cleanupHook->second.first == fun) {
73233eb0b6dSopenharmony_ci        cleanupHooks_.erase(arg);
73333eb0b6dSopenharmony_ci        return napi_ok;
73433eb0b6dSopenharmony_ci    }
73533eb0b6dSopenharmony_ci    HILOG_ERROR("RemoveCleanupHook Failed.");
73633eb0b6dSopenharmony_ci    return napi_generic_failure;
73733eb0b6dSopenharmony_ci}
73833eb0b6dSopenharmony_ci
73933eb0b6dSopenharmony_civoid NativeEngine::RunCleanup()
74033eb0b6dSopenharmony_ci{
74133eb0b6dSopenharmony_ci    HILOG_DEBUG("%{public}s, start.", __func__);
74233eb0b6dSopenharmony_ci    CleanupHandles();
74333eb0b6dSopenharmony_ci    // sync clean up
74433eb0b6dSopenharmony_ci    while (!cleanupHooks_.empty()) {
74533eb0b6dSopenharmony_ci        HILOG_DEBUG("NativeEngine::RunCleanup cleanupHooks_ is not empty");
74633eb0b6dSopenharmony_ci        using CleanupCallbackTuple = std::pair<void*, std::pair<CleanupCallback, uint64_t>>;
74733eb0b6dSopenharmony_ci        // Copy into a vector, since we can't sort an unordered_set in-place.
74833eb0b6dSopenharmony_ci        std::vector<CleanupCallbackTuple> callbacks(cleanupHooks_.begin(), cleanupHooks_.end());
74933eb0b6dSopenharmony_ci        // We can't erase the copied elements from `cleanupHooks_` yet, because we
75033eb0b6dSopenharmony_ci        // need to be able to check whether they were un-scheduled by another hook.
75133eb0b6dSopenharmony_ci
75233eb0b6dSopenharmony_ci        std::sort(callbacks.begin(), callbacks.end(), [](const CleanupCallbackTuple& a, const CleanupCallbackTuple& b) {
75333eb0b6dSopenharmony_ci            // Sort in descending order so that the most recently inserted callbacks are run first.
75433eb0b6dSopenharmony_ci            return a.second.second > b.second.second;
75533eb0b6dSopenharmony_ci        });
75633eb0b6dSopenharmony_ci        HILOG_DEBUG(
75733eb0b6dSopenharmony_ci            "NativeEngine::RunCleanup cleanup_hooks callbacks size:%{public}d", (int32_t)callbacks.size());
75833eb0b6dSopenharmony_ci        for (const CleanupCallbackTuple& cb : callbacks) {
75933eb0b6dSopenharmony_ci            void* data = cb.first;
76033eb0b6dSopenharmony_ci            if (cleanupHooks_.find(data) == cleanupHooks_.end()) {
76133eb0b6dSopenharmony_ci                // This hook was removed from the `cleanupHooks_` set during another
76233eb0b6dSopenharmony_ci                // hook that was run earlier. Nothing to do here.
76333eb0b6dSopenharmony_ci                continue;
76433eb0b6dSopenharmony_ci            }
76533eb0b6dSopenharmony_ci            CleanupCallback fun = cb.second.first;
76633eb0b6dSopenharmony_ci            if (fun != nullptr) {
76733eb0b6dSopenharmony_ci                fun(data);
76833eb0b6dSopenharmony_ci            }
76933eb0b6dSopenharmony_ci            cleanupHooks_.erase(data);
77033eb0b6dSopenharmony_ci        }
77133eb0b6dSopenharmony_ci        CleanupHandles();
77233eb0b6dSopenharmony_ci    }
77333eb0b6dSopenharmony_ci
77433eb0b6dSopenharmony_ci    // Close all unclosed uv handles
77533eb0b6dSopenharmony_ci    auto const ensureClosing = [](uv_handle_t *handle, void *arg) {
77633eb0b6dSopenharmony_ci        if (!uv_is_closing(handle)) {
77733eb0b6dSopenharmony_ci            uv_close(handle, nullptr);
77833eb0b6dSopenharmony_ci        }
77933eb0b6dSopenharmony_ci    };
78033eb0b6dSopenharmony_ci    uv_walk(loop_, ensureClosing, nullptr);
78133eb0b6dSopenharmony_ci
78233eb0b6dSopenharmony_ci    while (uv_run(loop_, UV_RUN_DEFAULT) != 0) {};
78333eb0b6dSopenharmony_ci
78433eb0b6dSopenharmony_ci    HILOG_DEBUG("%{public}s, end.", __func__);
78533eb0b6dSopenharmony_ci}
78633eb0b6dSopenharmony_ci
78733eb0b6dSopenharmony_civoid NativeEngine::CleanupHandles()
78833eb0b6dSopenharmony_ci{
78933eb0b6dSopenharmony_ci    while (requestWaiting_.load() > 0) {
79033eb0b6dSopenharmony_ci        HILOG_INFO("%{public}s, request waiting:%{public}d.", __func__,
79133eb0b6dSopenharmony_ci            requestWaiting_.load(std::memory_order_relaxed));
79233eb0b6dSopenharmony_ci        uv_run(loop_, UV_RUN_ONCE);
79333eb0b6dSopenharmony_ci    }
79433eb0b6dSopenharmony_ci}
79533eb0b6dSopenharmony_ci
79633eb0b6dSopenharmony_civoid NativeEngine::IncreaseWaitingRequestCounter()
79733eb0b6dSopenharmony_ci{
79833eb0b6dSopenharmony_ci    requestWaiting_++;
79933eb0b6dSopenharmony_ci}
80033eb0b6dSopenharmony_ci
80133eb0b6dSopenharmony_civoid NativeEngine::DecreaseWaitingRequestCounter()
80233eb0b6dSopenharmony_ci{
80333eb0b6dSopenharmony_ci    requestWaiting_--;
80433eb0b6dSopenharmony_ci}
80533eb0b6dSopenharmony_ci
80633eb0b6dSopenharmony_cibool NativeEngine::HasWaitingRequest()
80733eb0b6dSopenharmony_ci{
80833eb0b6dSopenharmony_ci    return requestWaiting_.load() != 0;
80933eb0b6dSopenharmony_ci}
81033eb0b6dSopenharmony_ci
81133eb0b6dSopenharmony_civoid NativeEngine::IncreaseListeningCounter()
81233eb0b6dSopenharmony_ci{
81333eb0b6dSopenharmony_ci    listeningCounter_++;
81433eb0b6dSopenharmony_ci}
81533eb0b6dSopenharmony_ci
81633eb0b6dSopenharmony_civoid NativeEngine::DecreaseListeningCounter()
81733eb0b6dSopenharmony_ci{
81833eb0b6dSopenharmony_ci    listeningCounter_--;
81933eb0b6dSopenharmony_ci}
82033eb0b6dSopenharmony_ci
82133eb0b6dSopenharmony_cibool NativeEngine::HasListeningCounter()
82233eb0b6dSopenharmony_ci{
82333eb0b6dSopenharmony_ci    return listeningCounter_.load() != 0;
82433eb0b6dSopenharmony_ci}
82533eb0b6dSopenharmony_ci
82633eb0b6dSopenharmony_civoid NativeEngine::RegisterWorkerFunction(const NativeEngine* engine)
82733eb0b6dSopenharmony_ci{
82833eb0b6dSopenharmony_ci    if (engine == nullptr) {
82933eb0b6dSopenharmony_ci        return;
83033eb0b6dSopenharmony_ci    }
83133eb0b6dSopenharmony_ci    SetInitWorkerFunc(engine->GetInitWorkerFunc());
83233eb0b6dSopenharmony_ci    SetGetAssetFunc(engine->GetGetAssetFunc());
83333eb0b6dSopenharmony_ci    SetOffWorkerFunc(engine->GetOffWorkerFunc());
83433eb0b6dSopenharmony_ci}
83533eb0b6dSopenharmony_ci
83633eb0b6dSopenharmony_ci// this interface for restrictedWorker with entryPoint to execute mergeabc
83733eb0b6dSopenharmony_cinapi_value NativeEngine::RunScriptForAbc(const char* path, char* entryPoint)
83833eb0b6dSopenharmony_ci{
83933eb0b6dSopenharmony_ci    EcmaVM* vm = const_cast<EcmaVM*>(GetEcmaVm());
84033eb0b6dSopenharmony_ci    panda::EscapeLocalScope scope(vm);
84133eb0b6dSopenharmony_ci    std::string normalizedPath = panda::JSNApi::NormalizePath(path);
84233eb0b6dSopenharmony_ci    uint8_t* scriptContent = nullptr;
84333eb0b6dSopenharmony_ci    size_t scriptContentSize = 0;
84433eb0b6dSopenharmony_ci    std::vector<uint8_t> content;
84533eb0b6dSopenharmony_ci    std::string ami;
84633eb0b6dSopenharmony_ci    if (!GetAbcBuffer(normalizedPath.c_str(), &scriptContent, &scriptContentSize,
84733eb0b6dSopenharmony_ci        content, ami, true)) {
84833eb0b6dSopenharmony_ci        HILOG_ERROR("RunScript: GetAbcBuffer failed");
84933eb0b6dSopenharmony_ci        return nullptr;
85033eb0b6dSopenharmony_ci    }
85133eb0b6dSopenharmony_ci    HILOG_DEBUG("RunScriptForAbc: GetAmi: %{private}s", ami.c_str());
85233eb0b6dSopenharmony_ci    // if buffer is empty, return directly.
85333eb0b6dSopenharmony_ci    if (scriptContentSize == 0) {
85433eb0b6dSopenharmony_ci        HILOG_ERROR("asset size is %{public}zu", scriptContentSize);
85533eb0b6dSopenharmony_ci        ThrowException("RunScriptForAbc: abc file is empty.");
85633eb0b6dSopenharmony_ci        return nullptr;
85733eb0b6dSopenharmony_ci    }
85833eb0b6dSopenharmony_ci    panda::JSNApi::Execute(vm, ami, entryPoint, false, true);
85933eb0b6dSopenharmony_ci    if (panda::JSNApi::HasPendingException(vm)) {
86033eb0b6dSopenharmony_ci        HandleUncaughtException();
86133eb0b6dSopenharmony_ci        return nullptr;
86233eb0b6dSopenharmony_ci    }
86333eb0b6dSopenharmony_ci    Local<JSValueRef> undefObj = JSValueRef::Undefined(vm);
86433eb0b6dSopenharmony_ci    return JsValueFromLocalValue(scope.Escape(undefObj));
86533eb0b6dSopenharmony_ci}
86633eb0b6dSopenharmony_ci
86733eb0b6dSopenharmony_cinapi_value NativeEngine::RunScript(const char* path, char* entryPoint)
86833eb0b6dSopenharmony_ci{
86933eb0b6dSopenharmony_ci    uint8_t* scriptContent = nullptr;
87033eb0b6dSopenharmony_ci    size_t scriptContentSize = 0;
87133eb0b6dSopenharmony_ci    std::vector<uint8_t> content;
87233eb0b6dSopenharmony_ci    std::string ami;
87333eb0b6dSopenharmony_ci    if (!GetAbcBuffer(path, &scriptContent, &scriptContentSize, content, ami)) {
87433eb0b6dSopenharmony_ci        HILOG_ERROR("RunScript: GetAbcBuffer failed");
87533eb0b6dSopenharmony_ci        return nullptr;
87633eb0b6dSopenharmony_ci    }
87733eb0b6dSopenharmony_ci    HILOG_DEBUG("RunScript: GetAmi: %{private}s", ami.c_str());
87833eb0b6dSopenharmony_ci    // if buffer is empty, return directly.
87933eb0b6dSopenharmony_ci    if (scriptContentSize == 0) {
88033eb0b6dSopenharmony_ci        HILOG_ERROR("RunScript: buffer size is empty, please check abc path");
88133eb0b6dSopenharmony_ci        return nullptr;
88233eb0b6dSopenharmony_ci    }
88333eb0b6dSopenharmony_ci    return RunActor(scriptContent, scriptContentSize, ami.c_str(), entryPoint, false);
88433eb0b6dSopenharmony_ci}
88533eb0b6dSopenharmony_ci
88633eb0b6dSopenharmony_cinapi_value NativeEngine::RunScriptInRestrictedThread(const char* path)
88733eb0b6dSopenharmony_ci{
88833eb0b6dSopenharmony_ci    auto vm = GetEcmaVm();
88933eb0b6dSopenharmony_ci    panda::EscapeLocalScope scope(vm);
89033eb0b6dSopenharmony_ci    uint8_t* scriptContent = nullptr;
89133eb0b6dSopenharmony_ci    size_t scriptContentSize = 0;
89233eb0b6dSopenharmony_ci    std::vector<uint8_t> content;
89333eb0b6dSopenharmony_ci    std::string ami;
89433eb0b6dSopenharmony_ci    if (!GetAbcBuffer(path, &scriptContent, &scriptContentSize, content, ami, true)) {
89533eb0b6dSopenharmony_ci        HILOG_ERROR("RunScriptInRestrictedThread: GetAbcBuffer failed");
89633eb0b6dSopenharmony_ci        return nullptr;
89733eb0b6dSopenharmony_ci    }
89833eb0b6dSopenharmony_ci    HILOG_DEBUG("RunScriptInRestrictedThread: GetAmi: %{private}s", ami.c_str());
89933eb0b6dSopenharmony_ci    panda::JSNApi::Execute(vm, ami, PANDA_MAIN_FUNCTION, false, true);
90033eb0b6dSopenharmony_ci    if (panda::JSNApi::HasPendingException(vm)) {
90133eb0b6dSopenharmony_ci        HandleUncaughtException();
90233eb0b6dSopenharmony_ci        return nullptr;
90333eb0b6dSopenharmony_ci    }
90433eb0b6dSopenharmony_ci    Local<JSValueRef> undefObj = JSValueRef::Undefined(vm);
90533eb0b6dSopenharmony_ci    return JsValueFromLocalValue(scope.Escape(undefObj));
90633eb0b6dSopenharmony_ci}
90733eb0b6dSopenharmony_ci
90833eb0b6dSopenharmony_ci/* buffer, bufferSize is for secureMem; content is for normalMem.
90933eb0b6dSopenharmony_ci * If output is not secureMem, fullfill buffer, bufferSize with content data and size.
91033eb0b6dSopenharmony_ci */
91133eb0b6dSopenharmony_cibool NativeEngine::GetAbcBuffer(const char* path, uint8_t **buffer, size_t* bufferSize,
91233eb0b6dSopenharmony_ci    std::vector<uint8_t>& content, std::string& ami, bool isRestrictedWorker)
91333eb0b6dSopenharmony_ci{
91433eb0b6dSopenharmony_ci    std::string pathStr(path);
91533eb0b6dSopenharmony_ci    bool useSecureMem = false;
91633eb0b6dSopenharmony_ci    if (!CallGetAssetFunc(pathStr, buffer, bufferSize, content, ami, useSecureMem, isRestrictedWorker)) {
91733eb0b6dSopenharmony_ci        HILOG_ERROR("Get asset error");
91833eb0b6dSopenharmony_ci        return false;
91933eb0b6dSopenharmony_ci    }
92033eb0b6dSopenharmony_ci    if (!useSecureMem) {
92133eb0b6dSopenharmony_ci        *buffer = content.data();
92233eb0b6dSopenharmony_ci        *bufferSize = content.size();
92333eb0b6dSopenharmony_ci    }
92433eb0b6dSopenharmony_ci    return true;
92533eb0b6dSopenharmony_ci}
92633eb0b6dSopenharmony_ci
92733eb0b6dSopenharmony_civoid NativeEngine::SetInstanceData(void* data, NativeFinalize finalize_cb, void* hint)
92833eb0b6dSopenharmony_ci{
92933eb0b6dSopenharmony_ci    HILOG_DEBUG("NativeEngineWraper::%{public}s, start.", __func__);
93033eb0b6dSopenharmony_ci    std::lock_guard<std::mutex> insLock(instanceDataLock_);
93133eb0b6dSopenharmony_ci    FinalizerInstanceData();
93233eb0b6dSopenharmony_ci    instanceDataInfo_.engine = this;
93333eb0b6dSopenharmony_ci    instanceDataInfo_.callback = finalize_cb;
93433eb0b6dSopenharmony_ci    instanceDataInfo_.nativeObject = data;
93533eb0b6dSopenharmony_ci    instanceDataInfo_.hint = hint;
93633eb0b6dSopenharmony_ci}
93733eb0b6dSopenharmony_ci
93833eb0b6dSopenharmony_civoid NativeEngine::GetInstanceData(void** data)
93933eb0b6dSopenharmony_ci{
94033eb0b6dSopenharmony_ci    HILOG_DEBUG("NativeEngineWraper::%{public}s, start.", __func__);
94133eb0b6dSopenharmony_ci    std::lock_guard<std::mutex> insLock(instanceDataLock_);
94233eb0b6dSopenharmony_ci    if (data) {
94333eb0b6dSopenharmony_ci        *data = instanceDataInfo_.nativeObject;
94433eb0b6dSopenharmony_ci    }
94533eb0b6dSopenharmony_ci}
94633eb0b6dSopenharmony_ci
94733eb0b6dSopenharmony_civoid NativeEngine::FinalizerInstanceData(void)
94833eb0b6dSopenharmony_ci{
94933eb0b6dSopenharmony_ci    if (instanceDataInfo_.engine != nullptr && instanceDataInfo_.callback != nullptr) {
95033eb0b6dSopenharmony_ci        instanceDataInfo_.callback(instanceDataInfo_.engine, instanceDataInfo_.nativeObject, instanceDataInfo_.hint);
95133eb0b6dSopenharmony_ci    }
95233eb0b6dSopenharmony_ci    instanceDataInfo_.engine = nullptr;
95333eb0b6dSopenharmony_ci    instanceDataInfo_.callback = nullptr;
95433eb0b6dSopenharmony_ci    instanceDataInfo_.nativeObject = nullptr;
95533eb0b6dSopenharmony_ci    instanceDataInfo_.hint = nullptr;
95633eb0b6dSopenharmony_ci}
95733eb0b6dSopenharmony_ci
95833eb0b6dSopenharmony_ciconst char* NativeEngine::GetModuleFileName()
95933eb0b6dSopenharmony_ci{
96033eb0b6dSopenharmony_ci    HILOG_DEBUG("%{public}s, start.", __func__);
96133eb0b6dSopenharmony_ci    if (moduleFileName_.empty()) {
96233eb0b6dSopenharmony_ci        NativeModuleManager* moduleManager = GetModuleManager();
96333eb0b6dSopenharmony_ci        HILOG_DEBUG("NativeEngineWraper::GetFileName GetModuleManager");
96433eb0b6dSopenharmony_ci        if (moduleManager != nullptr) {
96533eb0b6dSopenharmony_ci            std::string moduleFileName = moduleManager->GetModuleFileName(moduleName_.c_str(), isAppModule_);
96633eb0b6dSopenharmony_ci            HILOG_INFO("NativeEngineWraper::GetFileName end filename:%{public}s", moduleFileName.c_str());
96733eb0b6dSopenharmony_ci            SetModuleFileName(moduleFileName);
96833eb0b6dSopenharmony_ci        }
96933eb0b6dSopenharmony_ci    }
97033eb0b6dSopenharmony_ci    return moduleFileName_.c_str();
97133eb0b6dSopenharmony_ci}
97233eb0b6dSopenharmony_ci
97333eb0b6dSopenharmony_civoid NativeEngine::SetModuleName(std::string& moduleName)
97433eb0b6dSopenharmony_ci{
97533eb0b6dSopenharmony_ci    moduleName_ = moduleName;
97633eb0b6dSopenharmony_ci}
97733eb0b6dSopenharmony_ci
97833eb0b6dSopenharmony_civoid NativeEngine::SetModuleFileName(std::string& moduleFileName)
97933eb0b6dSopenharmony_ci{
98033eb0b6dSopenharmony_ci    moduleFileName_ = moduleFileName;
98133eb0b6dSopenharmony_ci}
98233eb0b6dSopenharmony_ci
98333eb0b6dSopenharmony_civoid NativeEngine::SetExtensionInfos(std::unordered_map<std::string, int32_t>&& extensionInfos)
98433eb0b6dSopenharmony_ci{
98533eb0b6dSopenharmony_ci    extensionInfos_ = extensionInfos;
98633eb0b6dSopenharmony_ci}
98733eb0b6dSopenharmony_ci
98833eb0b6dSopenharmony_ciconst std::unordered_map<std::string, int32_t>& NativeEngine::GetExtensionInfos()
98933eb0b6dSopenharmony_ci{
99033eb0b6dSopenharmony_ci    return extensionInfos_;
99133eb0b6dSopenharmony_ci}
99233eb0b6dSopenharmony_ci
99333eb0b6dSopenharmony_civoid NativeEngine::SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate>& moduleCheckerDelegate)
99433eb0b6dSopenharmony_ci{
99533eb0b6dSopenharmony_ci    NativeModuleManager* moduleManager = GetModuleManager();
99633eb0b6dSopenharmony_ci    if (!moduleManager) {
99733eb0b6dSopenharmony_ci        HILOG_ERROR("SetModuleLoadChecker failed, moduleManager is nullptr");
99833eb0b6dSopenharmony_ci        return;
99933eb0b6dSopenharmony_ci    }
100033eb0b6dSopenharmony_ci    moduleManager->SetModuleLoadChecker(moduleCheckerDelegate);
100133eb0b6dSopenharmony_ci}
100233eb0b6dSopenharmony_ci
100333eb0b6dSopenharmony_cinapi_status NativeEngine::RunEventLoop(napi_event_mode mode)
100433eb0b6dSopenharmony_ci{
100533eb0b6dSopenharmony_ci    HILOG_DEBUG("%{public}s, start.", __func__);
100633eb0b6dSopenharmony_ci    if (loop_ == nullptr) {
100733eb0b6dSopenharmony_ci        HILOG_ERROR("nullptr loop in native engine");
100833eb0b6dSopenharmony_ci        return napi_status::napi_invalid_arg;
100933eb0b6dSopenharmony_ci    }
101033eb0b6dSopenharmony_ci
101133eb0b6dSopenharmony_ci    if (!IsNativeThread()) {
101233eb0b6dSopenharmony_ci        HILOG_ERROR("current thread is not native thread");
101333eb0b6dSopenharmony_ci        return napi_status::napi_generic_failure;
101433eb0b6dSopenharmony_ci    }
101533eb0b6dSopenharmony_ci
101633eb0b6dSopenharmony_ci    std::unique_lock<std::mutex> lock(loopRunningMutex_);
101733eb0b6dSopenharmony_ci    if (isLoopRunning_) {
101833eb0b6dSopenharmony_ci        HILOG_DEBUG("loop is already undered running state");
101933eb0b6dSopenharmony_ci        return napi_status::napi_ok;
102033eb0b6dSopenharmony_ci    }
102133eb0b6dSopenharmony_ci    isLoopRunning_ = true;
102233eb0b6dSopenharmony_ci    lock.unlock();
102333eb0b6dSopenharmony_ci    HILOG_DEBUG("uv loop is running with mode %{public}d", mode);
102433eb0b6dSopenharmony_ci    if (mode == napi_event_mode_default) {
102533eb0b6dSopenharmony_ci        uv_run(loop_, UV_RUN_DEFAULT);
102633eb0b6dSopenharmony_ci    }
102733eb0b6dSopenharmony_ci    if (mode == napi_event_mode_nowait) {
102833eb0b6dSopenharmony_ci        uv_run(loop_, UV_RUN_NOWAIT);
102933eb0b6dSopenharmony_ci    }
103033eb0b6dSopenharmony_ci    HILOG_DEBUG("uv loop is stopped");
103133eb0b6dSopenharmony_ci    lock.lock();
103233eb0b6dSopenharmony_ci    isLoopRunning_ = false;
103333eb0b6dSopenharmony_ci    return napi_status::napi_ok;
103433eb0b6dSopenharmony_ci}
103533eb0b6dSopenharmony_ci
103633eb0b6dSopenharmony_cinapi_status NativeEngine::StopEventLoop()
103733eb0b6dSopenharmony_ci{
103833eb0b6dSopenharmony_ci    HILOG_DEBUG("%{public}s, start.", __func__);
103933eb0b6dSopenharmony_ci    if (loop_ == nullptr) {
104033eb0b6dSopenharmony_ci        HILOG_ERROR("nullptr loop in native engine");
104133eb0b6dSopenharmony_ci        return napi_status::napi_invalid_arg;
104233eb0b6dSopenharmony_ci    }
104333eb0b6dSopenharmony_ci
104433eb0b6dSopenharmony_ci    if (!IsNativeThread()) {
104533eb0b6dSopenharmony_ci        HILOG_ERROR("current thread is not native thread");
104633eb0b6dSopenharmony_ci        return napi_status::napi_generic_failure;
104733eb0b6dSopenharmony_ci    }
104833eb0b6dSopenharmony_ci    std::unique_lock<std::mutex> lock(loopRunningMutex_);
104933eb0b6dSopenharmony_ci    if (!isLoopRunning_) {
105033eb0b6dSopenharmony_ci        HILOG_DEBUG("loop is already undered stop state");
105133eb0b6dSopenharmony_ci        return napi_status::napi_ok;
105233eb0b6dSopenharmony_ci    }
105333eb0b6dSopenharmony_ci    HILOG_DEBUG("uv loop is running");
105433eb0b6dSopenharmony_ci    uv_stop(loop_);
105533eb0b6dSopenharmony_ci    HILOG_DEBUG("uv loop is stopped");
105633eb0b6dSopenharmony_ci    return napi_status::napi_ok;
105733eb0b6dSopenharmony_ci}
105833eb0b6dSopenharmony_ci
105933eb0b6dSopenharmony_civoid NativeEngine::ThrowException(const char* msg)
106033eb0b6dSopenharmony_ci{
106133eb0b6dSopenharmony_ci    auto vm = GetEcmaVm();
106233eb0b6dSopenharmony_ci    Local<panda::JSValueRef> error = panda::Exception::Error(vm, StringRef::NewFromUtf8(vm, msg));
106333eb0b6dSopenharmony_ci    panda::JSNApi::ThrowException(vm, error);
106433eb0b6dSopenharmony_ci}
106533eb0b6dSopenharmony_ci
106633eb0b6dSopenharmony_cinapi_status NativeEngine::SendEvent(const std::function<void()> &cb, napi_event_priority priority)
106733eb0b6dSopenharmony_ci{
106833eb0b6dSopenharmony_ci    std::shared_lock<std::shared_mutex> readLock(eventMutex_);
106933eb0b6dSopenharmony_ci    if (defaultFunc_) {
107033eb0b6dSopenharmony_ci        auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(defaultFunc_);
107133eb0b6dSopenharmony_ci        return safeAsyncWork->SendEvent(cb, priority);
107233eb0b6dSopenharmony_ci    } else {
107333eb0b6dSopenharmony_ci        HILOG_ERROR("default function is nullptr!");
107433eb0b6dSopenharmony_ci        return napi_status::napi_generic_failure;
107533eb0b6dSopenharmony_ci    }
107633eb0b6dSopenharmony_ci}
1077