diff --git a/android/src/main/cpp/FrameProcessorRuntimeManager.cpp b/android/src/main/cpp/FrameProcessorRuntimeManager.cpp index 200c060..811181a 100644 --- a/android/src/main/cpp/FrameProcessorRuntimeManager.cpp +++ b/android/src/main/cpp/FrameProcessorRuntimeManager.cpp @@ -82,6 +82,26 @@ CameraView* FrameProcessorRuntimeManager::findCameraViewById(int viewId) { return result->cthis(); } +void FrameProcessorRuntimeManager::logErrorToJS(std::string message) { + if (!this->jsCallInvoker_) { + return; + } + + this->jsCallInvoker_->invokeAsync([this, message]() { + if (this->runtime_ == nullptr) { + return; + } + + auto& runtime = *this->runtime_; + auto consoleError = runtime + .global() + .getPropertyAsObject(runtime, "console") + .getPropertyAsFunction(runtime, "error"); + consoleError.call(runtime, jsi::String::createFromUtf8(runtime, message)); + }); + } + + // actual JSI installer void FrameProcessorRuntimeManager::installJSIBindings() { __android_log_write(ANDROID_LOG_INFO, TAG, "Installing JSI bindings..."); @@ -132,10 +152,16 @@ void FrameProcessorRuntimeManager::installJSIBindings() { auto function = std::make_shared(worklet->getValue(rt).asObject(rt).asFunction(rt)); // assign lambda to frame processor - cameraView->setFrameProcessor([&rt, function](jni::local_ref frame) { - // create HostObject which holds the Frame (JImageProxy) - auto hostObject = std::make_shared(frame); - function->call(rt, jsi::Object::createFromHostObject(rt, hostObject)); + cameraView->setFrameProcessor([this, &rt, function](jni::local_ref frame) { + try { + // create HostObject which holds the Frame (JImageProxy) + auto hostObject = std::make_shared(frame); + function->call(rt, jsi::Object::createFromHostObject(rt, hostObject)); + } catch (jsi::JSError& jsError) { + auto message = "Frame Processor threw an error: " + jsError.getMessage(); + __android_log_write(ANDROID_LOG_ERROR, TAG, message.c_str()); + this->logErrorToJS(message); + } }); __android_log_write(ANDROID_LOG_INFO, TAG, "Frame Processor set!"); diff --git a/android/src/main/cpp/FrameProcessorRuntimeManager.h b/android/src/main/cpp/FrameProcessorRuntimeManager.h index 640888b..f8cbc02 100644 --- a/android/src/main/cpp/FrameProcessorRuntimeManager.h +++ b/android/src/main/cpp/FrameProcessorRuntimeManager.h @@ -53,6 +53,7 @@ class FrameProcessorRuntimeManager : public jni::HybridClass plugin); + void logErrorToJS(std::string message); }; } // namespace vision diff --git a/ios/Frame Processor/FrameProcessorUtils.mm b/ios/Frame Processor/FrameProcessorUtils.mm index 21844ef..6fe7c81 100644 --- a/ios/Frame Processor/FrameProcessorUtils.mm +++ b/ios/Frame Processor/FrameProcessorUtils.mm @@ -9,19 +9,35 @@ #import "FrameProcessorUtils.h" #import #import + #import "FrameHostObject.h" #import "Frame.h" +#import +#import +#import "JSConsoleHelper.h" +#import + FrameProcessorCallback convertJSIFunctionToFrameProcessorCallback(jsi::Runtime &runtime, const jsi::Function &value) { __block auto cb = value.getFunction(runtime); return ^(Frame* frame) { - + auto frameHostObject = std::make_shared(frame); try { cb.call(runtime, jsi::Object::createFromHostObject(runtime, frameHostObject)); } catch (jsi::JSError& jsError) { - NSLog(@"Frame Processor threw an error: %s", jsError.getMessage().c_str()); + auto message = jsError.getMessage(); + + RCTBridge* bridge = [RCTBridge currentBridge]; + if (bridge != nil) { + bridge.jsCallInvoker->invokeAsync([bridge, message]() { + auto logFn = [JSConsoleHelper getLogFunctionForBridge:bridge]; + logFn(RCTLogLevelError, [NSString stringWithFormat:@"Frame Processor threw an error: %s", message.c_str()]); + }); + } else { + NSLog(@"Frame Processor threw an error: %s", message.c_str()); + } } // Manually free the buffer because: