react-native-worklets 0.9.1 → 0.9.3

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 (52) 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.cpp +9 -23
  8. package/Common/cpp/worklets/SharedItems/Serializable.h +30 -25
  9. package/Common/cpp/worklets/SharedItems/SerializableFactory.cpp +9 -3
  10. package/Common/cpp/worklets/SharedItems/SerializableFactory.h +3 -2
  11. package/Common/cpp/worklets/SharedItems/UnpackerLoader.h +38 -31
  12. package/Common/cpp/worklets/Tools/RNRuntimeStatus.h +27 -0
  13. package/android/build.gradle.kts +5 -1
  14. package/android/fix-prefab.gradle.kts +5 -1
  15. package/android/src/main/cpp/worklets/android/WorkletsModule.cpp +4 -1
  16. package/android/src/main/cpp/worklets/android/WorkletsModule.h +2 -0
  17. package/android/src/networking/com/swmansion/worklets/WorkletsModule.kt +0 -3
  18. package/android/src/no-networking/com/swmansion/worklets/WorkletsModule.kt +0 -3
  19. package/apple/worklets/apple/WorkletsModule.mm +8 -4
  20. package/bundleMode/index.js +19 -3
  21. package/lib/module/WorkletsModule/NativeWorklets.native.js +2 -2
  22. package/lib/module/WorkletsModule/NativeWorklets.native.js.map +1 -1
  23. package/lib/module/debug/jsVersion.js +1 -1
  24. package/lib/module/memory/serializable.native.js +13 -7
  25. package/lib/module/memory/serializable.native.js.map +1 -1
  26. package/lib/module/memory/serializableMappingCache.native.js.map +1 -1
  27. package/lib/module/privateGlobals.d.js +0 -1
  28. package/lib/module/privateGlobals.d.js.map +1 -1
  29. package/lib/typescript/WorkletsModule/NativeWorklets.native.d.ts.map +1 -1
  30. package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts +1 -1
  31. package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts.map +1 -1
  32. package/lib/typescript/debug/jsVersion.d.ts +1 -1
  33. package/lib/typescript/deprecated.d.ts +2 -2
  34. package/lib/typescript/memory/serializable.native.d.ts.map +1 -1
  35. package/lib/typescript/memory/serializableMappingCache.native.d.ts +2 -2
  36. package/lib/typescript/memory/serializableMappingCache.native.d.ts.map +1 -1
  37. package/lib/typescript/memory/types.d.ts +0 -4
  38. package/lib/typescript/memory/types.d.ts.map +1 -1
  39. package/package.json +2 -1
  40. package/plugin/index.js +8 -8
  41. package/src/WorkletsModule/NativeWorklets.native.ts +0 -2
  42. package/src/WorkletsModule/workletsModuleProxy.ts +0 -1
  43. package/src/debug/jsVersion.ts +1 -1
  44. package/src/memory/serializable.native.ts +14 -12
  45. package/src/memory/serializableMappingCache.native.ts +8 -2
  46. package/src/memory/types.ts +0 -5
  47. package/src/privateGlobals.d.ts +0 -2
  48. package/lib/module/memory/remoteFunctionRegistry.native.js +0 -12
  49. package/lib/module/memory/remoteFunctionRegistry.native.js.map +0 -1
  50. package/lib/typescript/memory/remoteFunctionRegistry.native.d.ts +0 -3
  51. package/lib/typescript/memory/remoteFunctionRegistry.native.d.ts.map +0 -1
  52. package/src/memory/remoteFunctionRegistry.native.ts +0 -14
@@ -336,25 +336,22 @@ jsi::Object JSIWorkletsModuleProxy::toOptimizedObject(jsi::Runtime &rt) const {
336
336
  return makeSerializableArrayBuffer(rt, buffer);
337
337
  });
338
338
 
