diff --git a/ReactCommon/jsi/JSCRuntime.cpp b/ReactCommon/jsi/JSCRuntime.cpp index 5d8487b2cd5b93..9eb578a229eb12 100644 --- a/ReactCommon/jsi/JSCRuntime.cpp +++ b/ReactCommon/jsi/JSCRuntime.cpp @@ -168,6 +168,12 @@ class JSCRuntime : public jsi::Runtime { const jsi::Object &) override; jsi::HostFunctionType &getHostFunction(const jsi::Function &) override; + bool hasNativeState(const jsi::Object &) override; + std::shared_ptr getNativeState( + const jsi::Object &) override; + void setNativeState(const jsi::Object &, std::shared_ptr) + override; + jsi::Value getProperty(const jsi::Object &, const jsi::String &name) override; jsi::Value getProperty(const jsi::Object &, const jsi::PropNameID &name) override; @@ -862,6 +868,21 @@ std::shared_ptr JSCRuntime::getHostObject( return metadata->hostObject; } +bool JSCRuntime::hasNativeState(const jsi::Object &) { + throw std::logic_error("Not implemented"); +} + +std::shared_ptr JSCRuntime::getNativeState( + const jsi::Object &) { + throw std::logic_error("Not implemented"); +} + +void JSCRuntime::setNativeState( + const jsi::Object &, + std::shared_ptr) { + throw std::logic_error("Not implemented"); +} + jsi::Value JSCRuntime::getProperty( const jsi::Object &obj, const jsi::String &name) { diff --git a/ReactCommon/jsi/jsi/decorator.h b/ReactCommon/jsi/jsi/decorator.h index 6f239c051b7d58..5c4811ac26ba8e 100644 --- a/ReactCommon/jsi/jsi/decorator.h +++ b/ReactCommon/jsi/jsi/decorator.h @@ -222,6 +222,17 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { return dhf.target()->plainHF_; }; + bool hasNativeState(const Object& o) override { + return plain_.hasNativeState(o); + } + std::shared_ptr getNativeState(const Object& o) override { + return plain_.getNativeState(o); + } + void setNativeState(const Object& o, std::shared_ptr state) + override { + plain_.setNativeState(o, state); + } + Value getProperty(const Object& o, const PropNameID& name) override { return plain_.getProperty(o, name); }; diff --git a/ReactCommon/jsi/jsi/jsi-inl.h b/ReactCommon/jsi/jsi/jsi-inl.h index 3823e8b255354a..992ee9f535e84f 100644 --- a/ReactCommon/jsi/jsi/jsi-inl.h +++ b/ReactCommon/jsi/jsi/jsi-inl.h @@ -202,6 +202,24 @@ inline std::shared_ptr Object::getHostObject( return runtime.getHostObject(*this); } +template +inline bool Object::hasNativeState(Runtime& runtime) const { + return runtime.hasNativeState(*this) && + std::dynamic_pointer_cast(runtime.getNativeState(*this)); +} + +template +inline std::shared_ptr Object::getNativeState(Runtime& runtime) const { + assert(hasNativeState(runtime)); + return std::static_pointer_cast(runtime.getNativeState(*this)); +} + +inline void Object::setNativeState( + Runtime& runtime, + std::shared_ptr state) const { + runtime.setNativeState(*this, state); +} + inline Array Object::getPropertyNames(Runtime& runtime) const { return runtime.getPropertyNames(*this); } diff --git a/ReactCommon/jsi/jsi/jsi.cpp b/ReactCommon/jsi/jsi/jsi.cpp index 3f56d0623b0b31..c8fe78379eaf67 100644 --- a/ReactCommon/jsi/jsi/jsi.cpp +++ b/ReactCommon/jsi/jsi/jsi.cpp @@ -81,6 +81,8 @@ void HostObject::set(Runtime& rt, const PropNameID& name, const Value&) { HostObject::~HostObject() {} +NativeState::~NativeState() {} + Runtime::~Runtime() {} Instrumentation& Runtime::instrumentation() { diff --git a/ReactCommon/jsi/jsi/jsi.h b/ReactCommon/jsi/jsi/jsi.h index 7c1479f006824c..4dc4a8fe5dc0e2 100644 --- a/ReactCommon/jsi/jsi/jsi.h +++ b/ReactCommon/jsi/jsi/jsi.h @@ -128,6 +128,13 @@ class JSI_EXPORT HostObject { virtual std::vector getPropertyNames(Runtime& rt); }; +/// Native state (and destructor) that can be attached to any JS object +/// using setNativeState. +class JSI_EXPORT NativeState { + public: + virtual ~NativeState(); +}; + /// Represents a JS runtime. Movable, but not copyable. Note that /// this object may not be thread-aware, but cannot be used safely from /// multiple threads at once. The application is responsible for @@ -296,6 +303,12 @@ class JSI_EXPORT Runtime { virtual std::shared_ptr getHostObject(const jsi::Object&) = 0; virtual HostFunctionType& getHostFunction(const jsi::Function&) = 0; + virtual bool hasNativeState(const jsi::Object&) = 0; + virtual std::shared_ptr getNativeState(const jsi::Object&) = 0; + virtual void setNativeState( + const jsi::Object&, + std::shared_ptr state) = 0; + virtual Value getProperty(const Object&, const PropNameID& name) = 0; virtual Value getProperty(const Object&, const String& name) = 0; virtual bool hasProperty(const Object&, const PropNameID& name) = 0; @@ -711,6 +724,25 @@ class JSI_EXPORT Object : public Pointer { template std::shared_ptr asHostObject(Runtime& runtime) const; + /// \return whether this object has native state of type T previously set by + /// \c setNativeState. + template + bool hasNativeState(Runtime& runtime) const; + + /// \return a shared_ptr to the state previously set by \c setNativeState. + /// If \c hasNativeState is false, this will assert. Note that this does a + /// type check and will assert if the native state isn't of type \c T + template + std::shared_ptr getNativeState(Runtime& runtime) const; + + /// Set the internal native state property of this object, overwriting any old + /// value. Creates a new shared_ptr to the object managed by \p state, which + /// will live until the value at this property becomes unreachable. + /// + /// Throws a type error if this object is a proxy or host object. + void setNativeState(Runtime& runtime, std::shared_ptr state) + const; + /// \return same as \c getProperty(name).asObject(), except with /// a better exception message. Object getPropertyAsObject(Runtime& runtime, const char* name) const;