Skip to content

Commit 972036d

Browse files
javachemeta-codesync[bot]
authored andcommitted
Add Fantom test for backgroundImage parsing (facebook#54185)
Summary: Pull Request resolved: facebook#54185 Validate that the changes in D83341309 work across both experiment variants. Changelog: [Internal] Differential Revision: D84924308
1 parent 33af0cf commit 972036d

File tree

4 files changed

+187
-1
lines changed

4 files changed

+187
-1
lines changed

packages/react-native/Libraries/Components/View/__tests__/View-itest.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* LICENSE file in the root directory of this source tree.
66
*
77
* @flow strict-local
8+
* @fantom_flags enableNativeCSSParsing:*
89
* @format
910
*/
1011

@@ -229,6 +230,49 @@ describe('<View>', () => {
229230
});
230231
});
231232
});
233+
234+
describe('background-image', () => {
235+
it('it parses CSS and object syntax', () => {
236+
const root = Fantom.createRoot();
237+
238+
Fantom.runTask(() => {
239+
root.render(
240+
<>
241+
<View
242+
style={{
243+
experimental_backgroundImage:
244+
'radial-gradient(#e66465, #9198e5)',
245+
}}
246+
/>
247+
<View
248+
style={{
249+
experimental_backgroundImage: [
250+
{
251+
type: 'radial-gradient',
252+
shape: 'ellipse',
253+
position: {top: '50%', right: '50%'},
254+
size: 'farthest-corner',
255+
colorStops: [{color: '#e66465'}, {color: '#9198e5'}],
256+
},
257+
],
258+
}}
259+
/>
260+
</>,
261+
);
262+
});
263+
264+
// We can't just assert this matches a fragment for some reason, the test
265+
// fails with "Compared values have no visual difference."
266+
// $FlowFixMe[unclear-type]
267+
const output = root.getRenderedOutput().toJSX() as any;
268+
React.Children.map(output.props.children, child => {
269+
// $FlowFixMe[incompatible-use]
270+
expect(child.props.backgroundImage).toEqual(
271+
'[radial-gradient(ellipse farthest-corner at 50% 50% , rgba(230, 100, 101, 1), rgba(145, 152, 229, 1))]',
272+
);
273+
});
274+
});
275+
});
232276
});
233277

