@shopify/react-native-skia 0.1.180 → 0.1.182

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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