@shopify/react-native-skia 0.1.175 → 0.1.178

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. package/android/CMakeLists.txt +2 -0
  2. package/android/build.gradle +2 -1
  3. package/cpp/jsi/JsiHostObject.cpp +13 -7
  4. package/cpp/jsi/JsiHostObject.h +3 -1
  5. package/cpp/jsi/RuntimeAwareCache.cpp +9 -0
  6. package/cpp/jsi/RuntimeAwareCache.h +101 -0
  7. package/cpp/jsi/RuntimeLifecycleMonitor.cpp +57 -0
  8. package/cpp/jsi/RuntimeLifecycleMonitor.h +32 -0
  9. package/cpp/rnskia/RNSkJsView.cpp +1 -1
  10. package/cpp/rnskia/RNSkManager.cpp +4 -0
  11. package/cpp/rnskia/dom/base/JsiDomNode.h +22 -2
  12. package/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm +12 -8
  13. package/lib/commonjs/external/reanimated/index.d.ts +1 -0
  14. package/lib/commonjs/external/reanimated/index.js +13 -0
  15. package/lib/commonjs/external/reanimated/index.js.map +1 -1
  16. package/lib/commonjs/external/reanimated/moduleWrapper.d.ts +8 -0
  17. package/lib/commonjs/external/reanimated/moduleWrapper.js +72 -0
  18. package/lib/commonjs/external/reanimated/moduleWrapper.js.map +1 -0
  19. package/lib/commonjs/external/reanimated/renderHelpers.d.ts +5 -0
  20. package/lib/commonjs/external/reanimated/renderHelpers.js +85 -0
  21. package/lib/commonjs/external/reanimated/renderHelpers.js.map +1 -0
  22. package/lib/commonjs/external/reanimated/useSharedValueEffect.d.ts +2 -5
  23. package/lib/commonjs/external/reanimated/useSharedValueEffect.js +10 -25
  24. package/lib/commonjs/external/reanimated/useSharedValueEffect.js.map +1 -1
  25. package/lib/commonjs/headless/index.d.ts +3 -0
  26. package/lib/commonjs/headless/index.js +57 -0
  27. package/lib/commonjs/headless/index.js.map +1 -0
  28. package/lib/commonjs/mock/index.d.ts +1 -2
  29. package/lib/commonjs/mock/index.js +0 -4
  30. package/lib/commonjs/mock/index.js.map +1 -1
  31. package/lib/commonjs/renderer/Canvas.js +7 -1
  32. package/lib/commonjs/renderer/Canvas.js.map +1 -1
  33. package/lib/commonjs/renderer/Container.d.ts +2 -1
  34. package/lib/commonjs/renderer/Container.js +2 -0
  35. package/lib/commonjs/renderer/Container.js.map +1 -1
  36. package/lib/commonjs/renderer/HostConfig.js +6 -4
  37. package/lib/commonjs/renderer/HostConfig.js.map +1 -1
  38. package/lib/commonjs/renderer/Reconciler.d.ts +1 -1
  39. package/lib/commonjs/renderer/Reconciler.js +2 -1
  40. package/lib/commonjs/renderer/Reconciler.js.map +1 -1
  41. package/lib/commonjs/renderer/processors/Animations/Animations.d.ts +4 -1
  42. package/lib/commonjs/renderer/processors/Animations/Animations.js.map +1 -1
  43. package/lib/commonjs/skia/web/JsiSkSurfaceFactory.js +8 -1
  44. package/lib/commonjs/skia/web/JsiSkSurfaceFactory.js.map +1 -1
  45. package/lib/module/external/reanimated/index.d.ts +1 -0
  46. package/lib/module/external/reanimated/index.js +1 -0
  47. package/lib/module/external/reanimated/index.js.map +1 -1
  48. package/lib/module/external/reanimated/moduleWrapper.d.ts +8 -0
  49. package/lib/module/external/reanimated/moduleWrapper.js +51 -0
  50. package/lib/module/external/reanimated/moduleWrapper.js.map +1 -0
  51. package/lib/module/external/reanimated/renderHelpers.d.ts +5 -0
  52. package/lib/module/external/reanimated/renderHelpers.js +76 -0
  53. package/lib/module/external/reanimated/renderHelpers.js.map +1 -0
  54. package/lib/module/external/reanimated/useSharedValueEffect.d.ts +2 -5
  55. package/lib/module/external/reanimated/useSharedValueEffect.js +7 -22
  56. package/lib/module/external/reanimated/useSharedValueEffect.js.map +1 -1
  57. package/lib/module/headless/index.d.ts +3 -0
  58. package/lib/module/headless/index.js +29 -0
  59. package/lib/module/headless/index.js.map +1 -0
  60. package/lib/module/mock/index.d.ts +1 -2
  61. package/lib/module/mock/index.js +0 -3
  62. package/lib/module/mock/index.js.map +1 -1
  63. package/lib/module/renderer/Canvas.js +7 -1
  64. package/lib/module/renderer/Canvas.js.map +1 -1
  65. package/lib/module/renderer/Container.d.ts +2 -1
  66. package/lib/module/renderer/Container.js +2 -0
  67. package/lib/module/renderer/Container.js.map +1 -1
  68. package/lib/module/renderer/HostConfig.js +5 -4
  69. package/lib/module/renderer/HostConfig.js.map +1 -1
  70. package/lib/module/renderer/Reconciler.d.ts +1 -1
  71. package/lib/module/renderer/Reconciler.js +2 -1
  72. package/lib/module/renderer/Reconciler.js.map +1 -1
  73. package/lib/module/renderer/processors/Animations/Animations.d.ts +4 -1
  74. package/lib/module/renderer/processors/Animations/Animations.js.map +1 -1
  75. package/lib/module/skia/web/JsiSkSurfaceFactory.js +8 -1
  76. package/lib/module/skia/web/JsiSkSurfaceFactory.js.map +1 -1
  77. package/lib/typescript/src/external/reanimated/index.d.ts +1 -0
  78. package/lib/typescript/src/external/reanimated/moduleWrapper.d.ts +8 -0
  79. package/lib/typescript/src/external/reanimated/renderHelpers.d.ts +5 -0
  80. package/lib/typescript/src/external/reanimated/useSharedValueEffect.d.ts +2 -5
  81. package/lib/typescript/src/headless/index.d.ts +3 -0
  82. package/lib/typescript/src/mock/index.d.ts +1 -2
  83. package/lib/typescript/src/renderer/Container.d.ts +2 -1
  84. package/lib/typescript/src/renderer/Reconciler.d.ts +1 -1
  85. package/lib/typescript/src/renderer/processors/Animations/Animations.d.ts +4 -1
  86. package/libs/ios/libskia.xcframework/Info.plist +5 -5
  87. package/libs/ios/libskia.xcframework/ios-arm64_arm64e/libskia.a +0 -0
  88. package/libs/ios/libskia.xcframework/ios-arm64_arm64e_x86_64-simulator/libskia.a +0 -0
  89. package/libs/ios/libskottie.xcframework/Info.plist +5 -5
  90. package/libs/ios/libskottie.xcframework/ios-arm64_arm64e/libskottie.a +0 -0
  91. package/libs/ios/libskottie.xcframework/ios-arm64_arm64e_x86_64-simulator/libskottie.a +0 -0
  92. package/libs/ios/libsksg.xcframework/Info.plist +5 -5
  93. package/libs/ios/libsksg.xcframework/ios-arm64_arm64e/libsksg.a +0 -0
  94. package/libs/ios/libsksg.xcframework/ios-arm64_arm64e_x86_64-simulator/libsksg.a +0 -0
  95. package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e/libskshaper.a +0 -0
  96. package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e_x86_64-simulator/libskshaper.a +0 -0
  97. package/libs/ios/libsvg.xcframework/ios-arm64_arm64e/libsvg.a +0 -0
  98. package/libs/ios/libsvg.xcframework/ios-arm64_arm64e_x86_64-simulator/libsvg.a +0 -0
  99. package/package.json +1 -1
  100. package/react-native-skia.podspec +7 -26
  101. package/src/external/reanimated/index.ts +1 -0
  102. package/src/external/reanimated/moduleWrapper.ts +62 -0
  103. package/src/external/reanimated/renderHelpers.ts +74 -0
  104. package/src/external/reanimated/useSharedValueEffect.ts +17 -23
  105. package/src/headless/index.ts +31 -0
  106. package/src/mock/index.ts +0 -5
  107. package/src/renderer/Canvas.tsx +6 -2
  108. package/src/renderer/Container.tsx +2 -1
  109. package/src/renderer/HostConfig.ts +8 -2
  110. package/src/renderer/Reconciler.tsx +3 -2
  111. package/src/renderer/processors/Animations/Animations.ts +9 -1
  112. package/src/skia/web/JsiSkSurfaceFactory.ts +6 -3
