#include #include #include // To be able to find objects that aren't cleaned up correctly, // we can set this value to 1 and debug the constructor/destructor #define JSI_DEBUG_ALLOCATIONS 0 namespace RNJsi { #if JSI_DEBUG_ALLOCATIONS int objCounter = 0; std::vector objects; #endif JsiHostObject::JsiHostObject() { #if JSI_DEBUG_ALLOCATIONS objects.push_back(this); objCounter++; #endif } JsiHostObject::~JsiHostObject() { #if JSI_DEBUG_ALLOCATIONS for (size_t i = 0; i < objects.size(); ++i) { if (objects.at(i) == this) { objects.erase(objects.begin() + i); break; } } objCounter--; #endif } void JsiHostObject::set(jsi::Runtime &rt, const jsi::PropNameID &name, const jsi::Value &value) { auto nameVal = name.utf8(rt); auto nameStr = nameVal.c_str(); /** Check the static setters map */ const JsiPropertySettersMap &setters = getExportedPropertySettersMap(); auto setter = setters.find(nameStr); if (setter != setters.end()) { auto dispatcher = std::bind(setter->second, this, std::placeholders::_1, std::placeholders::_2); return dispatcher(rt, value); } if (_propMap.count(nameStr) > 0) { auto prop = _propMap.at(nameStr); (prop.set)(rt, value); } } jsi::Value JsiHostObject::get(jsi::Runtime &runtime, const jsi::PropNameID &name) { auto nameVal = name.utf8(runtime); auto nameStr = nameVal.c_str(); // Check the static getters map const JsiPropertyGettersMap &getters = getExportedPropertyGettersMap(); auto getter = getters.find(nameStr); if (getter != getters.end()) { auto dispatcher = std::bind(getter->second, this, std::placeholders::_1); return dispatcher(runtime); } // Check the cache for functions auto runtimeCache = _cache.find(&runtime); JsiHostFunctionCache *currentCache; if (runtimeCache != _cache.end()) { currentCache = &runtimeCache->second; // Check if the runtime cache as a cache of the host function auto cachedFunc = runtimeCache->second.find(nameStr); if (cachedFunc != runtimeCache->second.end()) { return cachedFunc->second->asFunction(runtime); } } else { // Create cache for this runtime JsiHostFunctionCache runtimeCache; _cache.emplace(&runtime, JsiHostFunctionCache{}); currentCache = &_cache.at(&runtime); } // Check the static function map const JsiFunctionMap &funcs = getExportedFunctionMap(); auto func = funcs.find(nameStr); if (func != funcs.end()) { auto dispatcher = std::bind(func->second, (JsiHostObject *)this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4); // Add to cache currentCache->emplace(nameStr, std::make_unique( jsi::Function::createFromHostFunction( runtime, name, 0, dispatcher))); // return retVal; return currentCache->at(nameStr)->asFunction(runtime); } if (_funcMap.count(nameStr) > 0) { return jsi::Function::createFromHostFunction(runtime, name, 0, _funcMap.at(nameStr)); } if (_propMap.count(nameStr) > 0) { auto prop = _propMap.at(nameStr); return (prop.get)(runtime); } return jsi::Value::undefined(); } std::vector JsiHostObject::getPropertyNames(jsi::Runtime &runtime) { // statically exported functions const auto& funcs = getExportedFunctionMap(); // Statically exported property getters const auto& getters = getExportedPropertyGettersMap(); // Statically exported property setters const auto& setters = getExportedPropertySettersMap(); std::vector propNames; propNames.reserve(funcs.size() + getters.size() + setters.size() + _funcMap.size() + _propMap.size()); for (auto it = funcs.cbegin(); it != funcs.cend(); ++it) { propNames.push_back(jsi::PropNameID::forAscii(runtime, it->first)); } for (auto it = getters.cbegin(); it != getters.cend(); ++it) { propNames.push_back(jsi::PropNameID::forUtf8(runtime, it->first)); } for (auto it = getters.cbegin(); it != getters.cend(); ++it) { if (getters.count(it->first) == 0) { propNames.push_back(jsi::PropNameID::forUtf8(runtime, it->first)); } } // functions for (auto it = _funcMap.cbegin(); it != _funcMap.cend(); ++it) { propNames.push_back(jsi::PropNameID::forAscii(runtime, it->first)); } // props for (auto it = _propMap.cbegin(); it != _propMap.cend(); ++it) { propNames.push_back(jsi::PropNameID::forAscii(runtime, it->first)); } return propNames; } } // namespace RNJsi