/* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #include #include #include #include #include #include namespace facebook { namespace react { /* * Base templace class for all `ShadowNode`s which connects exact `ShadowNode` * type with exact `Props` type. * `ConcreteShadowNode` is a default implementation of `ShadowNode` interface * with many handy features. */ template < ComponentName concreteComponentName, typename BaseShadowNodeT, typename PropsT, typename EventEmitterT = EventEmitter, typename StateDataT = StateData> class ConcreteShadowNode : public BaseShadowNodeT { static_assert( std::is_base_of::value, "BaseShadowNodeT must be a descendant of ShadowNode"); static_assert( std::is_base_of::value, "PropsT must be a descendant of Props"); protected: using ShadowNode::props_; using ShadowNode::state_; public: using BaseShadowNodeT::BaseShadowNodeT; using ConcreteProps = PropsT; using SharedConcreteProps = std::shared_ptr; using ConcreteEventEmitter = EventEmitterT; using SharedConcreteEventEmitter = std::shared_ptr; using SharedConcreteShadowNode = std::shared_ptr; using ConcreteState = ConcreteState; using ConcreteStateData = StateDataT; static ComponentName Name() { return ComponentName(concreteComponentName); } static ComponentHandle Handle() { return ComponentHandle(concreteComponentName); } /* * A set of traits associated with a particular class. * Reimplement in subclasses to declare class-specific traits. */ static ShadowNodeTraits BaseTraits() { return BaseShadowNodeT::BaseTraits(); } static SharedConcreteProps Props( const PropsParserContext &context, RawProps const &rawProps, SharedProps const &baseProps = nullptr) { return std::make_shared( context, baseProps ? static_cast(*baseProps) : PropsT(), rawProps); } static SharedConcreteProps defaultSharedProps() { static const SharedConcreteProps defaultSharedProps = std::make_shared(); return defaultSharedProps; } static ConcreteStateData initialStateData( ShadowNodeFragment const &fragment, ShadowNodeFamilyFragment const &familyFragment, ComponentDescriptor const &componentDescriptor) { return {}; } /* * Returns a concrete props object associated with the node. * Thread-safe after the node is sealed. */ ConcreteProps const &getConcreteProps() const { react_native_assert( BaseShadowNodeT::props_ && "Props must not be `nullptr`."); react_native_assert( std::dynamic_pointer_cast(props_) && "Props must be an instance of ConcreteProps class."); return static_cast(*props_); } /* * Returns a concrete event emitter object associated with the node. * Thread-safe after the node is sealed. */ ConcreteEventEmitter const &getConcreteEventEmitter() const { react_native_assert( std::dynamic_pointer_cast( BaseShadowNodeT::getEventEmitter()) && "EventEmitter must be an instance of ConcreteEventEmitter class."); return static_cast( *BaseShadowNodeT::getEventEmitter()); } /* * Returns a concrete state data associated with the node. * Thread-safe after the node is sealed. */ ConcreteStateData const &getStateData() const { react_native_assert(state_ && "State must not be `nullptr`."); react_native_assert( std::dynamic_pointer_cast(state_) && "State must be an instance of ConcreteState class."); return static_cast(state_.get())->getData(); } /* * Creates and assigns a new state object containing given state data. * Can be called only before the node is sealed (usually during construction). */ void setStateData(ConcreteStateData &&data) { Sealable::ensureUnsealed(); state_ = std::make_shared( std::make_shared(std::move(data)), *state_); } }; } // namespace react } // namespace facebook