@shopify/react-native-skia 0.1.180 → 0.1.182

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. package/android/build.gradle +6 -1
  2. package/cpp/api/JsiSkData.h +7 -0
  3. package/cpp/api/JsiSkImage.h +7 -1
  4. package/cpp/api/JsiSkSVG.h +7 -0
  5. package/cpp/api/JsiSkTypeface.h +7 -0
  6. package/cpp/jsi/RuntimeAwareCache.cpp +0 -2
  7. package/cpp/rnskia/RNSkDomView.cpp +2 -2
  8. package/cpp/rnskia/RNSkPlatformContext.h +2 -2
  9. package/cpp/rnskia/dom/base/DerivedNodeProp.h +1 -1
  10. package/cpp/rnskia/dom/base/JsiDependencyManager.h +10 -6
  11. package/cpp/rnskia/dom/base/JsiDomNode.h +133 -78
  12. package/cpp/rnskia/dom/base/JsiDomRenderNode.h +17 -5
  13. package/cpp/rnskia/dom/base/NodeProp.h +5 -5
  14. package/cpp/rnskia/dom/base/NodePropsContainer.h +8 -2
  15. package/cpp/rnskia/dom/props/ClipProp.h +13 -20
  16. package/cpp/rnskia/dom/props/PathProp.h +16 -14
  17. package/cpp/rnskia/dom/props/PointProp.h +1 -1
  18. package/cpp/rnskia/dom/props/RRectProp.h +39 -61
  19. package/cpp/rnskia/dom/props/RectProp.h +27 -25
  20. package/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm +0 -2
  21. package/lib/commonjs/dom/nodes/JsiSkDOM.js +56 -54
  22. package/lib/commonjs/dom/nodes/JsiSkDOM.js.map +1 -1
  23. package/lib/commonjs/renderer/Canvas.js +30 -9
  24. package/lib/commonjs/renderer/Canvas.js.map +1 -1
  25. package/lib/commonjs/renderer/HostComponents.d.ts +1 -0
  26. package/lib/commonjs/renderer/HostComponents.js +6 -1
  27. package/lib/commonjs/renderer/HostComponents.js.map +1 -1
  28. package/lib/commonjs/renderer/Reconciler.js +3 -1
  29. package/lib/commonjs/renderer/Reconciler.js.map +1 -1
  30. package/lib/commonjs/skia/core/Data.d.ts +2 -2
  31. package/lib/commonjs/skia/core/Data.js +5 -0
  32. package/lib/commonjs/skia/core/Data.js.map +1 -1
  33. package/lib/commonjs/skia/types/Data/Data.d.ts +2 -2
  34. package/lib/commonjs/skia/types/Data/Data.js.map +1 -1
  35. package/lib/commonjs/skia/types/Image/Image.d.ts +2 -2
  36. package/lib/commonjs/skia/types/Image/Image.js.map +1 -1
  37. package/lib/commonjs/skia/types/JsiInstance.d.ts +3 -0
  38. package/lib/commonjs/skia/types/JsiInstance.js.map +1 -1
  39. package/lib/commonjs/skia/types/SVG/SVG.d.ts +2 -2
  40. package/lib/commonjs/skia/types/SVG/SVG.js.map +1 -1
  41. package/lib/commonjs/skia/types/Typeface/Typeface.d.ts +2 -2
  42. package/lib/commonjs/skia/types/Typeface/Typeface.js.map +1 -1
  43. package/lib/commonjs/skia/web/JsiSkData.d.ts +1 -0
  44. package/lib/commonjs/skia/web/JsiSkData.js +3 -0
  45. package/lib/commonjs/skia/web/JsiSkData.js.map +1 -1
  46. package/lib/commonjs/skia/web/JsiSkImage.d.ts +1 -0
  47. package/lib/commonjs/skia/web/JsiSkImage.js +4 -0
  48. package/lib/commonjs/skia/web/JsiSkImage.js.map +1 -1
  49. package/lib/commonjs/skia/web/JsiSkTypeface.d.ts +1 -0
  50. package/lib/commonjs/skia/web/JsiSkTypeface.js +4 -0
  51. package/lib/commonjs/skia/web/JsiSkTypeface.js.map +1 -1
  52. package/lib/commonjs/views/SkiaBaseWebView.js +5 -1
  53. package/lib/commonjs/views/SkiaBaseWebView.js.map +1 -1
  54. package/lib/module/dom/nodes/JsiSkDOM.js +55 -54
  55. package/lib/module/dom/nodes/JsiSkDOM.js.map +1 -1
  56. package/lib/module/renderer/Canvas.js +29 -10
  57. package/lib/module/renderer/Canvas.js.map +1 -1
  58. package/lib/module/renderer/HostComponents.d.ts +1 -0
  59. package/lib/module/renderer/HostComponents.js +3 -0
  60. package/lib/module/renderer/HostComponents.js.map +1 -1
  61. package/lib/module/renderer/Reconciler.js +2 -1
  62. package/lib/module/renderer/Reconciler.js.map +1 -1
  63. package/lib/module/skia/core/Data.d.ts +2 -2
  64. package/lib/module/skia/core/Data.js +5 -0
  65. package/lib/module/skia/core/Data.js.map +1 -1
  66. package/lib/module/skia/types/Data/Data.d.ts +2 -2
  67. package/lib/module/skia/types/Data/Data.js.map +1 -1
  68. package/lib/module/skia/types/Image/Image.d.ts +2 -2
  69. package/lib/module/skia/types/Image/Image.js.map +1 -1
  70. package/lib/module/skia/types/JsiInstance.d.ts +3 -0
  71. package/lib/module/skia/types/JsiInstance.js.map +1 -1
  72. package/lib/module/skia/types/SVG/SVG.d.ts +2 -2
  73. package/lib/module/skia/types/SVG/SVG.js.map +1 -1
  74. package/lib/module/skia/types/Typeface/Typeface.d.ts +2 -2
  75. package/lib/module/skia/types/Typeface/Typeface.js.map +1 -1
  76. package/lib/module/skia/web/JsiSkData.d.ts +1 -0
  77. package/lib/module/skia/web/JsiSkData.js +3 -0
  78. package/lib/module/skia/web/JsiSkData.js.map +1 -1
  79. package/lib/module/skia/web/JsiSkImage.d.ts +1 -0
  80. package/lib/module/skia/web/JsiSkImage.js +4 -0
  81. package/lib/module/skia/web/JsiSkImage.js.map +1 -1
  82. package/lib/module/skia/web/JsiSkTypeface.d.ts +1 -0
  83. package/lib/module/skia/web/JsiSkTypeface.js +4 -0
  84. package/lib/module/skia/web/JsiSkTypeface.js.map +1 -1
  85. package/lib/module/views/SkiaBaseWebView.js +5 -1
  86. package/lib/module/views/SkiaBaseWebView.js.map +1 -1
  87. package/lib/typescript/src/renderer/HostComponents.d.ts +1 -0
  88. package/lib/typescript/src/skia/core/Data.d.ts +2 -2
  89. package/lib/typescript/src/skia/types/Data/Data.d.ts +2 -2
  90. package/lib/typescript/src/skia/types/Image/Image.d.ts +2 -2
  91. package/lib/typescript/src/skia/types/JsiInstance.d.ts +3 -0
  92. package/lib/typescript/src/skia/types/SVG/SVG.d.ts +2 -2
  93. package/lib/typescript/src/skia/types/Typeface/Typeface.d.ts +2 -2
  94. package/lib/typescript/src/skia/web/JsiSkData.d.ts +1 -0
  95. package/lib/typescript/src/skia/web/JsiSkImage.d.ts +1 -0
  96. package/lib/typescript/src/skia/web/JsiSkTypeface.d.ts +1 -0
  97. package/package.json +1 -1
  98. package/src/dom/nodes/JsiSkDOM.ts +55 -54
  99. package/src/renderer/Canvas.tsx +34 -14
  100. package/src/renderer/HostComponents.ts +4 -0
  101. package/src/renderer/Reconciler.tsx +2 -1
  102. package/src/skia/core/Data.ts +14 -6
  103. package/src/skia/types/Data/Data.ts +2 -2
  104. package/src/skia/types/Image/Image.ts +2 -2
  105. package/src/skia/types/JsiInstance.ts +4 -0
  106. package/src/skia/types/SVG/SVG.ts +2 -2
  107. package/src/skia/types/Typeface/Typeface.ts +2 -2
  108. package/src/skia/web/JsiSkData.ts +4 -0
  109. package/src/skia/web/JsiSkImage.ts +4 -0
  110. package/src/skia/web/JsiSkTypeface.ts +4 -0
  111. package/src/views/SkiaBaseWebView.tsx +5 -0
