1 | 'use strict';
|
2 | import { shouldBeUseWeb } from './PlatformChecker';
|
3 | import { isWorkletFunction } from './commonTypes';
|
4 | import type { WorkletFunction } from './commonTypes';
|
5 |
|
6 | function valueUnpacker(
|
7 | objectToUnpack: any,
|
8 | category?: string,
|
9 | remoteFunctionName?: string
|
10 | ): any {
|
11 | 'worklet';
|
12 | let workletsCache = global.__workletsCache;
|
13 | let handleCache = global.__handleCache;
|
14 | if (workletsCache === undefined) {
|
15 |
|
16 | workletsCache = global.__workletsCache = new Map();
|
17 | handleCache = global.__handleCache = new WeakMap();
|
18 | }
|
19 | const workletHash = objectToUnpack.__workletHash;
|
20 | if (workletHash !== undefined) {
|
21 | let workletFun = workletsCache.get(workletHash);
|
22 | if (workletFun === undefined) {
|
23 | const initData = objectToUnpack.__initData;
|
24 | if (global.evalWithSourceMap) {
|
25 |
|
26 |
|
27 |
|
28 |
|
29 | workletFun = global.evalWithSourceMap(
|
30 | '(' + initData.code + '\n)',
|
31 | initData.location,
|
32 | initData.sourceMap
|
33 | ) as (...args: any[]) => any;
|
34 | } else if (global.evalWithSourceUrl) {
|
35 |
|
36 |
|
37 |
|
38 |
|
39 | workletFun = global.evalWithSourceUrl(
|
40 | '(' + initData.code + '\n)',
|
41 | `worklet_${workletHash}`
|
42 | ) as (...args: any[]) => any;
|
43 | } else {
|
44 |
|
45 |
|
46 | workletFun = eval('(' + initData.code + '\n)') as (
|
47 | ...args: any[]
|
48 | ) => any;
|
49 | }
|
50 | workletsCache.set(workletHash, workletFun);
|
51 | }
|
52 | const functionInstance = workletFun.bind(objectToUnpack);
|
53 | objectToUnpack._recur = functionInstance;
|
54 | return functionInstance;
|
55 | } else if (objectToUnpack.__init !== undefined) {
|
56 | let value = handleCache.get(objectToUnpack);
|
57 | if (value === undefined) {
|
58 | value = objectToUnpack.__init();
|
59 | handleCache.set(objectToUnpack, value);
|
60 | }
|
61 | return value;
|
62 | } else if (category === 'RemoteFunction') {
|
63 | const fun = () => {
|
64 | const label = remoteFunctionName
|
65 | ? `function \`${remoteFunctionName}\``
|
66 | : 'anonymous function';
|
67 | throw new Error(`[Reanimated] Tried to synchronously call a non-worklet ${label} on the UI thread.
|
68 | See https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooting#tried-to-synchronously-call-a-non-worklet-function-on-the-ui-thread for more details.`);
|
69 | };
|
70 | fun.__remoteFunction = objectToUnpack;
|
71 | return fun;
|
72 | } else {
|
73 | throw new Error(
|
74 | `[Reanimated] Data type in category "${category}" not recognized by value unpacker: "${_toString(
|
75 | objectToUnpack
|
76 | )}".`
|
77 | );
|
78 | }
|
79 | }
|
80 |
|
81 | type ValueUnpacker = WorkletFunction<
|
82 | [objectToUnpack: any, category?: string],
|
83 | any
|
84 | >;
|
85 |
|
86 | if (__DEV__ && !shouldBeUseWeb()) {
|
87 | const testWorklet = (() => {
|
88 | 'worklet';
|
89 | }) as WorkletFunction<[], void>;
|
90 | if (!isWorkletFunction(testWorklet)) {
|
91 | throw new Error(
|
92 | `[Reanimated] Failed to create a worklet. See https:
|
93 | );
|
94 | }
|
95 | if (!isWorkletFunction(valueUnpacker)) {
|
96 | throw new Error('[Reanimated] `valueUnpacker` is not a worklet');
|
97 | }
|
98 | const closure = (valueUnpacker as ValueUnpacker).__closure;
|
99 | if (closure === undefined) {
|
100 | throw new Error('[Reanimated] `valueUnpacker` closure is undefined');
|
101 | }
|
102 | if (Object.keys(closure).length !== 0) {
|
103 | throw new Error('[Reanimated] `valueUnpacker` must have empty closure');
|
104 | }
|
105 | }
|
106 |
|
107 | export function getValueUnpackerCode() {
|
108 | return (valueUnpacker as ValueUnpacker).__initData.code;
|
109 | }
|
110 |
|
\ | No newline at end of file |