react-native-worklets 0.10.0 → 0.10.1

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 (47) hide show
  1. package/Common/cpp/worklets/NativeModules/JSIWorkletsModuleProxy.cpp +8 -11
  2. package/Common/cpp/worklets/NativeModules/JSIWorkletsModuleProxy.h +5 -0
  3. package/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp +4 -1
  4. package/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h +4 -1
  5. package/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.cpp +1 -1
  6. package/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.h +11 -8
  7. package/Common/cpp/worklets/SharedItems/Serializable.h +9 -3
  8. package/Common/cpp/worklets/SharedItems/SerializableFactory.cpp +17 -8
  9. package/Common/cpp/worklets/SharedItems/SerializableFactory.h +8 -5
  10. package/Common/cpp/worklets/SharedItems/SerializableRemoteFunction.cpp +34 -76
  11. package/Common/cpp/worklets/SharedItems/SerializableRemoteFunction.h +40 -113
  12. package/Common/cpp/worklets/Tools/RNRuntimeStatus.h +27 -0
  13. package/android/src/main/cpp/worklets/android/WorkletsModule.cpp +6 -2
  14. package/android/src/main/cpp/worklets/android/WorkletsModule.h +2 -0
  15. package/android/src/networking/com/swmansion/worklets/WorkletsModule.kt +0 -3
  16. package/android/src/no-networking/com/swmansion/worklets/WorkletsModule.kt +0 -3
  17. package/apple/worklets/apple/WorkletsModule.mm +6 -4
  18. package/bundleMode/index.js +2 -1
  19. package/lib/module/WorkletsModule/NativeWorklets.native.js +2 -2
  20. package/lib/module/WorkletsModule/NativeWorklets.native.js.map +1 -1
  21. package/lib/module/debug/jsVersion.js +1 -1
  22. package/lib/module/memory/serializable.native.js +15 -9
  23. package/lib/module/memory/serializable.native.js.map +1 -1
  24. package/lib/module/memory/serializableMappingCache.native.js.map +1 -1
  25. package/lib/typescript/WorkletsModule/NativeWorklets.native.d.ts.map +1 -1
  26. package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts +1 -1
  27. package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts.map +1 -1
  28. package/lib/typescript/debug/jsVersion.d.ts +1 -1
  29. package/lib/typescript/deprecated.d.ts +2 -2
  30. package/lib/typescript/memory/serializable.native.d.ts.map +1 -1
  31. package/lib/typescript/memory/serializableMappingCache.native.d.ts +2 -2
  32. package/lib/typescript/memory/serializableMappingCache.native.d.ts.map +1 -1
  33. package/lib/typescript/memory/types.d.ts +0 -4
  34. package/lib/typescript/memory/types.d.ts.map +1 -1
  35. package/package.json +1 -1
  36. package/src/WorkletsModule/NativeWorklets.native.ts +0 -2
  37. package/src/WorkletsModule/workletsModuleProxy.ts +0 -1
  38. package/src/debug/jsVersion.ts +1 -1
  39. package/src/memory/serializable.native.ts +15 -13
  40. package/src/memory/serializableMappingCache.native.ts +8 -2
  41. package/src/memory/types.ts +0 -5
  42. package/src/privateGlobals.d.ts +0 -1
  43. package/lib/module/memory/remoteFunctionRegistry.native.js +0 -12
  44. package/lib/module/memory/remoteFunctionRegistry.native.js.map +0 -1
  45. package/lib/typescript/memory/remoteFunctionRegistry.native.d.ts +0 -3
  46. package/lib/typescript/memory/remoteFunctionRegistry.native.d.ts.map +0 -1
  47. package/src/memory/remoteFunctionRegistry.native.ts +0 -14
@@ -335,25 +335,22 @@ jsi::Object JSIWorkletsModuleProxy::toOptimizedObject(jsi::Runtime &rt) const {
335
335
  return makeSerializableArrayBuffer(rt, buffer);
336
336
  });
337
337
 
