@shopify/react-native-skia 0.1.145 → 0.1.146

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,10 +2,12 @@
2
2
 
3
3
  #include <functional>
4
4
  #include <memory>
5
+ #include <mutex>
5
6
  #include <string>
6
7
  #include <vector>
7
8
 
8
9
  #include <JsiHostObject.h>
10
+ #include <JsiValueWrapper.h>
9
11
  #include <RNSkDrawView.h>
10
12
  #include <RNSkPlatformContext.h>
11
13
  #include <RNSkValue.h>
@@ -14,96 +16,143 @@
14
16
  namespace RNSkia {
15
17
  using namespace facebook;
16
18
 
17
- using CallbackInfo = struct CallbackInfo {
18
- CallbackInfo() {
19
- drawCallback = nullptr;
19
+ using RNSkViewInfo = struct RNSkViewInfo {
20
+ RNSkViewInfo() {
20
21
  view = nullptr;
21
22
  }
22
- std::shared_ptr<FunctionWrapper> drawCallback;
23
23
  std::shared_ptr<RNSkDrawView> view;
24
+ std::unordered_map<std::string, JsiValueWrapper> props;
24
25
  };
25
26
 
26
- class RNSkJsiViewApi : public JsiHostObject {
27
+ class RNSkJsiViewApi : public JsiHostObject, public std::enable_shared_from_this<RNSkJsiViewApi> {
27
28
  public:
28
- JSI_HOST_FUNCTION(setDrawCallback) {
29
- if (count != 2) {
29
+ /**
30
+ Sets a custom property on a view given a view id. The property name/value will
31
+ be stored in a map alongside the id of the view and propagated to the view when
32
+ needed.
33
+ */
34
+ JSI_HOST_FUNCTION(setJsiProperty) {
35
+ if (count != 3) {
30
36
  _platformContext->raiseError(
31
- std::string("setDrawCallback: Expected 2 arguments, got " +
37
+ std::string("setJsiProperty: Expected 3 arguments, got " +
32
38
  std::to_string(count) + "."));
33
39
  return jsi::Value::undefined();
34
40
  }
35
41
 
36
42
  if (!arguments[0].isNumber()) {
37
43
  _platformContext->raiseError(
38
- "setDrawCallback: First argument must be a number");
44
+ "setJsiProperty: First argument must be a number");
39
45
  return jsi::Value::undefined();
40
46
  }
41
47
 
42
- // We accept undefined to zero out the drawCallback
43
- if (!arguments[1].isUndefined()) {
44
- if (!arguments[1].isObject()) {
45
- _platformContext->raiseError(
46
- "setDrawCallback: Second argument must be a function");
47
- return jsi::Value::undefined();
48
- }
49
- if (!arguments[1].asObject(runtime).isFunction(runtime)) {
50
- _platformContext->raiseError(
51
- "setDrawCallback: Second argument must be a function");
52
- return jsi::Value::undefined();
53
- }
54
- }
55
-
56
- // find skia draw view
57
- int nativeId = arguments[0].asNumber();
48
+ if (!arguments[1].isString()) {
49
+ _platformContext->raiseError(
50
+ "setJsiProperty: Second argument must be the name of the property to set.");
58
51
 
59
- // and function to install as the draw drawCallback
60
- auto info = getEnsuredCallbackInfo(nativeId);
61
- if (arguments[1].isUndefined()) {
62
- info->drawCallback = nullptr;
63
- } else {
64
- info->drawCallback = std::make_shared<FunctionWrapper>(
65
- arguments[1].asObject(runtime).asFunction(runtime));
52
+ return jsi::Value::undefined();
66
53
  }
54
+ auto nativeId = arguments[0].asNumber();
55
+ auto info = getEnsuredViewInfo(nativeId);
67
56
 
68
- // Update view if set
69
- if (info->view != nullptr && info->drawCallback != nullptr) {
57
+ std::lock_guard<std::mutex> lock(_mutex);
58
+ info->props.emplace(arguments[1].asString(runtime).utf8(runtime), JsiValueWrapper(runtime, arguments[2]));
59
+
60
+ // Now let's see if we have a view that we can update
61
+ if(info->view != nullptr) {
62
+ // Update view!
70
63
  info->view->setNativeId(nativeId);
71
- info->view->setDrawCallback(info->drawCallback);
64
+ info->view->setJsiProperties(info->props);
65
+ info->props.clear();
72
66
  }
73
67
 
74
68
  return jsi::Value::undefined();
75
69
  }
76
70
 
77
- JSI_HOST_FUNCTION(invalidateSkiaView) {
78
- if (count != 1) {
71
+ /**
72
+ Calls a custom command / method on a view by the view id.
73
+ */
74
+ JSI_HOST_FUNCTION(callJsiMethod) {
75
+ if (count < 2) {
79
76
  _platformContext->raiseError(
80
- std::string("invalidateSkiaView: Expected 2 arguments, got " +
77
+ std::string("callCustomCommand: Expected at least 2 arguments, got " +
81
78
  std::to_string(count) + "."));
79
+
82
80
  return jsi::Value::undefined();
83
81
  }
84
82
 
85
83
  if (!arguments[0].isNumber()) {
86
84
  _platformContext->raiseError(
87
- "invalidateSkiaView: First argument must be a number");
85
+ "callCustomCommand: First argument must be a number");
86
+
88
87
  return jsi::Value::undefined();
89
88
  }
90
89
 
91
- // find skia draw view
92
- int nativeId = arguments[0].asNumber();
90
+ if (!arguments[1].isString()) {
91
+ _platformContext->raiseError(
92
+ "callCustomCommand: Second argument must be the name of the action to call.");
93
93
 
94
- auto info = getEnsuredCallbackInfo(nativeId);
95
- if (info->view != nullptr) {
96
- info->view->requestRedraw();
94
+ return jsi::Value::undefined();
97
95
  }
98
- return jsi::Value::undefined();
96
+
97
+ auto nativeId = arguments[0].asNumber();
98
+ auto action = arguments[1].asString(runtime).utf8(runtime);
99
+
100
+ auto info = getEnsuredViewInfo(nativeId);
101
+
102
+ if(info->view == nullptr) {
103
+ throw jsi::JSError(runtime,
104
+ std::string("callCustomCommand: Could not call action " + action +
105
+ " on view - view not ready.").c_str());
106
+
107
+ return jsi::Value::undefined();
108
+ }
109
+
110
+ // Get arguments
111
+ size_t paramsCount = count - 2;
112
+ const jsi::Value* params = paramsCount > 0 ? &arguments[2] : nullptr;
113
+ return info->view->callJsiMethod(runtime, action, params, paramsCount);
99
114
  }
100
-
115
+
116
+ JSI_HOST_FUNCTION(requestRedraw) {
117
+ if (count < 2) {
118
+ _platformContext->raiseError(
119
+ std::string("requestRedraw: Expected 2 arguments, got " + std::to_string(count) + "."));
120
+
121
+ return jsi::Value::undefined();
122
+ }
123
+
124
+ if (!arguments[0].isNumber()) {
125
+ _platformContext->raiseError(
126
+ "requestRedraw: First argument must be a number");
127
+
128
+ return jsi::Value::undefined();
129
+ }
130
+
131
+ // find Skia View
132
+ int nativeId = arguments[0].asNumber();
133
+
134
+ auto info = getEnsuredViewInfo(nativeId);
135
+ if (info->view != nullptr) {
136
+ info->view->requestRedraw();
137
+ }
138
+ return jsi::Value::undefined();
139
+ }
140
+
101
141
  JSI_HOST_FUNCTION(makeImageSnapshot) {
102
-
103
- // find skia draw view
142
+ if (count < 1) {
143
+ _platformContext->raiseError(std::string("makeImageSnapshot: Expected at least 1 argument, got " + std::to_string(count) + "."));
144
+ return jsi::Value::undefined();
145
+ }
146
+
147
+ if (!arguments[0].isNumber()) {
148
+ _platformContext->raiseError("makeImageSnapshot: First argument must be a number");
149
+ return jsi::Value::undefined();
150
+ }
151
+
152
+ // find Skia view
104
153
  int nativeId = arguments[0].asNumber();
105
154
  sk_sp<SkImage> image;
106
- auto info = getEnsuredCallbackInfo(nativeId);
155
+ auto info = getEnsuredViewInfo(nativeId);
107
156
  if (info->view != nullptr) {
108
157
  if(count > 1 && !arguments[1].isUndefined() && !arguments[1].isNull()) {
109
158
  auto rect = JsiSkRect::fromValue(runtime, arguments[1]);
@@ -112,88 +161,66 @@ public:
112
161
  image = info->view->makeImageSnapshot(nullptr);
113
162
  }
114
163
  if(image == nullptr) {
115
- jsi::detail::throwJSError(runtime, "Could not create image from current surface.");
164
+ throw jsi::JSError(runtime, "Could not create image from current surface.");
116
165
  return jsi::Value::undefined();
117
166
  }
118
167
  return jsi::Object::createFromHostObject(runtime, std::make_shared<JsiSkImage>(_platformContext, image));
119
168
  }
120
- jsi::detail::throwJSError(runtime, "No Skia View currently available.");
169
+ throw jsi::JSError(runtime, "No Skia View currently available.");
121
170
  return jsi::Value::undefined();
122
171
  }
123
-
124
- JSI_HOST_FUNCTION(setDrawMode) {
125
- if (count != 2) {
126
- _platformContext->raiseError(
127
- std::string("setDrawMode: Expected 2 arguments, got " +
128
- std::to_string(count) + "."));
129
- return jsi::Value::undefined();
130
- }
131
172
 
132
- if (!arguments[0].isNumber()) {
133
- _platformContext->raiseError(
134
- "setDrawMode: First argument must be a number");
135
- return jsi::Value::undefined();
136
- }
137
-
138
- // find skia draw view
139
- int nativeId = arguments[0].asNumber();
140
- auto info = getEnsuredCallbackInfo(nativeId);
141
- if (info->view != nullptr) {
142
- auto nextMode = arguments[1].asString(runtime).utf8(runtime);
143
- if(nextMode.compare("continuous") == 0) {
144
- info->view->setDrawingMode(RNSkDrawingMode::Continuous);
145
- } else {
146
- info->view->setDrawingMode(RNSkDrawingMode::Default);
147
- }
148
- }
149
- return jsi::Value::undefined();
150
- }
151
-
152
173
  JSI_HOST_FUNCTION(registerValuesInView) {
153
- // Check params
154
- if(!arguments[1].isObject() || !arguments[1].asObject(runtime).isArray(runtime)) {
155
- jsi::detail::throwJSError(runtime, "Expected array of Values as second parameter");
156
- return jsi::Value::undefined();
157
- }
158
-
159
- // Get identifier of native SkiaView
160
- int nativeId = arguments[0].asNumber();
161
-
162
- // Get values that should be added as dependencies
163
- auto values = arguments[1].asObject(runtime).asArray(runtime);
164
- std::vector<std::function<void()>> unsubscribers;
165
- const std::size_t size = values.size(runtime);
166
- unsubscribers.reserve(size);
167
- for(size_t i=0; i<size; ++i) {
168
- auto value = values.getValueAtIndex(runtime, i).asObject(runtime).asHostObject<RNSkReadonlyValue>(runtime);
169
-
170
- if(value != nullptr) {
171
- // Add change listener
172
- unsubscribers.push_back(value->addListener([this, nativeId](jsi::Runtime&){
173
- requestRedrawView(nativeId);
174
- }));
174
+ // Check params
175
+ if(!arguments[1].isObject() || !arguments[1].asObject(runtime).isArray(runtime)) {
176
+ throw jsi::JSError(runtime, "Expected array of Values as second parameter");
177
+ return jsi::Value::undefined();
175
178
  }
176
- }
177
-
178
- // Return unsubscribe method that unsubscribes to all values
179
- // that we subscribed to.
180
- return jsi::Function::createFromHostFunction(runtime,
181
- jsi::PropNameID::forUtf8(runtime, "unsubscribe"),
182
- 0,
183
- JSI_HOST_FUNCTION_LAMBDA {
184
- // decrease dependency count on the Skia View
185
- for(auto &unsub : unsubscribers) {
186
- unsub();
179
+
180
+ // Get identifier of native SkiaView
181
+ int nativeId = arguments[0].asNumber();
182
+
183
+ // Get values that should be added as dependencies
184
+ auto values = arguments[1].asObject(runtime).asArray(runtime);
185
+ std::vector<std::function<void()>> unsubscribers;
186
+ const std::size_t size = values.size(runtime);
187
+ unsubscribers.reserve(size);
188
+ for(size_t i=0; i<size; ++i) {
189
+ auto value = values.getValueAtIndex(runtime, i).asObject(runtime).asHostObject<RNSkReadonlyValue>(runtime);
190
+
191
+ if(value != nullptr) {
192
+ // Add change listener
193
+ unsubscribers.push_back(value->addListener([weakSelf = weak_from_this(), nativeId](jsi::Runtime&){
194
+ auto self = weakSelf.lock();
195
+ if(self) {
196
+ auto info = self->getEnsuredViewInfo(nativeId);
197
+ if(info->view != nullptr) {
198
+ info->view->requestRedraw();
199
+ }
200
+ }
201
+ }));
202
+ }
187
203
  }
188
- return jsi::Value::undefined();
189
- });
190
- }
191
-
192
- JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkJsiViewApi, setDrawCallback),
193
- JSI_EXPORT_FUNC(RNSkJsiViewApi, invalidateSkiaView),
194
- JSI_EXPORT_FUNC(RNSkJsiViewApi, makeImageSnapshot),
195
- JSI_EXPORT_FUNC(RNSkJsiViewApi, setDrawMode),
196
- JSI_EXPORT_FUNC(RNSkJsiViewApi, registerValuesInView))
204
+
205
+ // Return unsubscribe method that unsubscribes to all values
206
+ // that we subscribed to.
207
+ return jsi::Function::createFromHostFunction(runtime,
208
+ jsi::PropNameID::forUtf8(runtime, "unsubscribe"),
209
+ 0,
210
+ JSI_HOST_FUNCTION_LAMBDA {
211
+ // decrease dependency count on the Skia View
212
+ for(auto &unsub : unsubscribers) {
213
+ unsub();
214
+ }
215
+ return jsi::Value::undefined();
216
+ });
217
+ }
218
+
219
+ JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkJsiViewApi, setJsiProperty),
220
+ JSI_EXPORT_FUNC(RNSkJsiViewApi, callJsiMethod),
221
+ JSI_EXPORT_FUNC(RNSkJsiViewApi, registerValuesInView),
222
+ JSI_EXPORT_FUNC(RNSkJsiViewApi, requestRedraw),
223
+ JSI_EXPORT_FUNC(RNSkJsiViewApi, makeImageSnapshot))
197
224
 
198
225
  /**
199
226
  * Constructor
@@ -203,7 +230,7 @@ public:
203
230
  : JsiHostObject(), _platformContext(platformContext) {}
204
231
 
205
232
  /**
206
- * Invalidates the api object
233
+ * Invalidates the Skia View Api object
207
234
  */
208
235
  void invalidate() {
209
236
  unregisterAll();
@@ -214,11 +241,12 @@ public:
214
241
  */
215
242
  void unregisterAll() {
216
243
  // Unregister all views
217
- auto tempList = _callbackInfos;
244
+ auto tempList = _viewInfos;
218
245
  for (const auto& info : tempList) {
219
246
  unregisterSkiaDrawView(info.first);
220
247
  }
221
- _callbackInfos.clear();
248
+ std::lock_guard<std::mutex> lock(_mutex);
249
+ _viewInfos.clear();
222
250
  }
223
251
 
224
252
  /**
@@ -227,12 +255,12 @@ public:
227
255
  * @param view View to register
228
256
  */
229
257
  void registerSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view) {
230
- auto info = getEnsuredCallbackInfo(nativeId);
258
+ auto info = getEnsuredViewInfo(nativeId);
259
+ std::lock_guard<std::mutex> lock(_mutex);
231
260
  info->view = view;
232
- if (info->drawCallback != nullptr) {
233
- info->view->setNativeId(nativeId);
234
- info->view->setDrawCallback(info->drawCallback);
235
- }
261
+ info->view->setNativeId(nativeId);
262
+ info->view->setJsiProperties(info->props);
263
+ info->props.clear();
236
264
  }
237
265
 
238
266
  /**
@@ -240,37 +268,34 @@ public:
240
268
  * @param nativeId View id
241
269
  */
242
270
  void unregisterSkiaDrawView(size_t nativeId) {
243
- if (_callbackInfos.count(nativeId) == 0) {
271
+ if (_viewInfos.count(nativeId) == 0) {
244
272
  return;
245
273
  }
246
- auto info = getEnsuredCallbackInfo(nativeId);
247
- if (info->view != nullptr) {
248
- info->view->setDrawCallback(nullptr);
249
- }
274
+ auto info = getEnsuredViewInfo(nativeId);
275
+
276
+ std::lock_guard<std::mutex> lock(_mutex);
250
277
  info->view = nullptr;
251
- info->drawCallback = nullptr;
252
- _callbackInfos.erase(nativeId);
278
+ _viewInfos.erase(nativeId);
253
279
  }
254
-
280
+
255
281
  /**
256
282
  Sets a skia draw view for the given id. This function can be used
257
283
  to mark that an underlying SkiaView is not available (it could be
258
284
  removed due to ex. a transition). The view can be set to a nullptr
259
- or a valid view, effectively toggling the view's availability. If
260
- a valid view is set, the setDrawCallback method is called on the
261
- view (if a valid callback exists).
285
+ or a valid view, effectively toggling the view's availability.
262
286
  */
263
287
  void setSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view) {
264
- if (_callbackInfos.find(nativeId) == _callbackInfos.end()) {
288
+ if (_viewInfos.find(nativeId) == _viewInfos.end()) {
265
289
  return;
266
290
  }
267
- auto info = getEnsuredCallbackInfo(nativeId);
268
- if (view != nullptr && info->drawCallback != nullptr) {
291
+ auto info = getEnsuredViewInfo(nativeId);
292
+ std::lock_guard<std::mutex> lock(_mutex);
293
+ if (view != nullptr) {
269
294
  info->view = view;
270
295
  info->view->setNativeId(nativeId);
271
- info->view->setDrawCallback(info->drawCallback);
272
- } else if(view == nullptr && info->drawCallback != nullptr) {
273
- info->view->setDrawCallback(nullptr);
296
+ info->view->setJsiProperties(info->props);
297
+ info->props.clear();
298
+ } else if(view == nullptr) {
274
299
  info->view = view;
275
300
  }
276
301
  }
@@ -281,28 +306,17 @@ private:
281
306
  * @param nativeId View id
282
307
  * @return The callback info object for the requested view
283
308
  */
284
- CallbackInfo *getEnsuredCallbackInfo(size_t nativeId) {
285
- if (_callbackInfos.count(nativeId) == 0) {
286
- CallbackInfo info;
287
- _callbackInfos.emplace(nativeId, info);
288
- }
289
- return &_callbackInfos.at(nativeId);
290
- }
291
-
292
- /**
293
- Send a redraw request to the view
294
- */
295
- void requestRedrawView(size_t nativeId) {
296
- auto info = getEnsuredCallbackInfo(nativeId);
297
- if(info->view != nullptr) {
298
- info->view->requestRedraw();
309
+ RNSkViewInfo *getEnsuredViewInfo(size_t nativeId) {
310
+ if (_viewInfos.count(nativeId) == 0) {
311
+ RNSkViewInfo info;
312
+ std::lock_guard<std::mutex> lock(_mutex);
313
+ _viewInfos.emplace(nativeId, info);
299
314
  }
315
+ return &_viewInfos.at(nativeId);
300
316
  }
301
-
302
- // List of callbacks
303
- std::unordered_map<size_t, CallbackInfo> _callbackInfos;
304
-
305
- // Platform context
317
+
318
+ std::unordered_map<size_t, RNSkViewInfo> _viewInfos;
306
319
  std::shared_ptr<RNSkPlatformContext> _platformContext;
320
+ std::mutex _mutex;
307
321
  };
308
322
  } // namespace RNSkia
@@ -31,32 +31,32 @@ public:
31
31
  // Verify input
32
32
  if(!arguments[0].isObject() ||
33
33
  !arguments[0].asObject(runtime).isFunction(runtime)) {
34
- jsi::detail::throwJSError(runtime, "Expected callback function as first parameter");
34
+ throw jsi::JSError(runtime, "Expected callback function as first parameter");
35
35
  }
36
-
36
+
37
37
  if(!arguments[1].isObject() ||
38
38
  !arguments[1].asObject(runtime).isArray(runtime)) {
39
- jsi::detail::throwJSError(runtime, "Expected array of dependencies as second parameter");
39
+ throw jsi::JSError(runtime, "Expected array of dependencies as second parameter");
40
40
  }
41
-
41
+
42
42
  // Get callback for calculating result
43
43
  _callback = std::make_shared<jsi::Function>(arguments[0].asObject(runtime).asFunction(runtime));
44
44
  }
45
-
45
+
46
46
  void invalidate() override {
47
47
  RNSkReadonlyValue::invalidate();
48
-
48
+
49
49
  // Unregister listeners
50
50
  for(const auto &unsubscribe: _unsubscribers) {
51
51
  unsubscribe();
52
52
  }
53
53
  _unsubscribers.clear();
54
54
  }
55
-
55
+
56
56
  void initializeDependencies(jsi::Runtime &runtime, const jsi::Value *arguments, size_t count) {
57
57
  // Save dependencies
58
58
  std::vector<std::shared_ptr<RNSkReadonlyValue>> dependencies;
59
-
59
+
60
60
  // Ensure that all dependencies are Values
61
61
  auto deps = arguments[1].asObject(runtime).asArray(runtime);
62
62
  const std::size_t size = deps.size(runtime);
@@ -73,7 +73,7 @@ public:
73
73
  }
74
74
  dependencies.push_back(value);
75
75
  }
76
-
76
+
77
77
  // register change handler on dependencies
78
78
  _unsubscribers.reserve(_unsubscribers.size() + size);
79
79
  for(const auto &dep: dependencies) {
@@ -85,11 +85,11 @@ public:
85
85
  }
86
86
  }));
87
87
  }
88
-
88
+
89
89
  // Set initial value
90
90
  dependencyUpdated(runtime);
91
91
  }
92
-
92
+
93
93
  private:
94
94
  void dependencyUpdated(jsi::Runtime &runtime) {
95
95
  // Calculate new value
@@ -29,7 +29,7 @@ public:
29
29
  : JsiSkHostObject(platformContext),
30
30
  _valueHolder(std::make_unique<JsiSimpleValueWrapper>(*platformContext->getJsRuntime()))
31
31
  { }
32
-
32
+
33
33
  virtual ~RNSkReadonlyValue() {
34
34
  invalidate();
35
35
  }
@@ -37,21 +37,21 @@ public:
37
37
  JSI_PROPERTY_GET(__typename__) {
38
38
  return jsi::String::createFromUtf8(runtime, "RNSkValue");
39
39
  }
40
-
40
+
41
41
  JSI_PROPERTY_GET(current) {
42
42
  return getCurrent(runtime);
43
43
  }
44
-
44
+
45
45
  JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(RNSkReadonlyValue, __typename__),
46
46
  JSI_EXPORT_PROP_GET(RNSkReadonlyValue, current))
47
-
47
+
48
48
  JSI_HOST_FUNCTION(addListener) {
49
49
  if(!arguments[0].isObject() || !arguments[0].asObject(runtime).isFunction(runtime)) {
50
- jsi::detail::throwJSError(runtime, "Expected function as first parameter.");
50
+ throw jsi::JSError(runtime, "Expected function as first parameter.");
51
51
  return jsi::Value::undefined();
52
52
  }
53
53
  auto callback = std::make_shared<jsi::Function>(arguments[0].asObject(runtime).asFunction(runtime));
54
-
54
+
55
55
  auto unsubscribe = addListener([weakSelf = weak_from_this(),
56
56
  callback = std::move(callback)](jsi::Runtime& runtime){
57
57
  auto self = weakSelf.lock();
@@ -60,7 +60,7 @@ public:
60
60
  callback->call(runtime, selfReadonlyValue->get_current(runtime));
61
61
  }
62
62
  });
63
-
63
+
64
64
  return jsi::Function::createFromHostFunction(runtime,
65
65
  jsi::PropNameID::forUtf8(runtime, "unsubscribe"),
66
66
  0,
@@ -69,17 +69,17 @@ public:
69
69
  return jsi::Value::undefined();
70
70
  });
71
71
  }
72
-
73
-
74
-
72
+
73
+
74
+
75
75
  JSI_HOST_FUNCTION(__invalidate) {
76
76
  invalidate();
77
77
  return jsi::Value::undefined();
78
78
  }
79
-
79
+
80
80
  JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkReadonlyValue, addListener),
81
81
  JSI_EXPORT_FUNC(RNSkReadonlyValue, __invalidate))
