1 | 'use strict';
|
2 |
|
3 | import { shouldBeUseWeb } from "./PlatformChecker.js";
|
4 | import { ReanimatedError } from "./errors.js";
|
5 | import { logger } from "./logger/index.js";
|
6 | import { isFirstReactRender, isReactRendering } from "./reactUtils.js";
|
7 | import { shareableMappingCache } from "./shareableMappingCache.js";
|
8 | import { makeShareableCloneRecursive } from "./shareables.js";
|
9 | import { executeOnUIRuntimeSync, runOnUI } from "./threads.js";
|
10 | import { valueSetter } from "./valueSetter.js";
|
11 | const SHOULD_BE_USE_WEB = shouldBeUseWeb();
|
12 | function shouldWarnAboutAccessDuringRender() {
|
13 | return __DEV__ && isReactRendering() && !isFirstReactRender();
|
14 | }
|
15 | function checkInvalidReadDuringRender() {
|
16 | if (shouldWarnAboutAccessDuringRender()) {
|
17 | logger.warn('Reading from `value` during component render. Please ensure that you do not access the `value` property or use `get` method of a shared value while React is rendering a component.', {
|
18 | strict: true
|
19 | });
|
20 | }
|
21 | }
|
22 | function checkInvalidWriteDuringRender() {
|
23 | if (shouldWarnAboutAccessDuringRender()) {
|
24 | logger.warn('Writing to `value` during component render. Please ensure that you do not access the `value` property or use `set` method of a shared value while React is rendering a component.', {
|
25 | strict: true
|
26 | });
|
27 | }
|
28 | }
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 | function addCompilerSafeGetAndSet(mutable) {
|
39 | 'worklet';
|
40 |
|
41 | Object.defineProperties(mutable, {
|
42 | get: {
|
43 | value() {
|
44 | return mutable.value;
|
45 | },
|
46 | configurable: false,
|
47 | enumerable: false
|
48 | },
|
49 | set: {
|
50 | value(newValue) {
|
51 | if (typeof newValue === 'function') {
|
52 | mutable.value = newValue(mutable.value);
|
53 | } else {
|
54 | mutable.value = newValue;
|
55 | }
|
56 | },
|
57 | configurable: false,
|
58 | enumerable: false
|
59 | }
|
60 | });
|
61 | }
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 | function hideInternalValueProp(mutable) {
|
76 | 'worklet';
|
77 |
|
78 | Object.defineProperty(mutable, '_value', {
|
79 | configurable: false,
|
80 | enumerable: false
|
81 | });
|
82 | }
|
83 | export function makeMutableUI(initial) {
|
84 | 'worklet';
|
85 |
|
86 | const listeners = new Map();
|
87 | let value = initial;
|
88 | const mutable = {
|
89 | get value() {
|
90 | return value;
|
91 | },
|
92 | set value(newValue) {
|
93 | valueSetter(mutable, newValue);
|
94 | },
|
95 | get _value() {
|
96 | return value;
|
97 | },
|
98 | set _value(newValue) {
|
99 | value = newValue;
|
100 | listeners.forEach(listener => {
|
101 | listener(newValue);
|
102 | });
|
103 | },
|
104 | modify: (modifier, forceUpdate = true) => {
|
105 | valueSetter(mutable, modifier !== undefined ? modifier(value) : value, forceUpdate);
|
106 | },
|
107 | addListener: (id, listener) => {
|
108 | listeners.set(id, listener);
|
109 | },
|
110 | removeListener: id => {
|
111 | listeners.delete(id);
|
112 | },
|
113 | _animation: null,
|
114 | _isReanimatedSharedValue: true
|
115 | };
|
116 | hideInternalValueProp(mutable);
|
117 | addCompilerSafeGetAndSet(mutable);
|
118 | return mutable;
|
119 | }
|
120 | function makeMutableNative(initial) {
|
121 | const handle = makeShareableCloneRecursive({
|
122 | __init: () => {
|
123 | 'worklet';
|
124 |
|
125 | return makeMutableUI(initial);
|
126 | }
|
127 | });
|
128 | const mutable = {
|
129 | get value() {
|
130 | checkInvalidReadDuringRender();
|
131 | const uiValueGetter = executeOnUIRuntimeSync(sv => {
|
132 | return sv.value;
|
133 | });
|
134 | return uiValueGetter(mutable);
|
135 | },
|
136 | set value(newValue) {
|
137 | checkInvalidWriteDuringRender();
|
138 | runOnUI(() => {
|
139 | mutable.value = newValue;
|
140 | })();
|
141 | },
|
142 | get _value() {
|
143 | throw new ReanimatedError('Reading from `_value` directly is only possible on the UI runtime. Perhaps you passed an Animated Style to a non-animated component?');
|
144 | },
|
145 | set _value(_newValue) {
|
146 | throw new ReanimatedError('Setting `_value` directly is only possible on the UI runtime. Perhaps you want to assign to `value` instead?');
|
147 | },
|
148 | modify: (modifier, forceUpdate = true) => {
|
149 | runOnUI(() => {
|
150 | mutable.modify(modifier, forceUpdate);
|
151 | })();
|
152 | },
|
153 | addListener: () => {
|
154 | throw new ReanimatedError('Adding listeners is only possible on the UI runtime.');
|
155 | },
|
156 | removeListener: () => {
|
157 | throw new ReanimatedError('Removing listeners is only possible on the UI runtime.');
|
158 | },
|
159 | _isReanimatedSharedValue: true
|
160 | };
|
161 | hideInternalValueProp(mutable);
|
162 | addCompilerSafeGetAndSet(mutable);
|
163 | shareableMappingCache.set(mutable, handle);
|
164 | return mutable;
|
165 | }
|
166 | function makeMutableWeb(initial) {
|
167 | let value = initial;
|
168 | const listeners = new Map();
|
169 | const mutable = {
|
170 | get value() {
|
171 | checkInvalidReadDuringRender();
|
172 | return value;
|
173 | },
|
174 | set value(newValue) {
|
175 | checkInvalidWriteDuringRender();
|
176 | valueSetter(mutable, newValue);
|
177 | },
|
178 | get _value() {
|
179 | return value;
|
180 | },
|
181 | set _value(newValue) {
|
182 | value = newValue;
|
183 | listeners.forEach(listener => {
|
184 | listener(newValue);
|
185 | });
|
186 | },
|
187 | modify: (modifier, forceUpdate = true) => {
|
188 | valueSetter(mutable, modifier !== undefined ? modifier(mutable.value) : mutable.value, forceUpdate);
|
189 | },
|
190 | addListener: (id, listener) => {
|
191 | listeners.set(id, listener);
|
192 | },
|
193 | removeListener: id => {
|
194 | listeners.delete(id);
|
195 | },
|
196 | _isReanimatedSharedValue: true
|
197 | };
|
198 | hideInternalValueProp(mutable);
|
199 | addCompilerSafeGetAndSet(mutable);
|
200 | return mutable;
|
201 | }
|
202 | export const makeMutable = SHOULD_BE_USE_WEB ? makeMutableWeb : makeMutableNative;
|
203 |
|
\ | No newline at end of file |