1*26ad19fcSEvan Bacon/**
2*26ad19fcSEvan Bacon * Copyright (c) 650 Industries.
3*26ad19fcSEvan Bacon * Copyright (c) Meta Platforms, Inc. and affiliates.
4*26ad19fcSEvan Bacon *
5*26ad19fcSEvan Bacon * This source code is licensed under the MIT license found in the
6*26ad19fcSEvan Bacon * LICENSE file in the root directory of this source tree.
7*26ad19fcSEvan Bacon */
8*26ad19fcSEvan Bacon
9*26ad19fcSEvan Baconimport parseErrorStack from '../parseErrorStack';
10*26ad19fcSEvan Bacon
11*26ad19fcSEvan Bacontype ExtendedError = any;
12*26ad19fcSEvan Bacon
13*26ad19fcSEvan Baconclass SyntheticError extends Error {
14*26ad19fcSEvan Bacon  name: string = '';
15*26ad19fcSEvan Bacon}
16*26ad19fcSEvan Bacon
17*26ad19fcSEvan Bacon/**
18*26ad19fcSEvan Bacon * Handles the developer-visible aspect of errors and exceptions
19*26ad19fcSEvan Bacon */
20*26ad19fcSEvan Baconlet exceptionID = 0;
21*26ad19fcSEvan Bacon
22*26ad19fcSEvan Baconfunction parseException(e: ExtendedError, isFatal: boolean) {
23*26ad19fcSEvan Bacon  const stack = parseErrorStack(e?.stack);
24*26ad19fcSEvan Bacon  const currentExceptionID = ++exceptionID;
25*26ad19fcSEvan Bacon  const originalMessage = e.message || '';
26*26ad19fcSEvan Bacon  let message = originalMessage;
27*26ad19fcSEvan Bacon  if (e.componentStack != null) {
28*26ad19fcSEvan Bacon    message += `\n\nThis error is located at:${e.componentStack}`;
29*26ad19fcSEvan Bacon  }
30*26ad19fcSEvan Bacon  const namePrefix = e.name == null || e.name === '' ? '' : `${e.name}: `;
31*26ad19fcSEvan Bacon
32*26ad19fcSEvan Bacon  if (!message.startsWith(namePrefix)) {
33*26ad19fcSEvan Bacon    message = namePrefix + message;
34*26ad19fcSEvan Bacon  }
35*26ad19fcSEvan Bacon
36*26ad19fcSEvan Bacon  message = e.jsEngine == null ? message : `${message}, js engine: ${e.jsEngine}`;
37*26ad19fcSEvan Bacon
38*26ad19fcSEvan Bacon  const data = {
39*26ad19fcSEvan Bacon    message,
40*26ad19fcSEvan Bacon    originalMessage: message === originalMessage ? null : originalMessage,
41*26ad19fcSEvan Bacon    name: e.name == null || e.name === '' ? null : e.name,
42*26ad19fcSEvan Bacon    componentStack: typeof e.componentStack === 'string' ? e.componentStack : null,
43*26ad19fcSEvan Bacon    stack,
44*26ad19fcSEvan Bacon    id: currentExceptionID,
45*26ad19fcSEvan Bacon    isFatal,
46*26ad19fcSEvan Bacon    extraData: {
47*26ad19fcSEvan Bacon      jsEngine: e.jsEngine,
48*26ad19fcSEvan Bacon      rawStack: e.stack,
49*26ad19fcSEvan Bacon    },
50*26ad19fcSEvan Bacon  };
51*26ad19fcSEvan Bacon
52*26ad19fcSEvan Bacon  return {
53*26ad19fcSEvan Bacon    ...data,
54*26ad19fcSEvan Bacon    isComponentError: !!e.isComponentError,
55*26ad19fcSEvan Bacon  };
56*26ad19fcSEvan Bacon}
57*26ad19fcSEvan Bacon
58*26ad19fcSEvan Bacon/**
59*26ad19fcSEvan Bacon * Logs exceptions to the (native) console and displays them
60*26ad19fcSEvan Bacon */
61*26ad19fcSEvan Baconfunction handleException(e: any) {
62*26ad19fcSEvan Bacon  let error: Error;
63*26ad19fcSEvan Bacon  if (e instanceof Error) {
64*26ad19fcSEvan Bacon    error = e;
65*26ad19fcSEvan Bacon  } else {
66*26ad19fcSEvan Bacon    // Workaround for reporting errors caused by `throw 'some string'`
67*26ad19fcSEvan Bacon    // Unfortunately there is no way to figure out the stacktrace in this
68*26ad19fcSEvan Bacon    // case, so if you ended up here trying to trace an error, look for
69*26ad19fcSEvan Bacon    // `throw '<error message>'` somewhere in your codebase.
70*26ad19fcSEvan Bacon    error = new SyntheticError(e);
71*26ad19fcSEvan Bacon  }
72*26ad19fcSEvan Bacon
73*26ad19fcSEvan Bacon  require('../../LogBox').default.addException(parseException(error, true));
74*26ad19fcSEvan Bacon}
75*26ad19fcSEvan Bacon
76*26ad19fcSEvan Baconconst ErrorUtils = {
77*26ad19fcSEvan Bacon  parseException,
78*26ad19fcSEvan Bacon  handleException,
79*26ad19fcSEvan Bacon  SyntheticError,
80*26ad19fcSEvan Bacon};
81*26ad19fcSEvan Bacon
82*26ad19fcSEvan Baconexport default ErrorUtils;
83