@@ -49,6 +49,8 @@ add_library(
49
49
 
50
50
  "${PROJECT_SOURCE_DIR}/cpp/jsi/JsiHostObject.cpp"
51
51
  "${PROJECT_SOURCE_DIR}/cpp/jsi/JsiValue.cpp"
52
+ "${PROJECT_SOURCE_DIR}/cpp/jsi/RuntimeLifecycleMonitor.cpp"
53
+ "${PROJECT_SOURCE_DIR}/cpp/jsi/RuntimeAwareCache.cpp"
52
54
 
53
55
  "${PROJECT_SOURCE_DIR}/cpp/rnskia/RNSkManager.cpp"
54
56
  "${PROJECT_SOURCE_DIR}/cpp/rnskia/RNSkJsView.cpp"
@@ -266,8 +266,9 @@ task extractJNIFiles {
266
266
  extractJNIFiles.mustRunAfter extractAARHeaders
267
267
 
268
268
  if (ENABLE_PREFAB) {
269
+ // Package everything with the original file structure
269
270
  task prepareHeaders(type: Copy) {
270
- from fileTree('../cpp').filter { it.isFile() }
271
+ from('./cpp')
271
272
  into "${project.buildDir}/headers/rnskia/"
272
273
  includeEmptyDirs = false
273
274
  }
@@ -55,12 +55,18 @@ jsi::Value JsiHostObject::get(jsi::Runtime &runtime,
55
55
  const jsi::PropNameID &name) {
56
56
  auto nameStr = name.utf8(runtime);
57
57
 
58
- // Do the happy-paths first
58
+ // Happy path - cached host functions are cheapest to look up
59
+ const JsiFunctionMap &funcs = getExportedFunctionMap();
60
+ auto func = funcs.find(nameStr);
59
61
 
60
62
  // Check function cache
61
- auto cachedFunc = _hostFunctionCache.find(nameStr);
62
- if (cachedFunc != _hostFunctionCache.end()) {
63
- return cachedFunc->second.asFunction(runtime);
63
+ if (func != funcs.end()) {
64
+ std::map<std::string, jsi::Function> &runtimeCache =
65
+ _hostFunctionCache.get(runtime);
66
+ auto cachedFunc = runtimeCache.find(nameStr);
67
+ if (cachedFunc != runtimeCache.end()) {
68
+ return cachedFunc->second.asFunction(runtime);
69
+ }
64
70
  }
65
71
 
66
72
  // Check the static getters map
@@ -72,9 +78,9 @@ jsi::Value JsiHostObject::get(jsi::Runtime &runtime,
72
78
  }
73
79
 
74
80
  // Check the static function map
75
- const JsiFunctionMap &funcs = getExportedFunctionMap();
76
- auto func = funcs.find(nameStr);
77
81
  if (func != funcs.end()) {
82
+
83
+ // Create dispatcher
78
84
  auto dispatcher =
79
85
  std::bind(func->second, reinterpret_cast<JsiHostObject *>(this),
80
86
  std::placeholders::_1, std::placeholders::_2,
@@ -82,7 +88,7 @@ jsi::Value JsiHostObject::get(jsi::Runtime &runtime,
82
88
 
83
89
  // Add to cache - it is important to cache the results from the
84
90
  // createFromHostFunction function which takes some time.
85
- return _hostFunctionCache
91
+ return _hostFunctionCache.get(runtime)
86
92
  .emplace(nameStr, jsi::Function::createFromHostFunction(runtime, name,
87
93
  0, dispatcher))
88
94
  .first->second.asFunction(runtime);
@@ -9,6 +9,8 @@
9
9
  #include <unordered_map>
10
10
  #include <vector>
11
11
 
12
+ #include "RuntimeAwareCache.h"
13
+
12
14
  #define STR_CAT_NX(A, B) A##B
13
15
  #define STR_CAT(A, B) STR_CAT_NX(A, B)
14
16
  #define STR_GET get_
@@ -363,6 +365,6 @@ private:
363
365
  std::unordered_map<std::string, jsi::HostFunctionType> _funcMap;
364
366
  std::unordered_map<std::string, JsPropertyType> _propMap;
365
367
 
366
- std::map<std::string, jsi::Function> _hostFunctionCache;
368
+ RuntimeAwareCache<std::map<std::string, jsi::Function>> _hostFunctionCache;
367
369
  };
368
370
  } // namespace RNJsi
@@ -0,0 +1,9 @@
1
+ #pragma once
2
+
3
+ #include "RuntimeAwareCache.h"
4
+
5
+ namespace RNJsi {
6
+
7
+ jsi::Runtime *BaseRuntimeAwareCache::_mainRuntime = nullptr;
8
+
9
+ } // namespace RNJsi
@@ -0,0 +1,101 @@
1
+ #pragma once
2
+
3
+ #include <jsi/jsi.h>
4
+
5
+ #include <memory>
6
+ #include <unordered_map>
7
+ #include <utility>
8
+
9
+ #include "RuntimeLifecycleMonitor.h"
10
+
11
+ namespace RNJsi {
12
+
13
+ namespace jsi = facebook::jsi;
14
+
15
+ class BaseRuntimeAwareCache {
16
+ public:
17
+ static void setMainJsRuntime(jsi::Runtime *rt) { _mainRuntime = rt; }
18
+
19
+ protected:
20
+ static jsi::Runtime *getMainJsRuntime() {
21
+ assert(_mainRuntime != nullptr &&
22
+ "Expected main Javascript runtime to be set in the "
23
+ "BaseRuntimeAwareCache class.");
24
+
25
+ return _mainRuntime;
26
+ }
27
+
28
+ private:
29
+ static jsi::Runtime *_mainRuntime;
30
+ };
31
+
32
+ /**
33
+ * Provides a way to keep data specific to a jsi::Runtime instance that gets
34
+ * cleaned up when that runtime is destroyed. This is necessary because JSI does
35
+ * not allow for its associated objects to be retained past the runtime
36
+ * lifetime. If an object (e.g. jsi::Values or jsi::Function instances) is kept
37
+ * after the runtime is torn down, its destructor (once it is destroyed
38
+ * eventually) will result in a crash (JSI objects keep a pointer to memory
39
+ * managed by the runtime, accessing that portion of the memory after runtime is
40
+ * deleted is the root cause of that crash).
41
+ *
42
+ * In order to provide an efficient implementation that does not add an overhead
43
+ * for the cases when only a single runtiome is used, which is the primary
44
+ * usecase, the following assumption has been made: Only for secondary runtimes
45
+ * we track destruction and clean up the store associated with that runtime. For
46
+ * the first runtime we assume that the object holding the store is destroyed
47
+ * prior to the destruction of that runtime.
48
+ *
49
+ * The above assumption makes it work without any overhead when only single
50
+ * runtime is in use. Specifically, we don't perform any additional operations
51
+ * related to tracking runtime lifecycle when only a single runtime is used.
52
+ */
53
+ template <typename T>
54
+ class RuntimeAwareCache : public BaseRuntimeAwareCache,
55
+ public RuntimeLifecycleListener {
56
+
57
+ public:
58
+ void onRuntimeDestroyed(jsi::Runtime *rt) override {
59
+ if (getMainJsRuntime() != rt) {
60
+ // We are removing a secondary runtime
61
+ _secondaryRuntimeCaches.erase(rt);
62
+ }
63
+ }
64
+
65
+ ~RuntimeAwareCache() {
66
+ for (auto &cache : _secondaryRuntimeCaches) {
67
+ RuntimeLifecycleMonitor::removeListener(
68
+ *static_cast<jsi::Runtime *>(cache.first), this);
69
+ }
70
+ }
71
+
72
+ T &get(jsi::Runtime &rt) {
73
+ // We check if we're accessing the main runtime - this is the happy path
74
+ // to avoid us having to lookup by runtime for caches that only has a single
75
+ // runtime
76
+ if (getMainJsRuntime() == &rt) {
77
+ return _primaryCache;
78
+ } else {
79
+ if (_secondaryRuntimeCaches.count(&rt) == 0) {
80
+ // we only add listener when the secondary runtime is used, this assumes
81
+ // that the secondary runtime is terminated first. This lets us avoid
82
+ // additional complexity for the majority of cases when objects are not
83
+ // shared between runtimes. Otherwise we'd have to register all objecrts
84
+ // with the RuntimeMonitor as opposed to only registering ones that are
85
+ // used in secondary runtime. Note that we can't register listener here
86
+ // with the primary runtime as it may run on a separate thread.
87
+ RuntimeLifecycleMonitor::addListener(rt, this);
88
+
89
+ T cache;
90
+ _secondaryRuntimeCaches.emplace(&rt, std::move(cache));
91
+ }
92
+ }
93
+ return _secondaryRuntimeCaches.at(&rt);
94
+ }
95
+
96
+ private:
97
+ std::unordered_map<void *, T> _secondaryRuntimeCaches;
98
+ T _primaryCache;
99
+ };
100
+
101
+ } // namespace RNJsi
@@ -0,0 +1,57 @@
1
+ #include "RuntimeLifecycleMonitor.h"
2
+
3
+ #include <unordered_map>
4
+ #include <unordered_set>
5
+ #include <utility>
6
+
7
+ namespace RNJsi {
8
+
9
+ static std::unordered_map<jsi::Runtime *,
10
+ std::unordered_set<RuntimeLifecycleListener *>>
11
+ listeners;
12
+
13
+ struct RuntimeLifecycleMonitorObject : public jsi::HostObject {
14
+ jsi::Runtime *_rt;
15
+ explicit RuntimeLifecycleMonitorObject(jsi::Runtime *rt) : _rt(rt) {}
16
+ ~RuntimeLifecycleMonitorObject() {
17
+ auto listenersSet = listeners.find(_rt);
18
+ if (listenersSet != listeners.end()) {
19
+ for (auto listener : listenersSet->second) {
20
+ listener->onRuntimeDestroyed(_rt);
21
+ }
22
+ listeners.erase(listenersSet);
23
+ }
24
+ }
25
+ };
26
+
27
+ void RuntimeLifecycleMonitor::addListener(jsi::Runtime &rt,
28
+ RuntimeLifecycleListener *listener) {
29
+ auto listenersSet = listeners.find(&rt);
30
+ if (listenersSet == listeners.end()) {
31
+ // We install a global host object in the provided runtime, this way we can
32
+ // use that host object destructor to get notified when the runtime is being
33
+ // terminated. We use a unique name for the object as it gets saved with the
34
+ // runtime's global object.
35
+ rt.global().setProperty(
36
+ rt, "__rnskia_rt_lifecycle_monitor",
37
+ jsi::Object::createFromHostObject(
38
+ rt, std::make_shared<RuntimeLifecycleMonitorObject>(&rt)));
39
+ std::unordered_set<RuntimeLifecycleListener *> newSet;
40
+ newSet.insert(listener);
41
+ listeners.emplace(&rt, std::move(newSet));
42
+ } else {
43
+ listenersSet->second.insert(listener);
44
+ }
45
+ }
46
+
47
+ void RuntimeLifecycleMonitor::removeListener(
48
+ jsi::Runtime &rt, RuntimeLifecycleListener *listener) {
49
+ auto listenersSet = listeners.find(&rt);
50
+ if (listenersSet == listeners.end()) {
51
+ // nothing to do here
52
+ } else {
53
+ listenersSet->second.erase(listener);
54
+ }
55
+ }
56
+
57
+ } // namespace RNJsi
@@ -0,0 +1,32 @@
1
+ #pragma once
2
+
3
+ #include <jsi/jsi.h>
4
+
5
+ #include <memory>
6
+
7
+ namespace RNJsi {
8
+
9
+ namespace jsi = facebook::jsi;
10
+
11
+ /**
12
+ * Listener interface that allows for getting notified when a jsi::Runtime
13
+ * instance is destroyed.
14
+ */
15
+ struct RuntimeLifecycleListener {
16
+ virtual ~RuntimeLifecycleListener() {}
17
+ virtual void onRuntimeDestroyed(jsi::Runtime *) = 0;
18
+ };
19
+
20
+ /**
21
+ * This class provides an API via static methods for registering and
22
+ * unregistering runtime lifecycle listeners. The listeners can be used to
23
+ * cleanup any data that references a given jsi::Runtime instance before it gets
24
+ * destroyed.
25
+ */
26
+ struct RuntimeLifecycleMonitor {
27
+ static void addListener(jsi::Runtime &rt, RuntimeLifecycleListener *listener);
28
+ static void removeListener(jsi::Runtime &rt,
29
+ RuntimeLifecycleListener *listener);
30
+ };
31
+
32
+ } // namespace RNJsi
@@ -8,7 +8,7 @@ RNSkJsRenderer::RNSkJsRenderer(std::function<void()> requestRedraw,
8
8
  std::shared_ptr<RNSkPlatformContext> context)
9
9
  : RNSkRenderer(requestRedraw),
10
10
  _jsiCanvas(std::make_shared<JsiSkCanvas>(context)),
11
- _platformContext(std::move(context)),
11
+ _platformContext(context),
12
12
  _infoObject(std::make_shared<RNSkInfoObject>()),
13
13
  _jsDrawingLock(std::make_shared<std::timed_mutex>()),
14
14
  _gpuDrawingLock(std::make_shared<std::timed_mutex>()),
@@ -11,6 +11,7 @@
11
11
  #include <RNSkView.h>
12
12
 
13
13
  #include <JsiDomApi.h>
14
+ #include <RuntimeAwareCache.h>
14
15
 
15
16
  namespace RNSkia {
16
17
  namespace jsi = facebook::jsi;
@@ -23,6 +24,9 @@ RNSkManager::RNSkManager(
23
24
  _platformContext(platformContext),
24
25
  _viewApi(std::make_shared<RNSkJsiViewApi>(platformContext)) {
25
26
 
27
+ // Register main runtime
28
+ BaseRuntimeAwareCache::setMainJsRuntime(_jsRuntime);
29
+
26
30
  // Install bindings
27
31
  installBindings();
28
32
  }
@@ -73,9 +73,29 @@ public:
73
73
  }
74
74
 
75
75
  /**
76
- Empty setProp implementation - compatibility with JS node
76
+ Updates the selected property value
77
77
  */
78
- JSI_HOST_FUNCTION(setProp) { return jsi::Value::undefined(); }
78
+ JSI_HOST_FUNCTION(setProp) {
79
+ if (_propsContainer == nullptr) {
80
+ // TODO: we ignore individual properties updates if the initial properties
81
+ // hasn't been defined. It is likely an error if we reach this branch and
82
+ // perhaps should throw an exception but platformContext isn't available
83
+ // here.
84
+ return jsi::Value::undefined();
85
+ }
86
+ auto propName = arguments[0].asString(runtime).utf8(runtime);
87
+ const jsi::Value &propValue = arguments[1];
88
+
89
+ auto mappedProps = _propsContainer->getMappedProperties();
90
+ auto propMapIt = mappedProps.find(JsiPropId::get(propName));
91
+ if (propMapIt != mappedProps.end()) {
92
+ for (auto &prop : propMapIt->second) {
93
+ prop->updateValue(runtime, propValue);
94
+ }
95
+ }
96
+
97
+ return jsi::Value::undefined();
98
+ }
79
99
 
80
100
  /**
81
101
  JS Function to be called when the node is no longer part of the reconciler
@@ -73,14 +73,18 @@ void RNSkMetalCanvasProvider::renderToCanvas(
73
73
  // background or inactive. This will cause an error that might clear the
74
74
  // CAMetalLayer so that the canvas is empty when the app receives focus again.
75
75
  // Reference: https://github.com/Shopify/react-native-skia/issues/1257
76
- auto state = UIApplication.sharedApplication.applicationState;
77
- if (state == UIApplicationStateBackground ||
78
- state == UIApplicationStateInactive) {
79
- // Request a redraw in the next run loop callback
80
- _requestRedraw();
81
- // and don't draw now since it might cause errors in the metal renderer if
82
- // we try to render while in the background. (see above issue)
83
- return;
76
+ // NOTE: UIApplication.sharedApplication.applicationState can only be
77
+ // accessed from the main thread so we need to check here.
78
+ if ([[NSThread currentThread] isMainThread]) {
79
+ auto state = UIApplication.sharedApplication.applicationState;
80
+ if (state == UIApplicationStateBackground ||
81
+ state == UIApplicationStateInactive) {
82
+ // Request a redraw in the next run loop callback
83
+ _requestRedraw();
84
+ // and don't draw now since it might cause errors in the metal renderer if
85
+ // we try to render while in the background. (see above issue)
86
+ return;
87
+ }
84
88
  }
85
89
 
86
90
  // Get render context for current thread
@@ -1 +1,2 @@
1
1
  export * from "./useSharedValueEffect";
2
+ export * from "./renderHelpers";
@@ -16,4 +16,17 @@ Object.keys(_useSharedValueEffect).forEach(function (key) {
16
16
  }
17
17
  });
18
18
  });
19
+
20
+ var _renderHelpers = require("./renderHelpers");
21
+
22
+ Object.keys(_renderHelpers).forEach(function (key) {
23
+ if (key === "default" || key === "__esModule") return;
24
+ if (key in exports && exports[key] === _renderHelpers[key]) return;
25
+ Object.defineProperty(exports, key, {
26
+ enumerable: true,
27
+ get: function () {
28
+ return _renderHelpers[key];
29
+ }
30
+ });
31
+ });
19
32
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./useSharedValueEffect\";\n"],"mappings":";;;;;;AAAA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA"}
1
+ {"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./useSharedValueEffect\";\nexport * from \"./renderHelpers\";\n"],"mappings":";;;;;;AAAA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA"}
@@ -0,0 +1,8 @@
1
+ import type { SharedValueType } from "../../renderer/processors/Animations";
2
+ export declare const HAS_REANIMATED: boolean;
3
+ export declare function throwOnIncompatibleReanimatedVersion(): void;
4
+ export declare const useSharedValue: any;
5
+ export declare const startMapper: any;
6
+ export declare const stopMapper: any;
7
+ export declare const runOnJS: any;
8
+ export declare const isSharedValue: <T>(value: unknown) => value is SharedValueType<T>;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.stopMapper = exports.startMapper = exports.runOnJS = exports.isSharedValue = exports.HAS_REANIMATED = void 0;
7
+ exports.throwOnIncompatibleReanimatedVersion = throwOnIncompatibleReanimatedVersion;
8
+ exports.useSharedValue = void 0;
9
+
10
+ var _react = require("react");
11
+
12
+ var _Reanimated, _Reanimated2, _Reanimated3, _Reanimated4;
13
+
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ let Reanimated;
16
+
17
+ try {
18
+ Reanimated = require("react-native-reanimated");
19
+ } catch (e) {// Ignore
20
+ }
21
+
22
+ const HAS_REANIMATED = !!Reanimated;
23
+ exports.HAS_REANIMATED = HAS_REANIMATED;
24
+
25
+ function throwOnMissingReanimated() {
26
+ throw new Error("Reanimated was not found, make sure react-native-reanimated package is installed if you want to use \
27
+ react-naitve-skia's integration layer API.");
28
+ }
29
+
30
+ let ReanimatedVersionTested = false;
31
+
32
+ function throwOnIncompatibleReanimatedVersion() {
33
+ if (ReanimatedVersionTested) {
34
+ // we avoid testing version more than once as it won't change and we throw
35
+ // an error when version is incompatible
36
+ return;
37
+ }
38
+
39
+ ReanimatedVersionTested = true;
40
+
41
+ const reanimatedVersion = // eslint-disable-next-line import/extensions
42
+ require("react-native-reanimated/package.json").version; // The first compatible version is 3.0.0 but we need to exclude 3.0.0 pre-releases
43
+ // as they have limited support for the used API.
44
+
45
+
46
+ if (!reanimatedVersion || reanimatedVersion < "3.0.0" || reanimatedVersion.includes("3.0.0-")) {
47
+ throw new Error(`Reanimated version ${reanimatedVersion} is not supported, please upgrade to 3.0.0 or newer.`);
48
+ }
49
+ }
50
+
51
+ const useSharedValue = ((_Reanimated = Reanimated) === null || _Reanimated === void 0 ? void 0 : _Reanimated.useSharedValue) || (value => (0, _react.useMemo)(() => ({
52
+ value
53
+ }), [value]));
54
+
55
+ exports.useSharedValue = useSharedValue;
56
+ const startMapper = ((_Reanimated2 = Reanimated) === null || _Reanimated2 === void 0 ? void 0 : _Reanimated2.startMapper) || throwOnMissingReanimated;
57
+ exports.startMapper = startMapper;
58
+ const stopMapper = ((_Reanimated3 = Reanimated) === null || _Reanimated3 === void 0 ? void 0 : _Reanimated3.stopMapper) || throwOnMissingReanimated;
59
+ exports.stopMapper = stopMapper;
60
+ const runOnJS = ((_Reanimated4 = Reanimated) === null || _Reanimated4 === void 0 ? void 0 : _Reanimated4.runOnJS) || throwOnMissingReanimated;
61
+ exports.runOnJS = runOnJS;
62
+
63
+ const isSharedValue = value => {
64
+ if (!Reanimated) {
65
+ throwOnMissingReanimated();
66
+ }
67
+
68
+ return !!value && Reanimated.isSharedValue(value);
69
+ };
70
+
71
+ exports.isSharedValue = isSharedValue;
72
+ //# sourceMappingURL=moduleWrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Reanimated","require","e","HAS_REANIMATED","throwOnMissingReanimated","Error","ReanimatedVersionTested","throwOnIncompatibleReanimatedVersion","reanimatedVersion","version","includes","useSharedValue","value","useMemo","startMapper","stopMapper","runOnJS","isSharedValue"],"sources":["moduleWrapper.ts"],"sourcesContent":["import { useMemo } from \"react\";\n\nimport type { SharedValueType } from \"../../renderer/processors/Animations\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet Reanimated: any;\n\ntry {\n Reanimated = require(\"react-native-reanimated\");\n} catch (e) {\n // Ignore\n}\n\nexport const HAS_REANIMATED = !!Reanimated;\n\nfunction throwOnMissingReanimated() {\n throw new Error(\n \"Reanimated was not found, make sure react-native-reanimated package is installed if you want to use \\\n react-naitve-skia's integration layer API.\"\n );\n}\n\nlet ReanimatedVersionTested = false;\n\nexport function throwOnIncompatibleReanimatedVersion() {\n if (ReanimatedVersionTested) {\n // we avoid testing version more than once as it won't change and we throw\n // an error when version is incompatible\n return;\n }\n ReanimatedVersionTested = true;\n const reanimatedVersion =\n // eslint-disable-next-line import/extensions\n require(\"react-native-reanimated/package.json\").version;\n // The first compatible version is 3.0.0 but we need to exclude 3.0.0 pre-releases\n // as they have limited support for the used API.\n if (\n !reanimatedVersion ||\n reanimatedVersion < \"3.0.0\" ||\n reanimatedVersion.includes(\"3.0.0-\")\n ) {\n throw new Error(\n `Reanimated version ${reanimatedVersion} is not supported, please upgrade to 3.0.0 or newer.`\n );\n }\n}\n\nexport const useSharedValue =\n Reanimated?.useSharedValue ||\n ((value: number) => useMemo(() => ({ value }), [value]));\n\nexport const startMapper = Reanimated?.startMapper || throwOnMissingReanimated;\nexport const stopMapper = Reanimated?.stopMapper || throwOnMissingReanimated;\nexport const runOnJS = Reanimated?.runOnJS || throwOnMissingReanimated;\nexport const isSharedValue = <T>(\n value: unknown\n): value is SharedValueType<T> => {\n if (!Reanimated) {\n throwOnMissingReanimated();\n }\n return !!value && Reanimated.isSharedValue(value);\n};\n"],"mappings":";;;;;;;;;AAAA;;;;AAIA;AACA,IAAIA,UAAJ;;AAEA,IAAI;EACFA,UAAU,GAAGC,OAAO,CAAC,yBAAD,CAApB;AACD,CAFD,CAEE,OAAOC,CAAP,EAAU,CACV;AACD;;AAEM,MAAMC,cAAc,GAAG,CAAC,CAACH,UAAzB;;;AAEP,SAASI,wBAAT,GAAoC;EAClC,MAAM,IAAIC,KAAJ,CACJ;AACJ,+CAFQ,CAAN;AAID;;AAED,IAAIC,uBAAuB,GAAG,KAA9B;;AAEO,SAASC,oCAAT,GAAgD;EACrD,IAAID,uBAAJ,EAA6B;IAC3B;IACA;IACA;EACD;;EACDA,uBAAuB,GAAG,IAA1B;;EACA,MAAME,iBAAiB,GACrB;EACAP,OAAO,CAAC,sCAAD,CAAP,CAAgDQ,OAFlD,CAPqD,CAUrD;EACA;;;EACA,IACE,CAACD,iBAAD,IACAA,iBAAiB,GAAG,OADpB,IAEAA,iBAAiB,CAACE,QAAlB,CAA2B,QAA3B,CAHF,EAIE;IACA,MAAM,IAAIL,KAAJ,CACH,sBAAqBG,iBAAkB,sDADpC,CAAN;EAGD;AACF;;AAEM,MAAMG,cAAc,GACzB,gBAAAX,UAAU,UAAV,kDAAYW,cAAZ,MACEC,KAAD,IAAmB,IAAAC,cAAA,EAAQ,OAAO;EAAED;AAAF,CAAP,CAAR,EAA2B,CAACA,KAAD,CAA3B,CADpB,CADK;;;AAIA,MAAME,WAAW,GAAG,iBAAAd,UAAU,UAAV,oDAAYc,WAAZ,KAA2BV,wBAA/C;;AACA,MAAMW,UAAU,GAAG,iBAAAf,UAAU,UAAV,oDAAYe,UAAZ,KAA0BX,wBAA7C;;AACA,MAAMY,OAAO,GAAG,iBAAAhB,UAAU,UAAV,oDAAYgB,OAAZ,KAAuBZ,wBAAvC;;;AACA,MAAMa,aAAa,GACxBL,KAD2B,IAEK;EAChC,IAAI,CAACZ,UAAL,EAAiB;IACfI,wBAAwB;EACzB;;EACD,OAAO,CAAC,CAACQ,KAAF,IAAWZ,UAAU,CAACiB,aAAX,CAAyBL,KAAzB,CAAlB;AACD,CAPM"}
@@ -0,0 +1,5 @@
1
+ import type { Container } from "../../renderer/Container";
2
+ import type { AnimatedProps } from "../../renderer/processors";
3
+ import type { Node } from "../../dom/types";
4
+ export declare function extractReanimatedProps(props: AnimatedProps<any>): AnimatedProps<any, never>[];
5
+ export declare function bindReanimatedProps(container: Container, node: Node<any>, reanimatedProps: AnimatedProps<any>): void;
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.bindReanimatedProps = bindReanimatedProps;
7
+ exports.extractReanimatedProps = extractReanimatedProps;
8
+
9
+ var _moduleWrapper = require("./moduleWrapper");
10
+
11
+ /* eslint-disable @typescript-eslint/no-explicit-any */
12
+
13
+ /* eslint-disable reanimated/js-function-in-worklet */
14
+ const _bindings = new WeakMap();
15
+
16
+ function extractReanimatedProps(props) {
17
+ if (!_moduleWrapper.HAS_REANIMATED) {
18
+ return [props, {}];
19
+ }
20
+
21
+ const reanimatedProps = {};
22
+ const otherProps = {};
23
+
24
+ for (const propName in props) {
25
+ if (propName === "children") {
26
+ continue;
27
+ }
28
+
29
+ const propValue = props[propName];
30
+
31
+ if ((0, _moduleWrapper.isSharedValue)(propValue)) {
32
+ reanimatedProps[propName] = propValue;
33
+ otherProps[propName] = propValue.value;
34
+ } else {
35
+ otherProps[propName] = propValue;
36
+ }
37
+ }
38
+
39
+ return [otherProps, reanimatedProps];
40
+ }
41
+
42
+ function bindReanimatedProps(container, node, reanimatedProps) {
43
+ if (!_moduleWrapper.HAS_REANIMATED) {
44
+ return;
45
+ }
46
+
47
+ if (__DEV__) {
48
+ (0, _moduleWrapper.throwOnIncompatibleReanimatedVersion)();
49
+ }
50
+
51
+ const sharedValues = Object.values(reanimatedProps);
52
+
53
+ const previousMapperId = _bindings.get(node);
54
+
55
+ if (previousMapperId !== undefined) {
56
+ (0, _moduleWrapper.stopMapper)(previousMapperId);
57
+ }
58
+
59
+ if (sharedValues.length > 0) {
60
+ const viewId = container.getNativeId();
61
+ const {
62
+ SkiaViewApi
63
+ } = global;
64
+ const mapperId = (0, _moduleWrapper.startMapper)(() => {
65
+ "worklet";
66
+
67
+ for (const propName in reanimatedProps) {
68
+ node && node.setProp(propName, reanimatedProps[propName].value);
69
+ } // On React Native we use the SkiaViewApi to redraw because it can
70
+ // run on the worklet thread (container.redraw can't)
71
+ // if SkiaViewApi is undefined, we are on web and container.redraw()
72
+ // can safely be invoked
73
+
74
+
75
+ if (SkiaViewApi) {
76
+ SkiaViewApi.requestRedraw(viewId);
77
+ } else {
78
+ container.redraw();
79
+ }
80
+ }, sharedValues);
81
+
82
+ _bindings.set(node, mapperId);
83
+ }
84
+ }
85
+ //# sourceMappingURL=renderHelpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_bindings","WeakMap","extractReanimatedProps","props","HAS_REANIMATED","reanimatedProps","otherProps","propName","propValue","isSharedValue","value","bindReanimatedProps","container","node","__DEV__","throwOnIncompatibleReanimatedVersion","sharedValues","Object","values","previousMapperId","get","undefined","stopMapper","length","viewId","getNativeId","SkiaViewApi","global","mapperId","startMapper","setProp","requestRedraw","redraw","set"],"sources":["renderHelpers.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable reanimated/js-function-in-worklet */\nimport type { Container } from \"../../renderer/Container\";\nimport type { AnimatedProps } from \"../../renderer/processors\";\nimport type { Node } from \"../../dom/types\";\n\nimport {\n startMapper,\n stopMapper,\n isSharedValue,\n throwOnIncompatibleReanimatedVersion,\n HAS_REANIMATED,\n} from \"./moduleWrapper\";\n\nconst _bindings = new WeakMap<Node<unknown>, unknown>();\n\nexport function extractReanimatedProps(props: AnimatedProps<any>) {\n if (!HAS_REANIMATED) {\n return [props, {}];\n }\n const reanimatedProps = {} as AnimatedProps<any>;\n const otherProps = {} as AnimatedProps<any>;\n for (const propName in props) {\n if (propName === \"children\") {\n continue;\n }\n const propValue = props[propName];\n if (isSharedValue(propValue)) {\n reanimatedProps[propName] = propValue;\n otherProps[propName] = propValue.value;\n } else {\n otherProps[propName] = propValue;\n }\n }\n return [otherProps, reanimatedProps];\n}\n\nexport function bindReanimatedProps(\n container: Container,\n node: Node<any>,\n reanimatedProps: AnimatedProps<any>\n) {\n if (!HAS_REANIMATED) {\n return;\n }\n if (__DEV__) {\n throwOnIncompatibleReanimatedVersion();\n }\n const sharedValues = Object.values(reanimatedProps);\n const previousMapperId = _bindings.get(node);\n if (previousMapperId !== undefined) {\n stopMapper(previousMapperId);\n }\n if (sharedValues.length > 0) {\n const viewId = container.getNativeId();\n const { SkiaViewApi } = global;\n const mapperId = startMapper(() => {\n \"worklet\";\n for (const propName in reanimatedProps) {\n node && node.setProp(propName, reanimatedProps[propName].value);\n }\n // On React Native we use the SkiaViewApi to redraw because it can\n // run on the worklet thread (container.redraw can't)\n // if SkiaViewApi is undefined, we are on web and container.redraw()\n // can safely be invoked\n if (SkiaViewApi) {\n SkiaViewApi.requestRedraw(viewId);\n } else {\n container.redraw();\n }\n }, sharedValues);\n _bindings.set(node, mapperId);\n }\n}\n"],"mappings":";;;;;;;;AAMA;;AANA;;AACA;AAaA,MAAMA,SAAS,GAAG,IAAIC,OAAJ,EAAlB;;AAEO,SAASC,sBAAT,CAAgCC,KAAhC,EAA2D;EAChE,IAAI,CAACC,6BAAL,EAAqB;IACnB,OAAO,CAACD,KAAD,EAAQ,EAAR,CAAP;EACD;;EACD,MAAME,eAAe,GAAG,EAAxB;EACA,MAAMC,UAAU,GAAG,EAAnB;;EACA,KAAK,MAAMC,QAAX,IAAuBJ,KAAvB,EAA8B;IAC5B,IAAII,QAAQ,KAAK,UAAjB,EAA6B;MAC3B;IACD;;IACD,MAAMC,SAAS,GAAGL,KAAK,CAACI,QAAD,CAAvB;;IACA,IAAI,IAAAE,4BAAA,EAAcD,SAAd,CAAJ,EAA8B;MAC5BH,eAAe,CAACE,QAAD,CAAf,GAA4BC,SAA5B;MACAF,UAAU,CAACC,QAAD,CAAV,GAAuBC,SAAS,CAACE,KAAjC;IACD,CAHD,MAGO;MACLJ,UAAU,CAACC,QAAD,CAAV,GAAuBC,SAAvB;IACD;EACF;;EACD,OAAO,CAACF,UAAD,EAAaD,eAAb,CAAP;AACD;;AAEM,SAASM,mBAAT,CACLC,SADK,EAELC,IAFK,EAGLR,eAHK,EAIL;EACA,IAAI,CAACD,6BAAL,EAAqB;IACnB;EACD;;EACD,IAAIU,OAAJ,EAAa;IACX,IAAAC,mDAAA;EACD;;EACD,MAAMC,YAAY,GAAGC,MAAM,CAACC,MAAP,CAAcb,eAAd,CAArB;;EACA,MAAMc,gBAAgB,GAAGnB,SAAS,CAACoB,GAAV,CAAcP,IAAd,CAAzB;;EACA,IAAIM,gBAAgB,KAAKE,SAAzB,EAAoC;IAClC,IAAAC,yBAAA,EAAWH,gBAAX;EACD;;EACD,IAAIH,YAAY,CAACO,MAAb,GAAsB,CAA1B,EAA6B;IAC3B,MAAMC,MAAM,GAAGZ,SAAS,CAACa,WAAV,EAAf;IACA,MAAM;MAAEC;IAAF,IAAkBC,MAAxB;IACA,MAAMC,QAAQ,GAAG,IAAAC,0BAAA,EAAY,MAAM;MACjC;;MACA,KAAK,MAAMtB,QAAX,IAAuBF,eAAvB,EAAwC;QACtCQ,IAAI,IAAIA,IAAI,CAACiB,OAAL,CAAavB,QAAb,EAAuBF,eAAe,CAACE,QAAD,CAAf,CAA0BG,KAAjD,CAAR;MACD,CAJgC,CAKjC;MACA;MACA;MACA;;;MACA,IAAIgB,WAAJ,EAAiB;QACfA,WAAW,CAACK,aAAZ,CAA0BP,MAA1B;MACD,CAFD,MAEO;QACLZ,SAAS,CAACoB,MAAV;MACD;IACF,CAdgB,EAcdhB,YAdc,CAAjB;;IAeAhB,SAAS,CAACiC,GAAV,CAAcpB,IAAd,EAAoBe,QAApB;EACD;AACF"}
@@ -1,11 +1,8 @@
1
- declare type SharedValueTypeWrapper<T = number> = {
2
- value: T;
3
- };
1
+ import type { SharedValueType } from "../../renderer/processors/Animations";
4
2
  /**
5
3
  * Connects a shared value from reanimated to a SkiaView or Canvas
6
4
  * so whenever the shared value changes the SkiaView will redraw.
7
5
  * @param cb Callback that will be called whenever the shared value changes.
8
6
  * @param values One or more shared values to listen for.
9
7
  */
10
- export declare const useSharedValueEffect: <T = number>(cb: () => void, value: SharedValueTypeWrapper<T>, ...values: SharedValueTypeWrapper<T>[]) => void;
11
- export {};
8
+ export declare const useSharedValueEffect: <T = number>(cb: () => void, value: SharedValueType<T>, ...values: SharedValueType<T>[]) => void;