@@ -28,6 +28,11 @@ def safeExtGet(prop, fallback) {
28
28
 
29
29
  apply plugin: 'com.android.library'
30
30
 
31
+ def reactNativeArchitectures() {
32
+ def value = project.getProperties().get("reactNativeArchitectures")
33
+ return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
34
+ }
35
+
31
36
  static def findNodeModules(baseDir) {
32
37
  def basePath = baseDir.toPath().normalize()
33
38
  // Node's module resolution algorithm searches up to the root directory,
@@ -119,7 +124,7 @@ android {
119
124
  externalNativeBuild {
120
125
  cmake {
121
126
  cppFlags "-fexceptions", "-frtti", "-std=c++1y", "-DONANDROID"
122
- abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
127
+ abiFilters (*reactNativeArchitectures())
123
128
  arguments '-DANDROID_STL=c++_shared',
124
129
  "-DREACT_NATIVE_VERSION=${REACT_NATIVE_VERSION}",
125
130
  "-DNODE_MODULES_DIR=${nodeModules}",
@@ -30,6 +30,13 @@ public:
30
30
 
31
31
  JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkData, __typename__))
32
32
 
33
+ JSI_HOST_FUNCTION(dispose) {
34
+ setObject(nullptr);
35
+ return jsi::Value::undefined();
36
+ }
37
+
38
+ JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkData, dispose))
39
+
33
40
  /**
34
41
  Returns the underlying object from a host object of this type
35
42
  */
@@ -104,12 +104,18 @@ public:
104
104
  return jsi::String::createFromAscii(runtime, buffer);
105
105
  }
