Skip to content
2 changes: 2 additions & 0 deletions packages/react-native/Libraries/LogBox/Data/LogBoxData.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export type LogData = $ReadOnly<{|
message: Message,
category: Category,
componentStack: ComponentStack,
codeFrame?: string,
|}>;

export type Observer = (
Expand Down Expand Up @@ -208,6 +209,7 @@ export function addLog(log: LogData): void {
stack,
category: log.category,
componentStack: log.componentStack,
codeFrame: log.codeFrame,
}),
);
} catch (error) {
Expand Down
35 changes: 33 additions & 2 deletions packages/react-native/Libraries/promiseRejectionTrackingOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@

import typeof {enable} from 'promise/setimmediate/rejection-tracking';

let rejectionTrackingOptions: $NonMaybeType<Parameters<enable>[0]> = {
type ExtractOptionsType = <P>(((options?: ?P) => void)) => P;

let rejectionTrackingOptions: $Call<ExtractOptionsType, enable> = {
allRejections: true,
onUnhandled: (id, rejection = {}) => {
onUnhandled: async (id, rejection = {}) => {
let message: string;
let stack: ?string;

Expand All @@ -22,6 +24,35 @@ let rejectionTrackingOptions: $NonMaybeType<Parameters<enable>[0]> = {
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
message = Error.prototype.toString.call(rejection);
const error: Error = (rejection: $FlowFixMe);

// Print pretty unhandled rejections while on DEV
if (__DEV__) {
const parseErrorStack = require('react-native/Libraries/Core/Devtools/parseErrorStack');
const symbolicateStackTrace = require('react-native/Libraries/Core/Devtools/symbolicateStackTrace');
const LogBox = require('react-native/Libraries/LogBox/LogBox').default;

stack = parseErrorStack(error.stack);
stack = await symbolicateStackTrace(stack);
if (stack) {
const warning =
`Possible Unhandled Promise Rejection (id: ${id}):\n` +
`${message ?? ''}\n` +
`at File: ${stack.codeFrame.fileName}, row: ${stack.codeFrame.location.row}, column: ${stack.codeFrame.location.column}`;

console.log(stack.codeFrame.content)

LogBox.addLog({
level: 'warn',
message: {content: warning, substitutions: []},
isComponentError: false,
codeFrame: stack.codeFrame,
stack: error.stack,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we just pass the symbolicated stack variable here instead of the original obfuscated error.stack?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logbox already supports doing the symbolication, can we leverage the logic there?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you provide more context on how to do that? I can see that he already provided it with the error.stack but still the correct first frame wasn't shown

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may need to use LogBox.addException for this, and update parseLogBoxException to treat these as non-fatal

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ospfranco can you please give this a try?

Copy link
Contributor Author

@ospfranco ospfranco Oct 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, doesn't seem to be working, didn't change the level yet, but stack parsing doesn't seem to work.

category: `${stack.codeFrame.fileName}-${stack.codeFrame.location.row}-${stack.codeFrame.location.column}`,
});
return;
}
}

stack = error.stack;
} else {
try {
Expand Down