[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%