From 47e16a9d57e2042acb00793c5d0a787b91e32ad9 Mon Sep 17 00:00:00 2001 From: y00576111 Date: Sat, 18 Sep 2021 18:32:49 +0800 Subject: [PATCH] fixed a22f6e5 from https://gitee.com/yaojian16/ace_napi/pulls/34 add quickjs worker napi && support ark Signed-off-by: y00576111 Change-Id: Iaafedc94c71d0522fbd305d02048631987807cd6 --- native_engine/impl/ark/ark_native_engine.cpp | 10 ++ native_engine/impl/ark/ark_native_engine.h | 1 + .../ark/native_value/ark_native_object.cpp | 6 +- native_engine/impl/quickjs/quickjs_ext.cpp | 2 +- .../impl/quickjs/quickjs_native_engine.cpp | 101 +++++++++++++++++- .../impl/quickjs/quickjs_native_engine.h | 28 +++++ native_engine/impl/v8/v8_native_engine.cpp | 3 +- test/unittest/test_napi.cpp | 4 - 8 files changed, 140 insertions(+), 15 deletions(-) diff --git a/native_engine/impl/ark/ark_native_engine.cpp b/native_engine/impl/ark/ark_native_engine.cpp index fd0eb35a3..ee81553f9 100644 --- a/native_engine/impl/ark/ark_native_engine.cpp +++ b/native_engine/impl/ark/ark_native_engine.cpp @@ -570,3 +570,13 @@ NativeValue* ArkNativeEngine::ValueToNativeValue(JSValueWrapper& value) Global arkValue = value; return ArkValueToNativeValue(this, arkValue.ToLocal(vm_)); } + +bool ArkNativeEngine::ExecuteJsBin(const std::string& fileName) +{ + panda::JSExecutionScope executionScope(vm_); + LocalScope scope(vm_); + Local file = StringRef::NewFromUtf8(vm_, fileName.c_str()); + Local entryPoint = StringRef::NewFromUtf8(vm_, PANDA_MAIN_FUNCTION); + bool ret = JSNApi::Execute(vm_, file, entryPoint); + return ret; +} diff --git a/native_engine/impl/ark/ark_native_engine.h b/native_engine/impl/ark/ark_native_engine.h index 0efbb561a..bd37bcb70 100644 --- a/native_engine/impl/ark/ark_native_engine.h +++ b/native_engine/impl/ark/ark_native_engine.h @@ -145,6 +145,7 @@ public: NativeValue* ValueToNativeValue(JSValueWrapper& value) override; + bool ExecuteJsBin(const std::string& fileName); private: EcmaVM* vm_ = nullptr; std::string exceptionStr_; diff --git a/native_engine/impl/ark/native_value/ark_native_object.cpp b/native_engine/impl/ark/native_value/ark_native_object.cpp index ef67b3a7d..bbc066900 100644 --- a/native_engine/impl/ark/native_value/ark_native_object.cpp +++ b/native_engine/impl/ark/native_value/ark_native_object.cpp @@ -71,10 +71,8 @@ void ArkNativeObject::SetNativePointer(void* pointer, NativeFinalize cb, void* h objInfo); Local key = StringRef::NewFromUtf8(vm, "_napiwrapper"); - bool has = value->Has(vm, key); - if (!has) { - value->Set(vm, key, object); - } + // bool has = value->Has(vm, key); + value->Set(vm, key, object); } void* ArkNativeObject::GetNativePointer() diff --git a/native_engine/impl/quickjs/quickjs_ext.cpp b/native_engine/impl/quickjs/quickjs_ext.cpp index 9d720a412..8ce1ed314 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 bc502ca5c..943292244 100644 --- a/native_engine/impl/quickjs/quickjs_native_engine.cpp +++ b/native_engine/impl/quickjs/quickjs_native_engine.cpp @@ -30,8 +30,15 @@ #include "quickjs_native_deferred.h" #include "quickjs_native_reference.h" +#include "securec.h" + +#include "utils/assert.h" + #include "utils/log.h" +static const int JS_WRITE_OBJ = (1 << 2) | (1 << 3); +static const int JS_ATOM_MESSAGE = 51; + QuickJSNativeEngine::QuickJSNativeEngine(JSRuntime* runtime, JSContext* context, void* jsEngine) : NativeEngine(jsEngine) { @@ -348,7 +355,9 @@ NativeValue* QuickJSNativeEngine::RunScript(NativeValue* script) NativeValue* QuickJSNativeEngine::RunBufferScript(std::vector& buffer) { - return nullptr; + JSValue result = + JS_Eval(context_, reinterpret_cast(buffer.data()), buffer.size(), "", JS_EVAL_TYPE_GLOBAL); + return JSValueToNativeValue(this, result); } NativeValue* QuickJSNativeEngine::LoadModule(NativeValue* str, const std::string& fileName) @@ -587,26 +596,108 @@ NativeValue* QuickJSNativeEngine::JSValueToNativeValue(QuickJSNativeEngine* engi void* QuickJSNativeEngine::CreateRuntime() { - return nullptr; + JSRuntime* runtime = JS_NewRuntime(); + JSContext* context = JS_NewContext(runtime); + return reinterpret_cast(new QuickJSNativeEngine(runtime, context, this)); +} + +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) { - return nullptr; + 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) { - return nullptr; + 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 { - return nullptr; + 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) diff --git a/native_engine/impl/quickjs/quickjs_native_engine.h b/native_engine/impl/quickjs/quickjs_native_engine.h index 0be47b113..91a395ce4 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* contex, void* jsEngine); @@ -79,6 +105,8 @@ public: 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; diff --git a/native_engine/impl/v8/v8_native_engine.cpp b/native_engine/impl/v8/v8_native_engine.cpp index ea5e85023..39cb20c27 100644 --- a/native_engine/impl/v8/v8_native_engine.cpp +++ b/native_engine/impl/v8/v8_native_engine.cpp @@ -399,7 +399,8 @@ NativeValue* V8NativeEngine::RunScript(NativeValue* script) NativeValue* V8NativeEngine::RunBufferScript(std::vector& buffer) { - return nullptr; + NativeValue* script = CreateString(reinterpret_cast(buffer.data()), buffer.size()); + return RunScript(script); } namespace { diff --git a/test/unittest/test_napi.cpp b/test/unittest/test_napi.cpp index fe8e1f8c5..0e443ff22 100644 --- a/test/unittest/test_napi.cpp +++ b/test/unittest/test_napi.cpp @@ -826,11 +826,7 @@ HWTEST_F(NativeEngineTest, CreateRuntimeTest, testing::ext::TestSize.Level0) napi_env newEnv = nullptr; napi_create_runtime(env, &newEnv); -#ifdef USE_V8_ENGINE ASSERT_NE(newEnv, nullptr); -#elif USE_QUICKJS_ENGINE - ASSERT_EQ(newEnv, nullptr); -#endif } /** -- Gitee