338
- jsi_utils::addMethod<3>(
338
+ jsi_utils::addMethod<2>(
339
339
  rt,
340
340
  obj,
341
341
  "createSerializableNonWorkletFunction",
342
- [jsScheduler = jsScheduler_, hostRuntimeId = hostRuntimeId_](
343
- jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[3]) {
342
+ [jsScheduler = jsScheduler_, hostRuntimeId = hostRuntimeId_, rnRuntimeStatus = rnRuntimeStatus_](
343
+ jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[2]) {
344
344
  auto fun = at<0>(args).getObject(rt).getFunction(rt);
345
- const auto name = at<2>(args).isUndefined() ? "" : at<2>(args).getString(rt).utf8(rt);
345
+ const auto name = at<1>(args).isUndefined() ? "" : at<1>(args).getString(rt).utf8(rt);
346
346
  if (fun.isHostFunction(rt)) {
347
347
  return makeSerializableHostFunction(
348
348
  rt, fun.getHostFunction(rt), name, fun.getProperty(rt, "length").getNumber());
349
+ } else if (hostRuntimeId == RuntimeData::rnRuntimeId) {
350
+ return makeRNRuntimeSerializableRemoteFunction(rt, name, fun, jsScheduler, rnRuntimeStatus);
351
+ } else {
352
+ return makeWorkletRuntimeSerializableRemoteFunction(rt, name, fun, hostRuntimeId);
349
353
  }
350
- if (hostRuntimeId == RuntimeData::rnRuntimeId) {
351
- const int remoteId = static_cast<int>(at<1>(args).getNumber());
352
- auto ref = makeRNOriginSerializableRemoteFunction(rt, name, remoteId, jsScheduler);
353
- ref.asObject(rt).setProperty(rt, "__keepAlive", true);
354
- return ref;
355
- }
356
- return makeWorkletOriginSerializableRemoteFunction(rt, name, std::move(fun), hostRuntimeId);
357
354
  });
358
355
 
359
356
  jsi_utils::addMethod<2>(
@@ -4,6 +4,7 @@
4
4
  #include <worklets/SharedItems/MemoryManager.h>
5
5
  #include <worklets/SharedItems/Serializable.h>
6
6
  #include <worklets/SharedItems/UnpackerLoader.h>
7
+ #include <worklets/Tools/RNRuntimeStatus.h>
7
8
  #include <worklets/Tools/ScriptBuffer.h>
8
9
  #include <worklets/WorkletRuntime/BundleModeConfig.h>
9
10
  #include <worklets/WorkletRuntime/RuntimeBindings.h>
@@ -31,6 +32,7 @@ class JSIWorkletsModuleProxy : public std::enable_shared_from_this<JSIWorkletsMo
31
32
  const std::shared_ptr<RuntimeBindings> &runtimeBindings,
32
33
  const BundleModeConfig &bundleModeConfig,
33
34
  const std::shared_ptr<UnpackerLoader> &unpackerLoader,
35
+ const std::shared_ptr<RNRuntimeStatus> &rnRuntimeStatus,
34
36
  RuntimeData::RuntimeId hostRuntimeId)
35
37
  : isDevBundle_(isDevBundle),
36
38
  bundleModeConfig_(bundleModeConfig),
@@ -41,6 +43,7 @@ class JSIWorkletsModuleProxy : public std::enable_shared_from_this<JSIWorkletsMo
41
43
  uiWorkletRuntime_(uiWorkletRuntime),
42
44
  runtimeBindings_(runtimeBindings),
43
45
  unpackerLoader_(unpackerLoader),
46
+ rnRuntimeStatus_(rnRuntimeStatus),
44
47
  hostRuntimeId_(hostRuntimeId) {}
45
48
 
46
49
  static std::shared_ptr<JSIWorkletsModuleProxy> createForNewRuntime(
@@ -56,6 +59,7 @@ class JSIWorkletsModuleProxy : public std::enable_shared_from_this<JSIWorkletsMo
56
59
  sourceProxy->runtimeBindings_,
57
60
  sourceProxy->bundleModeConfig_,
58
61
  sourceProxy->unpackerLoader_,
62
+ sourceProxy->rnRuntimeStatus_,
59
63
  hostRuntimeId);
60
64
  }
61
65
 
@@ -115,6 +119,7 @@ class JSIWorkletsModuleProxy : public std::enable_shared_from_this<JSIWorkletsMo
115
119
  const std::weak_ptr<WorkletRuntime> uiWorkletRuntime_;
116
120
  const std::shared_ptr<RuntimeBindings> runtimeBindings_;
117
121
  const std::shared_ptr<UnpackerLoader> unpackerLoader_;
122
+ const std::shared_ptr<RNRuntimeStatus> rnRuntimeStatus_;
118
123
  const RuntimeData::RuntimeId hostRuntimeId_;
119
124
  };
120
125
 
@@ -45,7 +45,8 @@ WorkletsModuleProxy::WorkletsModuleProxy(
45
45
  const std::shared_ptr<UIScheduler> &uiScheduler,
46
46
  std::function<bool()> &&isJavaScriptThread,
47
47
  const std::shared_ptr<RuntimeBindings> &runtimeBindings,
48
- const BundleModeConfig &bundleModeConfig)
48
+ const BundleModeConfig &bundleModeConfig,
49
+ const std::shared_ptr<RNRuntimeStatus> &rnRuntimeStatus)
49
50
  : isDevBundle_(isDevBundleFromRNRuntime(rnRuntime)),
