Skip to content

Commit

Permalink
RN: Fallback for Invalid Colors in processColorArray
Browse files Browse the repository at this point in the history
Summary:
If an invalid color is supplied to a native component that expects `Array<ColorValue>`, it is currently possible to produce an array that contains null or undefined elements. This is problematic because the native component may not know what to do with the null or undefined value.

This changes `processColorArray` to always return an array with valid color values. Any invalid color values will fallback to being transparent black, `0x00000000`.

Changelog:
[General][Fixed] - For native components that accept color arrays, invalid elements will now fallback to transparent with a console error.

Reviewed By: JoshuaGross

Differential Revision: D27542291

fbshipit-source-id: efa5d130644b3aee68d2b9fad6fdb61af11a2966
  • Loading branch information
yungsters authored and facebook-github-bot committed Apr 2, 2021
1 parent 322e8f7 commit bb6cd56
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 7 deletions.
26 changes: 25 additions & 1 deletion Libraries/StyleSheet/__tests__/processColorArray-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const PlatformColorAndroid = require('../PlatformColorValueTypes.android')

const platformSpecific =
OS === 'android'
? unsigned => unsigned | 0 //eslint-disable-line no-bitwise
? unsigned => unsigned | 0 // eslint-disable-line no-bitwise
: x => x;

describe('processColorArray', () => {
Expand Down Expand Up @@ -63,6 +63,30 @@ describe('processColorArray', () => {
const colorFromNoArray = processColorArray(null);
expect(colorFromNoArray).toEqual(null);
});

it('converts invalid colors to transparent', () => {
const spy = jest.spyOn(console, 'error').mockReturnValue(undefined);

const colors = ['red', '???', null, undefined, false];
const colorFromStringArray = processColorArray(colors);
const expectedIntArray = [
0xffff0000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
].map(platformSpecific);
expect(colorFromStringArray).toEqual(expectedIntArray);

for (const color of colors.slice(1)) {
expect(spy).toHaveBeenCalledWith(
'Invalid value in color array:',
color,
);
}

spy.mockRestore();
});
});

describe('iOS', () => {
Expand Down
22 changes: 16 additions & 6 deletions Libraries/StyleSheet/processColorArray.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,25 @@

'use strict';

const processColor = require('./processColor');

import type {ColorValue} from './StyleSheet';
import type {ProcessedColorValue} from './processColor';
import processColor, {type ProcessedColorValue} from './processColor';

const TRANSPARENT = 0; // rgba(0, 0, 0, 0)

function processColorArray(
colors: ?Array<ColorValue>,
): ?Array<?ProcessedColorValue> {
return colors == null ? null : colors.map(processColor);
colors: ?$ReadOnlyArray<ColorValue>,
): ?$ReadOnlyArray<ProcessedColorValue> {
return colors == null ? null : colors.map(processColorElement);
}

function processColorElement(color: ColorValue): ProcessedColorValue {
const value = processColor(color);
// For invalid colors, fallback to transparent.
if (value == null) {
console.error('Invalid value in color array:', color);
return TRANSPARENT;
}
return value;
}

module.exports = processColorArray;

0 comments on commit bb6cd56

Please sign in to comment.