Exclude raw props from view shadow nodes

Summary:
With the `MapBuffer`-based props calculated from C++ props, there's no need to keep `rawProps` around for Android views.

This change makes sure that the `rawProps` field is only initialized under the feature flag that is responsible for enabling `MapBuffer` for prop diffing, potentially decreasing memory footprint and speeding up node initialization as JS props don't have to be converted to `folly::dynamic` anymore.

For layout animations, props rely on C++ values, so there's no need to update `rawProps` values either.

Changelog: [Internal][Android] - Do not init `rawProps` when mapbuffer serialization is used for ViewProps.

Reviewed By: mdvacca

Differential Revision: D33793044

fbshipit-source-id: 35873b10d3ca8b152b25344ef2c27aff9641846f
This commit is contained in:
Andrei Shikov 2022-02-22 16:29:13 -08:00 коммит произвёл Facebook GitHub Bot
Родитель 5928105d9d
Коммит 1953f6f02e
17 изменённых файлов: 96 добавлений и 40 удалений

Просмотреть файл

@ -223,6 +223,9 @@ local_ref<jobject> FabricMountingManager::getProps(
ShadowView const &newShadowView) { ShadowView const &newShadowView) {
if (useMapBufferForViewProps_ && if (useMapBufferForViewProps_ &&
newShadowView.traits.check(ShadowNodeTraits::Trait::View)) { newShadowView.traits.check(ShadowNodeTraits::Trait::View)) {
react_native_assert(
newShadowView.props->rawProps.empty() &&
"Raw props must be empty when views are using mapbuffer");
auto oldProps = oldShadowView.props != nullptr auto oldProps = oldShadowView.props != nullptr
? static_cast<ViewProps const &>(*oldShadowView.props) ? static_cast<ViewProps const &>(*oldShadowView.props)
: ViewProps{}; : ViewProps{};

Просмотреть файл

@ -60,6 +60,7 @@ rn_xplat_cxx_library(
react_native_xplat_target("react/renderer/core:core"), react_native_xplat_target("react/renderer/core:core"),
react_native_xplat_target("react/renderer/debug:debug"), react_native_xplat_target("react/renderer/debug:debug"),
react_native_xplat_target("react/renderer/graphics:graphics"), react_native_xplat_target("react/renderer/graphics:graphics"),
react_native_xplat_target("react/config:config"),
react_native_xplat_target("logger:logger"), react_native_xplat_target("logger:logger"),
], ],
) )

Просмотреть файл