50
51
  jsScheduler_(std::make_shared<JSScheduler>(rnRuntime, jsCallInvoker, std::move(isJavaScriptThread))),
51
52
  uiScheduler_(uiScheduler),
@@ -55,6 +56,7 @@ WorkletsModuleProxy::WorkletsModuleProxy(
55
56
  memoryManager_(std::make_shared<MemoryManager>()),
56
57
  runtimeManager_(std::make_shared<RuntimeManager>()),
57
58
  unpackerLoader_(std::make_shared<UnpackerLoader>()),
59
+ rnRuntimeStatus_(rnRuntimeStatus),
58
60
  uiWorkletRuntime_(runtimeManager_->createUninitializedUIRuntime(std::make_shared<AsyncQueueUI>(uiScheduler_))),
59
61
  rnRuntimeProxy_(std::make_shared<JSIWorkletsModuleProxy>(
60
62
  isDevBundle_,
@@ -66,6 +68,7 @@ WorkletsModuleProxy::WorkletsModuleProxy(
66
68
  runtimeBindings_,
67
69
  bundleModeConfig_,
68
70
  unpackerLoader_,
71
+ rnRuntimeStatus_,
69
72
  RuntimeData::rnRuntimeId)) {
70
73
  RNRuntimeWorkletDecorator::decorate(rnRuntime, rnRuntimeProxy_->toOptimizedObject(rnRuntime), jsLogger_);
71
74
  }
@@ -7,6 +7,7 @@
7
7
  #include <worklets/SharedItems/UnpackerLoader.h>
8
8
  #include <worklets/Tools/JSLogger.h>
9
9
  #include <worklets/Tools/JSScheduler.h>
10
+ #include <worklets/Tools/RNRuntimeStatus.h>
10
11
  #include <worklets/Tools/ScriptBuffer.h>
11
12
  #include <worklets/Tools/SingleInstanceChecker.h>
12
13
  #include <worklets/Tools/UIScheduler.h>
@@ -28,7 +29,8 @@ class WorkletsModuleProxy : public std::enable_shared_from_this<WorkletsModulePr
28
29
  const std::shared_ptr<UIScheduler> &uiScheduler,
29
30
  std::function<bool()> &&isJavaScriptQueue,
30
31
  const std::shared_ptr<RuntimeBindings> &runtimeBindings,
31
- const BundleModeConfig &bundleModeConfig);
32
+ const BundleModeConfig &bundleModeConfig,
33
+ const std::shared_ptr<RNRuntimeStatus> &rnRuntimeStatus);
32
34
 
33
35
  ~WorkletsModuleProxy();
34
36
 
@@ -62,6 +64,7 @@ class WorkletsModuleProxy : public std::enable_shared_from_this<WorkletsModulePr
62
64
  const std::shared_ptr<MemoryManager> memoryManager_;
63
65
  const std::shared_ptr<RuntimeManager> runtimeManager_;
64
66
  const std::shared_ptr<UnpackerLoader> unpackerLoader_;
67
+ const std::shared_ptr<RNRuntimeStatus> rnRuntimeStatus_;
65
68
  std::shared_ptr<WorkletRuntime> uiWorkletRuntime_;
66
69
  const std::shared_ptr<JSIWorkletsModuleProxy> rnRuntimeProxy_;
67
70
  std::shared_ptr<AnimationFrameBatchinator> animationFrameBatchinator_;
@@ -5,6 +5,6 @@
5
5
  namespace worklets {
6
6
 
7
7
  std::set<jsi::Runtime *> WorkletRuntimeRegistry::registry_{};
8
- std::mutex WorkletRuntimeRegistry::mutex_{};
8
+ std::shared_mutex WorkletRuntimeRegistry::mutex_{};
9
9
 
10
10
  } // namespace worklets
@@ -3,8 +3,9 @@
3
3
  #include <jsi/jsi.h>
4
4
  #include <react/debug/react_native_assert.h>
5
5
 
6
- #include <mutex>
7
6
  #include <set>
7
+ #include <shared_mutex>
8
+ #include <utility>
8
9
 
9
10
  using namespace facebook;
10
11
 
