This commit is contained in:
lvfulong
2026-02-25 19:05:22 +08:00
parent a513fcbc52
commit 89637246a7
8 changed files with 544 additions and 67 deletions
+5 -5
View File
@@ -1,12 +1,12 @@
#!/bin/sh
OHOS_NDK_CMAKE_PATH="F:/Ohayoo-native/huawei/ide6.0.1/DevEcoStudio/sdk/default/openharmony/native/build-tools/cmake/bin"
OHOS_NDK_CMAKE_TOOLCHAIN_PATH="F:/Ohayoo-native/huawei/ide6.0.1/DevEcoStudio/sdk/default/openharmony/native/build/cmake/ohos.toolchain.cmake"
OHOS_NDK_CMAKE_PATH="D:/Program Files/Huawei/DevEcoStudio/sdk/default/openharmony/native/build-tools/cmake/bin"
OHOS_NDK_CMAKE_TOOLCHAIN_PATH="D:/Program Files/Huawei/DevEcoStudio/sdk/default/openharmony/native/build/cmake/ohos.toolchain.cmake"
#export PATH=${OHOS_NDK_CMAKE_PATH}:$PATH
export PATH="${OHOS_NDK_CMAKE_PATH}:$PATH"
mkdir build
cd build
${OHOS_NDK_CMAKE_PATH}/cmake.exe -G "Ninja" -DCMAKE_BUILD_TYPE=Release -DOHOS_STL=c++_shared -DCMAKE_TOOLCHAIN_FILE=${OHOS_NDK_CMAKE_TOOLCHAIN_PATH} ../conch/proj.ohos
${OHOS_NDK_CMAKE_PATH}/cmake.exe --build .
"${OHOS_NDK_CMAKE_PATH}/cmake.exe" -G "Ninja" -DCMAKE_MAKE_PROGRAM="${OHOS_NDK_CMAKE_PATH}/ninja.exe" -DCMAKE_BUILD_TYPE=Release -DOHOS_STL=c++_shared -DCMAKE_TOOLCHAIN_FILE="${OHOS_NDK_CMAKE_TOOLCHAIN_PATH}" ../conch/proj.ohos
"${OHOS_NDK_CMAKE_PATH}/cmake.exe" --build .
# 如果需要编译静态库则需要设置 cmake 变量 -DBUILD_SHARED_LIBS=OFF
# 可以通过-DCMAKE_INSTALL_PREFIX=xxx 设置库的安装目录
# 编译 arm32 -DOHOS_ARCH=armeabi-v7a
+313 -16
View File
@@ -8,6 +8,7 @@
#include "JCScriptRuntime.h"
#include <algorithm>
#include <cstring>
#include <util/Log.h>
#include "JSWrapper/JSInterface/JSInterface.h"
#include "JSWrapper/LayaWrap/JSFileReader.h"
@@ -211,30 +212,313 @@ namespace laya
m_pAssetsRes = pAssetRes;
m_pPoster = pThreadCmdSender;
}
static void onUnhandledRejection(JSValueAsParam pPromise, JSValueAsParam pReason, const char* type)
#if defined(JS_V8) || defined(JS_JSVM)
// Promise rejection pipeline - engine-specific helpers
void JCScriptRuntime::ReleaseRecord(PromiseRejectionRecord& record)
{
#ifdef JS_V8
JSPromiseRejectionEvent* event = new JSPromiseRejectionEvent;
event->setPromise(pPromise);
event->setReason(pReason);
event->setType(type);
JCScriptRuntime::s_JSRT->m_pJSOnUnhandledRejectionFunction.Call(JSP_TO_JS(JSPromiseRejectionEvent*, event));
record.promise.Reset();
record.reason.Reset();
#elif JS_JSVM
JSPromiseRejectionEvent* event = new JSPromiseRejectionEvent;
event->setPromise(pPromise);
event->setReason(pReason);
event->setType(type);
JCScriptRuntime::s_JSRT->m_pJSOnUnhandledRejectionFunction.Call(JSP_TO_JS(JSPromiseRejectionEvent*, event));
auto env = Javascript::getEnv();
JSVM_Status status;
if (record.promise) { JSVM_API_CALL(status, env, OH_JSVM_DeleteReference(env, record.promise)); }
if (record.reason) { JSVM_API_CALL(status, env, OH_JSVM_DeleteReference(env, record.reason)); }
#endif
}
JCScriptRuntime::PromiseRejectionList::iterator JCScriptRuntime::FindPromiseRecord(
PromiseRejectionList& list, JSValueAsParam promise)
{
#ifdef JS_V8
v8::Isolate* isolate = v8::Isolate::GetCurrent();
for (auto it = list.begin(); it != list.end(); ++it)
{
v8::Local<v8::Value> p = v8::Local<v8::Value>::New(isolate, it->promise);
if (p->StrictEquals(promise))
{
return it;
}
}
#elif JS_JSVM
auto env = Javascript::getEnv();
JSVM_Status status;
for (auto it = list.begin(); it != list.end(); ++it)
{
JSVM_Value p;
JSVM_API_CALL(status, env, OH_JSVM_GetReferenceValue(env, it->promise, &p));
bool equals = false;
JSVM_API_CALL(status, env, OH_JSVM_StrictEquals(env, p, promise, &equals));
if (equals)
{
return it;
}
}
#endif
return list.end();
}
bool JCScriptRuntime::RemovePromiseRecord(PromiseRejectionList& list, JSValueAsParam promise)
{
auto it = FindPromiseRecord(list, promise);
if (it != list.end())
{
ReleaseRecord(*it);
list.erase(it);
return true;
}
return false;
}
void JCScriptRuntime::EmitPromiseRejectionEvent(const char* type, const PromiseRejectionRecord& record)
{
if (m_vJSOnUnhandledRejectionFunctions.empty())
return;
#ifdef JS_V8
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::HandleScope scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Local<v8::Object> eventObj = v8::Object::New(isolate);
eventObj->Set(context,
v8::String::NewFromUtf8(isolate, "promise").ToLocalChecked(),
v8::Local<v8::Value>::New(isolate, record.promise)).Check();
if (record.reasonType == PromiseRejectionRecord::ReasonType::ReasonTypeString)
{
eventObj->Set(context,
v8::String::NewFromUtf8(isolate, "reason").ToLocalChecked(),
v8::String::NewFromUtf8(isolate, record.reasonString.c_str()).ToLocalChecked()).Check();
}
else if (record.reasonType == PromiseRejectionRecord::ReasonType::ReasonTypeObject)
{
eventObj->Set(context,
v8::String::NewFromUtf8(isolate, "reason").ToLocalChecked(),
v8::Local<v8::Value>::New(isolate, record.reason)).Check();
}
eventObj->Set(context,
v8::String::NewFromUtf8(isolate, "type").ToLocalChecked(),
v8::String::NewFromUtf8(isolate, type).ToLocalChecked()).Check();
for (auto& funcGlobal : m_vJSOnUnhandledRejectionFunctions)
{
v8::Local<v8::Function> func = v8::Local<v8::Function>::New(isolate, funcGlobal);
v8::Local<v8::Value> argv[] = { eventObj };
func->Call(context, context->Global(), 1, argv).FromMaybe(v8::Local<v8::Value>());
}
#elif JS_JSVM
auto env = Javascript::getEnv();
JSVM_Status status;
AutoHandleScope scope;
JSVM_Value eventObj;
JSVM_API_CALL(status, env, OH_JSVM_CreateObject(env, &eventObj));
JSVM_Value promiseVal;
JSVM_API_CALL(status, env, OH_JSVM_GetReferenceValue(env, record.promise, &promiseVal));
JSVM_API_CALL(status, env, OH_JSVM_SetNamedProperty(env, eventObj, "promise", promiseVal));
if (record.reasonType == PromiseRejectionRecord::ReasonType::ReasonTypeString)
{
JSVM_Value reasonVal;
JSVM_API_CALL(status, env, OH_JSVM_CreateStringUtf8(env, record.reasonString.c_str(), record.reasonString.size(), &reasonVal));
JSVM_API_CALL(status, env, OH_JSVM_SetNamedProperty(env, eventObj, "reason", reasonVal));
}
else if (record.reasonType == PromiseRejectionRecord::ReasonType::ReasonTypeObject)
{
JSVM_Value reasonVal;
JSVM_API_CALL(status, env, OH_JSVM_GetReferenceValue(env, record.reason, &reasonVal));
JSVM_API_CALL(status, env, OH_JSVM_SetNamedProperty(env, eventObj, "reason", reasonVal));
}
JSVM_Value typeVal;
JSVM_API_CALL(status, env, OH_JSVM_CreateStringUtf8(env, type, strlen(type), &typeVal));
JSVM_API_CALL(status, env, OH_JSVM_SetNamedProperty(env, eventObj, "type", typeVal));
JSVM_Value global;
JSVM_API_CALL(status, env, OH_JSVM_GetGlobal(env, &global));
for (auto& funcRef : m_vJSOnUnhandledRejectionFunctions)
{
JSVM_Value func;
JSVM_API_CALL(status, env, OH_JSVM_GetReferenceValue(env, funcRef, &func));
JSVM_Value argv[] = { eventObj };
JSVM_Value result;
JSVM_API_CALL(status, env, OH_JSVM_CallFunction(env, global, func, 1, argv, &result));
}
#endif
}
void JCScriptRuntime::EnqueueUnhandledRejection(JSValueAsParam promise, JSValueAsParam reason)
{
PromiseRejectionRecord record;
record.uid = ++m_lastPromiseRejectionId;
#ifdef JS_V8
v8::Isolate* isolate = v8::Isolate::GetCurrent();
record.promise.Reset(isolate, promise);
if (!reason.IsEmpty() && reason->IsString())
{
record.reasonType = PromiseRejectionRecord::ReasonType::ReasonTypeString;
v8::String::Utf8Value str(isolate, reason);
record.reasonString = *str ? *str : "";
}
else if (!reason.IsEmpty() && reason->IsObject())
{
record.reasonType = PromiseRejectionRecord::ReasonType::ReasonTypeObject;
record.reasonString = "";
record.reason.Reset(isolate, reason);
}
else
{
record.reasonType = PromiseRejectionRecord::ReasonType::ReasonTypeString;
record.reasonString = "";
}
#elif JS_JSVM
auto env = Javascript::getEnv();
JSVM_Status status;
JSVM_API_CALL(status, env, OH_JSVM_CreateReference(env, promise, 1, &record.promise));
bool isString = false;
bool isObject = false;
if (reason != nullptr)
{
JSVM_API_CALL(status, env, OH_JSVM_IsString(env, reason, &isString));
if (!isString)
{
JSVM_API_CALL(status, env, OH_JSVM_IsObject(env, reason, &isObject));
}
}
if (isString)
{
record.reasonType = PromiseRejectionRecord::ReasonType::ReasonTypeString;
record.reasonString = __TransferToCpp<std::string>::ToCpp(reason);
}
else if (isObject)
{
record.reasonType = PromiseRejectionRecord::ReasonType::ReasonTypeObject;
record.reasonString = "";
JSVM_API_CALL(status, env, OH_JSVM_CreateReference(env, reason, 1, &record.reason));
}
else
{
record.reasonType = PromiseRejectionRecord::ReasonType::ReasonTypeString;
record.reasonString = "";
}
#endif
m_pendingUnhandledRejections.emplace_back(std::move(record));
SchedulePromiseRejectionProcessing();
}
// Promise rejection pipeline - unified methods (no engine-specific code)
void JCScriptRuntime::SchedulePromiseRejectionProcessing()
{
if (m_isProcessingScheduled)
return;
m_isProcessingScheduled = true;
m_pScriptThread->post([this]() {
this->ProcessPromiseRejectionEvents();
});
}
void JCScriptRuntime::ProcessPromiseRejectionEvents()
{
m_isProcessingScheduled = false;
PromiseRejectionList pending;
pending.swap(m_pendingUnhandledRejections);
for (auto& record : pending)
{
record.warned = true;
EmitPromiseRejectionEvent("unhandledrejection", record);
m_maybeUnhandledRejections.emplace_back(std::move(record));
}
if (!m_asyncHandledRejections.empty())
{
std::vector<uint64_t> handled;
handled.swap(m_asyncHandledRejections);
for (const auto uid : handled)
{
auto it = std::find_if(
m_maybeUnhandledRejections.begin(),
m_maybeUnhandledRejections.end(),
[uid](const PromiseRejectionRecord& entry) { return entry.uid == uid; });
if (it != m_maybeUnhandledRejections.end())
{
EmitPromiseRejectionEvent("rejectionhandled", *it);
ReleaseRecord(*it);
m_maybeUnhandledRejections.erase(it);
}
}
}
}
void JCScriptRuntime::EnqueueRejectionHandled(JSValueAsParam promise)
{
if (RemovePromiseRecord(m_pendingUnhandledRejections, promise))
return;
auto it = FindPromiseRecord(m_maybeUnhandledRejections, promise);
if (it != m_maybeUnhandledRejections.end())
{
if (std::find(m_asyncHandledRejections.begin(),
m_asyncHandledRejections.end(),
it->uid) == m_asyncHandledRejections.end())
{
m_asyncHandledRejections.push_back(it->uid);
SchedulePromiseRejectionProcessing();
}
}
}
void JCScriptRuntime::ClearPromiseRejectionTracking()
{
for (auto& record : m_pendingUnhandledRejections)
ReleaseRecord(record);
m_pendingUnhandledRejections.clear();
for (auto& record : m_maybeUnhandledRejections)
ReleaseRecord(record);
m_maybeUnhandledRejections.clear();
m_asyncHandledRejections.clear();
m_lastPromiseRejectionId = 0;
m_isProcessingScheduled = false;
}
void JCScriptRuntime::HandlePromiseRejectionEvent(JSValueAsParam promise, JSValueAsParam reason, const char* type)
{
if (type == nullptr)
return;
if (std::strcmp(type, "unhandledrejection") == 0)
{
EnqueueUnhandledRejection(promise, reason);
}
else if (std::strcmp(type, "rejectionhandled") == 0)
{
EnqueueRejectionHandled(promise);
}
}
#endif
void JCScriptRuntime::start(const char* pStartJS)
{
LOGI("Start js %s", pStartJS);
if (pStartJS)m_strStartJS = pStartJS;
#ifdef JS_V8
m_pScriptThread->initialize(JCConch::s_pConch->m_nJSDebugPort, std::bind(&onUnhandledRejection, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
#elif JS_JSVM
m_pScriptThread->initialize(JCConch::s_pConch->m_nJSDebugPort, std::bind(&onUnhandledRejection, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
#if defined(JS_V8) || defined(JS_JSVM)
m_pScriptThread->initialize(JCConch::s_pConch->m_nJSDebugPort,
[](JSValueAsParam promise, JSValueAsParam reason, const char* type) {
if (JCScriptRuntime::s_JSRT) {
JCScriptRuntime::s_JSRT->HandlePromiseRejectionEvent(promise, reason, type);
}
});
#else
m_pScriptThread->initialize(JCConch::s_pConch->m_nJSDebugPort);
#endif
@@ -426,7 +710,20 @@ namespace laya
m_pJSOnDrawFunction.Reset();
m_bJSBulletGetWorldTransformHandle.Reset();
m_bJSBulletSetWorldTransformHandle.Reset();
m_pJSOnUnhandledRejectionFunction.Reset();
#if defined(JS_V8) || defined(JS_JSVM)
ClearPromiseRejectionTracking();
#ifdef JS_JSVM
{
auto env = Javascript::getEnv();
JSVM_Status status;
for (auto& ref : m_vJSOnUnhandledRejectionFunctions)
{
if (ref) { JSVM_API_CALL(status, env, OH_JSVM_DeleteReference(env, ref)); }
}
}
#endif
m_vJSOnUnhandledRejectionFunctions.clear();
#endif
#ifdef OHOS
m_pGameJsOnMessage.Reset();
#endif
+46 -6
View File
@@ -10,6 +10,8 @@
#define __JCScriptRuntime_H__
#include <vector>
#include <algorithm>
#include <cstring>
#include <util/JCCommonMethod.h>
#include "JSWrapper/JSInterface/JSInterface.h"
#include <fontMgr/JCFreeTypeRender.h>
@@ -113,9 +115,7 @@ namespace laya
E_DEVICEORIENTATION,
E_TYPE_COUNT,
};
#ifdef JS_V8
class DebuggerAgent;
#elif JS_JSVM
#if defined(JS_V8) || defined(JS_JSVM)
class DebuggerAgent;
#endif
class JSLayaGL;
@@ -235,7 +235,6 @@ namespace laya
JsObjHandle m_pJSOnceOtherEvtFuction; //注册一次的事件 如截屏
JsObjHandle m_pJSNetworkEvtFunction; //网络事件的监听
JsObjHandle m_pJSOnBackPressedFunction;
JsObjHandle m_pJSOnUnhandledRejectionFunction;
bool m_bJSOnBackPressedFunctionSet;
JsObjHandle m_bJSBulletGetWorldTransformHandle;
JsObjHandle m_bJSBulletSetWorldTransformHandle;
@@ -269,10 +268,51 @@ namespace laya
void onJsObjHandle(std::string key ,std::string value);
void onJsObjHandleCallJSFunction(std::string key ,std::string value);
#endif
#if defined(JS_V8) || defined(JS_JSVM)
DebuggerAgent* m_pDbgAgent;
// Promise rejection tracking - multiple callback support
#ifdef JS_V8
DebuggerAgent* m_pDbgAgent;
std::vector<v8::Global<v8::Function>> m_vJSOnUnhandledRejectionFunctions;
#elif JS_JSVM
DebuggerAgent* m_pDbgAgent;
std::vector<JSVM_Ref> m_vJSOnUnhandledRejectionFunctions;
#endif
public:
void HandlePromiseRejectionEvent(JSValueAsParam promise, JSValueAsParam reason, const char* type);
private:
struct PromiseRejectionRecord {
enum class ReasonType {
ReasonTypeString,
ReasonTypeObject,
};
uint64_t uid = 0;
bool warned = false;
#ifdef JS_V8
v8::Global<v8::Value> promise;
v8::Global<v8::Value> reason;
#elif JS_JSVM
JSVM_Ref promise = nullptr;
JSVM_Ref reason = nullptr;
#endif
std::string reasonString;
ReasonType reasonType = ReasonType::ReasonTypeString;
};
using PromiseRejectionList = std::vector<PromiseRejectionRecord>;
PromiseRejectionList m_pendingUnhandledRejections;
PromiseRejectionList m_maybeUnhandledRejections;
std::vector<uint64_t> m_asyncHandledRejections;
uint64_t m_lastPromiseRejectionId = 0;
bool m_isProcessingScheduled = false;
PromiseRejectionList::iterator FindPromiseRecord(PromiseRejectionList& list, JSValueAsParam promise);
bool RemovePromiseRecord(PromiseRejectionList& list, JSValueAsParam promise);
void EmitPromiseRejectionEvent(const char* type, const PromiseRejectionRecord& record);
void ProcessPromiseRejectionEvents();
void SchedulePromiseRejectionProcessing();
void EnqueueUnhandledRejection(JSValueAsParam promise, JSValueAsParam reason);
void EnqueueRejectionHandled(JSValueAsParam promise);
void ClearPromiseRejectionTracking();
void ReleaseRecord(PromiseRejectionRecord& record);
#endif
private:
bool m_bRunDraw;
@@ -70,28 +70,21 @@ namespace laya
static void PromiseRejectHandlerInMainThread(v8::PromiseRejectMessage data) {
v8::Local<v8::Promise> promise = data.GetPromise();
v8::Isolate* isolate = promise->GetIsolate();
if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) {
return;
} else if (data.GetEvent() == v8::kPromiseRejectAfterResolved || data.GetEvent() == v8::kPromiseResolveAfterResolved) {
if (data.GetEvent() == v8::kPromiseRejectAfterResolved || data.GetEvent() == v8::kPromiseResolveAfterResolved) {
// Ignore reject/resolve after resolved.
return;
}
v8::Local<v8::Value> exception = data.GetValue();
char* error_message = nullptr;
v8::Local<v8::Message> message = v8::Exception::CreateMessage(isolate, exception);
if (!message.IsEmpty()) {
if (message->Get().IsEmpty() || message->Get()->IsNull())
error_message = "";
error_message = __TransferToCpp<char*>::ToCpp(message->Get().As<v8::Value>());
}
//std::string kBuf = "if(conch.onunhandledrejection){conch.onunhandledrejection('";
//kBuf += UrlEncode(error_message != nullptr ? error_message : "");
//kBuf += "');};";
//__JSRun::Run(kBuf.c_str());
IsolateData* pIsolateData = IsolateData::From(isolate);
Javascript* pJavascript = (Javascript*)pIsolateData->m_data;
pJavascript->m_promiseRejectHandler(data.GetPromise(), data.GetValue(), "unhandledrejection");
if (data.GetEvent() == v8::kPromiseRejectWithNoHandler) {
v8::Local<v8::Value> reason = data.GetValue();
if (reason.IsEmpty()) {
reason = v8::Undefined(isolate);
}
pJavascript->m_promiseRejectHandler(promise, reason, "unhandledrejection");
} else if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) {
pJavascript->m_promiseRejectHandler(promise, v8::Undefined(isolate), "rejectionhandled");
}
}
void Javascript::initJSEngine()
@@ -423,14 +423,152 @@ namespace laya
return JSWebGLPlus::getInstance()->updateArrayBufferRef(nID, bSyncToRender, pArrayBuffer);
}*/
#ifdef JS_V8
void JSRuntime::setOnUnhandledRejection(JSValueAsParam p_pFunction)
{
m_pScrpitRuntime->m_pJSOnUnhandledRejectionFunction.set(onunhandledrejection, this, p_pFunction);
if (p_pFunction.IsEmpty() || !p_pFunction->IsFunction())
return;
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(p_pFunction);
auto& list = m_pScrpitRuntime->m_vJSOnUnhandledRejectionFunctions;
// Check for duplicates
for (auto& existing : list)
{
v8::Local<v8::Function> existingLocal = v8::Local<v8::Function>::New(isolate, existing);
if (existingLocal->StrictEquals(func))
return;
}
v8::Global<v8::Function> globalFunc;
globalFunc.Reset(isolate, func);
list.push_back(std::move(globalFunc));
}
void JSRuntime::offUnhandledRejection(JSValueAsParam p_pFunction)
{
auto& list = m_pScrpitRuntime->m_vJSOnUnhandledRejectionFunctions;
if (p_pFunction.IsEmpty() || p_pFunction->IsUndefined() || p_pFunction->IsNull())
{
list.clear();
return;
}
if (p_pFunction->IsFunction())
{
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(p_pFunction);
for (auto it = list.begin(); it != list.end(); ++it)
{
v8::Local<v8::Function> existing = v8::Local<v8::Function>::New(isolate, *it);
if (existing->StrictEquals(func))
{
list.erase(it);
break;
}
}
}
}
JsValue JSRuntime::getOnUnhandledRejection()
{
return m_pScrpitRuntime->m_pJSOnUnhandledRejectionFunction.getJsObj();
auto& list = m_pScrpitRuntime->m_vJSOnUnhandledRejectionFunctions;
if (list.empty()) return v8::Undefined(v8::Isolate::GetCurrent());
v8::Isolate* isolate = v8::Isolate::GetCurrent();
return v8::Local<v8::Value>::Cast(v8::Local<v8::Function>::New(isolate, list.front()));
}
#elif JS_JSVM
void JSRuntime::setOnUnhandledRejection(JSValueAsParam p_pFunction)
{
auto env = Javascript::getEnv();
JSVM_Status status;
bool isFunc = false;
if (p_pFunction == nullptr) return;
JSVM_API_CALL(status, env, OH_JSVM_IsFunction(env, p_pFunction, &isFunc));
if (!isFunc) return;
auto& list = m_pScrpitRuntime->m_vJSOnUnhandledRejectionFunctions;
// Check for duplicates
for (auto& existing : list)
{
JSVM_Value existingVal;
JSVM_API_CALL(status, env, OH_JSVM_GetReferenceValue(env, existing, &existingVal));
bool equals = false;
JSVM_API_CALL(status, env, OH_JSVM_StrictEquals(env, existingVal, p_pFunction, &equals));
if (equals) return;
}
JSVM_Ref ref = nullptr;
JSVM_API_CALL(status, env, OH_JSVM_CreateReference(env, p_pFunction, 1, &ref));
list.push_back(ref);
}
void JSRuntime::offUnhandledRejection(JSValueAsParam p_pFunction)
{
auto env = Javascript::getEnv();
JSVM_Status status;
auto& list = m_pScrpitRuntime->m_vJSOnUnhandledRejectionFunctions;
bool isUndef = false, isNull = false;
if (p_pFunction == nullptr) { isNull = true; }
else {
JSVM_API_CALL(status, env, OH_JSVM_IsUndefined(env, p_pFunction, &isUndef));
JSVM_API_CALL(status, env, OH_JSVM_IsNull(env, p_pFunction, &isNull));
}
if (isUndef || isNull)
{
for (auto& ref : list)
{
if (ref) { JSVM_API_CALL(status, env, OH_JSVM_DeleteReference(env, ref)); }
}
list.clear();
return;
}
bool isFunc = false;
JSVM_API_CALL(status, env, OH_JSVM_IsFunction(env, p_pFunction, &isFunc));
if (isFunc)
{
for (auto it = list.begin(); it != list.end(); ++it)
{
JSVM_Value existingVal;
JSVM_API_CALL(status, env, OH_JSVM_GetReferenceValue(env, *it, &existingVal));
bool equals = false;
JSVM_API_CALL(status, env, OH_JSVM_StrictEquals(env, existingVal, p_pFunction, &equals));
if (equals)
{
JSVM_API_CALL(status, env, OH_JSVM_DeleteReference(env, *it));
list.erase(it);
break;
}
}
}
}
JsValue JSRuntime::getOnUnhandledRejection()
{
auto& list = m_pScrpitRuntime->m_vJSOnUnhandledRejectionFunctions;
if (list.empty()) return JsObjBase::getUndefined();
auto env = Javascript::getEnv();
JSVM_Status status;
JSVM_Value result;
JSVM_API_CALL(status, env, OH_JSVM_GetReferenceValue(env, list.front(), &result));
return result;
}
#elif defined(JS_JSC)
void JSRuntime::setOnUnhandledRejection(JSValueAsParam p_pFunction)
{
// Stub: JSC does not support promise rejection tracking via C API
}
void JSRuntime::offUnhandledRejection(JSValueAsParam p_pFunction)
{
// Stub: JSC does not support promise rejection tracking via C API
}
JsValue JSRuntime::getOnUnhandledRejection()
{
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
return JSValueMakeUndefined(ctx);
}
#endif
#if OHOS
std::string JSRuntime::postMessage(const char* eventName, const char* data){
std::string result = NapiHelper::GetInstance()->postMessageToUIThread(eventName,data);
@@ -484,6 +622,7 @@ namespace laya
JSP_GLOBAL_ADD_METHOD("convertBitmapToJpeg", JSRuntime::convertBitmapToJpeg);
JSP_GLOBAL_ADD_METHOD("callWebviewJS", JSRuntime::callWebviewJS);
JSP_GLOBAL_ADD_PROPERTY(onunhandledrejection, JSRuntime, getOnUnhandledRejection, setOnUnhandledRejection);
//JSP_GLOBAL_ADD_METHOD("offUnhandledRejection", JSRuntime::offUnhandledRejection);
//JSP_GLOBAL_ADD_METHOD("updateArrayBufferRef", JSRuntime::updateArrayBufferRef);
JSP_GLOBAL_ADD_METHOD("exit", JSRuntime::exit);
#ifdef OHOS
@@ -79,8 +79,8 @@ namespace laya
void setSetWorldTransformFunction(JSValueAsParam p_pFunction);
void offUnhandledRejection(JSValueAsParam p_pFunction);
void setOnUnhandledRejection(JSValueAsParam p_pFunction);
JsValue getOnUnhandledRejection();
public:
static JSRuntime* getInstance();
+20 -19
View File
@@ -89,7 +89,21 @@ void DispatchTouchEventCB(OH_NativeXComponent* component, void* window)
void dispatchKeyEventCB(OH_NativeXComponent* component, void* window) {
OH_NativeXComponent_KeyEvent* keyEvent;
if (OH_NativeXComponent_GetKeyEvent(component, &keyEvent) >= 0) {
PluginRender::GetInstance()->sendMsgToWorker(MessageType::WM_XCOMPONENT_KEY_EVENT, component, window);
static const int keyCodeUnknownInOH = -1;
static const int keyActionUnknownInOH = -1;
OH_NativeXComponent_KeyAction action;
OH_NativeXComponent_GetKeyEventAction(keyEvent, &action);
OH_NativeXComponent_KeyCode code;
OH_NativeXComponent_GetKeyEventCode(keyEvent, &code);
if (code == keyCodeUnknownInOH || action == keyActionUnknownInOH) {
// "unknown code and action dont't callback"
return;
}
LAYA_KeyEvent* event = new LAYA_KeyEvent();
event->action = action;
event->code = code;
PluginRender::GetInstance()->sendMsgToWorker(MessageType::WM_XCOMPONENT_KEY_EVENT, component, window, event);
} else {
// OpenHarmonyPlatform::getKeyEventError
}
@@ -152,7 +166,8 @@ void PluginRender::onMessageCallback(const uv_async_t* /* req */) {
OH_NativeXComponent_TouchEvent* touchEvent = reinterpret_cast<OH_NativeXComponent_TouchEvent*>(msgData.eventData);
render->DispatchTouchEvent(nativexcomponet, msgData.window, touchEvent);
} else if (msgData.type == MessageType::WM_XCOMPONENT_KEY_EVENT) {
render->DispatchKeyEvent(nativexcomponet, msgData.window);
LAYA_KeyEvent* keyEvent = reinterpret_cast<LAYA_KeyEvent*>(msgData.eventData);
render->DispatchKeyEvent(nativexcomponet, msgData.window, keyEvent);
} else if (msgData.type == MessageType::WM_XCOMPONENT_MOUSE_EVENT) {
OH_NativeXComponent_MouseEvent* mouseEvent = reinterpret_cast<OH_NativeXComponent_MouseEvent*>(msgData.eventData);
render->DispatchMouseEvent(nativexcomponet, msgData.window, mouseEvent);
@@ -363,24 +378,10 @@ void PluginRender::DispatchTouchEvent(OH_NativeXComponent* component, void* wind
delete touchEvent;
}
void PluginRender::DispatchKeyEvent(OH_NativeXComponent* component, void* window)
void PluginRender::DispatchKeyEvent(OH_NativeXComponent* component, void* window, LAYA_KeyEvent* keyEvent)
{
OH_NativeXComponent_KeyEvent* keyEvent;
if (OH_NativeXComponent_GetKeyEvent(component, &keyEvent) >= 0) {
static const int keyCodeUnknownInOH = -1;
static const int keyActionUnknownInOH = -1;
OH_NativeXComponent_KeyAction action;
OH_NativeXComponent_GetKeyEventAction(keyEvent, &action);
OH_NativeXComponent_KeyCode code;
OH_NativeXComponent_GetKeyEventCode(keyEvent, &code);
if (code == keyCodeUnknownInOH || action == keyActionUnknownInOH) {
// "unknown code and action dont't callback"
return;
}
nativeHandleKey(action, code);
} else {
// OpenHarmonyPlatform::getKeyEventError
}
nativeHandleKey(keyEvent->action, keyEvent->code);
delete keyEvent;
}
void PluginRender::DispatchMouseEvent(OH_NativeXComponent* component, void* window, OH_NativeXComponent_MouseEvent* mouseEvent)
+8 -1
View File
@@ -11,6 +11,13 @@
#include "egl_core.h"
#include "../WorkerMessageQueue.h"
typedef struct {
// key event action
OH_NativeXComponent_KeyAction action;
// key event code
OH_NativeXComponent_KeyCode code;
} LAYA_KeyEvent;
class PluginRender {
public:
PluginRender();
@@ -56,7 +63,7 @@ public:
void OnSurfaceShow(void* window);
void DispatchTouchEvent(OH_NativeXComponent* component, void* window, OH_NativeXComponent_TouchEvent* touchEvent);
void DispatchKeyEvent(OH_NativeXComponent* component, void* window);
void DispatchKeyEvent(OH_NativeXComponent* component, void* window, LAYA_KeyEvent* keyEvent);
void DispatchMouseEvent(OH_NativeXComponent* component, void* window, OH_NativeXComponent_MouseEvent* mouseEvent);
void OnCreateNative(napi_env env, uv_loop_t* loop);