1 #include "NativeReanimatedModule.h" 2 #include <functional> 3 #include <memory> 4 #include <thread> 5 #include "EventHandlerRegistry.h" 6 #include "FeaturesConfig.h" 7 #include "FrozenObject.h" 8 #include "JSIStoreValueUser.h" 9 #include "Mapper.h" 10 #include "MapperRegistry.h" 11 #include "MutableValue.h" 12 #include "ReanimatedHiddenHeaders.h" 13 #include "RuntimeDecorator.h" 14 #include "ShareableValue.h" 15 #include "WorkletEventHandler.h" 16 17 using namespace facebook; 18 19 namespace reanimated { 20 21 void extractMutables( 22 jsi::Runtime &rt, 23 std::shared_ptr<ShareableValue> sv, 24 std::vector<std::shared_ptr<MutableValue>> &res) { 25 switch (sv->type) { 26 case ValueType::MutableValueType: { 27 auto &mutableValue = ValueWrapper::asMutableValue(sv->valueContainer); 28 res.push_back(mutableValue); 29 break; 30 } 31 case ValueType::FrozenArrayType: 32 for (auto &it : ValueWrapper::asFrozenArray(sv->valueContainer)) { 33 extractMutables(rt, it, res); 34 } 35 break; 36 case ValueType::RemoteObjectType: 37 case ValueType::FrozenObjectType: 38 for (auto &it : ValueWrapper::asFrozenObject(sv->valueContainer)->map) { 39 extractMutables(rt, it.second, res); 40 } 41 break; 42 default: 43 break; 44 } 45 } 46 47 std::vector<std::shared_ptr<MutableValue>> extractMutablesFromArray( 48 jsi::Runtime &rt, 49 const jsi::Array &array, 50 NativeReanimatedModule *module) { 51 std::vector<std::shared_ptr<MutableValue>> res; 52 for (size_t i = 0, size = array.size(rt); i < size; i++) { 53 auto shareable = 54 ShareableValue::adapt(rt, array.getValueAtIndex(rt, i), module); 55 extractMutables(rt, shareable, res); 56 } 57 return res; 58 } 59 60 NativeReanimatedModule::NativeReanimatedModule( 61 std::shared_ptr<CallInvoker> jsInvoker, 62 std::shared_ptr<Scheduler> scheduler, 63 std::shared_ptr<jsi::Runtime> rt, 64 std::shared_ptr<ErrorHandler> errorHandler, 65 std::function<jsi::Value(jsi::Runtime &, const int, const jsi::String &)> 66 propObtainer, 67 std::shared_ptr<LayoutAnimationsProxy> layoutAnimationsProxy, 68 PlatformDepMethodsHolder platformDepMethodsHolder) 69 : NativeReanimatedModuleSpec(jsInvoker), 70 RuntimeManager(rt, errorHandler, scheduler, RuntimeType::UI), 71 mapperRegistry(std::make_shared<MapperRegistry>()), 72 eventHandlerRegistry(std::make_shared<EventHandlerRegistry>()), 73 requestRender(platformDepMethodsHolder.requestRender), 74 propObtainer(propObtainer), 75 animatedSensorModule(platformDepMethodsHolder, this), 76 configurePropsPlatformFunction( 77 platformDepMethodsHolder.configurePropsFunction) { 78 auto requestAnimationFrame = [=](FrameCallback callback) { 79 frameCallbacks.push_back(callback); 80 maybeRequestRender(); 81 }; 82 83 this->layoutAnimationsProxy = layoutAnimationsProxy; 84 85 RuntimeDecorator::decorateUIRuntime( 86 *runtime, 87 platformDepMethodsHolder.updaterFunction, 88 requestAnimationFrame, 89 platformDepMethodsHolder.scrollToFunction, 90 platformDepMethodsHolder.measuringFunction, 91 platformDepMethodsHolder.getCurrentTime, 92 platformDepMethodsHolder.registerSensor, 93 platformDepMethodsHolder.unregisterSensor, 94 platformDepMethodsHolder.setGestureStateFunction, 95 layoutAnimationsProxy); 96 onRenderCallback = [this](double timestampMs) { 97 this->renderRequested = false; 98 this->onRender(timestampMs); 99 }; 100 updaterFunction = platformDepMethodsHolder.updaterFunction; 101 } 102 103 void NativeReanimatedModule::installCoreFunctions( 104 jsi::Runtime &rt, 105 const jsi::Value &valueSetter) { 106 this->valueSetter = ShareableValue::adapt(rt, valueSetter, this); 107 } 108 109 jsi::Value NativeReanimatedModule::makeShareable( 110 jsi::Runtime &rt, 111 const jsi::Value &value) { 112 return ShareableValue::adapt(rt, value, this)->getValue(rt); 113 } 114 115 jsi::Value NativeReanimatedModule::makeMutable( 116 jsi::Runtime &rt, 117 const jsi::Value &value) { 118 return ShareableValue::adapt(rt, value, this, ValueType::MutableValueType) 119 ->getValue(rt); 120 } 121 122 jsi::Value NativeReanimatedModule::makeRemote( 123 jsi::Runtime &rt, 124 const jsi::Value &value) { 125 return ShareableValue::adapt(rt, value, this, ValueType::RemoteObjectType) 126 ->getValue(rt); 127 } 128 129 jsi::Value NativeReanimatedModule::startMapper( 130 jsi::Runtime &rt, 131 const jsi::Value &worklet, 132 const jsi::Value &inputs, 133 const jsi::Value &outputs, 134 const jsi::Value &updater, 135 const jsi::Value &viewDescriptors) { 136 static unsigned long MAPPER_ID = 1; 137 138 unsigned long newMapperId = MAPPER_ID++; 139 auto mapperShareable = ShareableValue::adapt(rt, worklet, this); 140 auto inputMutables = 141 extractMutablesFromArray(rt, inputs.asObject(rt).asArray(rt), this); 142 auto outputMutables = 143 extractMutablesFromArray(rt, outputs.asObject(rt).asArray(rt), this); 144 145 int optimalizationLvl = 0; 146 auto optimalization = 147 updater.asObject(rt).getProperty(rt, "__optimalization"); 148 if (optimalization.isNumber()) { 149 optimalizationLvl = optimalization.asNumber(); 150 } 151 auto updaterSV = ShareableValue::adapt(rt, updater, this); 152 auto viewDescriptorsSV = ShareableValue::adapt(rt, viewDescriptors, this); 153 154 scheduler->scheduleOnUI([=] { 155 auto mapperFunction = 156 mapperShareable->getValue(*runtime).asObject(*runtime).asFunction( 157 *runtime); 158 std::shared_ptr<jsi::Function> mapperFunctionPointer = 159 std::make_shared<jsi::Function>(std::move(mapperFunction)); 160 161 std::shared_ptr<Mapper> mapperPointer = std::make_shared<Mapper>( 162 this, 163 newMapperId, 164 mapperFunctionPointer, 165 inputMutables, 166 outputMutables); 167 if (optimalizationLvl > 0) { 168 mapperPointer->enableFastMode( 169 optimalizationLvl, updaterSV, viewDescriptorsSV); 170 } 171 mapperRegistry->startMapper(mapperPointer); 172 maybeRequestRender(); 173 }); 174 175 return jsi::Value(static_cast<double>(newMapperId)); 176 } 177 178 void NativeReanimatedModule::stopMapper( 179 jsi::Runtime &rt, 180 const jsi::Value &mapperId) { 181 unsigned long id = mapperId.asNumber(); 182 scheduler->scheduleOnUI([=] { 183 mapperRegistry->stopMapper(id); 184 maybeRequestRender(); 185 }); 186 } 187 188 jsi::Value NativeReanimatedModule::registerEventHandler( 189 jsi::Runtime &rt, 190 const jsi::Value &eventHash, 191 const jsi::Value &worklet) { 192 static unsigned long EVENT_HANDLER_ID = 1; 193 194 unsigned long newRegistrationId = EVENT_HANDLER_ID++; 195 auto eventName = eventHash.asString(rt).utf8(rt); 196 auto handlerShareable = ShareableValue::adapt(rt, worklet, this); 197 198 scheduler->scheduleOnUI([=] { 199 auto handlerFunction = 200 handlerShareable->getValue(*runtime).asObject(*runtime).asFunction( 201 *runtime); 202 auto handler = std::make_shared<WorkletEventHandler>( 203 newRegistrationId, eventName, std::move(handlerFunction)); 204 eventHandlerRegistry->registerEventHandler(handler); 205 }); 206 207 return jsi::Value(static_cast<double>(newRegistrationId)); 208 } 209 210 void NativeReanimatedModule::unregisterEventHandler( 211 jsi::Runtime &rt, 212 const jsi::Value ®istrationId) { 213 unsigned long id = registrationId.asNumber(); 214 scheduler->scheduleOnUI( 215 [=] { eventHandlerRegistry->unregisterEventHandler(id); }); 216 } 217 218 jsi::Value NativeReanimatedModule::getViewProp( 219 jsi::Runtime &rt, 220 const jsi::Value &viewTag, 221 const jsi::Value &propName, 222 const jsi::Value &callback) { 223 const int viewTagInt = static_cast<int>(viewTag.asNumber()); 224 std::string propNameStr = propName.asString(rt).utf8(rt); 225 jsi::Function fun = callback.getObject(rt).asFunction(rt); 226 std::shared_ptr<jsi::Function> funPtr = 227 std::make_shared<jsi::Function>(std::move(fun)); 228 229 scheduler->scheduleOnUI([&rt, viewTagInt, funPtr, this, propNameStr]() { 230 const jsi::String propNameValue = 231 jsi::String::createFromUtf8(rt, propNameStr); 232 jsi::Value result = propObtainer(rt, viewTagInt, propNameValue); 233 std::string resultStr = result.asString(rt).utf8(rt); 234 235 scheduler->scheduleOnJS([&rt, resultStr, funPtr]() { 236 const jsi::String resultValue = 237 jsi::String::createFromUtf8(rt, resultStr); 238 funPtr->call(rt, resultValue); 239 }); 240 }); 241 242 return jsi::Value::undefined(); 243 } 244 245 jsi::Value NativeReanimatedModule::enableLayoutAnimations( 246 jsi::Runtime &rt, 247 const jsi::Value &config) { 248 FeaturesConfig::setLayoutAnimationEnabled(config.getBool()); 249 return jsi::Value::undefined(); 250 } 251 252 jsi::Value NativeReanimatedModule::configureProps( 253 jsi::Runtime &rt, 254 const jsi::Value &uiProps, 255 const jsi::Value &nativeProps) { 256 configurePropsPlatformFunction(rt, uiProps, nativeProps); 257 return jsi::Value::undefined(); 258 } 259 260 void NativeReanimatedModule::onEvent( 261 std::string eventName, 262 std::string eventAsString) { 263 try { 264 eventHandlerRegistry->processEvent(*runtime, eventName, eventAsString); 265 mapperRegistry->execute(*runtime); 266 if (mapperRegistry->needRunOnRender()) { 267 maybeRequestRender(); 268 } 269 } catch (std::exception &e) { 270 std::string str = e.what(); 271 this->errorHandler->setError(str); 272 this->errorHandler->raise(); 273 } catch (...) { 274 std::string str = "OnEvent error"; 275 this->errorHandler->setError(str); 276 this->errorHandler->raise(); 277 } 278 } 279 280 bool NativeReanimatedModule::isAnyHandlerWaitingForEvent( 281 std::string eventName) { 282 return eventHandlerRegistry->isAnyHandlerWaitingForEvent(eventName); 283 } 284 285 void NativeReanimatedModule::maybeRequestRender() { 286 if (!renderRequested) { 287 renderRequested = true; 288 requestRender(onRenderCallback, *this->runtime); 289 } 290 } 291 292 void NativeReanimatedModule::onRender(double timestampMs) { 293 try { 294 std::vector<FrameCallback> callbacks = frameCallbacks; 295 frameCallbacks.clear(); 296 for (auto &callback : callbacks) { 297 callback(timestampMs); 298 } 299 mapperRegistry->execute(*runtime); 300 301 if (mapperRegistry->needRunOnRender()) { 302 maybeRequestRender(); 303 } 304 } catch (std::exception &e) { 305 std::string str = e.what(); 306 this->errorHandler->setError(str); 307 this->errorHandler->raise(); 308 } catch (...) { 309 std::string str = "OnRender error"; 310 this->errorHandler->setError(str); 311 this->errorHandler->raise(); 312 } 313 } 314 315 jsi::Value NativeReanimatedModule::registerSensor( 316 jsi::Runtime &rt, 317 const jsi::Value &sensorType, 318 const jsi::Value &interval, 319 const jsi::Value &sensorDataContainer) { 320 return animatedSensorModule.registerSensor( 321 rt, sensorType, interval, sensorDataContainer); 322 } 323 324 void NativeReanimatedModule::unregisterSensor( 325 jsi::Runtime &rt, 326 const jsi::Value &sensorId) { 327 animatedSensorModule.unregisterSensor(sensorId); 328 } 329 330 } // namespace reanimated 331