fix(android): skip null gradient color stop positions instead of warning (#58636)

Summary:
`processBackgroundImage` emits `position: null` for every color stop that has no explicit position, which is the common case (`linear-gradient(red, blue)`). On Android, `LinearGradient` and `RadialGradient` pass that value straight to `LengthPercentage.setFromDynamic`, which logs

```
W ReactNative: Unsupported type for radius property: Null
```

once per such stop on every props update. A static view logs it on each render; an animated `backgroundImage` (e.g. Reanimated CSS animations) floods logcat at frame rate. The value itself is handled correctly (`null` position → evenly spaced), so this is purely log noise, but it drowns out real warnings.

`BackgroundPosition` already guards against `ReadableType.Null` before calling `setFromDynamic`; this change does the same for gradient color stops in both gradient parsers.

## Changelog:

[ANDROID] [FIXED] - Stop logging "Unsupported type for radius property: Null" for gradient color stops without an explicit position

Pull Request resolved: https://github.com/react/react-native/pull/58636

Test Plan:
Built React Native from source (`includeBuild('../node_modules/react-native')`) in an app that animates `backgroundImage` on Android (Pixel 9 Pro emulator, API 37) and counted the warning in `adb logcat` over an identical ~90 s run:

- before: 1386 occurrences of `Unsupported type for radius property: Null`
- after: 0 occurrences

Gradients with and without stop positions render the same as before. `yarn format-check-kotlin` (ktfmt) passes on the changed files.

Reviewed By: Abbondanzo

Differential Revision: D121621185

Pulled By: javache

fbshipit-source-id: 7baeea9e373dd03db9b911c6a57d9cb90e33a866
This commit is contained in:
tshmieldev
2026-09-24 11:27:37 -07:00
committed by meta-codesync[bot]
parent ab373989c3
commit 585b28c5f0
2 changed files with 10 additions and 2 deletions
@@ -72,7 +72,11 @@ internal class LinearGradient(val direction: Direction, val colorStops: List<Col
else -> colorStop.getInt("color")
}
val colorStopPosition =
LengthPercentage.setFromDynamic(colorStop.getDynamic("position"))
if (colorStop.hasKey("position") && !colorStop.isNull("position")) {
LengthPercentage.setFromDynamic(colorStop.getDynamic("position"))
} else {
null
}
stops.add(ColorStop(color, colorStopPosition))
}
stops
@@ -128,7 +128,11 @@ internal class RadialGradient(
else -> colorStop.getInt("color")
}
val colorStopPosition =
LengthPercentage.setFromDynamic(colorStop.getDynamic("position"))
if (colorStop.hasKey("position") && !colorStop.isNull("position")) {
LengthPercentage.setFromDynamic(colorStop.getDynamic("position"))
} else {
null
}
stops.add(ColorStop(color, colorStopPosition))
}
stops