Skip to content

Commit feff4a7

Browse files
hannojgfacebook-github-bot
authored andcommitted
feat(android): allow passing filter function for prop folly::dynamic conversion (#48202)
Summary: ### Motivation - We need to exclude certain prop keys from conversion to `folly::dynamic` on android for our custom use case where we pass down `jsi::object`s with NativeState attached down the props Otherwise we run into crashes such as: ![CleanShot 2024-12-11 at 09 18 26@2x](https://github.com/user-attachments/assets/b460187e-5442-4547-ae36-ffd188f444f2) ### Changes - `dynamicFromValue` was marked as `noexcept` although it can throw, I removed the `noexcept` for correctness - Made it so you can pass down a filter function to exclude certain props from conversion (using the existing mechanism for that) - I think there is no way to pass a filter function and retain it in `RawProps` as that is constructed very early on in `UIManagerBinding` ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests --> [INTERNAL] [ADDED] - Allow passing a filter function to `BaseViewProps` to exclude certain props on android from being dynamically casted Pull Request resolved: #48202 Test Plan: You can try modifying for example `ScrollViewProps.cpp` and pass a fourth argument to `ViewProps` to confirm that the filtering is working: ```cpp ScrollViewProps::ScrollViewProps( const PropsParserContext& context, const ScrollViewProps& sourceProps, const RawProps& rawProps) : ViewProps(context, sourceProps, rawProps, [&](const std::string& keyName){ return true; }), ``` Reviewed By: NickGerleman Differential Revision: D67088540 Pulled By: javache fbshipit-source-id: ed8cf5d773d357dfc54553f5ccf7adf27c781d56
1 parent 1763321 commit feff4a7

10 files changed

Lines changed: 74 additions & 20 deletions

File tree

packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ std::array<float, 3> getTranslateForTransformOrigin(
5353
BaseViewProps::BaseViewProps(
5454
const PropsParserContext& context,
5555
const BaseViewProps& sourceProps,
56-
const RawProps& rawProps)
57-
: YogaStylableProps(context, sourceProps, rawProps),
56+
const RawProps& rawProps,
57+
const std::function<bool(const std::string&)>& filterObjectKeys)
58+
: YogaStylableProps(context, sourceProps, rawProps, filterObjectKeys),
5859
AccessibilityProps(context, sourceProps, rawProps),
5960
opacity(
6061
ReactNativeFeatureFlags::enableCppPropsIteratorSetter()

packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ class BaseViewProps : public YogaStylableProps, public AccessibilityProps {
3131
BaseViewProps(
3232
const PropsParserContext& context,
3333
const BaseViewProps& sourceProps,
34-
const RawProps& rawProps);
34+
const RawProps& rawProps,
35+
const std::function<bool(const std::string&)>& filterObjectKeys =
36+
nullptr);
3537

3638
void setProp(
3739
const PropsParserContext& context,

packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ namespace facebook::react {
1818
YogaStylableProps::YogaStylableProps(
1919
const PropsParserContext& context,
2020
const YogaStylableProps& sourceProps,
21-
const RawProps& rawProps)
21+
const RawProps& rawProps,
22+
const std::function<bool(const std::string&)>& filterObjectKeys)
2223
: Props() {
23-
initialize(context, sourceProps, rawProps);
24+
initialize(context, sourceProps, rawProps, filterObjectKeys);
2425

2526
yogaStyle.setDirection(convertRawProp(
2627
context,

packages/react-native/ReactCommon/react/renderer/components/view/YogaStylableProps.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ class YogaStylableProps : public Props {
2121
YogaStylableProps(
2222
const PropsParserContext& context,
2323
const YogaStylableProps& sourceProps,
24-
const RawProps& rawProps);
24+
const RawProps& rawProps,
25+
const std::function<bool(const std::string&)>& filterObjectKeys =
26+
nullptr);
2527

2628
void setProp(
2729
const PropsParserContext& context,

packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ namespace facebook::react {
2020
HostPlatformViewProps::HostPlatformViewProps(
2121
const PropsParserContext& context,
2222
const HostPlatformViewProps& sourceProps,
23-
const RawProps& rawProps)
24-
: BaseViewProps(context, sourceProps, rawProps),
23+
const RawProps& rawProps,
24+
const std::function<bool(const std::string&)>& filterObjectKeys)
25+
: BaseViewProps(context, sourceProps, rawProps, filterObjectKeys),
2526
elevation(
2627
ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
2728
? sourceProps.elevation

packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ class HostPlatformViewProps : public BaseViewProps {
2626
HostPlatformViewProps(
2727
const PropsParserContext& context,
2828
const HostPlatformViewProps& sourceProps,
29-
const RawProps& rawProps);
29+
const RawProps& rawProps,
30+
const std::function<bool(const std::string&)>& filterObjectKeys =
31+
nullptr);
3032

3133
void setProp(
3234
const PropsParserContext& context,

packages/react-native/ReactCommon/react/renderer/core/Props.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,22 @@ namespace facebook::react {
1717
Props::Props(
1818
const PropsParserContext& context,
1919
const Props& sourceProps,
20-
const RawProps& rawProps) {
21-
initialize(context, sourceProps, rawProps);
20+
const RawProps& rawProps,
21+
const std::function<bool(const std::string&)>& filterObjectKeys) {
22+
initialize(context, sourceProps, rawProps, filterObjectKeys);
2223
}
2324

2425
void Props::initialize(
2526
const PropsParserContext& context,
2627
const Props& sourceProps,
27-
const RawProps& rawProps) {
28+
const RawProps& rawProps,
29+
[[maybe_unused]] const std::function<bool(const std::string&)>&
30+
filterObjectKeys) {
2831
nativeId = ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
2932
? sourceProps.nativeId
3033
: convertRawProp(context, rawProps, "nativeID", sourceProps.nativeId, {});
3134
#ifdef ANDROID
32-
this->rawProps = (folly::dynamic)rawProps;
35+
this->rawProps = rawProps.toDynamic(filterObjectKeys);
3336
#endif
3437
}
3538

packages/react-native/ReactCommon/react/renderer/core/Props.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ class Props : public virtual Sealable, public virtual DebugStringConvertible {
3333
Props(
3434
const PropsParserContext& context,
3535
const Props& sourceProps,
36-
const RawProps& rawProps);
36+
const RawProps& rawProps,
37+
const std::function<bool(const std::string&)>& filterObjectKeys =
38+
nullptr);
3739
virtual ~Props() = default;
3840

3941
Props(const Props& other) = delete;
@@ -71,7 +73,13 @@ class Props : public virtual Sealable, public virtual DebugStringConvertible {
7173
void initialize(
7274
const PropsParserContext& context,
7375
const Props& sourceProps,
74-
const RawProps& rawProps);
76+
const RawProps& rawProps,
77+
/**
78+
* Filter object keys to be excluded when converting the RawProps to
79+
* folly::dynamic (android only)
80+
*/
81+
const std::function<bool(const std::string&)>& filterObjectKeys =
82+
nullptr);
7583
};
7684

7785
} // namespace facebook::react

packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,38 @@ void RawProps::parse(const RawPropsParser& parser) noexcept {
172172
* The support for explicit conversion to `folly::dynamic` is deprecated and
173173
* will be removed as soon Android implementation does not need it.
174174
*/
175-
RawProps::operator folly::dynamic() const noexcept {
175+
RawProps::operator folly::dynamic() const {
176+
return toDynamic();
177+
}
178+
179+
/*
180+
* Deprecated. Do not use.
181+
* The support for explicit conversion to `folly::dynamic` is deprecated and
182+
* will be removed as soon Android implementation does not need it.
183+
*/
184+
folly::dynamic RawProps::toDynamic(
185+
const std::function<bool(const std::string&)>& filterObjectKeys) const {
176186
switch (mode_) {
177187
case Mode::Empty:
178188
return folly::dynamic::object();
179-
case Mode::JSI:
180-
return jsi::dynamicFromValue(
181-
*runtime_, value_, ignoreYogaStyleProps_ ? isYogaStyleProp : nullptr);
189+
case Mode::JSI: {
190+
if (ignoreYogaStyleProps_ || filterObjectKeys != nullptr) {
191+
// We need to filter props
192+
return jsi::dynamicFromValue(
193+
*runtime_, value_, [&](const std::string& key) {
194+
if (ignoreYogaStyleProps_ && isYogaStyleProp(key)) {
195+
return true;
196+
}
197+
if (filterObjectKeys) {
198+
return filterObjectKeys(key);
199+
}
200+
return false;
201+
});
202+
} else {
203+
// We don't need to filter, just include all props by default
204+
return jsi::dynamicFromValue(*runtime_, value_, nullptr);
205+
}
206+
}
182207
case Mode::Dynamic:
183208
return dynamic_;
184209
}

packages/react-native/ReactCommon/react/renderer/core/RawProps.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,16 @@ class RawProps final {
7171
* The support for explicit conversion to `folly::dynamic` is deprecated and
7272
* will be removed as soon Android implementation does not need it.
7373
*/
74-
explicit operator folly::dynamic() const noexcept;
74+
explicit operator folly::dynamic() const;
75+
76+
/*
77+
* Deprecated. Do not use.
78+
* The support for explicit conversion to `folly::dynamic` is deprecated and
79+
* will be removed as soon Android implementation does not need it.
80+
*/
81+
folly::dynamic toDynamic(
82+
const std::function<bool(const std::string&)>& filterObjectKeys =
83+
nullptr) const;
7584

7685
/*
7786
* Once called, Yoga style props will be filtered out during conversion to

0 commit comments

Comments
 (0)