1a48bc6c0SBrent Vatne #include "NativeReanimatedModule.h"
25f154df9Saleqsio 
35f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
4*531a852fSaleqsio #include <react/renderer/core/TraitCast.h>
55f154df9Saleqsio #include <react/renderer/uimanager/UIManagerBinding.h>
65f154df9Saleqsio #include <react/renderer/uimanager/primitives.h>
75f154df9Saleqsio #endif
85f154df9Saleqsio 
9a48bc6c0SBrent Vatne #include <functional>
10a48bc6c0SBrent Vatne #include <memory>
11c7e4709dSKudo Chien #include <thread>
1204819bfdSŁukasz Kosmaty #include <unordered_map>
135f154df9Saleqsio 
145f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
155f154df9Saleqsio #include "FabricUtils.h"
165f154df9Saleqsio #include "NewestShadowNodesRegistry.h"
175f154df9Saleqsio #include "ReanimatedUIManagerBinding.h"
185f154df9Saleqsio #include "ShadowTreeCloner.h"
195f154df9Saleqsio #endif
2004819bfdSŁukasz Kosmaty 
21c7e4709dSKudo Chien #include "EventHandlerRegistry.h"
22c7e4709dSKudo Chien #include "FeaturesConfig.h"
23c7e4709dSKudo Chien #include "ReanimatedHiddenHeaders.h"
24c7e4709dSKudo Chien #include "RuntimeDecorator.h"
255f154df9Saleqsio #include "Shareables.h"
26c7e4709dSKudo Chien #include "WorkletEventHandler.h"
27a48bc6c0SBrent Vatne 
28a48bc6c0SBrent Vatne using namespace facebook;
29a48bc6c0SBrent Vatne 
30c7e4709dSKudo Chien namespace reanimated {
31a48bc6c0SBrent Vatne 
NativeReanimatedModule(const std::shared_ptr<CallInvoker> & jsInvoker,const std::shared_ptr<Scheduler> & scheduler,const std::shared_ptr<jsi::Runtime> & rt,const std::shared_ptr<ErrorHandler> & errorHandler,PlatformDepMethodsHolder platformDepMethodsHolder)32c7e4709dSKudo Chien NativeReanimatedModule::NativeReanimatedModule(
335f154df9Saleqsio     const std::shared_ptr<CallInvoker> &jsInvoker,
345f154df9Saleqsio     const std::shared_ptr<Scheduler> &scheduler,
355f154df9Saleqsio     const std::shared_ptr<jsi::Runtime> &rt,
365f154df9Saleqsio     const std::shared_ptr<ErrorHandler> &errorHandler,
375f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
385f154df9Saleqsio // nothing
395f154df9Saleqsio #else
40c7e4709dSKudo Chien     std::function<jsi::Value(jsi::Runtime &, const int, const jsi::String &)>
41c7e4709dSKudo Chien         propObtainer,
425f154df9Saleqsio #endif
43c7e4709dSKudo Chien     PlatformDepMethodsHolder platformDepMethodsHolder)
44c7e4709dSKudo Chien     : NativeReanimatedModuleSpec(jsInvoker),
45c7e4709dSKudo Chien       RuntimeManager(rt, errorHandler, scheduler, RuntimeType::UI),
465f154df9Saleqsio       eventHandlerRegistry(std::make_unique<EventHandlerRegistry>()),
47a48bc6c0SBrent Vatne       requestRender(platformDepMethodsHolder.requestRender),
485f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
495f154df9Saleqsio // nothing
505f154df9Saleqsio #else
513b78aaffSTomasz Sapeta       propObtainer(propObtainer),
525f154df9Saleqsio #endif
535f154df9Saleqsio       animatedSensorModule(platformDepMethodsHolder),
545f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
555f154df9Saleqsio       synchronouslyUpdateUIPropsFunction(
565f154df9Saleqsio           platformDepMethodsHolder.synchronouslyUpdateUIPropsFunction)
575f154df9Saleqsio #else
583b78aaffSTomasz Sapeta       configurePropsPlatformFunction(
595f154df9Saleqsio           platformDepMethodsHolder.configurePropsFunction)
605f154df9Saleqsio #endif
615f154df9Saleqsio {
625f154df9Saleqsio   auto requestAnimationFrame = [=](jsi::Runtime &rt, const jsi::Value &fn) {
635f154df9Saleqsio     auto jsFunction = std::make_shared<jsi::Value>(rt, fn);
645f154df9Saleqsio     frameCallbacks.push_back([=](double timestamp) {
655f154df9Saleqsio       runtimeHelper->runOnUIGuarded(*jsFunction, jsi::Value(timestamp));
665f154df9Saleqsio     });
67a48bc6c0SBrent Vatne     maybeRequestRender();
68a48bc6c0SBrent Vatne   };
69c7e4709dSKudo Chien 
705f154df9Saleqsio   auto scheduleOnJS = [this](
715f154df9Saleqsio                           jsi::Runtime &rt,
725f154df9Saleqsio                           const jsi::Value &remoteFun,
735f154df9Saleqsio                           const jsi::Value &argsValue) {
745f154df9Saleqsio     auto shareableRemoteFun = extractShareableOrThrow<ShareableRemoteFunction>(
755f154df9Saleqsio         rt,
765f154df9Saleqsio         remoteFun,
775f154df9Saleqsio         "Incompatible object passed to scheduleOnJS. It is only allowed to schedule functions defined on the React Native JS runtime this way.");
785f154df9Saleqsio     auto shareableArgs = argsValue.isUndefined()
795f154df9Saleqsio         ? nullptr
805f154df9Saleqsio         : extractShareableOrThrow(rt, argsValue);
815f154df9Saleqsio     auto jsRuntime = this->runtimeHelper->rnRuntime();
825f154df9Saleqsio     this->scheduler->scheduleOnJS([=] {
835f154df9Saleqsio       jsi::Runtime &rt = *jsRuntime;
845f154df9Saleqsio       auto remoteFun = shareableRemoteFun->getJSValue(rt);
855f154df9Saleqsio       if (shareableArgs == nullptr) {
865f154df9Saleqsio         // fast path for remote function w/o arguments
875f154df9Saleqsio         remoteFun.asObject(rt).asFunction(rt).call(rt);
885f154df9Saleqsio       } else {
895f154df9Saleqsio         auto argsArray = shareableArgs->getJSValue(rt).asObject(rt).asArray(rt);
905f154df9Saleqsio         auto argsSize = argsArray.size(rt);
915f154df9Saleqsio         // number of arguments is typically relatively small so it is ok to
925f154df9Saleqsio         // to use VLAs here, hence disabling the lint rule
935f154df9Saleqsio         jsi::Value args[argsSize]; // NOLINT(runtime/arrays)
945f154df9Saleqsio         for (size_t i = 0; i < argsSize; i++) {
955f154df9Saleqsio           args[i] = argsArray.getValueAtIndex(rt, i);
965f154df9Saleqsio         }
975f154df9Saleqsio         remoteFun.asObject(rt).asFunction(rt).call(rt, args, argsSize);
985f154df9Saleqsio       }
995f154df9Saleqsio     });
1005f154df9Saleqsio   };
1015f154df9Saleqsio 
1025f154df9Saleqsio   auto makeShareableClone = [this](jsi::Runtime &rt, const jsi::Value &value) {
1035f154df9Saleqsio     return this->makeShareableClone(rt, value, jsi::Value::undefined());
1045f154df9Saleqsio   };
1055f154df9Saleqsio 
1065f154df9Saleqsio   auto updateDataSynchronously =
1075f154df9Saleqsio       [this](
1085f154df9Saleqsio           jsi::Runtime &rt,
1095f154df9Saleqsio           const jsi::Value &synchronizedDataHolderRef,
1105f154df9Saleqsio           const jsi::Value &newData) {
1115f154df9Saleqsio         return this->updateDataSynchronously(
1125f154df9Saleqsio             rt, synchronizedDataHolderRef, newData);
1135f154df9Saleqsio       };
1145f154df9Saleqsio 
1155f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
1165f154df9Saleqsio   auto updateProps = [this](
1175f154df9Saleqsio                          jsi::Runtime &rt,
1185f154df9Saleqsio                          const jsi::Value &shadowNodeValue,
1195f154df9Saleqsio                          const jsi::Value &props) {
1205f154df9Saleqsio     this->updateProps(rt, shadowNodeValue, props);
1215f154df9Saleqsio   };
1225f154df9Saleqsio 
1235f154df9Saleqsio   auto removeShadowNodeFromRegistry =
1245f154df9Saleqsio       [this](jsi::Runtime &rt, const jsi::Value &tag) {
1255f154df9Saleqsio         this->removeShadowNodeFromRegistry(rt, tag);
1265f154df9Saleqsio       };
1275f154df9Saleqsio 
1285f154df9Saleqsio   auto measure = [this](jsi::Runtime &rt, const jsi::Value &shadowNodeValue) {
1295f154df9Saleqsio     return this->measure(rt, shadowNodeValue);
1305f154df9Saleqsio   };
1315f154df9Saleqsio 
1325f154df9Saleqsio   auto dispatchCommand = [this](
1335f154df9Saleqsio                              jsi::Runtime &rt,
1345f154df9Saleqsio                              const jsi::Value &shadowNodeValue,
1355f154df9Saleqsio                              const jsi::Value &commandNameValue,
1365f154df9Saleqsio                              const jsi::Value &argsValue) {
1375f154df9Saleqsio     this->dispatchCommand(rt, shadowNodeValue, commandNameValue, argsValue);
1385f154df9Saleqsio   };
1395f154df9Saleqsio #endif
140c7e4709dSKudo Chien 
141c7e4709dSKudo Chien   RuntimeDecorator::decorateUIRuntime(
142c7e4709dSKudo Chien       *runtime,
1435f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
1445f154df9Saleqsio       updateProps,
1455f154df9Saleqsio       measure,
1465f154df9Saleqsio       removeShadowNodeFromRegistry,
1475f154df9Saleqsio       dispatchCommand,
1485f154df9Saleqsio #else
1495f154df9Saleqsio       platformDepMethodsHolder.updatePropsFunction,
1505f154df9Saleqsio       platformDepMethodsHolder.measureFunction,
151a48bc6c0SBrent Vatne       platformDepMethodsHolder.scrollToFunction,
1525f154df9Saleqsio #endif
1535f154df9Saleqsio       requestAnimationFrame,
1545f154df9Saleqsio       scheduleOnJS,
1555f154df9Saleqsio       makeShareableClone,
1565f154df9Saleqsio       updateDataSynchronously,
157c7e4709dSKudo Chien       platformDepMethodsHolder.getCurrentTime,
158c7e4709dSKudo Chien       platformDepMethodsHolder.setGestureStateFunction,
1595f154df9Saleqsio       platformDepMethodsHolder.progressLayoutAnimation,
160*531a852fSaleqsio       platformDepMethodsHolder.endLayoutAnimation,
161*531a852fSaleqsio       platformDepMethodsHolder.maybeFlushUIUpdatesQueueFunction);
162c7e4709dSKudo Chien   onRenderCallback = [this](double timestampMs) {
163c7e4709dSKudo Chien     this->renderRequested = false;
164c7e4709dSKudo Chien     this->onRender(timestampMs);
165c7e4709dSKudo Chien   };
1665f154df9Saleqsio 
1675f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
1685f154df9Saleqsio   // nothing
1695f154df9Saleqsio #else
1705f154df9Saleqsio   updatePropsFunction = platformDepMethodsHolder.updatePropsFunction;
1715f154df9Saleqsio #endif
17204819bfdSŁukasz Kosmaty   subscribeForKeyboardEventsFunction =
17304819bfdSŁukasz Kosmaty       platformDepMethodsHolder.subscribeForKeyboardEvents;
17404819bfdSŁukasz Kosmaty   unsubscribeFromKeyboardEventsFunction =
17504819bfdSŁukasz Kosmaty       platformDepMethodsHolder.unsubscribeFromKeyboardEvents;
176a48bc6c0SBrent Vatne }
177a48bc6c0SBrent Vatne 
installCoreFunctions(jsi::Runtime & rt,const jsi::Value & callGuard,const jsi::Value & valueUnpacker)178c7e4709dSKudo Chien void NativeReanimatedModule::installCoreFunctions(
179c7e4709dSKudo Chien     jsi::Runtime &rt,
1805f154df9Saleqsio     const jsi::Value &callGuard,
1815f154df9Saleqsio     const jsi::Value &valueUnpacker) {
1825f154df9Saleqsio   if (!runtimeHelper) {
1835f154df9Saleqsio     // initialize runtimeHelper here if not already present. We expect only one
1845f154df9Saleqsio     // instace of the helper to exists.
1855f154df9Saleqsio     runtimeHelper =
1865f154df9Saleqsio         std::make_shared<JSRuntimeHelper>(&rt, this->runtime.get(), scheduler);
1875f154df9Saleqsio   }
1885f154df9Saleqsio   runtimeHelper->callGuard =
1895f154df9Saleqsio       std::make_unique<CoreFunction>(runtimeHelper.get(), callGuard);
1905f154df9Saleqsio   runtimeHelper->valueUnpacker =
1915f154df9Saleqsio       std::make_unique<CoreFunction>(runtimeHelper.get(), valueUnpacker);
192a48bc6c0SBrent Vatne }
193a48bc6c0SBrent Vatne 
~NativeReanimatedModule()1945f154df9Saleqsio NativeReanimatedModule::~NativeReanimatedModule() {
1955f154df9Saleqsio   if (runtimeHelper) {
1965f154df9Saleqsio     runtimeHelper->callGuard = nullptr;
1975f154df9Saleqsio     runtimeHelper->valueUnpacker = nullptr;
1985f154df9Saleqsio     // event handler registry and frame callbacks store some JSI values from UI
1995f154df9Saleqsio     // runtime, so they have to go away before we tear down the runtime
2005f154df9Saleqsio     eventHandlerRegistry.reset();
2015f154df9Saleqsio     frameCallbacks.clear();
2025f154df9Saleqsio     runtime.reset();
2035f154df9Saleqsio     // make sure uiRuntimeDestroyed is set after the runtime is deallocated
2045f154df9Saleqsio     runtimeHelper->uiRuntimeDestroyed = true;
2055f154df9Saleqsio   }
2065f154df9Saleqsio }
2075f154df9Saleqsio 
scheduleOnUI(jsi::Runtime & rt,const jsi::Value & worklet)2085f154df9Saleqsio void NativeReanimatedModule::scheduleOnUI(
209c7e4709dSKudo Chien     jsi::Runtime &rt,
2105f154df9Saleqsio     const jsi::Value &worklet) {
2115f154df9Saleqsio   auto shareableWorklet = extractShareableOrThrow(rt, worklet);
2125f154df9Saleqsio   assert(
2135f154df9Saleqsio       shareableWorklet->valueType() == Shareable::WorkletType &&
2145f154df9Saleqsio       "only worklets can be scheduled to run on UI");
215a48bc6c0SBrent Vatne   scheduler->scheduleOnUI([=] {
2165f154df9Saleqsio     jsi::Runtime &rt = *runtimeHelper->uiRuntime();
2175f154df9Saleqsio     auto workletValue = shareableWorklet->getJSValue(rt);
2185f154df9Saleqsio     runtimeHelper->runOnUIGuarded(workletValue);
219a48bc6c0SBrent Vatne   });
220a48bc6c0SBrent Vatne }
221a48bc6c0SBrent Vatne 
makeSynchronizedDataHolder(jsi::Runtime & rt,const jsi::Value & initialShareable)2225f154df9Saleqsio jsi::Value NativeReanimatedModule::makeSynchronizedDataHolder(
223c7e4709dSKudo Chien     jsi::Runtime &rt,
2245f154df9Saleqsio     const jsi::Value &initialShareable) {
2255f154df9Saleqsio   auto dataHolder = std::make_shared<ShareableSynchronizedDataHolder>(
2265f154df9Saleqsio       runtimeHelper, rt, initialShareable);
2275f154df9Saleqsio   return dataHolder->getJSValue(rt);
2285f154df9Saleqsio }
2295f154df9Saleqsio 
updateDataSynchronously(jsi::Runtime & rt,const jsi::Value & synchronizedDataHolderRef,const jsi::Value & newData)2305f154df9Saleqsio void NativeReanimatedModule::updateDataSynchronously(
2315f154df9Saleqsio     jsi::Runtime &rt,
2325f154df9Saleqsio     const jsi::Value &synchronizedDataHolderRef,
2335f154df9Saleqsio     const jsi::Value &newData) {
2345f154df9Saleqsio   auto dataHolder = extractShareableOrThrow<ShareableSynchronizedDataHolder>(
2355f154df9Saleqsio       rt, synchronizedDataHolderRef);
2365f154df9Saleqsio   dataHolder->set(rt, newData);
2375f154df9Saleqsio }
2385f154df9Saleqsio 
getDataSynchronously(jsi::Runtime & rt,const jsi::Value & synchronizedDataHolderRef)2395f154df9Saleqsio jsi::Value NativeReanimatedModule::getDataSynchronously(
2405f154df9Saleqsio     jsi::Runtime &rt,
2415f154df9Saleqsio     const jsi::Value &synchronizedDataHolderRef) {
2425f154df9Saleqsio   auto dataHolder = extractShareableOrThrow<ShareableSynchronizedDataHolder>(
2435f154df9Saleqsio       rt, synchronizedDataHolderRef);
2445f154df9Saleqsio   return dataHolder->get(rt);
2455f154df9Saleqsio }
2465f154df9Saleqsio 
makeShareableClone(jsi::Runtime & rt,const jsi::Value & value,const jsi::Value & shouldRetainRemote)2475f154df9Saleqsio jsi::Value NativeReanimatedModule::makeShareableClone(
2485f154df9Saleqsio     jsi::Runtime &rt,
2495f154df9Saleqsio     const jsi::Value &value,
2505f154df9Saleqsio     const jsi::Value &shouldRetainRemote) {
2515f154df9Saleqsio   std::shared_ptr<Shareable> shareable;
2525f154df9Saleqsio   if (value.isObject()) {
2535f154df9Saleqsio     auto object = value.asObject(rt);
2545f154df9Saleqsio     if (!object.getProperty(rt, "__workletHash").isUndefined()) {
2555f154df9Saleqsio       shareable = std::make_shared<ShareableWorklet>(runtimeHelper, rt, object);
2565f154df9Saleqsio     } else if (!object.getProperty(rt, "__init").isUndefined()) {
2575f154df9Saleqsio       shareable = std::make_shared<ShareableHandle>(runtimeHelper, rt, object);
2585f154df9Saleqsio     } else if (object.isFunction(rt)) {
259*531a852fSaleqsio       auto function = object.asFunction(rt);
260*531a852fSaleqsio       if (function.isHostFunction(rt)) {
261*531a852fSaleqsio         shareable =
262*531a852fSaleqsio             std::make_shared<ShareableHostFunction>(rt, std::move(function));
263*531a852fSaleqsio       } else {
2645f154df9Saleqsio         shareable = std::make_shared<ShareableRemoteFunction>(
265*531a852fSaleqsio             runtimeHelper, rt, std::move(function));
266*531a852fSaleqsio       }
2675f154df9Saleqsio     } else if (object.isArray(rt)) {
2685f154df9Saleqsio       if (shouldRetainRemote.isBool() && shouldRetainRemote.getBool()) {
2695f154df9Saleqsio         shareable = std::make_shared<RetainingShareable<ShareableArray>>(
2705f154df9Saleqsio             runtimeHelper, rt, object.asArray(rt));
2715f154df9Saleqsio       } else {
2725f154df9Saleqsio         shareable = std::make_shared<ShareableArray>(rt, object.asArray(rt));
2735f154df9Saleqsio       }
2745f154df9Saleqsio     } else if (object.isHostObject(rt)) {
2755f154df9Saleqsio       shareable = std::make_shared<ShareableHostObject>(
2765f154df9Saleqsio           runtimeHelper, rt, object.getHostObject(rt));
2775f154df9Saleqsio     } else {
2785f154df9Saleqsio       if (shouldRetainRemote.isBool() && shouldRetainRemote.getBool()) {
2795f154df9Saleqsio         shareable = std::make_shared<RetainingShareable<ShareableObject>>(
2805f154df9Saleqsio             runtimeHelper, rt, object);
2815f154df9Saleqsio       } else {
2825f154df9Saleqsio         shareable = std::make_shared<ShareableObject>(rt, object);
2835f154df9Saleqsio       }
2845f154df9Saleqsio     }
2855f154df9Saleqsio   } else if (value.isString()) {
2865f154df9Saleqsio     shareable = std::make_shared<ShareableString>(value.asString(rt).utf8(rt));
2875f154df9Saleqsio   } else if (value.isUndefined()) {
2885f154df9Saleqsio     shareable = std::make_shared<ShareableScalar>();
2895f154df9Saleqsio   } else if (value.isNull()) {
2905f154df9Saleqsio     shareable = std::make_shared<ShareableScalar>(nullptr);
2915f154df9Saleqsio   } else if (value.isBool()) {
2925f154df9Saleqsio     shareable = std::make_shared<ShareableScalar>(value.getBool());
2935f154df9Saleqsio   } else if (value.isNumber()) {
2945f154df9Saleqsio     shareable = std::make_shared<ShareableScalar>(value.getNumber());
2955f154df9Saleqsio   } else if (value.isSymbol()) {
2965f154df9Saleqsio     // TODO: this is only a placeholder implementation, here we replace symbols
2975f154df9Saleqsio     // with strings in order to make certain objects to be captured. There isn't
2985f154df9Saleqsio     // yet any usecase for using symbols on the UI runtime so it is fine to keep
2995f154df9Saleqsio     // it like this for now.
3005f154df9Saleqsio     shareable =
3015f154df9Saleqsio         std::make_shared<ShareableString>(value.getSymbol(rt).toString(rt));
3025f154df9Saleqsio   } else {
3035f154df9Saleqsio     throw std::runtime_error("attempted to convert an unsupported value type");
3045f154df9Saleqsio   }
3055f154df9Saleqsio   return ShareableJSRef::newHostObject(rt, shareable);
306a48bc6c0SBrent Vatne }
307a48bc6c0SBrent Vatne 
registerEventHandler(jsi::Runtime & rt,const jsi::Value & eventHash,const jsi::Value & worklet)308c7e4709dSKudo Chien jsi::Value NativeReanimatedModule::registerEventHandler(
309c7e4709dSKudo Chien     jsi::Runtime &rt,
310c7e4709dSKudo Chien     const jsi::Value &eventHash,
311c7e4709dSKudo Chien     const jsi::Value &worklet) {
3125f154df9Saleqsio   static uint64_t EVENT_HANDLER_ID = 1;
313a48bc6c0SBrent Vatne 
3145f154df9Saleqsio   uint64_t newRegistrationId = EVENT_HANDLER_ID++;
315a48bc6c0SBrent Vatne   auto eventName = eventHash.asString(rt).utf8(rt);
3165f154df9Saleqsio   auto handlerShareable = extractShareableOrThrow(rt, worklet);
317a48bc6c0SBrent Vatne 
318a48bc6c0SBrent Vatne   scheduler->scheduleOnUI([=] {
3195f154df9Saleqsio     jsi::Runtime &rt = *runtimeHelper->uiRuntime();
3205f154df9Saleqsio     auto handlerFunction = handlerShareable->getJSValue(rt);
321c7e4709dSKudo Chien     auto handler = std::make_shared<WorkletEventHandler>(
3225f154df9Saleqsio         runtimeHelper,
3235f154df9Saleqsio         newRegistrationId,
3245f154df9Saleqsio         eventName,
3255f154df9Saleqsio         std::move(handlerFunction));
3265f154df9Saleqsio     eventHandlerRegistry->registerEventHandler(std::move(handler));
327a48bc6c0SBrent Vatne   });
328a48bc6c0SBrent Vatne 
329c7e4709dSKudo Chien   return jsi::Value(static_cast<double>(newRegistrationId));
330a48bc6c0SBrent Vatne }
331a48bc6c0SBrent Vatne 
unregisterEventHandler(jsi::Runtime & rt,const jsi::Value & registrationId)332c7e4709dSKudo Chien void NativeReanimatedModule::unregisterEventHandler(
333c7e4709dSKudo Chien     jsi::Runtime &rt,
334c7e4709dSKudo Chien     const jsi::Value &registrationId) {
3355f154df9Saleqsio   uint64_t id = registrationId.asNumber();
336c7e4709dSKudo Chien   scheduler->scheduleOnUI(
337c7e4709dSKudo Chien       [=] { eventHandlerRegistry->unregisterEventHandler(id); });
338a48bc6c0SBrent Vatne }
339a48bc6c0SBrent Vatne 
getViewProp(jsi::Runtime & rt,const jsi::Value & viewTag,const jsi::Value & propName,const jsi::Value & callback)340c7e4709dSKudo Chien jsi::Value NativeReanimatedModule::getViewProp(
341c7e4709dSKudo Chien     jsi::Runtime &rt,
342c7e4709dSKudo Chien     const jsi::Value &viewTag,
343c7e4709dSKudo Chien     const jsi::Value &propName,
344c7e4709dSKudo Chien     const jsi::Value &callback) {
345c7e4709dSKudo Chien   const int viewTagInt = static_cast<int>(viewTag.asNumber());
346a48bc6c0SBrent Vatne   std::string propNameStr = propName.asString(rt).utf8(rt);
347a48bc6c0SBrent Vatne   jsi::Function fun = callback.getObject(rt).asFunction(rt);
348c7e4709dSKudo Chien   std::shared_ptr<jsi::Function> funPtr =
349c7e4709dSKudo Chien       std::make_shared<jsi::Function>(std::move(fun));
350a48bc6c0SBrent Vatne 
351a48bc6c0SBrent Vatne   scheduler->scheduleOnUI([&rt, viewTagInt, funPtr, this, propNameStr]() {
352c7e4709dSKudo Chien     const jsi::String propNameValue =
353c7e4709dSKudo Chien         jsi::String::createFromUtf8(rt, propNameStr);
354a48bc6c0SBrent Vatne     jsi::Value result = propObtainer(rt, viewTagInt, propNameValue);
355a48bc6c0SBrent Vatne     std::string resultStr = result.asString(rt).utf8(rt);
356a48bc6c0SBrent Vatne 
357a48bc6c0SBrent Vatne     scheduler->scheduleOnJS([&rt, resultStr, funPtr]() {
358c7e4709dSKudo Chien       const jsi::String resultValue =
359c7e4709dSKudo Chien           jsi::String::createFromUtf8(rt, resultStr);
360a48bc6c0SBrent Vatne       funPtr->call(rt, resultValue);
361a48bc6c0SBrent Vatne     });
362a48bc6c0SBrent Vatne   });
363a48bc6c0SBrent Vatne 
364a48bc6c0SBrent Vatne   return jsi::Value::undefined();
365a48bc6c0SBrent Vatne }
366a48bc6c0SBrent Vatne 
enableLayoutAnimations(jsi::Runtime & rt,const jsi::Value & config)367c7e4709dSKudo Chien jsi::Value NativeReanimatedModule::enableLayoutAnimations(
368c7e4709dSKudo Chien     jsi::Runtime &rt,
369c7e4709dSKudo Chien     const jsi::Value &config) {
370c7e4709dSKudo Chien   FeaturesConfig::setLayoutAnimationEnabled(config.getBool());
371c7e4709dSKudo Chien   return jsi::Value::undefined();
372c7e4709dSKudo Chien }
373c7e4709dSKudo Chien 
configureProps(jsi::Runtime & rt,const jsi::Value & uiProps,const jsi::Value & nativeProps)3743b78aaffSTomasz Sapeta jsi::Value NativeReanimatedModule::configureProps(
3753b78aaffSTomasz Sapeta     jsi::Runtime &rt,
3763b78aaffSTomasz Sapeta     const jsi::Value &uiProps,
3773b78aaffSTomasz Sapeta     const jsi::Value &nativeProps) {
3785f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
3795f154df9Saleqsio   jsi::Array array = nativeProps.asObject(rt).asArray(rt);
3805f154df9Saleqsio   for (int i = 0; i < array.size(rt); ++i) {
3815f154df9Saleqsio     std::string name = array.getValueAtIndex(rt, i).asString(rt).utf8(rt);
3825f154df9Saleqsio     nativePropNames_.insert(name);
3835f154df9Saleqsio   }
3845f154df9Saleqsio #else
3853b78aaffSTomasz Sapeta   configurePropsPlatformFunction(rt, uiProps, nativeProps);
3865f154df9Saleqsio #endif // RCT_NEW_ARCH_ENABLED
3875f154df9Saleqsio 
3885f154df9Saleqsio   return jsi::Value::undefined();
3895f154df9Saleqsio }
3905f154df9Saleqsio 
configureLayoutAnimation(jsi::Runtime & rt,const jsi::Value & viewTag,const jsi::Value & type,const jsi::Value & sharedTransitionTag,const jsi::Value & config)3915f154df9Saleqsio jsi::Value NativeReanimatedModule::configureLayoutAnimation(
3925f154df9Saleqsio     jsi::Runtime &rt,
3935f154df9Saleqsio     const jsi::Value &viewTag,
3945f154df9Saleqsio     const jsi::Value &type,
3955f154df9Saleqsio     const jsi::Value &sharedTransitionTag,
3965f154df9Saleqsio     const jsi::Value &config) {
3975f154df9Saleqsio   layoutAnimationsManager_.configureAnimation(
3985f154df9Saleqsio       viewTag.asNumber(),
3995f154df9Saleqsio       static_cast<LayoutAnimationType>(type.asNumber()),
4005f154df9Saleqsio       sharedTransitionTag.asString(rt).utf8(rt),
4015f154df9Saleqsio       extractShareableOrThrow(rt, config));
4023b78aaffSTomasz Sapeta   return jsi::Value::undefined();
4033b78aaffSTomasz Sapeta }
4043b78aaffSTomasz Sapeta 
onEvent(double eventTimestamp,const std::string & eventName,const jsi::Value & payload)405c7e4709dSKudo Chien void NativeReanimatedModule::onEvent(
4065f154df9Saleqsio     double eventTimestamp,
4075f154df9Saleqsio     const std::string &eventName,
4085f154df9Saleqsio     const jsi::Value &payload) {
4095f154df9Saleqsio   eventHandlerRegistry->processEvent(
4105f154df9Saleqsio       *runtime, eventTimestamp, eventName, payload);
411a48bc6c0SBrent Vatne }
412a48bc6c0SBrent Vatne 
isAnyHandlerWaitingForEvent(std::string eventName)413c7e4709dSKudo Chien bool NativeReanimatedModule::isAnyHandlerWaitingForEvent(
414c7e4709dSKudo Chien     std::string eventName) {
415a48bc6c0SBrent Vatne   return eventHandlerRegistry->isAnyHandlerWaitingForEvent(eventName);
416a48bc6c0SBrent Vatne }
417a48bc6c0SBrent Vatne 
maybeRequestRender()418c7e4709dSKudo Chien void NativeReanimatedModule::maybeRequestRender() {
419c7e4709dSKudo Chien   if (!renderRequested) {
420a48bc6c0SBrent Vatne     renderRequested = true;
421c7e4709dSKudo Chien     requestRender(onRenderCallback, *this->runtime);
422a48bc6c0SBrent Vatne   }
423a48bc6c0SBrent Vatne }
424a48bc6c0SBrent Vatne 
onRender(double timestampMs)425c7e4709dSKudo Chien void NativeReanimatedModule::onRender(double timestampMs) {
426a48bc6c0SBrent Vatne   std::vector<FrameCallback> callbacks = frameCallbacks;
427a48bc6c0SBrent Vatne   frameCallbacks.clear();
428c7e4709dSKudo Chien   for (auto &callback : callbacks) {
429a48bc6c0SBrent Vatne     callback(timestampMs);
430a48bc6c0SBrent Vatne   }
431a48bc6c0SBrent Vatne }
432a48bc6c0SBrent Vatne 
registerSensor(jsi::Runtime & rt,const jsi::Value & sensorType,const jsi::Value & interval,const jsi::Value & iosReferenceFrame,const jsi::Value & sensorDataHandler)4333b78aaffSTomasz Sapeta jsi::Value NativeReanimatedModule::registerSensor(
4343b78aaffSTomasz Sapeta     jsi::Runtime &rt,
4353b78aaffSTomasz Sapeta     const jsi::Value &sensorType,
4363b78aaffSTomasz Sapeta     const jsi::Value &interval,
4375f154df9Saleqsio     const jsi::Value &iosReferenceFrame,
4385f154df9Saleqsio     const jsi::Value &sensorDataHandler) {
4393b78aaffSTomasz Sapeta   return animatedSensorModule.registerSensor(
4405f154df9Saleqsio       rt,
4415f154df9Saleqsio       runtimeHelper,
4425f154df9Saleqsio       sensorType,
4435f154df9Saleqsio       interval,
4445f154df9Saleqsio       iosReferenceFrame,
4455f154df9Saleqsio       sensorDataHandler);
4463b78aaffSTomasz Sapeta }
4473b78aaffSTomasz Sapeta 
unregisterSensor(jsi::Runtime & rt,const jsi::Value & sensorId)4483b78aaffSTomasz Sapeta void NativeReanimatedModule::unregisterSensor(
4493b78aaffSTomasz Sapeta     jsi::Runtime &rt,
4503b78aaffSTomasz Sapeta     const jsi::Value &sensorId) {
4513b78aaffSTomasz Sapeta   animatedSensorModule.unregisterSensor(sensorId);
4523b78aaffSTomasz Sapeta }
4533b78aaffSTomasz Sapeta 
cleanupSensors()4545f154df9Saleqsio void NativeReanimatedModule::cleanupSensors() {
4555f154df9Saleqsio   animatedSensorModule.unregisterAllSensors();
4565f154df9Saleqsio }
4575f154df9Saleqsio 
4585f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
isThereAnyLayoutProp(jsi::Runtime & rt,const jsi::Value & props)4595f154df9Saleqsio bool NativeReanimatedModule::isThereAnyLayoutProp(
4605f154df9Saleqsio     jsi::Runtime &rt,
4615f154df9Saleqsio     const jsi::Value &props) {
4625f154df9Saleqsio   const jsi::Array propNames = props.asObject(rt).getPropertyNames(rt);
4635f154df9Saleqsio   for (size_t i = 0; i < propNames.size(rt); ++i) {
4645f154df9Saleqsio     const std::string propName =
4655f154df9Saleqsio         propNames.getValueAtIndex(rt, i).asString(rt).utf8(rt);
4665f154df9Saleqsio     bool isLayoutProp =
4675f154df9Saleqsio         nativePropNames_.find(propName) != nativePropNames_.end();
4685f154df9Saleqsio     if (isLayoutProp) {
4695f154df9Saleqsio       return true;
4705f154df9Saleqsio     }
4715f154df9Saleqsio   }
4725f154df9Saleqsio   return false;
4735f154df9Saleqsio }
4745f154df9Saleqsio #endif // RCT_NEW_ARCH_ENABLED
4755f154df9Saleqsio 
handleEvent(const std::string & eventName,const jsi::Value & payload,double currentTime)4765f154df9Saleqsio bool NativeReanimatedModule::handleEvent(
4775f154df9Saleqsio     const std::string &eventName,
4785f154df9Saleqsio     const jsi::Value &payload,
4795f154df9Saleqsio     double currentTime) {
4805f154df9Saleqsio   onEvent(currentTime, eventName, payload);
4815f154df9Saleqsio 
4825f154df9Saleqsio   // TODO: return true if Reanimated successfully handled the event
4835f154df9Saleqsio   // to avoid sending it to JavaScript
4845f154df9Saleqsio   return false;
4855f154df9Saleqsio }
4865f154df9Saleqsio 
4875f154df9Saleqsio #ifdef RCT_NEW_ARCH_ENABLED
handleRawEvent(const RawEvent & rawEvent,double currentTime)4885f154df9Saleqsio bool NativeReanimatedModule::handleRawEvent(
4895f154df9Saleqsio     const RawEvent &rawEvent,
4905f154df9Saleqsio     double currentTime) {
4915f154df9Saleqsio   const EventTarget *eventTarget = rawEvent.eventTarget.get();
4925f154df9Saleqsio   if (eventTarget == nullptr) {
4935f154df9Saleqsio     // after app reload scrollview is unmounted and its content offset is set to
4945f154df9Saleqsio     // 0 and view is thrown into recycle pool setting content offset triggers
4955f154df9Saleqsio     // scroll event eventTarget is null though, because it's unmounting we can
4965f154df9Saleqsio     // just ignore this event, because it's an event on unmounted component
4975f154df9Saleqsio     return false;
4985f154df9Saleqsio   }
4995f154df9Saleqsio   const std::string &type = rawEvent.type;
5005f154df9Saleqsio   const ValueFactory &payloadFactory = rawEvent.payloadFactory;
5015f154df9Saleqsio 
5025f154df9Saleqsio   int tag = eventTarget->getTag();
5035f154df9Saleqsio   std::string eventType = type;
5045f154df9Saleqsio   if (eventType.rfind("top", 0) == 0) {
5055f154df9Saleqsio     eventType = "on" + eventType.substr(3);
5065f154df9Saleqsio   }
5075f154df9Saleqsio   std::string eventName = std::to_string(tag) + eventType;
5085f154df9Saleqsio   jsi::Runtime &rt = *runtime.get();
5095f154df9Saleqsio   jsi::Value payload = payloadFactory(rt);
5105f154df9Saleqsio 
5115f154df9Saleqsio   auto res = handleEvent(eventName, std::move(payload), currentTime);
5125f154df9Saleqsio   // TODO: we should call performOperations conditionally if event is handled
5135f154df9Saleqsio   // (res == true), but for now handleEvent always returns false. Thankfully,
5145f154df9Saleqsio   // performOperations does not trigger a lot of code if there is nothing to be
5155f154df9Saleqsio   // done so this is fine for now.
5165f154df9Saleqsio   performOperations();
5175f154df9Saleqsio   return res;
5185f154df9Saleqsio }
5195f154df9Saleqsio 
updateProps(jsi::Runtime & rt,const jsi::Value & shadowNodeValue,const jsi::Value & props)5205f154df9Saleqsio void NativeReanimatedModule::updateProps(
5215f154df9Saleqsio     jsi::Runtime &rt,
5225f154df9Saleqsio     const jsi::Value &shadowNodeValue,
5235f154df9Saleqsio     const jsi::Value &props) {
5245f154df9Saleqsio   ShadowNode::Shared shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
5255f154df9Saleqsio 
5265f154df9Saleqsio   // TODO: support multiple surfaces
5275f154df9Saleqsio   surfaceId_ = shadowNode->getSurfaceId();
5285f154df9Saleqsio 
5295f154df9Saleqsio   if (isThereAnyLayoutProp(rt, props)) {
5305f154df9Saleqsio     operationsInBatch_.emplace_back(
5315f154df9Saleqsio         shadowNode, std::make_unique<jsi::Value>(rt, props));
5325f154df9Saleqsio   } else {
5335f154df9Saleqsio     // TODO: batch with layout props changes?
5345f154df9Saleqsio     Tag tag = shadowNode->getTag();
5355f154df9Saleqsio     synchronouslyUpdateUIPropsFunction(rt, tag, props);
5365f154df9Saleqsio   }
5375f154df9Saleqsio }
5385f154df9Saleqsio 
performOperations()5395f154df9Saleqsio void NativeReanimatedModule::performOperations() {
5405f154df9Saleqsio   if (operationsInBatch_.empty()) {
5415f154df9Saleqsio     return;
5425f154df9Saleqsio   }
5435f154df9Saleqsio 
5445f154df9Saleqsio   auto copiedOperationsQueue = std::move(operationsInBatch_);
5455f154df9Saleqsio   operationsInBatch_ =
5465f154df9Saleqsio       std::vector<std::pair<ShadowNode::Shared, std::unique_ptr<jsi::Value>>>();
5475f154df9Saleqsio 
5485f154df9Saleqsio   auto copiedTagsToRemove = std::move(tagsToRemove_);
5495f154df9Saleqsio   tagsToRemove_ = std::vector<Tag>();
5505f154df9Saleqsio 
5515f154df9Saleqsio   react_native_assert(uiManager_ != nullptr);
5525f154df9Saleqsio   const auto &shadowTreeRegistry = uiManager_->getShadowTreeRegistry();
5535f154df9Saleqsio   jsi::Runtime &rt = *runtime.get();
5545f154df9Saleqsio 
5555f154df9Saleqsio   shadowTreeRegistry.visit(surfaceId_, [&](ShadowTree const &shadowTree) {
5565f154df9Saleqsio     auto lock = newestShadowNodesRegistry_->createLock();
5575f154df9Saleqsio 
558*531a852fSaleqsio     shadowTree.commit(
559*531a852fSaleqsio         [&](RootShadowNode const &oldRootShadowNode) {
560*531a852fSaleqsio           auto rootNode =
561*531a852fSaleqsio               oldRootShadowNode.ShadowNode::clone(ShadowNodeFragment{});
5625f154df9Saleqsio 
5635f154df9Saleqsio           ShadowTreeCloner shadowTreeCloner{
5645f154df9Saleqsio               newestShadowNodesRegistry_, uiManager_, surfaceId_};
5655f154df9Saleqsio 
5665f154df9Saleqsio           for (const auto &pair : copiedOperationsQueue) {
5675f154df9Saleqsio             const ShadowNodeFamily &family = pair.first->getFamily();
5685f154df9Saleqsio             react_native_assert(family.getSurfaceId() == surfaceId_);
5695f154df9Saleqsio 
5705f154df9Saleqsio             auto newRootNode = shadowTreeCloner.cloneWithNewProps(
5715f154df9Saleqsio                 rootNode, family, RawProps(rt, *pair.second));
5725f154df9Saleqsio 
5735f154df9Saleqsio             if (newRootNode == nullptr) {
5745f154df9Saleqsio               // this happens when React removed the component but Reanimated
5755f154df9Saleqsio               // still tries to animate it, let's skip update for this specific
5765f154df9Saleqsio               // component
5775f154df9Saleqsio               continue;
5785f154df9Saleqsio             }
5795f154df9Saleqsio             rootNode = newRootNode;
5805f154df9Saleqsio           }
5815f154df9Saleqsio 
5825f154df9Saleqsio           // remove ShadowNodes and its ancestors from NewestShadowNodesRegistry
5835f154df9Saleqsio           for (auto tag : copiedTagsToRemove) {
5845f154df9Saleqsio             newestShadowNodesRegistry_->remove(tag);
5855f154df9Saleqsio           }
5865f154df9Saleqsio 
5875f154df9Saleqsio           shadowTreeCloner.updateYogaChildren();
5885f154df9Saleqsio 
5895f154df9Saleqsio           return std::static_pointer_cast<RootShadowNode>(rootNode);
590*531a852fSaleqsio         },
591*531a852fSaleqsio         {/* default commit options */});
5925f154df9Saleqsio   });
5935f154df9Saleqsio }
5945f154df9Saleqsio 
removeShadowNodeFromRegistry(jsi::Runtime & rt,const jsi::Value & tag)5955f154df9Saleqsio void NativeReanimatedModule::removeShadowNodeFromRegistry(
5965f154df9Saleqsio     jsi::Runtime &rt,
5975f154df9Saleqsio     const jsi::Value &tag) {
5985f154df9Saleqsio   tagsToRemove_.push_back(tag.asNumber());
5995f154df9Saleqsio }
6005f154df9Saleqsio 
dispatchCommand(jsi::Runtime & rt,const jsi::Value & shadowNodeValue,const jsi::Value & commandNameValue,const jsi::Value & argsValue)6015f154df9Saleqsio void NativeReanimatedModule::dispatchCommand(
6025f154df9Saleqsio     jsi::Runtime &rt,
6035f154df9Saleqsio     const jsi::Value &shadowNodeValue,
6045f154df9Saleqsio     const jsi::Value &commandNameValue,
6055f154df9Saleqsio     const jsi::Value &argsValue) {
6065f154df9Saleqsio   ShadowNode::Shared shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
6075f154df9Saleqsio   std::string commandName = stringFromValue(rt, commandNameValue);
6085f154df9Saleqsio   folly::dynamic args = commandArgsFromValue(rt, argsValue);
6095f154df9Saleqsio   uiManager_->dispatchCommand(shadowNode, commandName, args);
6105f154df9Saleqsio }
6115f154df9Saleqsio 
measure(jsi::Runtime & rt,const jsi::Value & shadowNodeValue)6125f154df9Saleqsio jsi::Value NativeReanimatedModule::measure(
6135f154df9Saleqsio     jsi::Runtime &rt,
6145f154df9Saleqsio     const jsi::Value &shadowNodeValue) {
6155f154df9Saleqsio   // based on implementation from UIManagerBinding.cpp
6165f154df9Saleqsio 
6175f154df9Saleqsio   auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
6185f154df9Saleqsio   auto layoutMetrics = uiManager_->getRelativeLayoutMetrics(
6195f154df9Saleqsio       *shadowNode, nullptr, {/* .includeTransform = */ true});
6205f154df9Saleqsio 
6215f154df9Saleqsio   if (layoutMetrics == EmptyLayoutMetrics) {
6225f154df9Saleqsio     // Originally, in this case React Native returns `{0, 0, 0, 0, 0, 0}`, most
6235f154df9Saleqsio     // likely due to the type of measure callback function which accepts just an
6245f154df9Saleqsio     // array of numbers (not null). In Reanimated, `measure` returns
6255f154df9Saleqsio     // `MeasuredDimensions | null`.
6265f154df9Saleqsio     return jsi::Value::null();
6275f154df9Saleqsio   }
6285f154df9Saleqsio   auto newestCloneOfShadowNode =
6295f154df9Saleqsio       uiManager_->getNewestCloneOfShadowNode(*shadowNode);
6305f154df9Saleqsio 
6315f154df9Saleqsio   auto layoutableShadowNode =
6325f154df9Saleqsio       traitCast<LayoutableShadowNode const *>(newestCloneOfShadowNode.get());
6335f154df9Saleqsio   facebook::react::Point originRelativeToParent =
6345f154df9Saleqsio       layoutableShadowNode != nullptr
6355f154df9Saleqsio       ? layoutableShadowNode->getLayoutMetrics().frame.origin
6365f154df9Saleqsio       : facebook::react::Point();
6375f154df9Saleqsio 
6385f154df9Saleqsio   auto frame = layoutMetrics.frame;
6395f154df9Saleqsio 
6405f154df9Saleqsio   jsi::Object result(rt);
6415f154df9Saleqsio   result.setProperty(
6425f154df9Saleqsio       rt, "x", jsi::Value(static_cast<double>(originRelativeToParent.x)));
6435f154df9Saleqsio   result.setProperty(
6445f154df9Saleqsio       rt, "y", jsi::Value(static_cast<double>(originRelativeToParent.y)));
6455f154df9Saleqsio   result.setProperty(
6465f154df9Saleqsio       rt, "width", jsi::Value(static_cast<double>(frame.size.width)));
6475f154df9Saleqsio   result.setProperty(
6485f154df9Saleqsio       rt, "height", jsi::Value(static_cast<double>(frame.size.height)));
6495f154df9Saleqsio   result.setProperty(
6505f154df9Saleqsio       rt, "pageX", jsi::Value(static_cast<double>(frame.origin.x)));
6515f154df9Saleqsio   result.setProperty(
6525f154df9Saleqsio       rt, "pageY", jsi::Value(static_cast<double>(frame.origin.y)));
6535f154df9Saleqsio   return result;
6545f154df9Saleqsio }
6555f154df9Saleqsio 
setUIManager(std::shared_ptr<UIManager> uiManager)6565f154df9Saleqsio void NativeReanimatedModule::setUIManager(
6575f154df9Saleqsio     std::shared_ptr<UIManager> uiManager) {
6585f154df9Saleqsio   uiManager_ = uiManager;
6595f154df9Saleqsio }
6605f154df9Saleqsio 
setNewestShadowNodesRegistry(std::shared_ptr<NewestShadowNodesRegistry> newestShadowNodesRegistry)6615f154df9Saleqsio void NativeReanimatedModule::setNewestShadowNodesRegistry(
6625f154df9Saleqsio     std::shared_ptr<NewestShadowNodesRegistry> newestShadowNodesRegistry) {
6635f154df9Saleqsio   newestShadowNodesRegistry_ = newestShadowNodesRegistry;
6645f154df9Saleqsio }
6655f154df9Saleqsio #endif // RCT_NEW_ARCH_ENABLED
6665f154df9Saleqsio 
subscribeForKeyboardEvents(jsi::Runtime & rt,const jsi::Value & handlerWorklet,const jsi::Value & isStatusBarTranslucent)66704819bfdSŁukasz Kosmaty jsi::Value NativeReanimatedModule::subscribeForKeyboardEvents(
66804819bfdSŁukasz Kosmaty     jsi::Runtime &rt,
6695f154df9Saleqsio     const jsi::Value &handlerWorklet,
6705f154df9Saleqsio     const jsi::Value &isStatusBarTranslucent) {
6715f154df9Saleqsio   auto shareableHandler = extractShareableOrThrow(rt, handlerWorklet);
6725f154df9Saleqsio   return subscribeForKeyboardEventsFunction(
6735f154df9Saleqsio       [=](int keyboardState, int height) {
6745f154df9Saleqsio         jsi::Runtime &rt = *runtimeHelper->uiRuntime();
6755f154df9Saleqsio         auto handler = shareableHandler->getJSValue(rt);
6765f154df9Saleqsio         runtimeHelper->runOnUIGuarded(
6775f154df9Saleqsio             handler, jsi::Value(keyboardState), jsi::Value(height));
6785f154df9Saleqsio       },
6795f154df9Saleqsio       isStatusBarTranslucent.getBool());
68004819bfdSŁukasz Kosmaty }
68104819bfdSŁukasz Kosmaty 
unsubscribeFromKeyboardEvents(jsi::Runtime & rt,const jsi::Value & listenerId)68204819bfdSŁukasz Kosmaty void NativeReanimatedModule::unsubscribeFromKeyboardEvents(
68304819bfdSŁukasz Kosmaty     jsi::Runtime &rt,
68404819bfdSŁukasz Kosmaty     const jsi::Value &listenerId) {
68504819bfdSŁukasz Kosmaty   unsubscribeFromKeyboardEventsFunction(listenerId.asNumber());
68604819bfdSŁukasz Kosmaty }
68704819bfdSŁukasz Kosmaty 
688a48bc6c0SBrent Vatne } // namespace reanimated
689