#pragma once #include #include #include #include #include #include namespace RNJsi { namespace jsi = facebook::jsi; enum struct PropType { Undefined = 0, Null = 1, // Keep undefined / null constant so that we can do checks faster Bool = 2, Number = 3, String = 4, Object = 5, HostObject = 6, HostFunction = 7, Array = 8 }; using PropId = const char *; class JsiPropId { public: static const char *get(const std::string &name) { return _get(name); } static const char *get(const std::string &&name) { return _get(std::move(name)); } private: static const char *_get(const std::string &name) { if (_impls().count(name) == 0) { // Alloc string char *impl = new char[name.size() + 1]; strncpy(impl, name.c_str(), name.size() + 1); _impls().emplace(name, impl); } return _impls().at(name); } static std::unordered_map &_impls() { static std::unordered_map impls; return impls; } }; /** This is a class that deep copies values from JS to C++. */ class JsiValue { public: /** Default constructor for an empty JsiValue */ JsiValue(); /** Constructs an instance of the JsiValue object with a current value */ JsiValue(jsi::Runtime &runtime, const jsi::Value &value); /** Updates the current value from the Javascript value. This function will perform a deep copy of the javascript value. */ void setCurrent(jsi::Runtime &runtime, const jsi::Value &value); /** Returns the type of value contained in this JsiValue */ PropType getType() const { return _type; } /** Returns true if the value is undefined or null. */ bool isUndefinedOrNull() const { return _type <= PropType::Null; } /** Returns true if the value is undefined. */ bool isUndefined() const { return _type == PropType::Undefined; } /** Returns true if the value is null. */ bool isNull() const { return _type == PropType::Null; } /** Returns the bool value. Requires that the underlying type is bool */ bool getAsBool() const; /** Returns the numeric value. Requires that the underlying type is number */ double getAsNumber() const; /** Returns the string value. Requires that the underlying type is string */ const std::string &getAsString() const; /** Returns the array value. Requires that the underlying type is array */ const std::vector &getAsArray() const; /** Returns an inner value by name. Requires that the underlying type is Object */ const JsiValue &getValue(PropId name) const; /** Returns true if the underlying type is Object and the property name exists. */ bool hasValue(PropId name) const; /** Returns the names of the properties stored in this value */ std::vector getKeys() const; /** Returns the host object value. Requires that the underlying type is Host Object */ std::shared_ptr getAsHostObject() const; /** Returns a dynamic cast of the host object value. Requires that the underlying type is Host Object */ template std::shared_ptr getAs() const { if (_type != PropType::HostObject) { throw std::runtime_error("Expected type host object, got " + getTypeAsString(_type)); } return std::dynamic_pointer_cast(_hostObject); } /** Returns the host function. Requires that the type is HostFunction */ jsi::HostFunctionType getAsHostFunction() const; /** Returns a callable HostFunction representing the undderlying js function. Requires that the type is Function */ const jsi::HostFunctionType getAsFunction() const; /** Returns a string representation of the value */ std::string asString() const; /** Converts the underlying value back to a JS value */ jsi::Value getAsJsiValue(jsi::Runtime &runtime) const; /** Returns a string representing the type. */ static std::string getTypeAsString(PropType type); /** Implements the equals operator */ bool operator==(const JsiValue &other) const; /** Implements the inequals operator */ bool operator!=(const JsiValue &other) const; protected: const std::unordered_map &getProps() const { return _props; } bool boolValue() const { return _boolValue; } double numberValue() const { return _numberValue; } std::string stringValue() const { return _stringValue; } std::shared_ptr hostObject() const { return _hostObject; } jsi::HostFunctionType hostFunction() const { return _hostFunction; } std::vector array() const { return _array; } std::unordered_map props() const { return _props; } const std::vector &keysCache() const { return _keysCache; } private: void setObject(jsi::Runtime &runtime, const jsi::Value &value); jsi::Object getObject(jsi::Runtime &runtime) const; void setFunction(jsi::Runtime &runtime, const jsi::Value &value); jsi::Object getHostFunction(jsi::Runtime &runtime) const; void setArray(jsi::Runtime &runtime, const jsi::Object &obj); jsi::Array getArray(jsi::Runtime &runtime) const; void setHostObject(jsi::Runtime &runtime, const jsi::Object &obj); jsi::Object getHostObject(jsi::Runtime &runtime) const; PropType _type = PropType::Undefined; bool _boolValue; double _numberValue; std::string _stringValue = ""; std::shared_ptr _hostObject; jsi::HostFunctionType _hostFunction; std::vector _array; std::unordered_map _props; std::vector _keysCache; }; } // namespace RNJsi