Skip to content

Commit

Permalink
feat: implemented base class for HostObjects
Browse files Browse the repository at this point in the history
  • Loading branch information
Maciej Makowski committed Dec 12, 2024
1 parent 0a7feb0 commit 4a8d3dd
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 0 deletions.
87 changes: 87 additions & 0 deletions packages/react-native-audio-api/common/cpp/utils/JsiHostObject.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include "JsiHostObject.h"

namespace audioapi {
JsiHostObject::JsiHostObject() {
propertyGetters_ = std::make_unique<std::unordered_map<
std::string,
jsi::Value (JsiHostObject::*)(jsi::Runtime &)>>();
propertyFunctions_ = std::make_unique<std::unordered_map<
std::string,
jsi::Value (JsiHostObject::*)(
jsi::Runtime &, const jsi::Value &, const jsi::Value *, size_t)>>();
propertySetters_ = std::make_unique<std::unordered_map<
std::string,
void (JsiHostObject::*)(jsi::Runtime &, const jsi::Value &)>>();

propertyGetters_->insert(JSI_EXPORT_PROPERTY_GETTER(JsiHostObject, then));
}

std::vector<jsi::PropNameID> JsiHostObject::getPropertyNames(jsi::Runtime &rt) {
std::vector<jsi::PropNameID> 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
98 changes: 98 additions & 0 deletions packages/react-native-audio-api/common/cpp/utils/JsiHostObject.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#pragma once

#include <jsi/jsi.h>
#include <memory>
#include <set>
#include <unordered_map>
#include <utility>
#include <vector>

#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<jsi::Value (JsiHostObject::*)( \
jsi::Runtime &, const jsi::Value &, const jsi::Value *, size_t)>( \
&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<jsi::Value (JsiHostObject::*)(jsi::Runtime &)>( \
&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<void (JsiHostObject::*)( \
jsi::Runtime &, const jsi::Value &)>(&CLASS::FUNCTION))

namespace audioapi {

using namespace facebook;

class JsiHostObject : public jsi::HostObject {
public:
JsiHostObject();

std::vector<jsi::PropNameID> 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 <typename... Args>
void addGetters(Args... args) {
(propertyGetters_->insert(args), ...);
}

template <typename... Args>
void addSetters(Args... args) {
(propertySetters_->insert(args), ...);
}

template <typename... Args>
void addFunctions(Args... args) {
(propertyFunctions_->insert(args), ...);
}

JSI_PROPERTY_GETTER(then) {
return jsi::Value::undefined();
}

protected:
std::unique_ptr<std::unordered_map<
std::string,
jsi::Value (JsiHostObject::*)(jsi::Runtime &)>>
propertyGetters_;

std::unique_ptr<std::unordered_map<
std::string,
jsi::Value (JsiHostObject::*)(
jsi::Runtime &,
const jsi::Value &,
const jsi::Value *,
size_t)>>
propertyFunctions_;

std::unique_ptr<std::unordered_map<
std::string,
void (JsiHostObject::*)(jsi::Runtime &, const jsi::Value &)>>
propertySetters_;
};

} // namespace audioapi

0 comments on commit 4a8d3dd

Please sign in to comment.