From d1fce78bc9de17390621fb12b20293e284a88413 Mon Sep 17 00:00:00 2001 From: Krzysztof Piaskowy Date: Mon, 25 Nov 2024 09:16:02 +0100 Subject: [PATCH 1/9] PoC --- .../NativeModules/NativeWorkletsModule.cpp | 5 ++-- .../NativeModules/NativeWorkletsModule.h | 3 +- .../NativeWorkletsModuleSpec.cpp | 2 +- .../NativeModules/NativeWorkletsModuleSpec.h | 3 +- .../cpp/worklets/SharedItems/Shareables.cpp | 29 +++++++++++++++++-- .../cpp/worklets/SharedItems/Shareables.h | 14 ++++++++- .../WorkletRuntimeDecorator.cpp | 2 +- .../src/animation/timing.ts | 1 + .../react-native-reanimated/src/shareables.ts | 12 ++++++-- .../worklets/WorkletsModule/NativeWorklets.ts | 6 ++-- 10 files changed, 63 insertions(+), 14 deletions(-) diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp index 80270752948..7a17d225dd8 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp @@ -28,11 +28,12 @@ jsi::Value NativeWorkletsModule::makeShareableClone( jsi::Runtime &rt, const jsi::Value &value, const jsi::Value &shouldRetainRemote, - const jsi::Value &nativeStateSource) { + const jsi::Value &nativeStateSource, + const jsi::Value &staticFunction) { // TODO: It might be a good idea to rename one of these methods to avoid // confusion. return worklets::makeShareableClone( - rt, value, shouldRetainRemote, nativeStateSource); + rt, value, shouldRetainRemote, nativeStateSource, staticFunction); } } // namespace worklets diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h index 5912056fb16..c40a17237c5 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h @@ -17,7 +17,8 @@ class NativeWorkletsModule : public NativeWorkletsModuleSpec { jsi::Runtime &rt, const jsi::Value &value, const jsi::Value &shouldRetainRemote, - const jsi::Value &nativeStateSource) override; + const jsi::Value &nativeStateSource, + const jsi::Value &staticFunction) override; [[nodiscard]] inline std::string getValueUnpackerCode() const { return valueUnpackerCode_; diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp index 95f05ac8036..585f2352318 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp @@ -14,7 +14,7 @@ static jsi::Value WORKLETS_SPEC_PREFIX(makeShareableClone)( size_t) { return static_cast(&turboModule) ->makeShareableClone( - rt, std::move(args[0]), std::move(args[1]), std::move(args[2])); + rt, std::move(args[0]), std::move(args[1]), std::move(args[2]), std::move(args[3])); } NativeWorkletsModuleSpec::NativeWorkletsModuleSpec( diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h index 1c1d622e17c..baedfdd2520 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h @@ -19,7 +19,8 @@ class JSI_EXPORT NativeWorkletsModuleSpec : public TurboModule { jsi::Runtime &rt, const jsi::Value &value, const jsi::Value &shouldRetainRemote, - const jsi::Value &nativeStateSource) = 0; + const jsi::Value &nativeStateSource, + const jsi::Value &staticFunction) = 0; }; } // namespace worklets diff --git a/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp b/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp index 525cd114ebb..bea0e185569 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp @@ -42,12 +42,17 @@ jsi::Value makeShareableClone( jsi::Runtime &rt, const jsi::Value &value, const jsi::Value &shouldRetainRemote, - const jsi::Value &nativeStateSource) { + const jsi::Value &nativeStateSource, + const jsi::Value &staticFunction) { std::shared_ptr shareable; if (value.isObject()) { auto object = value.asObject(rt); if (!object.getProperty(rt, "__workletHash").isUndefined()) { - shareable = std::make_shared(rt, object); + if (staticFunction.getBool()) { + shareable = std::make_shared(rt, object); + } else { + shareable = std::make_shared(rt, object); + } } else if (!object.getProperty(rt, "__init").isUndefined()) { shareable = std::make_shared(rt, object); } else if (object.isFunction(rt)) { @@ -213,8 +218,9 @@ ShareableObject::ShareableObject( nativeState_ = nativeStateSource.asObject(rt).getNativeState(rt); } } - +static int counter = 0; jsi::Value ShareableObject::toJSValue(jsi::Runtime &rt) { + counter++; auto obj = jsi::Object(rt); for (size_t i = 0, size = data_.size(); i < size; i++) { obj.setProperty( @@ -249,6 +255,23 @@ jsi::Value ShareableWorklet::toJSValue(jsi::Runtime &rt) { rt, obj, jsi::String::createFromAscii(rt, "Worklet")); } +jsi::Value ShareableStaticWorklet::toJSValue(jsi::Runtime &rt) { + assert( + std::any_of( + data_.cbegin(), + data_.cend(), + [](const auto &item) { return item.first == "__workletHash"; }) && + "ShareableWorklet doesn't have `__workletHash` property"); + if (jsValue_.get()) { + return jsValue_.get(); + } + jsi::Value obj = ShareableObject::toJSValue(rt); + auto jsValue = getValueUnpacker(rt).call( + rt, obj, jsi::String::createFromAscii(rt, "Worklet")); + jsValue_ = std::make_shared(std::move(jsValue)); + return jsValue; +} + jsi::Value ShareableRemoteFunction::toJSValue(jsi::Runtime &rt) { if (&rt == runtime_) { return jsi::Value(rt, *function_); diff --git a/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.h b/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.h index 62312d77330..a66a3b09824 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.h @@ -143,7 +143,8 @@ jsi::Value makeShareableClone( jsi::Runtime &rt, const jsi::Value &value, const jsi::Value &shouldRetainRemote, - const jsi::Value &nativeStateSource); + const jsi::Value &nativeStateSource, + const jsi::Value &staticFunction); std::shared_ptr extractShareableOrThrow( jsi::Runtime &rt, @@ -246,6 +247,17 @@ class ShareableWorklet : public ShareableObject { jsi::Value toJSValue(jsi::Runtime &rt) override; }; +class ShareableStaticWorklet : public ShareableObject { + public: + ShareableStaticWorklet(jsi::Runtime &rt, const jsi::Object &worklet) + : ShareableObject(rt, worklet) { + valueType_ = WorkletType; + } + + jsi::Value toJSValue(jsi::Runtime &rt) override; + std::shared_ptr jsValue_; +}; + class ShareableRemoteFunction : public Shareable, public std::enable_shared_from_this { diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp b/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp index 07caee39767..a19de3b564c 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp @@ -89,7 +89,7 @@ void WorkletRuntimeDecorator::decorate( const jsi::Value &nativeStateSource) { auto shouldRetainRemote = jsi::Value::undefined(); return makeShareableClone( - rt, value, shouldRetainRemote, nativeStateSource); + rt, value, shouldRetainRemote, nativeStateSource, false); }); jsi_utils::installJsiFunction( diff --git a/packages/react-native-reanimated/src/animation/timing.ts b/packages/react-native-reanimated/src/animation/timing.ts index 48fe9cf03d6..48476990513 100644 --- a/packages/react-native-reanimated/src/animation/timing.ts +++ b/packages/react-native-reanimated/src/animation/timing.ts @@ -157,3 +157,4 @@ export const withTiming = function ( } as TimingAnimation; }); } as withTimingType; +// withTiming.staticFn = true; diff --git a/packages/react-native-reanimated/src/shareables.ts b/packages/react-native-reanimated/src/shareables.ts index 23070fe7de9..42e71627a6c 100644 --- a/packages/react-native-reanimated/src/shareables.ts +++ b/packages/react-native-reanimated/src/shareables.ts @@ -128,6 +128,7 @@ export function makeShareableCloneRecursive( const type = typeof value; const isTypeObject = type === 'object'; const isTypeFunction = type === 'function'; + let isStaticFunction = false; if ((isTypeObject || isTypeFunction) && value !== null) { const cached = shareableMappingCache.get(value); if (cached === shareableMappingFlag) { @@ -166,6 +167,11 @@ export function makeShareableCloneRecursive( } else if (isPlainJSObject(value) || isTypeFunction) { toAdapt = {}; if (isWorkletFunction(value)) { + if (value.staticFn) { + console.log('value', value); + isStaticFunction = true; + } + // console.log('value', value); if (__DEV__) { const babelVersion = value.__initData.version; if (babelVersion !== undefined && babelVersion !== jsVersion) { @@ -276,7 +282,8 @@ Offending code was: \`${getWorkletCode(value)}\``); const adapted = WorkletsModule.makeShareableClone( toAdapt, shouldPersistRemote, - value + value, + isStaticFunction ); shareableMappingCache.set(value, adapted); shareableMappingCache.set(adapted); @@ -286,7 +293,8 @@ Offending code was: \`${getWorkletCode(value)}\``); return WorkletsModule.makeShareableClone( value, shouldPersistRemote, - undefined + undefined, + false ); } diff --git a/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts b/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts index e305d6f164d..12810dc64cc 100644 --- a/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts +++ b/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts @@ -29,12 +29,14 @@ See https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooti makeShareableClone( value: T, shouldPersistRemote: boolean, - nativeStateSource?: object + nativeStateSource?: object, + staticFunction: boolean = false ) { return this.#workletsModuleProxy.makeShareableClone( value, shouldPersistRemote, - nativeStateSource + nativeStateSource, + staticFunction ); } } From b07366c0eb425719b66b192ef2391d2f91c20c65 Mon Sep 17 00:00:00 2001 From: Krzysztof Piaskowy Date: Mon, 25 Nov 2024 12:23:55 +0100 Subject: [PATCH 2/9] Use retain value --- .../NativeModules/NativeWorkletsModule.cpp | 5 +- .../NativeModules/NativeWorkletsModule.h | 3 +- .../NativeWorkletsModuleSpec.cpp | 2 +- .../NativeModules/NativeWorkletsModuleSpec.h | 3 +- .../cpp/worklets/SharedItems/Shareables.cpp | 24 +-- .../cpp/worklets/SharedItems/Shareables.h | 14 +- .../WorkletRuntimeDecorator.cpp | 2 +- .../src/animation/commonTypes.ts | 4 + .../src/animation/timing.ts | 172 ++++++++++-------- .../src/commonTypes.ts | 5 +- .../react-native-reanimated/src/shareables.ts | 16 +- .../worklets/WorkletsModule/NativeWorklets.ts | 6 +- 12 files changed, 118 insertions(+), 138 deletions(-) diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp index 7a17d225dd8..80270752948 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp @@ -28,12 +28,11 @@ jsi::Value NativeWorkletsModule::makeShareableClone( jsi::Runtime &rt, const jsi::Value &value, const jsi::Value &shouldRetainRemote, - const jsi::Value &nativeStateSource, - const jsi::Value &staticFunction) { + const jsi::Value &nativeStateSource) { // TODO: It might be a good idea to rename one of these methods to avoid // confusion. return worklets::makeShareableClone( - rt, value, shouldRetainRemote, nativeStateSource, staticFunction); + rt, value, shouldRetainRemote, nativeStateSource); } } // namespace worklets diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h index c40a17237c5..5912056fb16 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h @@ -17,8 +17,7 @@ class NativeWorkletsModule : public NativeWorkletsModuleSpec { jsi::Runtime &rt, const jsi::Value &value, const jsi::Value &shouldRetainRemote, - const jsi::Value &nativeStateSource, - const jsi::Value &staticFunction) override; + const jsi::Value &nativeStateSource) override; [[nodiscard]] inline std::string getValueUnpackerCode() const { return valueUnpackerCode_; diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp index 585f2352318..95f05ac8036 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp @@ -14,7 +14,7 @@ static jsi::Value WORKLETS_SPEC_PREFIX(makeShareableClone)( size_t) { return static_cast(&turboModule) ->makeShareableClone( - rt, std::move(args[0]), std::move(args[1]), std::move(args[2]), std::move(args[3])); + rt, std::move(args[0]), std::move(args[1]), std::move(args[2])); } NativeWorkletsModuleSpec::NativeWorkletsModuleSpec( diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h index baedfdd2520..1c1d622e17c 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h @@ -19,8 +19,7 @@ class JSI_EXPORT NativeWorkletsModuleSpec : public TurboModule { jsi::Runtime &rt, const jsi::Value &value, const jsi::Value &shouldRetainRemote, - const jsi::Value &nativeStateSource, - const jsi::Value &staticFunction) = 0; + const jsi::Value &nativeStateSource) = 0; }; } // namespace worklets diff --git a/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp b/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp index bea0e185569..5924cb5dce6 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp @@ -42,14 +42,13 @@ jsi::Value makeShareableClone( jsi::Runtime &rt, const jsi::Value &value, const jsi::Value &shouldRetainRemote, - const jsi::Value &nativeStateSource, - const jsi::Value &staticFunction) { + const jsi::Value &nativeStateSource) { std::shared_ptr shareable; if (value.isObject()) { auto object = value.asObject(rt); if (!object.getProperty(rt, "__workletHash").isUndefined()) { - if (staticFunction.getBool()) { - shareable = std::make_shared(rt, object); + if (shouldRetainRemote.isBool() && shouldRetainRemote.getBool()) { + shareable = std::make_shared>(rt, object); } else { shareable = std::make_shared(rt, object); } @@ -255,23 +254,6 @@ jsi::Value ShareableWorklet::toJSValue(jsi::Runtime &rt) { rt, obj, jsi::String::createFromAscii(rt, "Worklet")); } -jsi::Value ShareableStaticWorklet::toJSValue(jsi::Runtime &rt) { - assert( - std::any_of( - data_.cbegin(), - data_.cend(), - [](const auto &item) { return item.first == "__workletHash"; }) && - "ShareableWorklet doesn't have `__workletHash` property"); - if (jsValue_.get()) { - return jsValue_.get(); - } - jsi::Value obj = ShareableObject::toJSValue(rt); - auto jsValue = getValueUnpacker(rt).call( - rt, obj, jsi::String::createFromAscii(rt, "Worklet")); - jsValue_ = std::make_shared(std::move(jsValue)); - return jsValue; -} - jsi::Value ShareableRemoteFunction::toJSValue(jsi::Runtime &rt) { if (&rt == runtime_) { return jsi::Value(rt, *function_); diff --git a/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.h b/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.h index a66a3b09824..62312d77330 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.h @@ -143,8 +143,7 @@ jsi::Value makeShareableClone( jsi::Runtime &rt, const jsi::Value &value, const jsi::Value &shouldRetainRemote, - const jsi::Value &nativeStateSource, - const jsi::Value &staticFunction); + const jsi::Value &nativeStateSource); std::shared_ptr extractShareableOrThrow( jsi::Runtime &rt, @@ -247,17 +246,6 @@ class ShareableWorklet : public ShareableObject { jsi::Value toJSValue(jsi::Runtime &rt) override; }; -class ShareableStaticWorklet : public ShareableObject { - public: - ShareableStaticWorklet(jsi::Runtime &rt, const jsi::Object &worklet) - : ShareableObject(rt, worklet) { - valueType_ = WorkletType; - } - - jsi::Value toJSValue(jsi::Runtime &rt) override; - std::shared_ptr jsValue_; -}; - class ShareableRemoteFunction : public Shareable, public std::enable_shared_from_this { diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp b/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp index a19de3b564c..07caee39767 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp @@ -89,7 +89,7 @@ void WorkletRuntimeDecorator::decorate( const jsi::Value &nativeStateSource) { auto shouldRetainRemote = jsi::Value::undefined(); return makeShareableClone( - rt, value, shouldRetainRemote, nativeStateSource, false); + rt, value, shouldRetainRemote, nativeStateSource); }); jsi_utils::installJsiFunction( diff --git a/packages/react-native-reanimated/src/animation/commonTypes.ts b/packages/react-native-reanimated/src/animation/commonTypes.ts index 064f6b837e5..c8ebf2d03e6 100644 --- a/packages/react-native-reanimated/src/animation/commonTypes.ts +++ b/packages/react-native-reanimated/src/animation/commonTypes.ts @@ -57,3 +57,7 @@ export interface StyleLayoutAnimation extends HigherOrderAnimation { ) => void; callback?: AnimationCallback; } + +export interface CacheableWorklet { + cacheable?: boolean; +} diff --git a/packages/react-native-reanimated/src/animation/timing.ts b/packages/react-native-reanimated/src/animation/timing.ts index 48476990513..fd77480eb65 100644 --- a/packages/react-native-reanimated/src/animation/timing.ts +++ b/packages/react-native-reanimated/src/animation/timing.ts @@ -14,6 +14,7 @@ import type { ReduceMotion, EasingFunction, } from '../commonTypes'; +import type { CacheableWorklet } from './commonTypes'; /** * The timing animation configuration. @@ -70,91 +71,102 @@ type withTimingType = ( * which holds the current state of the animation. * @see https://docs.swmansion.com/react-native-reanimated/docs/animations/withTiming */ -export const withTiming = function ( - toValue: AnimatableValue, - userConfig?: TimingConfig, - callback?: AnimationCallback -): Animation { - 'worklet'; - - if (__DEV__ && userConfig?.easing) { - assertEasingIsWorklet(userConfig.easing); - } - - return defineAnimation(toValue, () => { +export const withTiming = ( + function ( + toValue: AnimatableValue, + userConfig?: TimingConfig, + callback?: AnimationCallback + ): Animation { 'worklet'; - const config: Required> = { - duration: 300, - easing: Easing.inOut(Easing.quad), - }; - if (userConfig) { - Object.keys(userConfig).forEach( - (key) => - ((config as any)[key] = userConfig[key as keyof typeof userConfig]) - ); - } - function timing(animation: InnerTimingAnimation, now: Timestamp): boolean { - // eslint-disable-next-line @typescript-eslint/no-shadow - const { toValue, startTime, startValue } = animation; - const runtime = now - startTime; + if (__DEV__ && userConfig?.easing) { + assertEasingIsWorklet(userConfig.easing); + } - if (runtime >= config.duration) { - // reset startTime to avoid reusing finished animation config in `start` method - animation.startTime = 0; - animation.current = toValue; - return true; + return defineAnimation(toValue, () => { + 'worklet'; + const config: Required> = { + duration: 300, + easing: Easing.inOut(Easing.quad), + }; + if (userConfig) { + Object.keys(userConfig).forEach( + (key) => + ((config as any)[key] = userConfig[key as keyof typeof userConfig]) + ); } - const progress = animation.easing(runtime / config.duration); - animation.current = - (startValue as number) + (toValue - (startValue as number)) * progress; - return false; - } - function onStart( - animation: TimingAnimation, - value: number, - now: Timestamp, - previousAnimation: Animation - ): void { - if ( - previousAnimation && - (previousAnimation as TimingAnimation).type === 'timing' && - (previousAnimation as TimingAnimation).toValue === toValue && - (previousAnimation as TimingAnimation).startTime - ) { - // to maintain continuity of timing animations we check if we are starting - // new timing over the old one with the same parameters. If so, we want - // to copy animation timeline properties - animation.startTime = (previousAnimation as TimingAnimation).startTime; - animation.startValue = ( - previousAnimation as TimingAnimation - ).startValue; - } else { - animation.startTime = now; - animation.startValue = value; + function timing( + animation: InnerTimingAnimation, + now: Timestamp + ): boolean { + // eslint-disable-next-line @typescript-eslint/no-shadow + const { toValue, startTime, startValue } = animation; + const runtime = now - startTime; + + if (runtime >= config.duration) { + // reset startTime to avoid reusing finished animation config in `start` method + animation.startTime = 0; + animation.current = toValue; + return true; + } + const progress = animation.easing(runtime / config.duration); + animation.current = + (startValue as number) + + (toValue - (startValue as number)) * progress; + return false; } - animation.current = value; - if (typeof config.easing === 'object') { - animation.easing = config.easing.factory(); - } else { - animation.easing = config.easing; + + function onStart( + animation: TimingAnimation, + value: number, + now: Timestamp, + previousAnimation: Animation + ): void { + if ( + previousAnimation && + (previousAnimation as TimingAnimation).type === 'timing' && + (previousAnimation as TimingAnimation).toValue === toValue && + (previousAnimation as TimingAnimation).startTime + ) { + // to maintain continuity of timing animations we check if we are starting + // new timing over the old one with the same parameters. If so, we want + // to copy animation timeline properties + animation.startTime = ( + previousAnimation as TimingAnimation + ).startTime; + animation.startValue = ( + previousAnimation as TimingAnimation + ).startValue; + } else { + animation.startTime = now; + animation.startValue = value; + } + animation.current = value; + if (typeof config.easing === 'object') { + animation.easing = config.easing.factory(); + } else { + animation.easing = config.easing; + } } - } - return { - type: 'timing', - onFrame: timing, - onStart: onStart as (animation: TimingAnimation, now: number) => boolean, - progress: 0, - toValue, - startValue: 0, - startTime: 0, - easing: () => 0, - current: toValue, - callback, - reduceMotion: getReduceMotionForAnimation(userConfig?.reduceMotion), - } as TimingAnimation; - }); -} as withTimingType; -// withTiming.staticFn = true; + return { + type: 'timing', + onFrame: timing, + onStart: onStart as ( + animation: TimingAnimation, + now: number + ) => boolean, + progress: 0, + toValue, + startValue: 0, + startTime: 0, + easing: () => 0, + current: toValue, + callback, + reduceMotion: getReduceMotionForAnimation(userConfig?.reduceMotion), + } as TimingAnimation; + }); + } +); +withTiming.cacheable = true; diff --git a/packages/react-native-reanimated/src/commonTypes.ts b/packages/react-native-reanimated/src/commonTypes.ts index f50717436d8..03bcc703a0b 100644 --- a/packages/react-native-reanimated/src/commonTypes.ts +++ b/packages/react-native-reanimated/src/commonTypes.ts @@ -7,6 +7,7 @@ import type { } from 'react-native'; import type { WorkletsModuleProxy } from './worklets'; import type { ReanimatedModuleProxy } from './ReanimatedModule'; +import type { CacheableWorklet } from './animation/commonTypes'; export interface IWorkletsModule extends WorkletsModuleProxy {} @@ -360,7 +361,9 @@ export function isWorkletFunction< Args extends unknown[] = unknown[], ReturnValue = unknown, BuildType extends WorkletBaseDev | WorkletBaseRelease = WorkletBaseDev, ->(value: unknown): value is WorkletFunction & BuildType { +>( + value: unknown +): value is WorkletFunction & BuildType & CacheableWorklet { 'worklet'; // Since host objects always return true for `in` operator, we have to use dot notation to check if the property exists. // See https://github.com/facebook/hermes/blob/340726ef8cf666a7cce75bc60b02fa56b3e54560/lib/VM/JSObject.cpp#L1276. diff --git a/packages/react-native-reanimated/src/shareables.ts b/packages/react-native-reanimated/src/shareables.ts index 42e71627a6c..3bfb55aa1fc 100644 --- a/packages/react-native-reanimated/src/shareables.ts +++ b/packages/react-native-reanimated/src/shareables.ts @@ -128,7 +128,7 @@ export function makeShareableCloneRecursive( const type = typeof value; const isTypeObject = type === 'object'; const isTypeFunction = type === 'function'; - let isStaticFunction = false; + let isCacheableWorklet = false; if ((isTypeObject || isTypeFunction) && value !== null) { const cached = shareableMappingCache.get(value); if (cached === shareableMappingFlag) { @@ -167,11 +167,9 @@ export function makeShareableCloneRecursive( } else if (isPlainJSObject(value) || isTypeFunction) { toAdapt = {}; if (isWorkletFunction(value)) { - if (value.staticFn) { - console.log('value', value); - isStaticFunction = true; + if (value.cacheable) { + isCacheableWorklet = true; } - // console.log('value', value); if (__DEV__) { const babelVersion = value.__initData.version; if (babelVersion !== undefined && babelVersion !== jsVersion) { @@ -281,9 +279,8 @@ Offending code was: \`${getWorkletCode(value)}\``); } const adapted = WorkletsModule.makeShareableClone( toAdapt, - shouldPersistRemote, - value, - isStaticFunction + shouldPersistRemote || isCacheableWorklet, + value ); shareableMappingCache.set(value, adapted); shareableMappingCache.set(adapted); @@ -293,8 +290,7 @@ Offending code was: \`${getWorkletCode(value)}\``); return WorkletsModule.makeShareableClone( value, shouldPersistRemote, - undefined, - false + undefined ); } diff --git a/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts b/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts index 12810dc64cc..e305d6f164d 100644 --- a/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts +++ b/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts @@ -29,14 +29,12 @@ See https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooti makeShareableClone( value: T, shouldPersistRemote: boolean, - nativeStateSource?: object, - staticFunction: boolean = false + nativeStateSource?: object ) { return this.#workletsModuleProxy.makeShareableClone( value, shouldPersistRemote, - nativeStateSource, - staticFunction + nativeStateSource ); } } From ebd1bb0e7cdd64338941eb6eb5fea78ce42fd28b Mon Sep 17 00:00:00 2001 From: Krzysztof Piaskowy Date: Mon, 25 Nov 2024 12:25:43 +0100 Subject: [PATCH 3/9] Cleanup --- .../Common/cpp/worklets/SharedItems/Shareables.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp b/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp index 5924cb5dce6..17d295c8351 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp @@ -217,9 +217,8 @@ ShareableObject::ShareableObject( nativeState_ = nativeStateSource.asObject(rt).getNativeState(rt); } } -static int counter = 0; + jsi::Value ShareableObject::toJSValue(jsi::Runtime &rt) { - counter++; auto obj = jsi::Object(rt); for (size_t i = 0, size = data_.size(); i < size; i++) { obj.setProperty( From 0efd0c7959acfa27e63dda1d208847af9b1e8dcd Mon Sep 17 00:00:00 2001 From: Krzysztof Piaskowy Date: Mon, 25 Nov 2024 12:29:47 +0100 Subject: [PATCH 4/9] Restore changes --- .../src/animation/timing.ts | 169 ++++++++---------- 1 file changed, 79 insertions(+), 90 deletions(-) diff --git a/packages/react-native-reanimated/src/animation/timing.ts b/packages/react-native-reanimated/src/animation/timing.ts index fd77480eb65..55ea15b5dc0 100644 --- a/packages/react-native-reanimated/src/animation/timing.ts +++ b/packages/react-native-reanimated/src/animation/timing.ts @@ -71,102 +71,91 @@ type withTimingType = ( * which holds the current state of the animation. * @see https://docs.swmansion.com/react-native-reanimated/docs/animations/withTiming */ -export const withTiming = ( - function ( - toValue: AnimatableValue, - userConfig?: TimingConfig, - callback?: AnimationCallback - ): Animation { - 'worklet'; +export const withTiming = function ( + toValue: AnimatableValue, + userConfig?: TimingConfig, + callback?: AnimationCallback +): Animation { + 'worklet'; - if (__DEV__ && userConfig?.easing) { - assertEasingIsWorklet(userConfig.easing); - } + if (__DEV__ && userConfig?.easing) { + assertEasingIsWorklet(userConfig.easing); + } - return defineAnimation(toValue, () => { - 'worklet'; - const config: Required> = { - duration: 300, - easing: Easing.inOut(Easing.quad), - }; - if (userConfig) { - Object.keys(userConfig).forEach( - (key) => - ((config as any)[key] = userConfig[key as keyof typeof userConfig]) - ); - } + return defineAnimation(toValue, () => { + 'worklet'; + const config: Required> = { + duration: 300, + easing: Easing.inOut(Easing.quad), + }; + if (userConfig) { + Object.keys(userConfig).forEach( + (key) => + ((config as any)[key] = userConfig[key as keyof typeof userConfig]) + ); + } - function timing( - animation: InnerTimingAnimation, - now: Timestamp - ): boolean { - // eslint-disable-next-line @typescript-eslint/no-shadow - const { toValue, startTime, startValue } = animation; - const runtime = now - startTime; + function timing(animation: InnerTimingAnimation, now: Timestamp): boolean { + // eslint-disable-next-line @typescript-eslint/no-shadow + const { toValue, startTime, startValue } = animation; + const runtime = now - startTime; - if (runtime >= config.duration) { - // reset startTime to avoid reusing finished animation config in `start` method - animation.startTime = 0; - animation.current = toValue; - return true; - } - const progress = animation.easing(runtime / config.duration); - animation.current = - (startValue as number) + - (toValue - (startValue as number)) * progress; - return false; + if (runtime >= config.duration) { + // reset startTime to avoid reusing finished animation config in `start` method + animation.startTime = 0; + animation.current = toValue; + return true; } + const progress = animation.easing(runtime / config.duration); + animation.current = + (startValue as number) + (toValue - (startValue as number)) * progress; + return false; + } - function onStart( - animation: TimingAnimation, - value: number, - now: Timestamp, - previousAnimation: Animation - ): void { - if ( - previousAnimation && - (previousAnimation as TimingAnimation).type === 'timing' && - (previousAnimation as TimingAnimation).toValue === toValue && - (previousAnimation as TimingAnimation).startTime - ) { - // to maintain continuity of timing animations we check if we are starting - // new timing over the old one with the same parameters. If so, we want - // to copy animation timeline properties - animation.startTime = ( - previousAnimation as TimingAnimation - ).startTime; - animation.startValue = ( - previousAnimation as TimingAnimation - ).startValue; - } else { - animation.startTime = now; - animation.startValue = value; - } - animation.current = value; - if (typeof config.easing === 'object') { - animation.easing = config.easing.factory(); - } else { - animation.easing = config.easing; - } + function onStart( + animation: TimingAnimation, + value: number, + now: Timestamp, + previousAnimation: Animation + ): void { + if ( + previousAnimation && + (previousAnimation as TimingAnimation).type === 'timing' && + (previousAnimation as TimingAnimation).toValue === toValue && + (previousAnimation as TimingAnimation).startTime + ) { + // to maintain continuity of timing animations we check if we are starting + // new timing over the old one with the same parameters. If so, we want + // to copy animation timeline properties + animation.startTime = (previousAnimation as TimingAnimation).startTime; + animation.startValue = ( + previousAnimation as TimingAnimation + ).startValue; + } else { + animation.startTime = now; + animation.startValue = value; } + animation.current = value; + if (typeof config.easing === 'object') { + animation.easing = config.easing.factory(); + } else { + animation.easing = config.easing; + } + } - return { - type: 'timing', - onFrame: timing, - onStart: onStart as ( - animation: TimingAnimation, - now: number - ) => boolean, - progress: 0, - toValue, - startValue: 0, - startTime: 0, - easing: () => 0, - current: toValue, - callback, - reduceMotion: getReduceMotionForAnimation(userConfig?.reduceMotion), - } as TimingAnimation; - }); - } -); + return { + type: 'timing', + onFrame: timing, + onStart: onStart as (animation: TimingAnimation, now: number) => boolean, + progress: 0, + toValue, + startValue: 0, + startTime: 0, + easing: () => 0, + current: toValue, + callback, + reduceMotion: getReduceMotionForAnimation(userConfig?.reduceMotion), + } as TimingAnimation; + }); +}; withTiming.cacheable = true; From ef9393e278ef562a16c8b04c3b78db382968ba91 Mon Sep 17 00:00:00 2001 From: Krzysztof Piaskowy Date: Mon, 25 Nov 2024 12:51:02 +0100 Subject: [PATCH 5/9] Mark functions as a cacheable --- packages/react-native-reanimated/src/animation/clamp.ts | 7 ++++--- .../react-native-reanimated/src/animation/decay/decay.ts | 4 +++- packages/react-native-reanimated/src/animation/delay.ts | 7 ++++--- packages/react-native-reanimated/src/animation/repeat.ts | 7 ++++--- .../react-native-reanimated/src/animation/sequence.ts | 1 + packages/react-native-reanimated/src/animation/spring.ts | 8 +++++--- packages/react-native-reanimated/src/animation/timing.ts | 2 +- 7 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/react-native-reanimated/src/animation/clamp.ts b/packages/react-native-reanimated/src/animation/clamp.ts index b6ff6607bb3..bb518ffce67 100644 --- a/packages/react-native-reanimated/src/animation/clamp.ts +++ b/packages/react-native-reanimated/src/animation/clamp.ts @@ -11,7 +11,7 @@ import type { AnimationObject, ReduceMotion, } from '../commonTypes'; -import type { ClampAnimation } from './commonTypes'; +import type { CacheableWorklet, ClampAnimation } from './commonTypes'; import { logger } from '../logger'; type withClampType = ( @@ -22,7 +22,7 @@ type withClampType = ( clampedAnimation: T ) => T; -export const withClamp = function ( +export const withClamp = function ( config: { min?: T; max?: T; reduceMotion?: ReduceMotion }, _animationToClamp: AnimationObject | (() => AnimationObject) ): Animation { @@ -131,4 +131,5 @@ export const withClamp = function ( }; } ); -} as withClampType; +}; +withClamp.cacheable = true; diff --git a/packages/react-native-reanimated/src/animation/decay/decay.ts b/packages/react-native-reanimated/src/animation/decay/decay.ts index 9e6d5078aa0..491280c1b9f 100644 --- a/packages/react-native-reanimated/src/animation/decay/decay.ts +++ b/packages/react-native-reanimated/src/animation/decay/decay.ts @@ -15,6 +15,7 @@ import type { } from './utils'; import { rigidDecay } from './rigidDecay'; import { ReanimatedError } from '../../errors'; +import type { CacheableWorklet } from '../commonTypes'; export type WithDecayConfig = DecayConfig; @@ -121,4 +122,5 @@ export const withDecay = function ( reduceMotion: getReduceMotionForAnimation(config.reduceMotion), } as DecayAnimation; }); -} as unknown as withDecayType; +} as unknown as withDecayType & CacheableWorklet; +withDecay.cacheable = true; diff --git a/packages/react-native-reanimated/src/animation/delay.ts b/packages/react-native-reanimated/src/animation/delay.ts index 3839bfb9a72..9590ddcbc7f 100644 --- a/packages/react-native-reanimated/src/animation/delay.ts +++ b/packages/react-native-reanimated/src/animation/delay.ts @@ -7,7 +7,7 @@ import type { AnimationObject, ReduceMotion, } from '../commonTypes'; -import type { DelayAnimation } from './commonTypes'; +import type { CacheableWorklet, DelayAnimation } from './commonTypes'; // TODO TYPESCRIPT This is a temporary type to get rid of .d.ts file. type withDelayType = ( @@ -29,7 +29,7 @@ type withDelayType = ( * which holds the current state of the animation. * @see https://docs.swmansion.com/react-native-reanimated/docs/animations/withDelay */ -export const withDelay = function ( +export const withDelay = function ( delayMs: number, _nextAnimation: T | (() => T), reduceMotion?: ReduceMotion @@ -114,4 +114,5 @@ export const withDelay = function ( }; } ); -} as withDelayType; +}; +withDelay.cacheable = true; diff --git a/packages/react-native-reanimated/src/animation/repeat.ts b/packages/react-native-reanimated/src/animation/repeat.ts index bb8fb1a5f38..eee58269d88 100644 --- a/packages/react-native-reanimated/src/animation/repeat.ts +++ b/packages/react-native-reanimated/src/animation/repeat.ts @@ -8,7 +8,7 @@ import type { AnimationObject, ReduceMotion, } from '../commonTypes'; -import type { RepeatAnimation } from './commonTypes'; +import type { CacheableWorklet, RepeatAnimation } from './commonTypes'; // TODO TYPESCRIPT This is a temporary type to get rid of .d.ts file. type withRepeatType = ( @@ -36,7 +36,7 @@ type withRepeatType = ( * which holds the current state of the animation. * @see https://docs.swmansion.com/react-native-reanimated/docs/animations/withRepeat */ -export const withRepeat = function ( +export const withRepeat = function ( _nextAnimation: T | (() => T), numberOfReps = 2, reverse = false, @@ -141,4 +141,5 @@ export const withRepeat = function ( }; } ); -} as withRepeatType; +}; +withRepeat.cacheable = true; diff --git a/packages/react-native-reanimated/src/animation/sequence.ts b/packages/react-native-reanimated/src/animation/sequence.ts index a436e922822..b91627d3d3e 100644 --- a/packages/react-native-reanimated/src/animation/sequence.ts +++ b/packages/react-native-reanimated/src/animation/sequence.ts @@ -166,3 +166,4 @@ export function withSequence( } ); } +withSequence.cacheable = true; diff --git a/packages/react-native-reanimated/src/animation/spring.ts b/packages/react-native-reanimated/src/animation/spring.ts index 2362df8f9ed..3158dc701f8 100644 --- a/packages/react-native-reanimated/src/animation/spring.ts +++ b/packages/react-native-reanimated/src/animation/spring.ts @@ -22,6 +22,7 @@ import { scaleZetaToMatchClamps, checkIfConfigIsValid, } from './springUtils'; +import type { CacheableWorklet } from './commonTypes'; // TODO TYPESCRIPT This is a temporary type to get rid of .d.ts file. type withSpringType = ( @@ -43,11 +44,11 @@ type withSpringType = ( * which holds the current state of the animation * @see https://docs.swmansion.com/react-native-reanimated/docs/animations/withSpring */ -export const withSpring = (( +export const withSpring = function ( toValue: AnimatableValue, userConfig?: SpringConfig, callback?: AnimationCallback -): Animation => { +): Animation { 'worklet'; return defineAnimation(toValue, () => { @@ -245,4 +246,5 @@ export const withSpring = (( reduceMotion: getReduceMotionForAnimation(config.reduceMotion), } as SpringAnimation; }); -}) as withSpringType; +}; +withSpring.cacheable = true; diff --git a/packages/react-native-reanimated/src/animation/timing.ts b/packages/react-native-reanimated/src/animation/timing.ts index 55ea15b5dc0..7112604af48 100644 --- a/packages/react-native-reanimated/src/animation/timing.ts +++ b/packages/react-native-reanimated/src/animation/timing.ts @@ -71,7 +71,7 @@ type withTimingType = ( * which holds the current state of the animation. * @see https://docs.swmansion.com/react-native-reanimated/docs/animations/withTiming */ -export const withTiming = function ( +export const withTiming = function ( toValue: AnimatableValue, userConfig?: TimingConfig, callback?: AnimationCallback From 2f49e16ea72ac26d1a258341c5a74b5b646fb3c7 Mon Sep 17 00:00:00 2001 From: Krzysztof Piaskowy Date: Mon, 25 Nov 2024 12:56:14 +0100 Subject: [PATCH 6/9] Format c++ --- .../Common/cpp/worklets/SharedItems/Shareables.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp b/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp index 17d295c8351..12216edfeb4 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp @@ -48,7 +48,8 @@ jsi::Value makeShareableClone( auto object = value.asObject(rt); if (!object.getProperty(rt, "__workletHash").isUndefined()) { if (shouldRetainRemote.isBool() && shouldRetainRemote.getBool()) { - shareable = std::make_shared>(rt, object); + shareable = + std::make_shared>(rt, object); } else { shareable = std::make_shared(rt, object); } From 409754e1f82c02d42fe91d82a2c8f707021e0fc9 Mon Sep 17 00:00:00 2001 From: Krzysztof Piaskowy Date: Mon, 2 Dec 2024 17:01:08 +0100 Subject: [PATCH 7/9] Restore some changes --- packages/react-native-reanimated/src/animation/clamp.ts | 7 +++---- .../react-native-reanimated/src/animation/commonTypes.ts | 4 ---- .../react-native-reanimated/src/animation/decay/decay.ts | 4 +--- packages/react-native-reanimated/src/animation/delay.ts | 7 +++---- packages/react-native-reanimated/src/animation/repeat.ts | 7 +++---- packages/react-native-reanimated/src/animation/spring.ts | 8 +++----- packages/react-native-reanimated/src/animation/timing.ts | 6 ++---- packages/react-native-reanimated/src/commonTypes.ts | 5 ++--- 8 files changed, 17 insertions(+), 31 deletions(-) diff --git a/packages/react-native-reanimated/src/animation/clamp.ts b/packages/react-native-reanimated/src/animation/clamp.ts index bb518ffce67..b6ff6607bb3 100644 --- a/packages/react-native-reanimated/src/animation/clamp.ts +++ b/packages/react-native-reanimated/src/animation/clamp.ts @@ -11,7 +11,7 @@ import type { AnimationObject, ReduceMotion, } from '../commonTypes'; -import type { CacheableWorklet, ClampAnimation } from './commonTypes'; +import type { ClampAnimation } from './commonTypes'; import { logger } from '../logger'; type withClampType = ( @@ -22,7 +22,7 @@ type withClampType = ( clampedAnimation: T ) => T; -export const withClamp = function ( +export const withClamp = function ( config: { min?: T; max?: T; reduceMotion?: ReduceMotion }, _animationToClamp: AnimationObject | (() => AnimationObject) ): Animation { @@ -131,5 +131,4 @@ export const withClamp = function void; callback?: AnimationCallback; } - -export interface CacheableWorklet { - cacheable?: boolean; -} diff --git a/packages/react-native-reanimated/src/animation/decay/decay.ts b/packages/react-native-reanimated/src/animation/decay/decay.ts index 491280c1b9f..9e6d5078aa0 100644 --- a/packages/react-native-reanimated/src/animation/decay/decay.ts +++ b/packages/react-native-reanimated/src/animation/decay/decay.ts @@ -15,7 +15,6 @@ import type { } from './utils'; import { rigidDecay } from './rigidDecay'; import { ReanimatedError } from '../../errors'; -import type { CacheableWorklet } from '../commonTypes'; export type WithDecayConfig = DecayConfig; @@ -122,5 +121,4 @@ export const withDecay = function ( reduceMotion: getReduceMotionForAnimation(config.reduceMotion), } as DecayAnimation; }); -} as unknown as withDecayType & CacheableWorklet; -withDecay.cacheable = true; +} as unknown as withDecayType; diff --git a/packages/react-native-reanimated/src/animation/delay.ts b/packages/react-native-reanimated/src/animation/delay.ts index 9590ddcbc7f..3839bfb9a72 100644 --- a/packages/react-native-reanimated/src/animation/delay.ts +++ b/packages/react-native-reanimated/src/animation/delay.ts @@ -7,7 +7,7 @@ import type { AnimationObject, ReduceMotion, } from '../commonTypes'; -import type { CacheableWorklet, DelayAnimation } from './commonTypes'; +import type { DelayAnimation } from './commonTypes'; // TODO TYPESCRIPT This is a temporary type to get rid of .d.ts file. type withDelayType = ( @@ -29,7 +29,7 @@ type withDelayType = ( * which holds the current state of the animation. * @see https://docs.swmansion.com/react-native-reanimated/docs/animations/withDelay */ -export const withDelay = function ( +export const withDelay = function ( delayMs: number, _nextAnimation: T | (() => T), reduceMotion?: ReduceMotion @@ -114,5 +114,4 @@ export const withDelay = function ( @@ -36,7 +36,7 @@ type withRepeatType = ( * which holds the current state of the animation. * @see https://docs.swmansion.com/react-native-reanimated/docs/animations/withRepeat */ -export const withRepeat = function ( +export const withRepeat = function ( _nextAnimation: T | (() => T), numberOfReps = 2, reverse = false, @@ -141,5 +141,4 @@ export const withRepeat = function ( @@ -44,11 +43,11 @@ type withSpringType = ( * which holds the current state of the animation * @see https://docs.swmansion.com/react-native-reanimated/docs/animations/withSpring */ -export const withSpring = function ( +export const withSpring = (( toValue: AnimatableValue, userConfig?: SpringConfig, callback?: AnimationCallback -): Animation { +): Animation => { 'worklet'; return defineAnimation(toValue, () => { @@ -246,5 +245,4 @@ export const withSpring = function ( reduceMotion: getReduceMotionForAnimation(config.reduceMotion), } as SpringAnimation; }); -}; -withSpring.cacheable = true; +}) as withSpringType; diff --git a/packages/react-native-reanimated/src/animation/timing.ts b/packages/react-native-reanimated/src/animation/timing.ts index 7112604af48..48fe9cf03d6 100644 --- a/packages/react-native-reanimated/src/animation/timing.ts +++ b/packages/react-native-reanimated/src/animation/timing.ts @@ -14,7 +14,6 @@ import type { ReduceMotion, EasingFunction, } from '../commonTypes'; -import type { CacheableWorklet } from './commonTypes'; /** * The timing animation configuration. @@ -71,7 +70,7 @@ type withTimingType = ( * which holds the current state of the animation. * @see https://docs.swmansion.com/react-native-reanimated/docs/animations/withTiming */ -export const withTiming = function ( +export const withTiming = function ( toValue: AnimatableValue, userConfig?: TimingConfig, callback?: AnimationCallback @@ -157,5 +156,4 @@ export const withTiming = function ( reduceMotion: getReduceMotionForAnimation(userConfig?.reduceMotion), } as TimingAnimation; }); -}; -withTiming.cacheable = true; +} as withTimingType; diff --git a/packages/react-native-reanimated/src/commonTypes.ts b/packages/react-native-reanimated/src/commonTypes.ts index 00231e61bd8..725436df1d8 100644 --- a/packages/react-native-reanimated/src/commonTypes.ts +++ b/packages/react-native-reanimated/src/commonTypes.ts @@ -7,7 +7,6 @@ import type { } from 'react-native'; import type { WorkletsModuleProxy } from './worklets'; import type { ReanimatedModuleProxy } from './ReanimatedModule'; -import type { CacheableWorklet } from './animation/commonTypes'; export interface IWorkletsModule extends WorkletsModuleProxy {} @@ -331,12 +330,12 @@ interface WorkletBaseDev extends WorkletBaseCommon { export type WorkletFunctionDev< Args extends unknown[] = unknown[], ReturnValue = unknown, -> = ((...args: Args) => ReturnValue) & WorkletBaseDev & CacheableWorklet; +> = ((...args: Args) => ReturnValue) & WorkletBaseDev; type WorkletFunctionRelease< Args extends unknown[] = unknown[], ReturnValue = unknown, -> = ((...args: Args) => ReturnValue) & WorkletBaseRelease & CacheableWorklet; +> = ((...args: Args) => ReturnValue) & WorkletBaseRelease; export type WorkletFunction< Args extends unknown[] = unknown[], From 18d4bc99cd62b0188f5e797f1c6ddd05fc620d34 Mon Sep 17 00:00:00 2001 From: Krzysztof Piaskowy Date: Mon, 2 Dec 2024 17:02:34 +0100 Subject: [PATCH 8/9] Cache all --- packages/react-native-reanimated/src/animation/sequence.ts | 1 - packages/react-native-reanimated/src/shareables.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/react-native-reanimated/src/animation/sequence.ts b/packages/react-native-reanimated/src/animation/sequence.ts index b91627d3d3e..a436e922822 100644 --- a/packages/react-native-reanimated/src/animation/sequence.ts +++ b/packages/react-native-reanimated/src/animation/sequence.ts @@ -166,4 +166,3 @@ export function withSequence( } ); } -withSequence.cacheable = true; diff --git a/packages/react-native-reanimated/src/shareables.ts b/packages/react-native-reanimated/src/shareables.ts index ff749e7ed83..680e8d7e423 100644 --- a/packages/react-native-reanimated/src/shareables.ts +++ b/packages/react-native-reanimated/src/shareables.ts @@ -303,7 +303,7 @@ Offending code was: \`${getWorkletCode(value)}\``); } const clone = WorkletsModule.makeShareableClone( clonedProps, - shouldPersistRemote || !!value.cacheable, + true, value ) as ShareableRef; shareableMappingCache.set(value, clone); From 1fd459774262850f84df265e9d7e84a41b04a3f3 Mon Sep 17 00:00:00 2001 From: Krzysztof Piaskowy Date: Tue, 3 Dec 2024 10:15:04 +0100 Subject: [PATCH 9/9] Add comment --- packages/react-native-reanimated/src/shareables.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native-reanimated/src/shareables.ts b/packages/react-native-reanimated/src/shareables.ts index 680e8d7e423..ec4bdea2b33 100644 --- a/packages/react-native-reanimated/src/shareables.ts +++ b/packages/react-native-reanimated/src/shareables.ts @@ -303,6 +303,7 @@ Offending code was: \`${getWorkletCode(value)}\``); } const clone = WorkletsModule.makeShareableClone( clonedProps, + // retain all worklets true, value ) as ShareableRef;