@amazon-devices/react-native-worklets 1.0.0-rn-83
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/JSIWorkletsModuleProxy.cpp +712 -0
- package/Common/cpp/worklets/NativeModules/JSIWorkletsModuleProxy.h +88 -0
- package/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp +89 -0
- package/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h +80 -0
- package/Common/cpp/worklets/Public/AsyncQueue.h +14 -0
- package/Common/cpp/worklets/Registries/EventHandlerRegistry.cpp +94 -0
- package/Common/cpp/worklets/Registries/EventHandlerRegistry.h +51 -0
- package/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.cpp +8 -0
- package/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.h +40 -0
- package/Common/cpp/worklets/Resources/SynchronizableUnpacker.cpp +49 -0
- package/Common/cpp/worklets/Resources/Unpackers.h +6 -0
- package/Common/cpp/worklets/Resources/ValueUnpacker.cpp +53 -0
- package/Common/cpp/worklets/RunLoop/AsyncQueueImpl.cpp +62 -0
- package/Common/cpp/worklets/RunLoop/AsyncQueueImpl.h +46 -0
- package/Common/cpp/worklets/RunLoop/EventLoop.cpp +112 -0
- package/Common/cpp/worklets/RunLoop/EventLoop.h +52 -0
- package/Common/cpp/worklets/SharedItems/Serializable.cpp +545 -0
- package/Common/cpp/worklets/SharedItems/Serializable.h +473 -0
- package/Common/cpp/worklets/SharedItems/Synchronizable.cpp +67 -0
- package/Common/cpp/worklets/SharedItems/Synchronizable.h +59 -0
- package/Common/cpp/worklets/SharedItems/SynchronizableAccess.cpp +81 -0
- package/Common/cpp/worklets/SharedItems/SynchronizableAccess.h +45 -0
- package/Common/cpp/worklets/Tools/Defs.h +10 -0
- package/Common/cpp/worklets/Tools/FeatureFlags.cpp +15 -0
- package/Common/cpp/worklets/Tools/FeatureFlags.h +44 -0
- package/Common/cpp/worklets/Tools/JSISerializer.cpp +342 -0
- package/Common/cpp/worklets/Tools/JSISerializer.h +51 -0
- package/Common/cpp/worklets/Tools/JSLogger.cpp +68 -0
- package/Common/cpp/worklets/Tools/JSLogger.h +37 -0
- package/Common/cpp/worklets/Tools/JSScheduler.cpp +24 -0
- package/Common/cpp/worklets/Tools/JSScheduler.h +39 -0
- package/Common/cpp/worklets/Tools/PlatformLogger.h +16 -0
- package/Common/cpp/worklets/Tools/SingleInstanceChecker.h +82 -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 +26 -0
- package/Common/cpp/worklets/Tools/VersionUtils.cpp +75 -0
- package/Common/cpp/worklets/Tools/VersionUtils.h +28 -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 +46 -0
- package/Common/cpp/worklets/Tools/WorkletsJSIUtils.h +208 -0
- package/Common/cpp/worklets/Tools/WorkletsSystraceSection.h +161 -0
- package/Common/cpp/worklets/Tools/WorkletsVersion.cpp +54 -0
- package/Common/cpp/worklets/Tools/WorkletsVersion.h +20 -0
- package/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.cpp +38 -0
- package/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h +21 -0
- package/Common/cpp/worklets/WorkletRuntime/RuntimeData.cpp +3 -0
- package/Common/cpp/worklets/WorkletRuntime/RuntimeData.h +12 -0
- package/Common/cpp/worklets/WorkletRuntime/RuntimeInitialization.md +191 -0
- package/Common/cpp/worklets/WorkletRuntime/RuntimeKind.h +16 -0
- package/Common/cpp/worklets/WorkletRuntime/RuntimeManager.cpp +105 -0
- package/Common/cpp/worklets/WorkletRuntime/RuntimeManager.h +63 -0
- package/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.cpp +23 -0
- package/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.h +16 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletHermesRuntime.cpp +119 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletHermesRuntime.h +134 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.cpp +244 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.h +102 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeCollector.h +36 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp +308 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.h +26 -0
- package/LICENSE +7 -0
- package/README.md +31 -0
- package/RNWorklets.podspec +94 -0
- package/SystemBundles/cc12deac6e91c435b76698c8445aed85612f2f88e733218d14f88a35d06fb0f4.bundle +10512 -0
- package/SystemBundles/cc12deac6e91c435b76698c8445aed85612f2f88e733218d14f88a35d06fb0f4.map +3771 -0
- package/SystemModules/amzn__react-native-worklets-1.modules.txt +39 -0
- package/SystemModules/amzn__react-native-worklets-1.private.modules.txt +61 -0
- package/SystemModules/keplerscript-system-bundle-config.json +7 -0
- package/android/CMakeLists.txt +124 -0
- package/android/build.gradle +350 -0
- package/android/gradle.properties +5 -0
- package/android/proguard-rules.pro +3 -0
- package/android/spotless.gradle +9 -0
- package/android/src/experimentalBundling/com/swmansion/worklets/WorkletsModule.java +149 -0
- package/android/src/legacyBundling/com/swmansion/worklets/WorkletsModule.java +122 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/worklets/android/AndroidUIScheduler.cpp +63 -0
- package/android/src/main/cpp/worklets/android/AndroidUIScheduler.h +43 -0
- package/android/src/main/cpp/worklets/android/AnimationFrameCallback.h +34 -0
- package/android/src/main/cpp/worklets/android/PlatformLogger.cpp +29 -0
- package/android/src/main/cpp/worklets/android/WorkletsModule.cpp +115 -0
- package/android/src/main/cpp/worklets/android/WorkletsModule.h +78 -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/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 +73 -0
- package/android/src/main/java/com/swmansion/worklets/WorkletsPackage.java +48 -0
- package/android/src/main/java/com/swmansion/worklets/runloop/AnimationFrameCallback.java +19 -0
- package/android/src/main/java/com/swmansion/worklets/runloop/AnimationFrameQueue.java +113 -0
- package/apple/worklets/apple/AnimationFrameQueue.h +15 -0
- package/apple/worklets/apple/AnimationFrameQueue.mm +135 -0
- package/apple/worklets/apple/AssertJavaScriptQueue.h +14 -0
- package/apple/worklets/apple/AssertTurboModuleManagerQueue.h +16 -0
- package/apple/worklets/apple/IOSUIScheduler.h +15 -0
- package/apple/worklets/apple/IOSUIScheduler.mm +29 -0
- package/apple/worklets/apple/PlatformLogger.mm +31 -0
- package/apple/worklets/apple/SlowAnimations.h +8 -0
- package/apple/worklets/apple/SlowAnimations.mm +45 -0
- package/apple/worklets/apple/WorkletsDisplayLink.h +21 -0
- package/apple/worklets/apple/WorkletsMessageThread.h +16 -0
- package/apple/worklets/apple/WorkletsMessageThread.mm +31 -0
- package/apple/worklets/apple/WorkletsModule.h +28 -0
- package/apple/worklets/apple/WorkletsModule.mm +121 -0
- package/bundleMode/index.d.ts +3 -0
- package/bundleMode/index.js +59 -0
- package/compatibility.json +11 -0
- package/kepler-compatibility.json +5 -0
- package/kepler-transformed-package-info.json +3 -0
- package/lib/module/PlatformChecker/PlatformChecker.js +8 -0
- package/lib/module/PlatformChecker/PlatformChecker.js.map +1 -0
- package/lib/module/PlatformChecker/index.js +18 -0
- package/lib/module/PlatformChecker/index.js.map +1 -0
- package/lib/module/WorkletsError.js +29 -0
- package/lib/module/WorkletsError.js.map +1 -0
- package/lib/module/WorkletsModule/JSWorklets.js +111 -0
- package/lib/module/WorkletsModule/JSWorklets.js.map +1 -0
- package/lib/module/WorkletsModule/NativeWorklets.js +126 -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/bundleUnpacker.js +47 -0
- package/lib/module/bundleUnpacker.js.map +1 -0
- package/lib/module/callGuard.js +30 -0
- package/lib/module/callGuard.js.map +1 -0
- package/lib/module/deprecated.js +20 -0
- package/lib/module/deprecated.js.map +1 -0
- package/lib/module/errors.js +69 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/featureFlags/index.js +48 -0
- package/lib/module/featureFlags/index.js.map +1 -0
- package/lib/module/featureFlags/staticFlags.json +4 -0
- package/lib/module/index.js +26 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/initializers.js +221 -0
- package/lib/module/initializers.js.map +1 -0
- package/lib/module/isSynchronizable.js +6 -0
- package/lib/module/isSynchronizable.js.map +1 -0
- package/lib/module/logger.js +15 -0
- package/lib/module/logger.js.map +1 -0
- package/lib/module/privateGlobals.d.js +7 -0
- package/lib/module/privateGlobals.d.js.map +1 -0
- package/lib/module/publicGlobals.js +6 -0
- package/lib/module/publicGlobals.js.map +1 -0
- package/lib/module/runLoop/common/setImmediatePolyfill.js +15 -0
- package/lib/module/runLoop/common/setImmediatePolyfill.js.map +1 -0
- package/lib/module/runLoop/common/setIntervalPolyfill.js +26 -0
- package/lib/module/runLoop/common/setIntervalPolyfill.js.map +1 -0
- package/lib/module/runLoop/uiRuntime/mockedRequestAnimationFrame.js +10 -0
- package/lib/module/runLoop/uiRuntime/mockedRequestAnimationFrame.js.map +1 -0
- package/lib/module/runLoop/uiRuntime/requestAnimationFrame.js +52 -0
- package/lib/module/runLoop/uiRuntime/requestAnimationFrame.js.map +1 -0
- package/lib/module/runLoop/uiRuntime/setTimeoutPolyfill.js +32 -0
- package/lib/module/runLoop/uiRuntime/setTimeoutPolyfill.js.map +1 -0
- package/lib/module/runLoop/workletRuntime/index.js +19 -0
- package/lib/module/runLoop/workletRuntime/index.js.map +1 -0
- package/lib/module/runLoop/workletRuntime/queueMicrotask.js +11 -0
- package/lib/module/runLoop/workletRuntime/queueMicrotask.js.map +1 -0
- package/lib/module/runLoop/workletRuntime/requestAnimationFramePolyfill.js +48 -0
- package/lib/module/runLoop/workletRuntime/requestAnimationFramePolyfill.js.map +1 -0
- package/lib/module/runLoop/workletRuntime/setTimeout.js +28 -0
- package/lib/module/runLoop/workletRuntime/setTimeout.js.map +1 -0
- package/lib/module/runLoop/workletRuntime/taskQueue.js +37 -0
- package/lib/module/runLoop/workletRuntime/taskQueue.js.map +1 -0
- package/lib/module/runtimeKind.js +39 -0
- package/lib/module/runtimeKind.js.map +1 -0
- package/lib/module/runtimes.js +100 -0
- package/lib/module/runtimes.js.map +1 -0
- package/lib/module/serializable.js +568 -0
- package/lib/module/serializable.js.map +1 -0
- package/lib/module/serializableMappingCache.js +37 -0
- package/lib/module/serializableMappingCache.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/NativeWorkletsModule.kepler.js +7 -0
- package/lib/module/specs/NativeWorkletsModule.kepler.js.map +1 -0
- package/lib/module/specs/index.js +10 -0
- package/lib/module/specs/index.js.map +1 -0
- package/lib/module/synchronizable.js +9 -0
- package/lib/module/synchronizable.js.map +1 -0
- package/lib/module/synchronizableUnpacker.js +42 -0
- package/lib/module/synchronizableUnpacker.js.map +1 -0
- package/lib/module/threads.js +347 -0
- package/lib/module/threads.js.map +1 -0
- package/lib/module/utils/checkCppVersion.js +30 -0
- package/lib/module/utils/checkCppVersion.js.map +1 -0
- package/lib/module/utils/jsVersion.js +9 -0
- package/lib/module/utils/jsVersion.js.map +1 -0
- package/lib/module/valueUnpacker.js +60 -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/workletRuntimeEntry.js +32 -0
- package/lib/module/workletRuntimeEntry.js.map +1 -0
- package/lib/module/workletTypes.js +12 -0
- package/lib/module/workletTypes.js.map +1 -0
- package/lib/typescript/PlatformChecker/PlatformChecker.d.ts +5 -0
- package/lib/typescript/PlatformChecker/PlatformChecker.d.ts.map +1 -0
- package/lib/typescript/PlatformChecker/index.d.ts +10 -0
- package/lib/typescript/PlatformChecker/index.d.ts.map +1 -0
- package/lib/typescript/WorkletsError.d.ts +15 -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 +3 -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 +37 -0
- package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts.map +1 -0
- package/lib/typescript/bundleUnpacker.d.ts +7 -0
- package/lib/typescript/bundleUnpacker.d.ts.map +1 -0
- package/lib/typescript/callGuard.d.ts +4 -0
- package/lib/typescript/callGuard.d.ts.map +1 -0
- package/lib/typescript/deprecated.d.ts +20 -0
- package/lib/typescript/deprecated.d.ts.map +1 -0
- package/lib/typescript/errors.d.ts +16 -0
- package/lib/typescript/errors.d.ts.map +1 -0
- package/lib/typescript/featureFlags/index.d.ts +23 -0
- package/lib/typescript/featureFlags/index.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +17 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/initializers.d.ts +17 -0
- package/lib/typescript/initializers.d.ts.map +1 -0
- package/lib/typescript/isSynchronizable.d.ts +3 -0
- package/lib/typescript/isSynchronizable.d.ts.map +1 -0
- package/lib/typescript/logger.d.ts +5 -0
- package/lib/typescript/logger.d.ts.map +1 -0
- package/lib/typescript/publicGlobals.d.ts +31 -0
- package/lib/typescript/publicGlobals.d.ts.map +1 -0
- package/lib/typescript/runLoop/common/setImmediatePolyfill.d.ts +2 -0
- package/lib/typescript/runLoop/common/setImmediatePolyfill.d.ts.map +1 -0
- package/lib/typescript/runLoop/common/setIntervalPolyfill.d.ts +2 -0
- package/lib/typescript/runLoop/common/setIntervalPolyfill.d.ts.map +1 -0
- package/lib/typescript/runLoop/uiRuntime/mockedRequestAnimationFrame.d.ts +6 -0
- package/lib/typescript/runLoop/uiRuntime/mockedRequestAnimationFrame.d.ts.map +1 -0
- package/lib/typescript/runLoop/uiRuntime/requestAnimationFrame.d.ts +2 -0
- package/lib/typescript/runLoop/uiRuntime/requestAnimationFrame.d.ts.map +1 -0
- package/lib/typescript/runLoop/uiRuntime/setTimeoutPolyfill.d.ts +2 -0
- package/lib/typescript/runLoop/uiRuntime/setTimeoutPolyfill.d.ts.map +1 -0
- package/lib/typescript/runLoop/workletRuntime/index.d.ts +2 -0
- package/lib/typescript/runLoop/workletRuntime/index.d.ts.map +1 -0
- package/lib/typescript/runLoop/workletRuntime/queueMicrotask.d.ts +2 -0
- package/lib/typescript/runLoop/workletRuntime/queueMicrotask.d.ts.map +1 -0
- package/lib/typescript/runLoop/workletRuntime/requestAnimationFramePolyfill.d.ts +2 -0
- package/lib/typescript/runLoop/workletRuntime/requestAnimationFramePolyfill.d.ts.map +1 -0
- package/lib/typescript/runLoop/workletRuntime/setTimeout.d.ts +2 -0
- package/lib/typescript/runLoop/workletRuntime/setTimeout.d.ts.map +1 -0
- package/lib/typescript/runLoop/workletRuntime/taskQueue.d.ts +10 -0
- package/lib/typescript/runLoop/workletRuntime/taskQueue.d.ts.map +1 -0
- package/lib/typescript/runtimeKind.d.ts +25 -0
- package/lib/typescript/runtimeKind.d.ts.map +1 -0
- package/lib/typescript/runtimes.d.ts +77 -0
- package/lib/typescript/runtimes.d.ts.map +1 -0
- package/lib/typescript/serializable.d.ts +20 -0
- package/lib/typescript/serializable.d.ts.map +1 -0
- package/lib/typescript/serializableMappingCache.d.ts +16 -0
- package/lib/typescript/serializableMappingCache.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/NativeWorkletsModule.kepler.d.ts +7 -0
- package/lib/typescript/specs/NativeWorkletsModule.kepler.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/synchronizable.d.ts +15 -0
- package/lib/typescript/synchronizable.d.ts.map +1 -0
- package/lib/typescript/synchronizableUnpacker.d.ts +4 -0
- package/lib/typescript/synchronizableUnpacker.d.ts.map +1 -0
- package/lib/typescript/threads.d.ts +138 -0
- package/lib/typescript/threads.d.ts.map +1 -0
- package/lib/typescript/utils/checkCppVersion.d.ts +3 -0
- package/lib/typescript/utils/checkCppVersion.d.ts.map +1 -0
- package/lib/typescript/utils/jsVersion.d.ts +7 -0
- package/lib/typescript/utils/jsVersion.d.ts.map +1 -0
- package/lib/typescript/valueUnpacker.d.ts +6 -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/workletRuntimeEntry.d.ts +14 -0
- package/lib/typescript/workletRuntimeEntry.d.ts.map +1 -0
- package/lib/typescript/workletTypes.d.ts +61 -0
- package/lib/typescript/workletTypes.d.ts.map +1 -0
- package/package.json +153 -0
- package/plugin/index.js +1761 -0
- package/react-native.config.js +21 -0
- package/scripts/validate-react-native-version.js +43 -0
- package/scripts/worklets_utils.rb +94 -0
- package/src/PlatformChecker/PlatformChecker.ts +7 -0
- package/src/PlatformChecker/index.ts +30 -0
- package/src/WorkletsError.ts +36 -0
- package/src/WorkletsModule/JSWorklets.ts +200 -0
- package/src/WorkletsModule/NativeWorklets.ts +256 -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 +126 -0
- package/src/bundleUnpacker.ts +75 -0
- package/src/callGuard.ts +33 -0
- package/src/deprecated.ts +32 -0
- package/src/errors.ts +80 -0
- package/src/featureFlags/index.ts +72 -0
- package/src/featureFlags/staticFlags.json +4 -0
- package/src/index.ts +53 -0
- package/src/initializers.ts +262 -0
- package/src/isSynchronizable.ts +13 -0
- package/src/logger.ts +16 -0
- package/src/privateGlobals.d.ts +79 -0
- package/src/publicGlobals.ts +39 -0
- package/src/runLoop/common/setImmediatePolyfill.ts +20 -0
- package/src/runLoop/common/setIntervalPolyfill.ts +38 -0
- package/src/runLoop/uiRuntime/mockedRequestAnimationFrame.ts +11 -0
- package/src/runLoop/uiRuntime/requestAnimationFrame.ts +66 -0
- package/src/runLoop/uiRuntime/setTimeoutPolyfill.ts +40 -0
- package/src/runLoop/workletRuntime/index.ts +18 -0
- package/src/runLoop/workletRuntime/queueMicrotask.ts +13 -0
- package/src/runLoop/workletRuntime/requestAnimationFramePolyfill.ts +61 -0
- package/src/runLoop/workletRuntime/setTimeout.ts +37 -0
- package/src/runLoop/workletRuntime/taskQueue.ts +44 -0
- package/src/runtimeKind.ts +37 -0
- package/src/runtimes.ts +193 -0
- package/src/serializable.ts +801 -0
- package/src/serializableMappingCache.ts +42 -0
- package/src/specs/NativeWorkletsModule.kepler.ts +11 -0
- package/src/specs/NativeWorkletsModule.ts +9 -0
- package/src/specs/index.ts +13 -0
- package/src/synchronizable.ts +32 -0
- package/src/synchronizableUnpacker.ts +67 -0
- package/src/threads.ts +452 -0
- package/src/utils/checkCppVersion.ts +34 -0
- package/src/utils/jsVersion.ts +7 -0
- package/src/valueUnpacker.ts +90 -0
- package/src/workletFunction.ts +42 -0
- package/src/workletRuntimeEntry.ts +35 -0
- package/src/workletTypes.ts +81 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
package com.swmansion.worklets;
|
|
2
|
+
|
|
3
|
+
import com.facebook.jni.HybridData;
|
|
4
|
+
import com.facebook.proguard.annotations.DoNotStrip;
|
|
5
|
+
import com.facebook.react.bridge.GuardedRunnable;
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
7
|
+
import com.facebook.react.bridge.UiThreadUtil;
|
|
8
|
+
import java.util.concurrent.atomic.AtomicBoolean;
|
|
9
|
+
|
|
10
|
+
@SuppressWarnings("JavaJniMissingFunction")
|
|
11
|
+
public class AndroidUIScheduler {
|
|
12
|
+
|
|
13
|
+
@DoNotStrip
|
|
14
|
+
@SuppressWarnings({"unused", "FieldCanBeLocal"})
|
|
15
|
+
private final HybridData mHybridData;
|
|
16
|
+
|
|
17
|
+
private final ReactApplicationContext mContext;
|
|
18
|
+
private final AtomicBoolean mActive = new AtomicBoolean(true);
|
|
19
|
+
|
|
20
|
+
private final Runnable mUIThreadRunnable =
|
|
21
|
+
() -> {
|
|
22
|
+
// This callback is called on the UI thread, but the module is invalidated on the JS
|
|
23
|
+
// thread. Therefore we must synchronize for reloads. Without synchronization the cpp part
|
|
24
|
+
// gets torn down while the UI thread is still executing it, leading to crashes.
|
|
25
|
+
synchronized (mActive) {
|
|
26
|
+
if (mActive.get()) {
|
|
27
|
+
triggerUI();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
public AndroidUIScheduler(ReactApplicationContext context) {
|
|
33
|
+
mHybridData = initHybrid();
|
|
34
|
+
mContext = context;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private native HybridData initHybrid();
|
|
38
|
+
|
|
39
|
+
public native void triggerUI();
|
|
40
|
+
|
|
41
|
+
public native void invalidate();
|
|
42
|
+
|
|
43
|
+
@DoNotStrip
|
|
44
|
+
@SuppressWarnings("unused")
|
|
45
|
+
private void scheduleTriggerOnUI() {
|
|
46
|
+
UiThreadUtil.runOnUiThread(
|
|
47
|
+
new GuardedRunnable(mContext.getExceptionHandler()) {
|
|
48
|
+
public void runGuarded() {
|
|
49
|
+
mUIThreadRunnable.run();
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public void deactivate() {
|
|
55
|
+
synchronized (mActive) {
|
|
56
|
+
mActive.set(false);
|
|
57
|
+
invalidate();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
package com.swmansion.worklets;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.OptIn;
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
5
|
+
import com.facebook.react.common.annotations.FrameworkAPI;
|
|
6
|
+
import com.facebook.react.turbomodule.core.CallInvokerHolderImpl;
|
|
7
|
+
|
|
8
|
+
public class JSCallInvokerResolver {
|
|
9
|
+
|
|
10
|
+
@OptIn(markerClass = FrameworkAPI.class)
|
|
11
|
+
public static CallInvokerHolderImpl getJSCallInvokerHolder(ReactApplicationContext context) {
|
|
12
|
+
try {
|
|
13
|
+
var method = context.getClass().getMethod("getJSCallInvokerHolder");
|
|
14
|
+
return (CallInvokerHolderImpl) method.invoke(context);
|
|
15
|
+
} catch (Exception ignored) {
|
|
16
|
+
// In newer implementations, the method is in CatalystInstance, continue.
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
var catalystInstance = context.getClass().getMethod("getCatalystInstance").invoke(context);
|
|
20
|
+
assert catalystInstance != null;
|
|
21
|
+
var method = catalystInstance.getClass().getMethod("getJSCallInvokerHolder");
|
|
22
|
+
return (CallInvokerHolderImpl) method.invoke(catalystInstance);
|
|
23
|
+
} catch (Exception e) {
|
|
24
|
+
throw new RuntimeException("Failed to get JSCallInvokerHolder", e);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.swmansion.worklets;
|
|
2
|
+
|
|
3
|
+
import com.facebook.proguard.annotations.DoNotStrip;
|
|
4
|
+
|
|
5
|
+
@DoNotStrip
|
|
6
|
+
public class WorkletsMessageQueueThread extends WorkletsMessageQueueThreadBase {
|
|
7
|
+
@Override
|
|
8
|
+
public boolean runOnQueue(Runnable runnable) {
|
|
9
|
+
return messageQueueThread.runOnQueue(runnable);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@Override
|
|
13
|
+
public boolean isIdle() {
|
|
14
|
+
return messageQueueThread.isIdle();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
package com.swmansion.worklets;
|
|
2
|
+
|
|
3
|
+
import com.facebook.proguard.annotations.DoNotStrip;
|
|
4
|
+
import com.facebook.react.bridge.queue.MessageQueueThread;
|
|
5
|
+
import com.facebook.react.bridge.queue.MessageQueueThreadImpl;
|
|
6
|
+
import com.facebook.react.bridge.queue.MessageQueueThreadPerfStats;
|
|
7
|
+
import com.facebook.react.bridge.queue.MessageQueueThreadSpec;
|
|
8
|
+
import java.lang.reflect.Field;
|
|
9
|
+
import java.util.concurrent.Callable;
|
|
10
|
+
import java.util.concurrent.Future;
|
|
11
|
+
|
|
12
|
+
// This class is an almost exact copy of MessageQueueThreadImpl taken from here:
|
|
13
|
+
// https://github.com/facebook/react-native/blob/main/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadImpl.kt
|
|
14
|
+
// The only method that has changed is `quitSynchronous()` (see comment above
|
|
15
|
+
// function implementation for details).
|
|
16
|
+
@DoNotStrip
|
|
17
|
+
public abstract class WorkletsMessageQueueThreadBase implements MessageQueueThread {
|
|
18
|
+
protected final MessageQueueThreadImpl messageQueueThread;
|
|
19
|
+
|
|
20
|
+
public WorkletsMessageQueueThreadBase() {
|
|
21
|
+
messageQueueThread =
|
|
22
|
+
MessageQueueThreadImpl.create(
|
|
23
|
+
MessageQueueThreadSpec.mainThreadSpec(),
|
|
24
|
+
exception -> {
|
|
25
|
+
throw new RuntimeException(exception);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Override
|
|
30
|
+
public <T> Future<T> callOnQueue(Callable<T> callable) {
|
|
31
|
+
return messageQueueThread.callOnQueue(callable);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@Override
|
|
35
|
+
public boolean isOnThread() {
|
|
36
|
+
return messageQueueThread.isOnThread();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@Override
|
|
40
|
+
public void assertIsOnThread() {
|
|
41
|
+
messageQueueThread.assertIsOnThread();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@Override
|
|
45
|
+
public void assertIsOnThread(String s) {
|
|
46
|
+
messageQueueThread.assertIsOnThread(s);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// We don't want to quit the main looper (which is what MessageQueueThreadImpl would have done),
|
|
50
|
+
// but we still want to prevent anything else from executing.
|
|
51
|
+
@Override
|
|
52
|
+
@SuppressWarnings("CallToPrintStackTrace")
|
|
53
|
+
public void quitSynchronous() {
|
|
54
|
+
try {
|
|
55
|
+
Field mIsFinished = messageQueueThread.getClass().getDeclaredField("mIsFinished");
|
|
56
|
+
mIsFinished.setAccessible(true);
|
|
57
|
+
mIsFinished.set(messageQueueThread, true);
|
|
58
|
+
mIsFinished.setAccessible(false);
|
|
59
|
+
} catch (NoSuchFieldException | IllegalAccessException e) {
|
|
60
|
+
e.printStackTrace();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@Override
|
|
65
|
+
public MessageQueueThreadPerfStats getPerfStats() {
|
|
66
|
+
return messageQueueThread.getPerfStats();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@Override
|
|
70
|
+
public void resetPerfStats() {
|
|
71
|
+
messageQueueThread.resetPerfStats();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
package com.swmansion.worklets;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import com.facebook.react.BaseReactPackage;
|
|
5
|
+
import com.facebook.react.ReactPackage;
|
|
6
|
+
import com.facebook.react.bridge.NativeModule;
|
|
7
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
8
|
+
import com.facebook.react.module.annotations.ReactModule;
|
|
9
|
+
import com.facebook.react.module.annotations.ReactModuleList;
|
|
10
|
+
import com.facebook.react.module.model.ReactModuleInfo;
|
|
11
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
|
12
|
+
import java.util.HashMap;
|
|
13
|
+
import java.util.Map;
|
|
14
|
+
import java.util.Objects;
|
|
15
|
+
|
|
16
|
+
@ReactModuleList(nativeModules = {WorkletsModule.class})
|
|
17
|
+
public class WorkletsPackage extends BaseReactPackage implements ReactPackage {
|
|
18
|
+
@Override
|
|
19
|
+
public NativeModule getModule(
|
|
20
|
+
@NonNull String name, @NonNull ReactApplicationContext reactContext) {
|
|
21
|
+
return name.equals(WorkletsModule.NAME) ? new WorkletsModule(reactContext) : null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@SuppressWarnings({"rawtypes, unchecked"})
|
|
25
|
+
@NonNull
|
|
26
|
+
@Override
|
|
27
|
+
public ReactModuleInfoProvider getReactModuleInfoProvider() {
|
|
28
|
+
Class[] moduleList = new Class[] {WorkletsModule.class};
|
|
29
|
+
|
|
30
|
+
final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
|
|
31
|
+
for (Class<? extends NativeModule> moduleClass : moduleList) {
|
|
32
|
+
ReactModule reactModule =
|
|
33
|
+
Objects.requireNonNull(moduleClass.getAnnotation(ReactModule.class));
|
|
34
|
+
|
|
35
|
+
reactModuleInfoMap.put(
|
|
36
|
+
reactModule.name(),
|
|
37
|
+
new ReactModuleInfo(
|
|
38
|
+
reactModule.name(),
|
|
39
|
+
moduleClass.getName(),
|
|
40
|
+
reactModule.canOverrideExistingModule(),
|
|
41
|
+
reactModule.needsEagerInit(),
|
|
42
|
+
reactModule.isCxxModule(),
|
|
43
|
+
true));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return () -> reactModuleInfoMap;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
package com.swmansion.worklets.runloop;
|
|
2
|
+
|
|
3
|
+
import com.facebook.jni.HybridData;
|
|
4
|
+
import com.facebook.proguard.annotations.DoNotStrip;
|
|
5
|
+
|
|
6
|
+
@SuppressWarnings("JavaJniMissingFunction")
|
|
7
|
+
public class AnimationFrameCallback {
|
|
8
|
+
|
|
9
|
+
@DoNotStrip
|
|
10
|
+
@SuppressWarnings({"FieldCanBeLocal", "unused"})
|
|
11
|
+
private final HybridData mHybridData;
|
|
12
|
+
|
|
13
|
+
@DoNotStrip
|
|
14
|
+
private AnimationFrameCallback(HybridData hybridData) {
|
|
15
|
+
mHybridData = hybridData;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public native void onAnimationFrame(double timestampMs);
|
|
19
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
package com.swmansion.worklets.runloop;
|
|
2
|
+
|
|
3
|
+
import android.os.SystemClock;
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
5
|
+
import com.facebook.react.modules.core.ReactChoreographer;
|
|
6
|
+
import com.facebook.react.uimanager.GuardedFrameCallback;
|
|
7
|
+
import java.util.ArrayList;
|
|
8
|
+
import java.util.List;
|
|
9
|
+
import java.util.concurrent.atomic.AtomicBoolean;
|
|
10
|
+
|
|
11
|
+
public class AnimationFrameQueue {
|
|
12
|
+
|
|
13
|
+
private Long mFirstUptime = SystemClock.uptimeMillis();
|
|
14
|
+
private boolean mSlowAnimationsEnabled = false;
|
|
15
|
+
private double lastFrameTimeMs;
|
|
16
|
+
private int mAnimationsDragFactor = 1;
|
|
17
|
+
|
|
18
|
+
/// ReactChoreographer is
|
|
19
|
+
/// <a
|
|
20
|
+
// href="https://github.com/facebook/react-native/blob/main/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/ReactChoreographer.kt#L21">thread safe</a>.
|
|
21
|
+
///
|
|
22
|
+
private final ReactChoreographer mReactChoreographer = ReactChoreographer.getInstance();
|
|
23
|
+
private final GuardedFrameCallback mChoreographerCallback;
|
|
24
|
+
private final AtomicBoolean mCallbackPosted = new AtomicBoolean();
|
|
25
|
+
private final AtomicBoolean mPaused = new AtomicBoolean();
|
|
26
|
+
private final List<AnimationFrameCallback> mFrameCallbacks = new ArrayList<>();
|
|
27
|
+
|
|
28
|
+
public AnimationFrameQueue(ReactApplicationContext reactApplicationContext) {
|
|
29
|
+
mChoreographerCallback =
|
|
30
|
+
new GuardedFrameCallback(reactApplicationContext) {
|
|
31
|
+
@Override
|
|
32
|
+
protected void doFrameGuarded(long frameTimeNanos) {
|
|
33
|
+
executeQueue(frameTimeNanos);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public void resume() {
|
|
39
|
+
if (mPaused.getAndSet(false)) {
|
|
40
|
+
scheduleQueueExecution();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public void pause() {
|
|
45
|
+
synchronized (mPaused) {
|
|
46
|
+
if (!mPaused.getAndSet(true) && mCallbackPosted.getAndSet(false)) {
|
|
47
|
+
mReactChoreographer.removeFrameCallback(
|
|
48
|
+
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mChoreographerCallback);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public void requestAnimationFrame(AnimationFrameCallback animationFrameCallback) {
|
|
54
|
+
synchronized (mFrameCallbacks) {
|
|
55
|
+
mFrameCallbacks.add(animationFrameCallback);
|
|
56
|
+
}
|
|
57
|
+
scheduleQueueExecution();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public void enableSlowAnimations(boolean slowAnimationsEnabled, int animationsDragFactor) {
|
|
61
|
+
mSlowAnimationsEnabled = slowAnimationsEnabled;
|
|
62
|
+
mAnimationsDragFactor = animationsDragFactor;
|
|
63
|
+
if (slowAnimationsEnabled) {
|
|
64
|
+
mFirstUptime = SystemClock.uptimeMillis();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private void scheduleQueueExecution() {
|
|
69
|
+
synchronized (mPaused) {
|
|
70
|
+
if (!mPaused.get() && !mCallbackPosted.getAndSet(true)) {
|
|
71
|
+
mReactChoreographer.postFrameCallback(
|
|
72
|
+
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mChoreographerCallback);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private void executeQueue(long frameTimeNanos) {
|
|
78
|
+
double currentFrameTimeMs = calculateTimestamp(frameTimeNanos);
|
|
79
|
+
if (currentFrameTimeMs <= lastFrameTimeMs) {
|
|
80
|
+
// It is possible for ChoreographerCallback to be executed twice within the same frame
|
|
81
|
+
// due to frame drops. If this occurs, the additional callback execution should be ignored.
|
|
82
|
+
mCallbackPosted.set(false);
|
|
83
|
+
scheduleQueueExecution();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
var frameCallbacks = pullCallbacks();
|
|
88
|
+
mCallbackPosted.set(false);
|
|
89
|
+
|
|
90
|
+
lastFrameTimeMs = currentFrameTimeMs;
|
|
91
|
+
for (var callback : frameCallbacks) {
|
|
92
|
+
callback.onAnimationFrame(currentFrameTimeMs);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private List<AnimationFrameCallback> pullCallbacks() {
|
|
97
|
+
synchronized (mFrameCallbacks) {
|
|
98
|
+
List<AnimationFrameCallback> frameCallbacks = new ArrayList<>(mFrameCallbacks);
|
|
99
|
+
mFrameCallbacks.clear();
|
|
100
|
+
return frameCallbacks;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private double calculateTimestamp(long frameTimeNanos) {
|
|
105
|
+
final double NANOSECONDS_IN_MILLISECONDS = 1000000;
|
|
106
|
+
double currentFrameTimeMs = frameTimeNanos / NANOSECONDS_IN_MILLISECONDS;
|
|
107
|
+
if (mSlowAnimationsEnabled) {
|
|
108
|
+
currentFrameTimeMs =
|
|
109
|
+
mFirstUptime + (currentFrameTimeMs - mFirstUptime) / mAnimationsDragFactor;
|
|
110
|
+
}
|
|
111
|
+
return currentFrameTimeMs;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#if __cplusplus
|
|
2
|
+
|
|
3
|
+
#import <worklets/apple/WorkletsDisplayLink.h>
|
|
4
|
+
#import <functional>
|
|
5
|
+
|
|
6
|
+
@interface AnimationFrameQueue : NSObject
|
|
7
|
+
|
|
8
|
+
- (void)requestAnimationFrame:(std::function<void(double)>)callback;
|
|
9
|
+
- (void)executeQueue:(WorkletsDisplayLink *)displayLink;
|
|
10
|
+
|
|
11
|
+
- (void)invalidate;
|
|
12
|
+
|
|
13
|
+
@end
|
|
14
|
+
|
|
15
|
+
#endif // __cplusplus
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#import <worklets/Tools/FeatureFlags.h>
|
|
2
|
+
#import <worklets/apple/AnimationFrameQueue.h>
|
|
3
|
+
#import <worklets/apple/AssertJavaScriptQueue.h>
|
|
4
|
+
#import <worklets/apple/AssertTurboModuleManagerQueue.h>
|
|
5
|
+
#import <worklets/apple/SlowAnimations.h>
|
|
6
|
+
#import <chrono>
|
|
7
|
+
|
|
8
|
+
#import <React/RCTAssert.h>
|
|
9
|
+
|
|
10
|
+
constexpr auto TIME_SAMPLES_AMOUNT = 4;
|
|
11
|
+
|
|
12
|
+
namespace FrameRateRange {
|
|
13
|
+
const auto BEST = CAFrameRateRangeMake(60, 120, 120);
|
|
14
|
+
const auto STANDARD = CAFrameRateRangeMake(30, 60, 60);
|
|
15
|
+
const auto LOW = CAFrameRateRangeMake(24, 30, 30);
|
|
16
|
+
const auto POOR = CAFrameRateRangeMake(10, 24, 24);
|
|
17
|
+
} // namespace FrameRateRange
|
|
18
|
+
|
|
19
|
+
@implementation AnimationFrameQueue {
|
|
20
|
+
/* DisplayLink is thread safe. */
|
|
21
|
+
WorkletsDisplayLink *displayLink_;
|
|
22
|
+
std::vector<std::function<void(double)>> frameCallbacks_;
|
|
23
|
+
std::mutex callbacksMutex_;
|
|
24
|
+
std::chrono::duration<double, std::milli> timeDeltas_[TIME_SAMPLES_AMOUNT];
|
|
25
|
+
int timeDeltaIndex_;
|
|
26
|
+
CAFrameRateRange currentFrameRate_;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
typedef void (^AnimationFrameCallback)(WorkletsDisplayLink *displayLink);
|
|
30
|
+
|
|
31
|
+
#pragma mark-- public
|
|
32
|
+
|
|
33
|
+
- (instancetype)init
|
|
34
|
+
{
|
|
35
|
+
AssertJavaScriptQueue();
|
|
36
|
+
if constexpr (worklets::StaticFeatureFlags::getFlag("IOS_DYNAMIC_FRAMERATE_ENABLED")) {
|
|
37
|
+
bool supportsProMotion = [UIScreen mainScreen].maximumFramesPerSecond > 60;
|
|
38
|
+
SEL frameCallback = supportsProMotion ? @selector(executeQueueForProMotion:) : @selector(executeQueue:);
|
|
39
|
+
currentFrameRate_ = supportsProMotion ? FrameRateRange::BEST : FrameRateRange::STANDARD;
|
|
40
|
+
displayLink_ = [WorkletsDisplayLink displayLinkWithTarget:self selector:frameCallback];
|
|
41
|
+
} else {
|
|
42
|
+
displayLink_ = [WorkletsDisplayLink displayLinkWithTarget:self selector:@selector(executeQueue:)];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
#if TARGET_OS_OSX
|
|
46
|
+
// nothing
|
|
47
|
+
#else // TARGET_OS_OSX
|
|
48
|
+
displayLink_.preferredFramesPerSecond = 120; // will fallback to 60 fps for devices without Pro Motion display
|
|
49
|
+
#endif // TARGET_OS_OSX
|
|
50
|
+
[displayLink_ setPaused:TRUE];
|
|
51
|
+
[displayLink_ addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
|
52
|
+
return self;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
- (void)requestAnimationFrame:(std::function<void(double)>)callback
|
|
56
|
+
{
|
|
57
|
+
{
|
|
58
|
+
std::lock_guard<std::mutex> lock(callbacksMutex_);
|
|
59
|
+
frameCallbacks_.push_back(callback);
|
|
60
|
+
}
|
|
61
|
+
[self scheduleQueueExecution];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
- (void)invalidate
|
|
65
|
+
{
|
|
66
|
+
AssertTurboModuleManagerQueue();
|
|
67
|
+
[displayLink_ invalidate];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
#pragma mark-- private
|
|
71
|
+
|
|
72
|
+
- (void)scheduleQueueExecution
|
|
73
|
+
{
|
|
74
|
+
[displayLink_ setPaused:FALSE];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
- (void)executeQueue:(WorkletsDisplayLink *)displayLink
|
|
78
|
+
{
|
|
79
|
+
RCTAssertMainQueue();
|
|
80
|
+
|
|
81
|
+
auto frameCallbacks = [self pullCallbacks];
|
|
82
|
+
[displayLink_ setPaused:TRUE];
|
|
83
|
+
|
|
84
|
+
#if TARGET_OS_OSX
|
|
85
|
+
auto targetTimestamp = displayLink.timestamp + displayLink.duration;
|
|
86
|
+
#else // TARGET_OS_OSX
|
|
87
|
+
auto targetTimestamp = displayLink.targetTimestamp;
|
|
88
|
+
#endif // TARGET_OS_OSX
|
|
89
|
+
targetTimestamp = worklets::calculateTimestampWithSlowAnimations(targetTimestamp);
|
|
90
|
+
for (const auto &callback : frameCallbacks) {
|
|
91
|
+
callback(targetTimestamp);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
- (void)executeQueueForProMotion:(WorkletsDisplayLink *)displayLink
|
|
96
|
+
{
|
|
97
|
+
auto start = std::chrono::high_resolution_clock::now();
|
|
98
|
+
|
|
99
|
+
[self executeQueue:displayLink];
|
|
100
|
+
|
|
101
|
+
timeDeltaIndex_ = (timeDeltaIndex_ + 1) % TIME_SAMPLES_AMOUNT;
|
|
102
|
+
timeDeltas_[timeDeltaIndex_] = std::chrono::high_resolution_clock::now() - start;
|
|
103
|
+
if (timeDeltaIndex_ == TIME_SAMPLES_AMOUNT) {
|
|
104
|
+
// Perform this on every TIME_SAMPLES_AMOUNT-nth frame instead of each one
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
float averageComputationTime = 0;
|
|
108
|
+
for (int i = 0; i < TIME_SAMPLES_AMOUNT; i++) {
|
|
109
|
+
averageComputationTime += timeDeltas_[i].count();
|
|
110
|
+
}
|
|
111
|
+
averageComputationTime = averageComputationTime / TIME_SAMPLES_AMOUNT;
|
|
112
|
+
CAFrameRateRange frameRateRange;
|
|
113
|
+
if (averageComputationTime < 8) {
|
|
114
|
+
frameRateRange = FrameRateRange::BEST;
|
|
115
|
+
} else if (averageComputationTime < 16) {
|
|
116
|
+
frameRateRange = FrameRateRange::STANDARD;
|
|
117
|
+
} else if (averageComputationTime < 33) {
|
|
118
|
+
frameRateRange = FrameRateRange::LOW;
|
|
119
|
+
} else {
|
|
120
|
+
frameRateRange = FrameRateRange::POOR;
|
|
121
|
+
}
|
|
122
|
+
if (currentFrameRate_.preferred != frameRateRange.preferred) {
|
|
123
|
+
displayLink_.preferredFrameRateRange = frameRateRange;
|
|
124
|
+
currentFrameRate_ = frameRateRange;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
- (std::vector<std::function<void(double)>>)pullCallbacks
|
|
129
|
+
{
|
|
130
|
+
RCTAssertMainQueue();
|
|
131
|
+
std::lock_guard<std::mutex> lock(callbacksMutex_);
|
|
132
|
+
return std::move(frameCallbacks_);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#import <react/debug/react_native_assert.h>
|
|
2
|
+
|
|
3
|
+
// Copied from RCTJSThreadManager.mm
|
|
4
|
+
static NSString *const RCTJSThreadName = @"com.facebook.react.runtime.JavaScript";
|
|
5
|
+
|
|
6
|
+
static BOOL IsJavaScriptQueue()
|
|
7
|
+
{
|
|
8
|
+
return [NSThread.currentThread.name isEqualToString:RCTJSThreadName];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static void AssertJavaScriptQueue()
|
|
12
|
+
{
|
|
13
|
+
react_native_assert(IsJavaScriptQueue() && "This function must be called on the JavaScript queue");
|
|
14
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#import <react/debug/react_native_assert.h>
|
|
2
|
+
|
|
3
|
+
constexpr auto turboModuleManagerQueueLabel =
|
|
4
|
+
"com.meta.react.turbomodulemanager.queue";
|
|
5
|
+
|
|
6
|
+
static bool IsTurboModuleManagerQueue() {
|
|
7
|
+
const auto currentQueueLabel =
|
|
8
|
+
dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL);
|
|
9
|
+
return strcmp(currentQueueLabel, turboModuleManagerQueueLabel) == 0;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static void AssertTurboModuleManagerQueue() {
|
|
13
|
+
react_native_assert(
|
|
14
|
+
IsTurboModuleManagerQueue() &&
|
|
15
|
+
"This function must be called on the TurboModuleManager queue");
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#import <worklets/Tools/UIScheduler.h>
|
|
2
|
+
|
|
3
|
+
namespace worklets {
|
|
4
|
+
|
|
5
|
+
using namespace facebook;
|
|
6
|
+
using namespace react;
|
|
7
|
+
using namespace worklets;
|
|
8
|
+
|
|
9
|
+
class IOSUIScheduler : public UIScheduler,
|
|
10
|
+
public std::enable_shared_from_this<IOSUIScheduler> {
|
|
11
|
+
public:
|
|
12
|
+
void scheduleOnUI(std::function<void()> job) override;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
} // namespace worklets
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#import <worklets/apple/IOSUIScheduler.h>
|
|
2
|
+
|
|
3
|
+
namespace worklets {
|
|
4
|
+
|
|
5
|
+
using namespace facebook;
|
|
6
|
+
using namespace react;
|
|
7
|
+
|
|
8
|
+
void IOSUIScheduler::scheduleOnUI(std::function<void()> job)
|
|
9
|
+
{
|
|
10
|
+
if ([NSThread isMainThread]) {
|
|
11
|
+
job();
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
UIScheduler::scheduleOnUI(job);
|
|
16
|
+
|
|
17
|
+
if (!scheduledOnUI_) {
|
|
18
|
+
dispatch_async(dispatch_get_main_queue(), [weakThis = weak_from_this()] {
|
|
19
|
+
// Before triggering the UI, we check if the weak pointer is still valid to avoid possible dangling pointer
|
|
20
|
+
// issues, because when this async callback here gets executed, the original `IOSUIScheduler` object may have been
|
|
21
|
+
// destroyed.
|
|
22
|
+
if (auto strongThis = weakThis.lock()) {
|
|
23
|
+
strongThis->triggerUI();
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
} // namespace worklets
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
#import <worklets/Tools/PlatformLogger.h>
|
|
3
|
+
|
|
4
|
+
namespace worklets {
|
|
5
|
+
|
|
6
|
+
void PlatformLogger::log(const char *str)
|
|
7
|
+
{
|
|
8
|
+
NSLog(@"%@", [NSString stringWithCString:str encoding:[NSString defaultCStringEncoding]]);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
void PlatformLogger::log(const std::string &str)
|
|
12
|
+
{
|
|
13
|
+
log(str.c_str());
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
void PlatformLogger::log(const double d)
|
|
17
|
+
{
|
|
18
|
+
NSLog(@"%lf", d);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
void PlatformLogger::log(const int i)
|
|
22
|
+
{
|
|
23
|
+
NSLog(@"%i", i);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void PlatformLogger::log(const bool b)
|
|
27
|
+
{
|
|
28
|
+
log(b ? "true" : "false");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
} // namespace worklets
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#import <QuartzCore/QuartzCore.h>
|
|
2
|
+
|
|
3
|
+
#import <worklets/apple/SlowAnimations.h>
|
|
4
|
+
|
|
5
|
+
#if TARGET_IPHONE_SIMULATOR
|
|
6
|
+
#import <dlfcn.h>
|
|
7
|
+
#endif
|
|
8
|
+
|
|
9
|
+
namespace worklets {
|
|
10
|
+
|
|
11
|
+
CGFloat getUIAnimationDragCoefficient(void)
|
|
12
|
+
{
|
|
13
|
+
static float (*UIAnimationDragCoefficient)(void) = NULL;
|
|
14
|
+
#if TARGET_IPHONE_SIMULATOR
|
|
15
|
+
static dispatch_once_t onceToken;
|
|
16
|
+
dispatch_once(&onceToken, ^{
|
|
17
|
+
UIAnimationDragCoefficient = (float (*)(void))dlsym(RTLD_DEFAULT, "UIAnimationDragCoefficient");
|
|
18
|
+
});
|
|
19
|
+
#endif
|
|
20
|
+
return UIAnimationDragCoefficient ? UIAnimationDragCoefficient() : 1.f;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
CFTimeInterval calculateTimestampWithSlowAnimations(CFTimeInterval currentTimestamp)
|
|
24
|
+
{
|
|
25
|
+
static const auto MILLISECONDS_IN_SECOND = 1000;
|
|
26
|
+
#if TARGET_IPHONE_SIMULATOR
|
|
27
|
+
static CFTimeInterval dragCoefChangedTimestamp = CACurrentMediaTime();
|
|
28
|
+
static CGFloat previousDragCoef = getUIAnimationDragCoefficient();
|
|
29
|
+
|
|
30
|
+
const CGFloat dragCoef = getUIAnimationDragCoefficient();
|
|
31
|
+
if (previousDragCoef != dragCoef) {
|
|
32
|
+
previousDragCoef = dragCoef;
|
|
33
|
+
dragCoefChangedTimestamp = CACurrentMediaTime();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const bool areSlowAnimationsEnabled = dragCoef != 1.f;
|
|
37
|
+
if (areSlowAnimationsEnabled) {
|
|
38
|
+
currentTimestamp = (dragCoefChangedTimestamp + (currentTimestamp - dragCoefChangedTimestamp) / dragCoef);
|
|
39
|
+
}
|
|
40
|
+
#endif // TARGET_IPHONE_SIMULATOR
|
|
41
|
+
currentTimestamp *= MILLISECONDS_IN_SECOND;
|
|
42
|
+
return currentTimestamp;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
} // namespace worklets
|