1*af2ec015STomasz Sapeta #include "NativeReanimatedModule.h"
2*af2ec015STomasz Sapeta
3*af2ec015STomasz Sapeta #ifdef ABI49_0_0RCT_NEW_ARCH_ENABLED
4*af2ec015STomasz Sapeta #include <react/renderer/core/TraitCast.h>
5*af2ec015STomasz Sapeta #include <react/renderer/uimanager/UIManagerBinding.h>
6*af2ec015STomasz Sapeta #include <react/renderer/uimanager/primitives.h>
7*af2ec015STomasz Sapeta #endif
8*af2ec015STomasz Sapeta
9*af2ec015STomasz Sapeta #include <functional>
10*af2ec015STomasz Sapeta #include <memory>
11*af2ec015STomasz Sapeta #include <thread>
12*af2ec015STomasz Sapeta #include <unordered_map>
13*af2ec015STomasz Sapeta
14*af2ec015STomasz Sapeta #ifdef ABI49_0_0RCT_NEW_ARCH_ENABLED
15*af2ec015STomasz Sapeta #include "FabricUtils.h"
16*af2ec015STomasz Sapeta #include "NewestShadowNodesRegistry.h"
17*af2ec015STomasz Sapeta #include "ReanimatedUIManagerBinding.h"
18*af2ec015STomasz Sapeta #include "ShadowTreeCloner.h"
19*af2ec015STomasz Sapeta #endif
20*af2ec015STomasz Sapeta
21*af2ec015STomasz Sapeta #include "EventHandlerRegistry.h"
22*af2ec015STomasz Sapeta #include "FeaturesConfig.h"
23*af2ec015STomasz Sapeta #include "ReanimatedHiddenHeaders.h"
24*af2ec015STomasz Sapeta #include "RuntimeDecorator.h"
25*af2ec015STomasz Sapeta #include "Shareables.h"
26*af2ec015STomasz Sapeta #include "WorkletEventHandler.h"
27*af2ec015STomasz Sapeta
28*af2ec015STomasz Sapeta using namespace ABI49_0_0facebook;
29*af2ec015STomasz Sapeta
30*af2ec015STomasz Sapeta namespace ABI49_0_0reanimated {
31*af2ec015STomasz Sapeta
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)32*af2ec015STomasz Sapeta NativeReanimatedModule::NativeReanimatedModule(
33*af2ec015STomasz Sapeta const std::shared_ptr<CallInvoker> &jsInvoker,
34*af2ec015STomasz Sapeta const std::shared_ptr<Scheduler> &scheduler,
35*af2ec015STomasz Sapeta const std::shared_ptr<jsi::Runtime> &rt,
36*af2ec015STomasz Sapeta const std::shared_ptr<ErrorHandler> &errorHandler,
37*af2ec015STomasz Sapeta #ifdef ABI49_0_0RCT_NEW_ARCH_ENABLED
38*af2ec015STomasz Sapeta // nothing
39*af2ec015STomasz Sapeta #else
40*af2ec015STomasz Sapeta std::function<jsi::Value(jsi::Runtime &, const int, const jsi::String &)>
41*af2ec015STomasz Sapeta propObtainer,
42*af2ec015STomasz Sapeta #endif
43*af2ec015STomasz Sapeta PlatformDepMethodsHolder platformDepMethodsHolder)
44*af2ec015STomasz Sapeta : NativeReanimatedModuleSpec(jsInvoker),
45*af2ec015STomasz Sapeta RuntimeManager(rt, errorHandler, scheduler, RuntimeType::UI),
46*af2ec015STomasz Sapeta eventHandlerRegistry(std::make_unique<EventHandlerRegistry>()),
47*af2ec015STomasz Sapeta requestRender(platformDepMethodsHolder.requestRender),
48*af2ec015STomasz Sapeta #ifdef ABI49_0_0RCT_NEW_ARCH_ENABLED
49*af2ec015STomasz Sapeta // nothing
50*af2ec015STomasz Sapeta #else
51*af2ec015STomasz Sapeta propObtainer(propObtainer),
52*af2ec015STomasz Sapeta #endif
53*af2ec015STomasz Sapeta animatedSensorModule(platformDepMethodsHolder),
54*af2ec015STomasz Sapeta #ifdef ABI49_0_0RCT_NEW_ARCH_ENABLED
55*af2ec015STomasz Sapeta synchronouslyUpdateUIPropsFunction(
56*af2ec015STomasz Sapeta platformDepMethodsHolder.synchronouslyUpdateUIPropsFunction)
57*af2ec015STomasz Sapeta #else
58*af2ec015STomasz Sapeta configurePropsPlatformFunction(
59*af2ec015STomasz Sapeta platformDepMethodsHolder.configurePropsFunction)
60*af2ec015STomasz Sapeta #endif
61*af2ec015STomasz Sapeta {
62*af2ec015STomasz Sapeta auto requestAnimationFrame = [=](jsi::Runtime &rt, const jsi::Value &fn) {
63*af2ec015STomasz Sapeta auto jsFunction = std::make_shared<jsi::Value>(rt, fn);
64*af2ec015STomasz Sapeta frameCallbacks.push_back([=](double timestamp) {
65*af2ec015STomasz Sapeta runtimeHelper->runOnUIGuarded(*jsFunction, jsi::Value(timestamp));
66*af2ec015STomasz Sapeta });
67*af2ec015STomasz Sapeta maybeRequestRender();
68*af2ec015STomasz Sapeta };
69*af2ec015STomasz Sapeta
70*af2ec015STomasz Sapeta auto scheduleOnJS = [this](
71*af2ec015STomasz Sapeta jsi::Runtime &rt,
72*af2ec015STomasz Sapeta const jsi::Value &remoteFun,
73*af2ec015STomasz Sapeta const jsi::Value &argsValue) {
74*af2ec015STomasz Sapeta auto shareableRemoteFun = extractShareableOrThrow<ShareableRemoteFunction>(
75*af2ec015STomasz Sapeta rt,
76*af2ec015STomasz Sapeta remoteFun,
77*af2ec015STomasz Sapeta "Incompatible object passed to scheduleOnJS. It is only allowed to schedule functions defined on the ABI49_0_0React Native JS runtime this way.");
78*af2ec015STomasz Sapeta auto shareableArgs = argsValue.isUndefined()
79*af2ec015STomasz Sapeta ? nullptr
80*af2ec015STomasz Sapeta : extractShareableOrThrow(rt, argsValue);
81*af2ec015STomasz Sapeta auto jsRuntime = this->runtimeHelper->rnRuntime();
82*af2ec015STomasz Sapeta this->scheduler->scheduleOnJS([=] {
83*af2ec015STomasz Sapeta jsi::Runtime &rt = *jsRuntime;
84*af2ec015STomasz Sapeta auto remoteFun = shareableRemoteFun->getJSValue(rt);
85*af2ec015STomasz Sapeta if (shareableArgs == nullptr) {
86*af2ec015STomasz Sapeta // fast path for remote function w/o arguments
87*af2ec015STomasz Sapeta remoteFun.asObject(rt).asFunction(rt).call(rt);
88*af2ec015STomasz Sapeta } else {
89*af2ec015STomasz Sapeta auto argsArray = shareableArgs->getJSValue(rt).asObject(rt).asArray(rt);
90*af2ec015STomasz Sapeta auto argsSize = argsArray.size(rt);
91*af2ec015STomasz Sapeta // number of arguments is typically relatively small so it is ok to
92*af2ec015STomasz Sapeta // to use VLAs here, hence disabling the lint rule
93*af2ec015STomasz Sapeta jsi::Value args[argsSize]; // NOLINT(runtime/arrays)
94*af2ec015STomasz Sapeta for (size_t i = 0; i < argsSize; i++) {
95*af2ec015STomasz Sapeta args[i] = argsArray.getValueAtIndex(rt, i);
96*af2ec015STomasz Sapeta }
97*af2ec015STomasz Sapeta remoteFun.asObject(rt).asFunction(rt).call(rt, args, argsSize);
98*af2ec015STomasz Sapeta }
99*af2ec015STomasz Sapeta });
100*af2ec015STomasz Sapeta };
101*af2ec015STomasz Sapeta
102*af2ec015STomasz Sapeta auto makeShareableClone = [this](jsi::Runtime &rt, const jsi::Value &value) {
103*af2ec015STomasz Sapeta return this->makeShareableClone(rt, value, jsi::Value::undefined());
104*af2ec015STomasz Sapeta };
105*af2ec015STomasz Sapeta
106*af2ec015STomasz Sapeta auto updateDataSynchronously =
107*af2ec015STomasz Sapeta [this](
108*af2ec015STomasz Sapeta jsi::Runtime &rt,
109*af2ec015STomasz Sapeta const jsi::Value &synchronizedDataHolderRef,
110*af2ec015STomasz Sapeta const jsi::Value &newData) {
111*af2ec015STomasz Sapeta return this->updateDataSynchronously(
112*af2ec015STomasz Sapeta rt, synchronizedDataHolderRef, newData);
113*af2ec015STomasz Sapeta };
114*af2ec015STomasz Sapeta
115*af2ec015STomasz Sapeta #ifdef ABI49_0_0RCT_NEW_ARCH_ENABLED
116*af2ec015STomasz Sapeta auto updateProps = [this](
117*af2ec015STomasz Sapeta jsi::Runtime &rt,
118*af2ec015STomasz Sapeta const jsi::Value &shadowNodeValue,
119*af2ec015STomasz Sapeta const jsi::Value &props) {
120*af2ec015STomasz Sapeta this->updateProps(rt, shadowNodeValue, props);
121*af2ec015STomasz Sapeta };
122*af2ec015STomasz Sapeta
123*af2ec015STomasz Sapeta auto removeShadowNodeFromRegistry =
124*af2ec015STomasz Sapeta [this](jsi::Runtime &rt, const jsi::Value &tag) {
125*af2ec015STomasz Sapeta this->removeShadowNodeFromRegistry(rt, tag);
126*af2ec015STomasz Sapeta };
127*af2ec015STomasz Sapeta
128*af2ec015STomasz Sapeta auto measure = [this](jsi::Runtime &rt, const jsi::Value &shadowNodeValue) {
129*af2ec015STomasz Sapeta return this->measure(rt, shadowNodeValue);
130*af2ec015STomasz Sapeta };
131*af2ec015STomasz Sapeta
132*af2ec015STomasz Sapeta auto dispatchCommand = [this](
133*af2ec015STomasz Sapeta jsi::Runtime &rt,
134*af2ec015STomasz Sapeta const jsi::Value &shadowNodeValue,
135*af2ec015STomasz Sapeta const jsi::Value &commandNameValue,
136*af2ec015STomasz Sapeta const jsi::Value &argsValue) {
137*af2ec015STomasz Sapeta this->dispatchCommand(rt, shadowNodeValue, commandNameValue, argsValue);
138*af2ec015STomasz Sapeta };
139*af2ec015STomasz Sapeta #endif
140*af2ec015STomasz Sapeta
141*af2ec015STomasz Sapeta RuntimeDecorator::decorateUIRuntime(
142*af2ec015STomasz Sapeta *runtime,
143*af2ec015STomasz Sapeta #ifdef ABI49_0_0RCT_NEW_ARCH_ENABLED
144*af2ec015STomasz Sapeta updateProps,
145*af2ec015STomasz Sapeta measure,
146*af2ec015STomasz Sapeta removeShadowNodeFromRegistry,
147*af2ec015STomasz Sapeta dispatchCommand,
148*af2ec015STomasz Sapeta #else
149*af2ec015STomasz Sapeta platformDepMethodsHolder.updatePropsFunction,
150*af2ec015STomasz Sapeta platformDepMethodsHolder.measureFunction,
151*af2ec015STomasz Sapeta platformDepMethodsHolder.scrollToFunction,
152*af2ec015STomasz Sapeta #endif
153*af2ec015STomasz Sapeta requestAnimationFrame,
154*af2ec015STomasz Sapeta scheduleOnJS,
155*af2ec015STomasz Sapeta makeShareableClone,
156*af2ec015STomasz Sapeta updateDataSynchronously,
157*af2ec015STomasz Sapeta platformDepMethodsHolder.getCurrentTime,
158*af2ec015STomasz Sapeta platformDepMethodsHolder.setGestureStateFunction,
159*af2ec015STomasz Sapeta platformDepMethodsHolder.progressLayoutAnimation,
160*af2ec015STomasz Sapeta platformDepMethodsHolder.endLayoutAnimation,
161*af2ec015STomasz Sapeta platformDepMethodsHolder.maybeFlushUIUpdatesQueueFunction);
162*af2ec015STomasz Sapeta onRenderCallback = [this](double timestampMs) {
163*af2ec015STomasz Sapeta this->renderRequested = false;
164*af2ec015STomasz Sapeta this->onRender(timestampMs);
165*af2ec015STomasz Sapeta };
166*af2ec015STomasz Sapeta
167*af2ec015STomasz Sapeta #ifdef ABI49_0_0RCT_NEW_ARCH_ENABLED
168*af2ec015STomasz Sapeta // nothing
169*af2ec015STomasz Sapeta #else
170*af2ec015STomasz Sapeta updatePropsFunction = platformDepMethodsHolder.updatePropsFunction;
171*af2ec015STomasz Sapeta #endif
172*af2ec015STomasz Sapeta subscribeForKeyboardEventsFunction =
173*af2ec015STomasz Sapeta platformDepMethodsHolder.subscribeForKeyboardEvents;
174*af2ec015STomasz Sapeta unsubscribeFromKeyboardEventsFunction =
175*af2ec015STomasz Sapeta platformDepMethodsHolder.unsubscribeFromKeyboardEvents;
176*af2ec015STomasz Sapeta }
177*af2ec015STomasz Sapeta
installCoreFunctions(jsi::Runtime & rt,const jsi::Value & callGuard,const jsi::Value & valueUnpacker)178*af2ec015STomasz Sapeta void NativeReanimatedModule::installCoreFunctions(
179*af2ec015STomasz Sapeta jsi::Runtime &rt,
180*af2ec015STomasz Sapeta const jsi::Value &callGuard,
181*af2ec015STomasz Sapeta const jsi::Value &valueUnpacker) {
182*af2ec015STomasz Sapeta if (!runtimeHelper) {
183*af2ec015STomasz Sapeta // initialize runtimeHelper here if not already present. We expect only one
184*af2ec015STomasz Sapeta // instace of the helper to exists.
185*af2ec015STomasz Sapeta runtimeHelper =
186*af2ec015STomasz Sapeta std::make_shared<JSRuntimeHelper>(&rt, this->runtime.get(), scheduler);
187*af2ec015STomasz Sapeta }
188*af2ec015STomasz Sapeta runtimeHelper->callGuard =
189*af2ec015STomasz Sapeta std::make_unique<CoreFunction>(runtimeHelper.get(), callGuard);
190*af2ec015STomasz Sapeta runtimeHelper->valueUnpacker =
191*af2ec015STomasz Sapeta std::make_unique<CoreFunction>(runtimeHelper.get(), valueUnpacker);
192*af2ec015STomasz Sapeta }
193*af2ec015STomasz Sapeta
~NativeReanimatedModule()194*af2ec015STomasz Sapeta NativeReanimatedModule::~NativeReanimatedModule() {
195*af2ec015STomasz Sapeta if (runtimeHelper) {
196*af2ec015STomasz Sapeta runtimeHelper->callGuard = nullptr;
197*af2ec015STomasz Sapeta runtimeHelper->valueUnpacker = nullptr;
198*af2ec015STomasz Sapeta // event handler registry and frame callbacks store some JSI values from UI
199*af2ec015STomasz Sapeta // runtime, so they have to go away before we tear down the runtime
200*af2ec015STomasz Sapeta eventHandlerRegistry.reset();
201*af2ec015STomasz Sapeta frameCallbacks.clear();
202*af2ec015STomasz Sapeta runtime.reset();
203*af2ec015STomasz Sapeta // make sure uiRuntimeDestroyed is set after the runtime is deallocated
204*af2ec015STomasz Sapeta runtimeHelper->uiRuntimeDestroyed = true;
205*af2ec015STomasz Sapeta }
206*af2ec015STomasz Sapeta }
207*af2ec015STomasz Sapeta
scheduleOnUI(jsi::Runtime & rt,const jsi::Value & worklet)208*af2ec015STomasz Sapeta void NativeReanimatedModule::scheduleOnUI(
209*af2ec015STomasz Sapeta jsi::Runtime &rt,
210*af2ec015STomasz Sapeta const jsi::Value &worklet) {
211*af2ec015STomasz Sapeta auto shareableWorklet = extractShareableOrThrow(rt, worklet);
212*af2ec015STomasz Sapeta assert(
213*af2ec015STomasz Sapeta shareableWorklet->valueType() == Shareable::WorkletType &&
214*af2ec015STomasz Sapeta "only worklets can be scheduled to run on UI");
215*af2ec015STomasz Sapeta scheduler->scheduleOnUI([=] {
216*af2ec015STomasz Sapeta jsi::Runtime &rt = *runtimeHelper->uiRuntime();
217*af2ec015STomasz Sapeta auto workletValue = shareableWorklet->getJSValue(rt);
218*af2ec015STomasz Sapeta runtimeHelper->runOnUIGuarded(workletValue);
219*af2ec015STomasz Sapeta });
220*af2ec015STomasz Sapeta }
221*af2ec015STomasz Sapeta
makeSynchronizedDataHolder(jsi::Runtime & rt,const jsi::Value & initialShareable)222*af2ec015STomasz Sapeta jsi::Value NativeReanimatedModule::makeSynchronizedDataHolder(
223*af2ec015STomasz Sapeta jsi::Runtime &rt,
224*af2ec015STomasz Sapeta const jsi::Value &initialShareable) {
225*af2ec015STomasz Sapeta auto dataHolder = std::make_shared<ShareableSynchronizedDataHolder>(
226*af2ec015STomasz Sapeta runtimeHelper, rt, initialShareable);
227*af2ec015STomasz Sapeta return dataHolder->getJSValue(rt);
228*af2ec015STomasz Sapeta }
229*af2ec015STomasz Sapeta
updateDataSynchronously(jsi::Runtime & rt,const jsi::Value & synchronizedDataHolderRef,const jsi::Value & newData)230*af2ec015STomasz Sapeta void NativeReanimatedModule::updateDataSynchronously(
231*af2ec015STomasz Sapeta jsi::Runtime &rt,
232*af2ec015STomasz Sapeta const jsi::Value &synchronizedDataHolderRef,
233*af2ec015STomasz Sapeta const jsi::Value &newData) {
234*af2ec015STomasz Sapeta auto dataHolder = extractShareableOrThrow<ShareableSynchronizedDataHolder>(
235*af2ec015STomasz Sapeta rt, synchronizedDataHolderRef);
236*af2ec015STomasz Sapeta dataHolder->set(rt, newData);
237*af2ec015STomasz Sapeta }
238*af2ec015STomasz Sapeta
getDataSynchronously(jsi::Runtime & rt,const jsi::Value & synchronizedDataHolderRef)239*af2ec015STomasz Sapeta jsi::Value NativeReanimatedModule::getDataSynchronously(
240*af2ec015STomasz Sapeta jsi::Runtime &rt,
241*af2ec015STomasz Sapeta const jsi::Value &synchronizedDataHolderRef) {
242*af2ec015STomasz Sapeta auto dataHolder = extractShareableOrThrow<ShareableSynchronizedDataHolder>(
243*af2ec015STomasz Sapeta rt, synchronizedDataHolderRef);
244*af2ec015STomasz Sapeta return dataHolder->get(rt);
245*af2ec015STomasz Sapeta }
246*af2ec015STomasz Sapeta
makeShareableClone(jsi::Runtime & rt,const jsi::Value & value,const jsi::Value & shouldRetainRemote)247*af2ec015STomasz Sapeta jsi::Value NativeReanimatedModule::makeShareableClone(
248*af2ec015STomasz Sapeta jsi::Runtime &rt,
249*af2ec015STomasz Sapeta const jsi::Value &value,
250*af2ec015STomasz Sapeta const jsi::Value &shouldRetainRemote) {
251*af2ec015STomasz Sapeta std::shared_ptr<Shareable> shareable;
252*af2ec015STomasz Sapeta if (value.isObject()) {
253*af2ec015STomasz Sapeta auto object = value.asObject(rt);
254*af2ec015STomasz Sapeta if (!object.getProperty(rt, "__workletHash").isUndefined()) {
255*af2ec015STomasz Sapeta shareable = std::make_shared<ShareableWorklet>(runtimeHelper, rt, object);
256*af2ec015STomasz Sapeta } else if (!object.getProperty(rt, "__init").isUndefined()) {
257*af2ec015STomasz Sapeta shareable = std::make_shared<ShareableHandle>(runtimeHelper, rt, object);
258*af2ec015STomasz Sapeta } else if (object.isFunction(rt)) {
259*af2ec015STomasz Sapeta auto function = object.asFunction(rt);
260*af2ec015STomasz Sapeta if (function.isHostFunction(rt)) {
261*af2ec015STomasz Sapeta shareable =
262*af2ec015STomasz Sapeta std::make_shared<ShareableHostFunction>(rt, std::move(function));
263*af2ec015STomasz Sapeta } else {
264*af2ec015STomasz Sapeta shareable = std::make_shared<ShareableRemoteFunction>(
265*af2ec015STomasz Sapeta runtimeHelper, rt, std::move(function));
266*af2ec015STomasz Sapeta }
267*af2ec015STomasz Sapeta } else if (object.isArray(rt)) {
268*af2ec015STomasz Sapeta if (shouldRetainRemote.isBool() && shouldRetainRemote.getBool()) {
269*af2ec015STomasz Sapeta shareable = std::make_shared<RetainingShareable<ShareableArray>>(
270*af2ec015STomasz Sapeta runtimeHelper, rt, object.asArray(rt));
271*af2ec015STomasz Sapeta } else {
272*af2ec015STomasz Sapeta shareable = std::make_shared<ShareableArray>(rt, object.asArray(rt));
273*af2ec015STomasz Sapeta }
274*af2ec015STomasz Sapeta } else if (object.isHostObject(rt)) {
275*af2ec015STomasz Sapeta shareable = std::make_shared<ShareableHostObject>(
276*af2ec015STomasz Sapeta runtimeHelper, rt, object.getHostObject(rt));
277*af2ec015STomasz Sapeta } else {
278*af2ec015STomasz Sapeta if (shouldRetainRemote.isBool() && shouldRetainRemote.getBool()) {
279*af2ec015STomasz Sapeta shareable = std::make_shared<RetainingShareable<ShareableObject>>(
280*af2ec015STomasz Sapeta runtimeHelper, rt, object);
281*af2ec015STomasz Sapeta } else {
282*af2ec015STomasz Sapeta shareable = std::make_shared<ShareableObject>(rt, object);
283*af2ec015STomasz Sapeta }
284*af2ec015STomasz Sapeta }
285*af2ec015STomasz Sapeta } else if (value.isString()) {
286*af2ec015STomasz Sapeta shareable = std::make_shared<ShareableString>(value.asString(rt).utf8(rt));
287*af2ec015STomasz Sapeta } else if (value.isUndefined()) {
288*af2ec015STomasz Sapeta shareable = std::make_shared<ShareableScalar>();
289*af2ec015STomasz Sapeta } else if (value.isNull()) {
290*af2ec015STomasz Sapeta shareable = std::make_shared<ShareableScalar>(nullptr);
291*af2ec015STomasz Sapeta } else if (value.isBool()) {
292*af2ec015STomasz Sapeta shareable = std::make_shared<ShareableScalar>(value.getBool());
293*af2ec015STomasz Sapeta } else if (value.isNumber()) {
294*af2ec015STomasz Sapeta shareable = std::make_shared<ShareableScalar>(value.getNumber());
295*af2ec015STomasz Sapeta } else if (value.isSymbol()) {
296*af2ec015STomasz Sapeta // TODO: this is only a placeholder implementation, here we replace symbols
297*af2ec015STomasz Sapeta // with strings in order to make certain objects to be captured. There isn't
298*af2ec015STomasz Sapeta // yet any usecase for using symbols on the UI runtime so it is fine to keep
299*af2ec015STomasz Sapeta // it like this for now.
300*af2ec015STomasz Sapeta shareable =
301*af2ec015STomasz Sapeta std::make_shared<ShareableString>(value.getSymbol(rt).toString(rt));
302*af2ec015STomasz Sapeta } else {
303*af2ec015STomasz Sapeta throw std::runtime_error("attempted to convert an unsupported value type");
304*af2ec015STomasz Sapeta }
305*af2ec015STomasz Sapeta return ShareableJSRef::newHostObject(rt, shareable);
306*af2ec015STomasz Sapeta }
307*af2ec015STomasz Sapeta
registerEventHandler(jsi::Runtime & rt,const jsi::Value & eventHash,const jsi::Value & worklet)308*af2ec015STomasz Sapeta jsi::Value NativeReanimatedModule::registerEventHandler(
309*af2ec015STomasz Sapeta jsi::Runtime &rt,
310*af2ec015STomasz Sapeta const jsi::Value &eventHash,
311*af2ec015STomasz Sapeta const jsi::Value &worklet) {
312*af2ec015STomasz Sapeta static uint64_t EVENT_HANDLER_ID = 1;
313*af2ec015STomasz Sapeta
314*af2ec015STomasz Sapeta uint64_t newRegistrationId = EVENT_HANDLER_ID++;
315*af2ec015STomasz Sapeta auto eventName = eventHash.asString(rt).utf8(rt);
316*af2ec015STomasz Sapeta auto handlerShareable = extractShareableOrThrow(rt, worklet);
317*af2ec015STomasz Sapeta
318*af2ec015STomasz Sapeta scheduler->scheduleOnUI([=] {
319*af2ec015STomasz Sapeta jsi::Runtime &rt = *runtimeHelper->uiRuntime();
320*af2ec015STomasz Sapeta auto handlerFunction = handlerShareable->getJSValue(rt);
321*af2ec015STomasz Sapeta auto handler = std::make_shared<WorkletEventHandler>(
322*af2ec015STomasz Sapeta runtimeHelper,
323*af2ec015STomasz Sapeta newRegistrationId,
324*af2ec015STomasz Sapeta eventName,
325*af2ec015STomasz Sapeta std::move(handlerFunction));
326*af2ec015STomasz Sapeta eventHandlerRegistry->registerEventHandler(std::move(handler));
327*af2ec015STomasz Sapeta });
328*af2ec015STomasz Sapeta
329*af2ec015STomasz Sapeta return jsi::Value(static_cast<double>(newRegistrationId));
330*af2ec015STomasz Sapeta }
331*af2ec015STomasz Sapeta
unregisterEventHandler(jsi::Runtime & rt,const jsi::Value & registrationId)332*af2ec015STomasz Sapeta void NativeReanimatedModule::unregisterEventHandler(
333*af2ec015STomasz Sapeta jsi::Runtime &rt,
334*af2ec015STomasz Sapeta const jsi::Value ®istrationId) {
335*af2ec015STomasz Sapeta uint64_t id = registrationId.asNumber();
336*af2ec015STomasz Sapeta scheduler->scheduleOnUI(
337*af2ec015STomasz Sapeta [=] { eventHandlerRegistry->unregisterEventHandler(id); });
338*af2ec015STomasz Sapeta }
339*af2ec015STomasz Sapeta
getViewProp(jsi::Runtime & rt,const jsi::Value & viewTag,const jsi::Value & propName,const jsi::Value & callback)340*af2ec015STomasz Sapeta jsi::Value NativeReanimatedModule::getViewProp(
341*af2ec015STomasz Sapeta jsi::Runtime &rt,
342*af2ec015STomasz Sapeta const jsi::Value &viewTag,
343*af2ec015STomasz Sapeta const jsi::Value &propName,
344*af2ec015STomasz Sapeta const jsi::Value &callback) {
345*af2ec015STomasz Sapeta const int viewTagInt = static_cast<int>(viewTag.asNumber());
346*af2ec015STomasz Sapeta std::string propNameStr = propName.asString(rt).utf8(rt);
347*af2ec015STomasz Sapeta jsi::Function fun = callback.getObject(rt).asFunction(rt);
348*af2ec015STomasz Sapeta std::shared_ptr<jsi::Function> funPtr =
349*af2ec015STomasz Sapeta std::make_shared<jsi::Function>(std::move(fun));
350*af2ec015STomasz Sapeta
351*af2ec015STomasz Sapeta scheduler->scheduleOnUI([&rt, viewTagInt, funPtr, this, propNameStr]() {
352*af2ec015STomasz Sapeta const jsi::String propNameValue =
353*af2ec015STomasz Sapeta jsi::String::createFromUtf8(rt, propNameStr);
354*af2ec015STomasz Sapeta jsi::Value result = propObtainer(rt, viewTagInt, propNameValue);
355*af2ec015STomasz Sapeta std::string resultStr = result.asString(rt).utf8(rt);
356*af2ec015STomasz Sapeta
357*af2ec015STomasz Sapeta scheduler->scheduleOnJS([&rt, resultStr, funPtr]() {
358*af2ec015STomasz Sapeta const jsi::String resultValue =
359*af2ec015STomasz Sapeta jsi::String::createFromUtf8(rt, resultStr);
360*af2ec015STomasz Sapeta funPtr->call(rt, resultValue);
361*af2ec015STomasz Sapeta });
362*af2ec015STomasz Sapeta });
363*af2ec015STomasz Sapeta
364*af2ec015STomasz Sapeta return jsi::Value::undefined();
365*af2ec015STomasz Sapeta }
366*af2ec015STomasz Sapeta
enableLayoutAnimations(jsi::Runtime & rt,const jsi::Value & config)367*af2ec015STomasz Sapeta jsi::Value NativeReanimatedModule::enableLayoutAnimations(
368*af2ec015STomasz Sapeta jsi::Runtime &rt,
369*af2ec015STomasz Sapeta const jsi::Value &config) {
370*af2ec015STomasz Sapeta FeaturesConfig::setLayoutAnimationEnabled(config.getBool());
371*af2ec015STomasz Sapeta return jsi::Value::undefined();
372*af2ec015STomasz Sapeta }
373*af2ec015STomasz Sapeta
configureProps(jsi::Runtime & rt,const jsi::Value & uiProps,const jsi::Value & nativeProps)374*af2ec015STomasz Sapeta jsi::Value NativeReanimatedModule::configureProps(
375*af2ec015STomasz Sapeta jsi::Runtime &rt,
376*af2ec015STomasz Sapeta const jsi::Value &uiProps,
377*af2ec015STomasz Sapeta const jsi::Value &nativeProps) {
378*af2ec015STomasz Sapeta #ifdef ABI49_0_0RCT_NEW_ARCH_ENABLED
379*af2ec015STomasz Sapeta jsi::Array array = nativeProps.asObject(rt).asArray(rt);
380*af2ec015STomasz Sapeta for (int i = 0; i < array.size(rt); ++i) {
381*af2ec015STomasz Sapeta std::string name = array.getValueAtIndex(rt, i).asString(rt).utf8(rt);
382*af2ec015STomasz Sapeta nativePropNames_.insert(name);
383*af2ec015STomasz Sapeta }
384*af2ec015STomasz Sapeta #else
385*af2ec015STomasz Sapeta configurePropsPlatformFunction(rt, uiProps, nativeProps);
386*af2ec015STomasz Sapeta #endif // ABI49_0_0RCT_NEW_ARCH_ENABLED
387*af2ec015STomasz Sapeta
388*af2ec015STomasz Sapeta return jsi::Value::undefined();
389*af2ec015STomasz Sapeta }
390*af2ec015STomasz Sapeta
configureLayoutAnimation(jsi::Runtime & rt,const jsi::Value & viewTag,const jsi::Value & type,const jsi::Value & sharedTransitionTag,const jsi::Value & config)391*af2ec015STomasz Sapeta jsi::Value NativeReanimatedModule::configureLayoutAnimation(
392*af2ec015STomasz Sapeta jsi::Runtime &rt,
393*af2ec015STomasz Sapeta const jsi::Value &viewTag,
394*af2ec015STomasz Sapeta const jsi::Value &type,
395*af2ec015STomasz Sapeta const jsi::Value &sharedTransitionTag,
396*af2ec015STomasz Sapeta const jsi::Value &config) {
397*af2ec015STomasz Sapeta layoutAnimationsManager_.configureAnimation(
398*af2ec015STomasz Sapeta viewTag.asNumber(),
399*af2ec015STomasz Sapeta static_cast<LayoutAnimationType>(type.asNumber()),
400*af2ec015STomasz Sapeta sharedTransitionTag.asString(rt).utf8(rt),
401*af2ec015STomasz Sapeta extractShareableOrThrow(rt, config));
402*af2ec015STomasz Sapeta return jsi::Value::undefined();
403*af2ec015STomasz Sapeta }
404*af2ec015STomasz Sapeta
onEvent(double eventTimestamp,const std::string & eventName,const jsi::Value & payload)405*af2ec015STomasz Sapeta void NativeReanimatedModule::onEvent(
406*af2ec015STomasz Sapeta double eventTimestamp,
407*af2ec015STomasz Sapeta const std::string &eventName,
408*af2ec015STomasz Sapeta const jsi::Value &payload) {
409*af2ec015STomasz Sapeta eventHandlerRegistry->processEvent(
410*af2ec015STomasz Sapeta *runtime, eventTimestamp, eventName, payload);
411*af2ec015STomasz Sapeta }
412*af2ec015STomasz Sapeta
isAnyHandlerWaitingForEvent(std::string eventName)413*af2ec015STomasz Sapeta bool NativeReanimatedModule::isAnyHandlerWaitingForEvent(
414*af2ec015STomasz Sapeta std::string eventName) {
415*af2ec015STomasz Sapeta return eventHandlerRegistry->isAnyHandlerWaitingForEvent(eventName);
416*af2ec015STomasz Sapeta }
417*af2ec015STomasz Sapeta
maybeRequestRender()418*af2ec015STomasz Sapeta void NativeReanimatedModule::maybeRequestRender() {
419*af2ec015STomasz Sapeta if (!renderRequested) {
420*af2ec015STomasz Sapeta renderRequested = true;
421*af2ec015STomasz Sapeta requestRender(onRenderCallback, *this->runtime);
422*af2ec015STomasz Sapeta }
423*af2ec015STomasz Sapeta }
424*af2ec015STomasz Sapeta
onRender(double timestampMs)425*af2ec015STomasz Sapeta void NativeReanimatedModule::onRender(double timestampMs) {
426*af2ec015STomasz Sapeta std::vector<FrameCallback> callbacks = frameCallbacks;
427*af2ec015STomasz Sapeta frameCallbacks.clear();
428*af2ec015STomasz Sapeta for (auto &callback : callbacks) {
429*af2ec015STomasz Sapeta callback(timestampMs);
430*af2ec015STomasz Sapeta }
431*af2ec015STomasz Sapeta }
432*af2ec015STomasz Sapeta
registerSensor(jsi::Runtime & rt,const jsi::Value & sensorType,const jsi::Value & interval,const jsi::Value & iosReferenceFrame,const jsi::Value & sensorDataHandler)433*af2ec015STomasz Sapeta jsi::Value NativeReanimatedModule::registerSensor(
434*af2ec015STomasz Sapeta jsi::Runtime &rt,
435*af2ec015STomasz Sapeta const jsi::Value &sensorType,
436*af2ec015STomasz Sapeta const jsi::Value &interval,
437*af2ec015STomasz Sapeta const jsi::Value &iosReferenceFrame,
438*af2ec015STomasz Sapeta const jsi::Value &sensorDataHandler) {
439*af2ec015STomasz Sapeta return animatedSensorModule.registerSensor(
440*af2ec015STomasz Sapeta rt,
441*af2ec015STomasz Sapeta runtimeHelper,
442*af2ec015STomasz Sapeta sensorType,
443*af2ec015STomasz Sapeta interval,
444*af2ec015STomasz Sapeta iosReferenceFrame,
445*af2ec015STomasz Sapeta sensorDataHandler);
446*af2ec015STomasz Sapeta }
447*af2ec015STomasz Sapeta
unregisterSensor(jsi::Runtime & rt,const jsi::Value & sensorId)448*af2ec015STomasz Sapeta void NativeReanimatedModule::unregisterSensor(
449*af2ec015STomasz Sapeta jsi::Runtime &rt,
450*af2ec015STomasz Sapeta const jsi::Value &sensorId) {
451*af2ec015STomasz Sapeta animatedSensorModule.unregisterSensor(sensorId);
452*af2ec015STomasz Sapeta }
453*af2ec015STomasz Sapeta
cleanupSensors()454*af2ec015STomasz Sapeta void NativeReanimatedModule::cleanupSensors() {
455*af2ec015STomasz Sapeta animatedSensorModule.unregisterAllSensors();
456*af2ec015STomasz Sapeta }
457*af2ec015STomasz Sapeta
458*af2ec015STomasz Sapeta #ifdef ABI49_0_0RCT_NEW_ARCH_ENABLED
isThereAnyLayoutProp(jsi::Runtime & rt,const jsi::Value & props)459*af2ec015STomasz Sapeta bool NativeReanimatedModule::isThereAnyLayoutProp(
460*af2ec015STomasz Sapeta jsi::Runtime &rt,
461*af2ec015STomasz Sapeta const jsi::Value &props) {
462*af2ec015STomasz Sapeta const jsi::Array propNames = props.asObject(rt).getPropertyNames(rt);
463*af2ec015STomasz Sapeta for (size_t i = 0; i < propNames.size(rt); ++i) {
464*af2ec015STomasz Sapeta const std::string propName =
465*af2ec015STomasz Sapeta propNames.getValueAtIndex(rt, i).asString(rt).utf8(rt);
466*af2ec015STomasz Sapeta bool isLayoutProp =
467*af2ec015STomasz Sapeta nativePropNames_.find(propName) != nativePropNames_.end();
468*af2ec015STomasz Sapeta if (isLayoutProp) {
469*af2ec015STomasz Sapeta return true;
470*af2ec015STomasz Sapeta }
471*af2ec015STomasz Sapeta }
472*af2ec015STomasz Sapeta return false;
473*af2ec015STomasz Sapeta }
474*af2ec015STomasz Sapeta #endif // ABI49_0_0RCT_NEW_ARCH_ENABLED
475*af2ec015STomasz Sapeta
handleEvent(const std::string & eventName,const jsi::Value & payload,double currentTime)476*af2ec015STomasz Sapeta bool NativeReanimatedModule::handleEvent(
477*af2ec015STomasz Sapeta const std::string &eventName,
478*af2ec015STomasz Sapeta const jsi::Value &payload,
479*af2ec015STomasz Sapeta double currentTime) {
480*af2ec015STomasz Sapeta onEvent(currentTime, eventName, payload);
481*af2ec015STomasz Sapeta
482*af2ec015STomasz Sapeta // TODO: return true if Reanimated successfully handled the event
483*af2ec015STomasz Sapeta // to avoid sending it to JavaScript
484*af2ec015STomasz Sapeta return false;
485*af2ec015STomasz Sapeta }
486*af2ec015STomasz Sapeta
487*af2ec015STomasz Sapeta #ifdef ABI49_0_0RCT_NEW_ARCH_ENABLED
handleRawEvent(const RawEvent & rawEvent,double currentTime)488*af2ec015STomasz Sapeta bool NativeReanimatedModule::handleRawEvent(
489*af2ec015STomasz Sapeta const RawEvent &rawEvent,
490*af2ec015STomasz Sapeta double currentTime) {
491*af2ec015STomasz Sapeta const EventTarget *eventTarget = rawEvent.eventTarget.get();
492*af2ec015STomasz Sapeta if (eventTarget == nullptr) {
493*af2ec015STomasz Sapeta // after app reload scrollview is unmounted and its content offset is set to
494*af2ec015STomasz Sapeta // 0 and view is thrown into recycle pool setting content offset triggers
495*af2ec015STomasz Sapeta // scroll event eventTarget is null though, because it's unmounting we can
496*af2ec015STomasz Sapeta // just ignore this event, because it's an event on unmounted component
497*af2ec015STomasz Sapeta return false;
498*af2ec015STomasz Sapeta }
499*af2ec015STomasz Sapeta const std::string &type = rawEvent.type;
500*af2ec015STomasz Sapeta const ValueFactory &payloadFactory = rawEvent.payloadFactory;
501*af2ec015STomasz Sapeta
502*af2ec015STomasz Sapeta int tag = eventTarget->getTag();
503*af2ec015STomasz Sapeta std::string eventType = type;
504*af2ec015STomasz Sapeta if (eventType.rfind("top", 0) == 0) {
505*af2ec015STomasz Sapeta eventType = "on" + eventType.substr(3);
506*af2ec015STomasz Sapeta }
507*af2ec015STomasz Sapeta std::string eventName = std::to_string(tag) + eventType;
508*af2ec015STomasz Sapeta jsi::Runtime &rt = *runtime.get();
509*af2ec015STomasz Sapeta jsi::Value payload = payloadFactory(rt);
510*af2ec015STomasz Sapeta
511*af2ec015STomasz Sapeta auto res = handleEvent(eventName, std::move(payload), currentTime);
512*af2ec015STomasz Sapeta // TODO: we should call performOperations conditionally if event is handled
513*af2ec015STomasz Sapeta // (res == true), but for now handleEvent always returns false. Thankfully,
514*af2ec015STomasz Sapeta // performOperations does not trigger a lot of code if there is nothing to be
515*af2ec015STomasz Sapeta // done so this is fine for now.
516*af2ec015STomasz Sapeta performOperations();
517*af2ec015STomasz Sapeta return res;
518*af2ec015STomasz Sapeta }
519*af2ec015STomasz Sapeta
updateProps(jsi::Runtime & rt,const jsi::Value & shadowNodeValue,const jsi::Value & props)520*af2ec015STomasz Sapeta void NativeReanimatedModule::updateProps(
521*af2ec015STomasz Sapeta jsi::Runtime &rt,
522*af2ec015STomasz Sapeta const jsi::Value &shadowNodeValue,
523*af2ec015STomasz Sapeta const jsi::Value &props) {
524*af2ec015STomasz Sapeta ShadowNode::Shared shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
525*af2ec015STomasz Sapeta
526*af2ec015STomasz Sapeta // TODO: support multiple surfaces
527*af2ec015STomasz Sapeta surfaceId_ = shadowNode->getSurfaceId();
528*af2ec015STomasz Sapeta
529*af2ec015STomasz Sapeta if (isThereAnyLayoutProp(rt, props)) {
530*af2ec015STomasz Sapeta operationsInBatch_.emplace_back(
531*af2ec015STomasz Sapeta shadowNode, std::make_unique<jsi::Value>(rt, props));
532*af2ec015STomasz Sapeta } else {
533*af2ec015STomasz Sapeta // TODO: batch with layout props changes?
534*af2ec015STomasz Sapeta Tag tag = shadowNode->getTag();
535*af2ec015STomasz Sapeta synchronouslyUpdateUIPropsFunction(rt, tag, props);
536*af2ec015STomasz Sapeta }
537*af2ec015STomasz Sapeta }
538*af2ec015STomasz Sapeta
performOperations()539*af2ec015STomasz Sapeta void NativeReanimatedModule::performOperations() {
540*af2ec015STomasz Sapeta if (operationsInBatch_.empty()) {
541*af2ec015STomasz Sapeta return;
542*af2ec015STomasz Sapeta }
543*af2ec015STomasz Sapeta
544*af2ec015STomasz Sapeta auto copiedOperationsQueue = std::move(operationsInBatch_);
545*af2ec015STomasz Sapeta operationsInBatch_ =
546*af2ec015STomasz Sapeta std::vector<std::pair<ShadowNode::Shared, std::unique_ptr<jsi::Value>>>();
547*af2ec015STomasz Sapeta
548*af2ec015STomasz Sapeta auto copiedTagsToRemove = std::move(tagsToRemove_);
549*af2ec015STomasz Sapeta tagsToRemove_ = std::vector<Tag>();
550*af2ec015STomasz Sapeta
551*af2ec015STomasz Sapeta react_native_assert(uiManager_ != nullptr);
552*af2ec015STomasz Sapeta const auto &shadowTreeRegistry = uiManager_->getShadowTreeRegistry();
553*af2ec015STomasz Sapeta jsi::Runtime &rt = *runtime.get();
554*af2ec015STomasz Sapeta
555*af2ec015STomasz Sapeta shadowTreeRegistry.visit(surfaceId_, [&](ShadowTree const &shadowTree) {
556*af2ec015STomasz Sapeta auto lock = newestShadowNodesRegistry_->createLock();
557*af2ec015STomasz Sapeta
558*af2ec015STomasz Sapeta shadowTree.commit(
559*af2ec015STomasz Sapeta [&](RootShadowNode const &oldRootShadowNode) {
560*af2ec015STomasz Sapeta auto rootNode =
561*af2ec015STomasz Sapeta oldRootShadowNode.ShadowNode::clone(ShadowNodeFragment{});
562*af2ec015STomasz Sapeta
563*af2ec015STomasz Sapeta ShadowTreeCloner shadowTreeCloner{
564*af2ec015STomasz Sapeta newestShadowNodesRegistry_, uiManager_, surfaceId_};
565*af2ec015STomasz Sapeta
566*af2ec015STomasz Sapeta for (const auto &pair : copiedOperationsQueue) {
567*af2ec015STomasz Sapeta const ShadowNodeFamily &family = pair.first->getFamily();
568*af2ec015STomasz Sapeta react_native_assert(family.getSurfaceId() == surfaceId_);
569*af2ec015STomasz Sapeta
570*af2ec015STomasz Sapeta auto newRootNode = shadowTreeCloner.cloneWithNewProps(
571*af2ec015STomasz Sapeta rootNode, family, RawProps(rt, *pair.second));
572*af2ec015STomasz Sapeta
573*af2ec015STomasz Sapeta if (newRootNode == nullptr) {
574*af2ec015STomasz Sapeta // this happens when ABI49_0_0React removed the component but Reanimated
575*af2ec015STomasz Sapeta // still tries to animate it, let's skip update for this specific
576*af2ec015STomasz Sapeta // component
577*af2ec015STomasz Sapeta continue;
578*af2ec015STomasz Sapeta }
579*af2ec015STomasz Sapeta rootNode = newRootNode;
580*af2ec015STomasz Sapeta }
581*af2ec015STomasz Sapeta
582*af2ec015STomasz Sapeta // remove ShadowNodes and its ancestors from NewestShadowNodesRegistry
583*af2ec015STomasz Sapeta for (auto tag : copiedTagsToRemove) {
584*af2ec015STomasz Sapeta newestShadowNodesRegistry_->remove(tag);
585*af2ec015STomasz Sapeta }
586*af2ec015STomasz Sapeta
587*af2ec015STomasz Sapeta shadowTreeCloner.updateYogaChildren();
588*af2ec015STomasz Sapeta
589*af2ec015STomasz Sapeta return std::static_pointer_cast<RootShadowNode>(rootNode);
590*af2ec015STomasz Sapeta },
591*af2ec015STomasz Sapeta {/* default commit options */});
592*af2ec015STomasz Sapeta });
593*af2ec015STomasz Sapeta }
594*af2ec015STomasz Sapeta
removeShadowNodeFromRegistry(jsi::Runtime & rt,const jsi::Value & tag)595*af2ec015STomasz Sapeta void NativeReanimatedModule::removeShadowNodeFromRegistry(
596*af2ec015STomasz Sapeta jsi::Runtime &rt,
597*af2ec015STomasz Sapeta const jsi::Value &tag) {
598*af2ec015STomasz Sapeta tagsToRemove_.push_back(tag.asNumber());
599*af2ec015STomasz Sapeta }
600*af2ec015STomasz Sapeta
dispatchCommand(jsi::Runtime & rt,const jsi::Value & shadowNodeValue,const jsi::Value & commandNameValue,const jsi::Value & argsValue)601*af2ec015STomasz Sapeta void NativeReanimatedModule::dispatchCommand(
602*af2ec015STomasz Sapeta jsi::Runtime &rt,
603*af2ec015STomasz Sapeta const jsi::Value &shadowNodeValue,
604*af2ec015STomasz Sapeta const jsi::Value &commandNameValue,
605*af2ec015STomasz Sapeta const jsi::Value &argsValue) {
606*af2ec015STomasz Sapeta ShadowNode::Shared shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
607*af2ec015STomasz Sapeta std::string commandName = stringFromValue(rt, commandNameValue);
608*af2ec015STomasz Sapeta folly::dynamic args = commandArgsFromValue(rt, argsValue);
609*af2ec015STomasz Sapeta uiManager_->dispatchCommand(shadowNode, commandName, args);
610*af2ec015STomasz Sapeta }
611*af2ec015STomasz Sapeta
measure(jsi::Runtime & rt,const jsi::Value & shadowNodeValue)612*af2ec015STomasz Sapeta jsi::Value NativeReanimatedModule::measure(
613*af2ec015STomasz Sapeta jsi::Runtime &rt,
614*af2ec015STomasz Sapeta const jsi::Value &shadowNodeValue) {
615*af2ec015STomasz Sapeta // based on implementation from UIManagerBinding.cpp
616*af2ec015STomasz Sapeta
617*af2ec015STomasz Sapeta auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
618*af2ec015STomasz Sapeta auto layoutMetrics = uiManager_->getRelativeLayoutMetrics(
619*af2ec015STomasz Sapeta *shadowNode, nullptr, {/* .includeTransform = */ true});
620*af2ec015STomasz Sapeta
621*af2ec015STomasz Sapeta if (layoutMetrics == EmptyLayoutMetrics) {
622*af2ec015STomasz Sapeta // Originally, in this case ABI49_0_0React Native returns `{0, 0, 0, 0, 0, 0}`, most
623*af2ec015STomasz Sapeta // likely due to the type of measure callback function which accepts just an
624*af2ec015STomasz Sapeta // array of numbers (not null). In Reanimated, `measure` returns
625*af2ec015STomasz Sapeta // `MeasuredDimensions | null`.
626*af2ec015STomasz Sapeta return jsi::Value::null();
627*af2ec015STomasz Sapeta }
628*af2ec015STomasz Sapeta auto newestCloneOfShadowNode =
629*af2ec015STomasz Sapeta uiManager_->getNewestCloneOfShadowNode(*shadowNode);
630*af2ec015STomasz Sapeta
631*af2ec015STomasz Sapeta auto layoutableShadowNode =
632*af2ec015STomasz Sapeta traitCast<LayoutableShadowNode const *>(newestCloneOfShadowNode.get());
633*af2ec015STomasz Sapeta ABI49_0_0facebook::ABI49_0_0React::Point originRelativeToParent =
634*af2ec015STomasz Sapeta layoutableShadowNode != nullptr
635*af2ec015STomasz Sapeta ? layoutableShadowNode->getLayoutMetrics().frame.origin
636*af2ec015STomasz Sapeta : ABI49_0_0facebook::ABI49_0_0React::Point();
637*af2ec015STomasz Sapeta
638*af2ec015STomasz Sapeta auto frame = layoutMetrics.frame;
639*af2ec015STomasz Sapeta
640*af2ec015STomasz Sapeta jsi::Object result(rt);
641*af2ec015STomasz Sapeta result.setProperty(
642*af2ec015STomasz Sapeta rt, "x", jsi::Value(static_cast<double>(originRelativeToParent.x)));
643*af2ec015STomasz Sapeta result.setProperty(
644*af2ec015STomasz Sapeta rt, "y", jsi::Value(static_cast<double>(originRelativeToParent.y)));
645*af2ec015STomasz Sapeta result.setProperty(
646*af2ec015STomasz Sapeta rt, "width", jsi::Value(static_cast<double>(frame.size.width)));
647*af2ec015STomasz Sapeta result.setProperty(
648*af2ec015STomasz Sapeta rt, "height", jsi::Value(static_cast<double>(frame.size.height)));
649*af2ec015STomasz Sapeta result.setProperty(
650*af2ec015STomasz Sapeta rt, "pageX", jsi::Value(static_cast<double>(frame.origin.x)));
651*af2ec015STomasz Sapeta result.setProperty(
652*af2ec015STomasz Sapeta rt, "pageY", jsi::Value(static_cast<double>(frame.origin.y)));
653*af2ec015STomasz Sapeta return result;
654*af2ec015STomasz Sapeta }
655*af2ec015STomasz Sapeta
setUIManager(std::shared_ptr<UIManager> uiManager)656*af2ec015STomasz Sapeta void NativeReanimatedModule::setUIManager(
657*af2ec015STomasz Sapeta std::shared_ptr<UIManager> uiManager) {
658*af2ec015STomasz Sapeta uiManager_ = uiManager;
659*af2ec015STomasz Sapeta }
660*af2ec015STomasz Sapeta
setNewestShadowNodesRegistry(std::shared_ptr<NewestShadowNodesRegistry> newestShadowNodesRegistry)661*af2ec015STomasz Sapeta void NativeReanimatedModule::setNewestShadowNodesRegistry(
662*af2ec015STomasz Sapeta std::shared_ptr<NewestShadowNodesRegistry> newestShadowNodesRegistry) {
663*af2ec015STomasz Sapeta newestShadowNodesRegistry_ = newestShadowNodesRegistry;
664*af2ec015STomasz Sapeta }
665*af2ec015STomasz Sapeta #endif // ABI49_0_0RCT_NEW_ARCH_ENABLED
666*af2ec015STomasz Sapeta
subscribeForKeyboardEvents(jsi::Runtime & rt,const jsi::Value & handlerWorklet,const jsi::Value & isStatusBarTranslucent)667*af2ec015STomasz Sapeta jsi::Value NativeReanimatedModule::subscribeForKeyboardEvents(
668*af2ec015STomasz Sapeta jsi::Runtime &rt,
669*af2ec015STomasz Sapeta const jsi::Value &handlerWorklet,
670*af2ec015STomasz Sapeta const jsi::Value &isStatusBarTranslucent) {
671*af2ec015STomasz Sapeta auto shareableHandler = extractShareableOrThrow(rt, handlerWorklet);
672*af2ec015STomasz Sapeta return subscribeForKeyboardEventsFunction(
673*af2ec015STomasz Sapeta [=](int keyboardState, int height) {
674*af2ec015STomasz Sapeta jsi::Runtime &rt = *runtimeHelper->uiRuntime();
675*af2ec015STomasz Sapeta auto handler = shareableHandler->getJSValue(rt);
676*af2ec015STomasz Sapeta runtimeHelper->runOnUIGuarded(
677*af2ec015STomasz Sapeta handler, jsi::Value(keyboardState), jsi::Value(height));
678*af2ec015STomasz Sapeta },
679*af2ec015STomasz Sapeta isStatusBarTranslucent.getBool());
680*af2ec015STomasz Sapeta }
681*af2ec015STomasz Sapeta
unsubscribeFromKeyboardEvents(jsi::Runtime & rt,const jsi::Value & listenerId)682*af2ec015STomasz Sapeta void NativeReanimatedModule::unsubscribeFromKeyboardEvents(
683*af2ec015STomasz Sapeta jsi::Runtime &rt,
684*af2ec015STomasz Sapeta const jsi::Value &listenerId) {
685*af2ec015STomasz Sapeta unsubscribeFromKeyboardEventsFunction(listenerId.asNumber());
686*af2ec015STomasz Sapeta }
687*af2ec015STomasz Sapeta
688*af2ec015STomasz Sapeta } // namespace reanimated
689