82
-
82
+
83
83
  /**
84
84
  * Adds a callback that will be called whenever the value changes
85
85
  * @param cb Callback
@@ -96,7 +96,7 @@ public:
96
96
  }
97
97
  };
98
98
  }
99
-
99
+
100
100
  /**
101
101
  Updates the underlying value and notifies all listeners about the change.
102
102
  Listeners are only notified if the value was actually changed for numeric, boolean and string
@@ -111,7 +111,7 @@ public:
111
111
  notifyListeners(runtime);
112
112
  }
113
113
  }
114
-
114
+
115
115
  /**
116
116
  Override to implement invalidation logic for the value. In the base class this function
117
117
  clears all subscribers.
@@ -120,13 +120,13 @@ public:
120
120
  std::lock_guard<std::mutex> lock(_mutex);
121
121
  _listeners.clear();
122
122
  }
123
-
123
+
124
124
  jsi::Value getCurrent(jsi::Runtime &runtime) {
125
125
  return _valueHolder->getCurrent(runtime);
126
126
  }
127
-
127
+
128
128
  protected:
129
-
129
+
130
130
  /**
131
131
  Notifies listeners about changes
132
132
  @param runtime Current JS Runtime
@@ -141,7 +141,7 @@ protected:
141
141
  listener.second(runtime);
142
142
  }
143
143
  }
144
-
144
+
145
145
  /**
146
146
  Removes a subscription listeners
147
147
  @param listenerId identifier of listener to remove
@@ -153,7 +153,7 @@ protected:
153
153
 
154
154
  private:
155
155
  std::unique_ptr<JsiSimpleValueWrapper> _valueHolder;
156
-
156
+
157
157
  long _listenerId = 0;
158
158
  std::unordered_map<long, std::function<void(jsi::Runtime&)>> _listeners;
159
159
  std::mutex _mutex;