106
106
 
107
+ JSI_HOST_FUNCTION(dispose) {
108
+ setObject(nullptr);
109
+ return jsi::Value::undefined();
110
+ }
111
+
107
112
  JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkImage, width),
108
113
  JSI_EXPORT_FUNC(JsiSkImage, height),
109
114
  JSI_EXPORT_FUNC(JsiSkImage, makeShaderOptions),
110
115
  JSI_EXPORT_FUNC(JsiSkImage, makeShaderCubic),
111
116
  JSI_EXPORT_FUNC(JsiSkImage, encodeToBytes),
112
- JSI_EXPORT_FUNC(JsiSkImage, encodeToBase64))
117
+ JSI_EXPORT_FUNC(JsiSkImage, encodeToBase64),
118
+ JSI_EXPORT_FUNC(JsiSkImage, dispose))
113
119
 
114
120
  JsiSkImage(std::shared_ptr<RNSkPlatformContext> context,
115
121
  const sk_sp<SkImage> image)
@@ -30,6 +30,13 @@ public:
30
30
 
31
31
  JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkSVG, __typename__))
32
32
 
33
+ JSI_HOST_FUNCTION(dispose) {
34
+ setObject(nullptr);
35
+ return jsi::Value::undefined();
36
+ }
37
+
38
+ JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkSVG, dispose))
39
+
33
40
  /**
34
41
  Returns the underlying object from a host object of this type
35
42
  */
@@ -29,6 +29,13 @@ public:
29
29
 
30
30
  JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkTypeface, __typename__))
31
31
 
32
+ JSI_HOST_FUNCTION(dispose) {
33
+ setObject(nullptr);
34
+ return jsi::Value::undefined();
35
+ }
36
+
37
+ JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkTypeface, dispose))
38
+
32
39
  JsiSkTypeface(std::shared_ptr<RNSkPlatformContext> context,
33
40
  sk_sp<SkTypeface> typeface)
34
41
  : JsiSkWrappingSkPtrHostObject(std::move(context), std::move(typeface)) {}
@@ -1,5 +1,3 @@
1
- #pragma once
2
-
3
1
  #include "RuntimeAwareCache.h"
4
2
 
