1 | 'use strict';
|
2 | import type { WorkletStackDetails } from './commonTypes';
|
3 |
|
4 | const _workletStackDetails = new Map<number, WorkletStackDetails>();
|
5 |
|
6 | export function registerWorkletStackDetails(
|
7 | hash: number,
|
8 | stackDetails: WorkletStackDetails
|
9 | ) {
|
10 | _workletStackDetails.set(hash, stackDetails);
|
11 | }
|
12 |
|
13 | function getBundleOffset(error: Error): [string, number, number] {
|
14 | const frame = error.stack?.split('\n')?.[0];
|
15 | if (frame) {
|
16 | const parsedFrame = /@([^@]+):(\d+):(\d+)/.exec(frame);
|
17 | if (parsedFrame) {
|
18 | const [, file, line, col] = parsedFrame;
|
19 | return [file, Number(line), Number(col)];
|
20 | }
|
21 | }
|
22 | return ['unknown', 0, 0];
|
23 | }
|
24 |
|
25 | function processStack(stack: string): string {
|
26 | const workletStackEntries = stack.match(/worklet_(\d+):(\d+):(\d+)/g);
|
27 | let result = stack;
|
28 | workletStackEntries?.forEach((match) => {
|
29 | const [, hash, origLine, origCol] = match.split(/:|_/).map(Number);
|
30 | const errorDetails = _workletStackDetails.get(hash);
|
31 | if (!errorDetails) {
|
32 | return;
|
33 | }
|
34 | const [error, lineOffset, colOffset] = errorDetails;
|
35 | const [bundleFile, bundleLine, bundleCol] = getBundleOffset(error);
|
36 | const line = origLine + bundleLine + lineOffset;
|
37 | const col = origCol + bundleCol + colOffset;
|
38 |
|
39 | result = result.replace(match, `${bundleFile}:${line}:${col}`);
|
40 | });
|
41 | return result;
|
42 | }
|
43 |
|
44 | export function reportFatalErrorOnJS({
|
45 | message,
|
46 | stack,
|
47 | }: {
|
48 | message: string;
|
49 | stack?: string;
|
50 | }) {
|
51 | const error = new Error();
|
52 | error.message = message;
|
53 | error.stack = stack ? processStack(stack) : undefined;
|
54 | error.name = 'ReanimatedError';
|
55 |
|
56 | error.jsEngine = 'reanimated';
|
57 |
|
58 | global.ErrorUtils.reportFatalError(error);
|
59 | }
|