Skip to content

Commit e5a4e62

Browse files
committed
Pass committed view props to the platform routing predicate
1 parent e1ae440 commit e5a4e62

8 files changed

Lines changed: 79 additions & 16 deletions

File tree

packages/react-native-reanimated/Common/cpp/reanimated/CSS/core/transition/CSSPlatformTransitionProxy.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <react/debug/react_native_assert.h>
44

5+
#include <unordered_set>
56
#include <utility>
67

78
namespace reanimated::css {
@@ -48,14 +49,20 @@ CSSPlatformTransitionProxy::CSSPlatformTransitionProxy(
4849
CSSCanRoutePropertyFunction canRoute,
4950
CSSParseValueFunction parseValue,
5051
CSSApplyTransitionFunction applyTransition,
51-
CSSRemoveTransitionFunction removeTransition)
52+
CSSRemoveTransitionFunction removeTransition,
53+
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
5254
: canRoute_(std::move(canRoute)),
5355
parseValue_(std::move(parseValue)),
5456
applyTransition_(std::move(applyTransition)),
55-
removeTransition_(std::move(removeTransition)) {}
57+
removeTransition_(std::move(removeTransition)),
58+
viewStylesRepository_(viewStylesRepository) {}
5659

57-
bool CSSPlatformTransitionProxy::canRoute(const std::string &propertyName, const EasingConfig &easing) const {
58-
return canRoute_ && canRoute_(propertyName, easing);
60+
bool CSSPlatformTransitionProxy::canRoute(
61+
const std::string &propertyName,
62+
const EasingConfig &easing,
63+
const ShadowNode &shadowNode,
64+
const std::unordered_set<std::string> &transitioningProperties) const {
65+
return canRoute_ && canRoute_(propertyName, easing, shadowNode, transitioningProperties);
5966
}
6067

6168
std::optional<PlatformValue> CSSPlatformTransitionProxy::parseValue(
@@ -80,19 +87,29 @@ void CSSPlatformTransitionProxy::remove(const Tag viewTag, const std::string &pr
8087
// property migrates sides - that's when the old side gets a cancel.
8188
CSSPlatformTransitionProxy::ProcessedConfig CSSPlatformTransitionProxy::processConfig(
8289
jsi::Runtime &rt,
90+
const std::shared_ptr<const ShadowNode> &shadowNode,
8391
CSSTransitionConfig &&config,
8492
const CSSTransitionRouting &previousRouting) const {
8593
ProcessedConfig result;
8694
result.routing = previousRouting;
8795

96+
// Routing eligibility is decided against the view's latest committed props.
97+
const auto newestShadowNode = viewStylesRepository_->getNewestShadowNode(shadowNode);
98+
99+
std::unordered_set<std::string> transitioningProperties;
100+
transitioningProperties.reserve(config.changedPropertiesSettings.size());
101+
for (const auto &entry : config.changedPropertiesSettings) {
102+
transitioningProperties.insert(entry.first);
103+
}
104+
88105
// extract() preserves the move-only jsi::Value diffs.
89106
while (!config.changedPropertiesSettings.empty()) {
90107
auto settingsNode = config.changedPropertiesSettings.extract(config.changedPropertiesSettings.begin());
91108
const auto &propertyName = settingsNode.key();
92109
const auto &settings = settingsNode.mapped();
93110
const auto valueIt = config.changedProperties.find(propertyName);
94111

95-
bool routable = canRoute(propertyName, settings.easingConfig);
112+
bool routable = canRoute(propertyName, settings.easingConfig, *newestShadowNode, transitioningProperties);
96113
std::optional<PlatformValue> fromValue;
97114
std::optional<PlatformValue> toValue;
98115
if (routable && valueIt != config.changedProperties.end()) {

packages/react-native-reanimated/Common/cpp/reanimated/CSS/core/transition/CSSPlatformTransitionProxy.h

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,20 @@
33
#include <reanimated/CSS/common/definitions.h>
44
#include <reanimated/CSS/configs/CSSTransitionConfig.h>
55
#include <reanimated/CSS/easing/EasingConfigs.h>
6+
#include <reanimated/CSS/misc/ViewStylesRepository.h>
67

78
#include <folly/dynamic.h>
89
#include <jsi/jsi.h>
910
#include <react/renderer/core/ReactPrimitives.h>
11+
#include <react/renderer/core/ShadowNode.h>
1012

1113
#include <array>
1214
#include <functional>
15+
#include <memory>
1316
#include <optional>
1417
#include <string>
1518
#include <unordered_map>
19+
#include <unordered_set>
1620
#include <utility>
1721
#include <variant>
1822
#include <vector>
@@ -66,8 +70,14 @@ struct CSSPlatformTransitionConfig {
6670
}
6771
};
6872

69-
/// Whether the platform can animate the property natively for the given easing.
70-
using CSSCanRoutePropertyFunction = std::function<bool(const std::string &propertyName, const EasingConfig &easing)>;
73+
/// Whether the platform can animate the property natively. shadowNode carries the
74+
/// view's latest committed props; transitioningProperties lists the co-changing
75+
/// properties, so platforms can reject ones whose rendering depends on siblings.
76+
using CSSCanRoutePropertyFunction = std::function<bool(
77+
const std::string &propertyName,
78+
const EasingConfig &easing,
79+
const ShadowNode &shadowNode,
80+
const std::unordered_set<std::string> &transitioningProperties)>;
7181
/// Parses an extracted endpoint into the platform's value representation. An
7282
/// empty endpoint resolves to the property's CSS default; nullopt means the
7383
/// value is not expressible natively and the property runs on the loop.
@@ -98,16 +108,20 @@ class CSSPlatformTransitionProxy {
98108
CSSCanRoutePropertyFunction canRoute,
99109
CSSParseValueFunction parseValue,
100110
CSSApplyTransitionFunction applyTransition,
101-
CSSRemoveTransitionFunction removeTransition);
111+
CSSRemoveTransitionFunction removeTransition,
112+
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository);
102113

103114
void run(const CSSPlatformTransitionPropertyConfig &config) const;
104115
void remove(Tag viewTag, const std::string &propertyName) const;
105116

106117
/// Filters the config into loop / platform buckets, emitting implicit cancels
107118
/// on the old side when a property migrates vs previousRouting. A property
108119
/// routes to the platform only when canRoute holds and both endpoints parse.
109-
ProcessedConfig
110-
processConfig(jsi::Runtime &rt, CSSTransitionConfig &&config, const CSSTransitionRouting &previousRouting) const;
120+
ProcessedConfig processConfig(
121+
jsi::Runtime &rt,
122+
const std::shared_ptr<const ShadowNode> &shadowNode,
123+
CSSTransitionConfig &&config,
124+
const CSSTransitionRouting &previousRouting) const;
111125

112126
/// Splits already-routed pseudo-selector toggle diffs into loop / platform
113127
/// buckets, parsing the platform endpoints; values the platform cannot
@@ -117,13 +131,18 @@ class CSSPlatformTransitionProxy {
117131
const PropertyValueDynamicDiffsMap &propertyDiffs) const;
118132

119133
private:
120-
bool canRoute(const std::string &propertyName, const EasingConfig &easing) const;
134+
bool canRoute(
135+
const std::string &propertyName,
136+
const EasingConfig &easing,
137+
const ShadowNode &shadowNode,
138+
const std::unordered_set<std::string> &transitioningProperties) const;
121139
std::optional<PlatformValue> parseValue(const std::string &propertyName, const CSSEndpointValue &value) const;
122140

123141
CSSCanRoutePropertyFunction canRoute_;
124142
CSSParseValueFunction parseValue_;
125143
CSSApplyTransitionFunction applyTransition_;
126144
CSSRemoveTransitionFunction removeTransition_;
145+
const std::shared_ptr<ViewStylesRepository> viewStylesRepository_;
127146
};
128147

129148
} // namespace reanimated::css

packages/react-native-reanimated/Common/cpp/reanimated/CSS/core/transition/CSSTransition.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ folly::dynamic CSSTransition::run(jsi::Runtime &rt, CSSTransitionConfig &&config
3838

3939
// CSSTransition owns routing: platform-routed props run immediately on the platform
4040
// transition; the loop-routed remainder is applied to the loop transition below.
41-
auto processed = platformTransitionProxy_->processConfig(rt, std::move(config), routing_);
41+
auto processed = platformTransitionProxy_->processConfig(rt, shadowNode_, std::move(config), routing_);
4242
routing_ = std::move(processed.routing);
4343

4444
if (!processed.platform.empty()) {

packages/react-native-reanimated/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ folly::dynamic ViewStylesRepository::getStyleProp(const Tag tag, const PropertyP
7474
return getPropertyValue(staticPropsRegistry_->get(tag), propertyPath);
7575
}
7676

77+
std::shared_ptr<const ShadowNode> ViewStylesRepository::getNewestShadowNode(
78+
const std::shared_ptr<const ShadowNode> &shadowNode) {
79+
if (!uiManager_) {
80+
return shadowNode;
81+
}
82+
auto newestClone = uiManager_->getNewestCloneOfShadowNode(*shadowNode);
83+
return newestClone ? newestClone : shadowNode;
84+
}
85+
7786
void ViewStylesRepository::clearNodesCache() {
7887
shadowNodeCache_.clear();
7988
}

packages/react-native-reanimated/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ class ViewStylesRepository {
3636
jsi::Value getParentNodeProp(const std::shared_ptr<const ShadowNode> &shadowNode, const std::string &propName);
3737
folly::dynamic getStyleProp(Tag tag, const PropertyPath &propertyPath);
3838

39+
// Resolves the latest committed clone of the node (the caller's reference may
40+
// be stale); falls back to the given node when no newer clone exists.
41+
std::shared_ptr<const ShadowNode> getNewestShadowNode(const std::shared_ptr<const ShadowNode> &shadowNode);
42+
3943
void clearNodesCache();
4044

4145
private:

packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,8 @@ ReanimatedModuleProxy::ReanimatedModuleProxy(
224224
platformDepMethodsHolder.cssCanRouteProperty,
225225
platformDepMethodsHolder.cssParseValue,
226226
platformDepMethodsHolder.cssApplyTransition,
227-
platformDepMethodsHolder.cssRemoveTransition))),
227+
platformDepMethodsHolder.cssRemoveTransition,
228+
viewStylesRepository_))),
228229
pseudoStylesRegistry_(std::make_shared<PseudoStylesRegistry>(
229230
platformDepMethodsHolder.attachPseudoSelector,
230231
platformDepMethodsHolder.detachPseudoSelector,

packages/react-native-reanimated/apple/reanimated/apple/CSS/REACSSPlatformProps.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,27 @@
44
#import <reanimated/CSS/easing/EasingConfigs.h>
55
#import <reanimated/apple/CSS/REACSSPlatformValue.h>
66

7+
#import <react/renderer/core/ShadowNode.h>
8+
79
#import <Foundation/Foundation.h>
810
#import <QuartzCore/QuartzCore.h>
911

1012
#import <optional>
1113
#import <string>
14+
#import <unordered_set>
1215

1316
NS_ASSUME_NONNULL_BEGIN
1417

1518
namespace reanimated::css {
1619

17-
/// Whether Core Animation can drive the property natively for the given easing.
18-
bool canRouteCSSProperty(const std::string &propertyName, const EasingConfig &easing);
20+
/// Whether Core Animation can drive the property natively. shadowNode carries
21+
/// the view's latest committed props; transitioningProperties lists the
22+
/// properties changing in the same pass.
23+
bool canRouteCSSProperty(
24+
const std::string &propertyName,
25+
const EasingConfig &easing,
26+
const facebook::react::ShadowNode &shadowNode,
27+
const std::unordered_set<std::string> &transitioningProperties);
1928

2029
/// Parses an extracted endpoint into the platform value representation. An empty
2130
/// (monostate) endpoint resolves to the property's CSS default; nullopt means the

packages/react-native-reanimated/apple/reanimated/apple/CSS/REACSSPlatformProps.mm

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,11 @@ CGColorSpaceRef sharedSRGBColorSpace()
6161

6262
} // namespace
6363

64-
bool canRouteCSSProperty(const std::string &propertyName, const EasingConfig &easing)
64+
bool canRouteCSSProperty(
65+
const std::string &propertyName,
66+
const EasingConfig &easing,
67+
const facebook::react::ShadowNode & /*shadowNode*/,
68+
const std::unordered_set<std::string> & /*transitioningProperties*/)
6569
{
6670
if constexpr (!StaticFeatureFlags::getFlag("IOS_CSS_CORE_ANIMATION")) {
6771
return false;

0 commit comments

Comments
 (0)