5
3
  namespace RNJsi {
@@ -22,7 +22,7 @@ RNSkDomRenderer::RNSkDomRenderer(std::function<void()> requestRedraw,
22
22
 
23
23
  RNSkDomRenderer::~RNSkDomRenderer() {
24
24
  if (_root != nullptr) {
25
- _root->dispose();
25
+ _root->dispose(true);
26
26
  _root = nullptr;
27
27
  }
28
28
  }
@@ -63,7 +63,7 @@ void RNSkDomRenderer::renderImmediate(
63
63
  void RNSkDomRenderer::setRoot(std::shared_ptr<JsiDomRenderNode> node) {
64
64
  std::lock_guard<std::mutex> lock(_rootLock);
65
65
  if (_root != nullptr) {
66
- _root->dispose();
66
+ _root->dispose(true);
67
67
  _root = nullptr;
68
68
  }
69
69
  _root = node;
@@ -112,8 +112,8 @@ public:
112
112
 
113
113
  /**
114
114
  * Creates an offscreen surface
115
- * @param width
116
- * @param height
115
+ * @param width width of the surface
116
+ * @param height height of the surface
117
117
  * @return sk_sp<SkSurface>
118
118
  */
119
119
  virtual sk_sp<SkSurface> makeOffscreenSurface(int width, int height) = 0;
@@ -72,7 +72,7 @@ public:
72
72
  Adds a property to the derived property child props.
73
73
  */
74
74
  template <class _Tp, class... _Args,
75
- class = std::_EnableIf<!std::is_array<_Tp>::value>>
75
+ class = std::enable_if_t<!std::is_array<_Tp>::value>>
76
76
  _Tp *defineProperty(_Args &&...__args) {
77
77
  auto prop =
78
78
  std::make_shared<_Tp>(std::forward<_Args>(__args)..., _onChange);
@@ -23,8 +23,10 @@ class JsiDependencyManager
23
23
  public std::enable_shared_from_this<JsiDependencyManager> {
24
24
  public:
25
25
  JsiDependencyManager(std::shared_ptr<RNSkPlatformContext> context,
26
- jsi::Object &&registerValuesCallback)
27
- : _registerValuesCallback(std::move(registerValuesCallback)),
26
+ jsi::Runtime &runtime,
27
+ const jsi::Value &registerValuesCallback)
28
+ : _registerValuesCallback(std::make_shared<jsi::Object>(
29
+ registerValuesCallback.asObject(runtime))),
28
30
  JsiHostObject() {}
29
31
 
30
32
  ~JsiDependencyManager() { unsubscribeAll(); }
@@ -158,7 +160,7 @@ public:
158
160
  }
159
161
 
160
162
  // Call JS registerValues callback
161
- auto func = _registerValuesCallback.asFunction(runtime);
163
+ auto func = _registerValuesCallback->asFunction(runtime);
162
164
  _unregisterValues = std::make_shared<jsi::Object>(
163
165
  func.call(runtime, array, 1).asObject(runtime));
164
166
 
@@ -187,6 +189,8 @@ public:
187
189
 
188
190
  unsubscribeAll();
189
191
 
192
+ _registerValuesCallback = nullptr;
193
+
190
194
  return jsi::Value::undefined();
191
195
  }
192
196
 
@@ -203,8 +207,8 @@ public:
203
207
  return JSI_HOST_FUNCTION_LAMBDA {
204
208
  // Params: registerValues: (values: Array<SkiaValue<unknown>>) => () =>
205
209
  // void
206
- auto obj = std::make_shared<JsiDependencyManager>(
207
- context, getArgumentAsObject(runtime, arguments, count, 0));
210
+ auto obj = std::make_shared<JsiDependencyManager>(context, runtime,
211
+ arguments[0]);
208
212
 
209
213
  return jsi::Object::createFromHostObject(runtime, std::move(obj));
210
214
  };
@@ -283,7 +287,7 @@ private:
283
287
  return false;
284
288
  }
285
289
 
286
- jsi::Object _registerValuesCallback;
290
+ std::shared_ptr<jsi::Object> _registerValuesCallback;
287
291
  std::shared_ptr<jsi::Object> _unregisterValues;
288
292
  std::map<JsiDomNode *,
289
293
  std::vector<std::pair<std::shared_ptr<RNSkReadonlyValue>,
@@ -49,7 +49,19 @@ public:
49
49
  JsiDomNode(std::shared_ptr<RNSkPlatformContext> context, const char *type,
50
50
  NodeClass nodeClass)
51
51
  : _type(type), _context(context), _nodeClass(nodeClass),
52
- _nodeId(NodeIdent++), JsiHostObject() {}
52
+ _nodeId(NodeIdent++), JsiHostObject() {
53
+ #if SKIA_DOM_DEBUG
54
+ printDebugInfo("JsiDomNode." + std::string(_type) +
55
+ " CTOR - nodeId: " + std::to_string(_nodeId));
56
+ #endif
57
+ }
58
+
59
+ virtual ~JsiDomNode() {
60
+ #if SKIA_DOM_DEBUG
61
+ printDebugInfo("JsiDomNode." + std::string(_type) +
62
+ " DTOR - nodeId: " + std::to_string(_nodeId));
63
+ #endif
64
+ }
53
65
 
54
66
  /**
55
67
  Called when creating the node, resolves properties from the node constructor.
@@ -65,7 +77,7 @@ public:
65
77
  JSI_HOST_FUNCTION(setProps) {
66
78
  if (count == 1) {
67
79
  // Initialize properties container
68
- setProps(runtime, getArgumentAsObject(runtime, arguments, count, 0));
80
+ setProps(runtime, arguments[0]);
69
81
  } else {
70
82
  setEmptyProps();
71
83
  }
@@ -102,7 +114,7 @@ public:
102
114
  tree. Use for cleaning up.
103
115
  */
104
116
  JSI_HOST_FUNCTION(dispose) {
105
- dispose();
117
+ dispose(false);
106
118
  return jsi::Value::undefined();
107
119
  }
108
120
 
@@ -247,36 +259,9 @@ public:
247
259
  _propsContainer->markAsResolved();
248
260
  }
249
261
 
250
- // Now let's dispose if needed
262
+ // Now let's invalidate if needed
251
263
  if (_isDisposing && !_isDisposed) {
252
- _isDisposed = true;
253
-
254
- this->setParent(nullptr);
255
-
256
- // Callback signaling that we're done
257
- if (_disposeCallback != nullptr) {
258
- _disposeCallback();
259
- _disposeCallback = nullptr;
260
- }
261
-
262
- // Clear props
263
- if (_propsContainer != nullptr) {
264
- _propsContainer->dispose();
265
- }
266
-
267
- // Remove children
268
- std::vector<std::shared_ptr<JsiDomNode>> tmp;
269
- {
270
- std::lock_guard<std::mutex> lock(_childrenLock);
271
- tmp.reserve(_children.size());
272
- for (auto &child : _children) {
273
- tmp.push_back(child);
274
- }
275
- _children.clear();
276
- }
277
- for (auto &child : tmp) {
278
- child->dispose();
279
- }
264
+ invalidate();
280
265
  }
281
266
 
282
267
  // Resolve children
@@ -292,6 +277,22 @@ public:
292
277
  // Empty implementation
293
278
  }
