Fabric: Devirtualizing of props parsing infra

Summary:
This diff contains several tight to each other changes (which can/should not be split into several diffs):
 * The props parsing/conversion process was de-virtualized: we don't use virtual `apply` method to parse props anymore. Instead, we use old-fashioned constructors.
 * All fields of Props classes which represent props values were marked as `const` which make impossible to modify them after the objects were created (even if we have non-const value-of/pointer-to the whole Props object). Those fields are also `public` now.
 * All custom handwritten getters were removed (because we don't need them anymore).

So, now we don't need all those custom getters which makes code much more compact, performant and codegen-friendly.

Reviewed By: fkgozali

Differential Revision: D7901245

fbshipit-source-id: 9f4b1fd2da64bf963b63215ed3bd74b9d3c58dd5
This commit is contained in:
Valentin Shergin 2018-05-14 15:43:28 -07:00 committed by Facebook Github Bot
parent 582e1bded3
commit dd3a6eda70
31 changed files with 225 additions and 305 deletions

View File

@ -39,7 +39,7 @@ using namespace facebook::react;
[super updateProps:props oldProps:oldProps]; [super updateProps:props oldProps:oldProps];
auto paragraphProps = std::static_pointer_cast<const ParagraphProps>(props); auto paragraphProps = std::static_pointer_cast<const ParagraphProps>(props);
assert(paragraphProps); assert(paragraphProps);
_paragraphAttributes = paragraphProps->getParagraphAttributes(); _paragraphAttributes = paragraphProps->paragraphAttributes;
} }
- (void)updateLocalData:(SharedLocalData)localData - (void)updateLocalData:(SharedLocalData)localData

View File

@ -24,8 +24,8 @@ using namespace facebook::react;
auto oldViewProps = *std::dynamic_pointer_cast<const ViewProps>(oldProps); auto oldViewProps = *std::dynamic_pointer_cast<const ViewProps>(oldProps);
auto newViewProps = *std::dynamic_pointer_cast<const ViewProps>(props); auto newViewProps = *std::dynamic_pointer_cast<const ViewProps>(props);
if (oldViewProps.getBackgroundColor() != newViewProps.getBackgroundColor()) { if (oldViewProps.backgroundColor != newViewProps.backgroundColor) {
self.backgroundColor = [UIColor colorWithCGColor:newViewProps.getBackgroundColor().get()]; self.backgroundColor = [UIColor colorWithCGColor:newViewProps.backgroundColor.get()];
} }
// TODO: Implement all sutable non-layout <View> props. // TODO: Implement all sutable non-layout <View> props.

View File

@ -28,22 +28,12 @@ public:
using SharedConcreteProps = std::shared_ptr<const PropsT>; using SharedConcreteProps = std::shared_ptr<const PropsT>;
using SharedConcreteShadowNode = std::shared_ptr<const ConcreteShadowNode>; using SharedConcreteShadowNode = std::shared_ptr<const ConcreteShadowNode>;
static const SharedConcreteProps Props(const RawProps &rawProps, const SharedProps &baseProps = nullptr) { static SharedConcreteProps Props(const RawProps &rawProps, const SharedProps &baseProps = nullptr) {
if (!baseProps) { return std::make_shared<const PropsT>(baseProps ? *std::static_pointer_cast<const PropsT>(baseProps) : PropsT(), rawProps);
auto props = std::make_shared<PropsT>();
props->apply(rawProps);
return props;
} }
auto concreteBaseProps = std::dynamic_pointer_cast<const PropsT>(baseProps); static SharedConcreteProps defaultSharedProps() {
assert(concreteBaseProps); static const SharedConcreteProps defaultSharedProps = std::make_shared<const PropsT>();
auto props = std::make_shared<PropsT>(*concreteBaseProps);
props->apply(rawProps);
return props;
}
static const SharedConcreteProps defaultSharedProps() {
static const SharedConcreteProps defaultSharedProps = std::make_shared<PropsT>();
return defaultSharedProps; return defaultSharedProps;
} }

View File

@ -13,15 +13,8 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
void Props::apply(const RawProps &rawProps) { Props::Props(const Props &sourceProps, const RawProps &rawProps):
ensureUnsealed(); nativeId(convertRawProp(rawProps, "nativeID", sourceProps.nativeId)) {};
applyRawProp(rawProps, "nativeID", nativeId_);
}
const std::string &Props::getNativeId() const {
return nativeId_;
}
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -28,12 +28,10 @@ class Props:
public virtual DebugStringConvertible { public virtual DebugStringConvertible {
public: public:
virtual void apply(const RawProps &rawProps); Props() = default;
Props(const Props &sourceProps, const RawProps &rawProps);
const std::string &getNativeId() const; const std::string nativeId;
private:
std::string nativeId_ {""};
}; };
} // namespace react } // namespace react

View File

