From 7f5a7861bb7743363f2d8cce112d190fb611f20b Mon Sep 17 00:00:00 2001 From: Eduardo Speroni Date: Thu, 15 Jan 2026 17:05:26 -0300 Subject: [PATCH] fix: select correct runtime when calling from different threads and improve error message --- .../src/main/cpp/NativeScriptException.cpp | 32 +++++++++++++++++-- .../src/main/cpp/NativeScriptException.h | 7 ++-- .../runtime/src/main/cpp/ObjectManager.cpp | 17 +++++++--- .../src/main/java/com/tns/Runtime.java | 3 +- 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/test-app/runtime/src/main/cpp/NativeScriptException.cpp b/test-app/runtime/src/main/cpp/NativeScriptException.cpp index 1a2e92303..d5b69df62 100644 --- a/test-app/runtime/src/main/cpp/NativeScriptException.cpp +++ b/test-app/runtime/src/main/cpp/NativeScriptException.cpp @@ -143,6 +143,34 @@ void NativeScriptException::Init() { assert(NATIVESCRIPTEXCEPTION_GET_MESSAGE_METHOD_ID != nullptr); } +std::string NativeScriptException::ToString() const { + std::stringstream ss; + if (!m_javaException.IsNull()) { + JEnv env; + std::string message = GetExceptionMessage(env, m_javaException); + std::string stackTrace = GetExceptionStackTrace(env, m_javaException); + ss << "Java Exception: " << message << "\n" << stackTrace; + } else if (m_javascriptException != nullptr) { + ss << "JavaScript Exception: " << m_message << "\n" << m_stackTrace; + } else if (!m_message.empty()) { + ss << "Exception Message: " << m_message << "\n" << m_stackTrace; + } else { + ss << "No exception information available."; + } + return ss.str(); +} + +std::string NativeScriptException::GetErrorMessage() const { + if(!m_javaException.IsNull()) { + JEnv env; + return GetExceptionMessage(env, m_javaException); + } else if (m_javascriptException != nullptr) { + return m_message; + } else { + return m_message.empty() ? "No exception message available." : m_message; + } +} + // ON V8 UNCAUGHT EXCEPTION void NativeScriptException::OnUncaughtError(Local message, Local error) { string errorMessage = GetErrorMessage(message, error); @@ -375,7 +403,7 @@ string NativeScriptException::GetErrorStackTrace(const Local& stackT return ss.str(); } -string NativeScriptException::GetExceptionMessage(JEnv& env, jthrowable exception) { +string NativeScriptException::GetExceptionMessage(JEnv& env, jthrowable exception) const { string errMsg; JniLocalRef msg(env.CallStaticObjectMethod(NATIVESCRIPTEXCEPTION_CLASS, NATIVESCRIPTEXCEPTION_GET_MESSAGE_METHOD_ID, exception)); @@ -388,7 +416,7 @@ string NativeScriptException::GetExceptionMessage(JEnv& env, jthrowable exceptio return errMsg; } -string NativeScriptException::GetExceptionStackTrace(JEnv& env, jthrowable exception) { +string NativeScriptException::GetExceptionStackTrace(JEnv& env, jthrowable exception) const { string errStackTrace; JniLocalRef msg(env.CallStaticObjectMethod(NATIVESCRIPTEXCEPTION_CLASS, NATIVESCRIPTEXCEPTION_GET_STACK_TRACE_AS_STRING_METHOD_ID, exception)); diff --git a/test-app/runtime/src/main/cpp/NativeScriptException.h b/test-app/runtime/src/main/cpp/NativeScriptException.h index ee8afad0d..049238a30 100644 --- a/test-app/runtime/src/main/cpp/NativeScriptException.h +++ b/test-app/runtime/src/main/cpp/NativeScriptException.h @@ -33,6 +33,9 @@ class NativeScriptException { void ReThrowToV8(); void ReThrowToJava(); + std::string ToString() const; + std::string GetErrorMessage() const; + static void Init(); /* @@ -54,12 +57,12 @@ class NativeScriptException { /* * Gets java exception message from jthrowable */ - std::string GetExceptionMessage(JEnv& env, jthrowable exception); + std::string GetExceptionMessage(JEnv& env, jthrowable exception) const; /* * Gets java exception stack trace from jthrowable */ - std::string GetExceptionStackTrace(JEnv& env, jthrowable exception); + std::string GetExceptionStackTrace(JEnv& env, jthrowable exception) const; /* * Gets the member m_javaException, wraps it and creates a javascript error object from it diff --git a/test-app/runtime/src/main/cpp/ObjectManager.cpp b/test-app/runtime/src/main/cpp/ObjectManager.cpp index 18454156e..4ca4340f8 100644 --- a/test-app/runtime/src/main/cpp/ObjectManager.cpp +++ b/test-app/runtime/src/main/cpp/ObjectManager.cpp @@ -105,14 +105,23 @@ JniLocalRef ObjectManager::GetJavaObjectByJsObject( JSInstanceInfo* jsInstanceInfo = GetJSInstanceInfo(object); if (jsInstanceInfo != nullptr) { + jweak existingObject; + try { + existingObject = GetJavaObjectByID(jsInstanceInfo->JavaObjectID); + } catch (const NativeScriptException& e) { + // this captures usually the error + auto className = GetClassName(jsInstanceInfo->ObjectClazz); + throw NativeScriptException("Failed to get Java object by ID. id=" + + std::to_string(jsInstanceInfo->JavaObjectID) + + ", class=" + className + ". " + + e.GetErrorMessage()); + } if (m_useGlobalRefs) { - JniLocalRef javaObject(GetJavaObjectByID(jsInstanceInfo->JavaObjectID), - true); + JniLocalRef javaObject(existingObject, true); return javaObject; } else { JEnv env; - JniLocalRef javaObject( - env.NewLocalRef(GetJavaObjectByID(jsInstanceInfo->JavaObjectID))); + JniLocalRef javaObject(env.NewLocalRef(existingObject)); return javaObject; } } diff --git a/test-app/runtime/src/main/java/com/tns/Runtime.java b/test-app/runtime/src/main/java/com/tns/Runtime.java index 17272d34b..14c2aa438 100644 --- a/test-app/runtime/src/main/java/com/tns/Runtime.java +++ b/test-app/runtime/src/main/java/com/tns/Runtime.java @@ -1246,7 +1246,8 @@ public static Object callJSMethodWithDelay(Object javaObject, String methodName, public static Object callJSMethod(Object javaObject, String methodName, Class retType, boolean isConstructor, long delay, Object... args) throws NativeScriptException { Runtime runtime = Runtime.getCurrentRuntime(); - if (runtime == null) { + // if we're not in a runtime or the runtime we're in does not have the object, try to find the right one (this might happen if a worker fires a JS method on an object created in the main thread or another worker) + if (runtime == null || runtime.getJavaObjectID(javaObject) == null) { runtime = getObjectRuntime(javaObject); }