294
279
 
280
+ /**
281
+ Called when a node has been removed from the dom tree and needs to be cleaned
282
+ up. If the invalidate parameter is set, we will invalidate the node directly.
283
+ Calling dispose from the JS dispose function calls this with invalidate set
284
+ to false, while the dom render view calls this with true.
285
+ */
286
+ virtual void dispose(bool immediate) {
287
+ if (_isDisposing) {
288
+ return;
289
+ }
290
+ _isDisposing = true;
291
+ if (immediate) {
292
+ invalidate();
293
+ }
294
+ }
295
+
295
296
  protected:
296
297
  /**
297
298
  Adds an operation that will be executed when the render cycle is finished.
@@ -319,24 +320,17 @@ protected:
319
320
 
320
321
  /**
321
322
  Native implementation of the set properties method. This is called from the
322
- reconciler when properties are set due to changes in React. This method will
323
- always call the onPropsSet method as a signal that things have changed.
323
+ reconciler when properties are set due to changes in React.
324
324
  */
325
- void setProps(jsi::Runtime &runtime, jsi::Object &&props) {
325
+ void setProps(jsi::Runtime &runtime, const jsi::Value &maybeProps) {
326
326
  #if SKIA_DOM_DEBUG
327
327
  printDebugInfo("JS:setProps(nodeId: " + std::to_string(_nodeId) + ")");
328
328
  #endif
329
- if (_propsContainer == nullptr) {
329
+ // Initialize properties container
330
+ ensurePropertyContainer();
330
331
 
331
- // Initialize properties container
332
- _propsContainer = std::make_shared<NodePropsContainer>(
333
- getType(), [=](BaseNodeProp *p) { onPropertyChanged(p); });
334
-
335
- // Ask sub classes to define their properties
336
- defineProperties(_propsContainer.get());
337
- }
338
332
  // Update properties container
339
- _propsContainer->setProps(runtime, std::move(props));
333
+ _propsContainer->setProps(runtime, maybeProps);
340
334
 
341
335
  // Invalidate context
342
336
  invalidateContext();
@@ -349,15 +343,8 @@ protected:
349
343
  #if SKIA_DOM_DEBUG
350
344
  printDebugInfo("JS:setEmptyProps(nodeId: " + std::to_string(_nodeId) + ")");
351
345
  #endif
352
- if (_propsContainer == nullptr) {
353
-
354
- // Initialize properties container
355
- _propsContainer = std::make_shared<NodePropsContainer>(
356
- getType(), [=](BaseNodeProp *p) { onPropertyChanged(p); });
357
-
358
- // Ask sub classes to define their properties
359
- defineProperties(_propsContainer.get());
360
- }
346
+ // Initialize properties container
347
+ ensurePropertyContainer();
361
348
  }
362
349
 
363
350
  /**
@@ -381,9 +368,12 @@ protected:
381
368
  printDebugInfo("JS:addChild(childId: " + std::to_string(child->_nodeId) +
382
369
  ")");
383
370
  #endif
384
- enqueAsynOperation([child, this]() {
385
- _children.push_back(child);
386
- child->setParent(this);
371
+ enqueAsynOperation([child, weakSelf = weak_from_this()]() {
372
+ auto self = weakSelf.lock();
373
+ if (self) {
374
+ self->_children.push_back(child);
375
+ child->setParent(self.get());
376
+ }
387
377
  });
388
378
  }
389
379
 
@@ -398,10 +388,14 @@ protected:
398
388
  "JS:insertChildBefore(childId: " + std::to_string(child->_nodeId) +
399
389
  ", beforeId: " + std::to_string(before->_nodeId) + ")");
400
390
  #endif
401
- enqueAsynOperation([child, before, this]() {
402
- auto position = std::find(_children.begin(), _children.end(), before);
403
- _children.insert(position, child);
404
- child->setParent(this);
391
+ enqueAsynOperation([child, before, weakSelf = weak_from_this()]() {
392
+ auto self = weakSelf.lock();
393
+ if (self) {
394
+ auto position =
395
+ std::find(self->_children.begin(), self->_children.end(), before);
396
+ self->_children.insert(position, child);
397
+ child->setParent(self.get());
398
+ }
405
399
  });
406
400
  }
407
401
 
@@ -414,27 +408,25 @@ protected:
414
408
  printDebugInfo("JS:removeChild(childId: " + std::to_string(child->_nodeId) +
415
409
  ")");
416
410
  #endif
417
- enqueAsynOperation([child, this]() {
418
- // Delete child itself
419
- _children.erase(
420
- std::remove_if(_children.begin(), _children.end(),
421
- [child](const auto &node) { return node == child; }),
422
- _children.end());
423
-
424
- child->dispose();
425
- });
426
- }
411
+ auto removeChild = [child,
412
+ weakSelf = weak_from_this()](bool immediate = false) {
413
+ auto self = weakSelf.lock();
414
+ if (self) {
415
+ // Delete child itself
416
+ self->_children.erase(
417
+ std::remove_if(self->_children.begin(), self->_children.end(),
418
+ [child](const auto &node) { return node == child; }),
419
+ self->_children.end());
420
+
421
+ child->dispose(immediate);
422
+ }
423
+ };
427
424
 
428
- /**
429
- Called when a node has been removed from the dom tree and needs to be cleaned
430
- up.
431
- */
432
- virtual void dispose() {
433
425
  if (_isDisposing) {
434
- return;
426
+ removeChild(false);
427
+ } else {
428
+ enqueAsynOperation(removeChild);
435
429
  }
436
-
437
- _isDisposing = true;
438
430
  }
439
431
 
440
432
  #if SKIA_DOM_DEBUG
@@ -477,6 +469,69 @@ protected:
477
469
  }
