Skip to content

Commit 7cc791b

Browse files
sherginfacebook-github-bot
authored andcommitted
Fabric: ComponentDescriptor::cloneProps() now never returns the base props objects
Summary: The diff changes how the `empty raw props` optimization works in `ComponentDescriptor::cloneProps()`. Now it only fires only when the base `props` object is null, which is practically all production cases we have (and care about). (I tried, in a normal run there were no cases where the empty raw props were passed with non-null props.) From the other side, the old behavior that may return the same props objects previously several times created bugs and practically unexpected results and practically disallowed to clone props objects easily. Changelog: [Internal] Fabric-specific internal change. Reviewed By: JoshuaGross Differential Revision: D21110608 fbshipit-source-id: 884807cd8e9c5c3e6cc1c9e4c1f0227259cc21fb
1 parent 28dce36 commit 7cc791b

File tree

3 files changed

+11
-2
lines changed

3 files changed

+11
-2
lines changed

ReactCommon/fabric/core/componentdescriptor/ComponentDescriptor.h

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ class ComponentDescriptor {
9898
* `props` and `rawProps` applied on top of this.
9999
* If `props` is `nullptr`, a default `Props` object (with default values)
100100
* will be used.
101+
* Must return an object which is NOT pointer equal to `props`.
101102
*/
102103
virtual SharedProps cloneProps(
103104
const SharedProps &props,

ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,13 @@ class ConcreteComponentDescriptor : public ComponentDescriptor {
108108
dynamic_cast<ConcreteProps const *>(props.get()) &&
109109
"Provided `props` has an incompatible type.");
110110

111-
if (rawProps.isEmpty()) {
112-
return props ? props : ShadowNodeT::defaultSharedProps();
111+
// Optimization:
112+
// Quite often nodes are constructed with default/empty props: the base
113+
// `props` object is `null` (there no base because it's not cloning) and the
114+
// `rawProps` is empty. In this case, we can return the default props object
115+
// of a concrete type entirely bypassing parsing.
116+
if (!props && rawProps.isEmpty()) {
117+
return ShadowNodeT::defaultSharedProps();
113118
}
114119

115120
rawProps.parse(rawPropsParser_);

ReactCommon/fabric/core/tests/ComponentDescriptorTest.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ TEST(ComponentDescriptorTest, cloneShadowNode) {
7272
EXPECT_EQ(cloned->getTag(), 9);
7373
EXPECT_EQ(cloned->getSurfaceId(), 1);
7474
EXPECT_STREQ(cloned->getProps()->nativeId.c_str(), "abc");
75+
76+
auto clonedButSameProps = descriptor->cloneProps(props, RawProps());
77+
EXPECT_NE(clonedButSameProps, props);
7578
}
7679

7780
TEST(ComponentDescriptorTest, appendChild) {

0 commit comments

Comments
 (0)