diff --git a/interfaces/kits/napi/native_api.h b/interfaces/kits/napi/native_api.h
index d1c720cdb4879d08569ad59954f3bc079f52cd1e..ee4dea417fa0e84c0d78d3e76eadee2d4e10333e 100644
--- a/interfaces/kits/napi/native_api.h
+++ b/interfaces/kits/napi/native_api.h
@@ -27,5 +27,11 @@ DEPRECATED napi_status napi_get_value_string_utf16(napi_env env,
size_t bufsize,
size_t* result);
DEPRECATED napi_status napi_adjust_external_memory(napi_env env, int64_t change_in_bytes, int64_t* adjusted_value);
+napi_status napi_is_callable(napi_env env, napi_value value, bool* result);
+ napi_status napi_create_runtime(napi_env env, napi_env* result_env);
+ napi_status napi_serialize(napi_env env, napi_value object, napi_value transfer_list, napi_value* result);
+ napi_status napi_deserialize(napi_env env, napi_value recorder, napi_value* object);
+ napi_status napi_delete_serialization_data(napi_env env, napi_value value);
+ napi_status napi_get_exception_info_for_worker(napi_env env, napi_value obj);
#endif /* FOUNDATION_ACE_NAPI_INTERFACES_KITS_NAPI_NATIVE_API_H */
diff --git a/interfaces/kits/napi/native_common.h b/interfaces/kits/napi/native_common.h
index efba395e0f3f82787f749f98414ec089d3cea0a7..5fabf4e9f9c844b8cd54113d2293eff3a66cdf34 100644
--- a/interfaces/kits/napi/native_common.h
+++ b/interfaces/kits/napi/native_common.h
@@ -74,6 +74,11 @@
(name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, nullptr \
}
+#define DECLARE_NAPI_FUNCTION_WITH_DATA(name, func, data) \
+ { \
+ (name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, data \
+ }
+
#define DECLARE_NAPI_STATIC_FUNCTION(name, func) \
{ \
(name), nullptr, (func), nullptr, nullptr, nullptr, napi_static, nullptr \
diff --git a/module_manager/native_module_manager.cpp b/module_manager/native_module_manager.cpp
index 4445aa45e6ad37bf99b2a5ff0fb0f92edb409fd6..b7317d1638c5f927c5718bef0cdab44fc75ae8b3 100644
--- a/module_manager/native_module_manager.cpp
+++ b/module_manager/native_module_manager.cpp
@@ -74,7 +74,7 @@ void NativeModuleManager::Register(NativeModule* nativeModule)
lastNativeModule_->next = nullptr;
}
-NativeModule* NativeModuleManager::LoadNativeModule(const char* moduleName, bool internal)
+NativeModule* NativeModuleManager::LoadNativeModule(const char* moduleName, const char* path, bool internal)
{
if (moduleName == nullptr) {
HILOG_ERROR("moduleName value is null");
@@ -89,7 +89,7 @@ NativeModule* NativeModuleManager::LoadNativeModule(const char* moduleName, bool
NativeModule* nativeModule = FindNativeModuleByCache(moduleName);
if (nativeModule == nullptr) {
HILOG_INFO("not in cache: moduleName: %{public}s", moduleName);
- nativeModule = FindNativeModuleByDisk(moduleName, internal);
+ nativeModule = FindNativeModuleByDisk(moduleName, internal, path);
}
if (pthread_mutex_unlock(&mutex_) != 0) {
@@ -100,15 +100,21 @@ NativeModule* NativeModuleManager::LoadNativeModule(const char* moduleName, bool
return nativeModule;
}
-bool NativeModuleManager::GetNativeModulePath(const char* moduleName, char* nativeModulePath, int32_t pathLength)
+bool NativeModuleManager::GetNativeModulePath(
+ const char* moduleName, const char* path, char* nativeModulePath, int32_t pathLength) const
{
const char* soPostfix = ".so";
#ifdef _ARM64_
- const char* prefix = "/system/lib64/module";
+ const char* sysPrefix = "/system/lib64/module";
#else
- const char* prefix = "/system/lib/module";
+ const char* sysPrefix = "/system/lib/module";
#endif
-
+ const char* prefix = nullptr;
+ if (path) {
+ prefix = path;
+ } else {
+ prefix = sysPrefix;
+ }
int32_t lengthOfModuleName = strlen(moduleName);
char dupModuleName[PATH_MAX] = { 0 };
if (strcpy_s(dupModuleName, PATH_MAX, moduleName) != 0) {
@@ -154,10 +160,10 @@ bool NativeModuleManager::GetNativeModulePath(const char* moduleName, char* nati
}
using NAPIGetJSCode = void (*)(const char** buf, int* bufLen);
-NativeModule* NativeModuleManager::FindNativeModuleByDisk(const char* moduleName, bool internal)
+NativeModule* NativeModuleManager::FindNativeModuleByDisk(const char* moduleName, bool internal, const char* path)
{
char nativeModulePath[PATH_MAX] = { 0 };
- if (!GetNativeModulePath(moduleName, nativeModulePath, sizeof(nativeModulePath))) {
+ if (!GetNativeModulePath(moduleName, path, nativeModulePath, sizeof(nativeModulePath))) {
HILOG_ERROR("get module filed");
return nullptr;
}
@@ -195,7 +201,7 @@ NativeModule* NativeModuleManager::FindNativeModuleByDisk(const char* moduleName
return lastNativeModule_;
}
-NativeModule* NativeModuleManager::FindNativeModuleByCache(const char* moduleName)
+NativeModule* NativeModuleManager::FindNativeModuleByCache(const char* moduleName) const
{
NativeModule* result = nullptr;
for (NativeModule* temp = firstNativeModule_; temp != nullptr; temp = temp->next) {
diff --git a/module_manager/native_module_manager.h b/module_manager/native_module_manager.h
index 34b8da5117715bcc12aec6519af9114db713e231..3d24196fec059669886ed01a13e09c2e478c9a2e 100644
--- a/module_manager/native_module_manager.h
+++ b/module_manager/native_module_manager.h
@@ -41,16 +41,17 @@ public:
static NativeModuleManager* GetInstance();
static unsigned long Release();
- virtual void Register(NativeModule* nativeModule);
- virtual NativeModule* LoadNativeModule(const char* moduleName, bool internal = false);
+ void Register(NativeModule* nativeModule);
+ NativeModule* LoadNativeModule(const char* moduleName, const char* path, bool internal = false);
private:
NativeModuleManager();
virtual ~NativeModuleManager();
- bool GetNativeModulePath(const char* moduleName, char* nativeModulePath, int32_t pathLength);
- virtual NativeModule* FindNativeModuleByDisk(const char* moduleName, bool internal);
- virtual NativeModule* FindNativeModuleByCache(const char* moduleName);
+ bool GetNativeModulePath(
+ const char* moduleName, const char* path, char* nativeModulePath, int32_t pathLength) const;
+ NativeModule* FindNativeModuleByDisk(const char* moduleName, bool internal, const char* path);
+ NativeModule* FindNativeModuleByCache(const char* moduleName) const;
NativeModule* firstNativeModule_;
NativeModule* lastNativeModule_;
diff --git a/native_engine/impl/quickjs/quickjs_ext.cpp b/native_engine/impl/quickjs/quickjs_ext.cpp
index e3f703481c899f4dc57431fd5aea97da9a26d898..c01abfb4143f1d886521ea13437db7582ee4e761 100644
--- a/native_engine/impl/quickjs/quickjs_ext.cpp
+++ b/native_engine/impl/quickjs/quickjs_ext.cpp
@@ -26,7 +26,7 @@ struct JSObjectInfo {
void* hint = nullptr;
};
-JSClassID g_baseClassId = 0;
+JSClassID g_baseClassId = 1;
void AddIntrinsicExternal(JSContext* context)
{
diff --git a/native_engine/impl/quickjs/quickjs_native_engine.cpp b/native_engine/impl/quickjs/quickjs_native_engine.cpp
index 753599786af981b01fd4601f657f83c48011c91d..2f243cf96b8827586f686d426c0648b8d019f7cb 100644
--- a/native_engine/impl/quickjs/quickjs_native_engine.cpp
+++ b/native_engine/impl/quickjs/quickjs_native_engine.cpp
@@ -29,9 +29,14 @@
#include "native_value/quickjs_native_typed_array.h"
#include "quickjs_native_deferred.h"
#include "quickjs_native_reference.h"
+#include "securec.h"
+#include "utils/assert.h"
#include "utils/log.h"
+const int JS_WRITE_OBJ = (1 << 2) | (1 << 3);
+const int JS_ATOM_MESSAGE = 51;
+
QuickJSNativeEngine::QuickJSNativeEngine(JSRuntime* runtime, JSContext* context)
{
runtime_ = runtime;
@@ -58,7 +63,7 @@ QuickJSNativeEngine::QuickJSNativeEngine(JSRuntime* runtime, JSContext* context)
}
NativeModuleManager* moduleManager = that->GetModuleManager();
- NativeModule* module = moduleManager->LoadNativeModule(moduleName, true);
+ NativeModule* module = moduleManager->LoadNativeModule(moduleName, nullptr, true);
if (module != nullptr && module->registerCallback != nullptr) {
NativeValue* value = new QuickJSNativeObject(that);
@@ -79,16 +84,18 @@ QuickJSNativeEngine::QuickJSNativeEngine(JSRuntime* runtime, JSContext* context)
JSValue result = JS_UNDEFINED;
QuickJSNativeEngine* that = (QuickJSNativeEngine*)JS_VALUE_GET_PTR(funcData[0]);
-
const char* moduleName = JS_ToCString(that->GetContext(), argv[0]);
-
if (moduleName == nullptr || strlen(moduleName) == 0) {
HILOG_ERROR("moduleName is nullptr or length is 0");
return result;
}
+ const char* path = nullptr;
+ if (argc == 2) {
+ path = JS_ToCString(that->GetContext(), argv[1]);
+ }
NativeModuleManager* moduleManager = that->GetModuleManager();
- NativeModule* module = moduleManager->LoadNativeModule(moduleName);
+ NativeModule* module = moduleManager->LoadNativeModule(moduleName, nullptr);
if (module != nullptr) {
if (module->jsCode != nullptr) {
@@ -330,6 +337,10 @@ NativeValue* QuickJSNativeEngine::CallFunction(NativeValue* thisVar,
scopeManager_->Close(scope);
+ if (JS_IsError(context_, result) || JS_IsException(result)) {
+ return nullptr;
+ }
+
return JSValueToNativeValue(this, result);
}
@@ -339,6 +350,9 @@ NativeValue* QuickJSNativeEngine::RunScript(NativeValue* script)
const char* cScript = JS_ToCString(context_, *script);
result = JS_Eval(context_, cScript, strlen(cScript), "", JS_EVAL_TYPE_GLOBAL);
JS_FreeCString(context_, cScript);
+ if (JS_IsError(context_, result) || JS_IsException(result)) {
+ return nullptr;
+ }
return JSValueToNativeValue(this, result);
}
@@ -357,14 +371,14 @@ NativeValue* QuickJSNativeEngine::LoadModule(NativeValue* str, const std::string
JSValue moduleVal = JS_Eval(context_, moduleSource, len, fileName.c_str(), flags);
if (JS_IsException(moduleVal)) {
HILOG_ERROR("Eval source code exception");
- JS_FreeCString(context_, moduleSource);
+ JS_FreeCString(context_, moduleSource);
return nullptr;
}
JSValue evalRes = JS_EvalFunction(context_, moduleVal);
if (JS_IsException(evalRes)) {
HILOG_ERROR("Eval module exception");
- JS_FreeCString(context_, moduleSource);
+ JS_FreeCString(context_, moduleSource);
return nullptr;
}
@@ -564,3 +578,116 @@ NativeValue* QuickJSNativeEngine::JSValueToNativeValue(QuickJSNativeEngine* engi
}
return result;
}
+
+ void* QuickJSNativeEngine::CreateRuntime()
+ {
+ JSRuntime* runtime = JS_NewRuntime();
+ JSContext* context = JS_NewContext(runtime);
+ return reinterpret_cast(new QuickJSNativeEngine(runtime, context));
+}
+
+bool QuickJSNativeEngine::CheckTransferList(JSValue transferList)
+{
+ if (JS_IsUndefined(transferList)) {
+ return true;
+ }
+ if (!JS_IsArray(context_, transferList)) {
+ JS_ThrowTypeError(context_, "postMessage second parameter not a list or undefined");
+ return false;
+ }
+ int64_t len = 0;
+ js_get_length64(context_, &len, transferList);
+ for (int64_t i = 0; i < len; i++) {
+ JSValue tmp = JS_GetPropertyInt64(context_, transferList, i);
+ if (!JS_IsException(tmp)) {
+ if (!JS_IsArrayBuffer(context_, tmp)) {
+ HILOG_ERROR("JS_ISArrayBuffer fail");
+ return false;
+ }
+ } else {
+ HILOG_ERROR("JS_GetPropertyInt64 fail");
+ return false;
+ }
+ }
+ return true;
+}
+
+bool QuickJSNativeEngine::DetachTransferList(JSValue transferList)
+{
+ if (JS_IsUndefined(transferList)) {
+ return true;
+ }
+ int64_t len = 0;
+ js_get_length64(context_, &len, transferList);
+ for (int64_t i = 0; i < len; i++) {
+ JSValue tmp = JS_GetPropertyInt64(context_, transferList, i);
+ if (!JS_IsException(tmp)) {
+ JS_DetachArrayBuffer(context_, tmp);
+ } else {
+ return false;
+ }
+ }
+ return true;
+
+}
+
+NativeValue* QuickJSNativeEngine::Serialize(NativeEngine* context, NativeValue* value, NativeValue* transfer)
+{
+ if (!CheckTransferList(*transfer)) {
+ return nullptr;
+ }
+ size_t dataLen;
+ uint8_t *data = JS_WriteObject(context_, &dataLen, *value, JS_WRITE_OBJ);
+ DetachTransferList(*transfer);
+ return reinterpret_cast(new SerializeData(dataLen, data));
+}
+
+NativeValue* QuickJSNativeEngine::Deserialize(NativeEngine* context, NativeValue* recorder)
+{
+ std::unique_ptr data(reinterpret_cast(recorder));
+ JSValue result = JS_ReadObject(context_, data->GetData(), data->GetSize(), JS_WRITE_OBJ);
+ return JSValueToNativeValue(this, result);
+}
+
+void QuickJSNativeEngine::DeleteSerializationData(NativeValue* value) const
+{
+ SerializeData* data = reinterpret_cast(value);
+ delete data;
+}
+
+ExceptionInfo* QuickJSNativeEngine::GetExceptionForWorker() const
+{
+ JSValue exception = JS_GetCurrentException(runtime_);
+ ASSERT(JS_IsObject(exception));
+ JSValue msg;
+ ExceptionInfo* exceptionInfo = new ExceptionInfo();
+ msg = JS_GetProperty(context_, exception, JS_ATOM_MESSAGE);
+ ASSERT(JS_IsString(msg));
+ const char* exceptionStr = reinterpret_cast(JS_GetStringFromObject(msg));
+ const char* error = "Error: ";
+ int len = strlen(exceptionStr) + strlen(error) + 1;
+ if (len <= 0) {
+ return nullptr;
+ }
+ char* exceptionMessage = new char[len] { 0 };
+ if (memcpy_s(exceptionMessage, len, error, strlen(error)) != EOK) {
+ HILOG_INFO("worker:: memcpy_s error");
+ delete exceptionInfo;
+ delete[] exceptionMessage;
+ return nullptr;
+ }
+ if (memcpy_s(exceptionMessage + strlen(error), len, exceptionStr, strlen(exceptionStr)) != EOK) {
+ HILOG_INFO("worker:: memcpy_s error");
+ delete exceptionInfo;
+ delete[] exceptionMessage;
+ return nullptr;
+ }
+ exceptionInfo->message_ = exceptionMessage;
+ return exceptionInfo;
+}
+
+ NativeValue* QuickJSNativeEngine::ValueToNativeValue(JSValueWrapper& value)
+ {
+ JSValue quickValue = value;
+ return JSValueToNativeValue(this, quickValue);
+}
\ No newline at end of file
diff --git a/native_engine/impl/quickjs/quickjs_native_engine.h b/native_engine/impl/quickjs/quickjs_native_engine.h
index 072a4f0b3af01a7993de7b2a7692ac0f22285716..20cc2db15ea0f6373bd711920c99438dbff985f3 100644
--- a/native_engine/impl/quickjs/quickjs_native_engine.h
+++ b/native_engine/impl/quickjs/quickjs_native_engine.h
@@ -19,6 +19,32 @@
#include "native_engine/native_engine.h"
#include "quickjs_headers.h"
+class SerializeData {
+public:
+ SerializeData(size_t size, uint8_t *data) : dataSize_(size), value_(data) {}
+ ~SerializeData() = default;
+
+ uint8_t* GetData() const
+ {
+ return value_.get();
+ }
+ size_t GetSize() const
+ {
+ return dataSize_;
+ }
+
+private:
+ struct Deleter {
+ void operator()(uint8_t* ptr) const
+ {
+ free(ptr);
+ }
+ };
+
+ size_t dataSize_;
+ std::unique_ptr value_;
+};
+
class QuickJSNativeEngine : public NativeEngine {
public:
QuickJSNativeEngine(JSRuntime* runtime, JSContext* context);
@@ -77,9 +103,18 @@ public:
virtual bool Throw(NativeValue* error) override;
virtual bool Throw(NativeErrorType type, const char* code, const char* message) override;
+ virtual void* CreateRuntime() override;
+ bool CheckTransferList(JSValue transferList);
+ bool DetachTransferList(JSValue transferList);
+ virtual NativeValue* Serialize(NativeEngine* context, NativeValue* value, NativeValue* transfer) override;
+ virtual NativeValue* Deserialize(NativeEngine* context, NativeValue* recorder) override;
+ virtual void DeleteSerializationData(NativeValue* value) const override;
+ virtual ExceptionInfo* GetExceptionForWorker() const override;
+
virtual NativeValue* LoadModule(NativeValue* str, const std::string& fileName) override;
static NativeValue* JSValueToNativeValue(QuickJSNativeEngine* engine, JSValue value);
+ virtual NativeValue* ValueToNativeValue(JSValueWrapper& value) override;
private:
JSRuntime* runtime_;
diff --git a/native_engine/impl/quickjs/quickjs_native_reference.cpp b/native_engine/impl/quickjs/quickjs_native_reference.cpp
index da02027a24e45b722eaf1795931ed78ed9e3775e..1e8b94ac824df0df30409d89335285216860e002 100644
--- a/native_engine/impl/quickjs/quickjs_native_reference.cpp
+++ b/native_engine/impl/quickjs/quickjs_native_reference.cpp
@@ -59,7 +59,7 @@ uint32_t QuickJSNativeReference::Unref()
NativeValue* QuickJSNativeReference::Get()
{
- return new QuickJSNativeValue(engine_, JS_DupValue(engine_->GetContext(), value_));
+ return QuickJSNativeEngine::JSValueToNativeValue(engine_, JS_DupValue(engine_->GetContext(), value_));
}
QuickJSNativeReference::operator NativeValue*()
diff --git a/native_engine/native_api.cpp b/native_engine/native_api.cpp
index 5c5c5e19c867d25ce6f3496b606facb0e0947c3b..9cec57482b0dc6dfa298a8e497e077896f745bcf 100644
--- a/native_engine/native_api.cpp
+++ b/native_engine/native_api.cpp
@@ -1595,3 +1595,92 @@ NAPI_EXTERN napi_status napi_adjust_external_memory(napi_env env, int64_t change
return napi_clear_last_error(env);
}
+
+NAPI_EXTERN napi_status napi_create_runtime(napi_env env, napi_env* result_env)
+{
+ CHECK_ENV(env);
+ CHECK_ARG(env, result_env);
+
+ auto engine = reinterpret_cast(env);
+
+ auto result = engine->CreateRuntime();
+ *result_env = reinterpret_cast(result);
+
+ return napi_clear_last_error(env);
+}
+
+NAPI_EXTERN napi_status napi_serialize(napi_env env, napi_value object, napi_value transfer_list, napi_value* result)
+{
+ CHECK_ENV(env);
+ CHECK_ARG(env, object);
+ CHECK_ARG(env, transfer_list);
+ CHECK_ARG(env, result);
+
+ auto engine = reinterpret_cast(env);
+ auto nativeValue = reinterpret_cast(object);
+ auto transferList = reinterpret_cast(transfer_list);
+
+ auto resultValue = engine->Serialize(engine, nativeValue, transferList);
+ *result = reinterpret_cast(resultValue);
+
+ return napi_clear_last_error(env);
+}
+
+NAPI_EXTERN napi_status napi_deserialize(napi_env env, napi_value recorder, napi_value* object)
+{
+ CHECK_ENV(env);
+ CHECK_ARG(env, recorder);
+ CHECK_ARG(env, object);
+
+ auto engine = reinterpret_cast(env);
+ auto recorderValue = reinterpret_cast(recorder);
+
+ auto result = engine->Deserialize(engine, recorderValue);
+ *object = reinterpret_cast(result);
+
+ return napi_clear_last_error(env);
+}
+
+NAPI_EXTERN napi_status napi_delete_serialization_data(napi_env env, napi_value value)
+{
+ CHECK_ENV(env);
+ CHECK_ARG(env, value);
+
+ auto engine = reinterpret_cast(env);
+ auto nativeValue = reinterpret_cast(value);
+
+ engine->DeleteSerializationData(nativeValue);
+
+ return napi_clear_last_error(env);
+}
+
+NAPI_EXTERN napi_status napi_get_exception_info_for_worker(napi_env env, napi_value obj)
+{
+ CHECK_ENV(env);
+ CHECK_ARG(env, obj);
+
+ auto engine = reinterpret_cast(env);
+ ExceptionInfo* exceptionInfo = engine->GetExceptionForWorker();
+ if (exceptionInfo == nullptr) {
+ HILOG_INFO("engine get exception info error");
+ return napi_invalid_arg;
+ }
+
+ napi_value lineno = nullptr;
+ napi_create_int32(env, exceptionInfo->lineno_, &lineno);
+ napi_set_named_property(env, obj, "lineno", lineno);
+
+ napi_value colno = nullptr;
+ napi_create_int32(env, exceptionInfo->colno_, &lineno);
+ napi_set_named_property(env, obj, "colno", colno);
+
+ if (exceptionInfo->message_ != nullptr) {
+ napi_value messageValue = nullptr;
+ uint32_t messageLen = strlen(exceptionInfo->message_);
+ napi_create_strting_utf8(env, exceptionInfo->message_, messageLen, &messageValue);
+ napi_set_named_property(env, obj, "message", messageValue);
+ }
+
+ delete exceptionInfo;
+ return napi_clear_last_error(env);
+}
\ No newline at end of file
diff --git a/native_engine/native_async_work.cpp b/native_engine/native_async_work.cpp
index 404cd652c8b8095058728092a956e37bbec758cb..71ddaa1a7e142be9c51511d695dbefb0bd21d4e7 100644
--- a/native_engine/native_async_work.cpp
+++ b/native_engine/native_async_work.cpp
@@ -60,6 +60,53 @@ bool NativeAsyncWork::Cancel()
return true;
}
+void NativeAsyncWork::AsyncWorkRecvCallback(const uv_async_t* req)
+{
+ NativeAsyncWork* that = NativeAsyncWork::DereferenceOf(&NativeAsyncWork::workAsyncHandler_, req);
+ if (that == nullptr) {
+ return;
+ }
+ NativeAsyncWorkDataPointer res;
+ while (that->PopData(&res)) {
+ if (that->execute_ != nullptr) {
+ that->execute_(that->engine_, res.data_);
+ }
+ if (that->complete_ != nullptr) {
+ that->complete_(that->engine_, -1, res.data_);
+ }
+ }
+}
+
+void NativeAsyncWork::Send(void* data)
+{
+ std::lock_guard lock(workAsyncMutex_);
+ NativeAsyncWorkDataPointer dataPointer(data);
+ asyncWorkRecvData_.push(dataPointer);
+ uv_async_send(&workAsyncHandler_);
+}
+
+bool NativeAsyncWork::PopData(NativeAsyncWorkDataPointer* data)
+{
+ std::lock_guard lock(workAsyncMutex_);
+ if (asyncWorkRecvData_.empty()) {
+ return false;
+ }
+ *data = asyncWorkRecvData_.front();
+ asyncWorkRecvData_.pop();
+ return true;
+}
+
+bool NativeAsyncWork::Init()
+{
+ uv_loop_t* loop = engine_->GetUVLoop();
+ if (loop == nullptr) {
+ HILOG_ERROR("Get loop failed");
+ return false;
+ }
+ uv_async_init(loop, &workAsyncHandler_, reinterpret_cast(AsyncWorkRecvCallback));
+ return true;
+}
+
void NativeAsyncWork::AsyncWorkCallback(uv_work_t* req)
{
if (req == nullptr) {
diff --git a/native_engine/native_async_work.h b/native_engine/native_async_work.h
index 4e3f617e601a7e99e505b74abeba58f2972e4ca9..d9f47ce4f4b3e0f4b8c641b303741a91ec316705 100644
--- a/native_engine/native_async_work.h
+++ b/native_engine/native_async_work.h
@@ -18,8 +18,23 @@
#include "native_value.h"
+#include
+#include
#include
+struct NativeAsyncWorkDataPointer {
+ NativeAsyncWorkDataPointer()
+ {
+ data_ = nullptr;
+ }
+
+ explicit NativeAsyncWorkDataPointer(void* data)
+ {
+ data_ = data;
+ }
+ void* data_ { nullptr };
+};
+
class NativeAsyncWork {
public:
NativeAsyncWork(NativeEngine* engine,
@@ -30,19 +45,36 @@ public:
virtual ~NativeAsyncWork();
virtual bool Queue();
virtual bool Cancel();
+ virtual bool Init();
+ virtual void Send(void* data);
+ virtual bool PopData(NativeAsyncWorkDataPointer* data);
+
+ template
+ static Outer* DereferenceOf(const Inner Outer::*field, const Inner* pointer)
+ {
+ if (field != nullptr && pointer != nullptr) {
+ auto fieldOffset = reinterpret_cast(&(static_cast(0)->*field));
+ auto outPointer = reinterpret_cast(reinterpret_cast(pointer) - fieldOffset);
+ return outPointer;
+ }
+ return nullptr;
+ }
private:
static void AsyncWorkCallback(uv_work_t* req);
static void AsyncAfterWorkCallback(uv_work_t* req, int status);
+ static void AsyncWorkRecvCallback(const uv_async_t* req);
uv_work_t work_;
-
+ uv_async_t workAsyncHandler_;
NativeEngine* engine_;
int status_;
NativeAsyncExecuteCallback execute_;
NativeAsyncCompleteCallback complete_;
void* data_;
+ std::mutex workAsyncMutex_;
+ std::queue asyncWorkRecvData_;
};
#endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_NATIVE_ASYNC_WORK_H */
diff --git a/native_engine/native_engine.cpp b/native_engine/native_engine.cpp
index 21b94b27a0a3c4c1b2dd9f1b48828b86fdc995dd..922f9dd2c5324356e948d029a30c5f32fd534cf4 100644
--- a/native_engine/native_engine.cpp
+++ b/native_engine/native_engine.cpp
@@ -14,6 +14,7 @@
*/
#include "native_engine.h"
+#include "utils/log.h"
#include
@@ -92,6 +93,13 @@ NativeAsyncWork* NativeEngine::CreateAsyncWork(NativeValue* asyncResource,
return new NativeAsyncWork(this, execute, complete, data);
}
+NativeAsyncWork* NativeEngine::CreateAsyncWork(NativeAsyncExecuteCallback execute,
+ NativeAsyncCompleteCallback complete,
+ void* data)
+{
+ return new NativeAsyncWork(this, execute, complete, data);
+}
+
NativeErrorExtendedInfo* NativeEngine::GetLastError()
{
return &lastError_;
@@ -124,3 +132,38 @@ NativeValue* NativeEngine::GetAndClearLastException()
lastException_ = nullptr;
return temp;
}
+
+void NativeEngine::EncodeToUtf8(NativeValue* nativeValue,
+ char* buffer,
+ int32_t* written,
+ size_t bufferSize,
+ int32_t* nchars)
+{
+ if (nativeValue == nullptr || nchars == nullptr || written == nullptr) {
+ HILOG_ERROR("NativeEngine EncodeToUtf8 args is nullptr");
+ return;
+ }
+
+ auto nativeString = reinterpret_cast(nativeValue->GetInterface(NativeString::INTERFACE_ID));
+
+ if (nativeString == nullptr) {
+ HILOG_ERROR("nativeValue GetInterface is nullptr");
+ return;
+ }
+ *written = nativeString->EncodeWriteUtf8(buffer, bufferSize, nchars);
+}
+
+void NativeEngine::SetPostTask(PostTask postTask)
+{
+ HILOG_INFO("SetPostTask in");
+ postTask_ = postTask;
+}
+
+void NativeEngine::TriggerPostTask()
+{
+ if (postTask_ == nullptr) {
+ HILOG_ERROR("postTask_ is nullptr");
+ return;
+ }
+ postTask_();
+}
diff --git a/native_engine/native_engine.h b/native_engine/native_engine.h
index 902f31ccf892b9345047467270168a8cfbf82987..e9a2d3f930cd35262de30259e72e979aab8eada6 100644
--- a/native_engine/native_engine.h
+++ b/native_engine/native_engine.h
@@ -35,6 +35,25 @@ struct NativeErrorExtendedInfo {
int errorCode = 0;
};
+struct ExceptionInfo {
+ const char* message_ = nullptr;
+ int32_t lineno_ = 0;
+ int32_t colno_ = 0;
+
+ ~ExceptionInfo()
+ {
+ if (message_ != nullptr) {
+ delete[] message_;
+ }
+ }
+};
+
+enum LoopMode {
+ LOOP_DEFAULT, LOOP_ONCE, LOOP_NOWAIT
+}
+
+using PostTask = std::function;
+
class NativeEngine {
public:
NativeEngine();
@@ -44,7 +63,9 @@ public:
virtual NativeModuleManager* GetModuleManager();
virtual uv_loop_t* GetUVLoop() const;
- virtual void Loop();
+ virtual void Loop(LoopMode mode);
+ virtual void SetPostTask(PostTask postTask);
+ virtual void TriggerPostTask();
virtual NativeValue* GetGlobal() = 0;
@@ -93,11 +114,22 @@ public:
NativeAsyncExecuteCallback execute,
NativeAsyncCompleteCallback complete,
void* data);
+
+ virtual NativeAsyncWork* CreateAsyncWork(NativeAsyncExecuteCallback execute,
+ NativeAsyncCompleteCallback complete,
+ void* data);
+
virtual NativeReference* CreateReference(NativeValue* value, uint32_t initialRefcount) = 0;
virtual bool Throw(NativeValue* error) = 0;
virtual bool Throw(NativeErrorType type, const char* code, const char* message) = 0;
+ virtual void* CreateRuntime() = 0;
+ virtual NativeValue* Serialize(NativeEngine* context, NativeValue* value, NativeValue* transfer) = 0;
+ virtual NativeValue* Deserialize(NativeEngine* context, NativeValue* recorder) = 0;
+ virtual ExceptionInfo* GetExceptionForWorker() const = 0;
+ virtual void DeleteSerializationData(NativeValue* value) const = 0;
+
virtual NativeValue* LoadModule(NativeValue* str, const std::string& fileName) = 0;
NativeErrorExtendedInfo* GetLastError();
@@ -105,15 +137,31 @@ public:
void ClearLastError();
bool IsExceptionPending() const;
NativeValue* GetAndClearLastException();
+ void EncodeToUtf8(NativeValue* nativeValue, char* buffer, int32_t* written, size_t bufferSize, int32_t* nchars);
+
+ void MarkSubThread()
+ {
+ isMainThread_ = false;
+ }
+
+ bool IsMainThread() const
+ {
+ return isMainThread_;
+ }
+
protected:
- NativeModuleManager* moduleManager_;
- NativeScopeManager* scopeManager_;
+ NativeModuleManager* moduleManager_ { nullptr };
+ NativeScopeManager* scopeManager_ { nullptr };
NativeErrorExtendedInfo lastError_;
- NativeValue* lastException_;
+ NativeValue* lastException_ { nullptr };
uv_loop_t* loop_;
+
+private:
+ bool isMainThread_ { nullptr };
+ PostTask postTask_ { nullptr };
};
#endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_NATIVE_ENGINE_H */