@depup/react-native-worklets 0.11.4-depup.0 → 0.12.1-depup.0
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.
- package/Common/cpp/worklets/AnimationFrameQueue/AnimationFrameBatchinator.cpp +6 -3
- package/Common/cpp/worklets/Compat/StableApi.cpp +4 -0
- package/Common/cpp/worklets/Compat/StableApi.h +3 -1
- package/Common/cpp/worklets/NativeModules/JSIWorkletsModuleProxy.cpp +26 -43
- package/Common/cpp/worklets/RunLoop/EventLoop.cpp +16 -7
- package/Common/cpp/worklets/RunLoop/EventLoop.h +4 -2
- package/Common/cpp/worklets/SharedItems/MemoryManager.cpp +2 -2
- package/Common/cpp/worklets/SharedItems/Serializable.h +14 -16
- package/Common/cpp/worklets/Tools/UIScheduler.cpp +10 -0
- package/Common/cpp/worklets/Tools/UIScheduler.h +3 -0
- package/Common/cpp/worklets/Tools/WorkletsJSIUtils.h +23 -0
- package/Common/cpp/worklets/WorkletRuntime/RuntimeManager.cpp +7 -4
- package/Common/cpp/worklets/WorkletRuntime/RuntimeManager.h +2 -1
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.cpp +60 -88
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.h +335 -122
- package/README.md +2 -2
- package/android/build.gradle.kts +20 -6
- package/android/src/main/cpp/worklets/android/AndroidUIScheduler.cpp +10 -8
- package/android/src/main/cpp/worklets/android/JScriptBufferWrapper.cpp +2 -11
- package/android/src/main/cpp/worklets/android/JScriptBufferWrapper.h +1 -4
- package/android/src/main/java/com/swmansion/worklets/AndroidUIScheduler.kt +3 -0
- package/android/src/main/java/com/swmansion/worklets/ScriptBufferWrapper.kt +87 -43
- package/android/src/networking/com/swmansion/worklets/WorkletsModule.kt +1 -3
- package/android/src/no-networking/com/swmansion/worklets/WorkletsModule.kt +1 -3
- package/apple/worklets/apple/IOSUIScheduler.h +3 -0
- package/apple/worklets/apple/IOSUIScheduler.mm +6 -1
- package/apple/worklets/apple/ScriptLoader.h +11 -0
- package/apple/worklets/apple/ScriptLoader.mm +124 -0
- package/apple/worklets/apple/WorkletsModule.h +1 -16
- package/apple/worklets/apple/WorkletsModule.mm +4 -16
- package/changes.json +1 -1
- package/compatibility.json +4 -1
- package/lib/module/WorkletsModule/NativeWorklets.native.js +2 -2
- package/lib/module/WorkletsModule/NativeWorklets.native.js.map +1 -1
- package/lib/module/debug/jsVersion.js +1 -1
- package/lib/module/memory/serializable.native.js +59 -21
- package/lib/module/memory/serializable.native.js.map +1 -1
- package/lib/module/mock.js +58 -17
- package/lib/module/mock.js.map +1 -1
- package/lib/module/runLoop/uiRuntime/requestAnimationFrame.js +1 -2
- package/lib/module/runLoop/uiRuntime/requestAnimationFrame.js.map +1 -1
- package/lib/module/runLoop/workletRuntime/taskQueue.js +0 -1
- package/lib/module/runLoop/workletRuntime/taskQueue.js.map +1 -1
- package/lib/module/runtimes.native.js +7 -8
- package/lib/module/runtimes.native.js.map +1 -1
- package/lib/module/threads.js +35 -24
- package/lib/module/threads.js.map +1 -1
- package/lib/typescript/WorkletsModule/NativeWorklets.native.d.ts.map +1 -1
- package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts +1 -1
- package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts.map +1 -1
- package/lib/typescript/debug/jsVersion.d.ts +1 -1
- package/lib/typescript/memory/serializable.native.d.ts.map +1 -1
- package/lib/typescript/runLoop/uiRuntime/requestAnimationFrame.d.ts.map +1 -1
- package/lib/typescript/runLoop/workletRuntime/taskQueue.d.ts.map +1 -1
- package/lib/typescript/runtimes.native.d.ts.map +1 -1
- package/lib/typescript/specs/NativeWorkletsModule.d.ts +1 -1
- package/lib/typescript/threads.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +38 -8
- package/lib/typescript/types.d.ts.map +1 -1
- package/package.json +14 -15
- package/plugin/index.js +1625 -1572
- package/src/WorkletsModule/NativeWorklets.native.ts +4 -2
- package/src/WorkletsModule/workletsModuleProxy.ts +2 -1
- package/src/debug/jsVersion.ts +1 -1
- package/src/memory/serializable.native.ts +103 -36
- package/src/mock.ts +85 -23
- package/src/runLoop/uiRuntime/requestAnimationFrame.ts +1 -2
- package/src/runLoop/workletRuntime/taskQueue.ts +0 -1
- package/src/runtimes.native.ts +12 -8
- package/src/threads.ts +38 -26
- package/src/types.ts +42 -8
- package/Common/cpp/worklets/Registries/EventHandlerRegistry.cpp +0 -95
- package/Common/cpp/worklets/Registries/EventHandlerRegistry.h +0 -44
- package/Common/cpp/worklets/Tools/WorkletEventHandler.cpp +0 -34
- package/Common/cpp/worklets/Tools/WorkletEventHandler.h +0 -44
- package/jest/pluginTestUtils.ts +0 -16
|
@@ -45,9 +45,12 @@ void AnimationFrameBatchinator::flush() {
|
|
|
45
45
|
strongThis->flushRequested_ = false;
|
|
46
46
|
|
|
47
47
|
auto &uiWorkletRuntime = strongThis->uiWorkletRuntime_;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
uiWorkletRuntime->runSync([&](jsi::Runtime &rt) {
|
|
49
|
+
for (const auto &callback : callbacks) {
|
|
50
|
+
uiWorkletRuntime->runSync(*callback, timestampMs);
|
|
51
|
+
}
|
|
52
|
+
jsi_utils::triggerWeakRefCleanup(uiWorkletRuntime->getJSIRuntime());
|
|
53
|
+
});
|
|
51
54
|
});
|
|
52
55
|
}
|
|
53
56
|
|
|
@@ -22,6 +22,10 @@ void scheduleOnUI(const std::shared_ptr<UIScheduler> &uiScheduler, const std::fu
|
|
|
22
22
|
uiScheduler->scheduleOnUI(job);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
bool isOnUIThread(const std::shared_ptr<UIScheduler> &uiScheduler) {
|
|
26
|
+
return uiScheduler->isOnUIThread();
|
|
27
|
+
}
|
|
28
|
+
|
|
25
29
|
facebook::jsi::Runtime &getJSIRuntimeFromWorkletRuntime(const std::shared_ptr<WorkletRuntime> &workletRuntime) {
|
|
26
30
|
return workletRuntime->getJSIRuntime();
|
|
27
31
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* It can be used by libraries to verify they use a compatible version
|
|
6
6
|
* of `react-native-worklets` installed when integrating in C++.
|
|
7
7
|
*/
|
|
8
|
-
#define WORKLETS_STABLE_API_VERSION "0.
|
|
8
|
+
#define WORKLETS_STABLE_API_VERSION "0.12.1"
|
|
9
9
|
|
|
10
10
|
#include <cstdint>
|
|
11
11
|
#include <functional>
|
|
@@ -83,6 +83,8 @@ extern std::weak_ptr<WorkletRuntime> getWeakRuntimeFromJSIRuntime(facebook::jsi:
|
|
|
83
83
|
|
|
84
84
|
extern void scheduleOnUI(const std::shared_ptr<UIScheduler> &uiScheduler, const std::function<void()> &job);
|
|
85
85
|
|
|
86
|
+
extern bool isOnUIThread(const std::shared_ptr<UIScheduler> &uiScheduler);
|
|
87
|
+
|
|
86
88
|
extern std::string JSIValueToStdString(facebook::jsi::Runtime &rt, const facebook::jsi::Value &value);
|
|
87
89
|
|
|
88
90
|
extern std::shared_ptr<Serializable>
|
|
@@ -71,37 +71,11 @@ inline void scheduleOnUI(
|
|
|
71
71
|
if (!uiWorkletRuntime) {
|
|
72
72
|
return;
|
|
73
73
|
}
|
|
74
|
-
uiWorkletRuntime->schedule([worklets = std::move(worklets),
|
|
75
74
|
#ifndef NDEBUG
|
|
76
|
-
|
|
77
|
-
#endif // NDEBUG
|
|
78
|
-
weakUIWorkletRuntime]() {
|
|
79
|
-
// This callback can outlive the WorkletsModuleProxy object during the
|
|
80
|
-
// invalidation of React Native. This happens when WorkletsModuleProxy
|
|
81
|
-
// destructor is called on the JS thread and the UI thread is
|
|
82
|
-
// executing callbacks from the `scheduleOnUI` queue. Therefore, we
|
|
83
|
-
// need to make sure it's still alive before we try to access it.
|
|
84
|
-
auto uiWorkletRuntime = weakUIWorkletRuntime.lock();
|
|
85
|
-
if (!uiWorkletRuntime) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// JSI's scope defined here allows for JSI-objects to be cleared up
|
|
90
|
-
// after each runtime loop. Within these loops we typically create
|
|
91
|
-
// some temporary JSI objects and hence it allows for such objects to
|
|
92
|
-
// be garbage collected much sooner.
|
|
93
|
-
const auto scope = jsi::Scope(uiWorkletRuntime->getJSIRuntime());
|
|
94
|
-
|
|
95
|
-
for (size_t i = 0; i < worklets.size(); i++) {
|
|
96
|
-
#ifndef NDEBUG
|
|
97
|
-
uiWorkletRuntime->runSyncWithStack(worklets[i], scheduleStacks[i]);
|
|
75
|
+
uiWorkletRuntime->scheduleWithStack(std::move(worklets), std::move(scheduleStacks));
|
|
98
76
|
#else
|
|
99
|
-
|
|
77
|
+
uiWorkletRuntime->schedule(std::move(worklets));
|
|
100
78
|
#endif // NDEBUG
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
uiWorkletRuntime->callMicrotasks();
|
|
104
|
-
});
|
|
105
79
|
}
|
|
106
80
|
|
|
107
81
|
#ifndef NDEBUG
|
|
@@ -113,7 +87,8 @@ inline jsi::Value runOnUISync(
|
|
|
113
87
|
if (auto uiWorkletRuntime = weakUIWorkletRuntime.lock()) {
|
|
114
88
|
auto serializableWorklet = extractSerializableOrThrow<SerializableWorklet>(
|
|
115
89
|
rt, worklet, "[Worklets] Only worklets can be executed on UI runtime.");
|
|
116
|
-
auto serializedResult =
|
|
90
|
+
auto serializedResult =
|
|
91
|
+
uiWorkletRuntime->runSyncWithStack<std::shared_ptr<Serializable>>(serializableWorklet, scheduleStack);
|
|
117
92
|
return serializedResult->toJSValue(rt);
|
|
118
93
|
}
|
|
119
94
|
return jsi::Value::undefined();
|
|
@@ -140,7 +115,8 @@ jsi::Value runOnRuntimeSync(
|
|
|
140
115
|
auto workletRuntime = workletRuntimeValue.getObject(rt).getHostObject<WorkletRuntime>(rt);
|
|
141
116
|
auto worklet = extractSerializableOrThrow<SerializableWorklet>(
|
|
142
117
|
rt, serializableWorkletValue, "[Worklets] Only worklets can be executed on a worklet runtime.");
|
|
143
|
-
|
|
118
|
+
auto serializedResult = workletRuntime->runSyncWithStack<std::shared_ptr<Serializable>>(worklet, scheduleStack);
|
|
119
|
+
return serializedResult->toJSValue(rt);
|
|
144
120
|
}
|
|
145
121
|
#else
|
|
146
122
|
jsi::Value
|
|
@@ -148,7 +124,8 @@ runOnRuntimeSync(jsi::Runtime &rt, const jsi::Value &workletRuntimeValue, const
|
|
|
148
124
|
auto workletRuntime = workletRuntimeValue.getObject(rt).getHostObject<WorkletRuntime>(rt);
|
|
149
125
|
auto worklet = extractSerializableOrThrow<SerializableWorklet>(
|
|
150
126
|
rt, serializableWorkletValue, "[Worklets] Only worklets can be executed on a worklet runtime.");
|
|
151
|
-
|
|
127
|
+
auto serializedResult = workletRuntime->runSyncSerialized(worklet);
|
|
128
|
+
return serializedResult->toJSValue(rt);
|
|
152
129
|
}
|
|
153
130
|
#endif // NDEBUG
|
|
154
131
|
|
|
@@ -159,9 +136,10 @@ inline jsi::Value createWorkletRuntime(
|
|
|
159
136
|
const std::string &name,
|
|
160
137
|
std::shared_ptr<SerializableWorklet> &initializer,
|
|
161
138
|
const std::shared_ptr<AsyncQueue> &queue,
|
|
162
|
-
bool enableEventLoop
|
|
139
|
+
bool enableEventLoop,
|
|
140
|
+
bool enableLocking) {
|
|
163
141
|
const auto workletRuntime =
|
|
164
|
-
runtimeManager->createWorkletRuntime(sourceProxy, name, initializer, queue, enableEventLoop);
|
|
142
|
+
runtimeManager->createWorkletRuntime(sourceProxy, name, initializer, queue, enableEventLoop, enableLocking);
|
|
165
143
|
return jsi::Object::createFromHostObject(originRuntime, workletRuntime);
|
|
166
144
|
}
|
|
167
145
|
|
|
@@ -202,7 +180,9 @@ inline void registerCustomSerializable(
|
|
|
202
180
|
runtimeManager->withRegistrationPaused([&] {
|
|
203
181
|
memoryManager->registerCustomSerializable(data);
|
|
204
182
|
for (const auto &runtime : runtimeManager->getAllRuntimes()) {
|
|
205
|
-
|
|
183
|
+
if (runtime->isLockingEnabled()) {
|
|
184
|
+
memoryManager->loadCustomSerializable(runtime, data);
|
|
185
|
+
}
|
|
206
186
|
}
|
|
207
187
|
});
|
|
208
188
|
}
|
|
@@ -505,21 +485,23 @@ jsi::Object JSIWorkletsModuleProxy::toOptimizedObject(jsi::Runtime &rt) const {
|
|
|
505
485
|
if (at<2>(args).isString()) {
|
|
506
486
|
scheduleStack = at<2>(args).asString(rt).utf8(rt);
|
|
507
487
|
}
|
|
508
|
-
|
|
488
|
+
auto serializedResult =
|
|
489
|
+
workletRuntime->runSyncWithStack<std::shared_ptr<Serializable>>(serializableWorklet, scheduleStack);
|
|
509
490
|
#else
|
|
510
|
-
|
|
491
|
+
auto serializedResult = workletRuntime->runSyncSerialized(serializableWorklet);
|
|
511
492
|
#endif // NDEBUG
|
|
493
|
+
return serializedResult->toJSValue(rt);
|
|
512
494
|
});
|
|
513
495
|
|
|
514
|
-
jsi_utils::addMethod<
|
|
496
|
+
jsi_utils::addMethod<6>(
|
|
515
497
|
rt,
|
|
516
498
|
obj,
|
|
517
499
|
"createWorkletRuntime",
|
|
518
|
-
[sourceProxy = shared_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[
|
|
519
|
-
const auto name = at<0>(args).
|
|
500
|
+
[sourceProxy = shared_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[6]) {
|
|
501
|
+
const auto name = at<0>(args).getString(rt).utf8(rt);
|
|
520
502
|
auto serializableInitializer = extractSerializableOrThrow<SerializableWorklet>(
|
|
521
503
|
rt, at<1>(args), "[Worklets] Initializer must be a worklet.");
|
|
522
|
-
const auto useDefaultQueue = at<2>(args).
|
|
504
|
+
const auto useDefaultQueue = at<2>(args).getBool();
|
|
523
505
|
|
|
524
506
|
std::shared_ptr<AsyncQueue> asyncQueue;
|
|
525
507
|
if (useDefaultQueue) {
|
|
@@ -528,11 +510,12 @@ jsi::Object JSIWorkletsModuleProxy::toOptimizedObject(jsi::Runtime &rt) const {
|
|
|
528
510
|
asyncQueue = extractAsyncQueue(rt, at<3>(args));
|
|
529
511
|
}
|
|
530
512
|
|
|
531
|
-
const auto enableEventLoop = at<4>(args).
|
|
513
|
+
const auto enableEventLoop = at<4>(args).getBool();
|
|
514
|
+
const auto enableLocking = at<5>(args).getBool();
|
|
532
515
|
const auto runtimeManager = sourceProxy->getRuntimeManager();
|
|
533
516
|
|
|
534
517
|
return createWorkletRuntime(
|
|
535
|
-
rt, runtimeManager, sourceProxy, name, serializableInitializer, asyncQueue, enableEventLoop);
|
|
518
|
+
rt, runtimeManager, sourceProxy, name, serializableInitializer, asyncQueue, enableEventLoop, enableLocking);
|
|
536
519
|
});
|
|
537
520
|
|
|
538
521
|
jsi_utils::addMethod<3>(
|
|
@@ -566,7 +549,7 @@ jsi::Object JSIWorkletsModuleProxy::toOptimizedObject(jsi::Runtime &rt) const {
|
|
|
566
549
|
if (at<2>(args).isString()) {
|
|
567
550
|
scheduleStack = at<2>(args).asString(rt).utf8(rt);
|
|
568
551
|
}
|
|
569
|
-
workletRuntime->
|
|
552
|
+
workletRuntime->scheduleWithStack(worklet, scheduleStack);
|
|
570
553
|
#else
|
|
571
554
|
workletRuntime->schedule(worklet);
|
|
572
555
|
#endif // NDEBUG
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#include <worklets/RunLoop/EventLoop.h>
|
|
2
|
+
#include <worklets/Tools/WorkletsJSIUtils.h>
|
|
2
3
|
|
|
3
4
|
#include <memory>
|
|
4
5
|
#include <string>
|
|
@@ -11,8 +12,13 @@ namespace worklets {
|
|
|
11
12
|
EventLoop::EventLoop(
|
|
12
13
|
const std::string &name,
|
|
13
14
|
const std::shared_ptr<jsi::Runtime> &runtime,
|
|
14
|
-
const std::shared_ptr<AsyncQueue> &queue
|
|
15
|
-
|
|
15
|
+
const std::shared_ptr<AsyncQueue> &queue,
|
|
16
|
+
const std::shared_ptr<std::recursive_mutex> &runtimeMutex)
|
|
17
|
+
: runtime_(runtime),
|
|
18
|
+
queue_(queue),
|
|
19
|
+
runtimeMutex_(runtimeMutex),
|
|
20
|
+
timeoutsQueueState_(std::make_shared<TimeoutsQueueState>()),
|
|
21
|
+
name_(name) {}
|
|
16
22
|
|
|
17
23
|
EventLoop::~EventLoop() {
|
|
18
24
|
{
|
|
@@ -76,11 +82,14 @@ void EventLoop::run() {
|
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
void EventLoop::pushTask(std::function<void(jsi::Runtime &rt)> &&job) {
|
|
79
|
-
queue_->push(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
queue_->push(
|
|
86
|
+
[weakRuntime = std::weak_ptr<jsi::Runtime>{runtime_}, runtimeMutex = runtimeMutex_, job = std::move(job)] {
|
|
87
|
+
if (auto runtime = weakRuntime.lock()) {
|
|
88
|
+
std::unique_lock lock(*runtimeMutex);
|
|
89
|
+
job(*runtime);
|
|
90
|
+
jsi_utils::drainMicrotasks(*runtime);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
84
93
|
}
|
|
85
94
|
|
|
86
95
|
void EventLoop::pushTimeout(std::function<void(jsi::Runtime &rt)> &&job, int64_t delay) {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
#include <atomic>
|
|
7
7
|
#include <condition_variable>
|
|
8
8
|
#include <memory>
|
|
9
|
-
#include <
|
|
9
|
+
#include <mutex>
|
|
10
10
|
#include <string>
|
|
11
11
|
#include <vector>
|
|
12
12
|
|
|
@@ -34,7 +34,8 @@ class EventLoop : public std::enable_shared_from_this<EventLoop> {
|
|
|
34
34
|
EventLoop(
|
|
35
35
|
const std::string &name,
|
|
36
36
|
const std::shared_ptr<jsi::Runtime> &runtime,
|
|
37
|
-
const std::shared_ptr<AsyncQueue> &queue
|
|
37
|
+
const std::shared_ptr<AsyncQueue> &queue,
|
|
38
|
+
const std::shared_ptr<std::recursive_mutex> &runtimeMutex);
|
|
38
39
|
~EventLoop();
|
|
39
40
|
void run();
|
|
40
41
|
void pushTask(std::function<void(jsi::Runtime &rt)> &&job);
|
|
@@ -43,6 +44,7 @@ class EventLoop : public std::enable_shared_from_this<EventLoop> {
|
|
|
43
44
|
private:
|
|
44
45
|
const std::shared_ptr<jsi::Runtime> runtime_;
|
|
45
46
|
const std::shared_ptr<AsyncQueue> queue_;
|
|
47
|
+
const std::shared_ptr<std::recursive_mutex> runtimeMutex_;
|
|
46
48
|
const std::shared_ptr<TimeoutsQueueState> timeoutsQueueState_;
|
|
47
49
|
const std::string name_;
|
|
48
50
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
namespace worklets {
|
|
8
8
|
void MemoryManager::loadAllCustomSerializables(const std::shared_ptr<WorkletRuntime> &runtime) {
|
|
9
9
|
std::lock_guard lock(customSerializationDataMutex_);
|
|
10
|
-
runtime->
|
|
10
|
+
runtime->runSync([&](jsi::Runtime &rt) -> jsi::Value {
|
|
11
11
|
const auto registry = getCustomSerializationRegistry(rt);
|
|
12
12
|
for (const auto &data : customSerializationData_) {
|
|
13
13
|
loadCustomSerializable(rt, registry, data);
|
|
@@ -20,7 +20,7 @@ void MemoryManager::loadCustomSerializable(
|
|
|
20
20
|
const std::shared_ptr<WorkletRuntime> &runtime,
|
|
21
21
|
const SerializationData &data) {
|
|
22
22
|
std::lock_guard lock(customSerializationDataMutex_);
|
|
23
|
-
runtime->
|
|
23
|
+
runtime->runSync([this, data](jsi::Runtime &rt) -> jsi::Value {
|
|
24
24
|
const auto registry = getCustomSerializationRegistry(rt);
|
|
25
25
|
loadCustomSerializable(rt, registry, data);
|
|
26
26
|
return jsi::Value::undefined();
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#include <worklets/Tools/JSScheduler.h>
|
|
7
7
|
#include <worklets/WorkletRuntime/RuntimeData.h>
|
|
8
8
|
|
|
9
|
+
#include <atomic>
|
|
9
10
|
#include <memory>
|
|
10
11
|
#include <mutex>
|
|
11
12
|
#include <optional>
|
|
@@ -46,8 +47,9 @@ template <typename BaseClass>
|
|
|
46
47
|
class RetainingSerializable : virtual public BaseClass {
|
|
47
48
|
private:
|
|
48
49
|
jsi::Runtime *primaryRuntime_;
|
|
49
|
-
jsi::Runtime *secondaryRuntime_;
|
|
50
50
|
std::unique_ptr<jsi::Value> secondaryValue_;
|
|
51
|
+
std::atomic<jsi::Runtime *> secondaryRuntime_{nullptr};
|
|
52
|
+
std::mutex secondaryCacheMutex_;
|
|
51
53
|
|
|
52
54
|
public:
|
|
53
55
|
template <typename... Args>
|
|
@@ -56,28 +58,24 @@ class RetainingSerializable : virtual public BaseClass {
|
|
|
56
58
|
|
|
57
59
|
jsi::Value toJSValue(jsi::Runtime &rt) override {
|
|
58
60
|
if (&rt == primaryRuntime_) {
|
|
59
|
-
// TODO: it is suboptimal to generate new object every time getJS is
|
|
60
|
-
// called on host runtime – the objects we are generating already exists
|
|
61
|
-
// and we should possibly just grab a hold of such object and use it here
|
|
62
|
-
// instead of creating a new JS representation. As far as I understand the
|
|
63
|
-
// only case where it can be realistically called this way is when a
|
|
64
|
-
// shared value is created and then accessed on the same runtime
|
|
65
61
|
return BaseClass::toJSValue(rt);
|
|
66
62
|
}
|
|
67
|
-
if (
|
|
68
|
-
auto value = BaseClass::toJSValue(rt);
|
|
69
|
-
secondaryValue_ = std::make_unique<jsi::Value>(rt, value);
|
|
70
|
-
secondaryRuntime_ = &rt;
|
|
71
|
-
return value;
|
|
72
|
-
}
|
|
73
|
-
if (&rt == secondaryRuntime_) {
|
|
63
|
+
if (secondaryRuntime_.load(std::memory_order_acquire) == &rt) {
|
|
74
64
|
return jsi::Value(rt, *secondaryValue_);
|
|
75
65
|
}
|
|
76
|
-
|
|
66
|
+
auto value = BaseClass::toJSValue(rt);
|
|
67
|
+
{
|
|
68
|
+
std::lock_guard<std::mutex> lock(secondaryCacheMutex_);
|
|
69
|
+
if (secondaryRuntime_.load(std::memory_order_relaxed) == nullptr) {
|
|
70
|
+
secondaryValue_ = std::make_unique<jsi::Value>(rt, value);
|
|
71
|
+
secondaryRuntime_.store(&rt, std::memory_order_release);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return value;
|
|
77
75
|
}
|
|
78
76
|
|
|
79
77
|
~RetainingSerializable() override {
|
|
80
|
-
cleanupRuntimeAware(secondaryRuntime_, secondaryValue_);
|
|
78
|
+
cleanupRuntimeAware(secondaryRuntime_.load(std::memory_order_relaxed), secondaryValue_);
|
|
81
79
|
}
|
|
82
80
|
};
|
|
83
81
|
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
#include <worklets/Tools/UIScheduler.h>
|
|
2
2
|
|
|
3
|
+
#include <optional>
|
|
3
4
|
#include <utility>
|
|
4
5
|
|
|
5
6
|
namespace worklets {
|
|
6
7
|
|
|
8
|
+
static thread_local std::optional<bool> tls_isOnUIThread;
|
|
9
|
+
|
|
7
10
|
void UIScheduler::scheduleOnUI(std::function<void()> job) {
|
|
8
11
|
uiJobs_.push(std::move(job));
|
|
9
12
|
}
|
|
@@ -16,4 +19,11 @@ void UIScheduler::triggerUI() {
|
|
|
16
19
|
}
|
|
17
20
|
}
|
|
18
21
|
|
|
22
|
+
bool UIScheduler::isOnUIThread() const {
|
|
23
|
+
if (!tls_isOnUIThread.has_value()) {
|
|
24
|
+
tls_isOnUIThread = queryIsOnUIThread();
|
|
25
|
+
}
|
|
26
|
+
return *tls_isOnUIThread;
|
|
27
|
+
}
|
|
28
|
+
|
|
19
29
|
} // namespace worklets
|
|
@@ -12,9 +12,12 @@ class UIScheduler {
|
|
|
12
12
|
public:
|
|
13
13
|
virtual void scheduleOnUI(std::function<void()> job);
|
|
14
14
|
virtual void triggerUI();
|
|
15
|
+
bool isOnUIThread() const;
|
|
15
16
|
virtual ~UIScheduler() = default;
|
|
16
17
|
|
|
17
18
|
protected:
|
|
19
|
+
virtual bool queryIsOnUIThread() const = 0;
|
|
20
|
+
|
|
18
21
|
std::atomic<bool> scheduledOnUI_{false};
|
|
19
22
|
ThreadSafeQueue<std::function<void()>> uiJobs_;
|
|
20
23
|
};
|
|
@@ -11,6 +11,29 @@ using namespace facebook;
|
|
|
11
11
|
|
|
12
12
|
namespace worklets::jsi_utils {
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Drains Hermes microtasks - we don't use these, but Hermes WeakRefs are
|
|
16
|
+
* cleaned during Hermes microtask checkpoint.
|
|
17
|
+
*/
|
|
18
|
+
inline void triggerWeakRefCleanup(jsi::Runtime &rt) {
|
|
19
|
+
rt.drainMicrotasks();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Drains both Worklets and Hermes microtasks.
|
|
24
|
+
*/
|
|
25
|
+
inline void drainMicrotasks(jsi::Runtime &rt) {
|
|
26
|
+
auto callMicrotasks = rt.global().getProperty(rt, "__callMicrotasks");
|
|
27
|
+
if (callMicrotasks.isObject()) {
|
|
28
|
+
auto callMicrotasksObject = callMicrotasks.getObject(rt);
|
|
29
|
+
if (callMicrotasksObject.isFunction(rt)) {
|
|
30
|
+
callMicrotasksObject.getFunction(rt).call(rt);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
triggerWeakRefCleanup(rt);
|
|
35
|
+
}
|
|
36
|
+
|
|
14
37
|
// `get` functions take a pointer to `jsi::Value` and
|
|
15
38
|
// call an appropriate method to cast to the native type
|
|
16
39
|
template <typename T>
|
|
@@ -55,11 +55,12 @@ std::shared_ptr<WorkletRuntime> RuntimeManager::createWorkletRuntime(
|
|
|
55
55
|
const std::string &name,
|
|
56
56
|
const std::shared_ptr<SerializableWorklet> &initializer,
|
|
57
57
|
const std::shared_ptr<AsyncQueue> &queue,
|
|
58
|
-
bool enableEventLoop
|
|
58
|
+
bool enableEventLoop,
|
|
59
|
+
bool enableLocking) {
|
|
59
60
|
const auto runtimeId = getNextRuntimeId();
|
|
60
61
|
|
|
61
|
-
const auto workletRuntime =
|
|
62
|
-
|
|
62
|
+
const auto workletRuntime = std::make_shared<WorkletRuntime>(
|
|
63
|
+
runtimeId, RuntimeData::RuntimeKind::Worker, name, queue, enableEventLoop, enableLocking);
|
|
63
64
|
const auto targetProxy = JSIWorkletsModuleProxy::createForNewRuntime(sourceProxy, runtimeId);
|
|
64
65
|
|
|
65
66
|
workletRuntime->init(targetProxy);
|
|
@@ -84,7 +85,9 @@ void RuntimeManager::propagateModuleUpdate(const std::string &code, const std::s
|
|
|
84
85
|
moduleUpdates_.push_back(ModuleUpdate{.sourceUrl = sourceUrl, .code = code});
|
|
85
86
|
|
|
86
87
|
for (const auto &runtime : getAllRuntimes()) {
|
|
87
|
-
|
|
88
|
+
if (runtime->isLockingEnabled()) {
|
|
89
|
+
evaluateModuleUpdate(runtime, code, sourceUrl);
|
|
90
|
+
}
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
93
|
|
|
@@ -35,7 +35,8 @@ class RuntimeManager {
|
|
|
35
35
|
const std::string &name,
|
|
36
36
|
const std::shared_ptr<SerializableWorklet> &initializer = nullptr,
|
|
37
37
|
const std::shared_ptr<AsyncQueue> &queue = nullptr,
|
|
38
|
-
bool enableEventLoop = true
|
|
38
|
+
bool enableEventLoop = true,
|
|
39
|
+
bool enableLocking = true);
|
|
39
40
|
|
|
40
41
|
std::shared_ptr<WorkletRuntime> createUninitializedUIRuntime(const std::shared_ptr<AsyncQueue> &uiAsyncQueue);
|
|
41
42
|
|