Skip to content

Commit

Permalink
Exclude raw props from view shadow nodes
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Andrei Shikov authored and facebook-github-bot committed Feb 23, 2022
1 parent 5928105 commit 1953f6f
Show file tree
Hide file tree
Showing 17 changed files with 96 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ local_ref<jobject> FabricMountingManager::getProps(
ShadowView const &newShadowView) {
if (useMapBufferForViewProps_ &&
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
? static_cast<ViewProps const &>(*oldShadowView.props)
: ViewProps{};
Expand Down
1 change: 1 addition & 0 deletions ReactCommon/react/renderer/components/view/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ rn_xplat_cxx_library(
react_native_xplat_target("react/renderer/core:core"),
react_native_xplat_target("react/renderer/debug:debug"),
react_native_xplat_target("react/renderer/graphics:graphics"),
react_native_xplat_target("react/config:config"),
react_native_xplat_target("logger:logger"),
],
)
Expand Down
5 changes: 3 additions & 2 deletions ReactCommon/react/renderer/components/view/ViewProps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ namespace react {
ViewProps::ViewProps(
const PropsParserContext &context,
ViewProps const &sourceProps,
RawProps const &rawProps)
: YogaStylableProps(context, sourceProps, rawProps),
RawProps const &rawProps,
bool shouldSetRawProps)
: YogaStylableProps(context, sourceProps, rawProps, shouldSetRawProps),
AccessibilityProps(context, sourceProps, rawProps),
opacity(convertRawProp(
context,
Expand Down
3 changes: 2 additions & 1 deletion ReactCommon/react/renderer/components/view/ViewProps.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class ViewProps : public YogaStylableProps, public AccessibilityProps {
ViewProps(
const PropsParserContext &context,
ViewProps const &sourceProps,
RawProps const &rawProps);
RawProps const &rawProps,
bool shouldSetRawProps = true);

#pragma mark - Props

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ static inline void interpolateViewProps(
// mounting layer. Once we can remove this, we should change `rawProps` to
// be const again.
#ifdef ANDROID
interpolatedProps->rawProps["opacity"] = interpolatedProps->opacity;
if (!interpolatedProps->rawProps.isNull()) {
interpolatedProps->rawProps["opacity"] = interpolatedProps->opacity;

interpolatedProps->rawProps["transform"] =
(folly::dynamic)interpolatedProps->transform;
interpolatedProps->rawProps["transform"] =
(folly::dynamic)interpolatedProps->transform;
}
#endif
}

Expand Down
32 changes: 32 additions & 0 deletions ReactCommon/react/renderer/components/view/ViewShadowNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,45 @@
*/

#include "ViewShadowNode.h"
#include <react/config/ReactNativeConfig.h>
#include <react/renderer/components/view/primitives.h>

namespace facebook {
namespace react {

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(
ShadowNodeFragment const &fragment,
ShadowNodeFamily::Shared const &family,
Expand Down
14 changes: 13 additions & 1 deletion ReactCommon/react/renderer/components/view/ViewShadowNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,24 @@ namespace react {

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.
*/
class ViewShadowNode final : public ConcreteViewShadowNode<
ViewComponentName,
ViewProps,
ViewShadowNodeProps,
ViewEventEmitter> {
public:
static ShadowNodeTraits BaseTraits() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ namespace react {
YogaStylableProps::YogaStylableProps(
const PropsParserContext &context,
YogaStylableProps const &sourceProps,
RawProps const &rawProps)
: Props(context, sourceProps, rawProps),
RawProps const &rawProps,
bool shouldSetRawProps)
: Props(context, sourceProps, rawProps, shouldSetRawProps),
yogaStyle(convertRawProp(context, rawProps, sourceProps.yogaStyle)){};

#pragma mark - DebugStringConvertible
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ class YogaStylableProps : public Props {
YogaStylableProps(
const PropsParserContext &context,
YogaStylableProps const &sourceProps,
RawProps const &rawProps);
RawProps const &rawProps,
bool shouldSetRawProps = true);

#pragma mark - Props

Expand Down
10 changes: 5 additions & 5 deletions ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class LayoutTest : public ::testing::Test {
Element<ViewShadowNode>()
.reference(viewShadowNodeA_)
.props([] {
auto sharedProps = std::make_shared<ViewProps>();
auto sharedProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *sharedProps;
auto &yogaStyle = props.yogaStyle;
yogaStyle.positionType() = YGPositionTypeAbsolute;
Expand All @@ -86,7 +86,7 @@ class LayoutTest : public ::testing::Test {
Element<ViewShadowNode>()
.reference(viewShadowNodeAB_)
.props([] {
auto sharedProps = std::make_shared<ViewProps>();
auto sharedProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *sharedProps;
auto &yogaStyle = props.yogaStyle;
yogaStyle.positionType() = YGPositionTypeAbsolute;
Expand All @@ -100,7 +100,7 @@ class LayoutTest : public ::testing::Test {
Element<ViewShadowNode>()
.reference(viewShadowNodeABC_)
.props([=] {
auto sharedProps = std::make_shared<ViewProps>();
auto sharedProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *sharedProps;
auto &yogaStyle = props.yogaStyle;

Expand All @@ -119,7 +119,7 @@ class LayoutTest : public ::testing::Test {
Element<ViewShadowNode>()
.reference(viewShadowNodeABCD_)
.props([] {
auto sharedProps = std::make_shared<ViewProps>();
auto sharedProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *sharedProps;
auto &yogaStyle = props.yogaStyle;
yogaStyle.positionType() = YGPositionTypeAbsolute;
Expand All @@ -133,7 +133,7 @@ class LayoutTest : public ::testing::Test {
Element<ViewShadowNode>()
.reference(viewShadowNodeABE_)
.props([] {
auto sharedProps = std::make_shared<ViewProps>();
auto sharedProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *sharedProps;
auto &yogaStyle = props.yogaStyle;
yogaStyle.positionType() = YGPositionTypeAbsolute;
Expand Down
6 changes: 3 additions & 3 deletions ReactCommon/react/renderer/components/view/tests/ViewTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class YogaDirtyFlagTest : public ::testing::Test {
/*
* Some non-default props.
*/
auto mutableViewProps = std::make_shared<ViewProps>();
auto mutableViewProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *mutableViewProps;
props.nativeId = "native Id";
props.opacity = 0.5;
Expand Down Expand Up @@ -111,7 +111,7 @@ TEST_F(YogaDirtyFlagTest, changingNonLayoutSubPropsMustNotDirtyYogaNode) {
*/
auto newRootShadowNode = rootShadowNode_->cloneTree(
innerShadowNode_->getFamily(), [](ShadowNode const &oldShadowNode) {
auto viewProps = std::make_shared<ViewProps>();
auto viewProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *viewProps;

props.nativeId = "some new native Id";
Expand All @@ -135,7 +135,7 @@ TEST_F(YogaDirtyFlagTest, changingLayoutSubPropsMustDirtyYogaNode) {
*/
auto newRootShadowNode = rootShadowNode_->cloneTree(
innerShadowNode_->getFamily(), [](ShadowNode const &oldShadowNode) {
auto viewProps = std::make_shared<ViewProps>();
auto viewProps = std::make_shared<ViewShadowNodeProps>();
auto &props = *viewProps;

props.yogaStyle.alignContent() = YGAlignBaseline;
Expand Down
7 changes: 5 additions & 2 deletions ReactCommon/react/renderer/core/Props.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ namespace react {
Props::Props(
const PropsParserContext &context,
const Props &sourceProps,
const RawProps &rawProps)
const RawProps &rawProps,
const bool shouldSetRawProps)
: nativeId(convertRawProp(
context,
rawProps,
Expand All @@ -26,7 +27,9 @@ Props::Props(
revision(sourceProps.revision + 1)
#ifdef ANDROID
,
rawProps((folly::dynamic)rawProps)
rawProps(
shouldSetRawProps ? (folly::dynamic)rawProps
: /* null */ folly::dynamic())
#endif
{};

Expand Down
3 changes: 2 additions & 1 deletion ReactCommon/react/renderer/core/Props.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ class Props : public virtual Sealable, public virtual DebugStringConvertible {
Props(
const PropsParserContext &context,
const Props &sourceProps,
RawProps const &rawProps);
RawProps const &rawProps,
bool shouldSetRawProps = true);
virtual ~Props() = default;

std::string nativeId;
Expand Down
22 changes: 10 additions & 12 deletions ReactCommon/react/renderer/core/tests/FindNodeAtPointTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ TEST(FindNodeAtPointTest, withoutTransform) {
})
})
});

auto parentShadowNode = builder.build(element);

EXPECT_EQ(
LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {115, 115})->getTag(), 3);
EXPECT_EQ(LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {105, 105})->getTag(), 2);
Expand Down Expand Up @@ -91,7 +91,7 @@ TEST(FindNodeAtPointTest, viewIsTranslated) {
})
})
});

auto parentShadowNode = builder.build(element);

EXPECT_EQ(
Expand Down Expand Up @@ -125,7 +125,7 @@ TEST(FindNodeAtPointTest, viewIsScaled) {
Element<ViewShadowNode>()
.tag(3)
.props([] {
auto sharedProps = std::make_shared<ViewProps>();
auto sharedProps = std::make_shared<ViewShadowNodeProps>();
sharedProps->transform = Transform::Scale(0.5, 0.5, 0);
return sharedProps;
})
Expand All @@ -137,7 +137,7 @@ TEST(FindNodeAtPointTest, viewIsScaled) {
})
})
});

auto parentShadowNode = builder.build(element);

EXPECT_EQ(
Expand Down Expand Up @@ -175,9 +175,9 @@ TEST(FindNodeAtPointTest, overlappingViews) {
shadowNode.setLayoutMetrics(layoutMetrics);
})
});

auto parentShadowNode = builder.build(element);

EXPECT_EQ(
LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {50, 50})->getTag(), 3);
}
Expand All @@ -198,7 +198,7 @@ TEST(FindNodeAtPointTest, overlappingViewsWithZIndex) {
Element<ViewShadowNode>()
.tag(2)
.props([] {
auto sharedProps = std::make_shared<ViewProps>();
auto sharedProps = std::make_shared<ViewShadowNodeProps>();
sharedProps->zIndex = 1;
auto &yogaStyle = sharedProps->yogaStyle;
yogaStyle.positionType() = YGPositionTypeAbsolute;
Expand All @@ -219,11 +219,9 @@ TEST(FindNodeAtPointTest, overlappingViewsWithZIndex) {
shadowNode.setLayoutMetrics(layoutMetrics);
})
});

auto parentShadowNode = builder.build(element);

EXPECT_EQ(
LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {50, 50})->getTag(), 2);
}


Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ TEST(LayoutableShadowNodeTest, relativeLayoutMetricsOnTransformedNode) {
shadowNode.setLayoutMetrics(layoutMetrics);
})
.props([] {
auto sharedProps = std::make_shared<ViewProps>();
auto sharedProps = std::make_shared<ViewShadowNodeProps>();
sharedProps->transform = Transform::Scale(0.5, 0.5, 1);
return sharedProps;
})
Expand Down Expand Up @@ -199,7 +199,7 @@ TEST(LayoutableShadowNodeTest, relativeLayoutMetricsOnTransformedParent) {
.children({
Element<ViewShadowNode>()
.props([] {
auto sharedProps = std::make_shared<ViewProps>();
auto sharedProps = std::make_shared<ViewShadowNodeProps>();
sharedProps->transform = Transform::Scale(0.5, 0.5, 1);
return sharedProps;
})
Expand Down Expand Up @@ -280,7 +280,7 @@ TEST(LayoutableShadowNodeTest, relativeLayoutMetricsOnSameTransformedNode) {
auto element =
Element<ViewShadowNode>()
.props([] {
auto sharedProps = std::make_shared<ViewProps>();
auto sharedProps = std::make_shared<ViewShadowNodeProps>();
sharedProps->transform = Transform::Scale(2, 2, 1);
return sharedProps;
})
Expand Down
6 changes: 3 additions & 3 deletions ReactCommon/react/renderer/element/tests/ElementTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ TEST(ElementTest, testNormalCases) {
auto shadowNodeAB = 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";

// clang-format off
Expand All @@ -51,7 +51,7 @@ TEST(ElementTest, testNormalCases) {
.reference(shadowNodeAB)
.tag(3)
.props([]() {
auto props = std::make_shared<ViewProps>();
auto props = std::make_shared<ViewShadowNodeProps>();
props->nativeId = "node AB";
return props;
})
Expand All @@ -60,7 +60,7 @@ TEST(ElementTest, testNormalCases) {
.reference(shadowNodeABA)
.tag(4)
.props([]() {
auto props = std::make_shared<ViewProps>();
auto props = std::make_shared<ViewShadowNodeProps>();
props->nativeId = "node ABA";
return props;
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ class StackingContextTest : public ::testing::Test {
rootShadowNode_ =
std::static_pointer_cast<RootShadowNode>(rootShadowNode_->cloneTree(
node->getFamily(), [&](ShadowNode const &oldShadowNode) {
auto viewProps = std::make_shared<ViewProps>();
auto viewProps = std::make_shared<ViewShadowNodeProps>();
callback(*viewProps);
return oldShadowNode.clone(ShadowNodeFragment{viewProps});
}));
Expand Down

0 comments on commit 1953f6f

Please sign in to comment.