mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Introducing: Props forwarding whe cloning shadow node
Summary: Changelog: [internal] If ShadowNode has not been mounted, forward rawProps from `sourceShadowNode` to newly cloned shadow node. This is Android specific change, on iOS the logic should remain unchanged. Reviewed By: JoshuaGross Differential Revision: D26049264 fbshipit-source-id: 7c201bc2d4e99eec024065714d2172c5c817153c
This commit is contained in:
committed by
Facebook GitHub Bot
parent
78df536c78
commit
fc1f0df465
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Constants.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
static bool isPropsForwardingEnabled = false;
|
||||
|
||||
void Constants::setPropsForwardingEnabled(bool propsForwardingEnabled) {
|
||||
isPropsForwardingEnabled = propsForwardingEnabled;
|
||||
}
|
||||
|
||||
bool Constants::getPropsForwardingEnabled() {
|
||||
return isPropsForwardingEnabled;
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
struct Constants {
|
||||
/*
|
||||
Flag controling props forwarding when shadow node is cloned on Android.
|
||||
Has no effect on iOS.
|
||||
*/
|
||||
static void setPropsForwardingEnabled(bool propsForwardingEnabled);
|
||||
static bool getPropsForwardingEnabled();
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "ShadowNode.h"
|
||||
#include "Constants.h"
|
||||
#include "ShadowNodeFragment.h"
|
||||
|
||||
#include <better/small_vector.h>
|
||||
@@ -24,6 +25,33 @@ SharedShadowNodeSharedList ShadowNode::emptySharedShadowNodeSharedList() {
|
||||
return emptySharedShadowNodeSharedList;
|
||||
}
|
||||
|
||||
/*
|
||||
* On iOS, this method returns `props` if provided, `sourceShadowNode`'s props
|
||||
* otherwise. On Android, we forward props in case `sourceShadowNode` hasn't
|
||||
* been mounted. `Props::rawProps` are merged from `props` to a copy of
|
||||
* `sourceShadowNode.props_` and returned. This is necessary to enable
|
||||
* Background Executor and should be removed once reimplementation of JNI layer
|
||||
* is finished.
|
||||
*/
|
||||
SharedProps ShadowNode::propsForClonedShadowNode(
|
||||
ShadowNode const &sourceShadowNode,
|
||||
Props::Shared const &props) {
|
||||
#ifdef ANDROID
|
||||
if (Constants::getPropsForwardingEnabled()) {
|
||||
bool hasBeenMounted = sourceShadowNode.hasBeenMounted_;
|
||||
bool sourceNodeHasRawProps = !sourceShadowNode.getProps()->rawProps.empty();
|
||||
if (!hasBeenMounted && sourceNodeHasRawProps && props) {
|
||||
auto copiedProps = sourceShadowNode.getProps()->rawProps;
|
||||
copiedProps.merge_patch(props->rawProps);
|
||||
auto &castedProps = const_cast<Props &>(*props);
|
||||
castedProps.rawProps = copiedProps;
|
||||
return props;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return props ? props : sourceShadowNode.getProps();
|
||||
}
|
||||
|
||||
bool ShadowNode::sameFamily(const ShadowNode &first, const ShadowNode &second) {
|
||||
return first.family_ == second.family_;
|
||||
}
|
||||
@@ -60,13 +88,13 @@ ShadowNode::ShadowNode(
|
||||
}
|
||||
|
||||
ShadowNode::ShadowNode(
|
||||
const ShadowNode &sourceShadowNode,
|
||||
const ShadowNodeFragment &fragment)
|
||||
ShadowNode const &sourceShadowNode,
|
||||
ShadowNodeFragment const &fragment)
|
||||
:
|
||||
#if RN_DEBUG_STRING_CONVERTIBLE
|
||||
revision_(sourceShadowNode.revision_ + 1),
|
||||
#endif
|
||||
props_(fragment.props ? fragment.props : sourceShadowNode.props_),
|
||||
props_(propsForClonedShadowNode(sourceShadowNode, fragment.props)),
|
||||
children_(
|
||||
fragment.children ? fragment.children : sourceShadowNode.children_),
|
||||
state_(
|
||||
@@ -214,6 +242,7 @@ void ShadowNode::cloneChildrenIfShared() {
|
||||
void ShadowNode::setMounted(bool mounted) const {
|
||||
if (mounted) {
|
||||
family_->setMostRecentState(getState());
|
||||
hasBeenMounted_ = mounted;
|
||||
}
|
||||
|
||||
family_->eventEmitter_->setEnabled(mounted);
|
||||
|
||||
@@ -176,8 +176,6 @@ class ShadowNode : public Sealable, public DebugStringConvertible {
|
||||
*/
|
||||
void setMounted(bool mounted) const;
|
||||
|
||||
int getStateRevision() const;
|
||||
|
||||
#pragma mark - DebugStringConvertible
|
||||
|
||||
#if RN_DEBUG_STRING_CONVERTIBLE
|
||||
@@ -214,6 +212,12 @@ class ShadowNode : public Sealable, public DebugStringConvertible {
|
||||
*/
|
||||
ShadowNodeFamily::Shared family_;
|
||||
|
||||
mutable std::atomic<bool> hasBeenMounted_{false};
|
||||
|
||||
static SharedProps propsForClonedShadowNode(
|
||||
ShadowNode const &sourceShadowNode,
|
||||
Props::Shared const &props);
|
||||
|
||||
protected:
|
||||
/*
|
||||
* Traits associated with the particular `ShadowNode` class and an instance of
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <folly/dynamic.h>
|
||||
#include <glog/logging.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace folly;
|
||||
|
||||
/*
|
||||
Tests that verify expected behaviour from `folly::dynamic::merge_patch`.
|
||||
`merge_patch` is used for props forwarding on Android to enable Background
|
||||
Executor and will be removed once JNI layer is reimplmeneted.
|
||||
*/
|
||||
TEST(FollyDynamicMergePatchTest, handleNestedObjects) {
|
||||
dynamic map1 = dynamic::object;
|
||||
map1["style"] = dynamic::object("backgroundColor", "red");
|
||||
|
||||
dynamic map2 = dynamic::object;
|
||||
map2["style"] = dynamic::object("backgroundColor", "blue")("color", "black");
|
||||
map2["height"] = 100;
|
||||
|
||||
map2.merge_patch(map1);
|
||||
|
||||
EXPECT_TRUE(map2["style"].isObject());
|
||||
EXPECT_TRUE(map2["style"]["backgroundColor"].isString());
|
||||
EXPECT_TRUE(map2["style"]["color"].isString());
|
||||
EXPECT_TRUE(map2["height"].isInt());
|
||||
|
||||
EXPECT_EQ(map2["style"]["backgroundColor"], "red");
|
||||
EXPECT_EQ(map2["style"]["color"], "black");
|
||||
EXPECT_EQ(map2["height"], 100);
|
||||
}
|
||||
|
||||
TEST(FollyDynamicMergePatchTest, handleEmptyObject) {
|
||||
dynamic map1 = dynamic::object;
|
||||
|
||||
dynamic map2 = dynamic::object;
|
||||
map2["height"] = 100;
|
||||
|
||||
map2.merge_patch(map1);
|
||||
|
||||
EXPECT_TRUE(map2["height"].isInt());
|
||||
EXPECT_EQ(map2["height"], 100);
|
||||
|
||||
map1.merge_patch(map2);
|
||||
|
||||
EXPECT_TRUE(map1["height"].isInt());
|
||||
EXPECT_EQ(map1["height"], 100);
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
#include <react/renderer/componentregistry/ComponentDescriptorRegistry.h>
|
||||
#include <react/renderer/core/Constants.h>
|
||||
#include <react/renderer/core/LayoutContext.h>
|
||||
#include <react/renderer/debug/SystraceSection.h>
|
||||
#include <react/renderer/mounting/MountingOverrideDelegate.h>
|
||||
@@ -112,6 +113,8 @@ Scheduler::Scheduler(
|
||||
#ifdef ANDROID
|
||||
removeOutstandingSurfacesOnDestruction_ = reactNativeConfig_->getBool(
|
||||
"react_fabric:remove_outstanding_surfaces_on_destruction_android");
|
||||
Constants::setPropsForwardingEnabled(reactNativeConfig_->getBool(
|
||||
"react_fabric:enable_props_forwarding_android"));
|
||||
#else
|
||||
removeOutstandingSurfacesOnDestruction_ = reactNativeConfig_->getBool(
|
||||
"react_fabric:remove_outstanding_surfaces_on_destruction_ios");
|
||||
|
||||
@@ -798,7 +798,7 @@ SPEC CHECKSUMS:
|
||||
CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
|
||||
DoubleConversion: cde416483dac037923206447da6e1454df403714
|
||||
FBLazyVector: 91e874a8823933a268c38765a88cbd5dba1fa024
|
||||
FBReactNativeSpec: 9b595c8d6225c3406ac3b61cad0e0dcd9c4ce82c
|
||||
FBReactNativeSpec: f413828a0c0ca7fb738e67dd90281e454d353a46
|
||||
Flipper: be611d4b742d8c87fbae2ca5f44603a02539e365
|
||||
Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
|
||||
Flipper-Folly: e4493b013c02d9347d5e0cb4d128680239f6c78a
|
||||
|
||||
Reference in New Issue
Block a user