Update Flow to 0.273 (#34274)

This version introduces "Natural Inference" which requires a couple more
type annotations to make Flow pass.
This commit is contained in:
Jan Kassens 2025-08-22 16:58:01 -04:00 committed by GitHub
parent e67e3bed92
commit 4049cfeeab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 40 additions and 34 deletions

View File

@ -565,6 +565,7 @@ module.exports = {
BigInt: 'readonly', BigInt: 'readonly',
BigInt64Array: 'readonly', BigInt64Array: 'readonly',
BigUint64Array: 'readonly', BigUint64Array: 'readonly',
CacheType: 'readonly',
Class: 'readonly', Class: 'readonly',
ClientRect: 'readonly', ClientRect: 'readonly',
CopyInspectedElementPath: 'readonly', CopyInspectedElementPath: 'readonly',

View File

@ -74,8 +74,8 @@
"eslint-plugin-react-internal": "link:./scripts/eslint-rules", "eslint-plugin-react-internal": "link:./scripts/eslint-rules",
"fbjs-scripts": "^3.0.1", "fbjs-scripts": "^3.0.1",
"filesize": "^6.0.1", "filesize": "^6.0.1",
"flow-bin": "^0.272", "flow-bin": "^0.273",
"flow-remove-types": "^2.272", "flow-remove-types": "^2.273",
"flow-typed": "^4.1.1", "flow-typed": "^4.1.1",
"glob": "^7.1.6", "glob": "^7.1.6",
"glob-stream": "^6.1.0", "glob-stream": "^6.1.0",

View File

@ -6705,7 +6705,7 @@ export function attach(
if (isMostRecentlyInspectedElement(id) && !forceFullData) { if (isMostRecentlyInspectedElement(id) && !forceFullData) {
if (!hasElementUpdatedSinceLastInspected) { if (!hasElementUpdatedSinceLastInspected) {
if (path !== null) { if (path !== null) {
let secondaryCategory = null; let secondaryCategory: 'suspendedBy' | 'hooks' | null = null;
if (path[0] === 'hooks') { if (path[0] === 'hooks') {
secondaryCategory = 'hooks'; secondaryCategory = 'hooks';
} }

View File

@ -103,7 +103,7 @@ export function loadHookNames(
let timeoutID: $FlowFixMe | null; let timeoutID: $FlowFixMe | null;
let didTimeout = false; let didTimeout = false;
let status = 'unknown'; let status: 'success' | 'error' | 'timeout' | 'unknown' = 'unknown';
let resolvedHookNames: HookNames | null = null; let resolvedHookNames: HookNames | null = null;
const wake = () => { const wake = () => {

View File

@ -64,7 +64,7 @@ import type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/view
// Prefer a cached albeit stale response to reduce download time. // Prefer a cached albeit stale response to reduce download time.
// We wouldn't want to load/parse a newer version of the source (even if one existed). // We wouldn't want to load/parse a newer version of the source (even if one existed).
const FETCH_OPTIONS = {cache: 'force-cache'}; const FETCH_OPTIONS = {cache: 'force-cache' as CacheType};
const MAX_SOURCE_LENGTH = 100_000_000; const MAX_SOURCE_LENGTH = 100_000_000;

View File

@ -509,7 +509,7 @@ function processTimelineEvent(
} else if (name.startsWith('--schedule-forced-update-')) { } else if (name.startsWith('--schedule-forced-update-')) {
const [laneBitmaskString, componentName] = name.slice(25).split('-'); const [laneBitmaskString, componentName] = name.slice(25).split('-');
const forceUpdateEvent = { const forceUpdateEvent: SchedulingEvent = {
type: 'schedule-force-update', type: 'schedule-force-update',
lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString), lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString),
componentName, componentName,
@ -527,7 +527,7 @@ function processTimelineEvent(
} else if (name.startsWith('--schedule-state-update-')) { } else if (name.startsWith('--schedule-state-update-')) {
const [laneBitmaskString, componentName] = name.slice(24).split('-'); const [laneBitmaskString, componentName] = name.slice(24).split('-');
const stateUpdateEvent = { const stateUpdateEvent: SchedulingEvent = {
type: 'schedule-state-update', type: 'schedule-state-update',
lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString), lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString),
componentName, componentName,
@ -578,7 +578,7 @@ function processTimelineEvent(
// We can't know if they'll be resolved or not at this point. // We can't know if they'll be resolved or not at this point.
// We'll just give them a default (fake) duration width. // We'll just give them a default (fake) duration width.
const suspenseEvent = { const suspenseEvent: SuspenseEvent = {
componentName, componentName,
depth, depth,
duration: null, duration: null,

View File

@ -140,7 +140,7 @@ export function trackHydrated(
return false; return false;
} }
let valueField; let valueField: 'checked' | 'value';
let expectedValue; let expectedValue;
if (isCheckable(node)) { if (isCheckable(node)) {
valueField = 'checked'; valueField = 'checked';
@ -150,8 +150,11 @@ export function trackHydrated(
valueField = 'value'; valueField = 'value';
expectedValue = initialValue; expectedValue = initialValue;
} }
// eslint-disable-next-line react-internal/safe-string-coercion const currentValue =
const currentValue = '' + (node[valueField]: any); // eslint-disable-next-line react-internal/safe-string-coercion
'' +
(// $FlowFixMe[prop-missing]
node[valueField]: any);
node._valueTracker = trackValueOnNode(node, valueField, expectedValue); node._valueTracker = trackValueOnNode(node, valueField, expectedValue);
return currentValue !== expectedValue; return currentValue !== expectedValue;
} }

View File

@ -146,7 +146,7 @@ function createSyntheticEvent(Interface: EventInterfaceType) {
* @interface Event * @interface Event
* @see http://www.w3.org/TR/DOM-Level-3-Events/ * @see http://www.w3.org/TR/DOM-Level-3-Events/
*/ */
const EventInterface = { const EventInterface: EventInterfaceType = {
eventPhase: 0, eventPhase: 0,
bubbles: 0, bubbles: 0,
cancelable: 0, cancelable: 0,
@ -442,7 +442,7 @@ function getEventModifierState(nativeEvent: {[propName: string]: mixed}) {
* @interface KeyboardEvent * @interface KeyboardEvent
* @see http://www.w3.org/TR/DOM-Level-3-Events/ * @see http://www.w3.org/TR/DOM-Level-3-Events/
*/ */
const KeyboardEventInterface = { const KeyboardEventInterface: EventInterfaceType = {
...UIEventInterface, ...UIEventInterface,
key: getEventKey, key: getEventKey,
code: 0, code: 0,
@ -505,7 +505,7 @@ export const SyntheticKeyboardEvent: $FlowFixMe = createSyntheticEvent(
* @interface PointerEvent * @interface PointerEvent
* @see http://www.w3.org/TR/pointerevents/ * @see http://www.w3.org/TR/pointerevents/
*/ */
const PointerEventInterface = { const PointerEventInterface: EventInterfaceType = {
...MouseEventInterface, ...MouseEventInterface,
pointerId: 0, pointerId: 0,
width: 0, width: 0,
@ -526,7 +526,7 @@ export const SyntheticPointerEvent: $FlowFixMe = createSyntheticEvent(
* @interface TouchEvent * @interface TouchEvent
* @see http://www.w3.org/TR/touch-events/ * @see http://www.w3.org/TR/touch-events/
*/ */
const TouchEventInterface = { const TouchEventInterface: EventInterfaceType = {
...UIEventInterface, ...UIEventInterface,
touches: 0, touches: 0,
targetTouches: 0, targetTouches: 0,
@ -545,7 +545,7 @@ export const SyntheticTouchEvent: $FlowFixMe =
* @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events- * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-
* @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent
*/ */
const TransitionEventInterface = { const TransitionEventInterface: EventInterfaceType = {
...EventInterface, ...EventInterface,
propertyName: 0, propertyName: 0,
elapsedTime: 0, elapsedTime: 0,
@ -559,7 +559,7 @@ export const SyntheticTransitionEvent: $FlowFixMe = createSyntheticEvent(
* @interface WheelEvent * @interface WheelEvent
* @see http://www.w3.org/TR/DOM-Level-3-Events/ * @see http://www.w3.org/TR/DOM-Level-3-Events/
*/ */
const WheelEventInterface = { const WheelEventInterface: EventInterfaceType = {
...MouseEventInterface, ...MouseEventInterface,
deltaX(event: {[propName: string]: mixed}) { deltaX(event: {[propName: string]: mixed}) {
return 'deltaX' in event return 'deltaX' in event
@ -594,7 +594,7 @@ const WheelEventInterface = {
export const SyntheticWheelEvent: $FlowFixMe = export const SyntheticWheelEvent: $FlowFixMe =
createSyntheticEvent(WheelEventInterface); createSyntheticEvent(WheelEventInterface);
const ToggleEventInterface = { const ToggleEventInterface: EventInterfaceType = {
...EventInterface, ...EventInterface,
newState: 0, newState: 0,
oldState: 0, oldState: 0,

View File

@ -31,7 +31,7 @@ export type FormStatus = FormStatusPending | FormStatusNotPending;
// Since the "not pending" value is always the same, we can reuse the // Since the "not pending" value is always the same, we can reuse the
// same object across all transitions. // same object across all transitions.
const sharedNotPendingObject = { const sharedNotPendingObject: FormStatusNotPending = {
pending: false, pending: false,
data: null, data: null,
method: null, method: null,

View File

@ -207,6 +207,7 @@ const ResponderTouchHistoryStore = {
touchHistory.numberActiveTouches = nativeEvent.touches.length; touchHistory.numberActiveTouches = nativeEvent.touches.length;
if (touchHistory.numberActiveTouches === 1) { if (touchHistory.numberActiveTouches === 1) {
touchHistory.indexOfSingleActiveTouch = touchHistory.indexOfSingleActiveTouch =
// $FlowFixMe[incompatible-type] might be null according to type
nativeEvent.touches[0].identifier; nativeEvent.touches[0].identifier;
} }
} else if (isEndish(topLevelType)) { } else if (isEndish(topLevelType)) {

View File

@ -5020,7 +5020,7 @@ function commitPassiveUnmountInsideDeletedTreeOnFiber(
const instance: OffscreenInstance = offscreenFiber.stateNode; const instance: OffscreenInstance = offscreenFiber.stateNode;
const transitions = instance._transitions; const transitions = instance._transitions;
if (transitions !== null) { if (transitions !== null) {
const abortReason = { const abortReason: TransitionAbort = {
reason: 'suspense', reason: 'suspense',
name: current.memoizedProps.name || null, name: current.memoizedProps.name || null,
}; };
@ -5061,7 +5061,7 @@ function commitPassiveUnmountInsideDeletedTreeOnFiber(
const instance: TracingMarkerInstance = current.stateNode; const instance: TracingMarkerInstance = current.stateNode;
const transitions = instance.transitions; const transitions = instance.transitions;
if (transitions !== null) { if (transitions !== null) {
const abortReason = { const abortReason: TransitionAbort = {
reason: 'marker', reason: 'marker',
name: current.memoizedProps.name, name: current.memoizedProps.name,
}; };

View File

@ -9,6 +9,7 @@
import type {Fiber, FiberRoot} from 'react-reconciler/src/ReactInternalTypes'; import type {Fiber, FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
import type { import type {
Container,
PublicInstance, PublicInstance,
Instance, Instance,
TextInstance, TextInstance,
@ -505,7 +506,7 @@ function create(
isStrictMode = true; isStrictMode = true;
} }
} }
let container = { let container: Container = {
children: ([]: Array<Instance | TextInstance>), children: ([]: Array<Instance | TextInstance>),
createNodeMock, createNodeMock,
tag: 'CONTAINER', tag: 'CONTAINER',

View File

@ -76,7 +76,7 @@ export function unstable_scheduleCallback<T>(
callback: SchedulerCallback<T>, callback: SchedulerCallback<T>,
options?: {delay?: number}, options?: {delay?: number},
): CallbackNode { ): CallbackNode {
let postTaskPriority; let postTaskPriority: PostTaskPriorityLevel;
switch (priorityLevel) { switch (priorityLevel) {
case ImmediatePriority: case ImmediatePriority:
case UserBlockingPriority: case UserBlockingPriority:

View File

@ -23,8 +23,7 @@ export function useSyncExternalStoreWithSelector<Snapshot, Selection>(
selector: (snapshot: Snapshot) => Selection, selector: (snapshot: Snapshot) => Selection,
isEqual?: (a: Selection, b: Selection) => boolean, isEqual?: (a: Selection, b: Selection) => boolean,
): Selection { ): Selection {
// Use this to track the rendered snapshot. type Inst =
const instRef = useRef<
| { | {
hasValue: true, hasValue: true,
value: Selection, value: Selection,
@ -32,10 +31,11 @@ export function useSyncExternalStoreWithSelector<Snapshot, Selection>(
| { | {
hasValue: false, hasValue: false,
value: null, value: null,
} };
| null,
>(null); // Use this to track the rendered snapshot.
let inst; const instRef = useRef<Inst | null>(null);
let inst: Inst;
if (instRef.current === null) { if (instRef.current === null) {
inst = { inst = {
hasValue: false, hasValue: false,

View File

@ -9298,12 +9298,12 @@ flatted@^3.2.9:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
flow-bin@^0.272: flow-bin@^0.273:
version "0.272.2" version "0.273.1"
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.272.2.tgz#918fc58dc7a99725a83314f453d3e49a56aebdc5" resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.273.1.tgz#18621f169ecbabe3656c56980ebaabc439ee76c1"
integrity sha512-Rf8UG1biRBUGGh6qN7Ua2Y2lJRpR8Pbzby5kfHQ5m5SgjC5eOPw3Qjbrheb9ec5oU4L1gCOXRYbkbpr02PRUBw== integrity sha512-OlJkNCSd+i6z5xDoyGiS+3X5xYQx+vVUY2iUw6cHJR0LK3ttyA1wkiI93OuBALhLhF91KayzGhRSzXHqA75iUw==
flow-remove-types@^2.272: flow-remove-types@^2.273:
version "2.279.0" version "2.279.0"
resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-2.279.0.tgz#3a3388d9158eba0f82c40d80d31d9640b883a3f5" resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-2.279.0.tgz#3a3388d9158eba0f82c40d80d31d9640b883a3f5"
integrity sha512-bPFloMR/A2b/r/sIsf7Ix0LaMicCJNjwhXc4xEEQVzJCIz5u7C7XDaEOXOiqveKlCYK7DcBNn6R01Cbbc9gsYA== integrity sha512-bPFloMR/A2b/r/sIsf7Ix0LaMicCJNjwhXc4xEEQVzJCIz5u7C7XDaEOXOiqveKlCYK7DcBNn6R01Cbbc9gsYA==