234278
describe('pointerEvents', () => {

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

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@
88
#pragma once
99

1010
#include <react/featureflags/ReactNativeFeatureFlags.h>
11+
#include <react/renderer/components/view/conversions.h>
1112
#include <react/renderer/core/PropsParserContext.h>
1213
#include <react/renderer/core/RawProps.h>
14+
#include <react/renderer/core/graphicsConversions.h>
15+
#include <react/renderer/debug/flags.h>
1316
#include <react/renderer/graphics/BackgroundImage.h>
1417

18+
#include <sstream>
1519
#include <string>
1620

1721
namespace facebook::react {
@@ -48,4 +52,123 @@ inline void fromRawValue(
4852
}
4953
}
5054

55+
#if RN_DEBUG_STRING_CONVERTIBLE
56+
inline void toStringColorStop(
57+
std::stringstream& ss,
58+
const ColorStop& colorStop) {
59+
ss << toString(colorStop.color);
60+
if (colorStop.position.unit != UnitType::Undefined) {
61+
ss << " ";
62+
ss << toString(colorStop.position);
63+
}
64+
}
65+
66+
inline void toStringLinearGradient(
67+
std::stringstream& ss,
68+
const LinearGradient& gradient) {
69+
ss << "linear-gradient(";
70+
71+
if (gradient.direction.type == GradientDirectionType::Angle) {
72+
ss << std::get<Float>(gradient.direction.value) << "deg";
73+
} else {
74+
auto keyword = std::get<GradientKeyword>(gradient.direction.value);
75+
switch (keyword) {
76+
case GradientKeyword::ToTopRight:
77+
ss << "to top right";
78+
break;
79+
case GradientKeyword::ToBottomRight:
80+
ss << "to bottom right";
81+
break;
82+
case GradientKeyword::ToTopLeft:
83+
ss << "to top left";
84+
break;
85+
case GradientKeyword::ToBottomLeft:
86+
ss << "to bottom left";
87+
break;
88+
}
89+
}
90+
91+
for (const auto& colorStop : gradient.colorStops) {
92+
ss << ", ";
93+
toStringColorStop(ss, colorStop);
94+
}
95+
96+
ss << ")";
97+
}
98+
99+
inline void toStringRadialGradient(
100+
std::stringstream& ss,
101+
const RadialGradient& gradient) {
102+
ss << "radial-gradient("
103+
<< (gradient.shape == RadialGradientShape::Circle ? "circle" : "ellipse")
104+
<< " ";
105+
106+
if (std::holds_alternative<RadialGradientSize::SizeKeyword>(
107+
gradient.size.value)) {
108+
auto& keyword =
109+
std::get<RadialGradientSize::SizeKeyword>(gradient.size.value);
110+
switch (keyword) {
111+
case RadialGradientSize::SizeKeyword::ClosestSide:
112+
ss << "closest-side";
113+
break;
114+
case RadialGradientSize::SizeKeyword::FarthestSide:
115+
ss << "farthest-side";
116+
break;
117+
case RadialGradientSize::SizeKeyword::ClosestCorner:
118+
ss << "closest-corner";
119+
break;
120+
case RadialGradientSize::SizeKeyword::FarthestCorner:
121+
ss << "farthest-corner";
122+
break;
123+
}
124+
} else {
125+
auto& dimensions =
126+
std::get<RadialGradientSize::Dimensions>(gradient.size.value);
127+
ss << toString(dimensions.x) << " " << toString(dimensions.y);
128+
}
129+
130+
ss << " at ";
131+
132+
if (gradient.position.left.has_value()) {
133+
ss << toString(*gradient.position.left) << " ";
134+
}
135+
if (gradient.position.top.has_value()) {
136+
ss << toString(*gradient.position.top) << " ";
137+
}
138+
if (gradient.position.right.has_value()) {
139+
ss << toString(*gradient.position.right) << " ";
140+
}
141+
if (gradient.position.bottom.has_value()) {
142+
ss << toString(*gradient.position.bottom) << " ";
143+
}
144+
145+
for (const auto& colorStop : gradient.colorStops) {
146+
ss << ", ";
147+
toStringColorStop(ss, colorStop);
148+
}
149+
150+
ss << ")";
151+
}
152+
153+
inline std::string toString(std::vector<BackgroundImage>& value) {
154+
std::stringstream ss;
155+
156+
ss << "[";
157+
for (size_t i = 0; i < value.size(); i++) {
158+
if (i > 0) {
159+
ss << ", ";
160+
}
161+
162+
if (std::holds_alternative<LinearGradient>(value[i])) {
163+
toStringLinearGradient(ss, std::get<LinearGradient>(value[i]));
164+
} else if (std::holds_alternative<RadialGradient>(value[i])) {
165+
toStringRadialGradient(ss, std::get<RadialGradient>(value[i]));
166+
}
167+
}
168+
ss << "]";
169+
170+
return ss.str();
171+
}
172+
#endif
173+
51174
} // namespace facebook::react

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,10 @@ SharedDebugStringConvertibleList BaseViewProps::getDebugProps() const {
612612
defaultBaseViewProps.pointerEvents),
613613
debugStringConvertibleItem(
614614
"transform", transform, defaultBaseViewProps.transform),
615+
debugStringConvertibleItem(
616+
"backgroundImage",
617+
backgroundImage,
618+
defaultBaseViewProps.backgroundImage),
615619
};
616620
}
617621
#endif

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <react/renderer/css/CSSNumber.h>
1919
#include <react/renderer/css/CSSPercentage.h>
2020
#include <react/renderer/css/CSSValueParser.h>
21+
#include <react/renderer/debug/flags.h>
2122
#include <react/renderer/graphics/BlendMode.h>
2223
#include <react/renderer/graphics/Isolation.h>
2324
#include <react/renderer/graphics/LinearGradient.h>
@@ -557,6 +558,18 @@ inline ValueUnit toValueUnit(const RawValue& value) {
557558
return {};
558559
}
559560

561+
#if RN_DEBUG_STRING_CONVERTIBLE
562+
inline std::string toString(const ValueUnit& valueUnit) {
563+
if (valueUnit.unit == UnitType::Percent) {
564+
return toString(valueUnit.value) + "%";
565+
} else if (valueUnit.unit == UnitType::Point) {
566+
return toString(valueUnit.value) + "px";
567+
} else {
568+
return "undefined";
569+
}
570+
}
571+
#endif
572+
560573
inline void fromRawValue(
561574
const PropsParserContext& /*context*/,
562575
const RawValue& value,
@@ -565,7 +578,7 @@ inline void fromRawValue(
565578
}
566579

567580
inline void fromRawValue(
568-
const PropsParserContext& context,
581+
const PropsParserContext& /*context*/,
569582
const RawValue& value,
570583
Transform& result) {
571584
auto transformMatrix = Transform{};
@@ -1225,6 +1238,7 @@ inline void fromRawValue(
12251238
result = isolation.value();
12261239
}
12271240

1241+
#if RN_DEBUG_STRING_CONVERTIBLE
12281242
template <size_t N>
12291243
inline std::string toString(const std::array<float, N> vec) {
12301244
std::string s;
@@ -1422,5 +1436,6 @@ inline std::string toString(const Transform& transform) {
14221436
result += "]";
14231437
return result;
14241438
}
1439+
#endif
14251440

14261441
} // namespace facebook::react

0 commit comments

Comments
 (0)