Reland Remove redundant initial of isArray (#21188)
* Remove redundant initial of isArray (#21163) * Reapply prettier * Type the isArray function with refinement support This ensures that an argument gets refined just like it does if isArray is used directly. I'm not sure how to express with just a direct reference so I added a function wrapper and confirmed that this does get inlined properly by closure compiler. * A few more * Rename unit test to internal This is not testing a bundle. Co-authored-by: Behnam Mohammadi <itten@live.com>
Sebastian Markbåge committed
Apr 7, 2021 at 10:57 UTC
172e89b4bf0ec5ee5738af0156d90b0deef4d494
38 files changed
+141
-97
packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js
+6
-7
@@ -145,6 +145,8 @@ export default {
145
componentScope = currentScope;
146
}
147
148
+ const isArray = Array.isArray;
149
+
150
// Next we'll define a few helpers that helps us
151
// tell if some values don't have to be declared as deps.
152
@@ -157,7 +159,7 @@ export default {
159
// ^^^ true for this reference
160
// False for everything else.
161
function isStableKnownHookValue(resolved) {
160
- if (!Array.isArray(resolved.defs)) {
162
+ if (!isArray(resolved.defs)) {
163
return false;
164
}
165
const def = resolved.defs[0];
@@ -226,7 +228,7 @@ export default {
228
if (
229
id.type === 'ArrayPattern' &&
230
id.elements.length === 2 &&
229
- Array.isArray(resolved.identifiers)
231
+ isArray(resolved.identifiers)
232
) {
233
// Is second tuple value the same reference we're checking?
234
if (id.elements[1] === resolved.identifiers[0]) {
@@ -253,10 +255,7 @@ export default {
255
}
256
}
257
} else if (name === 'useTransition') {
256
- if (
257
- id.type === 'ArrayPattern' &&
258
- Array.isArray(resolved.identifiers)
259
- ) {
258
+ if (id.type === 'ArrayPattern' && isArray(resolved.identifiers)) {
259
// Is first tuple value the same reference we're checking?
260
if (id.elements[0] === resolved.identifiers[0]) {
261
// Setter is stable.
@@ -270,7 +269,7 @@ export default {
269
270
// Some are just functions that don't reference anything dynamic.
271
function isFunctionWithoutCapturedValues(resolved) {
273
- if (!Array.isArray(resolved.defs)) {
272
+ if (!isArray(resolved.defs)) {
273
return false;
274
}
275
const def = resolved.defs[0];
packages/jest-react/src/JestReact.js
+2
-1
@@ -8,6 +8,7 @@
8
import {REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE} from 'shared/ReactSymbols';
9
10
import invariant from 'shared/invariant';
11
+import isArray from 'shared/isArray';
12
13
function captureAssertion(fn) {
14
// Trick to use a Jest matcher inside another Jest matcher. `fn` contains an
@@ -42,7 +43,7 @@ export function unstable_toMatchRenderedOutput(root, expectedJSX) {
43
let actualJSX;
44
if (actualJSON === null || typeof actualJSON === 'string') {
45
actualJSX = actualJSON;
45
- } else if (Array.isArray(actualJSON)) {
46
+ } else if (isArray(actualJSON)) {
47
if (actualJSON.length === 0) {
48
actualJSX = null;
49
} else if (actualJSON.length === 1) {
packages/react-devtools-shared/src/backend/renderer.js
+2
-1
@@ -105,6 +105,7 @@ import type {
105
ElementType,
106
} from 'react-devtools-shared/src/types';
107
import is from 'shared/objectIs';
108
+import isArray from 'shared/isArray';
109
110
type getDisplayNameForFiberType = (fiber: Fiber) => string | null;
111
type getTypeSymbolType = (type: any) => Symbol | number;
@@ -1137,7 +1138,7 @@ export function attach(
1138
memoizedState.hasOwnProperty('create') &&
1139
memoizedState.hasOwnProperty('destroy') &&
1140
memoizedState.hasOwnProperty('deps') &&
1140
- (memoizedState.deps === null || Array.isArray(memoizedState.deps)) &&
1141
+ (memoizedState.deps === null || isArray(memoizedState.deps)) &&
1142
memoizedState.hasOwnProperty('next')
1143
);
1144
}
packages/react-devtools-shared/src/backend/utils.js
+6
-5
@@ -9,6 +9,7 @@
9
10
import {copy} from 'clipboard-js';
11
import {dehydrate} from '../hydration';
12
+import isArray from 'shared/isArray';
13
14
import type {DehydratedData} from 'react-devtools-shared/src/devtools/views/Components/types';
15
@@ -61,9 +62,9 @@ export function copyWithDelete(
62
index: number = 0,
63
): Object | Array<any> {
64
const key = path[index];
64
- const updated = Array.isArray(obj) ? obj.slice() : {...obj};
65
+ const updated = isArray(obj) ? obj.slice() : {...obj};
66
if (index + 1 === path.length) {
66
- if (Array.isArray(updated)) {
67
+ if (isArray(updated)) {
68
updated.splice(((key: any): number), 1);
69
} else {
70
delete updated[key];
@@ -84,12 +85,12 @@ export function copyWithRename(
85
index: number = 0,
86
): Object | Array<any> {
87
const oldKey = oldPath[index];
87
- const updated = Array.isArray(obj) ? obj.slice() : {...obj};
88
+ const updated = isArray(obj) ? obj.slice() : {...obj};
89
if (index + 1 === oldPath.length) {
90
const newKey = newPath[index];
91
// $FlowFixMe number or string is fine here
92
updated[newKey] = updated[oldKey];
92
- if (Array.isArray(updated)) {
93
+ if (isArray(updated)) {
94
updated.splice(((oldKey: any): number), 1);
95
} else {
96
delete updated[oldKey];
@@ -111,7 +112,7 @@ export function copyWithSet(
112
return value;
113
}
114
const key = path[index];
114
- const updated = Array.isArray(obj) ? obj.slice() : {...obj};
115
+ const updated = isArray(obj) ? obj.slice() : {...obj};
116
// $FlowFixMe number or string is fine here
117
updated[key] = copyWithSet(obj[key], path, value, index + 1);
118
return updated;
packages/react-dom/src/client/ReactDOMSelect.js
+4
-3
@@ -12,6 +12,7 @@ import {getCurrentFiberOwnerNameInDevOrNull} from 'react-reconciler/src/ReactCur
12
13
import {checkControlledValueProps} from '../shared/ReactControlledValuePropTypes';
14
import {getToStringValue, toString} from './ToStringValue';
15
+import isArray from 'shared/isArray';
16
17
let didWarnValueDefaultValue;
18
@@ -45,15 +46,15 @@ function checkSelectPropTypes(props) {
46
if (props[propName] == null) {
47
continue;
48
}
48
- const isArray = Array.isArray(props[propName]);
49
- if (props.multiple && !isArray) {
49
+ const propNameIsArray = isArray(props[propName]);
50
+ if (props.multiple && !propNameIsArray) {
51
console.error(
52
'The `%s` prop supplied to <select> must be an array if ' +
53
'`multiple` is true.%s',
54
propName,
55
getDeclarationErrorAddendum(),
56
);
56
- } else if (!props.multiple && isArray) {
57
+ } else if (!props.multiple && propNameIsArray) {
58
console.error(
59
'The `%s` prop supplied to <select> must be a scalar ' +
60
'value if `multiple` is false.%s',
packages/react-dom/src/client/ReactDOMTextarea.js
+2
-2
@@ -8,12 +8,12 @@
8
*/
9
10
import invariant from 'shared/invariant';
11
+import isArray from 'shared/isArray';
12
13
import {checkControlledValueProps} from '../shared/ReactControlledValuePropTypes';
14
import {getCurrentFiberOwnerNameInDevOrNull} from 'react-reconciler/src/ReactCurrentFiber';
15
import {getToStringValue, toString} from './ToStringValue';
16
import type {ToStringValue} from './ToStringValue';
16
-
17
import {disableTextareaChildren} from 'shared/ReactFeatureFlags';
18
19
let didWarnValDefaultVal = false;
@@ -100,7 +100,7 @@ export function initWrapperState(element: Element, props: Object) {
100
defaultValue == null,
101
'If you supply `defaultValue` on a <textarea>, do not pass children.',
102
);
103
- if (Array.isArray(children)) {
103
+ if (isArray(children)) {
104
invariant(
105
children.length <= 1,
106
'<textarea> can only have at most one child.',
packages/react-dom/src/server/ReactDOMServerFormatConfig.js
+1
-2
@@ -46,8 +46,7 @@ import hyphenateStyleName from '../shared/hyphenateStyleName';
46
import invariant from 'shared/invariant';
47
import hasOwnProperty from 'shared/hasOwnProperty';
48
import sanitizeURL from '../shared/sanitizeURL';
49
-
50
-const isArray = Array.isArray;
49
+import isArray from 'shared/isArray';
50
51
// Per response, global state that is not contextual to the rendering subtree.
52
export type ResponseState = {
packages/react-dom/src/server/ReactPartialRenderer.js
+6
-5
@@ -14,6 +14,7 @@ import type {ReactProvider, ReactContext} from 'shared/ReactTypes';
14
15
import * as React from 'react';
16
import invariant from 'shared/invariant';
17
+import isArray from 'shared/isArray';
18
import getComponentNameFromType from 'shared/getComponentNameFromType';
19
import {describeUnknownElementTypeFrameInDEV} from 'shared/ReactComponentStackFrame';
20
import ReactSharedInternals from 'shared/ReactSharedInternals';
@@ -1438,7 +1439,7 @@ class ReactDOMServerRenderer {
1439
defaultValue == null,
1440
'If you supply `defaultValue` on a <textarea>, do not pass children.',
1441
);
1441
- if (Array.isArray(textareaChildren)) {
1442
+ if (isArray(textareaChildren)) {
1443
invariant(
1444
textareaChildren.length <= 1,
1445
'<textarea> can only have at most one child.',
@@ -1467,14 +1468,14 @@ class ReactDOMServerRenderer {
1468
if (props[propName] == null) {
1469
continue;
1470
}
1470
- const isArray = Array.isArray(props[propName]);
1471
- if (props.multiple && !isArray) {
1471
+ const propNameIsArray = isArray(props[propName]);
1472
+ if (props.multiple && !propNameIsArray) {
1473
console.error(
1474
'The `%s` prop supplied to <select> must be an array if ' +
1475
'`multiple` is true.',
1476
propName,
1477
);
1477
- } else if (!props.multiple && isArray) {
1478
+ } else if (!props.multiple && propNameIsArray) {
1479
console.error(
1480
'The `%s` prop supplied to <select> must be a scalar ' +
1481
'value if `multiple` is false.',
@@ -1515,7 +1516,7 @@ class ReactDOMServerRenderer {
1516
value = optionChildren;
1517
}
1518
selected = false;
1518
- if (Array.isArray(selectValue)) {
1519
+ if (isArray(selectValue)) {
1520
// multiple
1521
for (let j = 0; j < selectValue.length; j++) {
1522
if ('' + selectValue[j] === value) {
packages/react-dom/src/test-utils/ReactTestUtils.js
+4
-3
@@ -24,6 +24,7 @@ import {
24
rethrowCaughtError,
25
invokeGuardedCallbackAndCatchFirstError,
26
} from 'shared/ReactErrorUtils';
27
+import isArray from 'shared/isArray';
28
29
// Keep in sync with ReactDOM.js, and ReactTestUtilsAct.js:
30
const EventInternals =
@@ -97,7 +98,7 @@ function validateClassInstance(inst, methodName) {
98
}
99
let received;
100
const stringified = '' + inst;
100
- if (Array.isArray(inst)) {
101
+ if (isArray(inst)) {
102
received = 'an array';
103
} else if (inst && inst.nodeType === ELEMENT_NODE && inst.tagName) {
104
received = 'a DOM node';
@@ -197,7 +198,7 @@ function scryRenderedDOMComponentsWithClass(root, classNames) {
198
}
199
const classList = className.split(/\s+/);
200
200
- if (!Array.isArray(classNames)) {
201
+ if (!isArray(classNames)) {
202
invariant(
203
classNames !== undefined,
204
'TestUtils.scryRenderedDOMComponentsWithClass expects a ' +
@@ -365,7 +366,7 @@ function executeDispatch(event, listener, inst) {
366
function executeDispatchesInOrder(event) {
367
const dispatchListeners = event._dispatchListeners;
368
const dispatchInstances = event._dispatchInstances;
368
- if (Array.isArray(dispatchListeners)) {
369
+ if (isArray(dispatchListeners)) {
370
for (let i = 0; i < dispatchListeners.length; i++) {
371
if (event.isPropagationStopped()) {
372
break;
packages/react-native-renderer/src/ReactNativeAttributePayload.js
+7
-6
@@ -12,6 +12,7 @@ import {
12
deepDiffer,
13
flattenStyle,
14
} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
15
+import isArray from 'shared/isArray';
16
17
import type {AttributeConfiguration} from './ReactNativeTypes';
18
@@ -51,7 +52,7 @@ function restoreDeletedValuesInNestedArray(
52
node: NestedNode,
53
validAttributes: AttributeConfiguration,
54
) {
54
- if (Array.isArray(node)) {
55
+ if (isArray(node)) {
56
let i = node.length;
57
while (i-- && removedKeyCount > 0) {
58
restoreDeletedValuesInNestedArray(
@@ -163,12 +164,12 @@ function diffNestedProperty(
164
return updatePayload;
165
}
166
166
- if (!Array.isArray(prevProp) && !Array.isArray(nextProp)) {
167
+ if (!isArray(prevProp) && !isArray(nextProp)) {
168
// Both are leaves, we can diff the leaves.
169
return diffProperties(updatePayload, prevProp, nextProp, validAttributes);
170
}
171
171
- if (Array.isArray(prevProp) && Array.isArray(nextProp)) {
172
+ if (isArray(prevProp) && isArray(nextProp)) {
173
// Both are arrays, we can diff the arrays.
174
return diffNestedArrayProperty(
175
updatePayload,
@@ -178,7 +179,7 @@ function diffNestedProperty(
179
);
180
}
181
181
- if (Array.isArray(prevProp)) {
182
+ if (isArray(prevProp)) {
183
return diffProperties(
184
updatePayload,
185
// $FlowFixMe - We know that this is always an object when the input is.
@@ -212,7 +213,7 @@ function addNestedProperty(
213
return updatePayload;
214
}
215
215
- if (!Array.isArray(nextProp)) {
216
+ if (!isArray(nextProp)) {
217
// Add each property of the leaf.
218
return addProperties(updatePayload, nextProp, validAttributes);
219
}
@@ -242,7 +243,7 @@ function clearNestedProperty(
243
return updatePayload;
244
}
245
245
- if (!Array.isArray(prevProp)) {
246
+ if (!isArray(prevProp)) {
247
// Add each property of the leaf.
248
return clearProperties(updatePayload, prevProp, validAttributes);
249
}
packages/react-native-renderer/src/__tests__/ReactNativeAttributePayload-test.internal.js
renamed
packages/react-native-renderer/src/legacy-events/EventPluginUtils.js
+6
-5
@@ -7,6 +7,7 @@
7
8
import {invokeGuardedCallbackAndCatchFirstError} from 'shared/ReactErrorUtils';
9
import invariant from 'shared/invariant';
10
+import isArray from 'shared/isArray';
11
12
export let getFiberCurrentPropsFromNode = null;
13
export let getInstanceFromNode = null;
@@ -36,14 +37,14 @@ if (__DEV__) {
37
const dispatchListeners = event._dispatchListeners;
38
const dispatchInstances = event._dispatchInstances;
39
39
- const listenersIsArr = Array.isArray(dispatchListeners);
40
+ const listenersIsArr = isArray(dispatchListeners);
41
const listenersLen = listenersIsArr
42
? dispatchListeners.length
43
: dispatchListeners
44
? 1
45
: 0;
46
46
- const instancesIsArr = Array.isArray(dispatchInstances);
47
+ const instancesIsArr = isArray(dispatchInstances);
48
const instancesLen = instancesIsArr
49
? dispatchInstances.length
50
: dispatchInstances
@@ -78,7 +79,7 @@ export function executeDispatchesInOrder(event) {
79
if (__DEV__) {
80
validateEventDispatches(event);
81
}
81
- if (Array.isArray(dispatchListeners)) {
82
+ if (isArray(dispatchListeners)) {
83
for (let i = 0; i < dispatchListeners.length; i++) {
84
if (event.isPropagationStopped()) {
85
break;
@@ -106,7 +107,7 @@ function executeDispatchesInOrderStopAtTrueImpl(event) {
107
if (__DEV__) {
108
validateEventDispatches(event);
109
}
109
- if (Array.isArray(dispatchListeners)) {
110
+ if (isArray(dispatchListeners)) {
111
for (let i = 0; i < dispatchListeners.length; i++) {
112
if (event.isPropagationStopped()) {
113
break;
@@ -150,7 +151,7 @@ export function executeDirectDispatch(event) {
151
const dispatchListener = event._dispatchListeners;
152
const dispatchInstance = event._dispatchInstances;
153
invariant(
153
- !Array.isArray(dispatchListener),
154
+ !isArray(dispatchListener),
155
'executeDirectDispatch(...): Invalid `event`.',
156
);
157
event.currentTarget = dispatchListener
packages/react-native-renderer/src/legacy-events/accumulate.js
+3
-2
@@ -8,6 +8,7 @@
8
*/
9
10
import invariant from 'shared/invariant';
11
+import isArray from 'shared/isArray';
12
13
/**
14
* Accumulates items that must not be null or undefined.
@@ -31,11 +32,11 @@ function accumulate<T>(
32
33
// Both are not empty. Warning: Never call x.concat(y) when you are not
34
// certain that x is an Array (x could be a string with concat method).
34
- if (Array.isArray(current)) {
35
+ if (isArray(current)) {
36
return current.concat(next);
37
}
38
38
- if (Array.isArray(next)) {
39
+ if (isArray(next)) {
40
return [current].concat(next);
41
}
42
packages/react-native-renderer/src/legacy-events/accumulateInto.js
+4
-3
@@ -8,6 +8,7 @@
8
*/
9
10
import invariant from 'shared/invariant';
11
+import isArray from 'shared/isArray';
12
13
/**
14
* Accumulates items that must not be null or undefined into the first one. This
@@ -37,8 +38,8 @@ function accumulateInto<T>(
38
39
// Both are not empty. Warning: Never call x.concat(y) when you are not
40
// certain that x is an Array (x could be a string with concat method).
40
- if (Array.isArray(current)) {
41
- if (Array.isArray(next)) {
41
+ if (isArray(current)) {
42
+ if (isArray(next)) {
43
current.push.apply(current, next);
44
return current;
45
}
@@ -46,7 +47,7 @@ function accumulateInto<T>(
47
return current;
48
}
49
49
- if (Array.isArray(next)) {
50
+ if (isArray(next)) {
51
// A bit too dangerous to mutate `next`.
52
return [current].concat(next);
53
}
packages/react-noop-renderer/src/createReactNoop.js
+5
-4
@@ -21,6 +21,7 @@ import type {RootTag} from 'react-reconciler/src/ReactRootTags';
21
22
import * as Scheduler from 'scheduler/unstable_mock';
23
import {REACT_FRAGMENT_TYPE, REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
24
+import isArray from 'shared/isArray';
25
import {
26
DefaultEventPriority,
27
IdleEventPriority,
@@ -604,7 +605,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
605
if (typeof child === 'string') {
606
return child;
607
}
607
- if (Array.isArray(child)) {
608
+ if (isArray(child)) {
609
if (child.length === 0) {
610
return null;
611
}
@@ -618,7 +619,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
619
}
620
return children;
621
}
621
- if (Array.isArray(child.children)) {
622
+ if (isArray(child.children)) {
623
// This is an instance.
624
const instance: Instance = (child: any);
625
const children = childToJSX(instance.children, instance.text);
@@ -668,7 +669,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
669
if (children === null) {
670
return null;
671
}
671
- if (Array.isArray(children)) {
672
+ if (isArray(children)) {
673
return {
674
$$typeof: REACT_ELEMENT_TYPE,
675
type: REACT_FRAGMENT_TYPE,
@@ -687,7 +688,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
688
if (children === null) {
689
return null;
690
}
690
- if (Array.isArray(children)) {
691
+ if (isArray(children)) {
692
return {
693
$$typeof: REACT_ELEMENT_TYPE,
694
type: REACT_FRAGMENT_TYPE,
packages/react-reconciler/src/ReactChildFiber.new.js
+1
-2
@@ -31,6 +31,7 @@ import {
31
SimpleMemoComponent,
32
} from './ReactWorkTags';
33
import invariant from 'shared/invariant';
34
+import isArray from 'shared/isArray';
35
import {
36
warnAboutStringRefs,
37
enableLazyElements,
@@ -97,8 +98,6 @@ if (__DEV__) {
98
};
99
}
100
100
-const isArray = Array.isArray;
101
-
101
function coerceRef(
102
returnFiber: Fiber,
103
current: Fiber | null,
packages/react-reconciler/src/ReactChildFiber.old.js
+1
-2
@@ -31,6 +31,7 @@ import {
31
SimpleMemoComponent,
32
} from './ReactWorkTags';
33
import invariant from 'shared/invariant';
34
+import isArray from 'shared/isArray';
35
import {
36
warnAboutStringRefs,
37
enableLazyElements,
@@ -97,8 +98,6 @@ if (__DEV__) {
98
};
99
}
100
100
-const isArray = Array.isArray;
101
-
101
function coerceRef(
102
returnFiber: Fiber,
103
current: Fiber | null,
packages/react-reconciler/src/ReactFiberBeginWork.new.js
+6
-5
@@ -87,6 +87,7 @@ import {
87
enableSuspenseLayoutEffectSemantics,
88
} from 'shared/ReactFeatureFlags';
89
import invariant from 'shared/invariant';
90
+import isArray from 'shared/isArray';
91
import shallowEqual from 'shared/shallowEqual';
92
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
93
import getComponentNameFromType from 'shared/getComponentNameFromType';
@@ -2713,11 +2714,11 @@ function validateTailOptions(
2714
2715
function validateSuspenseListNestedChild(childSlot: mixed, index: number) {
2716
if (__DEV__) {
2716
- const isArray = Array.isArray(childSlot);
2717
+ const isAnArray = isArray(childSlot);
2718
const isIterable =
2718
- !isArray && typeof getIteratorFn(childSlot) === 'function';
2719
- if (isArray || isIterable) {
2720
- const type = isArray ? 'array' : 'iterable';
2719
+ !isAnArray && typeof getIteratorFn(childSlot) === 'function';
2720
+ if (isAnArray || isIterable) {
2721
+ const type = isAnArray ? 'array' : 'iterable';
2722
console.error(
2723
'A nested %s was passed to row #%s in <SuspenseList />. Wrap it in ' +
2724
'an additional SuspenseList to configure its revealOrder: ' +
@@ -2745,7 +2746,7 @@ function validateSuspenseListChildren(
2746
children !== null &&
2747
children !== false
2748
) {
2748
- if (Array.isArray(children)) {
2749
+ if (isArray(children)) {
2750
for (let i = 0; i < children.length; i++) {
2751
if (!validateSuspenseListNestedChild(children[i], i)) {
2752
return;
packages/react-reconciler/src/ReactFiberBeginWork.old.js
+6
-5
@@ -87,6 +87,7 @@ import {
87
enableSuspenseLayoutEffectSemantics,
88
} from 'shared/ReactFeatureFlags';
89
import invariant from 'shared/invariant';
90
+import isArray from 'shared/isArray';
91
import shallowEqual from 'shared/shallowEqual';
92
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
93
import getComponentNameFromType from 'shared/getComponentNameFromType';
@@ -2713,11 +2714,11 @@ function validateTailOptions(
2714
2715
function validateSuspenseListNestedChild(childSlot: mixed, index: number) {
2716
if (__DEV__) {
2716
- const isArray = Array.isArray(childSlot);
2717
+ const isAnArray = isArray(childSlot);
2718
const isIterable =
2718
- !isArray && typeof getIteratorFn(childSlot) === 'function';
2719
- if (isArray || isIterable) {
2720
- const type = isArray ? 'array' : 'iterable';
2719
+ !isAnArray && typeof getIteratorFn(childSlot) === 'function';
2720
+ if (isAnArray || isIterable) {
2721
+ const type = isAnArray ? 'array' : 'iterable';
2722
console.error(
2723
'A nested %s was passed to row #%s in <SuspenseList />. Wrap it in ' +
2724
'an additional SuspenseList to configure its revealOrder: ' +
@@ -2745,7 +2746,7 @@ function validateSuspenseListChildren(
2746
children !== null &&
2747
children !== false
2748
) {
2748
- if (Array.isArray(children)) {
2749
+ if (isArray(children)) {
2750
for (let i = 0; i < children.length; i++) {
2751
if (!validateSuspenseListNestedChild(children[i], i)) {
2752
return;
packages/react-reconciler/src/ReactFiberClassComponent.new.js
+1
-1
@@ -36,6 +36,7 @@ import shallowEqual from 'shared/shallowEqual';
36
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
37
import getComponentNameFromType from 'shared/getComponentNameFromType';
38
import invariant from 'shared/invariant';
39
+import isArray from 'shared/isArray';
40
import {REACT_CONTEXT_TYPE, REACT_PROVIDER_TYPE} from 'shared/ReactSymbols';
41
42
import {resolveDefaultProps} from './ReactFiberLazyComponent.new';
@@ -81,7 +82,6 @@ import {
82
} from './SchedulingProfiler';
83
84
const fakeInternalInstance = {};
84
-const isArray = Array.isArray;
85
86
// React.Component uses a shared frozen object by default.
87
// We'll use it to determine whether we need to initialize legacy refs.
packages/react-reconciler/src/ReactFiberClassComponent.old.js
+1
-1
@@ -36,6 +36,7 @@ import shallowEqual from 'shared/shallowEqual';
36
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
37
import getComponentNameFromType from 'shared/getComponentNameFromType';
38
import invariant from 'shared/invariant';
39
+import isArray from 'shared/isArray';
40
import {REACT_CONTEXT_TYPE, REACT_PROVIDER_TYPE} from 'shared/ReactSymbols';
41
42
import {resolveDefaultProps} from './ReactFiberLazyComponent.old';
@@ -81,7 +82,6 @@ import {
82
} from './SchedulingProfiler';
83
84
const fakeInternalInstance = {};
84
-const isArray = Array.isArray;
85
86
// React.Component uses a shared frozen object by default.
87
// We'll use it to determine whether we need to initialize legacy refs.
packages/react-reconciler/src/ReactFiberHooks.new.js
+2
-1
@@ -87,6 +87,7 @@ import {
87
import invariant from 'shared/invariant';
88
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
89
import is from 'shared/objectIs';
90
+import isArray from 'shared/isArray';
91
import {
92
markWorkInProgressReceivedUpdate,
93
checkIfWorkInProgressReceivedUpdate,
@@ -229,7 +230,7 @@ function updateHookTypesDev() {
230
231
function checkDepsAreArrayDev(deps: mixed) {
232
if (__DEV__) {
232
- if (deps !== undefined && deps !== null && !Array.isArray(deps)) {
233
+ if (deps !== undefined && deps !== null && !isArray(deps)) {
234
// Verify deps, but only on mount to avoid extra checks.
235
// It's unlikely their type would change as usually you define them inline.
236
console.error(
packages/react-reconciler/src/ReactFiberHooks.old.js
+2
-1
@@ -87,6 +87,7 @@ import {
87
import invariant from 'shared/invariant';
88
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
89
import is from 'shared/objectIs';
90
+import isArray from 'shared/isArray';
91
import {
92
markWorkInProgressReceivedUpdate,
93
checkIfWorkInProgressReceivedUpdate,
@@ -229,7 +230,7 @@ function updateHookTypesDev() {
230
231
function checkDepsAreArrayDev(deps: mixed) {
232
if (__DEV__) {
232
- if (deps !== undefined && deps !== null && !Array.isArray(deps)) {
233
+ if (deps !== undefined && deps !== null && !isArray(deps)) {
234
// Verify deps, but only on mount to avoid extra checks.
235
// It's unlikely their type would change as usually you define them inline.
236
console.error(
packages/react-reconciler/src/ReactFiberReconciler.new.js
+6
-5
@@ -34,6 +34,7 @@ import {
34
} from './ReactWorkTags';
35
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
36
import invariant from 'shared/invariant';
37
+import isArray from 'shared/isArray';
38
import {enableSchedulingProfiler} from 'shared/ReactFeatureFlags';
39
import ReactSharedInternals from 'shared/ReactSharedInternals';
40
import {getPublicInstance} from './ReactFiberHostConfig';
@@ -482,9 +483,9 @@ if (__DEV__) {
483
index: number,
484
) => {
485
const key = path[index];
485
- const updated = Array.isArray(obj) ? obj.slice() : {...obj};
486
+ const updated = isArray(obj) ? obj.slice() : {...obj};
487
if (index + 1 === path.length) {
487
- if (Array.isArray(updated)) {
488
+ if (isArray(updated)) {
489
updated.splice(((key: any): number), 1);
490
} else {
491
delete updated[key];
@@ -510,12 +511,12 @@ if (__DEV__) {
511
index: number,
512
) => {
513
const oldKey = oldPath[index];
513
- const updated = Array.isArray(obj) ? obj.slice() : {...obj};
514
+ const updated = isArray(obj) ? obj.slice() : {...obj};
515
if (index + 1 === oldPath.length) {
516
const newKey = newPath[index];
517
// $FlowFixMe number or string is fine here
518
updated[newKey] = updated[oldKey];
518
- if (Array.isArray(updated)) {
519
+ if (isArray(updated)) {
520
updated.splice(((oldKey: any): number), 1);
521
} else {
522
delete updated[oldKey];
@@ -564,7 +565,7 @@ if (__DEV__) {
565
return value;
566
}
567
const key = path[index];
567
- const updated = Array.isArray(obj) ? obj.slice() : {...obj};
568
+ const updated = isArray(obj) ? obj.slice() : {...obj};
569
// $FlowFixMe number or string is fine here
570
updated[key] = copyWithSetImpl(obj[key], path, index + 1, value);
571
return updated;
packages/react-reconciler/src/ReactFiberReconciler.old.js
+6
-5
@@ -34,6 +34,7 @@ import {
34
} from './ReactWorkTags';
35
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
36
import invariant from 'shared/invariant';
37
+import isArray from 'shared/isArray';
38
import {enableSchedulingProfiler} from 'shared/ReactFeatureFlags';
39
import ReactSharedInternals from 'shared/ReactSharedInternals';
40
import {getPublicInstance} from './ReactFiberHostConfig';
@@ -482,9 +483,9 @@ if (__DEV__) {
483
index: number,
484
) => {
485
const key = path[index];
485
- const updated = Array.isArray(obj) ? obj.slice() : {...obj};
486
+ const updated = isArray(obj) ? obj.slice() : {...obj};
487
if (index + 1 === path.length) {
487
- if (Array.isArray(updated)) {
488
+ if (isArray(updated)) {
489
updated.splice(((key: any): number), 1);
490
} else {
491
delete updated[key];
@@ -510,12 +511,12 @@ if (__DEV__) {
511
index: number,
512
) => {
513
const oldKey = oldPath[index];
513
- const updated = Array.isArray(obj) ? obj.slice() : {...obj};
514
+ const updated = isArray(obj) ? obj.slice() : {...obj};
515
if (index + 1 === oldPath.length) {
516
const newKey = newPath[index];
517
// $FlowFixMe number or string is fine here
518
updated[newKey] = updated[oldKey];
518
- if (Array.isArray(updated)) {
519
+ if (isArray(updated)) {
520
updated.splice(((oldKey: any): number), 1);
521
} else {
522
delete updated[oldKey];
@@ -564,7 +565,7 @@ if (__DEV__) {
565
return value;
566
}
567
const key = path[index];
567
- const updated = Array.isArray(obj) ? obj.slice() : {...obj};
568
+ const updated = isArray(obj) ? obj.slice() : {...obj};
569
// $FlowFixMe number or string is fine here
570
updated[key] = copyWithSetImpl(obj[key], path, index + 1, value);
571
return updated;
packages/react-server-dom-relay/src/ReactFlightDOMRelayClientHostConfig.js
+3
-1
@@ -24,6 +24,8 @@ export {
24
requireModule,
25
} from 'ReactFlightDOMRelayClientIntegration';
26
27
+import isArray from 'shared/isArray';
28
+
29
export type {ModuleMetaData} from 'ReactFlightDOMRelayClientIntegration';
30
31
export type UninitializedModel = JSONValue;
@@ -35,7 +37,7 @@ function parseModelRecursively(response: Response, parentObj, value) {
37
return parseModelString(response, parentObj, value);
38
}
39
if (typeof value === 'object' && value !== null) {
38
- if (Array.isArray(value)) {
40
+ if (isArray(value)) {
41
const parsedValue = [];
42
for (let i = 0; i < value.length; i++) {
43
(parsedValue: any)[i] = parseModelRecursively(
packages/react-server-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js
+2
-1
@@ -14,6 +14,7 @@ import type {Request, ReactModel} from 'react-server/src/ReactFlightServer';
14
import JSResourceReference from 'JSResourceReference';
15
16
import hasOwnProperty from 'shared/hasOwnProperty';
17
+import isArray from 'shared/isArray';
18
19
export type ModuleReference<T> = JSResourceReference<T>;
20
@@ -82,7 +83,7 @@ function convertModelToJSON(
83
): JSONValue {
84
const json = resolveModelToJSON(request, parent, key, model);
85
if (typeof json === 'object' && json !== null) {
85
- if (Array.isArray(json)) {
86
+ if (isArray(json)) {
87
const jsonArray: Array<JSONValue> = [];
88
for (let i = 0; i < json.length; i++) {
89
jsonArray[i] = convertModelToJSON(request, json, '' + i, json[i]);
packages/react-server-dom-webpack/src/ReactFlightWebpackPlugin.js
+3
-1
@@ -17,6 +17,8 @@ import NullDependency from 'webpack/lib/dependencies/NullDependency';
17
import AsyncDependenciesBlock from 'webpack/lib/AsyncDependenciesBlock';
18
import Template from 'webpack/lib/Template';
19
20
+import isArray from 'shared/isArray';
21
+
22
class ClientReferenceDependency extends ModuleDependency {
23
constructor(request) {
24
super(request);
@@ -76,7 +78,7 @@ export default class ReactFlightWebpackPlugin {
78
];
79
} else if (
80
typeof options.clientReferences === 'string' ||
79
- !Array.isArray(options.clientReferences)
81
+ !isArray(options.clientReferences)
82
) {
83
this.clientReferences = [(options.clientReferences: $FlowFixMe)];
84
} else {
packages/react-server-native-relay/src/ReactFlightNativeRelayClientHostConfig.js
+3
-1
@@ -24,6 +24,8 @@ export {
24
requireModule,
25
} from 'ReactFlightNativeRelayClientIntegration';
26
27
+import isArray from 'shared/isArray';
28
+
29
export type {ModuleMetaData} from 'ReactFlightNativeRelayClientIntegration';
30
31
export type UninitializedModel = JSONValue;
@@ -35,7 +37,7 @@ function parseModelRecursively(response: Response, parentObj, value) {
37
return parseModelString(response, parentObj, value);
38
}
39
if (typeof value === 'object' && value !== null) {
38
- if (Array.isArray(value)) {
40
+ if (isArray(value)) {
41
const parsedValue = [];
42
for (let i = 0; i < value.length; i++) {
43
(parsedValue: any)[i] = parseModelRecursively(
packages/react-server-native-relay/src/ReactFlightNativeRelayServerHostConfig.js
+2
-2
@@ -8,9 +8,9 @@
8
*/
9
10
import type {RowEncoding, JSONValue} from './ReactFlightNativeRelayProtocol';
11
-
11
import type {Request, ReactModel} from 'react-server/src/ReactFlightServer';
12
import hasOwnProperty from 'shared/hasOwnProperty';
13
+import isArray from 'shared/isArray';
14
import JSResourceReferenceImpl from 'JSResourceReferenceImpl';
15
16
export type ModuleReference<T> = JSResourceReferenceImpl<T>;
@@ -80,7 +80,7 @@ function convertModelToJSON(
80
): JSONValue {
81
const json = resolveModelToJSON(request, parent, key, model);
82
if (typeof json === 'object' && json !== null) {
83
- if (Array.isArray(json)) {
83
+ if (isArray(json)) {
84
const jsonArray: Array<JSONValue> = [];
85
for (let i = 0; i < json.length; i++) {
86
jsonArray[i] = convertModelToJSON(request, json, '' + i, json[i]);
packages/react-server/src/ReactFizzServer.js
+2
-1
@@ -51,6 +51,7 @@ import {REACT_ELEMENT_TYPE, REACT_SUSPENSE_TYPE} from 'shared/ReactSymbols';
51
import ReactSharedInternals from 'shared/ReactSharedInternals';
52
53
import invariant from 'shared/invariant';
54
+import isArray from 'shared/isArray';
55
56
const ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
57
@@ -287,7 +288,7 @@ function renderNode(request: Request, task: Task, node: ReactNodeList): void {
288
return;
289
}
290
290
- if (Array.isArray(node)) {
291
+ if (isArray(node)) {
292
if (node.length > 0) {
293
for (let i = 0; i < node.length; i++) {
294
renderNode(request, task, node[i]);
packages/react-server/src/ReactFlightServer.js
+1
-2
@@ -44,8 +44,7 @@ import {
44
45
import ReactSharedInternals from 'shared/ReactSharedInternals';
46
import invariant from 'shared/invariant';
47
-
48
-const isArray = Array.isArray;
47
+import isArray from 'shared/isArray';
48
49
type ReactJSONValue =
50
| string
packages/react-test-renderer/src/ReactTestHostConfig.js
+2
-1
@@ -8,6 +8,7 @@
8
*/
9
10
import {REACT_OPAQUE_ID_TYPE} from 'shared/ReactSymbols';
11
+import isArray from 'shared/isArray';
12
import {DefaultEventPriority} from 'react-reconciler/src/ReactEventPriorities';
13
14
export type Type = string;
@@ -84,7 +85,7 @@ export function appendChild(
85
child: Instance | TextInstance,
86
): void {
87
if (__DEV__) {
87
- if (!Array.isArray(parentInstance.children)) {
88
+ if (!isArray(parentInstance.children)) {
89
console.error(
90
'An invalid container has been provided. ' +
91
'This may indicate that another renderer is being used in addition to the test renderer. ' +
packages/react-test-renderer/src/ReactTestRenderer.js
+2
-1
@@ -43,6 +43,7 @@ import {
43
ScopeComponent,
44
} from 'react-reconciler/src/ReactWorkTags';
45
import invariant from 'shared/invariant';
46
+import isArray from 'shared/isArray';
47
import getComponentNameFromType from 'shared/getComponentNameFromType';
48
import ReactVersion from 'shared/ReactVersion';
49
import ReactSharedInternals from 'shared/ReactSharedInternals';
@@ -158,7 +159,7 @@ function flatten(arr) {
159
while (n.i < n.array.length) {
160
const el = n.array[n.i];
161
n.i += 1;
161
- if (Array.isArray(el)) {
162
+ if (isArray(el)) {
163
stack.push(n);
164
stack.push({i: 0, array: el});
165
break;
packages/react/src/ReactChildren.js
+3
-2
@@ -10,6 +10,7 @@
10
import type {ReactNodeList} from 'shared/ReactTypes';
11
12
import invariant from 'shared/invariant';
13
+import isArray from 'shared/isArray';
14
import {
15
getIteratorFn,
16
REACT_ELEMENT_TYPE,
@@ -110,7 +111,7 @@ function mapIntoArray(
111
// so that it's consistent if the number of children grows:
112
const childKey =
113
nameSoFar === '' ? SEPARATOR + getElementKey(child, 0) : nameSoFar;
113
- if (Array.isArray(mappedChild)) {
114
+ if (isArray(mappedChild)) {
115
let escapedChildKey = '';
116
if (childKey != null) {
117
escapedChildKey = escapeUserProvidedKey(childKey) + '/';
@@ -142,7 +143,7 @@ function mapIntoArray(
143
const nextNamePrefix =
144
nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;
145
145
- if (Array.isArray(children)) {
146
+ if (isArray(children)) {
147
for (let i = 0; i < children.length; i++) {
148
child = children[i];
149
nextName = nextNamePrefix + getElementKey(child, i);
packages/react/src/ReactElementValidator.js
+5
-4
@@ -23,6 +23,7 @@ import {
23
} from 'shared/ReactSymbols';
24
import {warnAboutSpreadingKeyToJSX} from 'shared/ReactFeatureFlags';
25
import checkPropTypes from 'shared/checkPropTypes';
26
+import isArray from 'shared/isArray';
27
28
import ReactCurrentOwner from './ReactCurrentOwner';
29
import {
@@ -168,7 +169,7 @@ function validateChildKeys(node, parentType) {
169
if (typeof node !== 'object') {
170
return;
171
}
171
- if (Array.isArray(node)) {
172
+ if (isArray(node)) {
173
for (let i = 0; i < node.length; i++) {
174
const child = node[i];
175
if (isValidElement(child)) {
@@ -313,7 +314,7 @@ export function jsxWithValidation(
314
let typeString;
315
if (type === null) {
316
typeString = 'null';
316
- } else if (Array.isArray(type)) {
317
+ } else if (isArray(type)) {
318
typeString = 'array';
319
} else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
320
typeString = `<${getComponentNameFromType(type.type) || 'Unknown'} />`;
@@ -352,7 +353,7 @@ export function jsxWithValidation(
353
const children = props.children;
354
if (children !== undefined) {
355
if (isStaticChildren) {
355
- if (Array.isArray(children)) {
356
+ if (isArray(children)) {
357
for (let i = 0; i < children.length; i++) {
358
validateChildKeys(children[i], type);
359
}
@@ -437,7 +438,7 @@ export function createElementWithValidation(type, props, children) {
438
let typeString;
439
if (type === null) {
440
typeString = 'null';
440
- } else if (Array.isArray(type)) {
441
+ } else if (isArray(type)) {
442
typeString = 'array';
443
} else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
444
typeString = `<${getComponentNameFromType(type.type) || 'Unknown'} />`;
packages/react/src/jsx/ReactJSXElementValidator.js
+4
-3
@@ -23,6 +23,7 @@ import {
23
} from 'shared/ReactSymbols';
24
import {warnAboutSpreadingKeyToJSX} from 'shared/ReactFeatureFlags';
25
import hasOwnProperty from 'shared/hasOwnProperty';
26
+import isArray from 'shared/isArray';
27
import {jsxDEV} from './ReactJSXElement';
28
29
import {describeUnknownElementTypeFrameInDEV} from 'shared/ReactComponentStackFrame';
@@ -182,7 +183,7 @@ function validateChildKeys(node, parentType) {
183
if (typeof node !== 'object') {
184
return;
185
}
185
- if (Array.isArray(node)) {
186
+ if (isArray(node)) {
187
for (let i = 0; i < node.length; i++) {
188
const child = node[i];
189
if (isValidElement(child)) {
@@ -329,7 +330,7 @@ export function jsxWithValidation(
330
let typeString;
331
if (type === null) {
332
typeString = 'null';
332
- } else if (Array.isArray(type)) {
333
+ } else if (isArray(type)) {
334
typeString = 'array';
335
} else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
336
typeString = `<${getComponentNameFromType(type.type) || 'Unknown'} />`;
@@ -366,7 +367,7 @@ export function jsxWithValidation(
367
const children = props.children;
368
if (children !== undefined) {
369
if (isStaticChildren) {
369
- if (Array.isArray(children)) {
370
+ if (isArray(children)) {
371
for (let i = 0; i < children.length; i++) {
372
validateChildKeys(children[i], type);
373
}
packages/shared/isArray.js
new
+19
@@ -0,0 +1,19 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+declare function isArray(a: mixed): boolean %checks(Array.isArray(a));
11
+
12
+const isArrayImpl = Array.isArray;
13
+
14
+// eslint-disable-next-line no-redeclare
15
+function isArray(a: mixed): boolean {
16
+ return isArrayImpl(a);
17
+}
18
+
19
+export default isArray;