@ -20,33 +20,37 @@ inline int intFromDynamic(const folly::dynamic &value) { return value.getInt();
inline Float floatFromDynamic(const folly::dynamic &value) { return value.getDouble(); } inline Float floatFromDynamic(const folly::dynamic &value) { return value.getDouble(); }
inline std::string stringFromDynamic(const folly::dynamic &value) { return value.getString(); } inline std::string stringFromDynamic(const folly::dynamic &value) { return value.getString(); }
#define APPLY_RAW_PROP_TEMPLATE(type, converter) \ #define CONVERT_RAW_PROP_TEMPLATE(type, converter) \
inline static void applyRawProp(const RawProps &rawProps, const std::string &name, type &property) { \ inline static type convertRawProp(const RawProps &rawProps, const std::string &name, const type &defaultValue) { \
auto &&iterator = rawProps.find(name); \ auto &&iterator = rawProps.find(name); \
if (iterator != rawProps.end()) { \ if (iterator != rawProps.end()) { \
property = converter(iterator->second); \ return converter(iterator->second); \
} else { \
return defaultValue; \
} \ } \
} \ } \
\ \
inline static void applyRawProp(const RawProps &rawProps, const std::string &name, folly::Optional<type> &property) { \ inline static folly::Optional<type> convertRawProp(const RawProps &rawProps, const std::string &name, const folly::Optional<type> &defaultValue) { \
auto &&iterator = rawProps.find(name); \ auto &&iterator = rawProps.find(name); \
if (iterator != rawProps.end()) { \ if (iterator != rawProps.end()) { \
auto &&value = iterator->second; \ auto &&value = iterator->second; \
if (value.isNull()) { \ if (value.isNull()) { \
property = {}; \ return {}; \
} else { \ } else { \
property = converter(value); \ return converter(value); \
} \ } \
} else { \
return defaultValue; \
} \ } \
} }
APPLY_RAW_PROP_TEMPLATE(bool, boolFromDynamic) CONVERT_RAW_PROP_TEMPLATE(bool, boolFromDynamic)
APPLY_RAW_PROP_TEMPLATE(int, intFromDynamic) CONVERT_RAW_PROP_TEMPLATE(int, intFromDynamic)
APPLY_RAW_PROP_TEMPLATE(Float, floatFromDynamic) CONVERT_RAW_PROP_TEMPLATE(Float, floatFromDynamic)
APPLY_RAW_PROP_TEMPLATE(std::string, stringFromDynamic) CONVERT_RAW_PROP_TEMPLATE(std::string, stringFromDynamic)
APPLY_RAW_PROP_TEMPLATE(SharedColor, colorFromDynamic) CONVERT_RAW_PROP_TEMPLATE(SharedColor, colorFromDynamic)
APPLY_RAW_PROP_TEMPLATE(Point, pointFromDynamic) CONVERT_RAW_PROP_TEMPLATE(Point, pointFromDynamic)
APPLY_RAW_PROP_TEMPLATE(Size, sizeFromDynamic) CONVERT_RAW_PROP_TEMPLATE(Size, sizeFromDynamic)
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -26,7 +26,7 @@ TEST(ComponentDescriptorTest, createShadowNode) {
ASSERT_STREQ(node->getComponentName().c_str(), "Test"); ASSERT_STREQ(node->getComponentName().c_str(), "Test");
ASSERT_EQ(node->getTag(), 9); ASSERT_EQ(node->getTag(), 9);
ASSERT_EQ(node->getRootTag(), 1); ASSERT_EQ(node->getRootTag(), 1);
ASSERT_STREQ(node->getProps()->getNativeId().c_str(), "abc"); ASSERT_STREQ(node->getProps()->nativeId.c_str(), "abc");
} }
TEST(ComponentDescriptorTest, cloneShadowNode) { TEST(ComponentDescriptorTest, cloneShadowNode) {
@ -42,7 +42,7 @@ TEST(ComponentDescriptorTest, cloneShadowNode) {
ASSERT_STREQ(cloned->getComponentName().c_str(), "Test"); ASSERT_STREQ(cloned->getComponentName().c_str(), "Test");
ASSERT_EQ(cloned->getTag(), 9); ASSERT_EQ(cloned->getTag(), 9);
ASSERT_EQ(cloned->getRootTag(), 1); ASSERT_EQ(cloned->getRootTag(), 1);
ASSERT_STREQ(cloned->getProps()->getNativeId().c_str(), "abc"); ASSERT_STREQ(cloned->getProps()->nativeId.c_str(), "abc");
} }
TEST(ComponentDescriptorTest, appendChild) { TEST(ComponentDescriptorTest, appendChild) {

View File

@ -19,13 +19,12 @@ TEST(ShadowNodeTest, handleProps) {
RawProps raw; RawProps raw;
raw["nativeID"] = "abc"; raw["nativeID"] = "abc";
auto props = std::make_shared<Props>(); auto props = std::make_shared<Props>(Props(), raw);
props->apply(raw);
// Props are not sealed after applying raw props. // Props are not sealed after applying raw props.
ASSERT_FALSE(props->getSealed()); ASSERT_FALSE(props->getSealed());
ASSERT_STREQ(props->getNativeId().c_str(), "abc"); ASSERT_STREQ(props->nativeId.c_str(), "abc");
} }
TEST(ShadowNodeTest, handleShadowNodeCreation) { TEST(ShadowNodeTest, handleShadowNodeCreation) {
@ -41,7 +40,7 @@ TEST(ShadowNodeTest, handleShadowNodeCreation) {
ASSERT_EQ(node->getSourceNode(), nullptr); ASSERT_EQ(node->getSourceNode(), nullptr);
ASSERT_EQ(node->getChildren()->size(), 0); ASSERT_EQ(node->getChildren()->size(), 0);
ASSERT_STREQ(node->getProps()->getNativeId().c_str(), "testNativeID"); ASSERT_STREQ(node->getProps()->nativeId.c_str(), "testNativeID");
node->sealRecursive(); node->sealRecursive();
ASSERT_TRUE(node->getSealed()); ASSERT_TRUE(node->getSealed());

View File

@ -13,6 +13,7 @@
#include <fabric/core/ConcreteShadowNode.h> #include <fabric/core/ConcreteShadowNode.h>
#include <fabric/core/LocalData.h> #include <fabric/core/LocalData.h>
#include <fabric/core/ShadowNode.h> #include <fabric/core/ShadowNode.h>
#include <folly/dynamic.h>
using namespace facebook::react; using namespace facebook::react;
@ -37,11 +38,9 @@ private:
class TestProps : public Props { class TestProps : public Props {
public: public:
TestProps() { using Props::Props;
RawProps raw; TestProps():
raw["nativeID"] = "testNativeID"; Props(Props(), {{"nativeID", "testNativeID"}}) {}
apply(raw);
}
}; };
using SharedTestProps = std::shared_ptr<const TestProps>; using SharedTestProps = std::shared_ptr<const TestProps>;

View File

@ -16,52 +16,53 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
void BaseTextProps::apply(const RawProps &rawProps) { static TextAttributes convertRawProp(const RawProps &rawProps, const TextAttributes defaultTextAttributes) {
TextAttributes textAttributes;
// Color // Color
applyRawProp(rawProps, "color", textAttributes_.foregroundColor); textAttributes.foregroundColor = convertRawProp(rawProps, "color", defaultTextAttributes.foregroundColor);
applyRawProp(rawProps, "backgroundColor", textAttributes_.backgroundColor); textAttributes.backgroundColor = convertRawProp(rawProps, "backgroundColor", defaultTextAttributes.backgroundColor);
applyRawProp(rawProps, "opacity", textAttributes_.opacity); textAttributes.opacity = convertRawProp(rawProps, "opacity", defaultTextAttributes.opacity);
// Font // Font
applyRawProp(rawProps, "fontFamily", textAttributes_.fontFamily); textAttributes.fontFamily = convertRawProp(rawProps, "fontFamily", defaultTextAttributes.fontFamily);
applyRawProp(rawProps, "fontSize", textAttributes_.fontSize); textAttributes.fontSize = convertRawProp(rawProps, "fontSize", defaultTextAttributes.fontSize);
applyRawProp(rawProps, "fontSizeMultiplier", textAttributes_.fontSizeMultiplier); textAttributes.fontSizeMultiplier = convertRawProp(rawProps, "fontSizeMultiplier", defaultTextAttributes.fontSizeMultiplier);
applyRawProp(rawProps, "fontWeight", textAttributes_.fontWeight); textAttributes.fontWeight = convertRawProp(rawProps, "fontWeight", defaultTextAttributes.fontWeight);
applyRawProp(rawProps, "fontStyle", textAttributes_.fontStyle); textAttributes.fontStyle = convertRawProp(rawProps, "fontStyle", defaultTextAttributes.fontStyle);
applyRawProp(rawProps, "fontVariant", textAttributes_.fontVariant); textAttributes.fontVariant = convertRawProp(rawProps, "fontVariant", defaultTextAttributes.fontVariant);
applyRawProp(rawProps, "allowFontScaling", textAttributes_.allowFontScaling); textAttributes.allowFontScaling = convertRawProp(rawProps, "allowFontScaling", defaultTextAttributes.allowFontScaling);
applyRawProp(rawProps, "letterSpacing", textAttributes_.letterSpacing); textAttributes.letterSpacing = convertRawProp(rawProps, "letterSpacing", defaultTextAttributes.letterSpacing);
// Paragraph // Paragraph
applyRawProp(rawProps, "lineHeight", textAttributes_.lineHeight); textAttributes.lineHeight = convertRawProp(rawProps, "lineHeight", defaultTextAttributes.lineHeight);
applyRawProp(rawProps, "alignment", textAttributes_.alignment); textAttributes.alignment = convertRawProp(rawProps, "alignment", defaultTextAttributes.alignment);
applyRawProp(rawProps, "baseWritingDirection", textAttributes_.baseWritingDirection); textAttributes.baseWritingDirection = convertRawProp(rawProps, "baseWritingDirection", defaultTextAttributes.baseWritingDirection);
// Decoration // Decoration
applyRawProp(rawProps, "textDecorationColor", textAttributes_.textDecorationColor); textAttributes.textDecorationColor = convertRawProp(rawProps, "textDecorationColor", defaultTextAttributes.textDecorationColor);
applyRawProp(rawProps, "textDecorationLineType", textAttributes_.textDecorationLineType); textAttributes.textDecorationLineType = convertRawProp(rawProps, "textDecorationLineType", defaultTextAttributes.textDecorationLineType);
applyRawProp(rawProps, "textDecorationLineStyle", textAttributes_.textDecorationLineStyle); textAttributes.textDecorationLineStyle = convertRawProp(rawProps, "textDecorationLineStyle", defaultTextAttributes.textDecorationLineStyle);
applyRawProp(rawProps, "textDecorationLinePattern", textAttributes_.textDecorationLinePattern); textAttributes.textDecorationLinePattern = convertRawProp(rawProps, "textDecorationLinePattern", defaultTextAttributes.textDecorationLinePattern);
// Shadow // Shadow
applyRawProp(rawProps, "textShadowOffset", textAttributes_.textShadowOffset); textAttributes.textShadowOffset = convertRawProp(rawProps, "textShadowOffset", defaultTextAttributes.textShadowOffset);
applyRawProp(rawProps, "textShadowRadius", textAttributes_.textShadowRadius); textAttributes.textShadowRadius = convertRawProp(rawProps, "textShadowRadius", defaultTextAttributes.textShadowRadius);
applyRawProp(rawProps, "textShadowColor", textAttributes_.textShadowColor); textAttributes.textShadowColor = convertRawProp(rawProps, "textShadowColor", defaultTextAttributes.textShadowColor);
// Special // Special
applyRawProp(rawProps, "isHighlighted", textAttributes_.isHighlighted); textAttributes.isHighlighted = convertRawProp(rawProps, "isHighlighted", defaultTextAttributes.isHighlighted);
return textAttributes;
} }
#pragma mark - Getters BaseTextProps::BaseTextProps(const BaseTextProps &sourceProps, const RawProps &rawProps):
textAttributes(convertRawProp(rawProps, sourceProps.textAttributes)) {};
TextAttributes BaseTextProps::getTextAttributes() const {
return textAttributes_;
}
#pragma mark - DebugStringConvertible #pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList BaseTextProps::getDebugProps() const { SharedDebugStringConvertibleList BaseTextProps::getDebugProps() const {
return textAttributes_.getDebugProps(); return textAttributes.getDebugProps();
} }
} // namespace react } // namespace react

View File

@ -22,27 +22,17 @@ namespace react {
class BaseTextProps { class BaseTextProps {
public: public:
/* BaseTextProps() = default;
* Same semantic as `Props::apply(...)`. BaseTextProps(const BaseTextProps &sourceProps, const RawProps &rawProps);
*/
void apply(const RawProps &rawProps);
#pragma mark - Getters #pragma mark - Props
/* const TextAttributes textAttributes {};
* Returns all props values as `TextAttributes` object.
*/
TextAttributes getTextAttributes() const;
#pragma mark - DebugStringConvertible (partially) #pragma mark - DebugStringConvertible (partially)
SharedDebugStringConvertibleList getDebugProps() const; SharedDebugStringConvertibleList getDebugProps() const;
private:
TextAttributes textAttributes_;
}; };
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -30,7 +30,7 @@ AttributedString BaseTextShadowNode::getAttributedString(
SharedRawTextShadowNode rawTextShadowNode = std::dynamic_pointer_cast<const RawTextShadowNode>(childNode); SharedRawTextShadowNode rawTextShadowNode = std::dynamic_pointer_cast<const RawTextShadowNode>(childNode);
if (rawTextShadowNode) { if (rawTextShadowNode) {
AttributedString::Fragment fragment; AttributedString::Fragment fragment;
fragment.string = rawTextShadowNode->getProps()->getText(); fragment.string = rawTextShadowNode->getProps()->text;
fragment.textAttributes = textAttributes; fragment.textAttributes = textAttributes;
attributedString.appendFragment(fragment); attributedString.appendFragment(fragment);
continue; continue;
@ -40,7 +40,7 @@ AttributedString BaseTextShadowNode::getAttributedString(
SharedTextShadowNode textShadowNode = std::dynamic_pointer_cast<const TextShadowNode>(childNode); SharedTextShadowNode textShadowNode = std::dynamic_pointer_cast<const TextShadowNode>(childNode);
if (textShadowNode) { if (textShadowNode) {
TextAttributes localTextAttributes = textAttributes; TextAttributes localTextAttributes = textAttributes;
localTextAttributes.apply(textShadowNode->getProps()->getTextAttributes()); localTextAttributes.apply(textShadowNode->getProps()->textAttributes);
attributedString.appendAttributedString(textShadowNode->getAttributedString(localTextAttributes, textShadowNode->getChildren())); attributedString.appendAttributedString(textShadowNode->getAttributedString(localTextAttributes, textShadowNode->getChildren()));
continue; continue;
} }

View File

@ -15,38 +15,34 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
void ParagraphProps::apply(const RawProps &rawProps) { static ParagraphAttributes convertRawProp(const RawProps &rawProps, const ParagraphAttributes &defaultParagraphAttributes) {
ViewProps::apply(rawProps); ParagraphAttributes paragraphAttributes;
BaseTextProps::apply(rawProps);
// Paragraph Attributes paragraphAttributes.maximumNumberOfLines = convertRawProp(rawProps, "numberOfLines", defaultParagraphAttributes.maximumNumberOfLines);
applyRawProp(rawProps, "numberOfLines", paragraphAttributes_.maximumNumberOfLines); paragraphAttributes.ellipsizeMode = convertRawProp(rawProps, "ellipsizeMode", defaultParagraphAttributes.ellipsizeMode);
applyRawProp(rawProps, "ellipsizeMode", paragraphAttributes_.ellipsizeMode); paragraphAttributes.adjustsFontSizeToFit = convertRawProp(rawProps, "adjustsFontSizeToFit", defaultParagraphAttributes.adjustsFontSizeToFit);
applyRawProp(rawProps, "adjustsFontSizeToFit", paragraphAttributes_.adjustsFontSizeToFit); paragraphAttributes.minimumFontSize = convertRawProp(rawProps, "minimumFontSize", defaultParagraphAttributes.minimumFontSize);
applyRawProp(rawProps, "minimumFontSize", paragraphAttributes_.minimumFontSize); paragraphAttributes.maximumFontSize = convertRawProp(rawProps, "maximumFontSize", defaultParagraphAttributes.maximumFontSize);
applyRawProp(rawProps, "maximumFontSize", paragraphAttributes_.maximumFontSize);
// Other Props return paragraphAttributes;
applyRawProp(rawProps, "selectable", isSelectable_);
} }
#pragma mark - Getters ParagraphProps::ParagraphProps(const ParagraphProps &sourceProps, const RawProps &rawProps):
ViewProps(sourceProps, rawProps),
ParagraphAttributes ParagraphProps::getParagraphAttributes() const { BaseTextProps(sourceProps, rawProps),
return paragraphAttributes_; paragraphAttributes(convertRawProp(rawProps, sourceProps.paragraphAttributes)),
} isSelectable(convertRawProp(rawProps, "selectable", sourceProps.isSelectable)) {};
bool ParagraphProps::getIsSelectable() const {
return isSelectable_;
}
#pragma mark - DebugStringConvertible #pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList ParagraphProps::getDebugProps() const { SharedDebugStringConvertibleList ParagraphProps::getDebugProps() const {
return return
ViewProps::getDebugProps() + ViewProps::getDebugProps() +
paragraphAttributes_.getDebugProps() + BaseTextProps::getDebugProps() +
BaseTextProps::getDebugProps(); paragraphAttributes.getDebugProps() +
SharedDebugStringConvertibleList {
debugStringConvertibleItem("isSelectable", isSelectable)
};
} }
} // namespace react } // namespace react

View File

@ -32,30 +32,25 @@ class ParagraphProps:
public BaseTextProps { public BaseTextProps {
public: public:
ParagraphProps() = default;
ParagraphProps(const ParagraphProps &sourceProps, const RawProps &rawProps);
void apply(const RawProps &rawProps) override; #pragma mark - Props
#pragma mark - Getters
/* /*
* Returns `ParagraphAttributes` object which has all prop values that affect * Contains all prop values that affect visual representation of the paragraph.
* visual representation of the paragraph.
*/ */
ParagraphAttributes getParagraphAttributes() const; const ParagraphAttributes paragraphAttributes {};
/* /*
* Defines can the text be selected (and copied) or not. * Defines can the text be selected (and copied) or not.
*/ */
bool getIsSelectable() const; const bool isSelectable {false};
#pragma mark - DebugStringConvertible #pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList getDebugProps() const override; SharedDebugStringConvertibleList getDebugProps() const override;
private:
ParagraphAttributes paragraphAttributes_ {};
bool isSelectable_ {false};
}; };
} // namespace react } // namespace react

View File

@ -19,7 +19,7 @@ ComponentName ParagraphShadowNode::getComponentName() const {
} }
AttributedString ParagraphShadowNode::getAttributedString() const { AttributedString ParagraphShadowNode::getAttributedString() const {
return BaseTextShadowNode::getAttributedString(getProps()->getTextAttributes(), getChildren()); return BaseTextShadowNode::getAttributedString(getProps()->textAttributes, getChildren());
} }
void ParagraphShadowNode::setTextLayoutManager(SharedTextLayoutManager textLayoutManager) { void ParagraphShadowNode::setTextLayoutManager(SharedTextLayoutManager textLayoutManager) {
@ -41,7 +41,7 @@ void ParagraphShadowNode::updateLocalData() {
Size ParagraphShadowNode::measure(LayoutConstraints layoutConstraints) const { Size ParagraphShadowNode::measure(LayoutConstraints layoutConstraints) const {
return textLayoutManager_->measure( return textLayoutManager_->measure(
getAttributedString(), getAttributedString(),
getProps()->getParagraphAttributes(), getProps()->paragraphAttributes,
layoutConstraints layoutConstraints
); );
} }

View File

@ -15,15 +15,15 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
APPLY_RAW_PROP_TEMPLATE(EllipsizeMode, ellipsizeModeFromDynamic) CONVERT_RAW_PROP_TEMPLATE(EllipsizeMode, ellipsizeModeFromDynamic)
APPLY_RAW_PROP_TEMPLATE(FontWeight, fontWeightFromDynamic) CONVERT_RAW_PROP_TEMPLATE(FontWeight, fontWeightFromDynamic)
APPLY_RAW_PROP_TEMPLATE(FontStyle, fontStyleFromDynamic) CONVERT_RAW_PROP_TEMPLATE(FontStyle, fontStyleFromDynamic)
APPLY_RAW_PROP_TEMPLATE(FontVariant, fontVariantFromDynamic) CONVERT_RAW_PROP_TEMPLATE(FontVariant, fontVariantFromDynamic)
APPLY_RAW_PROP_TEMPLATE(WritingDirection, writingDirectionFromDynamic) CONVERT_RAW_PROP_TEMPLATE(WritingDirection, writingDirectionFromDynamic)
APPLY_RAW_PROP_TEMPLATE(TextAlignment, textAlignmentFromDynamic) CONVERT_RAW_PROP_TEMPLATE(TextAlignment, textAlignmentFromDynamic)
APPLY_RAW_PROP_TEMPLATE(TextDecorationLineType, textDecorationLineTypeFromDynamic) CONVERT_RAW_PROP_TEMPLATE(TextDecorationLineType, textDecorationLineTypeFromDynamic)
APPLY_RAW_PROP_TEMPLATE(TextDecorationLineStyle, textDecorationLineStyleFromDynamic) CONVERT_RAW_PROP_TEMPLATE(TextDecorationLineStyle, textDecorationLineStyleFromDynamic)
APPLY_RAW_PROP_TEMPLATE(TextDecorationLinePattern, textDecorationLinePatternFromDynamic) CONVERT_RAW_PROP_TEMPLATE(TextDecorationLinePattern, textDecorationLinePatternFromDynamic)
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -9,28 +9,21 @@
#include <fabric/core/propsConversions.h> #include <fabric/core/propsConversions.h>
#include <fabric/debug/DebugStringConvertibleItem.h> #include <fabric/debug/DebugStringConvertibleItem.h>
#include <fabric/debug/debugStringConvertibleUtils.h>
namespace facebook { namespace facebook {
namespace react { namespace react {
void RawTextProps::apply(const RawProps &rawProps) { RawTextProps::RawTextProps(const RawTextProps &sourceProps, const RawProps &rawProps):
Props::apply(rawProps); Props(sourceProps, rawProps),
text(convertRawProp(rawProps, "text", sourceProps.text)) {};
applyRawProp(rawProps, "text", text_);
}
#pragma mark - Getters
std::string RawTextProps::getText() const {
return text_;
}
#pragma mark - DebugStringConvertible #pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList RawTextProps::getDebugProps() const { SharedDebugStringConvertibleList RawTextProps::getDebugProps() const {
SharedDebugStringConvertibleList list = {}; return {
list.push_back(std::make_shared<DebugStringConvertibleItem>("text", text_)); debugStringConvertibleItem("text", text)
return list; };
} }
} // namespace react } // namespace react

View File

@ -24,19 +24,16 @@ class RawTextProps:
public: public:
void apply(const RawProps &rawProps) override; RawTextProps() = default;
RawTextProps(const RawTextProps &sourceProps, const RawProps &rawProps);
#pragma mark - Getters #pragma mark - Props
std::string getText() const; const std::string text {""};
#pragma mark - DebugStringConvertible #pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList getDebugProps() const override; SharedDebugStringConvertibleList getDebugProps() const override;
private:
std::string text_ {""};
}; };
} // namespace react } // namespace react

View File

@ -16,10 +16,8 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
void TextProps::apply(const RawProps &rawProps) { TextProps::TextProps(const TextProps &sourceProps, const RawProps &rawProps):
Props::apply(rawProps); BaseTextProps::BaseTextProps(sourceProps, rawProps) {};
BaseTextProps::apply(rawProps);
}
#pragma mark - DebugStringConvertible #pragma mark - DebugStringConvertible

View File

@ -25,7 +25,9 @@ class TextProps:
public BaseTextProps { public BaseTextProps {
public: public:
void apply(const RawProps &rawProps) override;
TextProps() = default;
TextProps(const TextProps &sourceProps, const RawProps &rawProps);
#pragma mark - DebugStringConvertible #pragma mark - DebugStringConvertible

View File

@ -44,9 +44,7 @@ void ShadowTree::constraintLayout(const LayoutConstraints &layoutConstraints, co
UnsharedRootShadowNode ShadowTree::cloneRootShadowNode(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const { UnsharedRootShadowNode ShadowTree::cloneRootShadowNode(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const {
auto oldRootShadowNode = rootShadowNode_; auto oldRootShadowNode = rootShadowNode_;
auto &&props = std::make_shared<RootProps>(*oldRootShadowNode->getProps()); auto &&props = std::make_shared<const RootProps>(*oldRootShadowNode->getProps(), layoutConstraints, layoutContext);
props->applyLayoutConstraints(layoutConstraints);
props->applyLayoutContext(layoutContext);
auto newRootShadowNode = std::make_shared<RootShadowNode>(oldRootShadowNode, props, nullptr); auto newRootShadowNode = std::make_shared<RootShadowNode>(oldRootShadowNode, props, nullptr);
return newRootShadowNode; return newRootShadowNode;
} }

View File

@ -7,59 +7,37 @@
#include "ViewProps.h" #include "ViewProps.h"
#include <fabric/debug/DebugStringConvertibleItem.h>
#include <fabric/graphics/graphicValuesConversions.h>
#include <fabric/core/propsConversions.h> #include <fabric/core/propsConversions.h>
#include <fabric/debug/debugStringConvertibleUtils.h>
#include <fabric/graphics/debugStringConvertibleUtils.h>
#include <fabric/graphics/graphicValuesConversions.h>
namespace facebook { namespace facebook {
namespace react { namespace react {
void ViewProps::apply(const RawProps &rawProps) { ViewProps::ViewProps(const YGStyle &yogaStyle):
Props::apply(rawProps); YogaStylableProps(yogaStyle) {}
YogaStylableProps::apply(rawProps);
applyRawProp(rawProps, "zIndex", zIndex_); ViewProps::ViewProps(const ViewProps &sourceProps, const RawProps &rawProps):
applyRawProp(rawProps, "opacity", opacity_); Props(sourceProps, rawProps),
applyRawProp(rawProps, "color", foregroundColor_); YogaStylableProps(sourceProps, rawProps),
applyRawProp(rawProps, "backgroundColor", backgroundColor_); zIndex(convertRawProp(rawProps, "zIndex", sourceProps.zIndex)),
} opacity(convertRawProp(rawProps, "opacity", sourceProps.opacity)),
foregroundColor(convertRawProp(rawProps, "color", sourceProps.foregroundColor)),
#pragma mark - Getters backgroundColor(convertRawProp(rawProps, "backgroundColor", sourceProps.backgroundColor)) {};
SharedColor ViewProps::getForegroundColor() const {
return foregroundColor_;
}
SharedColor ViewProps::getBackgroundColor() const {
return backgroundColor_;
}
#pragma mark - DebugStringConvertible #pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList ViewProps::getDebugProps() const { SharedDebugStringConvertibleList ViewProps::getDebugProps() const {
ViewProps defaultProps = {}; return
AccessibilityProps::getDebugProps() +
SharedDebugStringConvertibleList list = {}; YogaStylableProps::getDebugProps() +
SharedDebugStringConvertibleList {
#define VIEW_PROPS_ADD_TO_SET(stringName, propertyName, accessor, convertor) \ debugStringConvertibleItem("zIndex", zIndex),
if (propertyName != defaultProps.propertyName) { \ debugStringConvertibleItem("opacity", opacity),
list.push_back(std::make_shared<DebugStringConvertibleItem>(#stringName, convertor(propertyName accessor))); \ debugStringConvertibleItem("foregroundColor", foregroundColor),
} debugStringConvertibleItem("backgroundColor", backgroundColor),
};
VIEW_PROPS_ADD_TO_SET(zIndex, zIndex_, , std::to_string)
VIEW_PROPS_ADD_TO_SET(opacity, opacity_, , std::to_string)
VIEW_PROPS_ADD_TO_SET(backgroundColor, backgroundColor_, , colorNameFromColor)
VIEW_PROPS_ADD_TO_SET(foregroundColor, foregroundColor_, , colorNameFromColor)
// Accessibility Props
auto accessibilityPropsList = AccessibilityProps::getDebugProps();
std::move(accessibilityPropsList.begin(), accessibilityPropsList.end(), std::back_inserter(list));
// Yoga styles
list.push_back(std::make_shared<DebugStringConvertibleItem>("style", "", YogaStylableProps::getDebugProps()));
return list;
} }
} // namespace react } // namespace react

View File

@ -26,28 +26,26 @@ class ViewProps:
public AccessibilityProps { public AccessibilityProps {
public: public:
void apply(const RawProps &rawProps) override;
#pragma mark - Getters ViewProps() = default;
ViewProps(const YGStyle &yogaStyle);
ViewProps(const ViewProps &sourceProps, const RawProps &rawProps);
SharedColor getForegroundColor() const; #pragma mark - Props
SharedColor getBackgroundColor() const;
const int zIndex {0};
const Float opacity {1};
const SharedColor foregroundColor {nullptr};
const SharedColor backgroundColor {nullptr};
const SharedColor shadowColor {nullptr};
const Point shadowOffset {};
#pragma mark - DebugStringConvertible #pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList getDebugProps() const override; SharedDebugStringConvertibleList getDebugProps() const override;
private:
int zIndex_ {0};
Float opacity_ {1.0};
SharedColor foregroundColor_ {nullptr};
SharedColor backgroundColor_ {nullptr};
SharedColor shadowColor_ {nullptr};
Point shadowOffset_ {0, 0};
}; };
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -12,20 +12,7 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
void AccessibilityProps::apply(const RawProps &rawProps) { AccessibilityProps::AccessibilityProps(const AccessibilityProps &sourceProps, const RawProps &rawProps) {}
for (auto const &pair : rawProps) {
auto const &name = pair.first;
auto const &value = pair.second;
#define ACCESSIBILITY_PROPERTY(stringName, variableName, accessor, convertor) \
if (name == #stringName) { \
variableName = convertor(value accessor); \
continue; \
}
ACCESSIBILITY_PROPERTY(accessibilityLabel, accessibilityLabel_, .asString(),)
}
}
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -20,22 +20,24 @@ class AccessibilityProps;
typedef std::shared_ptr<const AccessibilityProps> SharedAccessibilityProps; typedef std::shared_ptr<const AccessibilityProps> SharedAccessibilityProps;
class AccessibilityProps: class AccessibilityProps:
public virtual DebugStringConvertible public virtual DebugStringConvertible {
{
public: public:
void apply(const RawProps &rawProps);
protected: AccessibilityProps() = default;
bool accessible_ {true}; AccessibilityProps(const AccessibilityProps &sourceProps, const RawProps &rawProps);
std::string accessibilityActions_ {""};
std::string accessibilityLabel_ {""}; #pragma mark - Props
AccessibilityTraits accessibilityTraits_ {AccessibilityTraits::None};
bool accessibilityViewIsModal_ {false}; const bool accessible {true};
bool accessibilityElementsHidden_ {false}; const std::string accessibilityActions {""};
SharedDirectEventHandler onAccessibilityAction_ {nullptr}; const std::string accessibilityLabel {""};
SharedDirectEventHandler onAccessibilityTap_ {nullptr}; const AccessibilityTraits accessibilityTraits {AccessibilityTraits::None};
SharedDirectEventHandler onMagicTap_ {nullptr}; const bool accessibilityViewIsModal {false};
const bool accessibilityElementsHidden {false};
const SharedDirectEventHandler onAccessibilityAction {nullptr};
const SharedDirectEventHandler onAccessibilityTap {nullptr};
const SharedDirectEventHandler onMagicTap {nullptr};
}; };
} // namespace react } // namespace react

View File

@ -7,39 +7,35 @@
#include "RootProps.h" #include "RootProps.h"
#include "YogaLayoutableShadowNode.h"
#include "yogaValuesConversions.h" #include "yogaValuesConversions.h"
namespace facebook { namespace facebook {
namespace react { namespace react {
void RootProps::applyLayoutConstraints(const LayoutConstraints &layoutConstraints) { static YGStyle yogaStyleFromLayoutConstraints(const LayoutConstraints &layoutConstraints) {
ensureUnsealed(); YGStyle yogaStyle;
yogaStyle.minDimensions[YGDimensionWidth] =
layoutConstraints_ = layoutConstraints;
yogaStyle_.minDimensions[YGDimensionWidth] =
yogaStyleValueFromFloat(layoutConstraints.minimumSize.width); yogaStyleValueFromFloat(layoutConstraints.minimumSize.width);
yogaStyle_.minDimensions[YGDimensionHeight] = yogaStyle.minDimensions[YGDimensionHeight] =
yogaStyleValueFromFloat(layoutConstraints.minimumSize.height); yogaStyleValueFromFloat(layoutConstraints.minimumSize.height);
yogaStyle_.maxDimensions[YGDimensionWidth] = yogaStyle.maxDimensions[YGDimensionWidth] =
yogaStyleValueFromFloat(layoutConstraints.maximumSize.width); yogaStyleValueFromFloat(layoutConstraints.maximumSize.width);
yogaStyle_.maxDimensions[YGDimensionHeight] = yogaStyle.maxDimensions[YGDimensionHeight] =
yogaStyleValueFromFloat(layoutConstraints.maximumSize.height); yogaStyleValueFromFloat(layoutConstraints.maximumSize.height);
return yogaStyle;
} }
void RootProps::applyLayoutContext(const LayoutContext &layoutContext) { RootProps::RootProps(
ensureUnsealed(); const RootProps &sourceProps,
layoutContext_ = layoutContext; const LayoutConstraints &layoutConstraints,
} const LayoutContext &layoutContext
):
LayoutConstraints RootProps::getLayoutConstraints() const { ViewProps(yogaStyleFromLayoutConstraints(layoutConstraints)),
return layoutConstraints_; layoutConstraints(layoutConstraints),
} layoutContext(layoutContext) {};
LayoutContext RootProps::getLayoutContext() const {
return layoutContext_;
}
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -25,19 +25,17 @@ class RootProps final:
public: public:
/* RootProps() = default;
* Same semantic as `apply()` but LayoutConstraints & LayoutContext specific. RootProps(
*/ const RootProps &sourceProps,
void applyLayoutConstraints(const LayoutConstraints &layoutConstraints); const LayoutConstraints &layoutConstraints,
void applyLayoutContext(const LayoutContext &layoutContext); const LayoutContext &layoutContext
);
LayoutConstraints getLayoutConstraints() const; #pragma mark - Props
LayoutContext getLayoutContext() const;
private: const LayoutConstraints layoutConstraints {};
const LayoutContext layoutContext {};
LayoutConstraints layoutConstraints_;
LayoutContext layoutContext_;
}; };
} // namespace react } // namespace react

View File

@ -16,7 +16,7 @@ ComponentName RootShadowNode::getComponentName() const {
void RootShadowNode::layout() { void RootShadowNode::layout() {
ensureUnsealed(); ensureUnsealed();
layout(getProps()->getLayoutContext()); layout(getProps()->layoutContext);
} }
} // namespace react } // namespace react

View File

@ -10,10 +10,10 @@
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include <yoga/Yoga.h>
#include <fabric/core/LayoutContext.h> #include <fabric/core/LayoutContext.h>
#include <fabric/core/LayoutConstraints.h> #include <fabric/core/LayoutConstraints.h>
#include <fabric/debug/DebugStringConvertibleItem.h> #include <fabric/debug/DebugStringConvertibleItem.h>
#include <yoga/Yoga.h>
#include "yogaValuesConversions.h" #include "yogaValuesConversions.h"
@ -40,7 +40,7 @@ YogaLayoutableShadowNode::YogaLayoutableShadowNode(
auto yogaNode = std::make_shared<YGNode>(); auto yogaNode = std::make_shared<YGNode>();
yogaNode->setConfig(suitableYogaConfig().get()); yogaNode->setConfig(suitableYogaConfig().get());
yogaNode->setStyle(props->getYogaStyle()); yogaNode->setStyle(props->yogaStyle);
yogaNode->setContext(this); yogaNode->setContext(this);
yogaNode->setDirty(true); yogaNode->setDirty(true);
YogaLayoutableShadowNode::setYogaNodeChildrenBasedOnShadowNodeChildren(*yogaNode, children); YogaLayoutableShadowNode::setYogaNodeChildrenBasedOnShadowNodeChildren(*yogaNode, children);
@ -59,7 +59,7 @@ YogaLayoutableShadowNode::YogaLayoutableShadowNode(
yogaNode->setDirty(true); yogaNode->setDirty(true);
if (props) { if (props) {
yogaNode->setStyle(props->getYogaStyle()); yogaNode->setStyle(props->yogaStyle);
} }
if (children) { if (children) {

View File

@ -17,18 +17,16 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
const YGStyle &YogaStylableProps::getYogaStyle() const { static YGStyle convertRawProp(const RawProps &rawProps, const YGStyle &defaultValue) {
return yogaStyle_; YGStyle yogaStyle = defaultValue;
}
void YogaStylableProps::apply(const RawProps &rawProps) {
for (auto const &pair : rawProps) { for (auto const &pair : rawProps) {
auto const &name = pair.first; auto const &name = pair.first;
auto const &value = pair.second; auto const &value = pair.second;
#define YOGA_STYLE_PROPERTY(stringName, yogaName, accessor, convertor) \ #define YOGA_STYLE_PROPERTY(stringName, yogaName, accessor, convertor) \
if (name == #stringName) { \ if (name == #stringName) { \
yogaStyle_.yogaName = convertor(value accessor); \ yogaStyle.yogaName = convertor(value accessor); \
continue; \ continue; \
} }
@ -97,15 +95,23 @@ void YogaStylableProps::apply(const RawProps &rawProps) {
YOGA_STYLE_OPTIONAL_FLOAT_PROPERTY(aspectRatio) YOGA_STYLE_OPTIONAL_FLOAT_PROPERTY(aspectRatio)
} }
return yogaStyle;
} }
YogaStylableProps::YogaStylableProps(const YGStyle &yogaStyle):
yogaStyle(yogaStyle) {}
YogaStylableProps::YogaStylableProps(const YogaStylableProps &sourceProps, const RawProps &rawProps):
yogaStyle(convertRawProp(rawProps, sourceProps.yogaStyle)) {};
#pragma mark - DebugStringConvertible #pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList YogaStylableProps::getDebugProps() const { SharedDebugStringConvertibleList YogaStylableProps::getDebugProps() const {
SharedDebugStringConvertibleList list = {}; SharedDebugStringConvertibleList list = {};
YGStyle defaultYogaStyle = YGStyle(); YGStyle defaultYogaStyle = YGStyle();
YGStyle currentYogaStyle = yogaStyle_; YGStyle currentYogaStyle = yogaStyle;
#define YOGA_STYLE_PROPS_ADD_TO_SET(stringName, propertyName, accessor, convertor) \ #define YOGA_STYLE_PROPS_ADD_TO_SET(stringName, propertyName, accessor, convertor) \
{ \ { \

View File

@ -23,16 +23,18 @@ class YogaStylableProps:
public virtual DebugStringConvertible { public virtual DebugStringConvertible {
public: public:
const YGStyle &getYogaStyle() const;
void apply(const RawProps &rawProps); YogaStylableProps() = default;
YogaStylableProps(const YGStyle &yogaStyle);
YogaStylableProps(const YogaStylableProps &sourceProps, const RawProps &rawProps);
#pragma mark - Props
const YGStyle yogaStyle {};
#pragma mark - DebugStringConvertible #pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList getDebugProps() const override; SharedDebugStringConvertibleList getDebugProps() const override;
protected:
YGStyle yogaStyle_ {};
}; };
} // namespace react } // namespace react