1 | 'use strict';
|
2 | import { reportFatalErrorOnJS } from './errors';
|
3 | import { isChromeDebugger, isJest, shouldBeUseWeb } from './PlatformChecker';
|
4 | import {
|
5 | runOnJS,
|
6 | setupMicrotasks,
|
7 | callMicrotasks,
|
8 | runOnUIImmediately,
|
9 | } from './threads';
|
10 | import { mockedRequestAnimationFrame } from './mockedRequestAnimationFrame';
|
11 |
|
12 | const IS_JEST = isJest();
|
13 | const SHOULD_BE_USE_WEB = shouldBeUseWeb();
|
14 | const IS_CHROME_DEBUGGER = isChromeDebugger();
|
15 |
|
16 |
|
17 | export function callGuardDEV<Args extends unknown[], ReturnValue>(
|
18 | fn: (...args: Args) => ReturnValue,
|
19 | ...args: Args
|
20 | ): ReturnValue | void {
|
21 | 'worklet';
|
22 | try {
|
23 | return fn(...args);
|
24 | } catch (e) {
|
25 | if (global.__ErrorUtils) {
|
26 | global.__ErrorUtils.reportFatalError(e as Error);
|
27 | } else {
|
28 | throw e;
|
29 | }
|
30 | }
|
31 | }
|
32 |
|
33 | export function setupCallGuard() {
|
34 | 'worklet';
|
35 | global.__callGuardDEV = callGuardDEV;
|
36 | global.__ErrorUtils = {
|
37 | reportFatalError: (error: Error) => {
|
38 | runOnJS(reportFatalErrorOnJS)({
|
39 | message: error.message,
|
40 | stack: error.stack,
|
41 | });
|
42 | },
|
43 | };
|
44 | }
|
45 |
|
46 |
|
47 |
|
48 | const capturableConsole = { ...console };
|
49 |
|
50 | export function setupConsole() {
|
51 | 'worklet';
|
52 | if (!IS_CHROME_DEBUGGER) {
|
53 |
|
54 | global.console = {
|
55 |
|
56 | assert: runOnJS(capturableConsole.assert),
|
57 | debug: runOnJS(capturableConsole.debug),
|
58 | log: runOnJS(capturableConsole.log),
|
59 | warn: runOnJS(capturableConsole.warn),
|
60 | error: runOnJS(capturableConsole.error),
|
61 | info: runOnJS(capturableConsole.info),
|
62 |
|
63 | };
|
64 | }
|
65 | }
|
66 |
|
67 | function setupRequestAnimationFrame() {
|
68 | 'worklet';
|
69 |
|
70 |
|
71 |
|
72 | const nativeRequestAnimationFrame = global.requestAnimationFrame;
|
73 |
|
74 | let animationFrameCallbacks: Array<(timestamp: number) => void> = [];
|
75 | let lastNativeAnimationFrameTimestamp = -1;
|
76 |
|
77 | global.__flushAnimationFrame = (frameTimestamp: number) => {
|
78 | const currentCallbacks = animationFrameCallbacks;
|
79 | animationFrameCallbacks = [];
|
80 | currentCallbacks.forEach((f) => f(frameTimestamp));
|
81 | callMicrotasks();
|
82 | };
|
83 |
|
84 | global.requestAnimationFrame = (
|
85 | callback: (timestamp: number) => void
|
86 | ): number => {
|
87 | animationFrameCallbacks.push(callback);
|
88 | if (animationFrameCallbacks.length === 1) {
|
89 |
|
90 |
|
91 |
|
92 | nativeRequestAnimationFrame((timestamp) => {
|
93 | if (lastNativeAnimationFrameTimestamp >= timestamp) {
|
94 |
|
95 | return;
|
96 | }
|
97 | lastNativeAnimationFrameTimestamp = timestamp;
|
98 | global.__frameTimestamp = timestamp;
|
99 | global.__flushAnimationFrame(timestamp);
|
100 | global.__frameTimestamp = undefined;
|
101 | });
|
102 | }
|
103 |
|
104 |
|
105 |
|
106 |
|
107 | return -1;
|
108 | };
|
109 | }
|
110 |
|
111 | export function initializeUIRuntime() {
|
112 | if (IS_JEST) {
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 | globalThis.requestAnimationFrame = mockedRequestAnimationFrame;
|
120 | }
|
121 |
|
122 | runOnUIImmediately(() => {
|
123 | 'worklet';
|
124 | setupCallGuard();
|
125 | setupConsole();
|
126 | if (!SHOULD_BE_USE_WEB) {
|
127 | setupMicrotasks();
|
128 | setupRequestAnimationFrame();
|
129 | }
|
130 | })();
|
131 | }
|