1 #include "NativeReanimatedModule.h" 2 #include "ShareableValue.h" 3 #include "MapperRegistry.h" 4 #include "Mapper.h" 5 #include "RuntimeDecorator.h" 6 #include "EventHandlerRegistry.h" 7 #include "WorkletEventHandler.h" 8 #include "FrozenObject.h" 9 #include <functional> 10 #include <thread> 11 #include <memory> 12 #include "JSIStoreValueUser.h" 13 14 using namespace facebook; 15 16 namespace reanimated 17 { 18 19 void extractMutables(jsi::Runtime &rt, 20 std::shared_ptr<ShareableValue> sv, 21 std::vector<std::shared_ptr<MutableValue>> &res) 22 { 23 switch (sv->type) 24 { 25 case ValueType::MutableValueType: { 26 auto& mutableValue = ValueWrapper::asMutableValue(sv->valueContainer); 27 res.push_back(mutableValue); 28 break; 29 } 30 case ValueType::FrozenArrayType: 31 for (auto &it : ValueWrapper::asFrozenArray(sv->valueContainer)) 32 { 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 { 40 extractMutables(rt, it.second, res); 41 } 42 break; 43 default: 44 break; 45 } 46 } 47 48 std::vector<std::shared_ptr<MutableValue>> extractMutablesFromArray(jsi::Runtime &rt, const jsi::Array &array, NativeReanimatedModule *module) 49 { 50 std::vector<std::shared_ptr<MutableValue>> res; 51 for (size_t i = 0, size = array.size(rt); i < size; i++) 52 { 53 auto shareable = ShareableValue::adapt(rt, array.getValueAtIndex(rt, i), module); 54 extractMutables(rt, shareable, res); 55 } 56 return res; 57 } 58 59 NativeReanimatedModule::NativeReanimatedModule(std::shared_ptr<CallInvoker> jsInvoker, 60 std::shared_ptr<Scheduler> scheduler, 61 std::unique_ptr<jsi::Runtime> rt, 62 std::shared_ptr<ErrorHandler> errorHandler, 63 std::function<jsi::Value(jsi::Runtime &, const int, const jsi::String &)> propObtainer, 64 PlatformDepMethodsHolder platformDepMethodsHolder) : 65 NativeReanimatedModuleSpec(jsInvoker), 66 RuntimeManager(std::move(rt), errorHandler, scheduler), 67 mapperRegistry(std::make_shared<MapperRegistry>()), 68 eventHandlerRegistry(std::make_shared<EventHandlerRegistry>()), 69 requestRender(platformDepMethodsHolder.requestRender), 70 propObtainer(propObtainer) 71 { 72 73 auto requestAnimationFrame = [=](FrameCallback callback) { 74 frameCallbacks.push_back(callback); 75 maybeRequestRender(); 76 }; 77 RuntimeDecorator::decorateUIRuntime(*runtime, 78 platformDepMethodsHolder.updaterFunction, 79 requestAnimationFrame, 80 platformDepMethodsHolder.scrollToFunction, 81 platformDepMethodsHolder.measuringFunction, 82 platformDepMethodsHolder.getCurrentTime); 83 } 84 85 void NativeReanimatedModule::installCoreFunctions(jsi::Runtime &rt, const jsi::Value &valueSetter) 86 { 87 this->valueSetter = ShareableValue::adapt(rt, valueSetter, this); 88 } 89 90 jsi::Value NativeReanimatedModule::makeShareable(jsi::Runtime &rt, const jsi::Value &value) 91 { 92 return ShareableValue::adapt(rt, value, this)->getValue(rt); 93 } 94 95 jsi::Value NativeReanimatedModule::makeMutable(jsi::Runtime &rt, const jsi::Value &value) 96 { 97 return ShareableValue::adapt(rt, value, this, ValueType::MutableValueType)->getValue(rt); 98 } 99 100 jsi::Value NativeReanimatedModule::makeRemote(jsi::Runtime &rt, const jsi::Value &value) 101 { 102 return ShareableValue::adapt(rt, value, this, ValueType::RemoteObjectType)->getValue(rt); 103 } 104 105 jsi::Value NativeReanimatedModule::startMapper(jsi::Runtime &rt, const jsi::Value &worklet, const jsi::Value &inputs, const jsi::Value &outputs) 106 { 107 static unsigned long MAPPER_ID = 1; 108 109 unsigned long newMapperId = MAPPER_ID++; 110 auto mapperShareable = ShareableValue::adapt(rt, worklet, this); 111 auto inputMutables = extractMutablesFromArray(rt, inputs.asObject(rt).asArray(rt), this); 112 auto outputMutables = extractMutablesFromArray(rt, outputs.asObject(rt).asArray(rt), this); 113 114 scheduler->scheduleOnUI([=] { 115 auto mapperFunction = mapperShareable->getValue(*runtime).asObject(*runtime).asFunction(*runtime); 116 std::shared_ptr<jsi::Function> mapperFunctionPointer = std::make_shared<jsi::Function>(std::move(mapperFunction)); 117 std::shared_ptr<Mapper> mapperPointer = std::make_shared<Mapper>(this, newMapperId, mapperFunctionPointer, inputMutables, outputMutables); 118 mapperRegistry->startMapper(mapperPointer); 119 maybeRequestRender(); 120 }); 121 122 return jsi::Value((double)newMapperId); 123 } 124 125 void NativeReanimatedModule::stopMapper(jsi::Runtime &rt, const jsi::Value &mapperId) 126 { 127 unsigned long id = mapperId.asNumber(); 128 scheduler->scheduleOnUI([=] { 129 mapperRegistry->stopMapper(id); 130 maybeRequestRender(); 131 }); 132 } 133 134 jsi::Value NativeReanimatedModule::registerEventHandler(jsi::Runtime &rt, const jsi::Value &eventHash, const jsi::Value &worklet) 135 { 136 static unsigned long EVENT_HANDLER_ID = 1; 137 138 unsigned long newRegistrationId = EVENT_HANDLER_ID++; 139 auto eventName = eventHash.asString(rt).utf8(rt); 140 auto handlerShareable = ShareableValue::adapt(rt, worklet, this); 141 142 scheduler->scheduleOnUI([=] { 143 auto handlerFunction = handlerShareable->getValue(*runtime).asObject(*runtime).asFunction(*runtime); 144 auto handler = std::make_shared<WorkletEventHandler>(newRegistrationId, eventName, std::move(handlerFunction)); 145 eventHandlerRegistry->registerEventHandler(handler); 146 }); 147 148 return jsi::Value((double)newRegistrationId); 149 } 150 151 void NativeReanimatedModule::unregisterEventHandler(jsi::Runtime &rt, const jsi::Value ®istrationId) 152 { 153 unsigned long id = registrationId.asNumber(); 154 scheduler->scheduleOnUI([=] { 155 eventHandlerRegistry->unregisterEventHandler(id); 156 }); 157 } 158 159 jsi::Value NativeReanimatedModule::getViewProp(jsi::Runtime &rt, const jsi::Value &viewTag, const jsi::Value &propName, const jsi::Value &callback) 160 { 161 162 const int viewTagInt = (int)viewTag.asNumber(); 163 std::string propNameStr = propName.asString(rt).utf8(rt); 164 jsi::Function fun = callback.getObject(rt).asFunction(rt); 165 std::shared_ptr<jsi::Function> funPtr = std::make_shared<jsi::Function>(std::move(fun)); 166 167 scheduler->scheduleOnUI([&rt, viewTagInt, funPtr, this, propNameStr]() { 168 const jsi::String propNameValue = jsi::String::createFromUtf8(rt, propNameStr); 169 jsi::Value result = propObtainer(rt, viewTagInt, propNameValue); 170 std::string resultStr = result.asString(rt).utf8(rt); 171 172 scheduler->scheduleOnJS([&rt, resultStr, funPtr]() { 173 const jsi::String resultValue = jsi::String::createFromUtf8(rt, resultStr); 174 funPtr->call(rt, resultValue); 175 }); 176 }); 177 178 return jsi::Value::undefined(); 179 } 180 181 void NativeReanimatedModule::onEvent(std::string eventName, std::string eventAsString) 182 { 183 try 184 { 185 eventHandlerRegistry->processEvent(*runtime, eventName, eventAsString); 186 mapperRegistry->execute(*runtime); 187 if (mapperRegistry->needRunOnRender()) 188 { 189 maybeRequestRender(); 190 } 191 } 192 catch(std::exception &e) { 193 std::string str = e.what(); 194 this->errorHandler->setError(str); 195 this->errorHandler->raise(); 196 } catch(...) { 197 std::string str = "OnEvent error"; 198 this->errorHandler->setError(str); 199 this->errorHandler->raise(); 200 } 201 } 202 203 bool NativeReanimatedModule::isAnyHandlerWaitingForEvent(std::string eventName) { 204 return eventHandlerRegistry->isAnyHandlerWaitingForEvent(eventName); 205 } 206 207 208 void NativeReanimatedModule::maybeRequestRender() 209 { 210 if (!renderRequested) 211 { 212 renderRequested = true; 213 requestRender([this](double timestampMs) { 214 this->renderRequested = false; 215 this->onRender(timestampMs); 216 }, *this->runtime); 217 } 218 } 219 220 void NativeReanimatedModule::onRender(double timestampMs) 221 { 222 try 223 { 224 std::vector<FrameCallback> callbacks = frameCallbacks; 225 frameCallbacks.clear(); 226 for (auto callback : callbacks) 227 { 228 callback(timestampMs); 229 } 230 mapperRegistry->execute(*runtime); 231 232 if (mapperRegistry->needRunOnRender()) 233 { 234 maybeRequestRender(); 235 } 236 } catch(std::exception &e) { 237 std::string str = e.what(); 238 this->errorHandler->setError(str); 239 this->errorHandler->raise(); 240 } catch(...) { 241 std::string str = "OnRender error"; 242 this->errorHandler->setError(str); 243 this->errorHandler->raise(); 244 } 245 } 246 247 NativeReanimatedModule::~NativeReanimatedModule() 248 { 249 StoreUser::clearStore(); 250 } 251 252 } // namespace reanimated 253