diff --git a/packages/react-native/Libraries/ActionSheetIOS/ActionSheetIOS.js b/packages/react-native/Libraries/ActionSheetIOS/ActionSheetIOS.js index 4cb8fcf51460..bac068ea8053 100644 --- a/packages/react-native/Libraries/ActionSheetIOS/ActionSheetIOS.js +++ b/packages/react-native/Libraries/ActionSheetIOS/ActionSheetIOS.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -49,6 +49,7 @@ export type ShareActionSheetIOSOptions = Readonly<{ export type ShareActionSheetError = Readonly<{ domain: string, code: string, + // $FlowFixMe[unclear-type] userInfo?: ?Object, message: string, }>; @@ -155,7 +156,9 @@ const ActionSheetIOS = { */ showShareActionSheetWithOptions( options: ShareActionSheetIOSOptions, + // $FlowFixMe[unclear-type] failureCallback: Function | ((error: ShareActionSheetError) => void), + // $FlowFixMe[unclear-type] successCallback: Function | ((success: boolean, method: ?string) => void), ) { invariant( diff --git a/packages/react-native/Libraries/Alert/Alert.js b/packages/react-native/Libraries/Alert/Alert.js index 4130ec511438..7d844cf63da9 100644 --- a/packages/react-native/Libraries/Alert/Alert.js +++ b/packages/react-native/Libraries/Alert/Alert.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -26,6 +26,7 @@ export type AlertButtonStyle = 'default' | 'cancel' | 'destructive'; export type AlertButton = { text?: string, + // $FlowFixMe[unclear-type] onPress?: ?((value?: string) => any) | ?Function, isPreferred?: boolean, style?: AlertButtonStyle, @@ -121,6 +122,7 @@ class Alert { cancelable: false, }; + // $FlowFixMe[sketchy-null-bool] if (options && options.cancelable) { config.cancelable = options.cancelable; } @@ -141,6 +143,7 @@ class Alert { config.buttonNegative = buttonNegative.text || ''; } if (buttonPositive) { + // $FlowFixMe[sketchy-null-string] config.buttonPositive = buttonPositive.text || defaultPositiveText; } @@ -186,6 +189,7 @@ class Alert { options?: AlertOptions, ): void { if (Platform.OS === 'ios') { + // $FlowFixMe[unclear-type] let callbacks: Array = []; const buttons = []; let cancelButtonKey; @@ -201,9 +205,11 @@ class Alert { } else if (btn.style === 'destructive') { destructiveButtonKey = String(index); } + // $FlowFixMe[sketchy-null-bool] if (btn.isPreferred) { preferredButtonKey = String(index); } + // $FlowFixMe[sketchy-null-string] if (btn.text || index < (callbackOrButtons || []).length - 1) { const btnDef: {[number]: string} = {}; btnDef[index] = btn.text || ''; @@ -215,6 +221,7 @@ class Alert { alertWithArgs( { title: title || '', + // $FlowFixMe[sketchy-null-string] message: message || undefined, buttons, type: type || undefined, diff --git a/packages/react-native/Libraries/Animated/AnimatedEvent.js b/packages/react-native/Libraries/Animated/AnimatedEvent.js index 866e9bdb20d7..f8926d815d16 100644 --- a/packages/react-native/Libraries/Animated/AnimatedEvent.js +++ b/packages/react-native/Libraries/Animated/AnimatedEvent.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -29,6 +29,7 @@ export type EventConfig = { }; export function attachNativeEventImpl( + // $FlowFixMe[unclear-type] viewRef: any, eventName: string, argMapping: ReadonlyArray, @@ -57,6 +58,7 @@ export function attachNativeEventImpl( }; invariant( + // $FlowFixMe[sketchy-null-mixed] argMapping[0] && argMapping[0].nativeEvent, 'Native driven events only support animated values contained inside `nativeEvent`.', ); @@ -91,7 +93,9 @@ export function attachNativeEventImpl( }; } +// $FlowFixMe[unclear-type] function validateMapping(argMapping: ReadonlyArray, args: any) { + // $FlowFixMe[unclear-type] const validate = (recMapping: ?Mapping, recEvt: any, key: string) => { if (recMapping instanceof AnimatedValue) { invariant( @@ -145,16 +149,19 @@ function validateMapping(argMapping: ReadonlyArray, args: any) { export class AnimatedEvent { _argMapping: ReadonlyArray; + // $FlowFixMe[unclear-type] _listeners: Array = []; _attachedEvent: ?{detach: () => void, ...}; __isNative: boolean; __platformConfig: ?PlatformConfig; + // $FlowFixMe[unclear-type] constructor(argMapping: ReadonlyArray, config: EventConfig) { this._argMapping = argMapping; if (config == null) { console.warn('Animated.event now requires a second argument for options'); + // $FlowFixMe[reassign-const] config = {useNativeDriver: false}; } @@ -166,14 +173,17 @@ export class AnimatedEvent { this.__platformConfig = config.platformConfig; } + // $FlowFixMe[unclear-type] __addListener(callback: Function): void { this._listeners.push(callback); } + // $FlowFixMe[unclear-type] __removeListener(callback: Function): void { this._listeners = this._listeners.filter(listener => listener !== callback); } + // $FlowFixMe[unclear-type] __attach(viewRef: any, eventName: string): void { invariant( this.__isNative, @@ -188,6 +198,7 @@ export class AnimatedEvent { ); } + // $FlowFixMe[unclear-type] __detach(viewTag: any, eventName: string): void { invariant( this.__isNative, @@ -197,10 +208,12 @@ export class AnimatedEvent { this._attachedEvent && this._attachedEvent.detach(); } + // $FlowFixMe[unclear-type] __getHandler(): any | ((...args: any) => void) { if (this.__isNative) { if (__DEV__) { let validatedMapping = false; + // $FlowFixMe[unclear-type] return (...args: any) => { if (!validatedMapping) { validateMapping(this._argMapping, args); @@ -214,6 +227,7 @@ export class AnimatedEvent { } let validatedMapping = false; + // $FlowFixMe[unclear-type] return (...args: any) => { if (__DEV__ && !validatedMapping) { validateMapping(this._argMapping, args); @@ -222,6 +236,7 @@ export class AnimatedEvent { const traverse = ( recMapping: ?(Mapping | AnimatedValue), + // $FlowFixMe[unclear-type] recEvt: any, ) => { if (recMapping instanceof AnimatedValue) { @@ -250,6 +265,7 @@ export class AnimatedEvent { }; } + // $FlowFixMe[unclear-type] _callListeners = (...args: any) => { this._listeners.forEach(listener => listener(...args)); }; diff --git a/packages/react-native/Libraries/Animated/AnimatedExports.js b/packages/react-native/Libraries/Animated/AnimatedExports.js index 55940d81c39e..4cb32cf74e00 100644 --- a/packages/react-native/Libraries/Animated/AnimatedExports.js +++ b/packages/react-native/Libraries/Animated/AnimatedExports.js @@ -4,10 +4,12 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ +// flowlint unsafe-getters-setters:off + import typeof AnimatedFlatList from './components/AnimatedFlatList'; import typeof AnimatedImage from './components/AnimatedImage'; import typeof AnimatedScrollView from './components/AnimatedScrollView'; @@ -27,7 +29,7 @@ export default { /** * FlatList and SectionList infer generic Type defined under their `data` and `section` props. */ - get FlatList(): AnimatedFlatList { + get FlatList(): AnimatedFlatList<> { return require('./components/AnimatedFlatList').default; }, /** @@ -47,7 +49,7 @@ export default { /** * FlatList and SectionList infer generic Type defined under their `data` and `section` props. */ - get SectionList(): AnimatedSectionList { + get SectionList(): AnimatedSectionList<> { return require('./components/AnimatedSectionList').default; }, /** diff --git a/packages/react-native/Libraries/Animated/AnimatedExports.js.flow b/packages/react-native/Libraries/Animated/AnimatedExports.js.flow index 7880f98f97af..6178617cec5b 100644 --- a/packages/react-native/Libraries/Animated/AnimatedExports.js.flow +++ b/packages/react-native/Libraries/Animated/AnimatedExports.js.flow @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/packages/react-native/Libraries/Animated/AnimatedImplementation.js b/packages/react-native/Libraries/Animated/AnimatedImplementation.js index 4a9d76a4806a..0b462419e380 100644 --- a/packages/react-native/Libraries/Animated/AnimatedImplementation.js +++ b/packages/react-native/Libraries/Animated/AnimatedImplementation.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -127,7 +127,9 @@ const _combineCallbacks = function ( const maybeVectorAnim = function ( value: AnimatedValue | AnimatedValueXY | AnimatedColor, + // $FlowFixMe[unclear-type] config: Object, + // $FlowFixMe[unclear-type] anim: (value: AnimatedValue, config: Object) => CompositeAnimation, ): ?CompositeAnimation { if (value instanceof AnimatedValueXY) { @@ -184,8 +186,11 @@ const springImpl = function ( configuration: SpringAnimationConfig, callback?: ?EndCallback, ): void { + // $FlowFixMe[reassign-const] callback = _combineCallbacks(callback, configuration); + // $FlowFixMe[unclear-type] const singleValue: any = animatedValue; + // $FlowFixMe[unclear-type] const singleConfig: any = configuration; singleValue.stopTracking(); if (configuration.toValue instanceof AnimatedNode) { @@ -241,8 +246,11 @@ const timingImpl = function ( configuration: TimingAnimationConfig, callback?: ?EndCallback, ): void { + // $FlowFixMe[reassign-const] callback = _combineCallbacks(callback, configuration); + // $FlowFixMe[unclear-type] const singleValue: any = animatedValue; + // $FlowFixMe[unclear-type] const singleConfig: any = configuration; singleValue.stopTracking(); if (configuration.toValue instanceof AnimatedNode) { @@ -299,8 +307,11 @@ const decayImpl = function ( configuration: DecayAnimationConfig, callback?: ?EndCallback, ): void { + // $FlowFixMe[reassign-const] callback = _combineCallbacks(callback, configuration); + // $FlowFixMe[unclear-type] const singleValue: any = animatedValue; + // $FlowFixMe[unclear-type] const singleConfig: any = configuration; singleValue.stopTracking(); singleValue.animate(new DecayAnimation(singleConfig), callback); @@ -551,8 +562,11 @@ const loopImpl = function ( }; function forkEventImpl( + // $FlowFixMe[unclear-type] event: ?AnimatedEvent | ?Function, + // $FlowFixMe[unclear-type] listener: Function, + // $FlowFixMe[unclear-type] ): AnimatedEvent | Function { if (!event) { return listener; @@ -568,7 +582,9 @@ function forkEventImpl( } function unforkEventImpl( + // $FlowFixMe[unclear-type] event: ?AnimatedEvent | ?Function, + // $FlowFixMe[unclear-type] listener: Function, ): void { if (event && event instanceof AnimatedEvent) { @@ -579,6 +595,7 @@ function unforkEventImpl( const eventImpl = function ( argMapping: ReadonlyArray, config: EventConfig, + // $FlowFixMe[unclear-type] ): any { const animatedEvent = new AnimatedEvent(argMapping, config); if (animatedEvent.__isNative) { diff --git a/packages/react-native/Libraries/Animated/AnimatedMock.js b/packages/react-native/Libraries/Animated/AnimatedMock.js index 88eab8815388..dee70ba1a01a 100644 --- a/packages/react-native/Libraries/Animated/AnimatedMock.js +++ b/packages/react-native/Libraries/Animated/AnimatedMock.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -94,6 +94,7 @@ const spring = function ( value: AnimatedValue | AnimatedValueXY | AnimatedColor, config: SpringAnimationConfig, ): CompositeAnimation { + // $FlowFixMe[unclear-type] const anyValue: any = value; return { ...emptyAnimation, @@ -108,6 +109,7 @@ const timing = function ( value: AnimatedValue | AnimatedValueXY | AnimatedColor, config: TimingAnimationConfig, ): CompositeAnimation { + // $FlowFixMe[unclear-type] const anyValue: any = value; return { ...emptyAnimation, diff --git a/packages/react-native/Libraries/Animated/createAnimatedComponent.js b/packages/react-native/Libraries/Animated/createAnimatedComponent.js index 922e95ec9f6c..0c1385c52417 100644 --- a/packages/react-native/Libraries/Animated/createAnimatedComponent.js +++ b/packages/react-native/Libraries/Animated/createAnimatedComponent.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -64,10 +64,10 @@ type PassThroughProps = Readonly<{ passthroughAnimatedPropExplicitValues?: ViewProps | null, }>; -type LooseOmit = Pick< - O, - Exclude, ->; +type LooseOmit< + O extends interface {}, + K extends string | number | symbol, +> = Pick>; export type AnimatedProps = LooseOmit< { @@ -94,7 +94,7 @@ export type AnimatedComponentType< > = component(ref?: React.RefSetter, ...AnimatedProps); export default function createAnimatedComponent< - TInstance extends React.ComponentType, + TInstance extends React.ComponentType, >( Component: TInstance, ): AnimatedComponentType< @@ -158,7 +158,9 @@ export function unstable_createAnimatedComponentWithAllowlist< }; AnimatedComponent.displayName = `Animated(${ - Component.displayName || 'Anonymous' + Component.displayName != null && Component.displayName !== '' + ? Component.displayName + : 'Anonymous' })`; return AnimatedComponent; diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedAddition.js b/packages/react-native/Libraries/Animated/nodes/AnimatedAddition.js index 91d686f5af3d..0f48c8072cfe 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedAddition.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedAddition.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -61,7 +61,11 @@ export default class AnimatedAddition extends AnimatedWithChildren { super.__detach(); } - __getNativeConfig(): any { + __getNativeConfig(): { + type: string, + input: [number, number], + debugID: ?string, + } { return { type: 'addition', input: [this._a.__getNativeTag(), this._b.__getNativeTag()], diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedColor.js b/packages/react-native/Libraries/Animated/nodes/AnimatedColor.js index 712c259d72ca..252814fd071d 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedColor.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedColor.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -90,9 +90,10 @@ function processColor( return null; } -function isRgbaValue(value: any): boolean { +function isRgbaValue(value: unknown): boolean { return ( - value && + value != null && + typeof value === 'object' && typeof value.r === 'number' && typeof value.g === 'number' && typeof value.b === 'number' && @@ -100,9 +101,10 @@ function isRgbaValue(value: any): boolean { ); } -function isRgbaAnimatedValue(value: any): boolean { +function isRgbaAnimatedValue(value: unknown): boolean { return ( - value && + value != null && + typeof value === 'object' && value.r instanceof AnimatedValue && value.g instanceof AnimatedValue && value.b instanceof AnimatedValue && @@ -166,7 +168,7 @@ export default class AnimatedColor extends AnimatedWithChildren { this.a = new AnimatedValue(initColor.a); } - if (config?.useNativeDriver) { + if (config?.useNativeDriver === true) { this.__makeNative(); } } @@ -325,7 +327,15 @@ export default class AnimatedColor extends AnimatedWithChildren { super.__makeNative(platformConfig); } - __getNativeConfig(): {...} { + __getNativeConfig(): { + type: string, + r: number, + g: number, + b: number, + a: number, + nativeColor: ?NativeColorValue, + debugID: ?string, + } { return { type: 'color', r: this.r.__getNativeTag(), diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedDiffClamp.js b/packages/react-native/Libraries/Animated/nodes/AnimatedDiffClamp.js index 94fef85aa0e1..29d0d170ad5c 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedDiffClamp.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedDiffClamp.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -68,7 +68,13 @@ export default class AnimatedDiffClamp extends AnimatedWithChildren { super.__detach(); } - __getNativeConfig(): any { + __getNativeConfig(): { + type: string, + input: number, + min: number, + max: number, + debugID: ?string, + } { return { type: 'diffclamp', input: this._a.__getNativeTag(), diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedDivision.js b/packages/react-native/Libraries/Animated/nodes/AnimatedDivision.js index 6b73ff7d9931..ac8eba488ecf 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedDivision.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedDivision.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -77,7 +77,11 @@ export default class AnimatedDivision extends AnimatedWithChildren { super.__detach(); } - __getNativeConfig(): any { + __getNativeConfig(): { + type: string, + input: [number, number], + debugID: ?string, + } { return { type: 'division', input: [this._a.__getNativeTag(), this._b.__getNativeTag()], diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedInterpolation.js b/packages/react-native/Libraries/Animated/nodes/AnimatedInterpolation.js index b6a0d4d3b5f5..2de142791f13 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedInterpolation.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedInterpolation.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -49,7 +49,7 @@ export type InterpolationConfigType< function createNumericInterpolation( config: InterpolationConfigType, ): (input: number) => number { - const outputRange: ReadonlyArray = config.outputRange as any; + const outputRange: ReadonlyArray = config.outputRange; const inputRange = config.inputRange; const easing = config.easing || Easing.linear; @@ -84,6 +84,7 @@ function createNumericInterpolation( easing, extrapolateLeft, extrapolateRight, + // $FlowFixMe[unclear-type] ) as any; }; } @@ -203,6 +204,7 @@ function mapStringToNumericComponents( const components: Array = []; let lastMatchEnd = 0; let match: RegExp$matchResult; + // $FlowFixMe[unclear-type] while ((match = numericComponentRegex.exec(input) as any) != null) { if (match.index > lastMatchEnd) { components.push(input.substring(lastMatchEnd, match.index)); @@ -466,12 +468,16 @@ export default class AnimatedInterpolation< if (!this._interpolation) { const config = this._config; if (config.outputRange && typeof config.outputRange[0] === 'string') { + // $FlowFixMe[unclear-type] this._interpolation = createStringInterpolation(config as any) as any; } else if (typeof config.outputRange[0] === 'object') { this._interpolation = createPlatformColorInterpolation( + // $FlowFixMe[unclear-type] config as any, + // $FlowFixMe[unclear-type] ) as any; } else { + // $FlowFixMe[unclear-type] this._interpolation = createNumericInterpolation(config as any) as any; } } @@ -508,6 +514,7 @@ export default class AnimatedInterpolation< super.__detach(); } + // $FlowFixMe[unclear-type] __getNativeConfig(): any { if (__DEV__) { validateInterpolation(this._config); @@ -526,6 +533,7 @@ export default class AnimatedInterpolation< } else { return NativeAnimatedHelper.transformDataType(value); } + // $FlowFixMe[unclear-type] }) as any; } else if (typeof outputRange[0] === 'object') { outputType = 'platform_color'; diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedModulo.js b/packages/react-native/Libraries/Animated/nodes/AnimatedModulo.js index 32a698afbdac..91825c3dcf0f 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedModulo.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedModulo.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -55,7 +55,12 @@ export default class AnimatedModulo extends AnimatedWithChildren { super.__detach(); } - __getNativeConfig(): any { + __getNativeConfig(): { + type: string, + input: number, + modulus: number, + debugID: ?string, + } { return { type: 'modulus', input: this._a.__getNativeTag(), diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedMultiplication.js b/packages/react-native/Libraries/Animated/nodes/AnimatedMultiplication.js index 93764f86c751..0411cb593ad3 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedMultiplication.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedMultiplication.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -60,7 +60,11 @@ export default class AnimatedMultiplication extends AnimatedWithChildren { super.__detach(); } - __getNativeConfig(): any { + __getNativeConfig(): { + type: string, + input: [number, number], + debugID: ?string, + } { return { type: 'multiplication', input: [this._a.__getNativeTag(), this._b.__getNativeTag()], diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedNode.js b/packages/react-native/Libraries/Animated/nodes/AnimatedNode.js index b10fe9da8bee..5eb2d18b2865 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedNode.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedNode.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -55,7 +55,9 @@ export default class AnimatedNode { this.__nativeTag = undefined; } } + // $FlowFixMe[unclear-type] __getValue(): any {} + // $FlowFixMe[unclear-type] __getAnimatedValue(): any { return this.__getValue(); } @@ -87,6 +89,7 @@ export default class AnimatedNode { * * See https://reactnative.dev/docs/animatedvalue#addlistener */ + // $FlowFixMe[unclear-type] addListener(callback: (value: any) => unknown): string { const id = String(_uniqueId++); this._listeners.set(id, callback); @@ -146,6 +149,7 @@ export default class AnimatedNode { if (this._platformConfig) { config.platformConfig = this._platformConfig; } + // $FlowFixMe[sketchy-null-bool] if (this.__disableBatchingForNativeCreate) { config.disableBatchingForNativeCreate = true; } @@ -154,6 +158,7 @@ export default class AnimatedNode { return nativeTag; } + // $FlowFixMe[unclear-type] __getNativeConfig(): Object { throw new Error( 'This JS animated node type cannot be used as native animated node', diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedObject.js b/packages/react-native/Libraries/Animated/nodes/AnimatedObject.js index 8f1793ec0472..6cbae410ddc1 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedObject.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedObject.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -64,7 +64,11 @@ function flatAnimatedNodes( } // Returns a copy of value with a transformation fn applied to any AnimatedNodes -function mapAnimatedNodes(value: any, fn: any => any, depth: number = 0): any { +function mapAnimatedNodes( + value: unknown, + fn: (node: AnimatedNode) => unknown, + depth: number = 0, +): unknown { if (depth >= MAX_DEPTH) { return value; } @@ -74,7 +78,7 @@ function mapAnimatedNodes(value: any, fn: any => any, depth: number = 0): any { } else if (Array.isArray(value)) { return value.map(element => mapAnimatedNodes(element, fn, depth + 1)); } else if (isPlainObject(value)) { - const result: {[string]: any} = {}; + const result: {[string]: unknown} = {}; const keys = Object.keys(value); for (let ii = 0, length = keys.length; ii < length; ii++) { const key = keys[ii]; @@ -115,13 +119,13 @@ export default class AnimatedObject extends AnimatedWithChildren { this._value = value; } - __getValue(): any { + __getValue(): unknown { return mapAnimatedNodes(this._value, node => { return node.__getValue(); }); } - __getValueWithStaticObject(staticObject: unknown): any { + __getValueWithStaticObject(staticObject: unknown): unknown { const nodes = this._nodes; let index = 0; // NOTE: We can depend on `this._value` and `staticObject` sharing a @@ -129,7 +133,7 @@ export default class AnimatedObject extends AnimatedWithChildren { return mapAnimatedNodes(staticObject, () => nodes[index++].__getValue()); } - __getAnimatedValue(): any { + __getAnimatedValue(): unknown { return mapAnimatedNodes(this._value, node => { return node.__getAnimatedValue(); }); @@ -162,7 +166,11 @@ export default class AnimatedObject extends AnimatedWithChildren { super.__makeNative(platformConfig); } - __getNativeConfig(): any { + __getNativeConfig(): { + type: string, + value: unknown, + debugID: ?string, + } { return { type: 'object', value: mapAnimatedNodes(this._value, node => { diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedProps.js b/packages/react-native/Libraries/Animated/nodes/AnimatedProps.js index 6581c150f437..fcc1661d4dea 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedProps.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedProps.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -119,6 +119,7 @@ export default class AnimatedProps extends AnimatedNode { this._rootTag = rootTag; } + // $FlowFixMe[unclear-type] __getValue(): Object { const props: {[string]: unknown} = {}; @@ -144,6 +145,7 @@ export default class AnimatedProps extends AnimatedNode { * `staticProps` object, except with animated nodes for any props that were * created by this `AnimatedProps` instance. */ + // $FlowFixMe[unclear-type] __getValueWithStaticProps(staticProps: Object): Object { const props: {[string]: unknown} = {...staticProps}; @@ -196,6 +198,7 @@ export default class AnimatedProps extends AnimatedNode { return tuples; } + // $FlowFixMe[unclear-type] __getAnimatedValue(): Object { const props: {[string]: unknown} = {}; @@ -356,6 +359,7 @@ export default class AnimatedProps extends AnimatedNode { } } + // $FlowFixMe[unclear-type] __getNativeConfig(): Object { const platformConfig = this.__getPlatformConfig(); const propsConfig: {[string]: number} = {}; diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedStyle.js b/packages/react-native/Libraries/Animated/nodes/AnimatedStyle.js index 3b04b8ba2835..57a9fc816153 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedStyle.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedStyle.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -184,6 +184,7 @@ export default class AnimatedStyle extends AnimatedWithChildren { } } + // $FlowFixMe[unclear-type] __getAnimatedValue(): Object { const style: {[string]: unknown} = {}; @@ -225,6 +226,7 @@ export default class AnimatedStyle extends AnimatedWithChildren { super.__makeNative(platformConfig); } + // $FlowFixMe[unclear-type] __getNativeConfig(): Object { const platformConfig = this.__getPlatformConfig(); const styleConfig: {[string]: ?number} = {}; diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedSubtraction.js b/packages/react-native/Libraries/Animated/nodes/AnimatedSubtraction.js index 04181bda7b20..0b1d3f22c52c 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedSubtraction.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedSubtraction.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -61,7 +61,11 @@ export default class AnimatedSubtraction extends AnimatedWithChildren { super.__detach(); } - __getNativeConfig(): any { + __getNativeConfig(): { + type: string, + input: [number, number], + debugID: ?string, + } { return { type: 'subtraction', input: [this._a.__getNativeTag(), this._b.__getNativeTag()], diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedTracking.js b/packages/react-native/Libraries/Animated/nodes/AnimatedTracking.js index d50d2921e5b0..17229e30b3bb 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedTracking.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedTracking.js @@ -4,33 +4,40 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; import type {PlatformConfig} from '../AnimatedPlatformConfig'; -import type {EndCallback} from '../animations/Animation'; +import type Animation from '../animations/Animation'; +import type {AnimationConfig, EndCallback} from '../animations/Animation'; import type {AnimatedNodeConfig} from './AnimatedNode'; import type AnimatedValue from './AnimatedValue'; import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper'; import AnimatedNode from './AnimatedNode'; +type TrackingAnimationConfig = Readonly<{ + ...AnimationConfig, + toValue: AnimatedNode, + ... +}>; + export default class AnimatedTracking extends AnimatedNode { _value: AnimatedValue; _parent: AnimatedNode; _callback: ?EndCallback; - _animationConfig: Object; - _animationClass: any; + _animationConfig: TrackingAnimationConfig; + _animationClass: Class; _useNativeDriver: boolean; constructor( value: AnimatedValue, parent: AnimatedNode, - animationClass: any, - animationConfig: Object, + animationClass: Class, + animationConfig: TrackingAnimationConfig, callback?: ?EndCallback, config?: ?AnimatedNodeConfig, ) { @@ -52,7 +59,7 @@ export default class AnimatedTracking extends AnimatedNode { this._value.__makeNative(platformConfig); } - __getValue(): Object { + __getValue(): number { return this._parent.__getValue(); } @@ -79,13 +86,20 @@ export default class AnimatedTracking extends AnimatedNode { this._value.animate( new this._animationClass({ ...this._animationConfig, - toValue: (this._animationConfig.toValue as any).__getValue(), + toValue: this._animationConfig.toValue.__getValue(), }), this._callback, ); } - __getNativeConfig(): any { + __getNativeConfig(): { + type: string, + animationId: number, + animationConfig: Readonly<{platformConfig: ?PlatformConfig, ...}>, + toValue: number, + value: number, + debugID: ?string, + } { const animation = new this._animationClass({ ...this._animationConfig, // remove toValue from the config as it's a ref to Animated.Value diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedTransform.js b/packages/react-native/Libraries/Animated/nodes/AnimatedTransform.js index 86900cc17f84..46d9ae1f5657 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedTransform.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedTransform.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -87,6 +87,7 @@ export default class AnimatedTransform extends AnimatedWithChildren { super.__makeNative(platformConfig); } + // $FlowFixMe[unclear-type] __getValue(): ReadonlyArray> { return mapTransforms(this._transforms, animatedNode => animatedNode.__getValue(), @@ -94,7 +95,9 @@ export default class AnimatedTransform extends AnimatedWithChildren { } __getValueWithStaticTransforms( + // $FlowFixMe[unclear-type] staticTransforms: ReadonlyArray, + // $FlowFixMe[unclear-type] ): ReadonlyArray { const values = []; mapTransforms(this._transforms, node => { @@ -105,6 +108,7 @@ export default class AnimatedTransform extends AnimatedWithChildren { return mapTransforms(staticTransforms, () => values.shift()); } + // $FlowFixMe[unclear-type] __getAnimatedValue(): ReadonlyArray> { return mapTransforms(this._transforms, animatedNode => animatedNode.__getAnimatedValue(), @@ -129,7 +133,9 @@ export default class AnimatedTransform extends AnimatedWithChildren { super.__detach(); } + // $FlowFixMe[unclear-type] __getNativeConfig(): any { + // $FlowFixMe[unclear-type] const transformsConfig: Array = []; const transforms = this._transforms; diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedValue.js b/packages/react-native/Libraries/Animated/nodes/AnimatedValue.js index 76dba2196f48..800f8dba0350 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedValue.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedValue.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -55,10 +55,12 @@ const NativeAnimatedAPI = NativeAnimatedHelper.API; * transform which can receive values from multiple parents. */ export function flushValue(rootNode: AnimatedNode): void { - const leaves = new Set<{update: () => void, ...}>(); + const leaves = new Set void}>(); function findAnimatedStyles(node: AnimatedNode) { - // $FlowFixMe[prop-missing] - if (typeof node.update === 'function') { + if ( + typeof (node as interface {update?: () => void}).update === 'function' + ) { + // $FlowFixMe[unclear-type] `update` is duck-typed on animated leaf nodes and not declared on AnimatedNode leaves.add(node as any); } else { node.__getChildren().forEach(findAnimatedStyles); @@ -138,7 +140,7 @@ export default class AnimatedValue extends AnimatedWithChildren { } } - addListener(callback: (value: any) => unknown): string { + addListener(callback: (value: {value: number}) => unknown): string { const id = super.addListener(callback); this._listenerCount++; if (this.__isNative) { @@ -371,7 +373,12 @@ export default class AnimatedValue extends AnimatedWithChildren { this.__callListeners(this.__getValue()); } - __getNativeConfig(): Object { + __getNativeConfig(): { + type: string, + value: number, + offset: number, + debugID: ?string, + } { return { type: 'value', value: this._value, diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedValueXY.js b/packages/react-native/Libraries/Animated/nodes/AnimatedValueXY.js index 0c008919c8b8..a2634798a856 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedValueXY.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedValueXY.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -52,18 +52,23 @@ export default class AnimatedValueXY extends AnimatedWithChildren { config?: ?AnimatedValueXYConfig, ) { super(config); - const value: any = valueIn || {x: 0, y: 0}; // @flowfixme: shouldn't need `: any` - if (typeof value.x === 'number' && typeof value.y === 'number') { - this.x = new AnimatedValue(value.x); - this.y = new AnimatedValue(value.y); + const value: { + readonly x: number | AnimatedValue, + readonly y: number | AnimatedValue, + ... + } = valueIn || {x: 0, y: 0}; + const {x, y} = value; + if (typeof x === 'number' && typeof y === 'number') { + this.x = new AnimatedValue(x); + this.y = new AnimatedValue(y); } else { invariant( - value.x instanceof AnimatedValue && value.y instanceof AnimatedValue, + x instanceof AnimatedValue && y instanceof AnimatedValue, 'AnimatedValueXY must be initialized with an object of numbers or ' + 'AnimatedValues.', ); - this.x = value.x; - this.y = value.y; + this.x = x; + this.y = y; } this._listeners = {}; if (config && config.useNativeDriver) { @@ -164,7 +169,7 @@ export default class AnimatedValueXY extends AnimatedWithChildren { */ addListener(callback: ValueXYListenerCallback): string { const id = String(_uniqueId++); - const jointCallback = ({value: number}: any) => { + const jointCallback = () => { callback(this.__getValue()); }; this._listeners[id] = { diff --git a/packages/react-native/Libraries/Blob/File.js b/packages/react-native/Libraries/Blob/File.js index 0783d1c503b6..ccbd83dba703 100644 --- a/packages/react-native/Libraries/Blob/File.js +++ b/packages/react-native/Libraries/Blob/File.js @@ -4,10 +4,12 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ +// flowlint unsafe-getters-setters:off + 'use strict'; import type {BlobOptions} from './BlobTypes'; diff --git a/packages/react-native/Libraries/Blob/FileReader.js b/packages/react-native/Libraries/Blob/FileReader.js index 3745c00923a8..c566a765c100 100644 --- a/packages/react-native/Libraries/Blob/FileReader.js +++ b/packages/react-native/Libraries/Blob/FileReader.js @@ -4,10 +4,12 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ +// flowlint unsafe-getters-setters:off + import type {EventCallback} from '../../src/private/webapis/dom/events/EventTarget'; import type Blob from './Blob'; diff --git a/packages/react-native/Libraries/Blob/URL.js b/packages/react-native/Libraries/Blob/URL.js index f4f879a51214..8386cc6d979d 100644 --- a/packages/react-native/Libraries/Blob/URL.js +++ b/packages/react-native/Libraries/Blob/URL.js @@ -4,10 +4,12 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ +// flowlint unsafe-getters-setters:off + import type Blob from './Blob'; import NativeBlobModule from './NativeBlobModule'; @@ -79,7 +81,7 @@ export class URL { // $FlowFixMe[missing-local-annot] constructor(url: string, base?: string | URL) { let baseUrl = null; - if (!base || validateBaseUrl(url)) { + if (base == null || base === '' || validateBaseUrl(url)) { this._url = url; if (this._url.includes('#')) { const split = this._url.split('#'); @@ -112,13 +114,14 @@ export class URL { if (baseUrl.endsWith('/')) { baseUrl = baseUrl.slice(0, baseUrl.length - 1); } - if (!url.startsWith('/')) { - url = `/${url}`; + let path = url; + if (!path.startsWith('/')) { + path = `/${path}`; } - if (baseUrl.endsWith(url)) { - url = ''; + if (baseUrl.endsWith(path)) { + path = ''; } - this._url = `${baseUrl}${url}`; + this._url = `${baseUrl}${path}`; } } diff --git a/packages/react-native/Libraries/Blob/URLSearchParams.js b/packages/react-native/Libraries/Blob/URLSearchParams.js index d325f7bb25a8..1cf3ef6b2f4e 100644 --- a/packages/react-native/Libraries/Blob/URLSearchParams.js +++ b/packages/react-native/Libraries/Blob/URLSearchParams.js @@ -4,10 +4,12 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ +// flowlint unsafe-getters-setters:off + // Small subset from whatwg-url: https://github.com/jsdom/whatwg-url/tree/master/src // The reference code bloat comes from Unicode issues with URLs, so those won't work here. export class URLSearchParams { diff --git a/packages/react-native/Libraries/Blob/URLSearchParams.js.flow b/packages/react-native/Libraries/Blob/URLSearchParams.js.flow index df5b32557dda..fe7741a88d41 100644 --- a/packages/react-native/Libraries/Blob/URLSearchParams.js.flow +++ b/packages/react-native/Libraries/Blob/URLSearchParams.js.flow @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/packages/react-native/Libraries/Components/ActivityIndicator/ActivityIndicator.js b/packages/react-native/Libraries/Components/ActivityIndicator/ActivityIndicator.js index 3200bb8afc56..f021d43aad26 100644 --- a/packages/react-native/Libraries/Components/ActivityIndicator/ActivityIndicator.js +++ b/packages/react-native/Libraries/Components/ActivityIndicator/ActivityIndicator.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -115,7 +115,7 @@ const ActivityIndicator: component( style, ...restProps }: { - ref?: any, + ref?: React.RefSetter, ...ActivityIndicatorProps, }) => { let sizeStyle; diff --git a/packages/react-native/Libraries/Components/Button.js b/packages/react-native/Libraries/Components/Button.js index c1bec4b65edf..7855575dbf80 100644 --- a/packages/react-native/Libraries/Components/Button.js +++ b/packages/react-native/Libraries/Components/Button.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -232,7 +232,7 @@ const Button: component( } = props; const buttonStyles: Array = [styles.button]; const textStyles: Array = [styles.text]; - if (color) { + if (color != null && color !== '' && color !== 0) { if (Platform.OS === 'ios') { textStyles.push({color: color}); } else { @@ -256,7 +256,7 @@ const Button: component( ? {..._accessibilityState, disabled} : _accessibilityState; - if (disabled) { + if (disabled === true) { buttonStyles.push(styles.buttonDisabled); textStyles.push(styles.textDisabled); } @@ -279,7 +279,9 @@ const Button: component( accessible={accessible} accessibilityActions={accessibilityActions} onAccessibilityAction={onAccessibilityAction} - accessibilityLabel={ariaLabel || accessibilityLabel} + accessibilityLabel={ + ariaLabel != null && ariaLabel !== '' ? ariaLabel : accessibilityLabel + } accessibilityHint={accessibilityHint} accessibilityLanguage={accessibilityLanguage} accessibilityRole="button" diff --git a/packages/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/packages/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index 77c72316cfe8..0ee0b92b667c 100644 --- a/packages/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/packages/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -4,10 +4,12 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ +// flowlint unsafe-getters-setters:off + import type { MeasureInWindowOnSuccessCallback, MeasureLayoutOnSuccessCallback, @@ -204,7 +206,7 @@ class DrawerLayoutAndroid ); } - setNativeProps(nativeProps: Object) { + setNativeProps(nativeProps: {...}) { nullthrows(this._nativeRef.current).setNativeProps(nativeProps); } } diff --git a/packages/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.js b/packages/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.js index 5776fd4f500e..0bf8cca18b4d 100644 --- a/packages/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.js +++ b/packages/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/packages/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroidTypes.js b/packages/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroidTypes.js index c5b16a13e090..cbe137320123 100644 --- a/packages/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroidTypes.js +++ b/packages/react-native/Libraries/Components/DrawerAndroid/DrawerLayoutAndroidTypes.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -127,7 +127,7 @@ export interface DrawerLayoutAndroidMethods { onSuccess: MeasureLayoutOnSuccessCallback, onFail?: () => void, ): void; - setNativeProps(nativeProps: Object): void; + setNativeProps(nativeProps: {...}): void; } export type DrawerLayoutAndroidInstance = DrawerLayoutAndroidMethods; diff --git a/packages/react-native/Libraries/Components/StatusBar/StatusBar.js b/packages/react-native/Libraries/Components/StatusBar/StatusBar.js index 0cd2315373ae..bab23467263c 100644 --- a/packages/react-native/Libraries/Components/StatusBar/StatusBar.js +++ b/packages/react-native/Libraries/Components/StatusBar/StatusBar.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -101,13 +101,25 @@ export type StatusBarProps = Readonly<{ type StackProps = { barStyle: ?{ - value: StatusBarProps['barStyle'], + value: StatusBarStyle, animated: boolean, }, hidden: ?{ value: boolean, animated: boolean, - transition: StatusBarProps['showHideTransition'], + transition: StatusBarAnimation, + }, +}; + +type ResolvedStackProps = { + barStyle: { + value: StatusBarStyle, + animated: boolean, + }, + hidden: { + value: boolean, + animated: boolean, + transition: StatusBarAnimation, }, }; @@ -126,13 +138,16 @@ function getAutoBarStyle(): 'light-content' | 'dark-content' { * barStyle to a concrete value. */ function mergePropsStack( - propsStack: Array, - defaultValues: Object, -): Object { - const merged: StackProps = propsStack.reduce( + propsStack: Array, + defaultValues: ResolvedStackProps, +): ResolvedStackProps { + const merged: ResolvedStackProps = propsStack.reduce( (prev, cur) => { for (const prop in cur) { + // $FlowFixMe[invalid-computed-prop] dynamic merge over the known StackProps keys if (cur[prop] != null) { + // $FlowFixMe[invalid-computed-prop] dynamic merge over the known StackProps keys + // $FlowFixMe[prop-missing] dynamic merge over the known StackProps keys prev[prop] = cur[prop]; } } @@ -141,7 +156,7 @@ function mergePropsStack( {...defaultValues}, ); - if (merged.barStyle?.value === 'auto') { + if (merged.barStyle.value === 'auto') { merged.barStyle = {...merged.barStyle, value: getAutoBarStyle()}; } @@ -224,10 +239,10 @@ function createStackEntry(props: StatusBarProps): StackProps { class StatusBar extends React.Component { static _propsStack: Array = []; - static _defaultProps: any = createStackEntry({ - barStyle: 'default', - hidden: false, - }); + static _defaultProps: ResolvedStackProps = { + barStyle: {value: 'default', animated: false}, + hidden: {value: false, animated: false, transition: 'fade'}, + }; // Timer for updating the native module values at the end of the frame. static _updateImmediate: ?number = null; @@ -235,7 +250,7 @@ class StatusBar extends React.Component { // The current merged values from the props stack. `barStyle.value` is stored // in its resolved form (never `'auto'`), so diff comparisons reflect what // was actually sent to the native module. - static _currentValues: ?StackProps = null; + static _currentValues: ?ResolvedStackProps = null; // Number of mounted `StatusBar` instances. Used to lazily subscribe to color // scheme changes only while at least one instance is on screen. @@ -264,10 +279,10 @@ class StatusBar extends React.Component { * changing the status bar hidden property. */ static setHidden(hidden: boolean, animation?: StatusBarAnimation) { - animation = animation || 'none'; + const resolvedAnimation = animation ?? 'none'; StatusBar._defaultProps.hidden.value = hidden; if (Platform.OS === 'ios') { - NativeStatusBarManagerIOS.setHidden(hidden, animation); + NativeStatusBarManagerIOS.setHidden(hidden, resolvedAnimation); } else if (Platform.OS === 'android') { NativeStatusBarManagerAndroid.setHidden(hidden); } @@ -279,11 +294,11 @@ class StatusBar extends React.Component { * @param animated Animate the style change. */ static setBarStyle(style: StatusBarStyle, animated?: boolean) { - animated = animated || false; + const resolvedAnimated = animated ?? false; StatusBar._defaultProps.barStyle.value = style; const resolvedStyle = style === 'auto' ? getAutoBarStyle() : style; if (Platform.OS === 'ios') { - NativeStatusBarManagerIOS.setStyle(resolvedStyle, animated); + NativeStatusBarManagerIOS.setStyle(resolvedStyle, resolvedAnimated); } else if (Platform.OS === 'android') { NativeStatusBarManagerAndroid.setStyle(resolvedStyle); } diff --git a/packages/react-native/Libraries/Components/Touchable/PooledClass.js b/packages/react-native/Libraries/Components/Touchable/PooledClass.js index 224c17bd295e..d831176f65af 100644 --- a/packages/react-native/Libraries/Components/Touchable/PooledClass.js +++ b/packages/react-native/Libraries/Components/Touchable/PooledClass.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -20,6 +20,7 @@ import invariant from 'invariant'; */ /* $FlowFixMe[missing-this-annot] The 'this' type annotation(s) required by * Flow's LTI update could not be added via codemod */ +// $FlowFixMe[unclear-type] const oneArgumentPooler = function (copyFieldsFrom: any) { const Klass = this; // eslint-disable-line consistent-this if (Klass.instancePool.length) { @@ -33,6 +34,7 @@ const oneArgumentPooler = function (copyFieldsFrom: any) { /* $FlowFixMe[missing-this-annot] The 'this' type annotation(s) required by * Flow's LTI update could not be added via codemod */ +// $FlowFixMe[unclear-type] const twoArgumentPooler = function (a1: any, a2: any) { const Klass = this; // eslint-disable-line consistent-this if (Klass.instancePool.length) { @@ -46,6 +48,7 @@ const twoArgumentPooler = function (a1: any, a2: any) { /* $FlowFixMe[missing-this-annot] The 'this' type annotation(s) required by * Flow's LTI update could not be added via codemod */ +// $FlowFixMe[unclear-type] const threeArgumentPooler = function (a1: any, a2: any, a3: any) { const Klass = this; // eslint-disable-line consistent-this if (Klass.instancePool.length) { @@ -59,6 +62,7 @@ const threeArgumentPooler = function (a1: any, a2: any, a3: any) { /* $FlowFixMe[missing-this-annot] The 'this' type annotation(s) required by * Flow's LTI update could not be added via codemod */ +// $FlowFixMe[unclear-type] const fourArgumentPooler = function (a1: any, a2: any, a3: any, a4: any) { const Klass = this; // eslint-disable-line consistent-this if (Klass.instancePool.length) { @@ -89,6 +93,7 @@ const standardReleaser = function (instance) { const DEFAULT_POOL_SIZE = 10; const DEFAULT_POOLER = oneArgumentPooler; +// $FlowFixMe[unclear-type] type Pooler = any; /** @@ -112,6 +117,7 @@ const addPoolingTo = function ( } { // Casting as any so that flow ignores the actual implementation and trusts // it to match the type we declared + // $FlowFixMe[unclear-type] const NewKlass: any = CopyConstructor; NewKlass.instancePool = []; NewKlass.getPooled = pooler || DEFAULT_POOLER; diff --git a/packages/react-native/Libraries/Components/Touchable/Touchable.js b/packages/react-native/Libraries/Components/Touchable/Touchable.js index 827477f98c5b..8c5605366426 100644 --- a/packages/react-native/Libraries/Components/Touchable/Touchable.js +++ b/packages/react-native/Libraries/Components/Touchable/Touchable.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -331,7 +331,7 @@ const TouchableMixinImpl = { */ /* $FlowFixMe[missing-this-annot] The 'this' type annotation(s) required by * Flow's LTI update could not be added via codemod */ - touchableHandleResponderTerminationRequest: function (): any { + touchableHandleResponderTerminationRequest: function (): boolean { return !this.props.rejectResponderTermination; }, @@ -340,7 +340,7 @@ const TouchableMixinImpl = { */ /* $FlowFixMe[missing-this-annot] The 'this' type annotation(s) required by * Flow's LTI update could not be added via codemod */ - touchableHandleStartShouldSetResponder: function (): any { + touchableHandleStartShouldSetResponder: function (): boolean { return !this.props.disabled; }, diff --git a/packages/react-native/Libraries/Core/Timers/JSTimers.js b/packages/react-native/Libraries/Core/Timers/JSTimers.js index 82bd3c81de00..f196f54015c5 100644 --- a/packages/react-native/Libraries/Core/Timers/JSTimers.js +++ b/packages/react-native/Libraries/Core/Timers/JSTimers.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format * @deprecated */ @@ -29,13 +29,15 @@ export type JSTimerType = | 'queueReactNativeMicrotask' | 'requestIdleCallback'; +type TimerFunc = (...args: Array) => unknown; + // These timing constants should be kept in sync with the ones in native ios and // android `RCTTiming` module. const FRAME_DURATION = 1000 / 60; const IDLE_CALLBACK_FRAME_DEADLINE = 1; // Parallel arrays -const callbacks: Array = []; +const callbacks: Array = []; const types: Array = []; const timerIDs: Array = []; const freeIdxs: Array = []; @@ -57,7 +59,7 @@ function _getFreeIndex(): number { return freeIdx; } -function _allocateCallback(func: Function, type: JSTimerType): number { +function _allocateCallback(func: TimerFunc, type: JSTimerType): number { const id = GUID++; const freeIndex = _getFreeIndex(); timerIDs[freeIndex] = id; @@ -210,9 +212,9 @@ const JSTimers = { * @param {number} duration Number of milliseconds. */ setTimeout: function ( - func: Function, + func: TimerFunc, duration: number, - ...args: any + ...args: Array ): number { const id = _allocateCallback( () => func.apply(undefined, args), @@ -227,9 +229,9 @@ const JSTimers = { * @param {number} duration Number of milliseconds. */ setInterval: function ( - func: Function, + func: TimerFunc, duration: number, - ...args: any + ...args: Array ): number { const id = _allocateCallback( () => func.apply(undefined, args), @@ -247,7 +249,10 @@ const JSTimers = { * @param {function} func Callback to be invoked before the end of the * current JavaScript execution loop. */ - queueReactNativeMicrotask: function (func: Function, ...args: any): number { + queueReactNativeMicrotask: function ( + func: TimerFunc, + ...args: Array + ): number { const id = _allocateCallback( () => func.apply(undefined, args), 'queueReactNativeMicrotask', @@ -259,7 +264,7 @@ const JSTimers = { /** * @param {function} func Callback to be invoked every frame. */ - requestAnimationFrame: function (func: Function): any | number { + requestAnimationFrame: function (func: TimerFunc): number { const id = _allocateCallback(func, 'requestAnimationFrame'); createTimer(id, 1, Date.now(), /* recurring */ false); return id; @@ -271,9 +276,9 @@ const JSTimers = { * @param {?object} options */ requestIdleCallback: function ( - func: Function, - options: ?Object, - ): any | number { + func: TimerFunc, + options: ?{timeout?: number, ...}, + ): number { if (requestIdleCallbacks.length === 0) { setSendIdleEvents(true); } @@ -281,7 +286,7 @@ const JSTimers = { const timeout = options && options.timeout; const id: number = _allocateCallback( timeout != null - ? (deadline: any) => { + ? (deadline: unknown) => { const timeoutId: number = requestIdleCallbackTimeouts[id]; if (timeoutId) { JSTimers.clearTimeout(timeoutId); @@ -353,7 +358,7 @@ const JSTimers = { * This is called from the native side. We are passed an array of timerIDs, * and */ - callTimers: function (timersToCall: Array): any | void { + callTimers: function (timersToCall: Array): void { invariant( timersToCall.length !== 0, 'Cannot call `callTimers` with an empty list of IDs.', @@ -458,20 +463,34 @@ function setSendIdleEvents(sendIdleEvents: boolean): void { } let ExportedJSTimers: { - callIdleCallbacks: (frameTime: number) => any | void, + callIdleCallbacks: (frameTime: number) => void, callReactNativeMicrotasks: () => void, - callTimers: (timersToCall: Array) => any | void, + callTimers: (timersToCall: Array) => void, cancelAnimationFrame: (timerID: number) => void, cancelIdleCallback: (timerID: number) => void, clearReactNativeMicrotask: (timerID: number) => void, clearInterval: (timerID: number) => void, clearTimeout: (timerID: number) => void, - emitTimeDriftWarning: (warningMessage: string) => any | void, - requestAnimationFrame: (func: any) => any | number, - requestIdleCallback: (func: any, options: ?any) => any | number, - queueReactNativeMicrotask: (func: any, ...args: any) => number, - setInterval: (func: any, duration: number, ...args: any) => number, - setTimeout: (func: any, duration: number, ...args: any) => number, + emitTimeDriftWarning: (warningMessage: string) => void, + requestAnimationFrame: (func: TimerFunc) => number, + requestIdleCallback: ( + func: TimerFunc, + options: ?{timeout?: number, ...}, + ) => number, + queueReactNativeMicrotask: ( + func: TimerFunc, + ...args: Array + ) => number, + setInterval: ( + func: TimerFunc, + duration: number, + ...args: Array + ) => number, + setTimeout: ( + func: TimerFunc, + duration: number, + ...args: Array + ) => number, }; if (!NativeTiming) { diff --git a/packages/react-native/Libraries/Core/Timers/immediateShim.js b/packages/react-native/Libraries/Core/Timers/immediateShim.js index 6e9534de1621..df84d573ed3f 100644 --- a/packages/react-native/Libraries/Core/Timers/immediateShim.js +++ b/packages/react-native/Libraries/Core/Timers/immediateShim.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format * @deprecated */ @@ -22,7 +22,10 @@ const clearedImmediates: Set = new Set(); * @param {function} func Callback to be invoked before the end of the * current JavaScript execution loop. */ -export function setImmediate(callback: Function, ...args: any): number { +export function setImmediate>( + callback: (...args: TArgs) => unknown, + ...args: TArgs +): number { if (arguments.length < 1) { throw new TypeError( 'setImmediate must be called with at least one argument (a function to call)', @@ -41,7 +44,6 @@ export function setImmediate(callback: Function, ...args: any): number { clearedImmediates.delete(id); } - // $FlowFixMe[incompatible-type] global.queueMicrotask(() => { if (!clearedImmediates.has(id)) { callback.apply(undefined, args); diff --git a/packages/react-native/Libraries/Core/Timers/queueMicrotask.js b/packages/react-native/Libraries/Core/Timers/queueMicrotask.js index 34741aa1f838..efc8a3da277f 100644 --- a/packages/react-native/Libraries/Core/Timers/queueMicrotask.js +++ b/packages/react-native/Libraries/Core/Timers/queueMicrotask.js @@ -4,13 +4,13 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; -let resolvedPromise; +let resolvedPromise: ?Promise; /** * Polyfill for the microtask queueing API defined by WHATWG HTML spec. @@ -19,7 +19,7 @@ let resolvedPromise; * The method must queue a microtask to invoke @param {function} callback, and * if the callback throws an exception, report the exception. */ -export default function queueMicrotask(callback: Function) { +export default function queueMicrotask(callback: () => unknown) { if (arguments.length < 1) { throw new TypeError( 'queueMicrotask must be called with at least one argument (a function to call)', @@ -30,7 +30,6 @@ export default function queueMicrotask(callback: Function) { } // Try to reuse a lazily allocated resolved promise from closure. - // $FlowFixMe[constant-condition] (resolvedPromise || (resolvedPromise = Promise.resolve())) .then(callback) .catch(error => diff --git a/packages/react-native/Libraries/Core/setUpReactDevTools.js b/packages/react-native/Libraries/Core/setUpReactDevTools.js index 0e5a7aeb6779..f5bc1ccf7bf7 100644 --- a/packages/react-native/Libraries/Core/setUpReactDevTools.js +++ b/packages/react-native/Libraries/Core/setUpReactDevTools.js @@ -4,13 +4,16 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; -import type {Domain} from '../../src/private/devsupport/rndevtools/setUpFuseboxReactDevToolsDispatcher'; +import type { + Domain, + JSONValue, +} from '../../src/private/devsupport/rndevtools/setUpFuseboxReactDevToolsDispatcher'; import type {Spec as NativeReactDevToolsRuntimeSettingsModuleSpec} from '../../src/private/devsupport/rndevtools/specs/NativeReactDevToolsRuntimeSettingsModule'; if (__DEV__) { @@ -35,6 +38,7 @@ if (__DEV__) { const { initialize, connectWithCustomMessagingProtocol, + // $FlowFixMe[untyped-import] } = require('react-devtools-core'); const reactDevToolsSettingsManager = require('../../src/private/devsupport/rndevtools/ReactDevToolsSettingsManager'); @@ -73,7 +77,7 @@ if (__DEV__) { require('../Components/View/ReactNativeStyleAttributes').default; const resolveRNStyle = require('../StyleSheet/flattenStyle').default; - function handleReactDevToolsSettingsUpdate(settings: Object) { + function handleReactDevToolsSettingsUpdate(settings: {[string]: unknown}) { reactDevToolsSettingsManager.setGlobalHookSettings( JSON.stringify(settings), ); @@ -97,13 +101,13 @@ if (__DEV__) { maybeReactDevToolsRuntimeSettingsModuleModule, ); disconnect = connectWithCustomMessagingProtocol({ - onSubscribe: listener => { + onSubscribe: (listener: (message: JSONValue) => void) => { domain.onMessage.addEventListener(listener); }, - onUnsubscribe: listener => { + onUnsubscribe: (listener: (message: JSONValue) => void) => { domain.onMessage.removeEventListener(listener); }, - onMessage: (event, payload) => { + onMessage: (event: string, payload: JSONValue) => { domain.sendMessage({event, payload}); }, nativeStyleEditorValidAttributes: Object.keys(ReactNativeStyleAttributes), diff --git a/packages/react-native/Libraries/Core/setUpReactRefresh.js b/packages/react-native/Libraries/Core/setUpReactRefresh.js index be8844dcf344..7c4a272fd73b 100644 --- a/packages/react-native/Libraries/Core/setUpReactRefresh.js +++ b/packages/react-native/Libraries/Core/setUpReactRefresh.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -18,6 +18,7 @@ if (__DEV__) { } // This needs to run before the renderer initializes. + // $FlowFixMe[untyped-import] const ReactRefreshRuntime = require('react-refresh/runtime'); ReactRefreshRuntime.injectIntoGlobalHook(global); diff --git a/packages/react-native/Libraries/EventEmitter/RCTEventEmitter.js b/packages/react-native/Libraries/EventEmitter/RCTEventEmitter.js index 069caedcb254..3e5bb8e66242 100644 --- a/packages/react-native/Libraries/EventEmitter/RCTEventEmitter.js +++ b/packages/react-native/Libraries/EventEmitter/RCTEventEmitter.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -12,8 +12,22 @@ import registerCallableModule from '../Core/registerCallableModule'; +type EventEmitterModule = { + receiveEvent: ( + rootNodeID: number, + topLevelType: string, + nativeEventParam: unknown, + ) => void, + receiveTouches: ( + eventTopLevelType: string, + touches: Array, + changedIndices: Array, + ) => void, + ... +}; + const RCTEventEmitter = { - register(eventEmitter: any) { + register(eventEmitter: EventEmitterModule) { registerCallableModule('RCTEventEmitter', eventEmitter); }, }; diff --git a/packages/react-native/Libraries/Interaction/PanResponder.js b/packages/react-native/Libraries/Interaction/PanResponder.js index 3c31c1a895c9..fbf0a5d5f0b2 100644 --- a/packages/react-native/Libraries/Interaction/PanResponder.js +++ b/packages/react-native/Libraries/Interaction/PanResponder.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/packages/react-native/Libraries/Lists/FlatList.js b/packages/react-native/Libraries/Lists/FlatList.js index ff4563be2406..6976a324b8dc 100644 --- a/packages/react-native/Libraries/Lists/FlatList.js +++ b/packages/react-native/Libraries/Lists/FlatList.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -78,10 +78,10 @@ type OptionalFlatListProps = { * any of your `renderItem`, Header, Footer, etc. functions depend on anything outside of the * `data` prop, stick it here and treat it immutably. */ - extraData?: any, + extraData?: unknown, /** * `getItemLayout` is an optional optimizations that let us skip measurement of dynamic content if - * you know the height of items a priori. `getItemLayout` is the most efficient, and is easy to + * you know the height of items a priori. * use if you have fixed height items, for example: * * getItemLayout={(data, index) => ( @@ -305,6 +305,7 @@ export type FlatListProps = Readonly<{ * * Also inherits [ScrollView Props](docs/scrollview.html#props), unless it is nested in another FlatList of same orientation. */ +// flowlint-next-line unclear-type:off class FlatList extends React.PureComponent> { /** * Scrolls to the end of the content. May be janky without `getItemLayout` prop. @@ -404,6 +405,7 @@ class FlatList extends React.PureComponent> { } } + // flowlint-next-line unclear-type:off getScrollableNode(): any { if (this._listRef) { return this._listRef.getScrollableNode(); @@ -499,7 +501,7 @@ class FlatList extends React.PureComponent> { 'FlatList does not support custom data formats.', ); if (numColumns > 1) { - invariant(!horizontal, 'numColumns does not support horizontal.'); + invariant(horizontal !== true, 'numColumns does not support horizontal.'); } else { invariant( !columnWrapperStyle, @@ -611,11 +613,13 @@ class FlatList extends React.PureComponent> { } _renderer = ( - ListItemComponent: ?(React.ComponentType | React.MixedElement), + ListItemComponent: ?( + React.ComponentType> | React.MixedElement + ), renderItem: ?ListRenderItem, columnWrapperStyle: ?ViewStyleProp, numColumns: ?number, - extraData: ?any, + extraData: ?unknown, // $FlowFixMe[missing-local-annot] ) => { const cols = numColumnsOrDefault(numColumns); diff --git a/packages/react-native/Libraries/Lists/SectionList.js b/packages/react-native/Libraries/Lists/SectionList.js index 9aa96b248aaa..bfc00d9be648 100644 --- a/packages/react-native/Libraries/Lists/SectionList.js +++ b/packages/react-native/Libraries/Lists/SectionList.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -26,6 +26,7 @@ import * as React from 'react'; const VirtualizedSectionList = VirtualizedLists.VirtualizedSectionList; type DefaultSectionT = { + // flowlint-next-line unclear-type:off [key: string]: any, }; @@ -74,7 +75,7 @@ type OptionalSectionListProps = { * any of your `renderItem`, Header, Footer, etc. functions depend on anything outside of the * `data` prop, stick it here and treat it immutably. */ - extraData?: any, + extraData?: unknown, /** * How many items to render in the initial batch. This should be enough to fill the screen but not * much more. Note these items will never be unmounted as part of the windowed rendering in order @@ -172,6 +173,7 @@ export type SectionListProps = { * @see https://reactnative.dev/docs/sectionlist */ export default class SectionList< + // flowlint-next-line unclear-type:off ItemT = any, SectionT = DefaultSectionT, > extends React.PureComponent> { @@ -226,6 +228,7 @@ export default class SectionList< /** * Provides a handle to the underlying scroll node. */ + // flowlint-next-line unclear-type:off getScrollableNode(): any { const listRef = this._wrapperListRef && this._wrapperListRef.getListRef(); if (listRef) { @@ -233,6 +236,7 @@ export default class SectionList< } } + // flowlint-next-line unclear-type:off setNativeProps(props: Object) { const listRef = this._wrapperListRef && this._wrapperListRef.getListRef(); if (listRef) { diff --git a/packages/react-native/Libraries/Lists/SectionListModern.js b/packages/react-native/Libraries/Lists/SectionListModern.js index 2661a31bc326..9ec7d56002c2 100644 --- a/packages/react-native/Libraries/Lists/SectionListModern.js +++ b/packages/react-native/Libraries/Lists/SectionListModern.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -26,6 +26,7 @@ import {useImperativeHandle, useRef} from 'react'; const VirtualizedSectionList = VirtualizedLists.VirtualizedSectionList; type DefaultSectionT = { + // flowlint-next-line unclear-type:off [key: string]: any, }; @@ -60,6 +61,7 @@ type OptionalProps = { separators: { highlight: () => void, unhighlight: () => void, + // flowlint-next-line unclear-type:off updateProps: (select: 'leading' | 'trailing', newProps: Object) => void, ... }, @@ -70,6 +72,7 @@ type OptionalProps = { * any of your `renderItem`, Header, Footer, etc. functions depend on anything outside of the * `data` prop, stick it here and treat it immutably. */ + // flowlint-next-line unclear-type:off extraData?: any, /** * How many items to render in the initial batch. This should be enough to fill the screen but not @@ -110,6 +113,9 @@ export type Props = Readonly<{ ...OptionalProps, }>; +// flowlint-next-line unclear-type:off +type SectionListComponentProps = Props; + /** * A performant interface for rendering sectioned lists, supporting the most handy features: * @@ -166,14 +172,16 @@ export type Props = Readonly<{ * */ const SectionList: component( + // flowlint-next-line unclear-type:off ref?: React.RefSetter, - ...Props + ...SectionListComponentProps ) = ({ ref, ...props }: { + // flowlint-next-line unclear-type:off ref?: React.RefSetter, - ...Props, + ...SectionListComponentProps, }) => { const propsWithDefaults = { stickySectionHeadersEnabled: Platform.OS === 'ios', @@ -224,11 +232,12 @@ const SectionList: component( wrapperRef.current?.getListRef()?.getScrollResponder(); }, + // flowlint-next-line unclear-type:off getScrollableNode(): any { wrapperRef.current?.getListRef()?.getScrollableNode(); }, - setNativeProps(nativeProps: Object) { + setNativeProps(nativeProps: {[string]: unknown}) { wrapperRef.current?.getListRef()?.setNativeProps(nativeProps); }, }), diff --git a/packages/react-native/Libraries/Lists/__flowtests__/SectionList-flowtest.js b/packages/react-native/Libraries/Lists/__flowtests__/SectionList-flowtest.js index 9f5a7efd2000..769e0da32376 100644 --- a/packages/react-native/Libraries/Lists/__flowtests__/SectionList-flowtest.js +++ b/packages/react-native/Libraries/Lists/__flowtests__/SectionList-flowtest.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -22,7 +22,7 @@ function renderMyListItem(info: { const renderMyHeader = ({ section, }: { - section: {fooNumber: number, ...} & Object, + section: {fooNumber: number, ...}, ... }) => ; diff --git a/packages/react-native/Libraries/LogBox/UI/AnsiHighlight.js b/packages/react-native/Libraries/LogBox/UI/AnsiHighlight.js index 8871f67c6bb0..26f25b6b8578 100644 --- a/packages/react-native/Libraries/LogBox/UI/AnsiHighlight.js +++ b/packages/react-native/Libraries/LogBox/UI/AnsiHighlight.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -13,6 +13,7 @@ import type {TextStyleProp} from '../../StyleSheet/StyleSheet'; import View from '../../Components/View/View'; import StyleSheet from '../../StyleSheet/StyleSheet'; import Text from '../../Text/Text'; +// $FlowFixMe[untyped-import] import {ansiToJson} from 'anser'; import * as React from 'react'; diff --git a/packages/react-native/Libraries/Network/FormData.js b/packages/react-native/Libraries/Network/FormData.js index 3e7b02e669dc..551a1eca57f9 100644 --- a/packages/react-native/Libraries/Network/FormData.js +++ b/packages/react-native/Libraries/Network/FormData.js @@ -14,7 +14,7 @@ type FormDataValue = string | {name?: string, type?: string, uri: string}; type FormDataNameValuePair = [string, FormDataValue]; type Headers = {[name: string]: string, ...}; -type FormDataPart = +export type FormDataPart = | { string: string, headers: Headers, diff --git a/packages/react-native/Libraries/Network/RCTNetworking.android.js b/packages/react-native/Libraries/Network/RCTNetworking.android.js index c79b584a4d3c..846467f19ab4 100644 --- a/packages/react-native/Libraries/Network/RCTNetworking.android.js +++ b/packages/react-native/Libraries/Network/RCTNetworking.android.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -21,10 +21,11 @@ import convertRequestBody from './convertRequestBody'; import NativeNetworkingAndroid from './NativeNetworkingAndroid'; type Header = [string, string]; +type HeadersMap = {[string]: string}; // Convert FormData headers to arrays, which are easier to consume in // native on Android. -function convertHeadersMapToArray(headers: Object): Array
{ +function convertHeadersMapToArray(headers: HeadersMap): Array
{ const headerArray: Array
= []; for (const name in headers) { headerArray.push([name, headers[name]]); @@ -37,7 +38,7 @@ function generateRequestId(): number { return _requestId++; } -const emitter = new NativeEventEmitter<$FlowFixMe>( +const emitter = new NativeEventEmitter( // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior // If you want to use the native module on other platforms, please remove this condition and test its behavior Platform.OS !== 'ios' ? null : NativeNetworkingAndroid, @@ -53,7 +54,6 @@ const RCTNetworking = { listener: (...RCTNetworkingEventDefinitions[K]) => unknown, context?: unknown, ): EventSubscription { - // $FlowFixMe[incompatible-type] return emitter.addListener(eventType, listener, context); }, @@ -61,8 +61,8 @@ const RCTNetworking = { method: string, trackingName: string | void, url: string, - headers: Object, - data: RequestBody, + headers: HeadersMap, + data: ?RequestBody, responseType: NativeResponseType, incrementalUpdates: boolean, timeout: number, @@ -70,12 +70,17 @@ const RCTNetworking = { withCredentials: boolean, ) { const body = convertRequestBody(data); - if (body && body.formData) { - body.formData = body.formData.map(part => ({ - ...part, - headers: convertHeadersMapToArray(part.headers), - })); - } + const formData = body.formData; + const nativeRequestBody = + formData != null + ? { + ...body, + formData: formData.map(part => ({ + ...part, + headers: convertHeadersMapToArray(part.headers), + })), + } + : body; const requestId = generateRequestId(); const devToolsRequestId = global.__NETWORK_REPORTER__?.createDevToolsRequestId(); @@ -84,7 +89,7 @@ const RCTNetworking = { url, requestId, convertHeadersMapToArray(headers), - {...body, trackingName, devToolsRequestId}, + {...nativeRequestBody, trackingName, devToolsRequestId}, responseType, incrementalUpdates, timeout, diff --git a/packages/react-native/Libraries/Network/RCTNetworking.ios.js b/packages/react-native/Libraries/Network/RCTNetworking.ios.js index a97c96dec1f9..79bb13c8e2c2 100644 --- a/packages/react-native/Libraries/Network/RCTNetworking.ios.js +++ b/packages/react-native/Libraries/Network/RCTNetworking.ios.js @@ -32,7 +32,7 @@ const RCTNetworking = { trackingName: string | void, url: string, headers: {...}, - data: RequestBody, + data: ?RequestBody, responseType: NativeResponseType, incrementalUpdates: boolean, timeout: number, diff --git a/packages/react-native/Libraries/Network/RCTNetworking.js.flow b/packages/react-native/Libraries/Network/RCTNetworking.js.flow index c1802972b4ea..d3dccfbe5006 100644 --- a/packages/react-native/Libraries/Network/RCTNetworking.js.flow +++ b/packages/react-native/Libraries/Network/RCTNetworking.js.flow @@ -27,8 +27,8 @@ declare const RCTNetworking: interface { method: string, trackingName: string | void, url: string, - headers: {...}, - data: RequestBody, + headers: {[string]: string}, + data: ?RequestBody, responseType: NativeResponseType, incrementalUpdates: boolean, timeout: number, diff --git a/packages/react-native/Libraries/Network/XMLHttpRequest.js b/packages/react-native/Libraries/Network/XMLHttpRequest.js index 7edb4c2a24c5..e60bf98d96d1 100644 --- a/packages/react-native/Libraries/Network/XMLHttpRequest.js +++ b/packages/react-native/Libraries/Network/XMLHttpRequest.js @@ -4,16 +4,19 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ +// flowlint unsafe-getters-setters:off + 'use strict'; import type { EventCallback, EventListener, } from '../../src/private/webapis/dom/events/EventTarget'; +import type {RequestBody} from './convertRequestBody'; import Event from '../../src/private/webapis/dom/events/Event'; import { @@ -30,20 +33,25 @@ const RCTNetworking = require('./RCTNetworking').default; const base64 = require('base64-js'); const invariant = require('invariant'); -const DEBUG_NETWORK_SEND_DELAY: false = false; // Set to a number of milliseconds when debugging +const DEBUG_NETWORK_SEND_DELAY: number = 0; // Set to a number of milliseconds when debugging export type NativeResponseType = 'base64' | 'blob' | 'text'; export type ResponseType = '' | 'arraybuffer' | 'blob' | 'document' | 'json' | 'text'; -export type Response = ?Object | string; +export type Response = unknown; type XHRInterceptor = interface { - requestSent(id: number, url: string, method: string, headers: Object): void, + requestSent( + id: number, + url: string, + method: string, + headers: {[string]: string}, + ): void, responseReceived( id: number, url: string, status: number, - headers: Object, + headers: {[string]: string}, ): void, dataReceived(id: number, data: string): void, loadingFinished(id: number, encodedDataLength: number): void, @@ -145,7 +153,7 @@ class XMLHttpRequest extends EventTarget { DONE: number = DONE; readyState: number = UNSENT; - responseHeaders: ?Object; + responseHeaders: ?{[string]: string}; status: number = 0; timeout: number = 0; responseURL: ?string; @@ -159,8 +167,8 @@ class XMLHttpRequest extends EventTarget { _aborted: boolean = false; _cachedResponse: Response; _hasError: boolean = false; - _headers: Object; - _lowerCaseResponseHeaders: Object; + _headers: {[string]: string}; + _lowerCaseResponseHeaders: {[string]: string}; _method: ?string = null; _perfKey: ?string = null; _responseType: ResponseType; @@ -305,8 +313,8 @@ class XMLHttpRequest extends EventTarget { XMLHttpRequest._interceptor && XMLHttpRequest._interceptor.requestSent( requestId, - this._url || '', - this._method || 'GET', + this._url ?? '', + this._method != null && this._method !== '' ? this._method : 'GET', this._headers, ); } @@ -332,7 +340,7 @@ class XMLHttpRequest extends EventTarget { __didReceiveResponse( requestId: number, status: number, - responseHeaders: ?Object, + responseHeaders: ?{[string]: string}, responseURL: ?string, ): void { if (requestId === this._requestId) { @@ -343,7 +351,7 @@ class XMLHttpRequest extends EventTarget { this.status = status; this.setResponseHeaders(responseHeaders); this.setReadyState(this.HEADERS_RECEIVED); - if (responseURL || responseURL === '') { + if (responseURL != null) { this.responseURL = responseURL; } else { delete this.responseURL; @@ -352,7 +360,9 @@ class XMLHttpRequest extends EventTarget { XMLHttpRequest._interceptor && XMLHttpRequest._interceptor.responseReceived( requestId, - responseURL || this._url || '', + responseURL != null && responseURL !== '' + ? responseURL + : (this._url ?? ''), status, responseHeaders || {}, ); @@ -509,7 +519,7 @@ class XMLHttpRequest extends EventTarget { return value !== undefined ? value : null; } - setRequestHeader(header: string, value: any): void { + setRequestHeader(header: string, value: string): void { if (this.readyState !== this.OPENED) { throw new Error('Request has not been opened'); } @@ -543,7 +553,7 @@ class XMLHttpRequest extends EventTarget { if (this.readyState !== this.UNSENT) { throw new Error('Cannot open, already sending'); } - if (async !== undefined && !async) { + if (async !== undefined && async !== true) { // async is default throw new Error('Synchronous http requests are not supported'); } @@ -556,7 +566,7 @@ class XMLHttpRequest extends EventTarget { this.setReadyState(this.OPENED); } - send(data: any): void { + send(data: ?RequestBody): void { if (this.readyState !== this.OPENED) { throw new Error('Request has not been opened'); } @@ -614,12 +624,12 @@ class XMLHttpRequest extends EventTarget { performanceLogger.startTimespan(this._perfKey); } invariant( - this._method, + this._method != null && this._method !== '', 'XMLHttpRequest method needs to be defined (%s).', friendlyName, ); invariant( - this._url, + this._url != null && this._url !== '', 'XMLHttpRequest URL needs to be defined (%s).', friendlyName, ); @@ -632,13 +642,10 @@ class XMLHttpRequest extends EventTarget { nativeResponseType, incrementalEvents, this.timeout, - // $FlowFixMe[method-unbinding] added when improving typing for this parameters - this.__didCreateRequest.bind(this), + (requestId: number) => this.__didCreateRequest(requestId), this.withCredentials, ); }; - /* $FlowFixMe[constant-condition] Error discovered during Constant - * Condition roll out. See https://fburl.com/workplace/1v97vimq. */ if (DEBUG_NETWORK_SEND_DELAY) { setTimeout(doSend, DEBUG_NETWORK_SEND_DELAY); } else { @@ -648,7 +655,7 @@ class XMLHttpRequest extends EventTarget { abort(): void { this._aborted = true; - if (this._requestId) { + if (this._requestId != null) { RCTNetworking.abortRequest(this._requestId); } // only call onreadystatechange if there is something to abort, @@ -665,13 +672,12 @@ class XMLHttpRequest extends EventTarget { this._reset(); } - setResponseHeaders(responseHeaders: ?Object): void { + setResponseHeaders(responseHeaders: ?{[string]: string}): void { this.responseHeaders = responseHeaders || null; - const headers = responseHeaders || {}; + const headers: {[string]: string} = responseHeaders || {}; this._lowerCaseResponseHeaders = Object.keys(headers).reduce<{ - [string]: any, + [string]: string, }>((lcaseHeaders, headerName) => { - // $FlowFixMe[invalid-computed-prop] lcaseHeaders[headerName.toLowerCase()] = headers[headerName]; return lcaseHeaders; }, {}); diff --git a/packages/react-native/Libraries/Network/convertRequestBody.js b/packages/react-native/Libraries/Network/convertRequestBody.js index caf79174078d..91ac9d944eea 100644 --- a/packages/react-native/Libraries/Network/convertRequestBody.js +++ b/packages/react-native/Libraries/Network/convertRequestBody.js @@ -4,13 +4,15 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; import typeof BlobT from '../Blob/Blob'; +import type {BlobData} from '../Blob/BlobTypes'; +import type {FormDataPart} from './FormData'; import typeof FormDataT from './FormData'; const Blob: BlobT = require('../Blob/Blob').default; @@ -25,7 +27,16 @@ export type RequestBody = | ArrayBuffer | $ArrayBufferView; -function convertRequestBody(body: RequestBody): Object { +type RequestBodyResult = Readonly<{ + string?: string, + blob?: BlobData, + formData?: Array, + base64?: string, + uri?: string, + ... +}>; + +function convertRequestBody(body: ?RequestBody): RequestBodyResult { if (typeof body === 'string') { return {string: body}; } @@ -35,12 +46,15 @@ function convertRequestBody(body: RequestBody): Object { if (body instanceof FormData) { return {formData: body.getParts()}; } + if (body == null) { + return {}; + } if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) { /* $FlowFixMe[incompatible-type] : no way to assert that 'body' is indeed * an ArrayBufferView */ return {base64: binaryToBase64(body)}; } - return body; + return {...body}; } export default convertRequestBody; diff --git a/packages/react-native/Libraries/PushNotificationIOS/PushNotificationIOS.js b/packages/react-native/Libraries/PushNotificationIOS/PushNotificationIOS.js index a8a6774614bd..7de529ce4f8b 100644 --- a/packages/react-native/Libraries/PushNotificationIOS/PushNotificationIOS.js +++ b/packages/react-native/Libraries/PushNotificationIOS/PushNotificationIOS.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -28,6 +28,7 @@ type PresentLocalNotificationDetails = { alertTitle?: string, soundName?: string, category?: string, + // $FlowFixMe[unclear-type] userInfo?: Object, applicationIconBadgeNumber?: number, fireDate?: number, @@ -122,6 +123,7 @@ export interface PushNotification { /** * An alias for `getAlert` to get the notification's main message string */ + // $FlowFixMe[unclear-type] getMessage(): ?string | ?Object; /** @@ -137,6 +139,7 @@ export interface PushNotification { /** * Gets the notification's main message from the `aps` object */ + // $FlowFixMe[unclear-type] getAlert(): ?string | ?Object; /** @@ -152,6 +155,7 @@ export interface PushNotification { /** * Gets the data object on the notif */ + // $FlowFixMe[unclear-type] getData(): ?Object; /** @@ -174,7 +178,9 @@ export interface PushNotification { * @deprecated Use [@react-native-community/push-notification-ios](https://www.npmjs.com/package/@react-native-community/push-notification-ios) instead */ class PushNotificationIOS { + // $FlowFixMe[unclear-type] _data: Object; + // $FlowFixMe[unclear-type] _alert: string | Object; _sound: string; _category: string; @@ -276,6 +282,7 @@ class PushNotificationIOS { * See https://reactnative.dev/docs/pushnotificationios#getdeliverednotifications */ static getDeliveredNotifications( + // $FlowFixMe[unclear-type] callback: (notifications: Array) => void, ): void { invariant( @@ -316,6 +323,7 @@ class PushNotificationIOS { * * See https://reactnative.dev/docs/pushnotificationios#getapplicationiconbadgenumber */ + // $FlowFixMe[unclear-type] static getApplicationIconBadgeNumber(callback: Function): void { invariant( NativePushNotificationManagerIOS, @@ -330,6 +338,7 @@ class PushNotificationIOS { * * See https://reactnative.dev/docs/pushnotificationios#cancellocalnotification */ + // $FlowFixMe[unclear-type] static cancelLocalNotifications(userInfo: Object): void { invariant( NativePushNotificationManagerIOS, @@ -343,6 +352,7 @@ class PushNotificationIOS { * * See https://reactnative.dev/docs/pushnotificationios#getscheduledlocalnotifications */ + // $FlowFixMe[unclear-type] static getScheduledLocalNotifications(callback: Function): void { invariant( NativePushNotificationManagerIOS, @@ -359,6 +369,7 @@ class PushNotificationIOS { */ static addEventListener( type: PushNotificationEventName, + // $FlowFixMe[unclear-type] handler: Function, ): void { invariant( @@ -539,6 +550,7 @@ class PushNotificationIOS { * `getInitialNotification` is sufficient. * */ + // $FlowFixMe[unclear-type] constructor(nativeNotif: Object) { this._data = {}; this._remoteNotificationCompleteCallbackCalled = false; @@ -603,6 +615,7 @@ class PushNotificationIOS { /** * An alias for `getAlert` to get the notification's main message string. */ + // $FlowFixMe[unclear-type] getMessage(): ?string | ?Object { // alias because "alert" is an ambiguous name return this._alert; @@ -633,6 +646,7 @@ class PushNotificationIOS { * * See https://reactnative.dev/docs/pushnotificationios#getalert */ + // $FlowFixMe[unclear-type] getAlert(): ?string | ?Object { return this._alert; } @@ -660,6 +674,7 @@ class PushNotificationIOS { * * See https://reactnative.dev/docs/pushnotificationios#getdata */ + // $FlowFixMe[unclear-type] getData(): ?Object { return this._data; } diff --git a/packages/react-native/Libraries/ReactNative/AppContainer.js b/packages/react-native/Libraries/ReactNative/AppContainer.js index a9e6fff6541e..9c26edfd1e65 100644 --- a/packages/react-native/Libraries/ReactNative/AppContainer.js +++ b/packages/react-native/Libraries/ReactNative/AppContainer.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -17,6 +17,7 @@ export type Props = Readonly<{ children?: React.Node, rootTag: number | RootTag, initialProps?: {...}, + // $FlowFixMe[unclear-type] WrapperComponent?: ?React.ComponentType, rootViewStyle?: ?ViewStyleProp, internal_excludeLogBox?: boolean, diff --git a/packages/react-native/Libraries/ReactNative/AppRegistry.flow.js b/packages/react-native/Libraries/ReactNative/AppRegistry.flow.js index 94de6edde6ec..f1f5e0b58b75 100644 --- a/packages/react-native/Libraries/ReactNative/AppRegistry.flow.js +++ b/packages/react-native/Libraries/ReactNative/AppRegistry.flow.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -13,13 +13,16 @@ import type {RootTag} from '../Types/RootTagTypes'; import type {DisplayModeType} from './DisplayMode'; import type {IPerformanceLogger} from './IPerformanceLogger.flow'; +// $FlowFixMe[unclear-type] type HeadlessTask = (taskData: any) => Promise; export type TaskProvider = () => HeadlessTask; +// $FlowFixMe[unclear-type] export type ComponentProvider = () => React.ComponentType; export type ComponentProviderInstrumentationHook = ( component_: ComponentProvider, scopedPerformanceLogger: IPerformanceLogger, + // $FlowFixMe[unclear-type] ) => React.ComponentType; export type AppConfig = { appKey: string, @@ -43,7 +46,10 @@ export type Registry = { ... }; export type WrapperComponentProvider = ( + // $FlowFixMe[unclear-type] appParameters: Object, appKey?: string, + // $FlowFixMe[unclear-type] ) => React.ComponentType; +// $FlowFixMe[unclear-type] export type RootViewStyleProvider = (appParameters: Object) => ViewStyleProp; diff --git a/packages/react-native/Libraries/ReactNative/AppRegistry.js b/packages/react-native/Libraries/ReactNative/AppRegistry.js index 036749c3514a..20e2168f0d62 100644 --- a/packages/react-native/Libraries/ReactNative/AppRegistry.js +++ b/packages/react-native/Libraries/ReactNative/AppRegistry.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/packages/react-native/Libraries/ReactNative/AppRegistry.js.flow b/packages/react-native/Libraries/ReactNative/AppRegistry.js.flow index aa5c650107ac..792f2c87e562 100644 --- a/packages/react-native/Libraries/ReactNative/AppRegistry.js.flow +++ b/packages/react-native/Libraries/ReactNative/AppRegistry.js.flow @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/packages/react-native/Libraries/ReactNative/AppRegistryImpl.js b/packages/react-native/Libraries/ReactNative/AppRegistryImpl.js index 33e0c84f3ba1..3166cbd5678d 100644 --- a/packages/react-native/Libraries/ReactNative/AppRegistryImpl.js +++ b/packages/react-native/Libraries/ReactNative/AppRegistryImpl.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -113,7 +113,7 @@ export function registerComponent( displayMode, }); }; - if (section) { + if (section === true) { sections[appKey] = runnables[appKey]; } return appKey; @@ -220,7 +220,7 @@ export function runApplication( */ export function setSurfaceProps( appKey: string, - appParameters: Object, + appParameters: AppParameters, displayMode?: number, ): void { if (appKey !== 'LogBox') { @@ -264,7 +264,6 @@ export function registerHeadlessTask( taskKey: string, taskProvider: TaskProvider, ): void { - // $FlowFixMe[object-this-reference] registerCancellableHeadlessTask(taskKey, taskProvider, () => () => { /* Cancel is no-op */ }); @@ -300,7 +299,7 @@ export function registerCancellableHeadlessTask( export function startHeadlessTask( taskId: number, taskKey: string, - data: any, + data: unknown, ): void { const NativeHeadlessJsTaskSupport = require('./NativeHeadlessJsTaskSupport').default; @@ -326,8 +325,7 @@ export function startHeadlessTask( NativeHeadlessJsTaskSupport && reason instanceof HeadlessJsTaskError ) { - // $FlowFixMe[unused-promise] - NativeHeadlessJsTaskSupport.notifyTaskRetry(taskId).then( + void NativeHeadlessJsTaskSupport.notifyTaskRetry(taskId).then( retryPosted => { if (!retryPosted) { NativeHeadlessJsTaskSupport.notifyTaskFinished(taskId); diff --git a/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js b/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js index 0db6d3415496..4ef402b626b3 100644 --- a/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js +++ b/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -12,27 +12,35 @@ import type {RootTag} from '../Types/RootTagTypes'; import type {UIManagerJSInterface} from '../Types/UIManagerJSInterface'; +import type {UIManagerConstants, ViewManagerConfig} from './NativeUIManager'; +import ReactNativeElement from '../../src/private/webapis/dom/nodes/ReactNativeElement'; import {unstable_hasComponent} from '../NativeComponent/NativeComponentRegistryUnstable'; import defineLazyObjectProperty from '../Utilities/defineLazyObjectProperty'; import Platform from '../Utilities/Platform'; import {getFabricUIManager} from './FabricUIManager'; +import {getNativeTagFromPublicInstance} from './ReactFabricPublicInstance/ReactFabricPublicInstance'; +import { + getNodeFromInternalInstanceHandle, + getPublicInstanceFromInternalInstanceHandle, +} from './RendererImplementation'; import nullthrows from 'nullthrows'; function raiseSoftError(methodName: string, details?: string): void { console.error( `[ReactNative Architecture][JS] '${methodName}' is not available in the new React Native architecture.` + - (details ? ` ${details}` : ''), + (details != null && details !== '' ? ` ${details}` : ''), ); } -const getUIManagerConstants: ?() => {[viewManagerName: string]: Object} = - global.RN$LegacyInterop_UIManager_getConstants; +const getUIManagerConstants: ?() => { + [viewManagerName: string]: ViewManagerConfig, +} = global.RN$LegacyInterop_UIManager_getConstants; const getUIManagerConstantsCached = (function () { let wasCalledOnce = false; - let result: {[viewManagerName: string]: Object} = {}; - return (): {[viewManagerName: string]: Object} => { + let result: {[viewManagerName: string]: ViewManagerConfig} = {}; + return (): {[viewManagerName: string]: ViewManagerConfig} => { if (!wasCalledOnce) { result = nullthrows(getUIManagerConstants)(); wasCalledOnce = true; @@ -41,16 +49,18 @@ const getUIManagerConstantsCached = (function () { }; })(); -const getConstantsForViewManager: ?(viewManagerName: string) => ?Object = +const getConstantsForViewManager: ?( + viewManagerName: string, +) => ?ViewManagerConfig = global.RN$LegacyInterop_UIManager_getConstantsForViewManager; -const getDefaultEventTypes: ?() => Object = +const getDefaultEventTypes: ?() => ViewManagerConfig = global.RN$LegacyInterop_UIManager_getDefaultEventTypes; const getDefaultEventTypesCached = (function () { let wasCalledOnce = false; let result = null; - return (): Object => { + return (): ViewManagerConfig => { if (!wasCalledOnce) { result = nullthrows(getDefaultEventTypes)(); wasCalledOnce = true; @@ -63,7 +73,13 @@ const getDefaultEventTypesCached = (function () { * UIManager.js overrides these APIs. * Pull them out from the BridgelessUIManager implementation. So, we can ignore them. */ -const UIManagerJSOverridenAPIs = { +const UIManagerJSOverridenAPIs: { + measure: UIManagerJSInterface['measure'], + measureInWindow: UIManagerJSInterface['measureInWindow'], + measureLayout: UIManagerJSInterface['measureLayout'], + measureLayoutRelativeToParent: UIManagerJSInterface['measureLayoutRelativeToParent'], + dispatchViewManagerCommand: UIManagerJSInterface['dispatchViewManagerCommand'], +} = { measure: ( reactTag: number, callback: ( @@ -86,7 +102,7 @@ const UIManagerJSOverridenAPIs = { measureLayout: ( reactTag: number, ancestorReactTag: number, - errorCallback: (error: Object) => void, + errorCallback, callback: ( left: number, top: number, @@ -98,7 +114,7 @@ const UIManagerJSOverridenAPIs = { }, measureLayoutRelativeToParent: ( reactTag: number, - errorCallback: (error: Object) => void, + errorCallback, callback: ( left: number, top: number, @@ -111,7 +127,7 @@ const UIManagerJSOverridenAPIs = { dispatchViewManagerCommand: ( reactTag: number, commandID: number, - commandArgs: ?Array, + commandArgs, ): void => { raiseSoftError('dispatchViewManagerCommand'); }, @@ -122,16 +138,23 @@ const UIManagerJSOverridenAPIs = { * In OSS, the New Architecture will just use the Fabric renderer, which uses * different APIs. */ -const UIManagerJSUnusedInNewArchAPIs = { +const UIManagerJSUnusedInNewArchAPIs: { + createView: UIManagerJSInterface['createView'], + updateView: UIManagerJSInterface['updateView'], + setChildren: UIManagerJSInterface['setChildren'], + manageChildren: UIManagerJSInterface['manageChildren'], + setJSResponder: UIManagerJSInterface['setJSResponder'], + clearJSResponder: UIManagerJSInterface['clearJSResponder'], +} = { createView: ( reactTag: number, viewName: string, rootTag: RootTag, - props: Object, + props, ): void => { raiseSoftError('createView'); }, - updateView: (reactTag: number, viewName: string, props: Object): void => { + updateView: (reactTag: number, viewName: string, props): void => { raiseSoftError('updateView'); }, setChildren: (containerTag: number, reactTags: Array): void => { @@ -165,7 +188,9 @@ const UIManagerJSDeprecatedPlatformAPIs = Platform.select({ const UIManagerJSPlatformAPIs = Platform.select({ android: { - getConstantsForViewManager: (viewManagerName: string): ?Object => { + getConstantsForViewManager: ( + viewManagerName: string, + ): ?ViewManagerConfig => { if (getConstantsForViewManager) { return getConstantsForViewManager(viewManagerName); } @@ -217,7 +242,7 @@ const UIManagerJSPlatformAPIs = Platform.select({ const FabricUIManager = nullthrows(getFabricUIManager()); const shadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); - if (!shadowNode) { + if (shadowNode == null) { console.error( `sendAccessibilityEvent() dropping event: Cannot find view with tag #${reactTag}`, ); @@ -233,7 +258,7 @@ const UIManagerJSPlatformAPIs = Platform.select({ * * Leave this unimplemented until we implement lazy loading of legacy modules and view managers in the new architecture. */ - lazilyLoadView: (name: string): Object => { + lazilyLoadView: (name: string): ViewManagerConfig => { raiseSoftError('lazilyLoadView'); return {}; }, @@ -241,7 +266,7 @@ const UIManagerJSPlatformAPIs = Platform.select({ const FabricUIManager = nullthrows(getFabricUIManager()); const shadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); - if (!shadowNode) { + if (shadowNode == null) { console.error(`focus() noop: Cannot find view with tag #${reactTag}`); return; } @@ -251,7 +276,7 @@ const UIManagerJSPlatformAPIs = Platform.select({ const FabricUIManager = nullthrows(getFabricUIManager()); const shadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); - if (!shadowNode) { + if (shadowNode == null) { console.error(`blur() noop: Cannot find view with tag #${reactTag}`); return; } @@ -260,12 +285,12 @@ const UIManagerJSPlatformAPIs = Platform.select({ }, }); -const UIManagerJS: UIManagerJSInterface & {[string]: any} = { +const UIManagerJS: UIManagerJSInterface & {[string]: ViewManagerConfig} = { ...UIManagerJSOverridenAPIs, ...UIManagerJSDeprecatedPlatformAPIs, ...UIManagerJSPlatformAPIs, ...UIManagerJSUnusedInNewArchAPIs, - getViewManagerConfig: (viewManagerName: string): unknown => { + getViewManagerConfig: (viewManagerName: string): ViewManagerConfig => { if (getUIManagerConstants) { const constants = getUIManagerConstantsCached(); if ( @@ -287,7 +312,7 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { hasViewManagerConfig: (viewManagerName: string): boolean => { return unstable_hasComponent(viewManagerName); }, - getConstants: (): Object => { + getConstants: (): UIManagerConstants => { if (getUIManagerConstants) { return getUIManagerConstantsCached(); } else { @@ -309,7 +334,7 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { const FabricUIManager = nullthrows(getFabricUIManager()); const shadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); - if (!shadowNode) { + if (shadowNode == null) { console.error( `findSubviewIn() noop: Cannot find view with reactTag ${reactTag}`, ); @@ -326,16 +351,21 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { return; } - let instanceHandle: Object = internalInstanceHandle; - let node = instanceHandle.stateNode.node; + const node = getNodeFromInternalInstanceHandle(internalInstanceHandle); + if (node == null) { + console.error('findSubviewIn(): Cannot find node at point'); + return; + } - if (!node) { + const publicInstance = getPublicInstanceFromInternalInstanceHandle( + internalInstanceHandle, + ); + if (!(publicInstance instanceof ReactNativeElement)) { console.error('findSubviewIn(): Cannot find node at point'); return; } - let nativeViewTag: number = - instanceHandle.stateNode.canonical.nativeTag; + const nativeViewTag = getNativeTagFromPublicInstance(publicInstance); FabricUIManager.measure( node, @@ -353,7 +383,7 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { ): void => { const FabricUIManager = nullthrows(getFabricUIManager()); const shadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); - if (!shadowNode) { + if (shadowNode == null) { console.error( `viewIsDescendantOf() noop: Cannot find view with reactTag ${reactTag}`, ); @@ -362,7 +392,7 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { const ancestorShadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(ancestorReactTag); - if (!ancestorShadowNode) { + if (ancestorShadowNode == null) { console.error( `viewIsDescendantOf() noop: Cannot find view with ancestorReactTag ${ancestorReactTag}`, ); @@ -382,11 +412,7 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { callback([isAncestor]); }, - configureNextLayoutAnimation: ( - config: Object, - callback: () => void, - errorCallback: (error: Object) => void, - ): void => { + configureNextLayoutAnimation: (config, callback, errorCallback): void => { const FabricUIManager = nullthrows(getFabricUIManager()); FabricUIManager.configureNextLayoutAnimation( config, diff --git a/packages/react-native/Libraries/ReactNative/PaperUIManager.js b/packages/react-native/Libraries/ReactNative/PaperUIManager.js index fadf460022fd..151b06fe457c 100644 --- a/packages/react-native/Libraries/ReactNative/PaperUIManager.js +++ b/packages/react-native/Libraries/ReactNative/PaperUIManager.js @@ -4,12 +4,13 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ import type {RootTag} from '../Types/RootTagTypes'; import type {UIManagerJSInterface} from '../Types/UIManagerJSInterface'; +import type {UIManagerConstants, ViewManagerConfig} from './NativeUIManager'; import NativeUIManager from './NativeUIManager'; import nullthrows from 'nullthrows'; @@ -20,13 +21,13 @@ const defineLazyObjectProperty = const Platform = require('../Utilities/Platform').default; const UIManagerProperties = require('./UIManagerProperties').default; -const viewManagerConfigs: {[string]: any | null} = {}; +const viewManagerConfigs: {[string]: ViewManagerConfig | null} = {}; const triedLoadingConfig = new Set(); let NativeUIManagerConstants = {}; let isNativeUIManagerConstantsSet = false; -function getConstants(): Object { +function getConstants(): UIManagerConstants { if (!isNativeUIManagerConstantsSet) { NativeUIManagerConstants = NativeUIManager.getConstants(); isNativeUIManagerConstantsSet = true; @@ -34,7 +35,7 @@ function getConstants(): Object { return NativeUIManagerConstants; } -function getViewManagerConfig(viewManagerName: string): any { +function getViewManagerConfig(viewManagerName: string): ViewManagerConfig { if ( viewManagerConfigs[viewManagerName] === undefined && NativeUIManager.getConstantsForViewManager @@ -86,7 +87,7 @@ const UIManagerJS: UIManagerJSInterface = { reactTag: number, viewName: string, rootTag: RootTag, - props: Object, + props, ): void { if (Platform.OS === 'ios' && viewManagerConfigs[viewName] === undefined) { // This is necessary to force the initialization of native viewManager @@ -96,10 +97,10 @@ const UIManagerJS: UIManagerJSInterface = { NativeUIManager.createView(reactTag, viewName, rootTag, props); }, - getConstants(): Object { + getConstants(): UIManagerConstants { return getConstants(); }, - getViewManagerConfig(viewManagerName: string): any { + getViewManagerConfig(viewManagerName: string): ViewManagerConfig { return getViewManagerConfig(viewManagerName); }, hasViewManagerConfig(viewManagerName: string): boolean { diff --git a/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/ReactNativeAttributePayload.js b/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/ReactNativeAttributePayload.js index 0f1edf031d0f..7d8f1a275fc6 100644 --- a/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/ReactNativeAttributePayload.js +++ b/packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/ReactNativeAttributePayload.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -24,7 +24,7 @@ const emptyObject = {}; * across modules, I've kept them isolated to this module. */ -type NestedNode = Array | Object; +type NestedNode = Array | {[string]: unknown}; // Tracks removed keys let removedKeys: {[string]: boolean} | null = null; @@ -45,7 +45,7 @@ function defaultDiffer(prevProp: unknown, nextProp: unknown): boolean { } function restoreDeletedValuesInNestedArray( - updatePayload: Object, + updatePayload: {[string]: unknown}, node: NestedNode, validAttributes: AttributeConfiguration, ) { @@ -76,11 +76,9 @@ function restoreDeletedValuesInNestedArray( } if (typeof nextProp === 'function') { - // $FlowFixMe[incompatible-type] found when upgrading Flow nextProp = true; } if (typeof nextProp === 'undefined') { - // $FlowFixMe[incompatible-type] found when upgrading Flow nextProp = null; } @@ -106,11 +104,12 @@ function restoreDeletedValuesInNestedArray( } function diffNestedArrayProperty( - updatePayload: null | Object, + updatePayloadInput: null | {[string]: unknown}, prevArray: Array, nextArray: Array, validAttributes: AttributeConfiguration, -): null | Object { +): null | {[string]: unknown} { + let updatePayload = updatePayloadInput; const minLength = prevArray.length < nextArray.length ? prevArray.length : nextArray.length; let i; @@ -144,11 +143,11 @@ function diffNestedArrayProperty( } function diffNestedProperty( - updatePayload: null | Object, + updatePayload: null | {[string]: unknown}, prevProp: NestedNode, nextProp: NestedNode, validAttributes: AttributeConfiguration, -): null | Object { +): null | {[string]: unknown} { if (!updatePayload && prevProp === nextProp) { // If no properties have been added, then we can bail out quickly on object // equality. @@ -183,7 +182,9 @@ function diffNestedProperty( if (Array.isArray(prevProp)) { return diffProperties( updatePayload, + // $FlowFixMe[incompatible-type] flattenStyle is reused to flatten a nested style array here flattenStyle(prevProp), + // $FlowFixMe[incompatible-type] a non-array nested node is a plain props object here nextProp, validAttributes, ); @@ -192,6 +193,7 @@ function diffNestedProperty( return diffProperties( updatePayload, prevProp, + // $FlowFixMe[incompatible-type] flattenStyle is reused to flatten a nested style array here flattenStyle(nextProp), validAttributes, ); @@ -202,10 +204,11 @@ function diffNestedProperty( * adds a null sentinel to the updatePayload, for each prop key. */ function clearNestedProperty( - updatePayload: null | Object, + updatePayloadInput: null | {[string]: unknown}, prevProp: NestedNode, validAttributes: AttributeConfiguration, -): null | Object { +): null | {[string]: unknown} { + let updatePayload = updatePayloadInput; if (!prevProp) { return updatePayload; } @@ -233,14 +236,15 @@ function clearNestedProperty( * anything changed. */ function diffProperties( - updatePayload: null | Object, - prevProps: Object, - nextProps: Object, + updatePayloadInput: null | {[string]: unknown}, + prevProps: {[string]: unknown}, + nextProps: {[string]: unknown}, validAttributes: AttributeConfiguration, -): null | Object { +): null | {[string]: unknown} { + let updatePayload = updatePayloadInput; let attributeConfig; - let nextProp; - let prevProp; + let nextProp: unknown; + let prevProp: unknown; for (const propKey in nextProps) { attributeConfig = validAttributes[propKey]; @@ -258,11 +262,11 @@ function diffProperties( if (!attributeConfigHasProcess) { // functions are converted to booleans as markers that the associated // events should be sent from native. - nextProp = true as any; + nextProp = true; // If nextProp is not a function, then don't bother changing prevProp // since nextProp will win and go into the updatePayload regardless. if (typeof prevProp === 'function') { - prevProp = true as any; + prevProp = true; } } } @@ -270,9 +274,9 @@ function diffProperties( // An explicit value of undefined is treated as a null because it overrides // any other preceding value. if (typeof nextProp === 'undefined') { - nextProp = null as any; + nextProp = null; if (typeof prevProp === 'undefined') { - prevProp = null as any; + prevProp = null; } } @@ -313,7 +317,7 @@ function diffProperties( // case: !Object is the default case if (defaultDiffer(prevProp, nextProp)) { // a normal leaf has changed - (updatePayload || (updatePayload = {} as {[string]: $FlowFixMe}))[ + (updatePayload || (updatePayload = {} as {[string]: unknown}))[ propKey ] = nextProp; } @@ -333,7 +337,7 @@ function diffProperties( ? // $FlowFixMe[incompatible-use] found when upgrading Flow attributeConfig.process(nextProp) : nextProp; - (updatePayload || (updatePayload = {} as {[string]: $FlowFixMe}))[ + (updatePayload || (updatePayload = {} as {[string]: unknown}))[ propKey ] = nextValue; } @@ -345,14 +349,19 @@ function diffProperties( // this point so we assume it must be AttributeConfiguration. updatePayload = diffNestedProperty( updatePayload, + // $FlowFixMe[incompatible-type] prop values are typed `unknown` but are nodes in this nested-config path prevProp, + // $FlowFixMe[incompatible-type] prop values are typed `unknown` but are nodes in this nested-config path nextProp, + // $FlowFixMe[unclear-type] AttributeConfiguration/AnyAttributeType are defined upstream with $FlowFixMe attributeConfig as any as AttributeConfiguration, ); if (removedKeyCount > 0 && updatePayload) { restoreDeletedValuesInNestedArray( updatePayload, + // $FlowFixMe[incompatible-type] prop values are typed `unknown` but are nodes in this nested-config path nextProp, + // $FlowFixMe[unclear-type] AttributeConfiguration/AnyAttributeType are defined upstream with $FlowFixMe attributeConfig as any as AttributeConfiguration, ); removedKeys = null; @@ -389,9 +398,8 @@ function diffProperties( ) { // case: CustomAttributeConfiguration | !Object // Flag the leaf property for removal by sending a sentinel. - (updatePayload || (updatePayload = {} as {[string]: $FlowFixMe}))[ - propKey - ] = null; + (updatePayload || (updatePayload = {} as {[string]: unknown}))[propKey] = + null; if (!removedKeys) { removedKeys = {} as {[string]: boolean}; } @@ -405,7 +413,9 @@ function diffProperties( // were removed so we need to go through and clear out all of them. updatePayload = clearNestedProperty( updatePayload, + // $FlowFixMe[incompatible-type] prop values are typed `unknown` but are nodes in this nested-config path prevProp, + // $FlowFixMe[unclear-type] AttributeConfiguration/AnyAttributeType are defined upstream with $FlowFixMe attributeConfig as any as AttributeConfiguration, ); } @@ -414,10 +424,11 @@ function diffProperties( } function addNestedProperty( - payload: null | Object, - props: Object, + payloadInput: null | {[string]: unknown}, + props: NestedNode, validAttributes: AttributeConfiguration, -): null | Object { +): null | {[string]: unknown} { + let payload = payloadInput; // Flatten nested style props. if (Array.isArray(props)) { for (let i = 0; i < props.length; i++) { @@ -431,6 +442,7 @@ function addNestedProperty( const attributeConfig = validAttributes[ propKey + // $FlowFixMe[unclear-type] AttributeConfiguration/AnyAttributeType are defined upstream with $FlowFixMe ] as any as AttributeConfiguration; if (attributeConfig == null) { @@ -466,13 +478,18 @@ function addNestedProperty( if (newValue !== undefined) { if (!payload) { - payload = {} as {[string]: $FlowFixMe}; + payload = {} as {[string]: unknown}; } payload[propKey] = newValue; continue; } - payload = addNestedProperty(payload, prop, attributeConfig); + payload = addNestedProperty( + payload, + // $FlowFixMe[incompatible-type] prop values are typed `unknown` but are nodes here + prop, + attributeConfig, + ); } return payload; @@ -483,25 +500,25 @@ function addNestedProperty( * to the payload for each valid key. */ function clearProperties( - updatePayload: null | Object, - prevProps: Object, + updatePayload: null | {[string]: unknown}, + prevProps: {[string]: unknown}, validAttributes: AttributeConfiguration, -): null | Object { +): null | {[string]: unknown} { return diffProperties(updatePayload, prevProps, emptyObject, validAttributes); } export function create( - props: Object, + props: NestedNode, validAttributes: AttributeConfiguration, -): null | Object { +): null | {[string]: unknown} { return addNestedProperty(null, props, validAttributes); } export function diff( - prevProps: Object, - nextProps: Object, + prevProps: {[string]: unknown}, + nextProps: {[string]: unknown}, validAttributes: AttributeConfiguration, -): null | Object { +): null | {[string]: unknown} { return diffProperties( null, // updatePayload prevProps, diff --git a/packages/react-native/Libraries/ReactNative/UIManager.js b/packages/react-native/Libraries/ReactNative/UIManager.js index a97c6a7b3ea7..a020393458ab 100644 --- a/packages/react-native/Libraries/ReactNative/UIManager.js +++ b/packages/react-native/Libraries/ReactNative/UIManager.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -60,7 +60,7 @@ const UIManager: UIManagerJSInterface = { const FabricUIManager = nullthrows(getFabricUIManager()); const shadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); - if (shadowNode) { + if (shadowNode != null) { FabricUIManager.measure(shadowNode, callback); } else { console.warn(`measure cannot find view with tag #${reactTag}`); @@ -103,7 +103,7 @@ const UIManager: UIManagerJSInterface = { const FabricUIManager = nullthrows(getFabricUIManager()); const shadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); - if (shadowNode) { + if (shadowNode != null) { FabricUIManager.measureInWindow(shadowNode, callback); } else { console.warn(`measure cannot find view with tag #${reactTag}`); @@ -129,7 +129,7 @@ const UIManager: UIManagerJSInterface = { measureLayout( reactTag: number, ancestorReactTag: number, - errorCallback: (error: Object) => void, + errorCallback, callback: ( left: number, top: number, @@ -144,7 +144,7 @@ const UIManager: UIManagerJSInterface = { const ancestorShadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(ancestorReactTag); - if (!shadowNode || !ancestorShadowNode) { + if (shadowNode == null || ancestorShadowNode == null) { return; } @@ -167,7 +167,7 @@ const UIManager: UIManagerJSInterface = { measureLayoutRelativeToParent( reactTag: number, - errorCallback: (error: Object) => void, + errorCallback, callback: ( left: number, top: number, @@ -182,7 +182,7 @@ const UIManager: UIManagerJSInterface = { const FabricUIManager = nullthrows(getFabricUIManager()); const shadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); - if (shadowNode) { + if (shadowNode != null) { FabricUIManager.measure( shadowNode, (left, top, width, height, pageX, pageY) => { @@ -210,7 +210,7 @@ const UIManager: UIManagerJSInterface = { dispatchViewManagerCommand( reactTag: number, commandName: number | string, - commandArgs: any[], + commandArgs: Array, ) { // Sometimes, libraries directly pass in the output of `findNodeHandle` to // this function without checking if it's null. This guards against that @@ -224,12 +224,16 @@ const UIManager: UIManagerJSInterface = { const FabricUIManager = nullthrows(getFabricUIManager()); const shadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); - if (shadowNode) { + if (shadowNode != null) { // Transform the accidental CommandID into a CommandName which is the stringified number. // The interop layer knows how to convert this number into the right method name. // Stringify a string is a no-op, so it's safe. - commandName = `${commandName}`; - FabricUIManager.dispatchCommand(shadowNode, commandName, commandArgs); + const resolvedCommandName = `${commandName}`; + FabricUIManager.dispatchCommand( + shadowNode, + resolvedCommandName, + commandArgs, + ); } } else { UIManagerImpl.dispatchViewManagerCommand( diff --git a/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js b/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js index 26846a19c551..c684465410c1 100644 --- a/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js +++ b/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js @@ -4,12 +4,14 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; +import type {ViewManagerConfig} from './NativeUIManager'; + import processBoxShadow from '../StyleSheet/processBoxShadow'; const ReactNativeStyleAttributes = @@ -33,7 +35,9 @@ const sizesDiffer = require('../Utilities/differ/sizesDiffer').default; const UIManager = require('./UIManager').default; const nullthrows = require('nullthrows'); -function getNativeComponentAttributes(uiViewClassName: string): any { +function getNativeComponentAttributes( + uiViewClassName: string, +): ViewManagerConfig { const viewConfig = UIManager.getViewManagerConfig(uiViewClassName); if (viewConfig == null) { @@ -109,17 +113,14 @@ function getNativeComponentAttributes(uiViewClassName: string): any { return viewConfig; } -function attachDefaultEventTypes(viewConfig: any) { +function attachDefaultEventTypes(viewConfig: ViewManagerConfig) { // This is supported on UIManager platforms (ex: Android), // as lazy view managers are not implemented for all platforms. // See [UIManager] for details on constants and implementations. const constants = UIManager.getConstants(); if (constants.ViewManagerNames || constants.LazyViewManagersEnabled) { // Lazy view managers enabled. - viewConfig = merge( - viewConfig, - nullthrows(UIManager.getDefaultEventTypes)(), - ); + merge(viewConfig, nullthrows(UIManager.getDefaultEventTypes)()); } else { viewConfig.bubblingEventTypes = merge( viewConfig.bubblingEventTypes, @@ -133,7 +134,10 @@ function attachDefaultEventTypes(viewConfig: any) { } // TODO: Figure out how to avoid all this runtime initialization cost. -function merge(destination: ?Object, source: ?Object): ?Object { +function merge( + destination: ?ViewManagerConfig, + source: ?ViewManagerConfig, +): ?ViewManagerConfig { if (!source) { return destination; } @@ -163,7 +167,12 @@ function merge(destination: ?Object, source: ?Object): ?Object { function getDifferForType( typeName: string, -): ?(prevProp: any, nextProp: any) => boolean { +): ?( + | typeof insetsDiffer + | typeof matricesDiffer + | typeof pointsDiffer + | typeof sizesDiffer +) { switch (typeName) { // iOS Types case 'CATransform3D': @@ -183,7 +192,19 @@ function getDifferForType( return null; } -function getProcessorForType(typeName: string): ?(nextProp: any) => any { +function getProcessorForType( + typeName: string, +): ?( + | typeof processBackgroundImage + | typeof processBackgroundPosition + | typeof processBackgroundRepeat + | typeof processBackgroundSize + | typeof processBoxShadow + | typeof processColor + | typeof processColorArray + | typeof processFilter + | typeof resolveAssetSource +) { switch (typeName) { // iOS Types case 'CGColor': diff --git a/packages/react-native/Libraries/ReactNative/requireNativeComponent.js b/packages/react-native/Libraries/ReactNative/requireNativeComponent.js index 96016159f59d..080380e0e86c 100644 --- a/packages/react-native/Libraries/ReactNative/requireNativeComponent.js +++ b/packages/react-native/Libraries/ReactNative/requireNativeComponent.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -29,8 +29,10 @@ const getNativeComponentAttributes = const requireNativeComponent = ( uiViewClassName: string, ): HostComponent => - createReactNativeComponentClass(uiViewClassName, () => - getNativeComponentAttributes(uiViewClassName), + createReactNativeComponentClass( + uiViewClassName, + () => getNativeComponentAttributes(uiViewClassName), + // $FlowFixMe[unclear-type] createReactNativeComponentClass returns the registered view name (a string) that Fabric resolves to this host component at runtime ) as any as HostComponent; export default requireNativeComponent; diff --git a/packages/react-native/Libraries/Settings/Settings.ios.js b/packages/react-native/Libraries/Settings/Settings.ios.js index 293fa9612cad..f06b80548970 100644 --- a/packages/react-native/Libraries/Settings/Settings.ios.js +++ b/packages/react-native/Libraries/Settings/Settings.ios.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -14,6 +14,7 @@ import invariant from 'invariant'; const subscriptions: Array<{ keys: Array, + // $FlowFixMe[unclear-type] callback: ?Function, ... }> = []; @@ -27,6 +28,7 @@ const subscriptions: Array<{ */ const Settings = { _settings: (NativeSettingsManager && + // $FlowFixMe[unclear-type] NativeSettingsManager.getConstants().settings) as any, /** @@ -41,6 +43,7 @@ const Settings = { * Set one or more values by merging the provided object into the current * settings. */ + // $FlowFixMe[unclear-type] set(settings: Object) { // $FlowFixMe[object-this-reference] // $FlowFixMe[unsafe-object-assign] @@ -53,8 +56,10 @@ const Settings = { * whenever a watched key's value changes. Returns a `watchId` that can be * passed to `clearWatch` to unsubscribe. */ + // $FlowFixMe[unclear-type] watchKeys(keys: string | Array, callback: Function): number { if (typeof keys === 'string') { + // $FlowFixMe[reassign-const] keys = [keys]; } @@ -77,6 +82,7 @@ const Settings = { } }, + // $FlowFixMe[unclear-type] _sendObservations(body: Object) { Object.keys(body).forEach(key => { const newValue = body[key]; diff --git a/packages/react-native/Libraries/Settings/Settings.js b/packages/react-native/Libraries/Settings/Settings.js index b0ec5480569f..9d6e84fa2d2d 100644 --- a/packages/react-native/Libraries/Settings/Settings.js +++ b/packages/react-native/Libraries/Settings/Settings.js @@ -4,14 +4,16 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ import Platform from '../Utilities/Platform'; let Settings: { + // $FlowFixMe[unclear-type] get(key: string): any, + // $FlowFixMe[unclear-type] set(settings: Object): void, watchKeys(keys: string | Array, callback: () => void): number, clearWatch(watchId: number): void, diff --git a/packages/react-native/Libraries/Settings/SettingsFallback.js b/packages/react-native/Libraries/Settings/SettingsFallback.js index bf00f04e16d6..b71f94948071 100644 --- a/packages/react-native/Libraries/Settings/SettingsFallback.js +++ b/packages/react-native/Libraries/Settings/SettingsFallback.js @@ -4,18 +4,20 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ 'use strict'; const Settings = { + // $FlowFixMe[unclear-type] get(key: string): any { console.warn('Settings is not yet supported on this platform.'); return null; }, + // $FlowFixMe[unclear-type] set(settings: Object) { console.warn('Settings is not yet supported on this platform.'); }, diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheet.js b/packages/react-native/Libraries/StyleSheet/StyleSheet.js index 529b9f3b6568..a6ec58a3fc9d 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheet.js +++ b/packages/react-native/Libraries/StyleSheet/StyleSheet.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheet.js.flow b/packages/react-native/Libraries/StyleSheet/StyleSheet.js.flow index 101d782aa278..28c096e51e00 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheet.js.flow +++ b/packages/react-native/Libraries/StyleSheet/StyleSheet.js.flow @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetExports.js.flow b/packages/react-native/Libraries/StyleSheet/StyleSheetExports.js.flow index 2aa4ee1d3ffb..9520c8d24788 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheetExports.js.flow +++ b/packages/react-native/Libraries/StyleSheet/StyleSheetExports.js.flow @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -86,9 +86,9 @@ declare export const flatten: typeof flattenStyle; * internally to process color and transform values. You should not use this * unless you really know what you are doing and have exhausted other options. */ -declare export const setStyleAttributePreprocessor: ( +declare export const setStyleAttributePreprocessor: ( property: string, - process: (nextProp: any) => any, + process: (nextProp: T) => unknown, ) => void; /** diff --git a/packages/react-native/Libraries/StyleSheet/processFilter.js b/packages/react-native/Libraries/StyleSheet/processFilter.js index daf37ea25537..b2385c5fb6c1 100644 --- a/packages/react-native/Libraries/StyleSheet/processFilter.js +++ b/packages/react-native/Libraries/StyleSheet/processFilter.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format strict-local */ @@ -51,13 +51,13 @@ export default function processFilter( } if (typeof filter === 'string') { - filter = filter.replace(NEWLINE_REGEX, ' '); + const normalizedFilter = filter.replace(NEWLINE_REGEX, ' '); // matches on functions with args and nested functions like "drop-shadow(10 10 10 rgba(0, 0, 0, 1))" FILTER_FUNCTION_REGEX.lastIndex = 0; let matches; - while ((matches = FILTER_FUNCTION_REGEX.exec(filter))) { + while ((matches = FILTER_FUNCTION_REGEX.exec(normalizedFilter))) { let filterName = matches[1].toLowerCase(); if (filterName === 'drop-shadow') { const dropShadow = parseDropShadow(matches[2]); @@ -159,7 +159,10 @@ function _getFilterAmount(filterName: string, filterArgs: unknown): ?number { // blur takes any positive CSS length that is not a percent. In RN // we currently only have DIPs, so we are not parsing units here. case 'blur': - if ((unit && unit !== 'px') || filterArgAsNumber < 0) { + if ( + (unit != null && unit !== '' && unit !== 'px') || + filterArgAsNumber < 0 + ) { return undefined; } return filterArgAsNumber; @@ -173,7 +176,10 @@ function _getFilterAmount(filterName: string, filterArgs: unknown): ?number { case 'opacity': case 'saturate': case 'sepia': - if ((unit && unit !== '%' && unit !== 'px') || filterArgAsNumber < 0) { + if ( + (unit != null && unit !== '' && unit !== '%' && unit !== 'px') || + filterArgAsNumber < 0 + ) { return undefined; } if (unit === '%') { diff --git a/packages/react-native/Libraries/StyleSheet/processTransform.js b/packages/react-native/Libraries/StyleSheet/processTransform.js index d4371e2b7c8c..8d43a9ae2bc3 100644 --- a/packages/react-native/Libraries/StyleSheet/processTransform.js +++ b/packages/react-native/Libraries/StyleSheet/processTransform.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -22,10 +22,13 @@ const invariant = require('invariant'); * interface to native code. */ function processTransform( + // $FlowFixMe[unclear-type] transform: Array | string, + // $FlowFixMe[unclear-type] ): Array | Array { if (typeof transform === 'string') { const regex = new RegExp(/(\w+)\(([^)]+)\)/g); + // $FlowFixMe[unclear-type] const transformArray: Array = []; let matches; @@ -39,13 +42,16 @@ function processTransform( transformArray.push({[key]: value}); } } + // $FlowFixMe[reassign-const] transform = transformArray; } if (__DEV__) { + // $FlowFixMe[incompatible-type] _validateTransforms(transform); } + // $FlowFixMe[incompatible-type] return transform; } @@ -138,6 +144,7 @@ const _getKeyAndValueFromCSSTransform: ( } }; +// $FlowFixMe[unclear-type] function _validateTransforms(transform: Array): void { transform.forEach(transformation => { const keys = Object.keys(transformation); @@ -160,10 +167,13 @@ function _validateTransforms(transform: Array): void { function _validateTransform( key: string, + // $FlowFixMe[unclear-type] value: any | number | string, + // $FlowFixMe[unclear-type] transformation: any, ) { invariant( + // $FlowFixMe[sketchy-null-mixed] !value.getValue, 'You passed an Animated.Value to a normal component. ' + 'You need to wrap that component in an Animated. For example, ' + diff --git a/packages/react-native/Libraries/StyleSheet/processTransformOrigin.js b/packages/react-native/Libraries/StyleSheet/processTransformOrigin.js index 5c132d92ae43..b90d3ced96e0 100644 --- a/packages/react-native/Libraries/StyleSheet/processTransformOrigin.js +++ b/packages/react-native/Libraries/StyleSheet/processTransformOrigin.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -20,10 +20,11 @@ const INDEX_Z = 2; /* eslint-disable no-labels */ export default function processTransformOrigin( - transformOrigin: Array | string, + transformOriginInput: Array | string, ): Array { - if (typeof transformOrigin === 'string') { - const transformOriginString = transformOrigin; + let transformOrigin: Array; + if (typeof transformOriginInput === 'string') { + const transformOriginString = transformOriginInput; TRANSFORM_ORIGIN_REGEX.lastIndex = 0; const transformOriginArray: Array = ['50%', '50%', 0]; @@ -111,6 +112,8 @@ export default function processTransformOrigin( } transformOrigin = transformOriginArray; + } else { + transformOrigin = transformOriginInput; } if (__DEV__) { diff --git a/packages/react-native/Libraries/StyleSheet/setNormalizedColorAlpha.js b/packages/react-native/Libraries/StyleSheet/setNormalizedColorAlpha.js index b412b260a30c..975243ad9eed 100644 --- a/packages/react-native/Libraries/StyleSheet/setNormalizedColorAlpha.js +++ b/packages/react-native/Libraries/StyleSheet/setNormalizedColorAlpha.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -17,15 +17,16 @@ * alpha should be number between 0 and 1 */ function setNormalizedColorAlpha(input: number, alpha: number): number { - if (alpha < 0) { - alpha = 0; - } else if (alpha > 1) { - alpha = 1; + let normalizedAlpha = alpha; + if (normalizedAlpha < 0) { + normalizedAlpha = 0; + } else if (normalizedAlpha > 1) { + normalizedAlpha = 1; } - alpha = Math.round(alpha * 255); + normalizedAlpha = Math.round(normalizedAlpha * 255); // magic bitshift guarantees we return an unsigned int - return ((input & 0xffffff00) | alpha) >>> 0; + return ((input & 0xffffff00) | normalizedAlpha) >>> 0; } export default setNormalizedColorAlpha; diff --git a/packages/react-native/Libraries/Text/TextNativeComponent.js b/packages/react-native/Libraries/Text/TextNativeComponent.js index 11c869113337..38cf4537601a 100644 --- a/packages/react-native/Libraries/Text/TextNativeComponent.js +++ b/packages/react-native/Libraries/Text/TextNativeComponent.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -77,23 +77,31 @@ const virtualTextViewConfig = { // Additional note: Our long term plan is to reduce the overhead of the // and wrappers so that we no longer have any reason to export these APIs. export const NativeText: HostComponent = - createReactNativeComponentClass('RCTText', () => - createViewConfig(textViewConfig), + createReactNativeComponentClass( + 'RCTText', + () => createViewConfig(textViewConfig), + // $FlowFixMe[unclear-type] ) as any; export const NativeVirtualText: HostComponent = + // $FlowFixMe[sketchy-null-bool] !global.RN$Bridgeless && !UIManager.hasViewManagerConfig('RCTVirtualText') ? NativeText - : (createReactNativeComponentClass('RCTVirtualText', () => - createViewConfig(virtualTextViewConfig), + : (createReactNativeComponentClass( + 'RCTVirtualText', + () => createViewConfig(virtualTextViewConfig), + // $FlowFixMe[unclear-type] ) as any); export const NativeSelectableText: HostComponent = enablePreparedTextLayout() - ? (createReactNativeComponentClass('RCTSelectableText', () => - createViewConfig({ - ...textViewConfig, - uiViewClassName: 'RCTSelectableText', - }), + ? (createReactNativeComponentClass( + 'RCTSelectableText', + () => + createViewConfig({ + ...textViewConfig, + uiViewClassName: 'RCTSelectableText', + }), + // $FlowFixMe[unclear-type] ) as any) : NativeText; diff --git a/packages/react-native/Libraries/Types/UIManagerJSInterface.js b/packages/react-native/Libraries/Types/UIManagerJSInterface.js index 26d59a2c13c4..31a07cb1f807 100644 --- a/packages/react-native/Libraries/Types/UIManagerJSInterface.js +++ b/packages/react-native/Libraries/Types/UIManagerJSInterface.js @@ -4,13 +4,13 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ -import type {Spec} from '../ReactNative/NativeUIManager'; +import type {Spec, ViewManagerConfig} from '../ReactNative/NativeUIManager'; export interface UIManagerJSInterface extends Spec { - readonly getViewManagerConfig: (viewManagerName: string) => Object; + readonly getViewManagerConfig: (viewManagerName: string) => ViewManagerConfig; readonly hasViewManagerConfig: (viewManagerName: string) => boolean; } diff --git a/packages/react-native/Libraries/Utilities/BackHandler.js.flow b/packages/react-native/Libraries/Utilities/BackHandler.js.flow index 68cc9095f5b5..4c1debea88b0 100644 --- a/packages/react-native/Libraries/Utilities/BackHandler.js.flow +++ b/packages/react-native/Libraries/Utilities/BackHandler.js.flow @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ diff --git a/packages/react-native/Libraries/Utilities/Dimensions.js b/packages/react-native/Libraries/Utilities/Dimensions.js index 85a6fc5dc494..6597885ac0db 100644 --- a/packages/react-native/Libraries/Utilities/Dimensions.js +++ b/packages/react-native/Libraries/Utilities/Dimensions.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -111,6 +111,7 @@ class Dimensions { */ static addEventListener( type: 'change', + // $FlowFixMe[unclear-type] handler: Function, ): EventSubscription { invariant( diff --git a/packages/react-native/Libraries/Utilities/FeatureDetection.js b/packages/react-native/Libraries/Utilities/FeatureDetection.js index 83cdd80ac4e1..3429a76f04ab 100644 --- a/packages/react-native/Libraries/Utilities/FeatureDetection.js +++ b/packages/react-native/Libraries/Utilities/FeatureDetection.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -15,7 +15,9 @@ * Note that a polyfill can technically fake this behavior but few does it. * Therefore, this is usually good enough for our purpose. */ -export function isNativeFunction(f: Function): boolean { +export function isNativeFunction( + f: (...args: ReadonlyArray) => unknown, +): boolean { return typeof f === 'function' && f.toString().indexOf('[native code]') > -1; } @@ -23,7 +25,10 @@ export function isNativeFunction(f: Function): boolean { * @return whether or not the constructor of @param {object} o is an native * function named with @param {string} expectedName. */ -export function hasNativeConstructor(o: Object, expectedName: string): boolean { +export function hasNativeConstructor( + o: interface {}, + expectedName: string, +): boolean { const con = Object.getPrototypeOf(o).constructor; return con.name === expectedName && isNativeFunction(con); } diff --git a/packages/react-native/Libraries/Utilities/ReactNativeTestTools.js b/packages/react-native/Libraries/Utilities/ReactNativeTestTools.js index a29fed1f0efb..a2ae7e50a55a 100644 --- a/packages/react-native/Libraries/Utilities/ReactNativeTestTools.js +++ b/packages/react-native/Libraries/Utilities/ReactNativeTestTools.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -163,6 +163,7 @@ function maximumDepthOfJSON(node: ?ReactTestRendererJSON): number { } } +// $FlowFixMe[unclear-type] function renderAndEnforceStrictMode(element: React.Node): any { expectNoConsoleError(); return renderWithStrictMode(element); @@ -217,6 +218,7 @@ function scrollToBottom(instance: ReactTestInstance) { // To make error messages a little bit better, we attach a custom toString // implementation to a predicate function withMessage(fn: Predicate, message: string): Predicate { + // $FlowFixMe[unclear-type] (fn as any).toString = () => message; return fn; } diff --git a/packages/react-native/Libraries/Utilities/codegenNativeCommands.js b/packages/react-native/Libraries/Utilities/codegenNativeCommands.js index 4ef170fd7d2f..d163443ab6df 100644 --- a/packages/react-native/Libraries/Utilities/codegenNativeCommands.js +++ b/packages/react-native/Libraries/Utilities/codegenNativeCommands.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -27,6 +27,7 @@ function codegenNativeCommands( }; }); + // $FlowFixMe[unclear-type] - dynamic command object cannot be statically typed as the generic interface T return commandObj as any as T; } diff --git a/packages/react-native/Libraries/Utilities/differ/deepDiffer.js b/packages/react-native/Libraries/Utilities/differ/deepDiffer.js index 0f5d48cc7270..49d00d08146a 100644 --- a/packages/react-native/Libraries/Utilities/differ/deepDiffer.js +++ b/packages/react-native/Libraries/Utilities/differ/deepDiffer.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -29,7 +29,9 @@ function unstable_setLogListeners(listeners: ?LogListeners) { * @returns {bool} true if different, false if equal */ function deepDiffer( + // $FlowFixMe[unclear-type] - deepDiffer compares values of arbitrary shape one: any, + // $FlowFixMe[unclear-type] - deepDiffer compares values of arbitrary shape two: any, maxDepthOrOptions: Options | number = -1, maybeOptions?: Options, diff --git a/packages/react-native/Libraries/Utilities/differ/insetsDiffer.js b/packages/react-native/Libraries/Utilities/differ/insetsDiffer.js index 0742df32c31e..c504e64543a1 100644 --- a/packages/react-native/Libraries/Utilities/differ/insetsDiffer.js +++ b/packages/react-native/Libraries/Utilities/differ/insetsDiffer.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -26,14 +26,14 @@ const dummyInsets = { }; function insetsDiffer(one: Inset, two: Inset): boolean { - one = one || dummyInsets; - two = two || dummyInsets; + const insetOne = one || dummyInsets; + const insetTwo = two || dummyInsets; return ( - one !== two && - (one.top !== two.top || - one.left !== two.left || - one.right !== two.right || - one.bottom !== two.bottom) + insetOne !== insetTwo && + (insetOne.top !== insetTwo.top || + insetOne.left !== insetTwo.left || + insetOne.right !== insetTwo.right || + insetOne.bottom !== insetTwo.bottom) ); } diff --git a/packages/react-native/Libraries/Utilities/differ/pointsDiffer.js b/packages/react-native/Libraries/Utilities/differ/pointsDiffer.js index 9bf891f914e2..0c02cad24a66 100644 --- a/packages/react-native/Libraries/Utilities/differ/pointsDiffer.js +++ b/packages/react-native/Libraries/Utilities/differ/pointsDiffer.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -19,9 +19,12 @@ type Point = { const dummyPoint: Point = {x: undefined, y: undefined}; function pointsDiffer(one: ?Point, two: ?Point): boolean { - one = one || dummyPoint; - two = two || dummyPoint; - return one !== two && (one.x !== two.x || one.y !== two.y); + const onePoint = one ?? dummyPoint; + const twoPoint = two ?? dummyPoint; + return ( + onePoint !== twoPoint && + (onePoint.x !== twoPoint.x || onePoint.y !== twoPoint.y) + ); } export default pointsDiffer; diff --git a/packages/react-native/Libraries/Utilities/stringifyViewConfig.js b/packages/react-native/Libraries/Utilities/stringifyViewConfig.js index 419bce0a8ba6..419de5b44902 100644 --- a/packages/react-native/Libraries/Utilities/stringifyViewConfig.js +++ b/packages/react-native/Libraries/Utilities/stringifyViewConfig.js @@ -4,19 +4,21 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ -export default function stringifyViewConfig(viewConfig: any): string { - return JSON.stringify( - viewConfig, - (key, val) => { - if (typeof val === 'function') { - return `ƒ ${val.name}`; - } - return val; - }, - 2, +export default function stringifyViewConfig(viewConfig: unknown): string { + return ( + JSON.stringify( + viewConfig, + (key, val) => { + if (typeof val === 'function') { + return `ƒ ${val.name}`; + } + return val; + }, + 2, + ) ?? '' ); } diff --git a/packages/react-native/Libraries/WebSocket/WebSocket.js b/packages/react-native/Libraries/WebSocket/WebSocket.js index 6ed5630f7438..0a48672d8696 100644 --- a/packages/react-native/Libraries/WebSocket/WebSocket.js +++ b/packages/react-native/Libraries/WebSocket/WebSocket.js @@ -4,10 +4,12 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ +// flowlint unsafe-getters-setters:off + import type {EventCallback} from '../../src/private/webapis/dom/events/EventTarget'; import type {BlobData} from '../Blob/BlobTypes'; import type {EventSubscription} from '../vendor/emitter/EventEmitter'; @@ -98,29 +100,29 @@ class WebSocket extends EventTarget { constructor( url: string, protocols: ?string | ?Array, - options: ?{headers?: {origin?: string, ...}, ...}, + options: ?{headers?: {origin?: string, ...}, origin?: string, ...}, ) { super(); this.url = url; - if (typeof protocols === 'string') { - protocols = [protocols]; - } - - const {headers = {}, ...unrecognized} = options || {}; + const protocolList: ?Array = + typeof protocols === 'string' + ? [protocols] + : Array.isArray(protocols) + ? protocols + : null; + + const {headers = {}, ...unrecognized} = (options ?? {}) as { + headers?: {origin?: string, ...}, + origin?: string, + ... + }; // Preserve deprecated backwards compatibility for the 'origin' option - // $FlowFixMe[prop-missing] if (unrecognized && typeof unrecognized.origin === 'string') { console.warn( 'Specifying `origin` as a WebSocket connection option is deprecated. Include it under `headers` instead.', ); - /* $FlowFixMe[prop-missing] (>=0.54.0 site=react_native_fb,react_native_ - * oss) This comment suppresses an error found when Flow v0.54 was - * deployed. To see the error delete this comment and run Flow. */ headers.origin = unrecognized.origin; - /* $FlowFixMe[prop-missing] (>=0.54.0 site=react_native_fb,react_native_ - * oss) This comment suppresses an error found when Flow v0.54 was - * deployed. To see the error delete this comment and run Flow. */ delete unrecognized.origin; } @@ -134,10 +136,6 @@ class WebSocket extends EventTarget { ); } - if (!Array.isArray(protocols)) { - protocols = null; - } - this._eventEmitter = new NativeEventEmitter( // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior // If you want to use the native module on other platforms, please remove this condition and test its behavior @@ -149,7 +147,7 @@ class WebSocket extends EventTarget { global.__NETWORK_REPORTER__?.createDevToolsRequestId(); NativeWebSocketModule.connect( url, - protocols, + protocolList, {headers, unstable_devToolsRequestId: devToolsRequestId}, this._socketId, ); diff --git a/packages/react-native/Libraries/__flowtests__/ReactNativeTypes-flowtest.js b/packages/react-native/Libraries/__flowtests__/ReactNativeTypes-flowtest.js index 57c5c8910737..38c0a45aac49 100644 --- a/packages/react-native/Libraries/__flowtests__/ReactNativeTypes-flowtest.js +++ b/packages/react-native/Libraries/__flowtests__/ReactNativeTypes-flowtest.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ @@ -15,7 +15,7 @@ import * as React from 'react'; function takesHostComponentInstance(instance: HostInstance | null): void {} -const MyHostComponent = 'Host' as any as HostComponent<{...}>; +declare const MyHostComponent: HostComponent<{...}>; { diff --git a/packages/react-native/ReactNativeApi.d.ts b/packages/react-native/ReactNativeApi.d.ts index 24f632825a84..90ae080b97ad 100644 --- a/packages/react-native/ReactNativeApi.d.ts +++ b/packages/react-native/ReactNativeApi.d.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> * * This file was generated by scripts/js-api/build-types/index.js. */ @@ -336,8 +336,10 @@ declare const RCTNetworking_default: { method: string, trackingName: string | void, url: string, - headers: {}, - data: RequestBody, + headers: { + [$$Key$$: string]: string + }, + data: RequestBody | undefined, responseType: NativeResponseType, incrementalUpdates: boolean, timeout: number, @@ -371,9 +373,9 @@ declare const sequence: typeof $$AnimatedImplementation.sequence declare const sequenceImpl: ( animations: Array, ) => CompositeAnimation -declare const setStyleAttributePreprocessor: ( +declare const setStyleAttributePreprocessor: ( property: string, - process: (nextProp: any) => any, + process: (nextProp: T) => unknown, ) => void declare const Settings: typeof Settings_default declare let Settings_default: { @@ -1384,15 +1386,15 @@ declare class AnimatedTracking_default extends AnimatedNode_default { constructor( value: AnimatedValue_default, parent: AnimatedNode_default, - animationClass: any, - animationConfig: Object, + animationClass: new (...args: any[]) => Animation_default, + animationConfig: TrackingAnimationConfig, callback?: EndCallback | null | undefined, config?: AnimatedNodeConfig | null | undefined, ) update(): void } declare class AnimatedValue_default extends AnimatedWithChildren_default { - addListener(callback: (value: any) => unknown): string + addListener(callback: (value: { value: number }) => unknown): string animate( animation: Animation_default, callback: EndCallback | null | undefined, @@ -1766,7 +1768,7 @@ declare function counterEvent(eventName: EventName, value: number): void declare type create = typeof create declare type createAnimatedComponent = typeof createAnimatedComponent declare function createAnimatedComponent_default< - TInstance extends React.ComponentType, + TInstance extends React.ComponentType, >( Component: TInstance, ): AnimatedComponentType< @@ -1960,7 +1962,7 @@ declare interface DrawerLayoutAndroidMethods { onFail?: () => void, ): void openDrawer(): void - setNativeProps(nativeProps: Object): void + setNativeProps(nativeProps: {}): void } declare type DrawerLayoutAndroidProps = Readonly< ViewProps & { @@ -2913,7 +2915,7 @@ declare type LoopAnimationConfig = { iterations: number resetBeforeIteration?: boolean } -declare type LooseOmit = Pick< +declare type LooseOmit = Pick< O, Exclude > @@ -3242,7 +3244,7 @@ declare type OnAnimationDidFailCallback = () => void declare type OpaqueColorValue = NativeColorValue declare type OptionalFlatListProps = { columnWrapperStyle?: ViewStyleProp - extraData?: any + extraData?: unknown fadingEdgeLength?: | (number | undefined) | { @@ -3269,7 +3271,7 @@ declare type OptionalFlatListProps = { } declare type OptionalPlatformSelectSpec = { [key in PlatformOSType]?: T } declare type OptionalSectionListProps = { - extraData?: any + extraData?: unknown initialNumToRender?: number inverted?: boolean keyExtractor?: (item: ItemT, index: number) => string @@ -4445,7 +4447,7 @@ declare type setStyleAttributePreprocessor = typeof setStyleAttributePreprocessor declare function setSurfaceProps( appKey: string, - appParameters: Object, + appParameters: AppParameters, displayMode?: number, ): void declare type Settings = typeof Settings @@ -4507,9 +4509,9 @@ declare interface Spec extends TurboModule { readonly focus?: (reactTag: number) => void readonly getConstantsForViewManager?: ( viewManagerName: string, - ) => Object | undefined + ) => undefined | ViewManagerConfig readonly getDefaultEventTypes?: () => Array - readonly lazilyLoadView?: (name: string) => Object + readonly lazilyLoadView?: (name: string) => ViewManagerConfig readonly sendAccessibilityEvent?: ( reactTag: number, eventType: number, @@ -4517,20 +4519,20 @@ declare interface Spec extends TurboModule { readonly setLayoutAnimationEnabledExperimental?: (enabled: boolean) => void readonly clearJSResponder: () => void readonly configureNextLayoutAnimation: ( - config: Object, + config: UnsafeObject, callback: () => void, - errorCallback: (error: Object) => void, + errorCallback: (error: UnsafeObject) => void, ) => void readonly createView: ( reactTag: number, viewName: string, rootTag: RootTag, - props: Object, + props: UnsafeObject, ) => void readonly dispatchViewManagerCommand: ( reactTag: number, commandID: number, - commandArgs?: Array, + commandArgs?: Array, ) => void readonly findSubviewIn: ( reactTag: number, @@ -4543,7 +4545,7 @@ declare interface Spec extends TurboModule { height: number, ) => void, ) => void - readonly getConstants: () => Object + readonly getConstants: () => UIManagerConstants readonly manageChildren: ( containerTag: number, moveFromIndices: Array, @@ -4563,12 +4565,12 @@ declare interface Spec extends TurboModule { readonly measureLayout: ( reactTag: number, ancestorReactTag: number, - errorCallback: (error: Object) => void, + errorCallback: (error: UnsafeObject) => void, callback: NativeMeasureLayoutOnSuccessCallback, ) => void readonly measureLayoutRelativeToParent: ( reactTag: number, - errorCallback: (error: Object) => void, + errorCallback: (error: UnsafeObject) => void, callback: ( left: number, top: number, @@ -4584,7 +4586,7 @@ declare interface Spec extends TurboModule { readonly updateView: ( reactTag: number, viewName: string, - props: Object, + props: UnsafeObject, ) => void readonly viewIsDescendantOf: ( reactTag: number, @@ -4643,13 +4645,13 @@ declare type StackProps = { | undefined | { animated: boolean - value: StatusBarProps["barStyle"] + value: StatusBarStyle } hidden: | undefined | { animated: boolean - transition: StatusBarProps["showHideTransition"] + transition: StatusBarAnimation value: boolean } } @@ -4657,7 +4659,7 @@ declare type stagger = typeof stagger declare function startHeadlessTask( taskId: number, taskKey: string, - data: any, + data: unknown, ): void declare type State = { cellsAroundViewport: { @@ -5336,6 +5338,11 @@ declare function trace( fn: () => T, args?: EventArgs, ): T +declare type TrackingAnimationConfig = Readonly< + AnimationConfig & { + toValue: AnimatedNode_default + } +> declare type TransformsStyle = ____TransformStyle_Internal declare interface TurboModule extends DEPRECATED_RCTExport {} declare namespace TurboModuleRegistry { @@ -5350,8 +5357,9 @@ declare type TVViewPropsIOS = { readonly tvParallaxTiltAngle?: number } declare type UIManager = typeof UIManager +declare type UIManagerConstants = UnsafeObject declare interface UIManagerJSInterface extends Spec { - readonly getViewManagerConfig: (viewManagerName: string) => Object + readonly getViewManagerConfig: (viewManagerName: string) => ViewManagerConfig readonly hasViewManagerConfig: (viewManagerName: string) => boolean } declare type unforkEvent = typeof unforkEvent @@ -5497,6 +5505,7 @@ declare type ViewConfig = { readonly validAttributes: AttributeConfiguration } declare type ViewInstance = HostInstance +declare type ViewManagerConfig = UnsafeObject declare interface ViewProps extends Readonly< DirectEventProps & GestureResponderHandlers & @@ -5714,9 +5723,9 @@ export { AlertOptions, // 8a116d2a AlertType, // 5ab91217 AndroidKeyboardEvent, // e03becc8 - Animated, // 50cbe576 + Animated, // 51ae1ed0 AppConfig, // 35c0ca70 - AppRegistry, // 1e8c5a00 + AppRegistry, // 54cbc34d AppState, // 12012be5 AppStateEvent, // 80f034c3 AppStateStatus, // 447e5ef2 @@ -5728,8 +5737,8 @@ export { BackPressEventName, // 4620fb76 BlurEvent, // 4ba4f941 BoxShadowValue, // b679703f - Button, // bc8f6464 - ButtonInstance, // d94b4241 + Button, // f2435367 + ButtonInstance, // e4d65823 ButtonProps, // 21c5780c Clipboard, // 41addb89 CodegenTypes, // ab4986cc @@ -5748,8 +5757,8 @@ export { DimensionsPayload, // 653bc26c DisplayMetrics, // 1dc35cef DisplayMetricsAndroid, // 872e62eb - DrawerLayoutAndroid, // 7843b7b5 - DrawerLayoutAndroidInstance, // c0694352 + DrawerLayoutAndroid, // 58bc08bc + DrawerLayoutAndroidInstance, // aa243cbf DrawerLayoutAndroidProps, // 0c1d6155 DrawerSlideEvent, // c4ab8fba DropShadowValue, // e9df2606 @@ -5766,9 +5775,9 @@ export { EventSubscription, // b8d084aa ExtendedExceptionData, // 5a6ccf5a FilterFunction, // bf24c0e3 - FlatList, // e1b005c7 - FlatListInstance, // 2d1d8e45 - FlatListProps, // 94fa2dc7 + FlatList, // 171059bc + FlatListInstance, // ead0b62b + FlatListProps, // 80710cf1 FocusEvent, // 850f1517 FontVariant, // 7c7558bb GestureResponderEvent, // 14d3e77a @@ -5854,7 +5863,7 @@ export { NativeSyntheticEvent, // 534aaa92 NativeTouchEvent, // 59b676df NativeUIEvent, // 44ac26ac - Networking, // bbc5be42 + Networking, // bd182394 OpaqueColorValue, // 25f3fa5b PackagerAsset, // d1c88cf4 PanResponder, // e4df325a @@ -5909,18 +5918,18 @@ export { ScrollEvent, // d7abdd0a ScrollResponderType, // ba188eae ScrollToLocationParamsType, // d7ecdad1 - ScrollView, // 066a8597 + ScrollView, // f1d46d64 ScrollViewImperativeMethods, // 904c66fd ScrollViewInstance, // ccf4f341 - ScrollViewProps, // b62913d1 + ScrollViewProps, // 8434d563 ScrollViewPropsAndroid, // 02f3df2e ScrollViewPropsIOS, // 807cb4f6 ScrollViewScrollToOptions, // 3313411e SectionBase, // 9f13db00 - SectionList, // ee3e7972 + SectionList, // 22fb1f1f SectionListData, // 1a4de01a - SectionListInstance, // c9b991fe - SectionListProps, // 0e933318 + SectionListInstance, // 297fe811 + SectionListProps, // 47274631 SectionListRenderItem, // 715b2086 SectionListRenderItemInfo, // 4a48a922 Separators, // 6a45f7e3 @@ -5931,13 +5940,13 @@ export { ShareActionSheetIOSOptions, // eff574f5 ShareContent, // 7c627896 ShareOptions, // 800c3a4e - StatusBar, // f95dbb76 + StatusBar, // 5748d574 StatusBarAnimation, // 7fd047e6 - StatusBarInstance, // 416e9640 + StatusBarInstance, // de13e4a1 StatusBarProps, // c2a44d88 StatusBarStyle, // 78f53eea StyleProp, // fa0e9b4a - StyleSheet, // e734acd4 + StyleSheet, // 8f9da31a SubmitBehavior, // c4ddf490 Switch, // f495bab3 SwitchChangeEvent, // 899635b1 @@ -5973,15 +5982,15 @@ export { TouchableNativeFeedback, // fe739e82 TouchableNativeFeedbackInstance, // 0877e3e4 TouchableNativeFeedbackProps, // 1d0c2f30 - TouchableOpacity, // fe716ffc + TouchableOpacity, // ade59062 TouchableOpacityInstance, // b186055b - TouchableOpacityProps, // a3b32b69 + TouchableOpacityProps, // 98f8b9b4 TouchableWithoutFeedback, // ed159ba7 TouchableWithoutFeedbackProps, // e613ed05 TransformsStyle, // 65e70f18 TurboModule, // dfe29706 TurboModuleRegistry, // 4ace6db2 - UIManager, // afbcdf05 + UIManager, // 38bf2d34 UTFSequence, // ad625158 Vibration, // 31e4bbf8 View, // 3e72139a @@ -5993,10 +6002,10 @@ export { VirtualViewMode, // 6be59722 VirtualizedList, // 68c7345e VirtualizedListInstance, // 423ee7c0 - VirtualizedListProps, // f51f4a42 + VirtualizedListProps, // 47c47ba6 VirtualizedSectionList, // 9fd9cd61 VirtualizedSectionListInstance, // 12b706d5 - VirtualizedSectionListProps, // 8210f30a + VirtualizedSectionListProps, // 9775ebce WrapperComponentProvider, // 9ef54e61 codegenNativeCommands, // 628a7c0a codegenNativeComponent, // 32a1bca6 @@ -6004,9 +6013,9 @@ export { processColor, // 6e877698 registerCallableModule, // 839c8cfe requireNativeComponent, // aa36a6dd - useAnimatedColor, // a9dffd9f - useAnimatedValue, // 25733d13 - useAnimatedValueXY, // 04c70878 + useAnimatedColor, // d8b66fcd + useAnimatedValue, // 2386043c + useAnimatedValueXY, // 5b66327f useColorScheme, // d585efdb usePressability, // 782138ed useWindowDimensions, // bb4b683f diff --git a/packages/react-native/src/private/devsupport/devmenu/elementinspector/BoxInspector.js b/packages/react-native/src/private/devsupport/devmenu/elementinspector/BoxInspector.js index 59aa4c801a40..9565d23693de 100644 --- a/packages/react-native/src/private/devsupport/devmenu/elementinspector/BoxInspector.js +++ b/packages/react-native/src/private/devsupport/devmenu/elementinspector/BoxInspector.js @@ -61,10 +61,10 @@ type BoxContainerProps = Readonly<{ title: string, titleStyle?: TextStyleProp, box: Readonly<{ - top: number, - left: number, - right: number, - bottom: number, + top: number | string, + left: number | string, + right: number | string, + bottom: number | string, }>, children: React.Node, }>; diff --git a/packages/react-native/src/private/devsupport/devmenu/elementinspector/ElementBox.js b/packages/react-native/src/private/devsupport/devmenu/elementinspector/ElementBox.js index 08b4e9704ca0..a16c4fcec91c 100644 --- a/packages/react-native/src/private/devsupport/devmenu/elementinspector/ElementBox.js +++ b/packages/react-native/src/private/devsupport/devmenu/elementinspector/ElementBox.js @@ -16,8 +16,6 @@ import type {InspectedElementFrame} from './Inspector'; import * as React from 'react'; const View = require('../../../../../Libraries/Components/View/View').default; -const flattenStyle = - require('../../../../../Libraries/StyleSheet/flattenStyle').default; const StyleSheet = require('../../../../../Libraries/StyleSheet/StyleSheet').default; const Dimensions = @@ -31,9 +29,10 @@ type Props = Readonly<{ }>; function ElementBox({frame, style}: Props): React.Node { - const flattenedStyle = flattenStyle(style) || {}; - let margin: ?Readonly