Skip to content

Commit 022458f

Browse files
ngocdevvmeta-codesync[bot]
authored andcommitted
Distinguish transparent colors from undefined props (#58093)
Summary: Fixes #58085. Android represents both an undefined color and explicit transparent black as ARGB `0`. `SharedColor` previously compared only that raw value, so Props 2.0 considered an explicitly supplied transparent color equal to an absent prop and omitted it from the mount diff. This change tracks color presence separately from the platform value and includes it in equality, boolean conversion, and hashing. Platform parsers and the few call sites that intentionally produce an undefined color now preserve that state explicitly. ## Changelog: [ANDROID] [FIXED] - Preserve explicitly transparent colors during Props 2.0 reconciliation. Pull Request resolved: #58093 Test Plan: - Added `ColorTest.testTransparentColorIsDistinctFromUndefined`. - Compiled and ran a standalone regression harness against Android `Color.cpp`; it failed before this change and passes afterward. - Built `ReactAndroid` CMake Debug for `arm64-v8a` successfully. - Validated all 9 ReactCommon, ReactAndroid, and ReactApple C++ API snapshots against Doxygen 1.16.1. - Ran targeted clang-format and `git diff --check`. Reviewed By: javache Differential Revision: D117292692 Pulled By: Abbondanzo fbshipit-source-id: 08120b7eb805dbed06cd76b6bd14fe29a556d88e
1 parent 935f733 commit 022458f

10 files changed

Lines changed: 129 additions & 20 deletions

File tree

packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ AndroidTextInputProps::AndroidTextInputProps(
138138
"textTransform",
139139
sourceProps.textTransform,
140140
{})),
141-
color(0 /*convertRawProp(context, rawProps, "color", sourceProps.color, {0})*/),
141+
color(/*convertRawProp(context, rawProps, "color", sourceProps.color, {})*/),
142142
letterSpacing(convertRawProp(context, rawProps,
143143
"letterSpacing",
144144
sourceProps.letterSpacing,

packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ class AndroidTextInputProps final : public BaseTextInputProps {
105105
AndroidTextInputTextShadowOffsetStruct textShadowOffset{};
106106
Float lineHeight{0.0};
107107
std::string textTransform{};
108-
SharedColor color{0};
108+
SharedColor color{};
109109
Float letterSpacing{0.0};
110110
Float fontSize{0.0};
111111
std::string textAlign{};

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,8 @@ static void updateBorderColorPropValue(
309309
const std::optional<SharedColor>& newColor,
310310
const std::optional<SharedColor>& oldColor) {
311311
if (newColor != oldColor) {
312-
result[propName] = newColor.has_value() ? *newColor.value() : NULL;
312+
result[propName] = newColor.has_value() ? folly::dynamic(*newColor.value())
313+
: folly::dynamic(nullptr);
313314
}
314315
}
315316

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ namespace facebook::react {
1717

1818
#ifdef RN_SERIALIZABLE_STATE
1919

20+
inline folly::dynamic toDynamic(uint32_t value)
21+
{
22+
return value;
23+
}
24+
2025
inline folly::dynamic toDynamic(const std::vector<bool> &arrayValue)
2126
{
2227
folly::dynamic resultArray = folly::dynamic::array();

packages/react-native/ReactCommon/react/renderer/graphics/platform/android/react/renderer/graphics/HostPlatformColor.h

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,56 +8,91 @@
88
#pragma once
99

1010
#include <react/renderer/graphics/ColorComponents.h>
11+
#include <react/utils/hash_combine.h>
1112
#include <cmath>
13+
#include <cstdint>
14+
15+
#ifdef RN_SERIALIZABLE_STATE
16+
#include <folly/dynamic.h>
17+
#endif
1218

1319
namespace facebook::react {
1420

15-
using Color = int32_t;
21+
struct Color {
22+
int32_t value{0};
23+
bool isDefined{false};
24+
25+
constexpr Color() = default;
26+
constexpr Color(int32_t colorValue) : value(colorValue), isDefined(true) {}
27+
28+
constexpr bool operator==(const Color &otherColor) const
29+
{
30+
return value == otherColor.value && isDefined == otherColor.isDefined;
31+
}
32+
33+
constexpr bool operator!=(const Color &otherColor) const
34+
{
35+
return !(*this == otherColor);
36+
}
37+
38+
constexpr operator int32_t() const
39+
{
40+
return value;
41+
}
42+
43+
#ifdef RN_SERIALIZABLE_STATE
44+
operator folly::dynamic() const
45+
{
46+
return value;
47+
}
48+
#endif
49+
};
1650

1751
namespace HostPlatformColor {
18-
constexpr facebook::react::Color UndefinedColor = 0;
52+
constexpr facebook::react::Color UndefinedColor{};
1953
}
2054

2155
inline Color hostPlatformColorFromRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
2256
{
23-
return (a & 0xff) << 24 | (r & 0xff) << 16 | (g & 0xff) << 8 | (b & 0xff);
57+
return Color{(a & 0xff) << 24 | (r & 0xff) << 16 | (g & 0xff) << 8 | (b & 0xff)};
2458
}
2559

2660
inline Color hostPlatformColorFromComponents(ColorComponents components)
2761
{
2862
float ratio = 255;
29-
return ((int)round(components.alpha * ratio) & 0xff) << 24 | ((int)round(components.red * ratio) & 0xff) << 16 |
30-
((int)round(components.green * ratio) & 0xff) << 8 | ((int)round(components.blue * ratio) & 0xff);
63+
return Color{
64+
((int)round(components.alpha * ratio) & 0xff) << 24 | ((int)round(components.red * ratio) & 0xff) << 16 |
65+
((int)round(components.green * ratio) & 0xff) << 8 | ((int)round(components.blue * ratio) & 0xff)};
3166
}
3267

3368
inline ColorComponents colorComponentsFromHostPlatformColor(Color color)
3469
{
3570
float ratio = 255;
3671
return ColorComponents{
37-
.red = (float)((color >> 16) & 0xff) / ratio,
38-
.green = (float)((color >> 8) & 0xff) / ratio,
39-
.blue = (float)((color >> 0) & 0xff) / ratio,
40-
.alpha = (float)((color >> 24) & 0xff) / ratio};
72+
.red = (float)((color.value >> 16) & 0xff) / ratio,
73+
.green = (float)((color.value >> 8) & 0xff) / ratio,
74+
.blue = (float)((color.value >> 0) & 0xff) / ratio,
75+
.alpha = (float)((color.value >> 24) & 0xff) / ratio};
4176
}
4277

4378
inline float alphaFromHostPlatformColor(Color color)
4479
{
45-
return static_cast<float>((color >> 24) & 0xff);
80+
return static_cast<float>((color.value >> 24) & 0xff);
4681
}
4782

4883
inline float redFromHostPlatformColor(Color color)
4984
{
50-
return static_cast<float>((color >> 16) & 0xff);
85+
return static_cast<float>((color.value >> 16) & 0xff);
5186
}
5287

5388
inline float greenFromHostPlatformColor(Color color)
5489
{
55-
return static_cast<float>((color >> 8) & 0xff);
90+
return static_cast<float>((color.value >> 8) & 0xff);
5691
}
5792

5893
inline float blueFromHostPlatformColor(Color color)
5994
{
60-
return static_cast<uint8_t>((color >> 0) & 0xff);
95+
return static_cast<uint8_t>((color.value >> 0) & 0xff);
6196
}
6297

6398
inline bool hostPlatformColorIsColorMeaningful(Color color) noexcept
@@ -66,3 +101,11 @@ inline bool hostPlatformColorIsColorMeaningful(Color color) noexcept
66101
}
67102

68103
} // namespace facebook::react
104+
105+
template <>
106+
struct std::hash<facebook::react::Color> {
107+
size_t operator()(const facebook::react::Color &color) const
108+
{
109+
return facebook::react::hash_combine(color.value, color.isDefined);
110+
}
111+
};

packages/react-native/ReactCommon/react/renderer/graphics/platform/android/react/renderer/graphics/PlatformColorParser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ inline size_t hashGetColourArguments(int32_t surfaceId, const std::vector<std::s
3838
inline SharedColor
3939
parsePlatformColor(const ContextContainer &contextContainer, int32_t surfaceId, const RawValue &value)
4040
{
41-
Color color = 0;
41+
Color color{};
4242
if (value.hasType<std::unordered_map<std::string, RawValue>>()) {
4343
// Mixed array + string values, so read as a map of RawValue (a map of
4444
// vector<string> would assert on the fallback string).

packages/react-native/ReactCommon/react/renderer/graphics/tests/ColorTest.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,18 @@ TEST(ColorTest, testColorConversion) {
3636
EXPECT_EQ(std::round(colorComponents.blue * 10) / 10.f, 0);
3737
}
3838
}
39+
40+
#ifdef ANDROID
41+
TEST(ColorTest, testTransparentColorIsDistinctFromUndefined) {
42+
using namespace facebook::react;
43+
44+
EXPECT_NE(Color{}, Color{0});
45+
46+
SharedColor undefinedColor;
47+
auto transparentColor = clearColor();
48+
49+
EXPECT_FALSE(undefinedColor);
50+
EXPECT_TRUE(transparentColor);
51+
EXPECT_NE(undefinedColor, transparentColor);
52+
}
53+
#endif

scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,6 @@ using facebook::react::CascadedBorderCurves = facebook::react::CascadedRectangle
610610
using facebook::react::CascadedBorderRadii = facebook::react::CascadedRectangleCorners<facebook::react::ValueUnit>;
611611
using facebook::react::CascadedBorderStyles = facebook::react::CascadedRectangleEdges<facebook::react::BorderStyle>;
612612
using facebook::react::CascadedBorderWidths = facebook::react::CascadedRectangleEdges<facebook::react::Float>;
613-
using facebook::react::Color = int32_t;
614613
using facebook::react::ComponentDescriptorConstructor = facebook::react::ComponentDescriptor::Unique(const facebook::react::ComponentDescriptorParameters& parameters);
615614
using facebook::react::ComponentDescriptorProviderRequest = std::function<void(facebook::react::ComponentName componentName)>;
616615
using facebook::react::ComponentHandle = int64_t;
@@ -932,6 +931,7 @@ folly::dynamic facebook::react::toDynamic(const std::vector<facebook::react::Flo
932931
folly::dynamic facebook::react::toDynamic(const std::vector<folly::dynamic>& arrayValue);
933932
folly::dynamic facebook::react::toDynamic(const std::vector<int>& arrayValue);
934933
folly::dynamic facebook::react::toDynamic(const std::vector<std::string>& arrayValue);
934+
folly::dynamic facebook::react::toDynamic(uint32_t value);
935935
int facebook::react::toAndroidRepr(const facebook::react::SharedColor& color);
936936
int facebook::react::toInt(const facebook::react::DisplayType& displayType);
937937
int facebook::react::toInt(const facebook::react::LayoutDirection& layoutDirection);
@@ -7267,6 +7267,17 @@ struct facebook::react::CascadedRectangleEdgesNames {
72677267
public const char* vertical;
72687268
}
72697269

7270+
struct facebook::react::Color {
7271+
public bool isDefined;
7272+
public constexpr Color() = default;
7273+
public constexpr Color(int32_t colorValue);
7274+
public constexpr bool operator!=(const facebook::react::Color& otherColor) const;
7275+
public constexpr bool operator==(const facebook::react::Color& otherColor) const;
7276+
public constexpr operator int32_t() const;
7277+
public int32_t value;
7278+
public operator folly::dynamic() const;
7279+
}
7280+
72707281
struct facebook::react::ColorComponents {
72717282
public facebook::react::ColorSpace colorSpace;
72727283
public float alpha;
@@ -14005,6 +14016,10 @@ struct std::hash<facebook::react::AttributedStringBox> {
1400514016
public size_t operator()(const facebook::react::AttributedStringBox& attributedStringBox) const;
1400614017
}
1400714018

14019+
struct std::hash<facebook::react::Color> {
14020+
public size_t operator()(const facebook::react::Color& color) const;
14021+
}
14022+
1400814023
struct std::hash<facebook::react::EventAnimationDriverKey> {
1400914024
public size_t operator()(const facebook::react::EventAnimationDriverKey& key) const;
1401014025
}

scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,6 @@ using facebook::react::CascadedBorderCurves = facebook::react::CascadedRectangle
609609
using facebook::react::CascadedBorderRadii = facebook::react::CascadedRectangleCorners<facebook::react::ValueUnit>;
610610
using facebook::react::CascadedBorderStyles = facebook::react::CascadedRectangleEdges<facebook::react::BorderStyle>;
611611
using facebook::react::CascadedBorderWidths = facebook::react::CascadedRectangleEdges<facebook::react::Float>;
612-
using facebook::react::Color = int32_t;
613612
using facebook::react::ComponentDescriptorConstructor = facebook::react::ComponentDescriptor::Unique(const facebook::react::ComponentDescriptorParameters& parameters);
614613
using facebook::react::ComponentDescriptorProviderRequest = std::function<void(facebook::react::ComponentName componentName)>;
615614
using facebook::react::ComponentHandle = int64_t;
@@ -931,6 +930,7 @@ folly::dynamic facebook::react::toDynamic(const std::vector<facebook::react::Flo
931930
folly::dynamic facebook::react::toDynamic(const std::vector<folly::dynamic>& arrayValue);
932931
folly::dynamic facebook::react::toDynamic(const std::vector<int>& arrayValue);
933932
folly::dynamic facebook::react::toDynamic(const std::vector<std::string>& arrayValue);
933+
folly::dynamic facebook::react::toDynamic(uint32_t value);
934934
int facebook::react::toAndroidRepr(const facebook::react::SharedColor& color);
935935
int facebook::react::toInt(const facebook::react::DisplayType& displayType);
936936
int facebook::react::toInt(const facebook::react::LayoutDirection& layoutDirection);
@@ -7077,6 +7077,17 @@ struct facebook::react::CascadedRectangleEdgesNames {
70777077
public const char* vertical;
70787078
}
70797079

7080+
struct facebook::react::Color {
7081+
public bool isDefined;
7082+
public constexpr Color() = default;
7083+
public constexpr Color(int32_t colorValue);
7084+
public constexpr bool operator!=(const facebook::react::Color& otherColor) const;
7085+
public constexpr bool operator==(const facebook::react::Color& otherColor) const;
7086+
public constexpr operator int32_t() const;
7087+
public int32_t value;
7088+
public operator folly::dynamic() const;
7089+
}
7090+
70807091
struct facebook::react::ColorComponents {
70817092
public facebook::react::ColorSpace colorSpace;
70827093
public float alpha;
@@ -13618,6 +13629,10 @@ struct std::hash<facebook::react::AttributedStringBox> {
1361813629
public size_t operator()(const facebook::react::AttributedStringBox& attributedStringBox) const;
1361913630
}
1362013631

13632+
struct std::hash<facebook::react::Color> {
13633+
public size_t operator()(const facebook::react::Color& color) const;
13634+
}
13635+
1362113636
struct std::hash<facebook::react::EventAnimationDriverKey> {
1362213637
public size_t operator()(const facebook::react::EventAnimationDriverKey& key) const;
1362313638
}

scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,6 @@ using facebook::react::CascadedBorderCurves = facebook::react::CascadedRectangle
610610
using facebook::react::CascadedBorderRadii = facebook::react::CascadedRectangleCorners<facebook::react::ValueUnit>;
611611
using facebook::react::CascadedBorderStyles = facebook::react::CascadedRectangleEdges<facebook::react::BorderStyle>;
612612
using facebook::react::CascadedBorderWidths = facebook::react::CascadedRectangleEdges<facebook::react::Float>;
613-
using facebook::react::Color = int32_t;
614613
using facebook::react::ComponentDescriptorConstructor = facebook::react::ComponentDescriptor::Unique(const facebook::react::ComponentDescriptorParameters& parameters);
615614
using facebook::react::ComponentDescriptorProviderRequest = std::function<void(facebook::react::ComponentName componentName)>;
616615
using facebook::react::ComponentHandle = int64_t;
@@ -932,6 +931,7 @@ folly::dynamic facebook::react::toDynamic(const std::vector<facebook::react::Flo
932931
folly::dynamic facebook::react::toDynamic(const std::vector<folly::dynamic>& arrayValue);
933932
folly::dynamic facebook::react::toDynamic(const std::vector<int>& arrayValue);
934933
folly::dynamic facebook::react::toDynamic(const std::vector<std::string>& arrayValue);
934+
folly::dynamic facebook::react::toDynamic(uint32_t value);
935935
int facebook::react::toAndroidRepr(const facebook::react::SharedColor& color);
936936
int facebook::react::toInt(const facebook::react::DisplayType& displayType);
937937
int facebook::react::toInt(const facebook::react::LayoutDirection& layoutDirection);
@@ -7258,6 +7258,17 @@ struct facebook::react::CascadedRectangleEdgesNames {
72587258
public const char* vertical;
72597259
}
72607260

7261+
struct facebook::react::Color {
7262+
public bool isDefined;
7263+
public constexpr Color() = default;
7264+
public constexpr Color(int32_t colorValue);
7265+
public constexpr bool operator!=(const facebook::react::Color& otherColor) const;
7266+
public constexpr bool operator==(const facebook::react::Color& otherColor) const;
7267+
public constexpr operator int32_t() const;
7268+
public int32_t value;
7269+
public operator folly::dynamic() const;
7270+
}
7271+
72617272
struct facebook::react::ColorComponents {
72627273
public facebook::react::ColorSpace colorSpace;
72637274
public float alpha;
@@ -13849,6 +13860,10 @@ struct std::hash<facebook::react::AttributedStringBox> {
1384913860
public size_t operator()(const facebook::react::AttributedStringBox& attributedStringBox) const;
1385013861
}
1385113862

13863+
struct std::hash<facebook::react::Color> {
13864+
public size_t operator()(const facebook::react::Color& color) const;
13865+
}
13866+
1385213867
struct std::hash<facebook::react::EventAnimationDriverKey> {
1385313868
public size_t operator()(const facebook::react::EventAnimationDriverKey& key) const;
1385413869
}

0 commit comments

Comments
 (0)