@ -21,8 +21,9 @@ namespace react {
ViewProps::ViewProps( ViewProps::ViewProps(
const PropsParserContext &context, const PropsParserContext &context,
ViewProps const &sourceProps, ViewProps const &sourceProps,
RawProps const &rawProps) RawProps const &rawProps,
: YogaStylableProps(context, sourceProps, rawProps), bool shouldSetRawProps)
: YogaStylableProps(context, sourceProps, rawProps, shouldSetRawProps),
AccessibilityProps(context, sourceProps, rawProps), AccessibilityProps(context, sourceProps, rawProps),
opacity(convertRawProp( opacity(convertRawProp(
context, context,

Просмотреть файл

@ -30,7 +30,8 @@ class ViewProps : public YogaStylableProps, public AccessibilityProps {
ViewProps( ViewProps(
const PropsParserContext &context, const PropsParserContext &context,
ViewProps const &sourceProps, ViewProps const &sourceProps,
RawProps const &rawProps); RawProps const &rawProps,
bool shouldSetRawProps = true);
#pragma mark - Props #pragma mark - Props

Просмотреть файл

@ -44,10 +44,12 @@ static inline void interpolateViewProps(
// mounting layer. Once we can remove this, we should change `rawProps` to // mounting layer. Once we can remove this, we should change `rawProps` to
// be const again. // be const again.
#ifdef ANDROID #ifdef ANDROID
interpolatedProps->rawProps["opacity"] = interpolatedProps->opacity; if (!interpolatedProps->rawProps.isNull()) {
interpolatedProps->rawProps["opacity"] = interpolatedProps->opacity;
interpolatedProps->rawProps["transform"] = interpolatedProps->rawProps["transform"] =
(folly::dynamic)interpolatedProps->transform; (folly::dynamic)interpolatedProps->transform;
}
#endif #endif
} }

Просмотреть файл

@ -6,6 +6,7 @@
*/ */
#include "ViewShadowNode.h" #include "ViewShadowNode.h"
#include <react/config/ReactNativeConfig.h>
#include <react/renderer/components/view/primitives.h> #include <react/renderer/components/view/primitives.h>
namespace facebook { namespace facebook {
@ -13,6 +14,37 @@ namespace react {
char const ViewComponentName[] = "View"; char const ViewComponentName[] = "View";
static inline bool keepRawValuesInViewProps(PropsParserContext const &context) {
static bool shouldUseRawProps = true;
#ifdef ANDROID
static bool initialized = false;
if (!initialized) {
auto config =
context.contextContainer.find<std::shared_ptr<const ReactNativeConfig>>(
"ReactNativeConfig");
if (config.has_value()) {
initialized = true;
shouldUseRawProps = !config.value()->getBool(
"react_native_new_architecture:use_mapbuffer_for_viewprops");
}
}
#endif
return shouldUseRawProps;
}
ViewShadowNodeProps::ViewShadowNodeProps(
PropsParserContext const &context,
ViewShadowNodeProps const &sourceProps,
RawProps const &rawProps)
: ViewProps(
context,
sourceProps,
rawProps,
keepRawValuesInViewProps(context)){};
ViewShadowNode::ViewShadowNode( ViewShadowNode::ViewShadowNode(
ShadowNodeFragment const &fragment, ShadowNodeFragment const &fragment,
ShadowNodeFamily::Shared const &family, ShadowNodeFamily::Shared const &family,

Просмотреть файл

@ -15,12 +15,24 @@ namespace react {
extern const char ViewComponentName[]; extern const char ViewComponentName[];
/**
* Implementation of the ViewProps that propagates feature flag.
*/
class ViewShadowNodeProps final : public ViewProps {
public:
ViewShadowNodeProps() = default;
ViewShadowNodeProps(
const PropsParserContext &context,
ViewShadowNodeProps const &sourceProps,
RawProps const &rawProps);
};
/* /*
* `ShadowNode` for <View> component. * `ShadowNode` for <View> component.
*/ */
class ViewShadowNode final : public ConcreteViewShadowNode< class ViewShadowNode final : public ConcreteViewShadowNode<
ViewComponentName, ViewComponentName,
ViewProps, ViewShadowNodeProps,
ViewEventEmitter> { ViewEventEmitter> {
public: public:
static ShadowNodeTraits BaseTraits() { static ShadowNodeTraits BaseTraits() {

Просмотреть файл

@ -22,8 +22,9 @@ namespace react {
YogaStylableProps::YogaStylableProps( YogaStylableProps::YogaStylableProps(
const PropsParserContext &context, const PropsParserContext &context,
YogaStylableProps const &sourceProps, YogaStylableProps const &sourceProps,
RawProps const &rawProps) RawProps const &rawProps,
: Props(context, sourceProps, rawProps), bool shouldSetRawProps)
: Props(context, sourceProps, rawProps, shouldSetRawProps),
yogaStyle(convertRawProp(context, rawProps, sourceProps.yogaStyle)){}; yogaStyle(convertRawProp(context, rawProps, sourceProps.yogaStyle)){};
#pragma mark - DebugStringConvertible #pragma mark - DebugStringConvertible

Просмотреть файл

@ -22,7 +22,8 @@ class YogaStylableProps : public Props {
YogaStylableProps( YogaStylableProps(
const PropsParserContext &context, const PropsParserContext &context,
YogaStylableProps const &sourceProps, YogaStylableProps const &sourceProps,
RawProps const &rawProps); RawProps const &rawProps,
bool shouldSetRawProps = true);
#pragma mark - Props #pragma mark - Props

Просмотреть файл

@ -74,7 +74,7 @@ class LayoutTest : public ::testing::Test {
Element<ViewShadowNode>() Element<ViewShadowNode>()
.reference(viewShadowNodeA_) .reference(viewShadowNodeA_)
.props([] { .props([] {
auto sharedProps = std::make_shared<ViewProps>(); auto sharedProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *sharedProps; auto &props = *sharedProps;
auto &yogaStyle = props.yogaStyle; auto &yogaStyle = props.yogaStyle;
yogaStyle.positionType() = YGPositionTypeAbsolute; yogaStyle.positionType() = YGPositionTypeAbsolute;
@ -86,7 +86,7 @@ class LayoutTest : public ::testing::Test {
Element<ViewShadowNode>() Element<ViewShadowNode>()
.reference(viewShadowNodeAB_) .reference(viewShadowNodeAB_)
.props([] { .props([] {
auto sharedProps = std::make_shared<ViewProps>(); auto sharedProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *sharedProps; auto &props = *sharedProps;
auto &yogaStyle = props.yogaStyle; auto &yogaStyle = props.yogaStyle;
yogaStyle.positionType() = YGPositionTypeAbsolute; yogaStyle.positionType() = YGPositionTypeAbsolute;
@ -100,7 +100,7 @@ class LayoutTest : public ::testing::Test {
Element<ViewShadowNode>() Element<ViewShadowNode>()
.reference(viewShadowNodeABC_) .reference(viewShadowNodeABC_)
.props([=] { .props([=] {
auto sharedProps = std::make_shared<ViewProps>(); auto sharedProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *sharedProps; auto &props = *sharedProps;
auto &yogaStyle = props.yogaStyle; auto &yogaStyle = props.yogaStyle;
@ -119,7 +119,7 @@ class LayoutTest : public ::testing::Test {
Element<ViewShadowNode>() Element<ViewShadowNode>()
.reference(viewShadowNodeABCD_) .reference(viewShadowNodeABCD_)
.props([] { .props([] {
auto sharedProps = std::make_shared<ViewProps>(); auto sharedProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *sharedProps; auto &props = *sharedProps;
auto &yogaStyle = props.yogaStyle; auto &yogaStyle = props.yogaStyle;
yogaStyle.positionType() = YGPositionTypeAbsolute; yogaStyle.positionType() = YGPositionTypeAbsolute;
@ -133,7 +133,7 @@ class LayoutTest : public ::testing::Test {
Element<ViewShadowNode>() Element<ViewShadowNode>()
.reference(viewShadowNodeABE_) .reference(viewShadowNodeABE_)
.props([] { .props([] {
auto sharedProps = std::make_shared<ViewProps>(); auto sharedProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *sharedProps; auto &props = *sharedProps;
auto &yogaStyle = props.yogaStyle; auto &yogaStyle = props.yogaStyle;
yogaStyle.positionType() = YGPositionTypeAbsolute; yogaStyle.positionType() = YGPositionTypeAbsolute;

Просмотреть файл

@ -49,7 +49,7 @@ class YogaDirtyFlagTest : public ::testing::Test {
/* /*
* Some non-default props. * Some non-default props.
*/ */
auto mutableViewProps = std::make_shared<ViewProps>(); auto mutableViewProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *mutableViewProps; auto &props = *mutableViewProps;
props.nativeId = "native Id"; props.nativeId = "native Id";
props.opacity = 0.5; props.opacity = 0.5;
@ -111,7 +111,7 @@ TEST_F(YogaDirtyFlagTest, changingNonLayoutSubPropsMustNotDirtyYogaNode) {
*/ */
auto newRootShadowNode = rootShadowNode_->cloneTree( auto newRootShadowNode = rootShadowNode_->cloneTree(
innerShadowNode_->getFamily(), [](ShadowNode const &oldShadowNode) { innerShadowNode_->getFamily(), [](ShadowNode const &oldShadowNode) {
auto viewProps = std::make_shared<ViewProps>(); auto viewProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *viewProps; auto &props = *viewProps;
props.nativeId = "some new native Id"; props.nativeId = "some new native Id";
@ -135,7 +135,7 @@ TEST_F(YogaDirtyFlagTest, changingLayoutSubPropsMustDirtyYogaNode) {
*/ */
auto newRootShadowNode = rootShadowNode_->cloneTree( auto newRootShadowNode = rootShadowNode_->cloneTree(
innerShadowNode_->getFamily(), [](ShadowNode const &oldShadowNode) { innerShadowNode_->getFamily(), [](ShadowNode const &oldShadowNode) {
auto viewProps = std::make_shared<ViewProps>(); auto viewProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *viewProps; auto &props = *viewProps;
props.yogaStyle.alignContent() = YGAlignBaseline; props.yogaStyle.alignContent() = YGAlignBaseline;

Просмотреть файл

@ -16,7 +16,8 @@ namespace react {
Props::Props( Props::Props(
const PropsParserContext &context, const PropsParserContext &context,
const Props &sourceProps, const Props &sourceProps,
const RawProps &rawProps) const RawProps &rawProps,
const bool shouldSetRawProps)
: nativeId(convertRawProp( : nativeId(convertRawProp(
context, context,
rawProps, rawProps,
@ -26,7 +27,9 @@ Props::Props(
revision(sourceProps.revision + 1) revision(sourceProps.revision + 1)
#ifdef ANDROID #ifdef ANDROID
, ,
rawProps((folly::dynamic)rawProps) rawProps(
shouldSetRawProps ? (folly::dynamic)rawProps
: /* null */ folly::dynamic())
#endif #endif
{}; {};

Просмотреть файл

@ -33,7 +33,8 @@ class Props : public virtual Sealable, public virtual DebugStringConvertible {
Props( Props(
const PropsParserContext &context, const PropsParserContext &context,
const Props &sourceProps, const Props &sourceProps,
RawProps const &rawProps); RawProps const &rawProps,
bool shouldSetRawProps = true);
virtual ~Props() = default; virtual ~Props() = default;
std::string nativeId; std::string nativeId;

Просмотреть файл

@ -45,9 +45,9 @@ TEST(FindNodeAtPointTest, withoutTransform) {
}) })
}) })
}); });
auto parentShadowNode = builder.build(element); auto parentShadowNode = builder.build(element);
EXPECT_EQ( EXPECT_EQ(
LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {115, 115})->getTag(), 3); LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {115, 115})->getTag(), 3);
EXPECT_EQ(LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {105, 105})->getTag(), 2); EXPECT_EQ(LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {105, 105})->getTag(), 2);
@ -91,7 +91,7 @@ TEST(FindNodeAtPointTest, viewIsTranslated) {
}) })
}) })
}); });
auto parentShadowNode = builder.build(element); auto parentShadowNode = builder.build(element);
EXPECT_EQ( EXPECT_EQ(
@ -125,7 +125,7 @@ TEST(FindNodeAtPointTest, viewIsScaled) {
Element<ViewShadowNode>() Element<ViewShadowNode>()
.tag(3) .tag(3)
.props([] { .props([] {
auto sharedProps = std::make_shared<ViewProps>(); auto sharedProps = std::make_shared<ViewShadowNodeProps>();
sharedProps->transform = Transform::Scale(0.5, 0.5, 0); sharedProps->transform = Transform::Scale(0.5, 0.5, 0);
return sharedProps; return sharedProps;
}) })
@ -137,7 +137,7 @@ TEST(FindNodeAtPointTest, viewIsScaled) {
}) })
}) })
}); });
auto parentShadowNode = builder.build(element); auto parentShadowNode = builder.build(element);
EXPECT_EQ( EXPECT_EQ(
@ -175,9 +175,9 @@ TEST(FindNodeAtPointTest, overlappingViews) {
shadowNode.setLayoutMetrics(layoutMetrics); shadowNode.setLayoutMetrics(layoutMetrics);
}) })
}); });
auto parentShadowNode = builder.build(element); auto parentShadowNode = builder.build(element);
EXPECT_EQ( EXPECT_EQ(
LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {50, 50})->getTag(), 3); LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {50, 50})->getTag(), 3);
} }
@ -198,7 +198,7 @@ TEST(FindNodeAtPointTest, overlappingViewsWithZIndex) {
Element<ViewShadowNode>() Element<ViewShadowNode>()
.tag(2) .tag(2)
.props([] { .props([] {
auto sharedProps = std::make_shared<ViewProps>(); auto sharedProps = std::make_shared<ViewShadowNodeProps>();
sharedProps->zIndex = 1; sharedProps->zIndex = 1;
auto &yogaStyle = sharedProps->yogaStyle; auto &yogaStyle = sharedProps->yogaStyle;
yogaStyle.positionType() = YGPositionTypeAbsolute; yogaStyle.positionType() = YGPositionTypeAbsolute;
@ -219,11 +219,9 @@ TEST(FindNodeAtPointTest, overlappingViewsWithZIndex) {
shadowNode.setLayoutMetrics(layoutMetrics); shadowNode.setLayoutMetrics(layoutMetrics);
}) })
}); });
auto parentShadowNode = builder.build(element); auto parentShadowNode = builder.build(element);
EXPECT_EQ( EXPECT_EQ(
LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {50, 50})->getTag(), 2); LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {50, 50})->getTag(), 2);
} }

Просмотреть файл

@ -148,7 +148,7 @@ TEST(LayoutableShadowNodeTest, relativeLayoutMetricsOnTransformedNode) {
shadowNode.setLayoutMetrics(layoutMetrics); shadowNode.setLayoutMetrics(layoutMetrics);
}) })
.props([] { .props([] {
auto sharedProps = std::make_shared<ViewProps>(); auto sharedProps = std::make_shared<ViewShadowNodeProps>();
sharedProps->transform = Transform::Scale(0.5, 0.5, 1); sharedProps->transform = Transform::Scale(0.5, 0.5, 1);
return sharedProps; return sharedProps;
}) })
@ -199,7 +199,7 @@ TEST(LayoutableShadowNodeTest, relativeLayoutMetricsOnTransformedParent) {
.children({ .children({
Element<ViewShadowNode>() Element<ViewShadowNode>()
.props([] { .props([] {
auto sharedProps = std::make_shared<ViewProps>(); auto sharedProps = std::make_shared<ViewShadowNodeProps>();
sharedProps->transform = Transform::Scale(0.5, 0.5, 1); sharedProps->transform = Transform::Scale(0.5, 0.5, 1);
return sharedProps; return sharedProps;
}) })
@ -280,7 +280,7 @@ TEST(LayoutableShadowNodeTest, relativeLayoutMetricsOnSameTransformedNode) {
auto element = auto element =
Element<ViewShadowNode>() Element<ViewShadowNode>()
.props([] { .props([] {
auto sharedProps = std::make_shared<ViewProps>(); auto sharedProps = std::make_shared<ViewShadowNodeProps>();
sharedProps->transform = Transform::Scale(2, 2, 1); sharedProps->transform = Transform::Scale(2, 2, 1);
return sharedProps; return sharedProps;
}) })

Просмотреть файл

@ -26,7 +26,7 @@ TEST(ElementTest, testNormalCases) {
auto shadowNodeAB = std::shared_ptr<ViewShadowNode>{}; auto shadowNodeAB = std::shared_ptr<ViewShadowNode>{};
auto shadowNodeABA = std::shared_ptr<ViewShadowNode>{}; auto shadowNodeABA = std::shared_ptr<ViewShadowNode>{};
auto propsAA = std::make_shared<ViewProps>(); auto propsAA = std::make_shared<ViewShadowNodeProps>();
propsAA->nativeId = "node AA"; propsAA->nativeId = "node AA";
// clang-format off // clang-format off
@ -51,7 +51,7 @@ TEST(ElementTest, testNormalCases) {
.reference(shadowNodeAB) .reference(shadowNodeAB)
.tag(3) .tag(3)
.props([]() { .props([]() {
auto props = std::make_shared<ViewProps>(); auto props = std::make_shared<ViewShadowNodeProps>();
props->nativeId = "node AB"; props->nativeId = "node AB";
return props; return props;
}) })
@ -60,7 +60,7 @@ TEST(ElementTest, testNormalCases) {
.reference(shadowNodeABA) .reference(shadowNodeABA)
.tag(4) .tag(4)
.props([]() { .props([]() {
auto props = std::make_shared<ViewProps>(); auto props = std::make_shared<ViewShadowNodeProps>();
props->nativeId = "node ABA"; props->nativeId = "node ABA";
return props; return props;
}) })

Просмотреть файл

@ -158,7 +158,7 @@ class StackingContextTest : public ::testing::Test {
rootShadowNode_ = rootShadowNode_ =
std::static_pointer_cast<RootShadowNode>(rootShadowNode_->cloneTree( std::static_pointer_cast<RootShadowNode>(rootShadowNode_->cloneTree(
node->getFamily(), [&](ShadowNode const &oldShadowNode) { node->getFamily(), [&](ShadowNode const &oldShadowNode) {
auto viewProps = std::make_shared<ViewProps>(); auto viewProps = std::make_shared<ViewShadowNodeProps>();
callback(*viewProps); callback(*viewProps);
return oldShadowNode.clone(ShadowNodeFragment{viewProps}); return oldShadowNode.clone(ShadowNodeFragment{viewProps});
})); }));