@samitouri / QOS-React-2 / commits / e2424f33b3

[flow] enable exact_empty_objects (#25973)

This enables the "exact_empty_objects" setting for Flow which makes empty objects exact instead of building up the type as properties are added in code below. This is in preparation to Flow 191 which makes this the default and removes the config. More about the change in the Flow blog [here](https://medium.com/flow-type/improved-handling-of-the-empty-object-in-flow-ead91887e40c).

Jan Kassens committed Jan 9, 2023 at 17:00 UTC e2424f33b3ad727321fc12e75c5e94838e84c2b5
49 files changed +182 -135
packages/react-client/src/ReactFlightClient.js
+3 -1
@@ -393,7 +393,9 @@ function createElement(
393 // We don't really need to add any of these but keeping them for good measure.
394 // Unfortunately, _store is enumerable in jest matchers so for equality to
395 // work, I need to keep it or make _store non-enumerable in the other file.
396 - element._store = {};
396 + element._store = ({}: {
397 + validated?: boolean,
398 + });
399 Object.defineProperty(element._store, 'validated', {
400 configurable: false,
401 enumerable: false,
packages/react-debug-tools/src/ReactDebugHooks.js
+2 -2
@@ -524,7 +524,7 @@ function buildTree(
524 readHookLog: Array<HookLogEntry>,
525 includeHooksSource: boolean,
526 ): HooksTree {
527 - const rootChildren = [];
527 + const rootChildren: Array<HooksNode> = [];
528 let prevStack = null;
529 let levelChildren = rootChildren;
530 let nativeHookID = 0;
@@ -557,7 +557,7 @@ function buildTree(
557 // The remaining part of the new stack are custom hooks. Push them
558 // to the tree.
559 for (let j = stack.length - commonSteps - 1; j >= 1; j--) {
560 - const children = [];
560 + const children: Array<HooksNode> = [];
561 const stackFrame = stack[j];
562 const levelChild: HooksNode = {
563 id: null,
packages/react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor.js
+1 -1
@@ -170,7 +170,7 @@ function measureStyle(
170 }
171
172 function shallowClone(object: Object): Object {
173 - const cloned = {};
173 + const cloned: {[string]: $FlowFixMe} = {};
174 for (const n in object) {
175 cloned[n] = object[n];
176 }
packages/react-devtools-shared/src/backend/console.js
+4 -4
@@ -79,7 +79,7 @@ const injectedRenderers: Map<
79 > = new Map();
80
81 let targetConsole: Object = console;
82 -let targetConsoleMethods = {};
82 +let targetConsoleMethods: {[string]: $FlowFixMe} = {};
83 for (const method in console) {
84 targetConsoleMethods[method] = console[method];
85 }
@@ -97,7 +97,7 @@ export function dangerous_setTargetConsoleForTesting(
97 ): void {
98 targetConsole = targetConsoleForTesting;
99
100 - targetConsoleMethods = {};
100 + targetConsoleMethods = ({}: {[string]: $FlowFixMe});
101 for (const method in targetConsole) {
102 targetConsoleMethods[method] = console[method];
103 }
@@ -179,7 +179,7 @@ export function patch({
179 return;
180 }
181
182 - const originalConsoleMethods = {};
182 + const originalConsoleMethods: {[string]: $FlowFixMe} = {};
183
184 unpatchFn = () => {
185 for (const method in originalConsoleMethods) {
@@ -318,7 +318,7 @@ export function patchForStrictMode() {
318 return;
319 }
320
321 - const originalConsoleMethods = {};
321 + const originalConsoleMethods: {[string]: $FlowFixMe} = {};
322
323 unpatchForStrictModeFn = () => {
324 for (const method in originalConsoleMethods) {
packages/react-devtools-shared/src/backend/legacy/renderer.js
+3 -3
@@ -785,7 +785,7 @@ export function attach(
785
786 let owner = element._owner;
787 if (owner) {
788 - owners = [];
788 + owners = ([]: Array<SerializedElement>);
789 while (owner != null) {
790 owners.push({
791 displayName: getData(owner).displayName || 'Unknown',
@@ -807,8 +807,8 @@ export function attach(
807 }
808
809 // Not implemented
810 - const errors = [];
811 - const warnings = [];
810 + const errors: Array<[string, number]> = [];
811 + const warnings: Array<[string, number]> = [];
812
813 return {
814 id,
packages/react-devtools-shared/src/backend/legacy/utils.js
+1 -1
@@ -22,7 +22,7 @@ export function decorateMany(
22 source: Object,
23 fns: {[attr: string]: Function, ...},
24 ): Object {
25 - const olds = {};
25 + const olds: {[string]: $FlowFixMe} = {};
26 for (const name in fns) {
27 olds[name] = decorate(source, name, fns[name]);
28 }
packages/react-devtools-shared/src/backend/profilingHooks.js
+1 -1
@@ -52,7 +52,7 @@ let supportsUserTiming =
52 let supportsUserTimingV3 = false;
53 if (supportsUserTiming) {
54 const CHECK_V3_MARK = '__v3';
55 - const markOptions = {};
55 + const markOptions = ({}: {startTime?: number});
56 Object.defineProperty(markOptions, 'startTime', {
57 get: function() {
58 supportsUserTimingV3 = true;
packages/react-devtools-shared/src/backend/renderer.js
+2 -2
@@ -3252,7 +3252,7 @@ export function attach(
3252
3253 let owners = null;
3254 if (_debugOwner) {
3255 - owners = [];
3255 + owners = ([]: Array<SerializedElement>);
3256 let owner: null | Fiber = _debugOwner;
3257 while (owner !== null) {
3258 owners.push(fiberToSerializedElement(owner));
@@ -3265,7 +3265,7 @@ export function attach(
3265
3266 let hooks = null;
3267 if (usesHooks) {
3268 - const originalConsoleMethods = {};
3268 + const originalConsoleMethods: {[string]: $FlowFixMe} = {};
3269
3270 // Temporarily disable all console logging before re-running the hook.
3271 for (const method in console) {
packages/react-devtools-shared/src/backend/utils.js
+2 -2
@@ -20,8 +20,8 @@ export function cleanForBridge(
20 path?: Array<string | number> = [],
21 ): DehydratedData | null {
22 if (data !== null) {
23 - const cleanedPaths = [];
24 - const unserializablePaths = [];
23 + const cleanedPaths: Array<Array<string | number>> = [];
24 + const unserializablePaths: Array<Array<string | number>> = [];
25 const cleanedData = dehydrate(
26 data,
27 cleanedPaths,
packages/react-devtools-shared/src/devtools/utils.js
+1 -1
@@ -198,7 +198,7 @@ const STACK_SOURCE_LOCATION = /([^\s]+) \((.+):(.+):(.+)\)/;
198 export function stackToComponentSources(
199 stack: string,
200 ): Array<[string, ?Stack]> {
201 - const out = [];
201 + const out: Array<[string, ?Stack]> = [];
202 stack
203 .split(STACK_DELIMETER)
204 .slice(1)
packages/react-devtools-shared/src/devtools/views/Components/types.js
+9 -7
@@ -125,14 +125,16 @@ export type InspectedElement = {
125
126 // TODO: Add profiling type
127
128 +type Data =
129 + | string
130 + | Dehydrated
131 + | Unserializable
132 + | Array<Dehydrated>
133 + | Array<Unserializable>
134 + | {[string]: Data};
135 +
136 export type DehydratedData = {
137 cleaned: Array<Array<string | number>>,
130 - data:
131 - | string
132 - | Dehydrated
133 - | Unserializable
134 - | Array<Dehydrated>
135 - | Array<Unserializable>
136 - | {[key: string]: string | Dehydrated | Unserializable, ...},
138 + data: Data,
139 unserializable: Array<Array<string | number>>,
140 };
packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js
+1
@@ -150,6 +150,7 @@ function updateTree(
150
151 // Clone nodes before mutating them so edits don't affect them.
152 const getClonedNode = (id: number): CommitTreeNode => {
153 + // $FlowFixMe[prop-missing] - recommended fix is to use object spread operator
154 const clonedNode = ((Object.assign(
155 {},
156 nodes.get(id),
packages/react-devtools-shared/src/devtools/views/utils.js
+1 -1
@@ -134,7 +134,7 @@ export function serializeDataForCopy(props: Object): string {
134
135 export function serializeHooksForCopy(hooks: HooksTree | null): string {
136 // $FlowFixMe "HooksTree is not an object"
137 - const cloned = Object.assign([], hooks);
137 + const cloned = Object.assign(([]: Array<any>), hooks);
138
139 const queue = [...cloned];
140
packages/react-devtools-shared/src/hook.js
+5 -5
@@ -29,7 +29,7 @@ export function installHook(target: any): DevToolsHook | null {
29 }
30
31 let targetConsole: Object = console;
32 - let targetConsoleMethods = {};
32 + let targetConsoleMethods: {[string]: $FlowFixMe} = {};
33 for (const method in console) {
34 targetConsoleMethods[method] = console[method];
35 }
@@ -39,7 +39,7 @@ export function installHook(target: any): DevToolsHook | null {
39 ): void {
40 targetConsole = targetConsoleForTesting;
41
42 - targetConsoleMethods = {};
42 + targetConsoleMethods = ({}: {[string]: $FlowFixMe});
43 for (const method in targetConsole) {
44 targetConsoleMethods[method] = console[method];
45 }
@@ -250,7 +250,7 @@ export function installHook(target: any): DevToolsHook | null {
250 return;
251 }
252
253 - const originalConsoleMethods = {};
253 + const originalConsoleMethods: {[string]: $FlowFixMe} = {};
254
255 unpatchFn = () => {
256 for (const method in originalConsoleMethods) {
@@ -516,9 +516,9 @@ export function installHook(target: any): DevToolsHook | null {
516 }
517
518 // TODO: More meaningful names for "rendererInterfaces" and "renderers".
519 - const fiberRoots = {};
519 + const fiberRoots: {[RendererID]: Set<mixed>} = {};
520 const rendererInterfaces = new Map();
521 - const listeners = {};
521 + const listeners: {[string]: Array<Handler>} = {};
522 const renderers = new Map();
523
524 const hook: DevToolsHook = {
packages/react-devtools-shared/src/hooks/astUtils.js
+1 -1
@@ -362,7 +362,7 @@ function getPotentialHookDeclarationsFromAST(sourceAST: File): NodePath[] {
362 export function getHookNamesMappingFromAST(
363 sourceAST: File,
364 ): $ReadOnlyArray<{name: string, start: Position}> {
365 - const hookStack = [];
365 + const hookStack: Array<{name: string, start: $FlowFixMe}> = [];
366 const hookNames = [];
367 const pushFrame = (name: string, node: Node) => {
368 const nameInfo = {name, start: {...node.loc.start}};
packages/react-devtools-shared/src/hooks/generateHookMap.js
+1 -1
@@ -63,7 +63,7 @@ export function generateHookMap(sourceAST: File): HookMap {
63 const hookNamesMapping = getHookNamesMappingFromAST(sourceAST);
64 const namesMap: Map<string, number> = new Map();
65 const names = [];
66 - const mappings = [];
66 + const mappings: Array<HookMapLine> = [];
67
68 let currentLine = null;
69 hookNamesMapping.forEach(({name, start}) => {
packages/react-devtools-shared/src/hydration.js
+5 -9
@@ -16,7 +16,7 @@ import {
16 setInObject,
17 } from './utils';
18
19 -import type {DehydratedData} from 'react-devtools-shared/src/devtools/views/Components/types';
19 +import type {DehydratedData} from './devtools/views/Components/types';
20
21 export const meta = {
22 inspectable: (Symbol('inspectable'): symbol),
@@ -124,13 +124,7 @@ export function dehydrate(
124 path: Array<string | number>,
125 isPathAllowed: (path: Array<string | number>) => boolean,
126 level?: number = 0,
127 -):
128 - | string
129 - | Dehydrated
130 - | Unserializable
131 - | Array<Dehydrated>
132 - | Array<Unserializable>
133 - | {[key: string]: string | Dehydrated | Unserializable, ...} {
127 +): $PropertyType<DehydratedData, 'data'> {
128 const type = getDataType(data);
129
130 let isPathAllowedCheck;
@@ -304,7 +298,9 @@ export function dehydrate(
298 if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {
299 return createDehydrated(type, true, data, cleaned, path);
300 } else {
307 - const object = {};
301 + const object: {
302 + [string]: $PropertyType<DehydratedData, 'data'>,
303 + } = {};
304 getAllEnumerableKeys(data).forEach(key => {
305 const name = key.toString();
306 object[name] = dehydrate(
packages/react-devtools-shell/src/app/InspectableElements/CircularReferences.js
+9 -2
@@ -14,8 +14,15 @@ const arrayTwo = [];
14 arrayTwo.push(arrayOne);
15 arrayOne.push(arrayTwo);
16
17 -const objectOne = {};
18 -const objectTwo = {objectOne};
17 +type ObjectOne = {
18 + objectTwo?: ObjectTwo,
19 +};
20 +type ObjectTwo = {
21 + objectOne: ObjectOne,
22 +};
23 +
24 +const objectOne: ObjectOne = {};
25 +const objectTwo: ObjectTwo = {objectOne};
26 objectOne.objectTwo = objectTwo;
27
28 export default function CircularReferences(): React.Node {
packages/react-devtools-shell/src/app/index.js
+1 -1
@@ -33,7 +33,7 @@ ignoreErrors([
33 ignoreWarnings(['Warning: componentWillReceiveProps has been renamed']);
34 ignoreLogs([]);
35
36 -const unmountFunctions = [];
36 +const unmountFunctions: Array<() => void | boolean> = [];
37
38 function createContainer() {
39 const container = document.createElement('div');
packages/react-devtools-timeline/src/TimelineSearchContext.js
+1 -1
@@ -40,7 +40,7 @@ type Action =
40
41 type Dispatch = (action: Action) => void;
42
43 -const EMPTY_ARRAY = [];
43 +const EMPTY_ARRAY: Array<ReactComponentMeasure> = [];
44
45 function reducer(state: State, action: Action): State {
46 let {searchIndex, searchRegExp, searchResults, searchText} = state;
packages/react-dom-bindings/src/client/ReactDOMComponent.js
+3 -3
@@ -672,7 +672,7 @@ export function diffProperties(
672 for (styleName in lastStyle) {
673 if (lastStyle.hasOwnProperty(styleName)) {
674 if (!styleUpdates) {
675 - styleUpdates = {};
675 + styleUpdates = ({}: {[string]: $FlowFixMe});
676 }
677 styleUpdates[styleName] = '';
678 }
@@ -725,7 +725,7 @@ export function diffProperties(
725 (!nextProp || !nextProp.hasOwnProperty(styleName))
726 ) {
727 if (!styleUpdates) {
728 - styleUpdates = {};
728 + styleUpdates = ({}: {[string]: string});
729 }
730 styleUpdates[styleName] = '';
731 }
@@ -737,7 +737,7 @@ export function diffProperties(
737 lastProp[styleName] !== nextProp[styleName]
738 ) {
739 if (!styleUpdates) {
740 - styleUpdates = {};
740 + styleUpdates = ({}: {[string]: $FlowFixMe});
741 }
742 styleUpdates[styleName] = nextProp[styleName];
743 }
packages/react-dom-bindings/src/client/ReactDOMFloatClient.js
+6 -1
@@ -792,6 +792,7 @@ export function getResource(
792 function preloadPropsFromRawProps(
793 rawBorrowedProps: PreloadQualifyingProps,
794 ): PreloadProps {
795 + // $FlowFixMe[prop-missing] - recommended fix is to use object spread operator
796 return Object.assign({}, rawBorrowedProps);
797 }
798
@@ -805,6 +806,7 @@ function titlePropsFromRawProps(
806 }
807
808 function stylePropsFromRawProps(rawProps: StyleQualifyingProps): StyleProps {
809 + // $FlowFixMe[prop-missing] - recommended fix is to use object spread operator
810 const props: StyleProps = Object.assign({}, rawProps);
811 props['data-precedence'] = rawProps.precedence;
812 props.precedence = null;
@@ -813,6 +815,7 @@ function stylePropsFromRawProps(rawProps: StyleQualifyingProps): StyleProps {
815 }
816
817 function scriptPropsFromRawProps(rawProps: ScriptQualifyingProps): ScriptProps {
818 + // $FlowFixMe[prop-missing] - recommended fix is to use object spread operator
819 const props: ScriptProps = Object.assign({}, rawProps);
820 return props;
821 }
@@ -1318,7 +1321,9 @@ function acquireScriptResource(resource: ScriptResource): Instance {
1321 }
1322
1323 function attachLoadListeners(instance: Instance, resource: StyleResource) {
1321 - const listeners = {};
1324 + const listeners: {
1325 + [string]: () => mixed,
1326 + } = {};
1327 listeners.load = onResourceLoad.bind(
1328 null,
1329 instance,
packages/react-dom-bindings/src/client/ReactDOMSelect.js
+1 -1
@@ -77,7 +77,7 @@ function updateOptions(
77
78 if (multiple) {
79 const selectedValues = (propValue: Array<string>);
80 - const selectedValue = {};
80 + const selectedValue: {[string]: boolean} = {};
81 for (let i = 0; i < selectedValues.length; i++) {
82 // Prefix to avoid chaos with special keys.
83 selectedValue['$' + selectedValues[i]] = true;
packages/react-dom-bindings/src/client/validateDOMNesting.js
+1 -1
@@ -434,7 +434,7 @@ if (__DEV__) {
434 return null;
435 };
436
437 - const didWarn = {};
437 + const didWarn: {[string]: boolean} = {};
438
439 validateDOMNesting = function(
440 childTag: ?string,
packages/react-dom-bindings/src/events/checkPassiveEvents.js
+3 -1
@@ -15,7 +15,9 @@ export let passiveBrowserEventsSupported: boolean = false;
15 // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support
16 if (canUseDOM) {
17 try {
18 - const options = {};
18 + const options: {
19 + passive?: void,
20 + } = {};
21 Object.defineProperty(options, 'passive', {
22 get: function() {
23 passiveBrowserEventsSupported = true;
packages/react-dom-bindings/src/server/ReactDOMServerFormatConfig.js
+3 -3
@@ -191,7 +191,7 @@ export function createResponseState(
191 : stringToPrecomputedChunk(
192 '<script nonce="' + escapeTextForBrowser(nonce) + '">',
193 );
194 - const bootstrapChunks = [];
194 + const bootstrapChunks: Array<Chunk | PrecomputedChunk> = [];
195 let externalRuntimeDesc = null;
196 let streamingFormat = ScriptStreamingFormat;
197 if (bootstrapScriptContent !== undefined) {
@@ -2777,7 +2777,7 @@ export function writeInitialResources(
2777 }
2778 }
2779
2780 - const target = [];
2780 + const target: Array<Chunk | PrecomputedChunk> = [];
2781
2782 const {
2783 charset,
@@ -2902,7 +2902,7 @@ export function writeImmediateResources(
2902 }
2903 }
2904
2905 - const target = [];
2905 + const target: Array<Chunk | PrecomputedChunk> = [];
2906
2907 const {
2908 charset,
packages/react-dom-bindings/src/shared/DOMProperty.js
+3 -3
@@ -70,8 +70,8 @@ export const VALID_ATTRIBUTE_NAME_REGEX: RegExp = new RegExp(
70 '^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$',
71 );
72
73 -const illegalAttributeNameCache = {};
74 -const validatedAttributeNameCache = {};
73 +const illegalAttributeNameCache: {[string]: boolean} = {};
74 +const validatedAttributeNameCache: {[string]: boolean} = {};
75
76 export function isAttributeNameSafe(attributeName: string): boolean {
77 if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) {
@@ -239,7 +239,7 @@ function PropertyInfoRecord(
239 // When adding attributes to this list, be sure to also add them to
240 // the `possibleStandardNames` module to ensure casing and incorrect
241 // name warnings.
242 -const properties = {};
242 +const properties: {[string]: $FlowFixMe} = {};
243
244 // These props are reserved by React. They shouldn't be written to the DOM.
245 const reservedProps = [
packages/react-dom-bindings/src/shared/ReactDOMResourceValidation.js
+34 -19
@@ -108,7 +108,7 @@ export function validatePreloadResourceDifference(
108 let extraProps = null;
109 let differentProps = null;
110 if (originalProps.media != null && latestProps.media == null) {
111 - missingProps = missingProps || {};
111 + missingProps = missingProps || ({}: {[string]: $FlowFixMe});
112 missingProps.media = originalProps.media;
113 }
114
@@ -118,10 +118,12 @@ export function validatePreloadResourceDifference(
118
119 if (propValue != null && propValue !== originalValue) {
120 if (originalValue == null) {
121 - extraProps = extraProps || {};
121 + extraProps = extraProps || ({}: {[string]: $FlowFixMe});
122 extraProps[propName] = propValue;
123 } else {
124 - differentProps = differentProps || {};
124 + differentProps =
125 + differentProps ||
126 + ({}: {[string]: {latest: $FlowFixMe, original: $FlowFixMe}});
127 differentProps[propName] = {
128 original: originalValue,
129 latest: propValue,
@@ -166,7 +168,7 @@ export function validateStyleResourceDifference(
168 let extraProps = null;
169 let differentProps = null;
170 if (originalProps.media != null && latestProps.media == null) {
169 - missingProps = missingProps || {};
171 + missingProps = missingProps || ({}: {[string]: $FlowFixMe});
172 missingProps.media = originalProps.media;
173 }
174
@@ -177,10 +179,12 @@ export function validateStyleResourceDifference(
179 if (propValue != null && propValue !== originalValue) {
180 propName = propName === 'data-precedence' ? 'precedence' : propName;
181 if (originalValue == null) {
180 - extraProps = extraProps || {};
182 + extraProps = extraProps || ({}: {[string]: $FlowFixMe});
183 extraProps[propName] = propValue;
184 } else {
183 - differentProps = differentProps || {};
185 + differentProps =
186 + differentProps ||
187 + ({}: {[string]: {latest: $FlowFixMe, original: $FlowFixMe}});
188 differentProps[propName] = {
189 original: originalValue,
190 latest: propValue,
@@ -229,10 +233,12 @@ export function validateScriptResourceDifference(
233
234 if (propValue != null && propValue !== originalValue) {
235 if (originalValue == null) {
232 - extraProps = extraProps || {};
236 + extraProps = extraProps || ({}: {[string]: $FlowFixMe});
237 extraProps[propName] = propValue;
238 } else {
235 - differentProps = differentProps || {};
239 + differentProps =
240 + differentProps ||
241 + ({}: {[string]: {latest: $FlowFixMe, original: $FlowFixMe}});
242 differentProps[propName] = {
243 original: originalValue,
244 latest: propValue,
@@ -304,13 +310,15 @@ export function validateStyleAndHintProps(
310 !(preloadValue == null && styleValue == null)
311 ) {
312 if (styleValue == null) {
307 - missingProps = missingProps || {};
313 + missingProps = missingProps || ({}: {[string]: $FlowFixMe});
314 missingProps[propName] = preloadValue;
315 } else if (preloadValue == null) {
310 - extraProps = extraProps || {};
316 + extraProps = extraProps || ({}: {[string]: $FlowFixMe});
317 extraProps[propName] = styleValue;
318 } else {
313 - differentProps = differentProps || {};
319 + differentProps =
320 + differentProps ||
321 + ({}: {[string]: {latest: $FlowFixMe, original: $FlowFixMe}});
322 differentProps[propName] = {
323 original: preloadValue,
324 latest: styleValue,
@@ -383,13 +391,15 @@ export function validateScriptAndHintProps(
391 !(preloadValue == null && scriptValue == null)
392 ) {
393 if (scriptValue == null) {
386 - missingProps = missingProps || {};
394 + missingProps = missingProps || ({}: {[string]: $FlowFixMe});
395 missingProps[propName] = preloadValue;
396 } else if (preloadValue == null) {
389 - extraProps = extraProps || {};
397 + extraProps = extraProps || ({}: {[string]: $FlowFixMe});
398 extraProps[propName] = scriptValue;
399 } else {
392 - differentProps = differentProps || {};
400 + differentProps =
401 + differentProps ||
402 + ({}: {[string]: {latest: $FlowFixMe, original: $FlowFixMe}});
403 differentProps[propName] = {
404 original: preloadValue,
405 latest: scriptValue,
@@ -419,8 +429,8 @@ function warnDifferentProps(
429 urlPropKey: string,
430 originalName: string,
431 latestName: string,
422 - extraProps: ?{[string]: any},
423 - missingProps: ?{[string]: any},
432 + extraProps: ?{[string]: $FlowFixMe},
433 + missingProps: ?{[string]: $FlowFixMe},
434 differentProps: ?{[string]: {original: any, latest: any}},
435 ): void {
436 if (__DEV__) {
@@ -510,13 +520,15 @@ export function validateURLKeyedUpdatedProps(
520 !(pendingValue == null && currentValue == null)
521 ) {
522 if (pendingValue == null) {
513 - missingProps = missingProps || {};
523 + missingProps = missingProps || ({}: {[string]: mixed});
524 missingProps[propName] = currentValue;
525 } else if (currentValue == null) {
516 - extraProps = extraProps || {};
526 + extraProps = extraProps || ({}: {[string]: mixed});
527 extraProps[propName] = pendingValue;
528 } else {
519 - differentProps = differentProps || {};
529 + differentProps =
530 + differentProps ||
531 + ({}: {[string]: {latest: mixed, original: mixed}});
532 differentProps[propName] = {
533 original: currentValue,
534 latest: pendingValue,
@@ -534,16 +546,19 @@ export function validateURLKeyedUpdatedProps(
546 let comparisonStatement = '';
547 if (missingProps !== null && typeof missingProps === 'object') {
548 for (const propName in missingProps) {
549 + // $FlowFixMe[incompatible-type]
550 comparisonStatement += `\n ${propName}: missing or null in latest props, "${missingProps[propName]}" in original props`;
551 }
552 }
553 if (extraProps !== null && typeof extraProps === 'object') {
554 for (const propName in extraProps) {
555 + // $FlowFixMe[incompatible-type]
556 comparisonStatement += `\n ${propName}: "${extraProps[propName]}" in latest props, missing or null in original props`;
557 }
558 }
559 if (differentProps !== null && typeof differentProps === 'object') {
560 for (const propName in differentProps) {
561 + // $FlowFixMe[incompatible-type]
562 comparisonStatement += `\n ${propName}: "${differentProps[propName].latest}" in latest props, "${differentProps[propName].original}" in original props`;
563 }
564 }
packages/react-native-renderer/src/ReactNativeAttributePayload.js
+11 -5
@@ -30,7 +30,7 @@ const emptyObject = {};
30 type NestedNode = Array<NestedNode> | Object;
31
32 // Tracks removed keys
33 -let removedKeys = null;
33 +let removedKeys: {[string]: boolean} | null = null;
34 let removedKeyCount = 0;
35
36 const deepDifferOptions = {
@@ -345,7 +345,9 @@ function diffProperties(
345 // case: !Object is the default case
346 if (defaultDiffer(prevProp, nextProp)) {
347 // a normal leaf has changed
348 - (updatePayload || (updatePayload = {}))[propKey] = nextProp;
348 + (updatePayload || (updatePayload = ({}: {[string]: $FlowFixMe})))[
349 + propKey
350 + ] = nextProp;
351 }
352 } else if (
353 typeof attributeConfig.diff === 'function' ||
@@ -363,7 +365,9 @@ function diffProperties(
365 ? // $FlowFixMe[incompatible-use] found when upgrading Flow
366 attributeConfig.process(nextProp)
367 : nextProp;
366 - (updatePayload || (updatePayload = {}))[propKey] = nextValue;
368 + (updatePayload || (updatePayload = ({}: {[string]: $FlowFixMe})))[
369 + propKey
370 + ] = nextValue;
371 }
372 } else {
373 // default: fallthrough case when nested properties are defined
@@ -417,9 +421,11 @@ function diffProperties(
421 ) {
422 // case: CustomAttributeConfiguration | !Object
423 // Flag the leaf property for removal by sending a sentinel.
420 - (updatePayload || (updatePayload = {}))[propKey] = null;
424 + (updatePayload || (updatePayload = ({}: {[string]: $FlowFixMe})))[
425 + propKey
426 + ] = null;
427 if (!removedKeys) {
422 - removedKeys = {};
428 + removedKeys = ({}: {[string]: boolean});
429 }
430 if (!removedKeys[propKey]) {
431 removedKeys[propKey] = true;
packages/react-reconciler/src/ReactChildFiber.js
+3 -3
@@ -54,15 +54,15 @@ let warnForMissingKey = (child: mixed, returnFiber: Fiber) => {};
54 if (__DEV__) {
55 didWarnAboutMaps = false;
56 didWarnAboutGenerators = false;
57 - didWarnAboutStringRefs = {};
57 + didWarnAboutStringRefs = ({}: {[string]: boolean});
58
59 /**
60 * Warn if there's no key explicitly set on dynamic arrays of children or
61 * object keys are not valid. This allows us to keep track of children between
62 * updates.
63 */
64 - ownerHasKeyUseWarning = {};
65 - ownerHasFunctionTypeWarning = {};
64 + ownerHasKeyUseWarning = ({}: {[string]: boolean});
65 + ownerHasFunctionTypeWarning = ({}: {[string]: boolean});
66
67 warnForMissingKey = (child: mixed, returnFiber: Fiber) => {
68 if (child === null || typeof child !== 'object') {
packages/react-reconciler/src/ReactFiberBeginWork.js
+8 -8
@@ -303,15 +303,15 @@ let didWarnAboutTailOptions;
303 let didWarnAboutDefaultPropsOnFunctionComponent;
304
305 if (__DEV__) {
306 - didWarnAboutBadClass = {};
307 - didWarnAboutModulePatternComponent = {};
308 - didWarnAboutContextTypeOnFunctionComponent = {};
309 - didWarnAboutGetDerivedStateOnFunctionComponent = {};
310 - didWarnAboutFunctionRefs = {};
306 + didWarnAboutBadClass = ({}: {[string]: boolean});
307 + didWarnAboutModulePatternComponent = ({}: {[string]: boolean});
308 + didWarnAboutContextTypeOnFunctionComponent = ({}: {[string]: boolean});
309 + didWarnAboutGetDerivedStateOnFunctionComponent = ({}: {[string]: boolean});
310 + didWarnAboutFunctionRefs = ({}: {[string]: boolean});
311 didWarnAboutReassigningProps = false;
312 - didWarnAboutRevealOrder = {};
313 - didWarnAboutTailOptions = {};
314 - didWarnAboutDefaultPropsOnFunctionComponent = {};
312 + didWarnAboutRevealOrder = ({}: {[empty]: boolean});
313 + didWarnAboutTailOptions = ({}: {[string]: boolean});
314 + didWarnAboutDefaultPropsOnFunctionComponent = ({}: {[string]: boolean});
315 }
316
317 export function reconcileChildren(
packages/react-reconciler/src/ReactFiberClassComponent.js
+4 -2
@@ -77,7 +77,9 @@ import {
77 setIsStrictModeForDevtools,
78 } from './ReactFiberDevToolsHook';
79
80 -const fakeInternalInstance = {};
80 +const fakeInternalInstance: {
81 + _processChildContext?: () => empty,
82 +} = {};
83
84 let didWarnAboutStateAssignmentForComponent;
85 let didWarnAboutUninitializedState;
@@ -139,7 +141,7 @@ if (__DEV__) {
141 // exception.
142 Object.defineProperty(fakeInternalInstance, '_processChildContext', {
143 enumerable: false,
142 - value: function() {
144 + value: function(): empty {
145 throw new Error(
146 '_processChildContext is not available in React 16+. This likely ' +
147 'means you have multiple copies of React and are attempting to nest ' +
packages/react-reconciler/src/ReactFiberContext.js
+2 -2
@@ -21,7 +21,7 @@ import {createCursor, push, pop} from './ReactFiberStack';
21 let warnedAboutMissingGetChildContext;
22
23 if (__DEV__) {
24 - warnedAboutMissingGetChildContext = {};
24 + warnedAboutMissingGetChildContext = ({}: {[string]: boolean});
25 }
26
27 // $FlowFixMe[incompatible-exact]
@@ -98,7 +98,7 @@ function getMaskedContext(
98 return instance.__reactInternalMemoizedMaskedChildContext;
99 }
100
101 - const context = {};
101 + const context: {[string]: $FlowFixMe} = {};
102 for (const key in contextTypes) {
103 context[key] = unmaskedContext[key];
104 }
packages/react-reconciler/src/ReactFiberHooks.js
+3 -2
@@ -144,6 +144,7 @@ import {
144 createThenableState,
145 } from './ReactFiberThenable';
146 import type {ThenableState} from './ReactFiberThenable';
147 +import type {BatchConfigTransition} from './ReactFiberTracingMarkerComponent';
148
149 const {ReactCurrentDispatcher, ReactCurrentBatchConfig} = ReactSharedInternals;
150
@@ -2383,7 +2384,7 @@ function startTransition(
2384 setPending(true);
2385
2386 const prevTransition = ReactCurrentBatchConfig.transition;
2386 - ReactCurrentBatchConfig.transition = {};
2387 + ReactCurrentBatchConfig.transition = ({}: BatchConfigTransition);
2388 const currentTransition = ReactCurrentBatchConfig.transition;
2389
2390 if (enableTransitionTracing) {
@@ -2408,6 +2409,7 @@ function startTransition(
2409 if (__DEV__) {
2410 if (prevTransition === null && currentTransition._updatedFibers) {
2411 const updatedFibersCount = currentTransition._updatedFibers.size;
2412 + currentTransition._updatedFibers.clear();
2413 if (updatedFibersCount > 10) {
2414 console.warn(
2415 'Detected a large number of updates inside startTransition. ' +
@@ -2415,7 +2417,6 @@ function startTransition(
2417 'Otherwise concurrent mode guarantees are off the table.',
2418 );
2419 }
2418 - currentTransition._updatedFibers.clear();
2420 }
2421 }
2422 }
packages/react-reconciler/src/ReactFiberReconciler.js
+1 -1
@@ -136,7 +136,7 @@ let didWarnAboutFindNodeInStrictMode;
136
137 if (__DEV__) {
138 didWarnAboutNestedUpdates = false;
139 - didWarnAboutFindNodeInStrictMode = {};
139 + didWarnAboutFindNodeInStrictMode = ({}: {[string]: boolean});
140 }
141
142 function getContextForSubtree(
packages/react-reconciler/src/ReactFiberScope.js
+2 -2
@@ -149,7 +149,7 @@ function DO_NOT_USE_queryAllNodes(
149 return null;
150 }
151 const child = currentFiber.child;
152 - const scopedNodes = [];
152 + const scopedNodes: Array<any> = [];
153 if (child !== null) {
154 collectScopedNodesFromChildren(child, fn, scopedNodes);
155 }
@@ -191,7 +191,7 @@ function getChildContextValues<T>(
191 return [];
192 }
193 const child = currentFiber.child;
194 - const childContextValues = [];
194 + const childContextValues: Array<T> = [];
195 if (child !== null) {
196 collectNearestChildContextValues(child, context, childContextValues);
197 }
packages/react-server-dom-webpack/src/ReactFlightWebpackNodeLoader.js
+1 -1
@@ -237,7 +237,7 @@ export async function transformSource(
237 throw new Error('Expected source to have been transformed to a string.');
238 }
239
240 - const names = [];
240 + const names: Array<string> = [];
241 await parseExportNamesInto(
242 transformedSource,
243 names,
packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js
+3 -3
@@ -17,9 +17,9 @@ module.exports = function register() {
17
18 const proxyHandlers = {
19 get: function(
20 - target: {[string]: any},
20 + target: {[string]: $FlowFixMe},
21 name: string,
22 - receiver: Proxy<{[string]: any}>,
22 + receiver: Proxy<{[string]: $FlowFixMe}>,
23 ) {
24 switch (name) {
25 // These names are read by the Flight runtime if you end up using the exports object.
@@ -87,7 +87,7 @@ module.exports = function register() {
87 }
88 return cachedReference;
89 },
90 - getPrototypeOf(target: {[string]: any}) {
90 + getPrototypeOf(target: {[string]: $FlowFixMe}) {
91 // Pretend to be a Promise in case anyone asks.
92 return PROMISE_PROTOTYPE;
93 },
packages/react-server-dom-webpack/src/ReactFlightWebpackPlugin.js
+10 -4
@@ -215,14 +215,18 @@ export default class ReactFlightWebpackPlugin {
215 return;
216 }
217
218 - const json = {};
218 + const json: {
219 + [string]: {
220 + [string]: {chunks: $FlowFixMe, id: $FlowFixMe, name: string},
221 + },
222 + } = {};
223 compilation.chunkGroups.forEach(function(chunkGroup) {
224 const chunkIds = chunkGroup.chunks.map(function(c) {
225 return c.id;
226 });
227
228 // $FlowFixMe[missing-local-annot]
225 - function recordModule(id: any, module) {
229 + function recordModule(id: $FlowFixMe, module) {
230 // TODO: Hook into deps instead of the target module.
231 // That way we know by the type of dep whether to include.
232 // It also resolves conflicts when the same module is in multiple chunks.
@@ -235,7 +239,9 @@ export default class ReactFlightWebpackPlugin {
239 .getExportsInfo(module)
240 .getProvidedExports();
241
238 - const moduleExports = {};
242 + const moduleExports: {
243 + [string]: {chunks: $FlowFixMe, id: $FlowFixMe, name: string},
244 + } = {};
245 ['', '*']
246 .concat(
247 Array.isArray(moduleProvidedExports)
@@ -352,7 +358,7 @@ export default class ReactFlightWebpackPlugin {
358 result: $ReadOnlyArray<$ReadOnlyArray<ClientReferenceDependency>>,
359 ): void => {
360 if (err) return callback(err);
355 - const flat = [];
361 + const flat: Array<any> = [];
362 for (let i = 0; i < result.length; i++) {
363 // $FlowFixMe[method-unbinding]
364 flat.push.apply(flat, result[i]);
packages/react-server/src/ReactFizzClassComponent.js
+2 -2
@@ -20,8 +20,8 @@ import {REACT_CONTEXT_TYPE, REACT_PROVIDER_TYPE} from 'shared/ReactSymbols';
20 import assign from 'shared/assign';
21 import isArray from 'shared/isArray';
22
23 -const didWarnAboutNoopUpdateForComponent = {};
24 -const didWarnAboutDeprecatedWillMount = {};
23 +const didWarnAboutNoopUpdateForComponent: {[string]: boolean} = {};
24 +const didWarnAboutDeprecatedWillMount: {[string]: boolean} = {};
25
26 let didWarnAboutUninitializedState;
27 let didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate;
packages/react-server/src/ReactFizzContext.js
+2 -2
@@ -14,7 +14,7 @@ import checkPropTypes from 'shared/checkPropTypes';
14 let warnedAboutMissingGetChildContext;
15
16 if (__DEV__) {
17 - warnedAboutMissingGetChildContext = {};
17 + warnedAboutMissingGetChildContext = ({}: {[string]: boolean});
18 }
19
20 // $FlowFixMe[incompatible-exact]
@@ -32,7 +32,7 @@ export function getMaskedContext(type: any, unmaskedContext: Object): Object {
32 return emptyContextObject;
33 }
34
35 - const context = {};
35 + const context: {[string]: $FlowFixMe} = {};
36 for (const key in contextTypes) {
37 context[key] = unmaskedContext[key];
38 }
packages/react-server/src/ReactFizzServer.js
+10 -10
@@ -295,11 +295,11 @@ export function createRequest(
295 completedRootSegment: null,
296 abortableTasks: abortSet,
297 pingedTasks: pingedTasks,
298 - clientRenderedBoundaries: [],
299 - completedBoundaries: [],
300 - partialBoundaries: [],
301 - preamble: [],
302 - postamble: [],
298 + clientRenderedBoundaries: ([]: Array<SuspenseBoundary>),
299 + completedBoundaries: ([]: Array<SuspenseBoundary>),
300 + partialBoundaries: ([]: Array<SuspenseBoundary>),
301 + preamble: ([]: Array<Chunk | PrecomputedChunk>),
302 + postamble: ([]: Array<Chunk | PrecomputedChunk>),
303 onError: onError === undefined ? defaultErrorHandler : onError,
304 onAllReady: onAllReady === undefined ? noop : onAllReady,
305 onShellReady: onShellReady === undefined ? noop : onShellReady,
@@ -795,12 +795,12 @@ function renderClassComponent(
795 popComponentStackInDEV(task);
796 }
797
798 -const didWarnAboutBadClass = {};
799 -const didWarnAboutModulePatternComponent = {};
800 -const didWarnAboutContextTypeOnFunctionComponent = {};
801 -const didWarnAboutGetDerivedStateOnFunctionComponent = {};
798 +const didWarnAboutBadClass: {[string]: boolean} = {};
799 +const didWarnAboutModulePatternComponent: {[string]: boolean} = {};
800 +const didWarnAboutContextTypeOnFunctionComponent: {[string]: boolean} = {};
801 +const didWarnAboutGetDerivedStateOnFunctionComponent: {[string]: boolean} = {};
802 let didWarnAboutReassigningProps = false;
803 -const didWarnAboutDefaultPropsOnFunctionComponent = {};
803 +const didWarnAboutDefaultPropsOnFunctionComponent: {[string]: boolean} = {};
804 let didWarnAboutGenerators = false;
805 let didWarnAboutMaps = false;
806 let hasWarnedAboutUsingContextAsConsumer = false;
packages/react-server/src/ReactFlightServer.js
+3 -3
@@ -184,9 +184,9 @@ export function createRequest(
184 pendingChunks: 0,
185 abortableTasks: abortSet,
186 pingedTasks: pingedTasks,
187 - completedModuleChunks: [],
188 - completedJSONChunks: [],
189 - completedErrorChunks: [],
187 + completedModuleChunks: ([]: Array<Chunk>),
188 + completedJSONChunks: ([]: Array<Chunk>),
189 + completedErrorChunks: ([]: Array<Chunk>),
190 writtenSymbols: new Map(),
191 writtenModules: new Map(),
192 writtenProviders: new Map(),
packages/react/src/ReactChildren.js
+1 -1
@@ -249,7 +249,7 @@ function mapChildren(
249 if (children == null) {
250 return children;
251 }
252 - const result = [];
252 + const result: Array<React$Node> = [];
253 let count = 0;
254 mapIntoArray(children, result, '', '', function(child) {
255 return func.call(context, child, count++);
packages/react/src/ReactStartTransition.js
+3 -2
@@ -6,6 +6,7 @@
6 *
7 * @flow
8 */
9 +import type {BatchConfigTransition} from 'react-reconciler/src/ReactFiberTracingMarkerComponent';
10 import type {StartTransitionOptions} from 'shared/ReactTypes';
11
12 import ReactCurrentBatchConfig from './ReactCurrentBatchConfig';
@@ -16,7 +17,7 @@ export function startTransition(
17 options?: StartTransitionOptions,
18 ) {
19 const prevTransition = ReactCurrentBatchConfig.transition;
19 - ReactCurrentBatchConfig.transition = {};
20 + ReactCurrentBatchConfig.transition = ({}: BatchConfigTransition);
21 const currentTransition = ReactCurrentBatchConfig.transition;
22
23 if (__DEV__) {
@@ -40,6 +41,7 @@ export function startTransition(
41 if (__DEV__) {
42 if (prevTransition === null && currentTransition._updatedFibers) {
43 const updatedFibersCount = currentTransition._updatedFibers.size;
44 + currentTransition._updatedFibers.clear();
45 if (updatedFibersCount > 10) {
46 console.warn(
47 'Detected a large number of updates inside startTransition. ' +
@@ -47,7 +49,6 @@ export function startTransition(
49 'Otherwise concurrent mode guarantees are off the table.',
50 );
51 }
50 - currentTransition._updatedFibers.clear();
52 }
53 }
54 }
packages/scheduler/src/forks/SchedulerMock.js
+1 -1
@@ -66,7 +66,7 @@ var LOW_PRIORITY_TIMEOUT = 10000;
66 var IDLE_PRIORITY_TIMEOUT = maxSigned31BitInt;
67
68 // Tasks are stored on a min heap
69 -var taskQueue = [];
69 +var taskQueue: Array<Task> = [];
70 var timerQueue: Array<Task> = [];
71
72 // Incrementing id counter. Used to maintain insertion order.
packages/shared/checkPropTypes.js
+1 -1
@@ -7,7 +7,7 @@
7 * @flow
8 */
9
10 -const loggedTypeFailures = {};
10 +const loggedTypeFailures: {[string]: boolean} = {};
11
12 import {describeUnknownElementTypeFrameInDEV} from 'shared/ReactComponentStackFrame';
13
scripts/error-codes/invertObject.js
+2 -2
@@ -16,8 +16,8 @@
16 * into
17 * { 0: 'MUCH ERROR', 1: 'SUCH WRONG' }
18 */
19 -function invertObject(targetObj /* : ErrorMap */) /* : ErrorMap */ {
20 - const result = {};
19 +function invertObject(targetObj /*: ErrorMap */) /*: ErrorMap */ {
20 + const result /*: {[string]: string} */ = {};
21 const mapKeys = Object.keys(targetObj);
22
23 // eslint-disable-next-line no-for-of-loops/no-for-of-loops
scripts/flow/config/flowconfig
+1
@@ -44,6 +44,7 @@ untyped-type-import=error
44 exact_by_default=true
45 munge_underscores=false
46 enforce_local_inference_annotations=true
47 +exact_empty_objects=true
48
49 # Substituted by createFlowConfig.js:
50 %REACT_RENDERER_FLOW_OPTIONS%