@@ -13,27 +14,29 @@ namespace worklets {
13
14
  class WorkletRuntimeRegistry {
14
15
  private:
15
16
  static std::set<jsi::Runtime *> registry_;
16
- static std::mutex mutex_; // Protects `registry_`.
17
+ static std::shared_mutex mutex_;
17
18
 
18
- WorkletRuntimeRegistry() {} // private ctor
19
+ WorkletRuntimeRegistry() {}
19
20
 
20
21
  static void registerRuntime(jsi::Runtime &runtime) {
21
- std::lock_guard<std::mutex> lock(mutex_);
22
+ std::lock_guard<std::shared_mutex> lock(mutex_);
22
23
  registry_.insert(&runtime);
23
24
  }
24
25
 
25
26
  static void unregisterRuntime(jsi::Runtime &runtime) {
26
- std::lock_guard<std::mutex> lock(mutex_);
27
+ std::lock_guard<std::shared_mutex> lock(mutex_);
27
28
  registry_.erase(&runtime);
28
29
  }
29
30
 
30
31
  friend class WorkletRuntimeCollector;
31
32
 
32
33
  public:
33
- static bool isRuntimeAlive(jsi::Runtime *runtime) {
34
+ template <typename TFn>
35
+ static void runWhileLocked(jsi::Runtime *runtime, TFn &&fn) {
34
36
  react_native_assert(runtime != nullptr && "runtime is nullptr");
35
- std::lock_guard<std::mutex> lock(mutex_);
36
- return registry_.find(runtime) != registry_.end();
37
+ std::shared_lock<std::shared_mutex> lock(mutex_);
38
+ const bool isAlive = registry_.find(runtime) != registry_.end();
39
+ std::forward<TFn>(fn)(isAlive);
37
40
  }
38
41
  };
39
42
 
@@ -11,7 +11,6 @@
11
11
  #include <optional>
12
12
  #include <string>
13
13
  #include <utility>
14
- #include <variant>
15
14
  #include <vector>
16
15
 
17
16
  using namespace facebook;
@@ -31,9 +30,16 @@ inline void freeWithoutCallingDestructor(std::unique_ptr<jsi::Value> &value) {
31
30
  }
32
31
 
33
32
  inline void cleanupRuntimeAware(jsi::Runtime *rt, std::unique_ptr<jsi::Value> &value) {
34
- if (rt != nullptr && !WorkletRuntimeRegistry::isRuntimeAlive(rt)) {
35
- freeWithoutCallingDestructor(value);
33
+ if (value == nullptr || rt == nullptr) {
34
+ return;
36
35
  }
36
+ WorkletRuntimeRegistry::runWhileLocked(rt, [&value](bool isAlive) {
37
+ if (isAlive) {
38
+ value.reset();
39
+ } else {
40
+ freeWithoutCallingDestructor(value);
41
+ }
42
+ });
37
43
  }
38
44
 
39
45
  template <typename BaseClass>
@@ -61,22 +61,31 @@ jsi::Value makeSerializableHostFunction(
61
61
  return SerializableJSRef::newNativeStateObject(rt, serializable);
62
62
  }
63
63
 
64
- jsi::Value makeRNOriginSerializableRemoteFunction(
64
+ jsi::Value makeRNRuntimeSerializableRemoteFunction(
65
65
  jsi::Runtime &rnRuntime,
66
66
  const std::string &name,
67
- const int remoteId,
68
- const std::shared_ptr<JSScheduler> &jsScheduler) {
69
- auto serializable = std::make_shared<SerializableRemoteFunction::RNOrigin>(rnRuntime, name, remoteId, jsScheduler);
67
+ const jsi::Function &function,
68
+ const std::shared_ptr<JSScheduler> &jsScheduler,
69
+ const std::shared_ptr<RNRuntimeStatus> &rnRuntimeStatus) {
70
+ auto serializable = std::make_shared<SerializableRemoteFunction>(
71
+ rnRuntime,
72
+ name,
73
+ jsi::Value(rnRuntime, function).getObject(rnRuntime).getFunction(rnRuntime),
74
+ jsScheduler,
75
+ rnRuntimeStatus);
70
76
  return SerializableJSRef::newNativeStateObject(rnRuntime, serializable);
71
77
  }
72
78
 
73
- jsi::Value makeWorkletOriginSerializableRemoteFunction(
79
+ jsi::Value makeWorkletRuntimeSerializableRemoteFunction(
74
80
  jsi::Runtime &workletRuntime,
75
81
  const std::string &name,
76
- jsi::Function &&function,
82
+ const jsi::Function &function,
77
83
  RuntimeData::RuntimeId hostRuntimeId) {
78
- auto serializable = std::make_shared<SerializableRemoteFunction::WorkletOrigin>(
79
- workletRuntime, name, std::move(function), hostRuntimeId);
84
+ auto serializable = std::make_shared<SerializableRemoteFunction>(
85
+ workletRuntime,
86
+ name,
87
+ jsi::Value(workletRuntime, function).getObject(workletRuntime).getFunction(workletRuntime),
88
+ hostRuntimeId);
80
89
  return SerializableJSRef::newNativeStateObject(workletRuntime, serializable);
81
90
  }
82
91
 
@@ -9,6 +9,8 @@
9
9
 
10
10
  namespace worklets {
11
11
 
12
+ class RNRuntimeStatus;
13
+
12
14
  jsi::Value makeSerializableString(jsi::Runtime &rt, const jsi::String &string);
13
15
 
14
16
  jsi::Value makeSerializableNumber(jsi::Runtime &rt, double number);
@@ -63,16 +65,17 @@ jsi::Value makeSerializableHostFunction(
63
65
  const std::string &name,
64
66
  unsigned int paramCount);
65
67
 
66
- jsi::Value makeRNOriginSerializableRemoteFunction(
68
+ jsi::Value makeRNRuntimeSerializableRemoteFunction(
67
69
  jsi::Runtime &rnRuntime,
68
70
  const std::string &name,
69
- int remoteId,
70
- const std::shared_ptr<JSScheduler> &jsScheduler);
71
+ const jsi::Function &function,
72
+ const std::shared_ptr<JSScheduler> &jsScheduler,
73
+ const std::shared_ptr<RNRuntimeStatus> &rnRuntimeStatus);
71
74
 
72
- jsi::Value makeWorkletOriginSerializableRemoteFunction(
75
+ jsi::Value makeWorkletRuntimeSerializableRemoteFunction(
73
76
  jsi::Runtime &workletRuntime,
74
77
  const std::string &name,
75
- jsi::Function &&function,
78
+ const jsi::Function &function,
76
79
  RuntimeData::RuntimeId hostRuntimeId);
77
80
 
78
81
  jsi::Value makeSerializableWorklet(jsi::Runtime &rt, const jsi::Object &object, const bool &shouldRetainRemote);
@@ -6,7 +6,6 @@
6
6
  #include <worklets/WorkletRuntime/WorkletRuntime.h>
7
7
 
8
8
  #include <memory>
9
- #include <utility>
10
9
 
11
10
  using namespace facebook;
12
11
 
@@ -20,94 +19,53 @@ jsi::Function getRemoteFunctionUnpacker(jsi::Runtime &rt) {
20
19
  return remoteFunctionUnpacker.asObject(rt).asFunction(rt);
21
20
  }
22
21
 
23
- jsi::Object getRemoteFunctionRegistry(jsi::Runtime &rt) {
24
- auto registry = rt.global().getProperty(rt, "__remoteFunctionRegistry");
25
- react_native_assert(registry.isObject() && "remoteFunctionRegistry not found");
26
- return registry.getObject(rt);
27
- }
28
-
29
22
  } // namespace
30
23
 
31
- SerializableRemoteFunction::~SerializableRemoteFunction() = default;
32
-
33
- jsi::Value SerializableRemoteFunction::unpackSelf(jsi::Runtime &rt) {
34
- const auto nameValue = name_.empty() ? jsi::Value::undefined() : jsi::String::createFromUtf8(rt, name_);
35
- auto holderFunction = getRemoteFunctionUnpacker(rt).call(rt, nameValue).getObject(rt);
36
- holderFunction.setNativeState(rt, std::make_shared<SerializableJSRef>(shared_from_this()));
37
- return holderFunction;
38
- }
39
-
40
- jsi::Value SerializableRemoteFunction::RNOrigin::toJSValue(jsi::Runtime &rt) {
41
- if (&rt == hostRuntime_) {
42
- const auto registry = getRemoteFunctionRegistry(rt);
43
- return registry.getPropertyAsFunction(rt, "get").callWithThis(rt, registry, jsi::Value(remoteId_));
24
+ SerializableRemoteFunction::~SerializableRemoteFunction() {
25
+ if (isHostedOnRNRuntime()) {
26
+ rnRuntimeStatus_->runWhileLocked([this](bool isDead) {
27
+ if (isDead) {
28
+ freeWithoutCallingDestructor(function_);
29
+ } else {
30
+ function_.reset();
31
+ }
32
+ });
33
+ } else {
34
+ cleanupRuntimeAware(hostRuntime_, function_);
44
35
  }
45
- std::shared_ptr<SerializableRemoteFunction> proxy;
46
- {
47
- std::lock_guard<std::mutex> lock(proxyMutex_);
48
- proxy = proxy_.lock();
49
- if (!proxy) {
50
- auto self = std::static_pointer_cast<RNOrigin>(shared_from_this());
51
- proxy = std::make_shared<RNOriginProxy>(self);
52
- proxy_ = proxy;
53
- }
54
- }
55
- return proxy->toJSValue(rt);
56
- }
57
-
58
- void SerializableRemoteFunction::RNOrigin::resolveOrRejectPromise(
59
- const std::shared_ptr<Serializable> &resolveValue,
60
- const std::shared_ptr<RuntimeManager> & /*runtimeManager*/) {
61
- jsScheduler_->scheduleOnJS([resolver = shared_from_this(), resolveValue](jsi::Runtime &rt) {
62
- resolver->toJSValue(rt).getObject(rt).getFunction(rt).call(rt, resolveValue->toJSValue(rt));
63
- });
64
- }
65
-
66
- SerializableRemoteFunction::WorkletOrigin::~WorkletOrigin() {
67
- cleanupRuntimeAware(hostRuntime_, function_);
68
36
  }
69
37
 
70
- jsi::Value SerializableRemoteFunction::WorkletOrigin::toJSValue(jsi::Runtime &rt) {
38
+ jsi::Value SerializableRemoteFunction::toJSValue(jsi::Runtime &rt) {
71
39
  if (&rt == hostRuntime_) {
72
40
  return jsi::Value(rt, *function_);
41
+ } else {
42
+ const auto name = name_.empty() ? jsi::Value::undefined() : jsi::String::createFromUtf8(rt, name_);
43
+ auto holderFunction = getRemoteFunctionUnpacker(rt).call(rt, name).getObject(rt);
44
+ holderFunction.setNativeState(rt, std::make_shared<SerializableJSRef>(shared_from_this()));
45
+ return holderFunction;
73
46
  }
74
- return unpackSelf(rt);
75
47
  }
76
48
 
77
- void SerializableRemoteFunction::WorkletOrigin::resolveOrRejectPromise(
49
+ // TODO: generalize it and merge with other scheduling methods
50
+ void SerializableRemoteFunction::resolveOrRejectPromise(
78
51
  const std::shared_ptr<Serializable> &resolveValue,
79
52
  const std::shared_ptr<RuntimeManager> &runtimeManager) {
80
- const auto workletRuntime = runtimeManager->getRuntime(hostRuntimeId_);
81
- // NOLINTNEXTLINE(readability/braces)
82
- if (!workletRuntime) [[unlikely]] {
83
- return;
84
- }
85
- workletRuntime->schedule([resolver = shared_from_this(), resolveValue](jsi::Runtime &rt) {
86
- resolver->toJSValue(rt).getObject(rt).getFunction(rt).call(rt, resolveValue->toJSValue(rt));
87
- });
88
- }
89
-
90
- SerializableRemoteFunction::RNOrigin::RNOriginProxy::RNOriginProxy(const std::shared_ptr<RNOrigin> &origin)
91
- : SerializableRemoteFunction(nullptr, origin->getHostRuntimeId(), origin->getName()), origin_(origin) {}
92
-
93
- SerializableRemoteFunction::RNOrigin::RNOriginProxy::~RNOriginProxy() {
94
- origin_->getJSScheduler()->scheduleOnJS([id = origin_->getRemoteId()](jsi::Runtime &rt) {
95
- const auto registry = getRemoteFunctionRegistry(rt);
96
- registry.getPropertyAsFunction(rt, "delete").callWithThis(rt, registry, jsi::Value(id));
97
- });
98
- }
99
-
100
- jsi::Value SerializableRemoteFunction::RNOrigin::RNOriginProxy::toJSValue(jsi::Runtime &rt) {
101
- if (&rt == origin_->getHostRuntime()) {
102
- return origin_->toJSValue(rt);
53
+ if (isHostedOnRNRuntime()) {
54
+ jsScheduler_->scheduleOnJS([resolver = shared_from_this(), resolveValue](jsi::Runtime &rt) {
55
+ resolver->toJSValue(rt).getObject(rt).getFunction(rt).call(rt, resolveValue->toJSValue(rt));
56
+ });
57
+ } else {
58
+ const auto workletRuntime = runtimeManager->getRuntime(hostRuntimeId_);
59
+ // NOLINTNEXTLINE(readability/braces)
60
+ if (!workletRuntime) [[unlikely]] {
61
+ // Host runtime is dead, most likely we're the last owner of the Remote Function.
62
+ // Do nothing.
63
+ } else {
64
+ workletRuntime->schedule([resolver = shared_from_this(), resolveValue](jsi::Runtime &rt) {
65
+ resolver->toJSValue(rt).getObject(rt).getFunction(rt).call(rt, resolveValue->toJSValue(rt));
66
+ });
67
+ }
103
68
  }
104
- return unpackSelf(rt);
105
- }
106
-
107
- void SerializableRemoteFunction::RNOrigin::RNOriginProxy::resolveOrRejectPromise(
108
- const std::shared_ptr<Serializable> &resolveValue,
109
- const std::shared_ptr<RuntimeManager> &runtimeManager) {
110
- origin_->resolveOrRejectPromise(resolveValue, runtimeManager);
111
69
  }
112
70
 
113
71
  } // namespace worklets
@@ -3,12 +3,10 @@
3
3
  #include <jsi/jsi.h>
4
4
  #include <worklets/SharedItems/Serializable.h>
5
5
  #include <worklets/Tools/JSScheduler.h>
6
- #include <worklets/WorkletRuntime/RuntimeData.h>
6
+ #include <worklets/Tools/RNRuntimeStatus.h>
7
7
 
8
8
  #include <memory>
9
- #include <mutex>
10
9
  #include <string>
11
- #include <utility>
12
10
 
13
11
  namespace worklets {
14
12
 
@@ -17,132 +15,61 @@ class RuntimeManager;
17
15
  class SerializableRemoteFunction : public Serializable,
18
16
  public std::enable_shared_from_this<SerializableRemoteFunction> {
19
17
  public:
20
- class RNOrigin;
21
- class WorkletOrigin;
18
+ /** Creates RN Runtime Remote Function. */
19
+ SerializableRemoteFunction(
20
+ jsi::Runtime &rnRuntime,
21
+ const std::string &name,
22
+ jsi::Function &&function,
23
+ const std::shared_ptr<JSScheduler> &jsScheduler,
24
+ const std::shared_ptr<RNRuntimeStatus> &rnRuntimeStatus)
25
+ : Serializable(ValueType::RemoteFunctionType),
26
+ hostRuntime_(&rnRuntime),
27
+ hostRuntimeId_(RuntimeData::rnRuntimeId),
28
+ function_(std::make_unique<jsi::Value>(rnRuntime, std::move(function))),
29
+ name_(name),
30
+ jsScheduler_(jsScheduler),
31
+ rnRuntimeStatus_(rnRuntimeStatus) {}
32
+
33
+ /** Creates Worklet Runtime Remote Function. */
34
+ SerializableRemoteFunction(
35
+ jsi::Runtime &workletRuntime,
36
+ const std::string &name,
37
+ jsi::Function &&function,
38
+ RuntimeData::RuntimeId hostRuntimeId)
39
+ : Serializable(ValueType::RemoteFunctionType),
40
+ hostRuntime_(&workletRuntime),
41
+ hostRuntimeId_(hostRuntimeId),
42
+ function_(std::make_unique<jsi::Value>(workletRuntime, std::move(function))),
43
+ name_(name),
44
+ jsScheduler_(nullptr),
45
+ rnRuntimeStatus_(nullptr) {}
22
46
 
23
47
  ~SerializableRemoteFunction() override;
24
48
 
25
49
  SerializableRemoteFunction(const SerializableRemoteFunction &) = delete;
26
50
  SerializableRemoteFunction &operator=(const SerializableRemoteFunction &) = delete;
27
51
 
28
- facebook::jsi::Value toJSValue(facebook::jsi::Runtime &rt) override = 0;
29
-
30
- virtual void resolveOrRejectPromise(
52
+ void resolveOrRejectPromise(
31
53
  const std::shared_ptr<Serializable> &resolveValue,
32
- const std::shared_ptr<RuntimeManager> &runtimeManager) = 0;
54
+ const std::shared_ptr<RuntimeManager> &runtimeManager);
33
55
 
34
- [[nodiscard]] virtual bool isHostedOnRNRuntime() const noexcept = 0;
35
-
36
- [[nodiscard]] RuntimeData::RuntimeId getHostRuntimeId() const {
37
- return hostRuntimeId_;
38
- }
56
+ jsi::Value toJSValue(jsi::Runtime &rt) override;
39
57
 
40
- [[nodiscard]] facebook::jsi::Runtime *getHostRuntime() const {
41
- return hostRuntime_;
58
+ [[nodiscard]] bool isHostedOnRNRuntime() const noexcept {
59
+ return hostRuntimeId_ == RuntimeData::rnRuntimeId;
42
60
  }
43
61
 
44
- [[nodiscard]] const std::string &getName() const {
45
- return name_;
62
+ [[nodiscard]] RuntimeData::RuntimeId getHostRuntimeId() const noexcept {
63
+ return hostRuntimeId_;
46
64
  }
47
65
 
48
- protected:
49
- facebook::jsi::Runtime *hostRuntime_;
66
+ private:
67
+ jsi::Runtime *hostRuntime_;
50
68
  const RuntimeData::RuntimeId hostRuntimeId_;
69
+ std::unique_ptr<jsi::Value> function_;
51
70
  const std::string name_;
52
-
53
- SerializableRemoteFunction(
54
- facebook::jsi::Runtime *hostRuntime,
55
- RuntimeData::RuntimeId hostRuntimeId,
56
- const std::string &name)
57
- : Serializable(ValueType::RemoteFunctionType),
58
- hostRuntime_(hostRuntime),
59
- hostRuntimeId_(hostRuntimeId),
60
- name_(name) {}
61
-
62
- facebook::jsi::Value unpackSelf(facebook::jsi::Runtime &rt);
63
- };
64
-
65
- class SerializableRemoteFunction::RNOrigin final : public SerializableRemoteFunction {
66
- public:
67
- RNOrigin(
68
- facebook::jsi::Runtime &rnRuntime,
69
- const std::string &name,
70
- int remoteId,
71
- const std::shared_ptr<JSScheduler> &jsScheduler)
72
- : SerializableRemoteFunction(&rnRuntime, RuntimeData::rnRuntimeId, name),
73
- remoteId_(remoteId),
74
- jsScheduler_(jsScheduler) {}
75
-
76
- facebook::jsi::Value toJSValue(facebook::jsi::Runtime &rt) override;
77
-
78
- void resolveOrRejectPromise(
79
- const std::shared_ptr<Serializable> &resolveValue,
80
- const std::shared_ptr<RuntimeManager> &runtimeManager) override;
81
-
82
- [[nodiscard]] bool isHostedOnRNRuntime() const noexcept override {
83
- return true;
84
- }
85
-
86
- [[nodiscard]] int getRemoteId() const {
87
- return remoteId_;
88
- }
89
- [[nodiscard]] const std::shared_ptr<JSScheduler> &getJSScheduler() const {
90
- return jsScheduler_;
91
- }
92
-
93
- private:
94
- class RNOriginProxy;
95
-
96
- const int remoteId_;
97
71
  const std::shared_ptr<JSScheduler> jsScheduler_;
98
- std::weak_ptr<SerializableRemoteFunction> proxy_;
99
- std::mutex proxyMutex_;
100
- };
101
-
102
- class SerializableRemoteFunction::WorkletOrigin final : public SerializableRemoteFunction {
103
- public:
104
- WorkletOrigin(
105
- facebook::jsi::Runtime &workletRuntime,
106
- const std::string &name,
107
- facebook::jsi::Function &&function,
108
- RuntimeData::RuntimeId hostRuntimeId)
109
- : SerializableRemoteFunction(&workletRuntime, hostRuntimeId, name),
110
- function_(std::make_unique<facebook::jsi::Value>(workletRuntime, std::move(function))) {}
111
-
112
- ~WorkletOrigin() override;
113
-
114
- facebook::jsi::Value toJSValue(facebook::jsi::Runtime &rt) override;
115
-
116
- void resolveOrRejectPromise(
117
- const std::shared_ptr<Serializable> &resolveValue,
118
- const std::shared_ptr<RuntimeManager> &runtimeManager) override;
119
-
120
- [[nodiscard]] bool isHostedOnRNRuntime() const noexcept override {
121
- return false;
122
- }
123
-
124
- private:
125
- std::unique_ptr<facebook::jsi::Value> function_;
126
- };
127
-
128
- class SerializableRemoteFunction::RNOrigin::RNOriginProxy final : public SerializableRemoteFunction {
129
- public:
130
- explicit RNOriginProxy(const std::shared_ptr<RNOrigin> &origin);
131
-
132
- ~RNOriginProxy() override;
133
-
134
- facebook::jsi::Value toJSValue(facebook::jsi::Runtime &rt) override;
135
-
136
- void resolveOrRejectPromise(
137
- const std::shared_ptr<Serializable> &resolveValue,
138
- const std::shared_ptr<RuntimeManager> &runtimeManager) override;
139
-
140
- [[nodiscard]] bool isHostedOnRNRuntime() const noexcept override {
141
- return false;
142
- }
143
-
144
- private:
145
- std::shared_ptr<RNOrigin> origin_;
72
+ const std::shared_ptr<RNRuntimeStatus> rnRuntimeStatus_;
146
73
  };
147
74
 
148
75
  } // namespace worklets
@@ -0,0 +1,27 @@
1
+ #pragma once
2
+
3
+ #include <shared_mutex>
4
+ #include <utility>
5
+
6
+ namespace worklets {
7
+
8
+ class RNRuntimeStatus {
9
+ public:
10
+ void setDead() {
11
+ std::lock_guard<std::shared_mutex> lock(mutex_);
12
+ isDead_ = true;
13
+ }
14
+
15
+ template <typename TFn>
16
+ void runWhileLocked(TFn &&fn) {
17
+ std::shared_lock<std::shared_mutex> lock(mutex_);
18
+ const bool isDead = isDead_;
19
+ std::forward<TFn>(fn)(isDead);
20
+ }
21
+
22
+ private:
23
+ bool isDead_ = false;
24
+ std::shared_mutex mutex_;
25
+ };
26
+
27
+ } // namespace worklets