339
- jsi_utils::addMethod<3>(
339
+ jsi_utils::addMethod<2>(
340
340
  rt,
341
341
  obj,
342
342
  "createSerializableNonWorkletFunction",
343
- [jsScheduler = jsScheduler_, hostRuntimeId = hostRuntimeId_](
344
- jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[3]) {
343
+ [jsScheduler = jsScheduler_, hostRuntimeId = hostRuntimeId_, rnRuntimeStatus = rnRuntimeStatus_](
344
+ jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[2]) {
345
345
  auto fun = at<0>(args).getObject(rt).getFunction(rt);
346
- const auto name = at<2>(args).isUndefined() ? "" : at<2>(args).getString(rt).utf8(rt);
346
+ const auto name = at<1>(args).isUndefined() ? "" : at<1>(args).getString(rt).utf8(rt);
347
347
  if (fun.isHostFunction(rt)) {
348
348
  return makeSerializableHostFunction(
349
349
  rt, fun.getHostFunction(rt), name, fun.getProperty(rt, "length").getNumber());
350
+ } else if (hostRuntimeId == RuntimeData::rnRuntimeId) {
351
+ return makeSerializableRemoteFunction(rt, name, fun, jsScheduler, rnRuntimeStatus);
352
+ } else {
353
+ return makeSerializableRemoteFunction(rt, name, std::move(fun), hostRuntimeId);
350
354
  }
351
- if (hostRuntimeId == RuntimeData::rnRuntimeId) {
352
- const int remoteId = static_cast<int>(at<1>(args).getNumber());
353
- auto ref = makeSerializableRemoteFunction(rt, name, remoteId, jsScheduler);
354
- ref.asObject(rt).setProperty(rt, "__keepAlive", true);
355
- return ref;
356
- }
357
- return makeSerializableRemoteFunction(rt, name, std::move(fun), hostRuntimeId);
358
355
  });
359
356
 
360
357
  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
 
@@ -28,12 +28,6 @@ jsi::Function getRemoteFunctionUnpacker(jsi::Runtime &rt) {
28
28
  return remoteFunctionUnpacker.asObject(rt).asFunction(rt);
29
29
  }
30
30
 
31
- jsi::Object getRemoteFunctionRegistry(jsi::Runtime &rt) {
32
- auto registry = rt.global().getProperty(rt, "__remoteFunctionRegistry");
33
- react_native_assert(registry.isObject() && "remoteFunctionRegistry not found");
34
- return registry.getObject(rt);
35
- }
36
-
37
31
  } // namespace
38
32
 
39
33
  jsi::Value makeSerializableClone(
@@ -298,28 +292,21 @@ jsi::Value SerializableImport::toJSValue(jsi::Runtime &rt) {
298
292
 
299
293
  SerializableRemoteFunction::~SerializableRemoteFunction() {
300
294
  if (isHostedOnRNRuntime()) {
301
- // TODO: consider batching
302
- const auto &data = std::get<RNRuntimeData>(runtimeData_);
303
- data.jsScheduler->scheduleOnJS([id = data.remoteId](jsi::Runtime &rt) {
304
- const auto registry = getRemoteFunctionRegistry(rt);
305
- registry.getPropertyAsFunction(rt, "delete").callWithThis(rt, registry, jsi::Value(id));
295
+ rnRuntimeStatus_->runWhileLocked([this](bool isDead) {
296
+ if (isDead) {
297
+ freeWithoutCallingDestructor(function_);
298
+ } else {
299
+ function_.reset();
300
+ }
306
301
  });
307
302
  } else {
308
- auto &workletData = std::get<WorkletRuntimeData>(runtimeData_);
309
- cleanupRuntimeAware(hostRuntime_, workletData.function);
303
+ cleanupRuntimeAware(hostRuntime_, function_);
310
304
  }
311
305
  }
312
306
 
313
307
  jsi::Value SerializableRemoteFunction::toJSValue(jsi::Runtime &rt) {
314
308
  if (&rt == hostRuntime_) {
315
- if (isHostedOnRNRuntime()) {
316
- const auto &rnData = std::get<RNRuntimeData>(runtimeData_);
317
- const auto registry = getRemoteFunctionRegistry(rt);
318
- return registry.getPropertyAsFunction(rt, "get").callWithThis(rt, registry, jsi::Value(rnData.remoteId));
319
- } else {
320
- const auto &workletData = std::get<WorkletRuntimeData>(runtimeData_);
321
- return jsi::Value(rt, *workletData.function);
322
- }
309
+ return jsi::Value(rt, *function_);
323
310
  } else {
324
311
  const auto name = name_.empty() ? jsi::Value::undefined() : jsi::String::createFromUtf8(rt, name_);
325
312
  auto holderFunction = getRemoteFunctionUnpacker(rt).call(rt, name).getObject(rt);
@@ -333,8 +320,7 @@ void SerializableRemoteFunction::resolveOrRejectPromise(
333
320
  const std::shared_ptr<Serializable> &resolveValue,
334
321
  const std::shared_ptr<RuntimeManager> &runtimeManager) {
335
322
  if (isHostedOnRNRuntime()) {
336
- const auto &data = std::get<RNRuntimeData>(runtimeData_);
337
- data.jsScheduler->scheduleOnJS([resolver = shared_from_this(), resolveValue](jsi::Runtime &rt) {
323
+ jsScheduler_->scheduleOnJS([resolver = shared_from_this(), resolveValue](jsi::Runtime &rt) {
338
324
  resolver->toJSValue(rt).getObject(rt).getFunction(rt).call(rt, resolveValue->toJSValue(rt));
339
325
  });
340
326
  } else {
@@ -4,13 +4,13 @@
4
4
  #include <worklets/Compat/StableApi.h>
5
5
  #include <worklets/Registries/WorkletRuntimeRegistry.h>
6
6
  #include <worklets/Tools/JSScheduler.h>
7
+ #include <worklets/Tools/RNRuntimeStatus.h>
7
8
  #include <worklets/WorkletRuntime/RuntimeData.h>
8
9
 
9
10
  #include <memory>
10
11
  #include <optional>
11
12
  #include <string>
12
13
  #include <utility>
13
- #include <variant>
14
14
  #include <vector>
15
15
 
16
16
  using namespace facebook;
@@ -30,9 +30,16 @@ inline void freeWithoutCallingDestructor(std::unique_ptr<jsi::Value> &value) {
30
30
  }
31
31
 
32
32
  inline void cleanupRuntimeAware(jsi::Runtime *rt, std::unique_ptr<jsi::Value> &value) {
33
- if (rt != nullptr && !WorkletRuntimeRegistry::isRuntimeAlive(rt)) {
34
- freeWithoutCallingDestructor(value);
33
+ if (value == nullptr || rt == nullptr) {
34
+ return;
35
35
  }
36
+ WorkletRuntimeRegistry::runWhileLocked(rt, [&value](bool isAlive) {
37
+ if (isAlive) {
38
+ value.reset();
39
+ } else {
40
+ freeWithoutCallingDestructor(value);
41
+ }
42
+ });
36
43
  }
37
44
 
38
45
  template <typename BaseClass>
@@ -283,33 +290,21 @@ class RuntimeManager;
283
290
 
284
291
  class SerializableRemoteFunction : public Serializable,
285
292
  public std::enable_shared_from_this<SerializableRemoteFunction> {
286
- private:
287
- struct RNRuntimeData {
288
- const int remoteId;
289
- const std::shared_ptr<JSScheduler> jsScheduler;
290
- };
291
-
292
- struct WorkletRuntimeData {
293
- std::unique_ptr<jsi::Value> function;
294
- };
295
-
296
- jsi::Runtime *hostRuntime_;
297
- const RuntimeData::RuntimeId hostRuntimeId_;
298
- std::variant<RNRuntimeData, WorkletRuntimeData> runtimeData_;
299
- const std::string name_;
300
-
301
293
  public:
302
294
  /** Creates RN Runtime Remote Function. */
303
295
  SerializableRemoteFunction(
304
296
  jsi::Runtime &rnRuntime,
305
297
  const std::string &name,
306
- const int remoteId,
307
- const std::shared_ptr<JSScheduler> &jsScheduler)
298
+ jsi::Function &&function,
299
+ const std::shared_ptr<JSScheduler> &jsScheduler,
300
+ const std::shared_ptr<RNRuntimeStatus> &rnRuntimeStatus)
308
301
  : Serializable(ValueType::RemoteFunctionType),
309
302
  hostRuntime_(&rnRuntime),
310
303
  hostRuntimeId_(RuntimeData::rnRuntimeId),
311
- runtimeData_(RNRuntimeData{.remoteId = remoteId, .jsScheduler = jsScheduler}),
312
- name_(name) {}
304
+ function_(std::make_unique<jsi::Value>(rnRuntime, std::move(function))),
305
+ name_(name),
306
+ jsScheduler_(jsScheduler),
307
+ rnRuntimeStatus_(rnRuntimeStatus) {}
313
308
 
314
309
  /** Creates Worklet Runtime Remote Function. */
315
310
  SerializableRemoteFunction(
@@ -320,8 +315,10 @@ class SerializableRemoteFunction : public Serializable,
320
315
  : Serializable(ValueType::RemoteFunctionType),
321
316
  hostRuntime_(&workletRuntime),
322
317
  hostRuntimeId_(hostRuntimeId),
323
- runtimeData_(WorkletRuntimeData{.function = std::make_unique<jsi::Value>(workletRuntime, std::move(function))}),
324
- name_(name) {}
318
+ function_(std::make_unique<jsi::Value>(workletRuntime, std::move(function))),
319
+ name_(name),
320
+ jsScheduler_(nullptr),
321
+ rnRuntimeStatus_(nullptr) {}
325
322
 
326
323
  ~SerializableRemoteFunction() override;
327
324
 
@@ -335,12 +332,20 @@ class SerializableRemoteFunction : public Serializable,
335
332
  jsi::Value toJSValue(jsi::Runtime &rt) override;
336
333
 
337
334
  [[nodiscard]] bool isHostedOnRNRuntime() const noexcept {
338
- return std::holds_alternative<RNRuntimeData>(runtimeData_);
335
+ return hostRuntimeId_ == RuntimeData::rnRuntimeId;
339
336
  }
340
337
 
341
338
  [[nodiscard]] RuntimeData::RuntimeId getHostRuntimeId() const {
342
339
  return hostRuntimeId_;
343
340
  }
341
+
342
+ private:
343
+ jsi::Runtime *hostRuntime_;
344
+ const RuntimeData::RuntimeId hostRuntimeId_;
345
+ std::unique_ptr<jsi::Value> function_;
346
+ const std::string name_;
347
+ const std::shared_ptr<JSScheduler> jsScheduler_;
348
+ const std::shared_ptr<RNRuntimeStatus> rnRuntimeStatus_;
344
349
  };
345
350
 
346
351
  class SerializableInitializer : public Serializable {
@@ -63,9 +63,15 @@ jsi::Value makeSerializableHostFunction(
63
63
  jsi::Value makeSerializableRemoteFunction(
64
64
  jsi::Runtime &rnRuntime,
65
65
  const std::string &name,
66
- const int remoteId,
67
- const std::shared_ptr<JSScheduler> &jsScheduler) {
68
- auto serializable = std::make_shared<SerializableRemoteFunction>(rnRuntime, name, remoteId, jsScheduler);
66
+ const jsi::Function &function,
67
+ const std::shared_ptr<JSScheduler> &jsScheduler,
68
+ const std::shared_ptr<RNRuntimeStatus> &rnRuntimeStatus) {
69
+ auto serializable = std::make_shared<SerializableRemoteFunction>(
70
+ rnRuntime,
71
+ name,
72
+ jsi::Value(rnRuntime, function).getObject(rnRuntime).getFunction(rnRuntime),
73
+ jsScheduler,
74
+ rnRuntimeStatus);
69
75
  return SerializableJSRef::newNativeStateObject(rnRuntime, serializable);
70
76
  }
71
77
 
@@ -63,8 +63,9 @@ jsi::Value makeSerializableHostFunction(
63
63
  jsi::Value makeSerializableRemoteFunction(
64
64
  jsi::Runtime &rnRuntime,
65
65
  const std::string &name,
66
- int remoteId,
67
- const std::shared_ptr<JSScheduler> &jsScheduler);
66
+ const jsi::Function &function,
67
+ const std::shared_ptr<JSScheduler> &jsScheduler,
68
+ const std::shared_ptr<RNRuntimeStatus> &rnRuntimeStatus);
68
69
 
69
70
  /** Creates Worklet Runtime Remote Function. */
70
71
  jsi::Value makeSerializableRemoteFunction(
@@ -2,11 +2,7 @@
2
2
 
3
3
  #include <jsi/jsi.h>
4
4
 
5
- #ifndef NDEBUG
6
- // Nothing
7
- #else
8
5
  #include <memory>
9
- #endif // NDEBUG
10
6
  #include <string>
11
7
 
12
8
  namespace worklets {
@@ -63,36 +59,47 @@ class UnpackerLoader {
63
59
  "[Worklets] UnpackerLoader tried to install unpackers but the code for unpackers was not loaded.");
64
60
  }
65
61
 
62
+ const auto useSourceMaps =
66
63
  #ifndef NDEBUG
67
- auto evalWithSourceMap = rt.global().getPropertyAsFunction(rt, "evalWithSourceMap");
68
- evalWithSourceMap.call(rt, valueUnpacker_.code, valueUnpacker_.location, valueUnpacker_.sourceMap);
69
- evalWithSourceMap.call(
70
- rt, synchronizableUnpacker_.code, synchronizableUnpacker_.location, synchronizableUnpacker_.sourceMap);
71
- evalWithSourceMap.call(
72
- rt,
73
- customSerializableUnpacker_.code,
74
- customSerializableUnpacker_.location,
75
- customSerializableUnpacker_.sourceMap);
76
- evalWithSourceMap.call(
77
- rt, shareableHostUnpacker_.code, shareableHostUnpacker_.location, shareableHostUnpacker_.sourceMap);
78
- evalWithSourceMap.call(
79
- rt, shareableGuestUnpacker_.code, shareableGuestUnpacker_.location, shareableGuestUnpacker_.sourceMap);
80
- evalWithSourceMap.call(
81
- rt, remoteFunctionUnpacker_.code, remoteFunctionUnpacker_.location, remoteFunctionUnpacker_.sourceMap);
64
+ !valueUnpacker_.sourceMap.empty();
82
65
  #else
83
- rt.evaluateJavaScript(std::make_shared<facebook::jsi::StringBuffer>(valueUnpacker_.code), valueUnpacker_.location);
84
- rt.evaluateJavaScript(
85
- std::make_shared<facebook::jsi::StringBuffer>(synchronizableUnpacker_.code), synchronizableUnpacker_.location);
86
- rt.evaluateJavaScript(
87
- std::make_shared<facebook::jsi::StringBuffer>(customSerializableUnpacker_.code),
88
- customSerializableUnpacker_.location);
89
- rt.evaluateJavaScript(
90
- std::make_shared<facebook::jsi::StringBuffer>(shareableHostUnpacker_.code), shareableHostUnpacker_.location);
91
- rt.evaluateJavaScript(
92
- std::make_shared<facebook::jsi::StringBuffer>(shareableGuestUnpacker_.code), shareableGuestUnpacker_.location);
93
- rt.evaluateJavaScript(
94
- std::make_shared<facebook::jsi::StringBuffer>(remoteFunctionUnpacker_.code), remoteFunctionUnpacker_.location);
66
+ false;
95
67
  #endif // NDEBUG
68
+
69
+ if (useSourceMaps) {
70
+ const auto evalWithSourceMap = rt.global().getPropertyAsFunction(rt, "evalWithSourceMap");
71
+ evalWithSourceMap.call(rt, valueUnpacker_.code, valueUnpacker_.location, valueUnpacker_.sourceMap);
72
+ evalWithSourceMap.call(
73
+ rt, synchronizableUnpacker_.code, synchronizableUnpacker_.location, synchronizableUnpacker_.sourceMap);
74
+ evalWithSourceMap.call(
75
+ rt,
76
+ customSerializableUnpacker_.code,
77
+ customSerializableUnpacker_.location,
78
+ customSerializableUnpacker_.sourceMap);
79
+ evalWithSourceMap.call(
80
+ rt, shareableHostUnpacker_.code, shareableHostUnpacker_.location, shareableHostUnpacker_.sourceMap);
81
+ evalWithSourceMap.call(
82
+ rt, shareableGuestUnpacker_.code, shareableGuestUnpacker_.location, shareableGuestUnpacker_.sourceMap);
83
+ evalWithSourceMap.call(
84
+ rt, remoteFunctionUnpacker_.code, remoteFunctionUnpacker_.location, remoteFunctionUnpacker_.sourceMap);
85
+ } else {
86
+ rt.evaluateJavaScript(
87
+ std::make_shared<facebook::jsi::StringBuffer>(valueUnpacker_.code), valueUnpacker_.location);
88
+ rt.evaluateJavaScript(
89
+ std::make_shared<facebook::jsi::StringBuffer>(synchronizableUnpacker_.code),
90
+ synchronizableUnpacker_.location);
91
+ rt.evaluateJavaScript(
92
+ std::make_shared<facebook::jsi::StringBuffer>(customSerializableUnpacker_.code),
93
+ customSerializableUnpacker_.location);
94
+ rt.evaluateJavaScript(
95
+ std::make_shared<facebook::jsi::StringBuffer>(shareableHostUnpacker_.code), shareableHostUnpacker_.location);
96
+ rt.evaluateJavaScript(
97
+ std::make_shared<facebook::jsi::StringBuffer>(shareableGuestUnpacker_.code),
98
+ shareableGuestUnpacker_.location);
99
+ rt.evaluateJavaScript(
100
+ std::make_shared<facebook::jsi::StringBuffer>(remoteFunctionUnpacker_.code),
101
+ remoteFunctionUnpacker_.location);
102
+ }
96
103
  }
97
104
 
98
105
  private:
@@ -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
@@ -136,7 +136,11 @@ val workletsPrefabHeadersDir: File = project.file("${layout.buildDirectory.get()
136
136
 
137
137
  fun reactNativeArchitectures(): List<String> {
138
138
  val value = project.findProperty("reactNativeArchitectures") as String?
139
- return value?.split(",") ?: listOf("armeabi-v7a", "x86", "x86_64", "arm64-v8a")
139
+ return value?.split(",")
140
+ ?.map { it.trim() }
141
+ ?.filter { it.isNotEmpty() }
142
+ ?.ifEmpty { null }
143
+ ?: listOf("armeabi-v7a", "x86", "x86_64", "arm64-v8a")
140
144
  }
141
145
 
142
146
  if (project == rootProject) {
@@ -1,6 +1,10 @@
1
1
  fun reactNativeArchitectures(): List<String> {
2
2
  val value = project.findProperty("reactNativeArchitectures") as String?
3
- return value?.split(",") ?: listOf("armeabi-v7a", "x86", "x86_64", "arm64-v8a")
3
+ return value?.split(",")
4
+ ?.map { it.trim() }
5
+ ?.filter { it.isNotEmpty() }
6
+ ?.ifEmpty { null }
7
+ ?: listOf("armeabi-v7a", "x86", "x86_64", "arm64-v8a")
4
8
  }
5
9
 
6
10
  tasks.configureEach {
@@ -33,13 +33,15 @@ WorkletsModule::WorkletsModule(
33
33
  const std::shared_ptr<UIScheduler> &uiScheduler)
34
34
  : javaPart_(jni::make_global(jThis)),
35
35
  rnRuntime_(rnRuntime),
36
+ rnRuntimeStatus_(std::make_shared<RNRuntimeStatus>()),
36
37
  workletsModuleProxy_(std::make_shared<WorkletsModuleProxy>(
37
38
  *rnRuntime,
38
39
  jsCallInvoker,
39
40
  uiScheduler,
40
41
  getIsOnJSQueueThread(),
41
42
  getRuntimeBindings(bundleModeConfig.enabled, *rnRuntime),
42
- bundleModeConfig)) {}
43
+ bundleModeConfig,
44
+ rnRuntimeStatus_)) {}
43
45
 
44
46
  jni::local_ref<WorkletsModule::jhybriddata> WorkletsModule::initHybrid(
45
47
  jni::alias_ref<jhybridobject> jThis, // NOLINT //(performance-unnecessary-value-param)
@@ -179,6 +181,7 @@ std::function<bool()> WorkletsModule::getIsOnJSQueueThread() {
179
181
  }
180
182
 
181
183
  void WorkletsModule::invalidateCpp() {
184
+ rnRuntimeStatus_->setDead();
182
185
  javaPart_.reset();
183
186
  workletsModuleProxy_.reset();
184
187
  }
@@ -4,6 +4,7 @@
4
4
  #include <fbjni/fbjni.h>
5
5
  #include <jsi/jsi.h>
6
6
  #include <worklets/NativeModules/WorkletsModuleProxy.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>
@@ -67,6 +68,7 @@ class WorkletsModule : public jni::HybridClass<WorkletsModule> {
67
68
  friend HybridBase;
68
69
  jni::global_ref<WorkletsModule::javaobject> javaPart_;
69
70
  jsi::Runtime *rnRuntime_;
71
+ std::shared_ptr<RNRuntimeStatus> rnRuntimeStatus_;
70
72
  std::shared_ptr<WorkletsModuleProxy> workletsModuleProxy_;
71
73
  };
72
74
 
@@ -166,9 +166,6 @@ class WorkletsModule(
166
166
  return
167
167
  }
168
168
  if (mHybridData != null && mHybridData!!.isValid) {
169
- // We have to destroy extra runtimes when invalidate is called. If we clean
170
- // it up later instead there's a chance the runtime will retain references
171
- // to invalidated memory and will crash on its destruction.
172
169
  invalidateCpp()
173
170
  }
174
171
  mAndroidUIScheduler.deactivate()
@@ -122,9 +122,6 @@ class WorkletsModule(
122
122
  return
123
123
  }
124
124
  if (mHybridData != null && mHybridData!!.isValid) {
125
- // We have to destroy extra runtimes when invalidate is called. If we clean
126
- // it up later instead there's a chance the runtime will retain references
127
- // to invalidated memory and will crash on its destruction.
128
125
  invalidateCpp()
129
126
  }
130
127
  mAndroidUIScheduler.deactivate()
@@ -1,4 +1,5 @@
1
1
  #import <worklets/NativeModules/JSIWorkletsModuleProxy.h>
2
+ #import <worklets/Tools/RNRuntimeStatus.h>
2
3
  #import <worklets/Tools/ScriptBuffer.h>
3
4
  #import <worklets/Tools/SingleInstanceChecker.h>
4
5
  #import <worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h>
@@ -27,6 +28,7 @@ using namespace worklets;
27
28
  @implementation WorkletsModule {
28
29
  AnimationFrameQueue *animationFrameQueue_;
29
30
  std::shared_ptr<WorkletsModuleProxy> workletsModuleProxy_;
31
+ std::shared_ptr<RNRuntimeStatus> rnRuntimeStatus_;
30
32
  #ifdef WORKLETS_FETCH_PREVIEW_ENABLED
31
33
  WorkletsNetworking *workletsNetworking_;
32
34
  #endif // WORKLETS_FETCH_PREVIEW_ENABLED
@@ -79,6 +81,7 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(installTurboModule : (BOOL)bundleModeEnab
79
81
  };
80
82
  animationFrameQueue_ = [AnimationFrameQueue new];
81
83
  auto runtimeBindings = [self getRuntimeBindings:rnRuntime bundleModeEnabled:bundleModeEnabled];
84
+ rnRuntimeStatus_ = std::make_shared<RNRuntimeStatus>();
82
85
 
83
86
  workletsModuleProxy_ = std::make_shared<WorkletsModuleProxy>(
84
87
  rnRuntime,
@@ -86,7 +89,8 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(installTurboModule : (BOOL)bundleModeEnab
86
89
  uiScheduler,
87
90
  std::move(isJavaScriptQueue),
88
91
  runtimeBindings,
89
- BundleModeConfig{.enabled = static_cast<bool>(bundleModeEnabled), .script = script, .sourceURL = sourceURL});
92
+ BundleModeConfig{.enabled = static_cast<bool>(bundleModeEnabled), .script = script, .sourceURL = sourceURL},
93
+ rnRuntimeStatus_);
90
94
 
91
95
  return @YES;
92
96
  }
@@ -109,9 +113,9 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(toggleSlowAnimationsOnUIRuntime)
109
113
 
110
114
  [animationFrameQueue_ invalidate];
111
115
 
112
- // We have to destroy extra runtimes when invalidate is called. If we clean
113
- // it up later instead there's a chance the runtime will retain references
114
- // to invalidated memory and will crash on destruction.
116
+ if (rnRuntimeStatus_) {
117
+ rnRuntimeStatus_->setDead();
118
+ }
115
119
  workletsModuleProxy_.reset();
116
120
 
117
121
  [super invalidate];