Skip to content

Commit

Permalink
feat: Support JSIConverter<AnyMap>::canConvert (+ AnyValue and `u…
Browse files Browse the repository at this point in the history
…nordered_map<string, T>`)
  • Loading branch information
mrousavy committed Aug 7, 2024
1 parent 2910180 commit 882054e
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 35 deletions.
1 change: 1 addition & 0 deletions packages/react-native-nitro-modules/cpp/jsi/JSICache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

#include "JSICache.hpp"
#include "JSIHelpers.hpp"

namespace margelo::nitro {

Expand Down
1 change: 0 additions & 1 deletion packages/react-native-nitro-modules/cpp/jsi/JSICache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#pragma once

#include "BorrowingReference.hpp"
#include "GetRuntimeID.hpp"
#include "NitroLogger.hpp"
#include "OwningReference.hpp"
#include <jsi/jsi.h>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct JSIConverter;
#include "JSIConverter.hpp"

#include "AnyMap.hpp"
#include "JSIHelpers.hpp"
#include <jsi/jsi.h>
#include <memory>

Expand All @@ -33,8 +34,8 @@ struct JSIConverter<AnyValue> {
static inline jsi::Value toJSI(jsi::Runtime& runtime, const AnyValue& value) {
return JSIConverter<AnyValue::variant>::toJSI(runtime, value);
}
static inline bool canConvert(jsi::Runtime&, const jsi::Value& value) {
throw std::runtime_error("idk if jsi::Value can be converted to AnyValue!");
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
return JSIConverter<AnyValue::variant>::canConvert(runtime, value);
}
};

Expand Down Expand Up @@ -62,8 +63,23 @@ struct JSIConverter<std::shared_ptr<AnyMap>> {
}
return object;
}
static inline bool canConvert(jsi::Runtime&, const jsi::Value& value) {
throw std::runtime_error("idk if jsi::Value can be converted to AnyMap!");
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
if (!value.isObject()) {
return false;
}
jsi::Object object = value.getObject(runtime);
if (!isPlainObject(runtime, object)) {
return false;
}
jsi::Array properties = object.getPropertyNames(runtime);
size_t size = properties.size(runtime);
for (size_t i = 0; i < size; i++) {
bool canConvertProp = JSIConverter<AnyValue>::canConvert(runtime, properties.getValueAtIndex(runtime, i));
if (!canConvertProp) {
return false;
}
}
return true;
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ struct JSIConverter;
#include "JSIConverter.hpp"

#include "AnyMap.hpp"
#include "JSIHelpers.hpp"
#include <jsi/jsi.h>
#include <unordered_map>

Expand Down Expand Up @@ -47,7 +48,22 @@ struct JSIConverter<std::unordered_map<std::string, ValueType>> {
}

static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
throw std::runtime_error("Don't know if I can convert jsi::Value to AnyMap!");
if (!value.isObject()) {
return false;
}
jsi::Object object = value.getObject(runtime);
if (!isPlainObject(runtime, object)) {
return false;
}
jsi::Array properties = object.getPropertyNames(runtime);
size_t size = properties.size(runtime);
for (size_t i = 0; i < size; i++) {
bool canConvertProp = JSIConverter<ValueType>::canConvert(runtime, properties.getValueAtIndex(runtime, i));
if (!canConvertProp) {
return false;
}
}
return true;
}
};

Expand Down
53 changes: 53 additions & 0 deletions packages/react-native-nitro-modules/cpp/jsi/JSIHelpers.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// JSIHelpers.hpp
// Pods
//
// Created by Marc Rousavy on 07.08.24.
//

#pragma once

#include "ThreadUtils.hpp"
#include <jsi/jsi.h>

namespace margelo::nitro {

using namespace facebook;

/**
* Returns whether the given `jsi::Object` is a plain-JS object, or not.
* If it is not a plain-JS object, it could be an Array, ArrayBuffer, Function,
* HostObject or NativeState.
*/
static inline bool isPlainObject(jsi::Runtime& runtime, const jsi::Object& object) {
if (object.isArray(runtime)) {
return false;
}
if (object.isArrayBuffer(runtime)) {
return false;
}
if (object.isFunction(runtime)) {
return false;
}
if (object.isHostObject(runtime)) {
return false;
}
if (object.hasNativeState(runtime)) {
return false;
}
return true;
}

/**
* Get an ID for the given Runtime.
*
* The ID usually consists of a Runtime description (e.g. "HermesRuntime"),
* and it's Thread (e.g. "com.facebook.react.runtime.JavaScript")
*/
static inline std::string getRuntimeId(jsi::Runtime& runtime) {
std::string threadName = ThreadUtils::getThreadName();
return runtime.description() + std::string(" (") + threadName + std::string(")");
}

} // namespace margelo::nitro

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "Dispatcher.hpp"
#include "GetRuntimeID.hpp"
#include "JSIHelpers.hpp"
#include "NitroLogger.hpp"

namespace margelo::nitro {
Expand Down
28 changes: 0 additions & 28 deletions packages/react-native-nitro-modules/cpp/utils/GetRuntimeID.hpp

This file was deleted.

0 comments on commit 882054e

Please sign in to comment.