Skip to content

Commit

Permalink
fix: Fix JSIConverter<function>::fromJSI (2/2)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrousavy committed Feb 22, 2024
1 parent 2797b91 commit 644383f
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 54 deletions.
93 changes: 51 additions & 42 deletions package/cpp/jsi/JSIConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
#pragma once

#include "HybridObject.h"
#include <array>
#include <jsi/jsi.h>
#include <memory>
#include <type_traits>
#include <unordered_map>
#include <array>

namespace margelo {

Expand Down Expand Up @@ -84,52 +84,61 @@ template <> struct JSIConverter<std::string> {
};

template <typename TInner> struct JSIConverter<std::optional<TInner>> {
static std::optional<TInner> fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
if (arg.isUndefined() || arg.isNull()) {
return std::nullopt;
} else {
return JSIConverter<TInner>::fromJSI(runtime, std::move(arg));
}
static std::optional<TInner> fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
if (arg.isUndefined() || arg.isNull()) {
return std::nullopt;
} else {
return JSIConverter<TInner>::fromJSI(runtime, std::move(arg));
}
static jsi::Value toJSI(jsi::Runtime& runtime, std::optional<TInner> arg) {
if (arg == std::nullopt) {
return jsi::Value::undefined();
} else {
return JSIConverter<TInner>::toJSI(runtime, arg);
}
}
static jsi::Value toJSI(jsi::Runtime& runtime, std::optional<TInner> arg) {
if (arg == std::nullopt) {
return jsi::Value::undefined();
} else {
return JSIConverter<TInner>::toJSI(runtime, arg);
}
}
};

template <typename ReturnType, typename... Args>
struct JSIConverter<std::function<ReturnType(Args...)>> {
static std::function<ReturnType(Args...)> fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
jsi::Function function = arg.asObject(runtime).asFunction(runtime);
std::shared_ptr<jsi::Function> sharedFunction = std::make_shared<jsi::Function>(std::move(function));
return [&runtime, sharedFunction] (Args... args) -> ReturnType {
jsi::Value result = sharedFunction->call(runtime, JSIConverter<Args>::toJSI(runtime, args)...);
if constexpr (std::is_same_v<ReturnType, void>) {
return;
} else {
return JSIConverter<ReturnType>::fromJSI(runtime, std::move(result));
}
};
}

/*template<size_t... Is>
static jsi::Value callHybridFunction(const std::function<ReturnType(Args...)>& function, jsi::Runtime& runtime, const jsi::Value* args, std::index_sequence<Is...>) {
ReturnType result = function(JSIConverter<Args>::fromJSI(runtime, args[Is])...);
return JSIConverter<ReturnType>::toJSI(runtime, result);
}*/
static jsi::Value toJSI(jsi::Runtime& runtime, std::function<ReturnType(Args...)> function) {
return jsi::Value::undefined();
/*jsi::HostFunctionType jsFunction = [function = std::move(function)] (jsi::Runtime& runtime,
const jsi::Value& thisValue,
const jsi::Value* args,
size_t count) -> jsi::Value {
callHybridFunction(function, runtime, args, std::index_sequence_for<Args...>{});
};
return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "hostFunction"), sizeof...(Args), jsFunction);*/
template <typename ReturnType, typename... Args> struct JSIConverter<std::function<ReturnType(Args...)>> {
static std::function<ReturnType(Args...)> fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
jsi::Function function = arg.asObject(runtime).asFunction(runtime);
std::shared_ptr<jsi::Function> sharedFunction = std::make_shared<jsi::Function>(std::move(function));
return [&runtime, sharedFunction](Args... args) -> ReturnType {
jsi::Value result = sharedFunction->call(runtime, JSIConverter<Args>::toJSI(runtime, args)...);
if constexpr (std::is_same_v<ReturnType, void>) {
// it is a void function (returns undefined)
return;
} else {
// it returns a custom type, parse it from the JSI value.
return JSIConverter<ReturnType>::fromJSI(runtime, std::move(result));
}
};
}

template <size_t... Is>
static jsi::Value callHybridFunction(const std::function<ReturnType(Args...)>& function, jsi::Runtime& runtime, const jsi::Value* args,
std::index_sequence<Is...>) {
if constexpr (std::is_same_v<ReturnType, void>) {
function(JSIConverter<Args>::fromJSI(runtime, args[Is])...);
return jsi::Value::undefined();
} else {
ReturnType result = function(JSIConverter<Args>::fromJSI(runtime, args[Is])...);
return JSIConverter<ReturnType>::toJSI(runtime, result);
}
}
static jsi::Value toJSI(jsi::Runtime& runtime, std::function<ReturnType(Args...)> function) {
jsi::HostFunctionType jsFunction = [function = std::move(function)](jsi::Runtime& runtime, const jsi::Value& thisValue,
const jsi::Value* args, size_t count) -> jsi::Value {
if (count != sizeof...(Args)) {
[[unlikely]];
throw jsi::JSError(runtime, "Function expected " + std::to_string(sizeof...(Args)) + " arguments, but received " +
std::to_string(count) + "!");
}
return callHybridFunction(function, runtime, args, std::index_sequence_for<Args...>{});
};
return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "hostFunction"), sizeof...(Args), jsFunction);
}
};

template <typename ElementType> struct JSIConverter<std::vector<ElementType>> {
Expand Down
26 changes: 14 additions & 12 deletions package/cpp/test/TestHybridObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,25 @@ namespace margelo {

class TestHybridObject : public HybridObject {
public:
int getInt() { return _int; }
void setInt(int newValue) { _int = newValue; }
std::string getString() { return _string; }
void setString(std::string newValue) { _string = newValue; }
int getInt() {
return _int;
}
void setInt(int newValue) {
_int = newValue;
}
std::string getString() {
return _string;
}
void setString(std::string newValue) {
_string = newValue;
}

std::unordered_map<std::string, double> multipleArguments(int first, bool second, std::string third) {
return std::unordered_map<std::string, double> {
{"first", 5312},
{"second", 532233},
{"third", 2786}
};
return std::unordered_map<std::string, double>{{"first", 5312}, {"second", 532233}, {"third", 2786}};
}

std::function<int()> getIntGetter() {
return [this]() -> int {
return this->_int;
};
return [this]() -> int { return this->_int; };
}
void sayHelloCallback(std::function<void(std::string)> callback) {
callback("Test Hybrid");
Expand Down

0 comments on commit 644383f

Please sign in to comment.