react-native-worklets 0.0.1-alpha → 0.1.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 +71 -0
- package/Common/cpp/worklets/AnimationFrameQueue/AnimationFrameBatchinator.h +38 -0
- package/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp +131 -0
- package/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h +82 -0
- package/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp +72 -0
- package/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h +44 -0
- package/Common/cpp/worklets/Registries/EventHandlerRegistry.cpp +94 -0
- package/Common/cpp/worklets/Registries/EventHandlerRegistry.h +49 -0
- package/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.cpp +8 -0
- package/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.h +39 -0
- package/Common/cpp/worklets/SharedItems/Shareables.cpp +326 -0
- package/Common/cpp/worklets/SharedItems/Shareables.h +345 -0
- package/Common/cpp/worklets/Tools/AsyncQueue.cpp +52 -0
- package/Common/cpp/worklets/Tools/AsyncQueue.h +35 -0
- package/Common/cpp/worklets/Tools/Defs.h +10 -0
- package/Common/cpp/worklets/Tools/JSISerializer.cpp +342 -0
- package/Common/cpp/worklets/Tools/JSISerializer.h +47 -0
- package/Common/cpp/worklets/Tools/JSLogger.cpp +16 -0
- package/Common/cpp/worklets/Tools/JSLogger.h +20 -0
- package/Common/cpp/worklets/Tools/JSScheduler.cpp +10 -0
- package/Common/cpp/worklets/Tools/JSScheduler.h +29 -0
- package/Common/cpp/worklets/Tools/PlatformLogger.h +16 -0
- package/Common/cpp/worklets/Tools/SingleInstanceChecker.h +72 -0
- package/Common/cpp/worklets/Tools/ThreadSafeQueue.h +49 -0
- package/Common/cpp/worklets/Tools/UIScheduler.cpp +19 -0
- package/Common/cpp/worklets/Tools/UIScheduler.h +22 -0
- package/Common/cpp/worklets/Tools/WorkletEventHandler.cpp +29 -0
- package/Common/cpp/worklets/Tools/WorkletEventHandler.h +41 -0
- package/Common/cpp/worklets/Tools/WorkletsJSIUtils.cpp +26 -0
- package/Common/cpp/worklets/Tools/WorkletsJSIUtils.h +199 -0
- package/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.cpp +20 -0
- package/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h +19 -0
- package/Common/cpp/worklets/WorkletRuntime/RuntimeInitialization.md +191 -0
- package/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.cpp +19 -0
- package/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.h +16 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletHermesRuntime.cpp +108 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletHermesRuntime.h +127 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.cpp +183 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.h +90 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeCollector.h +36 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp +179 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.h +22 -0
- package/LICENSE +20 -0
- package/README.md +27 -0
- package/RNWorklets.podspec +70 -0
- package/android/CMakeLists.txt +56 -0
- package/android/build.gradle +313 -0
- package/android/gradle.properties +5 -0
- package/android/proguard-rules.pro +3 -0
- package/android/spotless.gradle +9 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/worklets/CMakeLists.txt +85 -0
- package/android/src/main/cpp/worklets/android/AndroidUIScheduler.cpp +63 -0
- package/android/src/main/cpp/worklets/android/AndroidUIScheduler.h +41 -0
- package/android/src/main/cpp/worklets/android/AnimationFrameCallback.h +32 -0
- package/android/src/main/cpp/worklets/android/PlatformLogger.cpp +29 -0
- package/android/src/main/cpp/worklets/android/WorkletsModule.cpp +83 -0
- package/android/src/main/cpp/worklets/android/WorkletsModule.h +63 -0
- package/android/src/main/cpp/worklets/android/WorkletsOnLoad.cpp +13 -0
- package/android/src/main/java/com/swmansion/worklets/AndroidUIScheduler.java +60 -0
- package/android/src/main/java/com/swmansion/worklets/AnimationFrameQueue/AnimationFrameCallback.java +20 -0
- package/android/src/main/java/com/swmansion/worklets/AnimationFrameQueue/AnimationFrameQueue.java +113 -0
- package/android/src/main/java/com/swmansion/worklets/JSCallInvokerResolver.java +27 -0
- package/android/src/main/java/com/swmansion/worklets/WorkletsMessageQueueThread.java +16 -0
- package/android/src/main/java/com/swmansion/worklets/WorkletsMessageQueueThreadBase.java +72 -0
- package/android/src/main/java/com/swmansion/worklets/WorkletsModule.java +106 -0
- package/android/src/main/java/com/swmansion/worklets/WorkletsPackage.java +49 -0
- package/android/src/paper/com/swmansion/worklets/NativeWorkletsModuleSpec.java +26 -0
- package/apple/worklets/apple/AnimationFrameQueue.h +15 -0
- package/apple/worklets/apple/AnimationFrameQueue.mm +81 -0
- package/apple/worklets/apple/AssertJavaScriptQueue.h +14 -0
- package/apple/worklets/apple/AssertTurboModuleManagerQueue.h +16 -0
- package/apple/worklets/apple/IOSUIScheduler.h +14 -0
- package/apple/worklets/apple/IOSUIScheduler.mm +24 -0
- package/apple/worklets/apple/PlatformLogger.mm +31 -0
- package/apple/worklets/apple/SlowAnimations.h +8 -0
- package/apple/worklets/apple/SlowAnimations.mm +47 -0
- package/apple/worklets/apple/WorkletsDisplayLink.h +21 -0
- package/apple/worklets/apple/WorkletsMessageThread.h +16 -0
- package/apple/worklets/apple/WorkletsMessageThread.mm +32 -0
- package/apple/worklets/apple/WorkletsModule.h +10 -0
- package/apple/worklets/apple/WorkletsModule.mm +85 -0
- package/lib/module/PlatformChecker.js +35 -0
- package/lib/module/PlatformChecker.js.map +1 -0
- package/lib/module/WorkletsError.js +13 -0
- package/lib/module/WorkletsError.js.map +1 -0
- package/lib/module/WorkletsModule/JSWorklets.js +36 -0
- package/lib/module/WorkletsModule/JSWorklets.js.map +1 -0
- package/lib/module/WorkletsModule/NativeWorklets.js +39 -0
- package/lib/module/WorkletsModule/NativeWorklets.js.map +1 -0
- package/lib/module/WorkletsModule/index.js +4 -0
- package/lib/module/WorkletsModule/index.js.map +1 -0
- package/lib/module/WorkletsModule/workletsModuleInstance.js +7 -0
- package/lib/module/WorkletsModule/workletsModuleInstance.js.map +1 -0
- package/lib/module/WorkletsModule/workletsModuleInstance.web.js +5 -0
- package/lib/module/WorkletsModule/workletsModuleInstance.web.js.map +1 -0
- package/lib/module/WorkletsModule/workletsModuleProxy.js +4 -0
- package/lib/module/WorkletsModule/workletsModuleProxy.js.map +1 -0
- package/lib/module/animationFrameQueue/mockedRequestAnimationFrame.js +10 -0
- package/lib/module/animationFrameQueue/mockedRequestAnimationFrame.js.map +1 -0
- package/lib/module/animationFrameQueue/requestAnimationFrame.js +36 -0
- package/lib/module/animationFrameQueue/requestAnimationFrame.js.map +1 -0
- package/lib/module/errors.js +78 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/index.js +17 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/initializers.js +158 -0
- package/lib/module/initializers.js.map +1 -0
- package/lib/module/logger/LogBox.js +15 -0
- package/lib/module/logger/LogBox.js.map +1 -0
- package/lib/module/logger/index.js +5 -0
- package/lib/module/logger/index.js.map +1 -0
- package/lib/module/logger/logger.js +137 -0
- package/lib/module/logger/logger.js.map +1 -0
- package/lib/module/privateGlobals.d.js +8 -0
- package/lib/module/privateGlobals.d.js.map +1 -0
- package/lib/module/runtimes.js +63 -0
- package/lib/module/runtimes.js.map +1 -0
- package/lib/module/shareableMappingCache.js +39 -0
- package/lib/module/shareableMappingCache.js.map +1 -0
- package/lib/module/shareables.js +417 -0
- package/lib/module/shareables.js.map +1 -0
- package/lib/module/specs/NativeWorkletsModule.js +5 -0
- package/lib/module/specs/NativeWorkletsModule.js.map +1 -0
- package/lib/module/specs/index.js +5 -0
- package/lib/module/specs/index.js.map +1 -0
- package/lib/module/threads.js +204 -0
- package/lib/module/threads.js.map +1 -0
- package/lib/module/valueUnpacker.js +83 -0
- package/lib/module/valueUnpacker.js.map +1 -0
- package/lib/module/workletFunction.js +37 -0
- package/lib/module/workletFunction.js.map +1 -0
- package/lib/module/workletTypes.js +12 -0
- package/lib/module/workletTypes.js.map +1 -0
- package/lib/typescript/PlatformChecker.d.ts +7 -0
- package/lib/typescript/PlatformChecker.d.ts.map +1 -0
- package/lib/typescript/WorkletsError.d.ts +3 -0
- package/lib/typescript/WorkletsError.d.ts.map +1 -0
- package/lib/typescript/WorkletsModule/JSWorklets.d.ts +3 -0
- package/lib/typescript/WorkletsModule/JSWorklets.d.ts.map +1 -0
- package/lib/typescript/WorkletsModule/NativeWorklets.d.ts +5 -0
- package/lib/typescript/WorkletsModule/NativeWorklets.d.ts.map +1 -0
- package/lib/typescript/WorkletsModule/index.d.ts +3 -0
- package/lib/typescript/WorkletsModule/index.d.ts.map +1 -0
- package/lib/typescript/WorkletsModule/workletsModuleInstance.d.ts +2 -0
- package/lib/typescript/WorkletsModule/workletsModuleInstance.d.ts.map +1 -0
- package/lib/typescript/WorkletsModule/workletsModuleInstance.web.d.ts +2 -0
- package/lib/typescript/WorkletsModule/workletsModuleInstance.web.d.ts.map +1 -0
- package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts +12 -0
- package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts.map +1 -0
- package/lib/typescript/animationFrameQueue/mockedRequestAnimationFrame.d.ts +6 -0
- package/lib/typescript/animationFrameQueue/mockedRequestAnimationFrame.d.ts.map +1 -0
- package/lib/typescript/animationFrameQueue/requestAnimationFrame.d.ts +2 -0
- package/lib/typescript/animationFrameQueue/requestAnimationFrame.d.ts.map +1 -0
- package/lib/typescript/errors.d.ts +19 -0
- package/lib/typescript/errors.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +13 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/initializers.d.ts +6 -0
- package/lib/typescript/initializers.d.ts.map +1 -0
- package/lib/typescript/logger/LogBox.d.ts +32 -0
- package/lib/typescript/logger/LogBox.d.ts.map +1 -0
- package/lib/typescript/logger/index.d.ts +3 -0
- package/lib/typescript/logger/index.d.ts.map +1 -0
- package/lib/typescript/logger/logger.d.ts +52 -0
- package/lib/typescript/logger/logger.d.ts.map +1 -0
- package/lib/typescript/runtimes.d.ts +16 -0
- package/lib/typescript/runtimes.d.ts.map +1 -0
- package/lib/typescript/shareableMappingCache.d.ts +16 -0
- package/lib/typescript/shareableMappingCache.d.ts.map +1 -0
- package/lib/typescript/shareables.d.ts +15 -0
- package/lib/typescript/shareables.d.ts.map +1 -0
- package/lib/typescript/specs/NativeWorkletsModule.d.ts +7 -0
- package/lib/typescript/specs/NativeWorkletsModule.d.ts.map +1 -0
- package/lib/typescript/specs/index.d.ts +3 -0
- package/lib/typescript/specs/index.d.ts.map +1 -0
- package/lib/typescript/threads.d.ts +49 -0
- package/lib/typescript/threads.d.ts.map +1 -0
- package/lib/typescript/valueUnpacker.d.ts +2 -0
- package/lib/typescript/valueUnpacker.d.ts.map +1 -0
- package/lib/typescript/workletFunction.d.ts +27 -0
- package/lib/typescript/workletFunction.d.ts.map +1 -0
- package/lib/typescript/workletTypes.d.ts +49 -0
- package/lib/typescript/workletTypes.d.ts.map +1 -0
- package/package.json +106 -8
- package/plugin/index.js +3 -0
- package/scripts/worklets_utils.rb +53 -0
- package/src/PlatformChecker.ts +43 -0
- package/src/WorkletsError.ts +13 -0
- package/src/WorkletsModule/JSWorklets.ts +57 -0
- package/src/WorkletsModule/NativeWorklets.ts +68 -0
- package/src/WorkletsModule/index.ts +7 -0
- package/src/WorkletsModule/workletsModuleInstance.ts +9 -0
- package/src/WorkletsModule/workletsModuleInstance.web.ts +5 -0
- package/src/WorkletsModule/workletsModuleProxy.ts +30 -0
- package/src/animationFrameQueue/mockedRequestAnimationFrame.ts +11 -0
- package/src/animationFrameQueue/requestAnimationFrame.ts +41 -0
- package/src/errors.ts +103 -0
- package/src/index.ts +42 -0
- package/src/initializers.ts +175 -0
- package/src/logger/LogBox.ts +55 -0
- package/src/logger/index.ts +3 -0
- package/src/logger/logger.ts +155 -0
- package/src/privateGlobals.d.ts +41 -0
- package/src/runtimes.ts +92 -0
- package/src/shareableMappingCache.ts +44 -0
- package/src/shareables.ts +577 -0
- package/src/specs/NativeWorkletsModule.ts +9 -0
- package/src/specs/index.ts +5 -0
- package/src/threads.ts +275 -0
- package/src/valueUnpacker.ts +110 -0
- package/src/workletFunction.ts +47 -0
- package/src/workletTypes.ts +76 -0
- package/Animated.js +0 -13
- package/AnimatedEvent.js +0 -167
- package/AnimatedImplementation.js +0 -666
- package/CoreAnimated.js +0 -43
- package/Easing.js +0 -236
- package/NativeAnimatedHelper.js +0 -226
- package/SpringConfig.js +0 -79
- package/animations/Animation.js +0 -36
- package/animations/DecayAnimation.js +0 -70
- package/animations/SpringAnimation.js +0 -125
- package/animations/TimingAnimation.js +0 -70
- package/bezier.js +0 -128
- package/createAnimatedComponent.js +0 -188
- package/nodes/AnimatedBlock.js +0 -19
- package/nodes/AnimatedClock.js +0 -76
- package/nodes/AnimatedCond.js +0 -23
- package/nodes/AnimatedDetach.js +0 -15
- package/nodes/AnimatedInterpolation.js +0 -338
- package/nodes/AnimatedNode.js +0 -97
- package/nodes/AnimatedOnChange.js +0 -28
- package/nodes/AnimatedOp.js +0 -17
- package/nodes/AnimatedProps.js +0 -154
- package/nodes/AnimatedSet.js +0 -19
- package/nodes/AnimatedStartClock.js +0 -21
- package/nodes/AnimatedStopClock.js +0 -21
- package/nodes/AnimatedStyle.js +0 -89
- package/nodes/AnimatedTracking.js +0 -36
- package/nodes/AnimatedTransform.js +0 -93
- package/nodes/AnimatedValue.js +0 -271
- package/nodes/AnimatedWithInput.js +0 -21
- package/nodes/SpringNode.js +0 -106
- package/nodes/TimingStep.js +0 -44
- package/utils.js +0 -28
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#include <worklets/Tools/AsyncQueue.h>
|
|
2
|
+
|
|
3
|
+
#include <utility>
|
|
4
|
+
|
|
5
|
+
namespace worklets {
|
|
6
|
+
|
|
7
|
+
AsyncQueue::AsyncQueue(std::string name)
|
|
8
|
+
: state_(std::make_shared<AsyncQueueState>()) {
|
|
9
|
+
auto thread = std::thread([name, state = state_] {
|
|
10
|
+
#if __APPLE__
|
|
11
|
+
pthread_setname_np(name.c_str());
|
|
12
|
+
#endif
|
|
13
|
+
while (state->running) {
|
|
14
|
+
std::unique_lock<std::mutex> lock(state->mutex);
|
|
15
|
+
state->cv.wait(
|
|
16
|
+
lock, [state] { return !state->queue.empty() || !state->running; });
|
|
17
|
+
if (!state->running) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (state->queue.empty()) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
auto job = std::move(state->queue.front());
|
|
24
|
+
state->queue.pop();
|
|
25
|
+
lock.unlock();
|
|
26
|
+
job();
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
#ifdef ANDROID
|
|
30
|
+
pthread_setname_np(thread.native_handle(), name.c_str());
|
|
31
|
+
#endif
|
|
32
|
+
thread.detach();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
AsyncQueue::~AsyncQueue() {
|
|
36
|
+
{
|
|
37
|
+
std::unique_lock<std::mutex> lock(state_->mutex);
|
|
38
|
+
state_->running = false;
|
|
39
|
+
state_->queue = {};
|
|
40
|
+
}
|
|
41
|
+
state_->cv.notify_all();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
void AsyncQueue::push(std::function<void()> &&job) {
|
|
45
|
+
{
|
|
46
|
+
std::unique_lock<std::mutex> lock(state_->mutex);
|
|
47
|
+
state_->queue.emplace(job);
|
|
48
|
+
}
|
|
49
|
+
state_->cv.notify_one();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
} // namespace worklets
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <jsi/jsi.h>
|
|
4
|
+
|
|
5
|
+
#include <atomic>
|
|
6
|
+
#include <condition_variable>
|
|
7
|
+
#include <memory>
|
|
8
|
+
#include <queue>
|
|
9
|
+
#include <string>
|
|
10
|
+
#include <thread>
|
|
11
|
+
#include <utility>
|
|
12
|
+
#include <vector>
|
|
13
|
+
|
|
14
|
+
namespace worklets {
|
|
15
|
+
|
|
16
|
+
struct AsyncQueueState {
|
|
17
|
+
std::atomic_bool running{true};
|
|
18
|
+
std::mutex mutex;
|
|
19
|
+
std::condition_variable cv;
|
|
20
|
+
std::queue<std::function<void()>> queue;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
class AsyncQueue {
|
|
24
|
+
public:
|
|
25
|
+
explicit AsyncQueue(std::string name);
|
|
26
|
+
|
|
27
|
+
~AsyncQueue();
|
|
28
|
+
|
|
29
|
+
void push(std::function<void()> &&job);
|
|
30
|
+
|
|
31
|
+
private:
|
|
32
|
+
const std::shared_ptr<AsyncQueueState> state_;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
} // namespace worklets
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
On Android JS_RUNTIME_HERMES is set in CMakeList.txt,
|
|
5
|
+
but on iOS there is no simple way to defect if Hermes exists
|
|
6
|
+
so we have to check if headers are available.
|
|
7
|
+
*/
|
|
8
|
+
#if __APPLE__ && __has_include(<hermes/hermes.h>)
|
|
9
|
+
#define JS_RUNTIME_HERMES 1
|
|
10
|
+
#endif
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
#include <worklets/Tools/JSISerializer.h>
|
|
2
|
+
|
|
3
|
+
#include <cxxabi.h>
|
|
4
|
+
#include <iostream>
|
|
5
|
+
#include <sstream>
|
|
6
|
+
|
|
7
|
+
namespace worklets {
|
|
8
|
+
|
|
9
|
+
const std::vector<std::string> SUPPORTED_ERROR_TYPES = {
|
|
10
|
+
"Error",
|
|
11
|
+
"AggregateError",
|
|
12
|
+
"EvalError",
|
|
13
|
+
"RangeError",
|
|
14
|
+
"ReferenceError",
|
|
15
|
+
"SyntaxError",
|
|
16
|
+
"TypeError",
|
|
17
|
+
"URIError",
|
|
18
|
+
"InternalError"};
|
|
19
|
+
|
|
20
|
+
const std::vector<std::string> SUPPORTED_INDEXED_COLLECTION_TYPES = {
|
|
21
|
+
"Int8Array",
|
|
22
|
+
"Uint8Array",
|
|
23
|
+
"Uint8ClampedArray",
|
|
24
|
+
"Int16Array",
|
|
25
|
+
"Uint16Array",
|
|
26
|
+
"Int32Array",
|
|
27
|
+
"Uint32Array",
|
|
28
|
+
"BigInt64Array",
|
|
29
|
+
"BigUint64Array",
|
|
30
|
+
"Float32Array",
|
|
31
|
+
"Float64Array",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const std::vector<std::string> SUPPORTED_STRUCTURED_DATA_TYPES = {
|
|
35
|
+
"ArrayBuffer",
|
|
36
|
+
"SharedArrayBuffer",
|
|
37
|
+
"DataView",
|
|
38
|
+
"Atomics",
|
|
39
|
+
"JSON",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const std::vector<std::string> SUPPORTED_MANAGING_MEMORY_TYPES = {
|
|
43
|
+
"WeakRef",
|
|
44
|
+
"FinalizationRegistry",
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const std::vector<std::string> SUPPORTED_ABSTRACTION_OBJECT_TYPES = {
|
|
48
|
+
"Iterator",
|
|
49
|
+
"AsyncIterator",
|
|
50
|
+
"Promise",
|
|
51
|
+
"GeneratorFunction",
|
|
52
|
+
"AsyncGeneratorFunction",
|
|
53
|
+
"Generator",
|
|
54
|
+
"AsyncGenerator",
|
|
55
|
+
"AsyncFunction",
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const std::vector<std::string> SUPPORTED_REFLECTION_TYPES = {
|
|
59
|
+
"Reflect",
|
|
60
|
+
"Proxy",
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
static inline std::string getObjectTypeName(
|
|
64
|
+
jsi::Runtime &rt,
|
|
65
|
+
const jsi::Object &object) {
|
|
66
|
+
return object.getPropertyAsObject(rt, "constructor")
|
|
67
|
+
.getProperty(rt, "name")
|
|
68
|
+
.toString(rt)
|
|
69
|
+
.utf8(rt);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
static inline bool isInstanceOf(
|
|
73
|
+
jsi::Runtime &rt,
|
|
74
|
+
const jsi::Object &object,
|
|
75
|
+
const std::string &type) {
|
|
76
|
+
return getObjectTypeName(rt, object) == type;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
static inline bool isInstanceOfAny(
|
|
80
|
+
jsi::Runtime &rt,
|
|
81
|
+
const jsi::Object &object,
|
|
82
|
+
const std::vector<std::string> &supportedTypes) {
|
|
83
|
+
auto instanceType = getObjectTypeName(rt, object);
|
|
84
|
+
|
|
85
|
+
return std::find(
|
|
86
|
+
supportedTypes.begin(), supportedTypes.end(), instanceType) !=
|
|
87
|
+
supportedTypes.end();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
JSISerializer::JSISerializer(jsi::Runtime &rt)
|
|
91
|
+
: rt_(rt),
|
|
92
|
+
visitedNodes_(rt_.global()
|
|
93
|
+
.getPropertyAsFunction(rt_, "Set")
|
|
94
|
+
.callAsConstructor(rt_)
|
|
95
|
+
.asObject(rt_)) {}
|
|
96
|
+
|
|
97
|
+
std::string JSISerializer::stringifyWithName(const jsi::Object &object) {
|
|
98
|
+
std::stringstream ss;
|
|
99
|
+
ss << '[' << getObjectTypeName(rt_, object) << ']';
|
|
100
|
+
|
|
101
|
+
return ss.str();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
std::string JSISerializer::stringifyArray(const jsi::Array &arr) {
|
|
105
|
+
std::stringstream ss;
|
|
106
|
+
ss << '[';
|
|
107
|
+
|
|
108
|
+
for (size_t i = 0, length = arr.size(rt_); i < length; i++) {
|
|
109
|
+
jsi::Value element = arr.getValueAtIndex(rt_, i);
|
|
110
|
+
ss << stringifyJSIValueRecursively(element);
|
|
111
|
+
if (i != length - 1) {
|
|
112
|
+
ss << ", ";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
ss << ']';
|
|
117
|
+
|
|
118
|
+
return ss.str();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
std::string JSISerializer::stringifyFunction(const jsi::Function &func) {
|
|
122
|
+
std::stringstream ss;
|
|
123
|
+
auto kind = (func.isHostFunction(rt_) ? "jsi::HostFunction" : "Function");
|
|
124
|
+
auto name = func.getProperty(rt_, "name").toString(rt_).utf8(rt_);
|
|
125
|
+
name = name.empty() ? "anonymous" : name;
|
|
126
|
+
|
|
127
|
+
ss << '[' << kind << ' ' << name << ']';
|
|
128
|
+
return ss.str();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
std::string JSISerializer::stringifyHostObject(jsi::HostObject &hostObject) {
|
|
132
|
+
int status = -1;
|
|
133
|
+
char *hostObjClassName =
|
|
134
|
+
abi::__cxa_demangle(typeid(hostObject).name(), NULL, NULL, &status);
|
|
135
|
+
if (status != 0) {
|
|
136
|
+
return "[jsi::HostObject]";
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
std::stringstream ss;
|
|
140
|
+
ss << "[jsi::HostObject(" << hostObjClassName << ")";
|
|
141
|
+
std::free(hostObjClassName);
|
|
142
|
+
|
|
143
|
+
auto props = hostObject.getPropertyNames(rt_);
|
|
144
|
+
auto propsCount = props.size();
|
|
145
|
+
|
|
146
|
+
if (propsCount > 0) {
|
|
147
|
+
ss << " {";
|
|
148
|
+
auto lastKey = props.back().utf8(rt_);
|
|
149
|
+
for (const auto &key : props) {
|
|
150
|
+
auto formattedKey = key.utf8(rt_);
|
|
151
|
+
auto value = hostObject.get(rt_, key);
|
|
152
|
+
ss << '"' << formattedKey << '"' << ": "
|
|
153
|
+
<< stringifyJSIValueRecursively(value);
|
|
154
|
+
if (formattedKey != lastKey) {
|
|
155
|
+
ss << ", ";
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
ss << '}';
|
|
159
|
+
}
|
|
160
|
+
ss << ']';
|
|
161
|
+
|
|
162
|
+
return ss.str();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
std::string JSISerializer::stringifyObject(const jsi::Object &object) {
|
|
166
|
+
std::stringstream ss;
|
|
167
|
+
ss << '{';
|
|
168
|
+
|
|
169
|
+
auto props = object.getPropertyNames(rt_);
|
|
170
|
+
|
|
171
|
+
for (size_t i = 0, propsCount = props.size(rt_); i < propsCount; i++) {
|
|
172
|
+
jsi::String propName = props.getValueAtIndex(rt_, i).toString(rt_);
|
|
173
|
+
ss << '"' << propName.utf8(rt_) << '"' << ": "
|
|
174
|
+
<< stringifyJSIValueRecursively(object.getProperty(rt_, propName));
|
|
175
|
+
if (i != propsCount - 1) {
|
|
176
|
+
ss << ", ";
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
ss << '}';
|
|
181
|
+
|
|
182
|
+
return ss.str();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
std::string JSISerializer::stringifyError(const jsi::Object &object) {
|
|
186
|
+
std::stringstream ss;
|
|
187
|
+
ss << '[' << object.getProperty(rt_, "name").toString(rt_).utf8(rt_) << ": "
|
|
188
|
+
<< object.getProperty(rt_, "message").toString(rt_).utf8(rt_) << ']';
|
|
189
|
+
return ss.str();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
std::string JSISerializer::stringifySet(const jsi::Object &object) {
|
|
193
|
+
std::stringstream ss;
|
|
194
|
+
jsi::Function arrayFrom = rt_.global()
|
|
195
|
+
.getPropertyAsObject(rt_, "Array")
|
|
196
|
+
.getPropertyAsFunction(rt_, "from");
|
|
197
|
+
jsi::Object result = arrayFrom.call(rt_, object).asObject(rt_);
|
|
198
|
+
|
|
199
|
+
if (!result.isArray(rt_)) {
|
|
200
|
+
return "[Set]";
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
auto arr = result.asArray(rt_);
|
|
204
|
+
ss << "Set {";
|
|
205
|
+
|
|
206
|
+
for (size_t i = 0, length = arr.size(rt_); i < length; i++) {
|
|
207
|
+
ss << stringifyJSIValueRecursively(arr.getValueAtIndex(rt_, i));
|
|
208
|
+
if (i != length - 1) {
|
|
209
|
+
ss << ", ";
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
ss << '}';
|
|
214
|
+
|
|
215
|
+
return ss.str();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
std::string JSISerializer::stringifyMap(const jsi::Object &object) {
|
|
219
|
+
std::stringstream ss;
|
|
220
|
+
jsi::Function arrayFrom = rt_.global()
|
|
221
|
+
.getPropertyAsObject(rt_, "Array")
|
|
222
|
+
.getPropertyAsFunction(rt_, "from");
|
|
223
|
+
jsi::Object result = arrayFrom.call(rt_, object).asObject(rt_);
|
|
224
|
+
|
|
225
|
+
if (!result.isArray(rt_)) {
|
|
226
|
+
return "[Map]";
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
auto arr = result.asArray(rt_);
|
|
230
|
+
ss << "Map {";
|
|
231
|
+
|
|
232
|
+
for (size_t i = 0, length = arr.size(rt_); i < length; i++) {
|
|
233
|
+
auto pair = arr.getValueAtIndex(rt_, i).asObject(rt_).getArray(rt_);
|
|
234
|
+
auto key = pair.getValueAtIndex(rt_, 0);
|
|
235
|
+
auto value = pair.getValueAtIndex(rt_, 1);
|
|
236
|
+
ss << stringifyJSIValueRecursively(key) << ": "
|
|
237
|
+
<< stringifyJSIValueRecursively(value);
|
|
238
|
+
if (i != length - 1) {
|
|
239
|
+
ss << ", ";
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
ss << '}';
|
|
244
|
+
|
|
245
|
+
return ss.str();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
std::string JSISerializer::stringifyRecursiveType(const jsi::Object &object) {
|
|
249
|
+
auto type = getObjectTypeName(rt_, object);
|
|
250
|
+
|
|
251
|
+
if (type == "Array") {
|
|
252
|
+
return "[...]";
|
|
253
|
+
}
|
|
254
|
+
if (type == "Object") {
|
|
255
|
+
return "{...}";
|
|
256
|
+
}
|
|
257
|
+
return "...";
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
std::string JSISerializer::stringifyWithToString(const jsi::Object &object) {
|
|
261
|
+
return object.getPropertyAsFunction(rt_, "toString")
|
|
262
|
+
.callWithThis(rt_, object)
|
|
263
|
+
.toString(rt_)
|
|
264
|
+
.utf8(rt_);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
std::string JSISerializer::stringifyJSIValueRecursively(
|
|
268
|
+
const jsi::Value &value,
|
|
269
|
+
bool isTopLevel) {
|
|
270
|
+
if (value.isBool() || value.isNumber()) {
|
|
271
|
+
return value.toString(rt_).utf8(rt_);
|
|
272
|
+
}
|
|
273
|
+
if (value.isString()) {
|
|
274
|
+
return isTopLevel ? value.getString(rt_).utf8(rt_)
|
|
275
|
+
: '"' + value.getString(rt_).utf8(rt_) + '"';
|
|
276
|
+
}
|
|
277
|
+
if (value.isSymbol()) {
|
|
278
|
+
return value.getSymbol(rt_).toString(rt_);
|
|
279
|
+
}
|
|
280
|
+
if (value.isBigInt()) {
|
|
281
|
+
return value.getBigInt(rt_).toString(rt_).utf8(rt_) + 'n';
|
|
282
|
+
}
|
|
283
|
+
if (value.isUndefined()) {
|
|
284
|
+
return "undefined";
|
|
285
|
+
}
|
|
286
|
+
if (value.isNull()) {
|
|
287
|
+
return "null";
|
|
288
|
+
}
|
|
289
|
+
if (value.isObject()) {
|
|
290
|
+
jsi::Object object = value.asObject(rt_);
|
|
291
|
+
|
|
292
|
+
if (hasBeenVisited(object)) {
|
|
293
|
+
return stringifyRecursiveType(object);
|
|
294
|
+
}
|
|
295
|
+
markAsVisited(object);
|
|
296
|
+
|
|
297
|
+
if (object.isArray(rt_)) {
|
|
298
|
+
return stringifyArray(object.getArray(rt_));
|
|
299
|
+
}
|
|
300
|
+
if (object.isFunction(rt_)) {
|
|
301
|
+
return stringifyFunction(object.getFunction(rt_));
|
|
302
|
+
}
|
|
303
|
+
if (object.isHostObject(rt_)) {
|
|
304
|
+
return stringifyHostObject(*object.getHostObject(rt_));
|
|
305
|
+
}
|
|
306
|
+
if (isInstanceOfAny(rt_, object, SUPPORTED_ERROR_TYPES)) {
|
|
307
|
+
return stringifyError(object);
|
|
308
|
+
}
|
|
309
|
+
if (isInstanceOfAny(rt_, object, SUPPORTED_INDEXED_COLLECTION_TYPES) ||
|
|
310
|
+
isInstanceOfAny(rt_, object, SUPPORTED_STRUCTURED_DATA_TYPES) ||
|
|
311
|
+
isInstanceOfAny(rt_, object, SUPPORTED_MANAGING_MEMORY_TYPES) ||
|
|
312
|
+
isInstanceOfAny(rt_, object, SUPPORTED_ABSTRACTION_OBJECT_TYPES) ||
|
|
313
|
+
isInstanceOfAny(rt_, object, SUPPORTED_REFLECTION_TYPES) ||
|
|
314
|
+
isInstanceOf(rt_, object, "Intl") ||
|
|
315
|
+
isInstanceOf(rt_, object, "WeakMap") ||
|
|
316
|
+
isInstanceOf(rt_, object, "WeakSet")) {
|
|
317
|
+
// TODO: Consider extending this log info
|
|
318
|
+
return stringifyWithName(object);
|
|
319
|
+
}
|
|
320
|
+
if (isInstanceOf(rt_, object, "Date") ||
|
|
321
|
+
isInstanceOf(rt_, object, "RegExp")) {
|
|
322
|
+
return stringifyWithToString(object);
|
|
323
|
+
}
|
|
324
|
+
if (isInstanceOf(rt_, object, "Map")) {
|
|
325
|
+
return stringifyMap(object);
|
|
326
|
+
}
|
|
327
|
+
if (isInstanceOf(rt_, object, "Set")) {
|
|
328
|
+
return stringifySet(object);
|
|
329
|
+
}
|
|
330
|
+
return stringifyObject(object);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
throw std::runtime_error("[Worklets] Unsupported value type.");
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
std::string stringifyJSIValue(jsi::Runtime &rt, const jsi::Value &value) {
|
|
337
|
+
JSISerializer serializer(rt);
|
|
338
|
+
|
|
339
|
+
return serializer.stringifyJSIValueRecursively(value, true);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
} // namespace worklets
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <jsi/jsi.h>
|
|
4
|
+
#include <string>
|
|
5
|
+
#include <vector>
|
|
6
|
+
|
|
7
|
+
using namespace facebook;
|
|
8
|
+
|
|
9
|
+
namespace worklets {
|
|
10
|
+
|
|
11
|
+
class JSISerializer {
|
|
12
|
+
public:
|
|
13
|
+
explicit JSISerializer(jsi::Runtime &rt);
|
|
14
|
+
std::string stringifyJSIValueRecursively(
|
|
15
|
+
const jsi::Value &value,
|
|
16
|
+
bool isTopLevel = false);
|
|
17
|
+
|
|
18
|
+
private:
|
|
19
|
+
std::string stringifyArray(const jsi::Array &arr);
|
|
20
|
+
std::string stringifyFunction(const jsi::Function &func);
|
|
21
|
+
std::string stringifyHostObject(jsi::HostObject &hostObject);
|
|
22
|
+
std::string stringifyObject(const jsi::Object &object);
|
|
23
|
+
std::string stringifyError(const jsi::Object &object);
|
|
24
|
+
std::string stringifySet(const jsi::Object &object);
|
|
25
|
+
std::string stringifyMap(const jsi::Object &object);
|
|
26
|
+
std::string stringifyWithName(const jsi::Object &object);
|
|
27
|
+
std::string stringifyWithToString(const jsi::Object &object);
|
|
28
|
+
std::string stringifyRecursiveType(const jsi::Object &object);
|
|
29
|
+
|
|
30
|
+
bool hasBeenVisited(const jsi::Object &object) {
|
|
31
|
+
return visitedNodes_.getPropertyAsFunction(rt_, "has")
|
|
32
|
+
.callWithThis(rt_, visitedNodes_, object)
|
|
33
|
+
.getBool();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void markAsVisited(const jsi::Object &object) {
|
|
37
|
+
visitedNodes_.getPropertyAsFunction(rt_, "add")
|
|
38
|
+
.callWithThis(rt_, visitedNodes_, object);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
jsi::Runtime &rt_;
|
|
42
|
+
jsi::Object visitedNodes_;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
std::string stringifyJSIValue(jsi::Runtime &rt, const jsi::Value &value);
|
|
46
|
+
|
|
47
|
+
} // namespace worklets
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#include <worklets/Tools/JSLogger.h>
|
|
2
|
+
#include <memory>
|
|
3
|
+
|
|
4
|
+
namespace worklets {
|
|
5
|
+
|
|
6
|
+
void JSLogger::warnOnJS(const std::string &warning) const {
|
|
7
|
+
#ifndef NDEBUG
|
|
8
|
+
jsScheduler_->scheduleOnJS([warning](jsi::Runtime &rt) {
|
|
9
|
+
auto console = rt.global().getPropertyAsObject(rt, "console");
|
|
10
|
+
auto warn = console.getPropertyAsFunction(rt, "warn");
|
|
11
|
+
warn.call(rt, jsi::String::createFromUtf8(rt, warning));
|
|
12
|
+
});
|
|
13
|
+
#endif // NDEBUG
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
} // namespace worklets
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <worklets/Tools/JSScheduler.h>
|
|
4
|
+
|
|
5
|
+
#include <memory>
|
|
6
|
+
#include <string>
|
|
7
|
+
|
|
8
|
+
namespace worklets {
|
|
9
|
+
|
|
10
|
+
class JSLogger {
|
|
11
|
+
public:
|
|
12
|
+
explicit JSLogger(const std::shared_ptr<JSScheduler> &jsScheduler)
|
|
13
|
+
: jsScheduler_(jsScheduler) {}
|
|
14
|
+
void warnOnJS(const std::string &warning) const;
|
|
15
|
+
|
|
16
|
+
private:
|
|
17
|
+
const std::shared_ptr<JSScheduler> jsScheduler_;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
} // namespace worklets
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <ReactCommon/CallInvoker.h>
|
|
4
|
+
#include <jsi/jsi.h>
|
|
5
|
+
|
|
6
|
+
#include <memory>
|
|
7
|
+
|
|
8
|
+
using namespace facebook;
|
|
9
|
+
using namespace react;
|
|
10
|
+
|
|
11
|
+
namespace worklets {
|
|
12
|
+
|
|
13
|
+
class JSScheduler {
|
|
14
|
+
using Job = std::function<void(jsi::Runtime &rt)>;
|
|
15
|
+
|
|
16
|
+
public:
|
|
17
|
+
explicit JSScheduler(
|
|
18
|
+
jsi::Runtime &rnRuntime,
|
|
19
|
+
const std::shared_ptr<CallInvoker> &jsCallInvoker)
|
|
20
|
+
: rnRuntime_(rnRuntime), jsCallInvoker_(jsCallInvoker) {}
|
|
21
|
+
|
|
22
|
+
void scheduleOnJS(std::function<void(jsi::Runtime &rt)> job);
|
|
23
|
+
|
|
24
|
+
protected:
|
|
25
|
+
jsi::Runtime &rnRuntime_;
|
|
26
|
+
const std::shared_ptr<CallInvoker> jsCallInvoker_;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
} // namespace worklets
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <string>
|
|
4
|
+
|
|
5
|
+
namespace worklets {
|
|
6
|
+
|
|
7
|
+
class PlatformLogger {
|
|
8
|
+
public:
|
|
9
|
+
static void log(const char *str);
|
|
10
|
+
static void log(const std::string &str);
|
|
11
|
+
static void log(const double d);
|
|
12
|
+
static void log(const int i);
|
|
13
|
+
static void log(const bool b);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
} // namespace worklets
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#ifndef NDEBUG
|
|
4
|
+
|
|
5
|
+
#include <cxxabi.h>
|
|
6
|
+
|
|
7
|
+
#include <atomic>
|
|
8
|
+
#include <cassert>
|
|
9
|
+
#include <iostream>
|
|
10
|
+
#include <string>
|
|
11
|
+
|
|
12
|
+
#ifdef ANDROID
|
|
13
|
+
#include <android/log.h>
|
|
14
|
+
#endif // ANDROID
|
|
15
|
+
|
|
16
|
+
namespace worklets {
|
|
17
|
+
|
|
18
|
+
// This is a class that counts how many instances of a different class there
|
|
19
|
+
// are. It is meant only to be used with classes that should only have one
|
|
20
|
+
// instance.
|
|
21
|
+
|
|
22
|
+
template <class T>
|
|
23
|
+
class SingleInstanceChecker {
|
|
24
|
+
public:
|
|
25
|
+
SingleInstanceChecker();
|
|
26
|
+
~SingleInstanceChecker();
|
|
27
|
+
|
|
28
|
+
private:
|
|
29
|
+
void assertWithMessage(bool condition, std::string message) {
|
|
30
|
+
if (!condition) {
|
|
31
|
+
#ifdef ANDROID
|
|
32
|
+
__android_log_print(
|
|
33
|
+
ANDROID_LOG_WARN, "Worklets", "%s", message.c_str());
|
|
34
|
+
#else
|
|
35
|
+
std::cerr << "[Worklets] " << message << std::endl;
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
#ifdef IS_REANIMATED_EXAMPLE_APP
|
|
39
|
+
assert(false);
|
|
40
|
+
#endif
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// A static field will exist separately for every class template.
|
|
45
|
+
// This has to be inline for automatic initialization.
|
|
46
|
+
inline static std::atomic<int> instanceCount_;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
template <class T>
|
|
50
|
+
SingleInstanceChecker<T>::SingleInstanceChecker() {
|
|
51
|
+
int status = 0;
|
|
52
|
+
std::string className =
|
|
53
|
+
__cxxabiv1::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
|
|
54
|
+
|
|
55
|
+
// React Native can spawn up to two instances of a Native Module at the same
|
|
56
|
+
// time. This happens during a reload when a new instance of React Native is
|
|
57
|
+
// created while simultaneously the old one is torn down.
|
|
58
|
+
instanceCount_++;
|
|
59
|
+
assertWithMessage(
|
|
60
|
+
instanceCount_ <= 2,
|
|
61
|
+
"[Worklets] More than two instances of " + className +
|
|
62
|
+
" present. This may indicate a memory leak due to a retain cycle.");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
template <class T>
|
|
66
|
+
SingleInstanceChecker<T>::~SingleInstanceChecker() {
|
|
67
|
+
instanceCount_--;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
} // namespace worklets
|
|
71
|
+
|
|
72
|
+
#endif // NDEBUG
|