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