From 7dc84491e9049fa5d8fa6ef3f197e3775fcad8ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 15 Jul 2025 03:45:28 -0700 Subject: [PATCH] Fix reporting of errors without stack traces (#52601) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/52601 Changelog: [internal] Fixes a bug in Fantom when throwing a value that's not an instance of `Error` in a test. Reviewed By: javache Differential Revision: D78332756 fbshipit-source-id: 350479dcb7bcea399070c6851aca76a1d1cc2629 --- private/react-native-fantom/runner/runner.js | 4 +++- private/react-native-fantom/runtime/setup.js | 17 +++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/private/react-native-fantom/runner/runner.js b/private/react-native-fantom/runner/runner.js index 2e9f3cac2b6..d184b1f9cff 100644 --- a/private/react-native-fantom/runner/runner.js +++ b/private/react-native-fantom/runner/runner.js @@ -59,7 +59,9 @@ function buildError( sourceMapPath: string, ): Error { const error = new Error(failureDetail.message); - error.stack = symbolicateStackTrace(sourceMapPath, failureDetail.stack); + if (failureDetail.stack != null) { + error.stack = symbolicateStackTrace(sourceMapPath, failureDetail.stack); + } if (failureDetail.cause != null) { error.cause = buildError(failureDetail.cause, sourceMapPath); } diff --git a/private/react-native-fantom/runtime/setup.js b/private/react-native-fantom/runtime/setup.js index 75ee2a057b3..9a649e46cb1 100644 --- a/private/react-native-fantom/runtime/setup.js +++ b/private/react-native-fantom/runtime/setup.js @@ -30,7 +30,7 @@ export type TestCaseResult = { export type FailureDetail = { message: string, - stack: string, + stack?: string, cause?: FailureDetail, }; @@ -320,7 +320,7 @@ function runSpec(spec: Spec): TestCaseResult { } let status: 'passed' | 'failed' | 'pending'; - let error; + let error: mixed; const start = Date.now(); snapshotContext.setTargetTest(result.fullName); @@ -331,16 +331,21 @@ function runSpec(spec: Spec): TestCaseResult { invokeHooks(spec.parentContext, 'afterEachHooks'); status = 'passed'; - } catch (e) { + } catch (e: mixed) { error = e; status = 'failed'; } result.status = status; result.duration = Date.now() - start; - if (status === 'failed' && error) { - result.failureMessages = [error.stack ?? error.message ?? String(error)]; - result.failureDetails = [serializeError(error)]; + if (status === 'failed' && error != null) { + if (error instanceof Error) { + result.failureMessages = [error.stack ?? error.message ?? String(error)]; + result.failureDetails = [serializeError(error)]; + } else { + result.failureMessages = [`Non-error value thrown: ${String(error)}`]; + result.failureDetails = []; + } } else { result.failureMessages = []; result.failureDetails = [];