478
470
 
479
471
  private:
472
+ /**
473
+ Invalidates the node - meaning removing and clearing children and properties
474
+ **/
475
+ void invalidate() {
476
+ if (_isDisposing && !_isDisposed) {
477
+ #if SKIA_DOM_DEBUG
478
+ printDebugInfo("JsiDomNode::invalidate: nodeid: " +
479
+ std::to_string(_nodeId));
480
+ #endif
481
+
482
+ _isDisposed = true;
483
+
484
+ // Clear parent
485
+ this->setParent(nullptr);
486
+
487
+ // Clear any async operations
488
+ _queuedNodeOps.clear();
489
+
490
+ // Callback signaling that we're done
491
+ if (_disposeCallback != nullptr) {
492
+ _disposeCallback();
493
+ _disposeCallback = nullptr;
494
+ }
495
+
496
+ // Clear props
497
+ if (_propsContainer != nullptr) {
498
+ _propsContainer->dispose();
499
+ }
500
+
501
+ // Remove children
502
+ std::vector<std::shared_ptr<JsiDomNode>> tmp;
503
+ {
504
+ std::lock_guard<std::mutex> lock(_childrenLock);
505
+ tmp.reserve(_children.size());
506
+ for (auto &child : _children) {
507
+ tmp.push_back(child);
508
+ }
509
+ _children.clear();
510
+ }
511
+ for (auto &child : tmp) {
512
+ child->dispose(true);
513
+ }
514
+ }
515
+ }
516
+
517
+ /**
518
+ Creates and sets up the property container
519
+ */
520
+ void ensurePropertyContainer() {
521
+ if (_propsContainer == nullptr) {
522
+ _propsContainer = std::make_shared<NodePropsContainer>(
523
+ getType(), [weakSelf = weak_from_this()](BaseNodeProp *p) {
524
+ auto self = weakSelf.lock();
525
+ if (self) {
526
+ self->onPropertyChanged(p);
527
+ }
528
+ });
529
+
530
+ // Ask sub classes to define their properties
531
+ defineProperties(_propsContainer.get());
532
+ }
533
+ }
534
+
480
535
  const char *_type;
