From 4a8d3dd77ee5b460c286f7bc2bced47990049a18 Mon Sep 17 00:00:00 2001 From: Maciej Makowski Date: Thu, 12 Dec 2024 17:34:33 +0100 Subject: [PATCH] feat: implemented base class for HostObjects --- .../common/cpp/utils/JsiHostObject.cpp | 87 ++++++++++++++++ .../common/cpp/utils/JsiHostObject.h | 98 +++++++++++++++++++ 2 files changed, 185 insertions(+) create mode 100644 packages/react-native-audio-api/common/cpp/utils/JsiHostObject.cpp create mode 100644 packages/react-native-audio-api/common/cpp/utils/JsiHostObject.h diff --git a/packages/react-native-audio-api/common/cpp/utils/JsiHostObject.cpp b/packages/react-native-audio-api/common/cpp/utils/JsiHostObject.cpp new file mode 100644 index 00000000..42fefcfd --- /dev/null +++ b/packages/react-native-audio-api/common/cpp/utils/JsiHostObject.cpp @@ -0,0 +1,87 @@ +#include "JsiHostObject.h" + +namespace audioapi { +JsiHostObject::JsiHostObject() { + propertyGetters_ = std::make_unique>(); + propertyFunctions_ = std::make_unique>(); + propertySetters_ = std::make_unique>(); + + propertyGetters_->insert(JSI_EXPORT_PROPERTY_GETTER(JsiHostObject, then)); +} + +std::vector JsiHostObject::getPropertyNames(jsi::Runtime &rt) { + std::vector propertyNames; + propertyNames.reserve( + propertyGetters_->size() + propertyFunctions_->size() + + propertySetters_->size()); + + for (const auto &it : *propertyGetters_) { + propertyNames.push_back(jsi::PropNameID::forUtf8(rt, it.first)); + } + + for (const auto &it : *propertyFunctions_) { + propertyNames.push_back(jsi::PropNameID::forAscii(rt, it.first)); + } + + for (const auto &it : *propertySetters_) { + propertyNames.push_back(jsi::PropNameID::forAscii(rt, it.first)); + } + + return propertyNames; +} + +jsi::Value JsiHostObject::get( + jsi::Runtime &runtime, + const jsi::PropNameID &name) { + auto nameAsString = name.utf8(runtime); + + auto propertyGetter = propertyGetters_->find(nameAsString); + if (propertyGetter != propertyGetters_->end()) { + auto dispatcher = [this, &propertyGetter](jsi::Runtime &runtime) { + return (this->*(propertyGetter->second))(runtime); + }; + + return dispatcher(runtime); + } + + auto propertyFunction = propertyFunctions_->find(nameAsString); + if (propertyFunction != propertyFunctions_->end()) { + auto dispatcher = [this, &propertyFunction]( + jsi::Runtime &runtime, + const jsi::Value &thisVal, + const jsi::Value *args, + size_t count) -> jsi::Value { + return (this->*(propertyFunction->second))(runtime, thisVal, args, count); + }; + + return jsi::Function::createFromHostFunction(runtime, name, 0, dispatcher); + } + + return jsi::Value::undefined(); +} + +void JsiHostObject::set( + jsi::Runtime &runtime, + const jsi::PropNameID &name, + const jsi::Value &value) { + auto nameAsString = name.utf8(runtime); + + auto propertySetter = propertySetters_->find(nameAsString); + + if (propertySetter != propertySetters_->end()) { + auto dispatcher = [this, &propertySetter]( + jsi::Runtime &runtime, const jsi::Value &value) { + return (this->*(propertySetter->second))(runtime, value); + }; + + return dispatcher(runtime, value); + } +} +} // namespace audioapi diff --git a/packages/react-native-audio-api/common/cpp/utils/JsiHostObject.h b/packages/react-native-audio-api/common/cpp/utils/JsiHostObject.h new file mode 100644 index 00000000..7ad56e0a --- /dev/null +++ b/packages/react-native-audio-api/common/cpp/utils/JsiHostObject.h @@ -0,0 +1,98 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#define JSI_HOST_FUNCTION(NAME) \ + jsi::Value NAME( \ + jsi::Runtime &runtime, \ + const jsi::Value &thisVal, \ + const jsi::Value *args, \ + size_t count) + +#define JSI_EXPORT_FUNCTION(CLASS, FUNCTION) \ + std::make_pair( \ + std::string(#FUNCTION), \ + static_cast( \ + &CLASS::FUNCTION)) + +#define JSI_PROPERTY_GETTER(name) jsi::Value name(jsi::Runtime &runtime) + +#define JSI_EXPORT_PROPERTY_GETTER(CLASS, FUNCTION) \ + std::make_pair( \ + std::string(#FUNCTION), \ + static_cast( \ + &CLASS::FUNCTION)) + +#define JSI_PROPERTY_SETTER(name) \ + void name(jsi::Runtime &runtime, const jsi::Value &value) + +#define JSI_EXPORT_PROPERTY_SETTER(CLASS, FUNCTION) \ + std::make_pair( \ + std::string(#FUNCTION), \ + static_cast(&CLASS::FUNCTION)) + +namespace audioapi { + +using namespace facebook; + +class JsiHostObject : public jsi::HostObject { + public: + JsiHostObject(); + + std::vector getPropertyNames(jsi::Runtime &rt) override; + + jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &name) override; + + void set( + jsi::Runtime &runtime, + const jsi::PropNameID &name, + const jsi::Value &value) override; + + template + void addGetters(Args... args) { + (propertyGetters_->insert(args), ...); + } + + template + void addSetters(Args... args) { + (propertySetters_->insert(args), ...); + } + + template + void addFunctions(Args... args) { + (propertyFunctions_->insert(args), ...); + } + + JSI_PROPERTY_GETTER(then) { + return jsi::Value::undefined(); + } + + protected: + std::unique_ptr> + propertyGetters_; + + std::unique_ptr> + propertyFunctions_; + + std::unique_ptr> + propertySetters_; +}; + +} // namespace audioapi