Animated: Create Default NativeAnimatedAllowlist (#46385)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46385

Changes `NativeAnimatedAllowlist` to export a "default allowlist" for use with "native animated components" (i.e. components that are only used with `Animated` values with `useNativeDriver`).

This required some minor internal implementation changes in order to make the allowlist conform to `{[string]: true}`, so I also added some unit tests to ensure the functionality remains the same.

Changelog:
[Internal]

Reviewed By: javache

Differential Revision: D62351434

fbshipit-source-id: e92b7245c0d61da87a0d149ffeb967f1ebb888a2
This commit is contained in:
Tim Yung
2024-09-09 20:34:57 -07:00
committed by Facebook GitHub Bot
parent f3f652daab
commit 8dabed60f4
3 changed files with 109 additions and 10 deletions
@@ -8,6 +8,8 @@
* @format
*/
import type {AnimatedPropsAllowlist} from './nodes/AnimatedProps';
import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags';
/**
@@ -16,7 +18,7 @@ import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNa
* In general native animated implementation should support any numeric or color property that
* doesn't need to be updated through the shadow view hierarchy (all non-layout properties).
*/
const SUPPORTED_COLOR_STYLES: {[string]: boolean} = {
const SUPPORTED_COLOR_STYLES: {[string]: true} = {
backgroundColor: true,
borderBottomColor: true,
borderColor: true,
@@ -29,7 +31,7 @@ const SUPPORTED_COLOR_STYLES: {[string]: boolean} = {
tintColor: true,
};
const SUPPORTED_STYLES: {[string]: boolean} = {
const SUPPORTED_STYLES: {[string]: true} = {
...SUPPORTED_COLOR_STYLES,
borderBottomEndRadius: true,
borderBottomLeftRadius: true,
@@ -58,7 +60,7 @@ const SUPPORTED_STYLES: {[string]: boolean} = {
translateY: true,
};
const SUPPORTED_TRANSFORMS: {[string]: boolean} = {
const SUPPORTED_TRANSFORMS: {[string]: true} = {
translateX: true,
translateY: true,
scale: true,
@@ -71,10 +73,12 @@ const SUPPORTED_TRANSFORMS: {[string]: boolean} = {
perspective: true,
skewX: true,
skewY: true,
matrix: ReactNativeFeatureFlags.shouldUseAnimatedObjectForTransform(),
...(ReactNativeFeatureFlags.shouldUseAnimatedObjectForTransform()
? {matrix: true}
: {}),
};
const SUPPORTED_INTERPOLATION_PARAMS: {[string]: boolean} = {
const SUPPORTED_INTERPOLATION_PARAMS: {[string]: true} = {
inputRange: true,
outputRange: true,
extrapolate: true,
@@ -82,6 +86,13 @@ const SUPPORTED_INTERPOLATION_PARAMS: {[string]: boolean} = {
extrapolateLeft: true,
};
/**
* Default allowlist for component props that support native animated values.
*/
export default {
style: SUPPORTED_STYLES,
} as AnimatedPropsAllowlist;
export function allowInterpolationParam(param: string): void {
SUPPORTED_INTERPOLATION_PARAMS[param] = true;
}
@@ -95,17 +106,17 @@ export function allowTransformProp(prop: string): void {
}
export function isSupportedColorStyleProp(prop: string): boolean {
return SUPPORTED_COLOR_STYLES[prop] === true;
return Object.hasOwn(SUPPORTED_COLOR_STYLES, prop);
}
export function isSupportedInterpolationParam(param: string): boolean {
return SUPPORTED_INTERPOLATION_PARAMS[param] === true;
return Object.hasOwn(SUPPORTED_INTERPOLATION_PARAMS, param);
}
export function isSupportedStyleProp(prop: string): boolean {
return SUPPORTED_STYLES[prop] === true;
return Object.hasOwn(SUPPORTED_STYLES, prop);
}
export function isSupportedTransformProp(prop: string): boolean {
return SUPPORTED_TRANSFORMS[prop] === true;
return Object.hasOwn(SUPPORTED_TRANSFORMS, prop);
}
@@ -0,0 +1,87 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall react_native
*/
describe('NativeAnimatedAllowlist', () => {
beforeEach(() => {
jest.restoreAllMocks();
jest.resetModules();
});
it('checks invalid style props', () => {
const {isSupportedStyleProp} = require('../NativeAnimatedAllowlist');
// $FlowExpectedError[incompatible-call]
expect(isSupportedStyleProp(null)).toBe(false);
// $FlowExpectedError[incompatible-call]
expect(isSupportedStyleProp(undefined)).toBe(false);
// $FlowExpectedError[incompatible-call]
expect(isSupportedStyleProp({})).toBe(false);
// $FlowExpectedError[incompatible-call]
expect(isSupportedStyleProp([])).toBe(false);
// $FlowExpectedError[incompatible-call]
expect(isSupportedStyleProp(true)).toBe(false);
// $FlowExpectedError[incompatible-call]
expect(isSupportedStyleProp(false)).toBe(false);
});
it('checks supported interpolation params', () => {
const {
isSupportedInterpolationParam,
} = require('../NativeAnimatedAllowlist');
expect(isSupportedInterpolationParam('inputRange')).toBe(true);
expect(isSupportedInterpolationParam('outputRange')).toBe(true);
expect(isSupportedInterpolationParam('extrapolate')).toBe(true);
expect(isSupportedInterpolationParam('extrapolateRight')).toBe(true);
expect(isSupportedInterpolationParam('extrapolateLeft')).toBe(true);
});
it('allows new interpolation params', () => {
const {
allowInterpolationParam,
isSupportedInterpolationParam,
} = require('../NativeAnimatedAllowlist');
expect(isSupportedInterpolationParam('other')).toBe(false);
allowInterpolationParam('other');
expect(isSupportedInterpolationParam('other')).toBe(true);
});
it('checks supported transform props', () => {
jest
.spyOn(
require('../../../src/private/featureflags/ReactNativeFeatureFlags'),
'shouldUseAnimatedObjectForTransform',
)
.mockReturnValue(false);
const {isSupportedTransformProp} = require('../NativeAnimatedAllowlist');
expect(isSupportedTransformProp('translateX')).toBe(true);
expect(isSupportedTransformProp('translateY')).toBe(true);
expect(isSupportedTransformProp('matrix')).toBe(false);
});
it('checks supported transform props with object for transform', () => {
jest
.spyOn(
require('../../../src/private/featureflags/ReactNativeFeatureFlags'),
'shouldUseAnimatedObjectForTransform',
)
.mockReturnValue(true);
const {isSupportedTransformProp} = require('../NativeAnimatedAllowlist');
expect(isSupportedTransformProp('translateX')).toBe(true);
expect(isSupportedTransformProp('translateY')).toBe(true);
expect(isSupportedTransformProp('matrix')).toBe(true);
});
});
@@ -373,7 +373,8 @@ declare export default typeof Easing;
`;
exports[`public API should not change unintentionally Libraries/Animated/NativeAnimatedAllowlist.js 1`] = `
"declare export function allowInterpolationParam(param: string): void;
"declare export default AnimatedPropsAllowlist;
declare export function allowInterpolationParam(param: string): void;
declare export function allowStyleProp(prop: string): void;
declare export function allowTransformProp(prop: string): void;
declare export function isSupportedColorStyleProp(prop: string): boolean;