481
536
  std::shared_ptr<RNSkPlatformContext> _context;
482
537
 
@@ -133,18 +133,26 @@ public:
133
133
  void resetPendingChanges() override { JsiDomNode::resetPendingChanges(); }
134
134
 
135
135
  /**
136
- Signal from the JS side that the node is removed from the dom.
136
+ Overridden dispose to release resources
137
137
  */
138
- void dispose() override { JsiDomNode::dispose(); }
138
+ void dispose(bool immediate) override {
139
+ JsiDomNode::dispose(immediate);
140
+ _paintCache.clear();
141
+ }
139
142
 
140
143
  protected:
141
144
  /**
142
145
  Invalidates and marks then context as changed.
143
146
  */
144
147
  void invalidateContext() override {
145
- enqueAsynOperation([=]() {
146
- _paintCache.parent = nullptr;
147
- _paintCache.child = nullptr;
148
+ enqueAsynOperation([weakSelf = weak_from_this()]() {
149
+ auto self = weakSelf.lock();
150
+ if (self) {
151
+ std::static_pointer_cast<JsiDomRenderNode>(self)->_paintCache.parent =
152
+ nullptr;
153
+ std::static_pointer_cast<JsiDomRenderNode>(self)->_paintCache.child =
154
+ nullptr;
155
+ }
148
156
  });
149
157
  }
150
158
 
@@ -232,6 +240,10 @@ private:
232
240
  }
233
241
 
234
242
  struct PaintCache {
243
+ void clear() {
244
+ parent = nullptr;
245
+ child = nullptr;
246
+ }
235
247
  std::shared_ptr<SkPaint> parent;
236
248
  std::shared_ptr<SkPaint> child;
237
249
  };
@@ -33,7 +33,7 @@ public:
33
33
  // readValueFromJS Function (which comes from the reconciler
34
34
  // setting a new property value on the property
35
35
  if (_value == nullptr) {
36
- _value = std::make_shared<JsiValue>(runtime, read(runtime, _name, this));
36
+ _value = std::make_unique<JsiValue>(runtime, read(runtime, _name, this));
37
37
  _isChanged = true;
38
38
  _hasNewValue = false;
39
39
  } else {
@@ -41,7 +41,7 @@ public:
41
41
  std::lock_guard<std::mutex> lock(_swapMutex);
42
42
  if (_buffer == nullptr) {
43
43
  _buffer =
44
- std::make_shared<JsiValue>(runtime, read(runtime, _name, this));
44
+ std::make_unique<JsiValue>(runtime, read(runtime, _name, this));
45
45
  } else {
46
46
  _buffer->setCurrent(runtime, read(runtime, _name, this));
47
47
  }
@@ -60,7 +60,7 @@ public:
60
60
  // and we don't want to rip out the underlying value object.
61
61
  std::lock_guard<std::mutex> lock(_swapMutex);
62
62
  if (_buffer == nullptr) {
63
- _buffer = std::make_shared<JsiValue>(runtime, value);
63
+ _buffer = std::make_unique<JsiValue>(runtime, value);
64
64
  } else {
65
65
  _buffer->setCurrent(runtime, value);
66
66
  }
@@ -129,8 +129,8 @@ private:
129
129
 
130
130
  std::function<void(BaseNodeProp *)> _onChange;
131
131
 
132
- std::shared_ptr<JsiValue> _value;
133
- std::shared_ptr<JsiValue> _buffer;
132
+ std::unique_ptr<JsiValue> _value;
133
+ std::unique_ptr<JsiValue> _buffer;
134
134
  std::atomic<bool> _isChanged = {false};
135
135
  std::atomic<bool> _hasNewValue = {false};
136
136
  std::mutex _swapMutex;
@@ -82,10 +82,16 @@ public:
82
82
  /**
83
83
  Called when the React / JS side sets properties on a node
84
84
  */
85
- void setProps(jsi::Runtime &runtime, jsi::Object &&props) {
85
+ void setProps(jsi::Runtime &runtime, const jsi::Value &maybePropsObject) {
86
86
  // Clear property mapping
87
87
  _mappedProperties.clear();
88
88
 
89
+ if (!maybePropsObject.isObject()) {
90
+ throw jsi::JSError(runtime, "Expected property object.");
91
+ }
92
+
93
+ auto props = maybePropsObject.asObject(runtime);
94
+
89
95
  // Use specialized reader function to be able to intercept calls that
90
96
  // reads specific named values from the js property object.
91
97
  auto read = [&](jsi::Runtime &runtime, PropId name, NodeProp *prop) {
@@ -106,7 +112,7 @@ public:
106
112
  Defines a property that will be added to the container
107
113
  */
108
114
  template <class _Tp, class... _Args,
109
- class = std::_EnableIf<!std::is_array<_Tp>::value>>
115
+ class = std::enable_if_t<!std::is_array<_Tp>::value>>
110
116
  _Tp *defineProperty(_Args &&...__args) {
111
117
  // Create property and set onChange callback
112
118
  auto prop =
@@ -22,43 +22,36 @@ public:
22
22
  explicit ClipProp(PropId name,
23
23
  const std::function<void(BaseNodeProp *)> &onChange)
24
24
  : BaseDerivedProp(onChange) {
25
- _pathProp = defineProperty<PathProp>(name);
26
- _rectProp = defineProperty<RectProp>(name);
27
- _rrectProp = defineProperty<RRectProp>(name);
25
+ _clipProp = defineProperty<NodeProp>(name);
28
26
  }
29
27
 
30
28
  void updateDerivedValue() override {
31
- if (_pathProp->isSet()) {
32
- _rect = nullptr;
33
- _rrect = nullptr;
34
- _path = _pathProp->getDerivedValue();
35
- } else if (_rrectProp->isSet()) {
36
- _rect = nullptr;
37
- _rrect = _rrectProp->getDerivedValue();
38
- _path = nullptr;
39
- } else if (_rectProp->isSet()) {
40
- _rect = _rectProp->getDerivedValue();
29
+ if (_clipProp->isSet()) {
30
+ auto value = _clipProp->value();
31
+ _rect = RectProp::processRect(value);
41
32
  _rrect = nullptr;
42
33
  _path = nullptr;
34
+ if (!_rect) {
35
+ _path = PathProp::processPath(value);
36
+ if (!_path) {
37
+ _rrect = RRectProp::processRRect(value);
38
+ }
39
+ }
43
40
  }
44
41
  }
45
42
 
46
- bool isSet() override {
47
- return _pathProp->isSet() || _rectProp->isSet() || _rrectProp->isSet();
48
- }
43
+ bool isSet() override { return _clipProp->isSet(); }
49
44
 
50
45
  const SkPath *getPath() { return _path.get(); }
51
46
  const SkRect *getRect() { return _rect.get(); }
52
47
  const SkRRect *getRRect() { return _rrect.get(); }
53
48
 
54
49
  private:
55
- PathProp *_pathProp;
56
- RectProp *_rectProp;
57
- RRectProp *_rrectProp;
50
+ NodeProp *_clipProp;
58
51
 
59
52
  std::shared_ptr<const SkPath> _path;
60
53
  std::shared_ptr<const SkRect> _rect;
61
54
  std::shared_ptr<const SkRRect> _rrect;
62
55
  };
63
56
 
64
- } // namespace RNSkia
57
+ } // namespace RNSkia