Fixes LogBox displaying "Unknown" when an exception is thrown from an…#56000
Fixes LogBox displaying "Unknown" when an exception is thrown from an…#56000Adityakk9031 wants to merge 1 commit intofacebook:mainfrom
Conversation
… extra Hermes Runtime
|
Hi @Adityakk9031! Thank you for your pull request and welcome to our community. Action RequiredIn order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you. ProcessIn order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA. Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks! |
|
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks! |
|
@christophpurrer sir please have a look |
Fixes #55913
Root cause
RuntimeScheduler_Modern::executeTask catches jsi::JSError and forwards it to
handleJSError
via onTaskError_. Inside
handleJSError
(ErrorUtils.h:34), the error is reported to JS via:
cpp
func.call(runtime, error.value());
error.value() returns a jsi::Value — a JS Error object — that belongs to the source (extra) Hermes runtime's heap. When passed as an argument into the main runtime, Hermes sees a foreign heap object. The result is
undefined
or an invalid value on the JS side, which is why LogBox's error parser displays "Unknown" instead of the real message.
The previously attempted fix (jsi::JSError errorCopy(runtime, msg, stack)) also failed because the
JSError(Runtime&, string, string)
constructor creates a plain {} object rather than a new Error(). This means instanceof Error is false and LogBox's parseErrorStack cannot pick up the stack frames correctly.
Fix
In both
executeTask
and
performMicrotaskCheckpoint
, when a jsi::JSError is caught, we now:
Extract getMessage() and getStack() — these are plain std::string values already copied out of the source runtime at throw time, so they are safely portable.
Call new Error(message) in the main runtime via
callAsConstructor
— this produces a proper Error instance with the correct prototype chain (instanceof Error === true).
Override .stack on the new object with the original (cross-runtime) stack string.
Wrap in jsi::JSError(Value&&, string, string) — the constructor that stores values directly without calling
setValue()
to re-read properties, eliminating any remaining cross-runtime JSI access.
Fall back to a plain-string error if reconstruction itself fails (e.g. runtime not yet fully initialized).
Changelog:
[IOS] [FIXED] - Fix LogBox showing "Unknown" for errors thrown from extra Hermes Runtimes by reconstructing the Error in the correct runtime before forwarding to ErrorUtils
Test Plan:
Using NativeCxxModuleExample in RN Tester, create an extra Hermes Runtime and throw a JS error from it:
cpp
auto extraRuntime = facebook::hermes::makeHermesRuntime();
extraRuntime->evaluateJavaScript(
std::make_sharedjsi::StringBuffer(
"throw new Error('hello from extra runtime')"),
"extra_runtime_test.js");
Before this fix: LogBox shows Uncaught Error · message: "Unknown" · broken call stack.
After this fix: LogBox shows the correct error message and the original stack trace from the extra runtime.