Compare commits
21 Commits
pr34560
...
walaura-es
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbc344e8e7 | ||
|
|
e3b59c14ba | ||
|
|
341faaf4e3 | ||
|
|
48b03f3774 | ||
|
|
416e258b3c | ||
|
|
1a9b639c2f | ||
|
|
a20f13e3cd | ||
|
|
b73cdc72df | ||
|
|
5ddb7a01c6 | ||
|
|
fb0a374117 | ||
|
|
d84332c4f7 | ||
|
|
fafc2e1889 | ||
|
|
c791455637 | ||
|
|
38f5068684 | ||
|
|
46e17a9700 | ||
|
|
3db8a02d28 | ||
|
|
07c28b59a8 | ||
|
|
a2d7a0ca7a | ||
|
|
d363805462 | ||
|
|
b1fc0040a9 | ||
|
|
d94f6972eb |
@@ -93,6 +93,7 @@ module.exports = {
|
||||
'react-internal/no-primitive-constructors': ERROR,
|
||||
'react-internal/no-to-warn-dev-within-to-throw': ERROR,
|
||||
'react-internal/warning-and-invariant-args': ERROR,
|
||||
'react-internal/no-production-logging': ERROR,
|
||||
},
|
||||
|
||||
overrides: [
|
||||
|
||||
@@ -36,14 +36,16 @@ export function createSubscription<Property, Value>(
|
||||
}> {
|
||||
const {getCurrentValue, subscribe} = config;
|
||||
|
||||
warningWithoutStack(
|
||||
typeof getCurrentValue === 'function',
|
||||
'Subscription must specify a getCurrentValue function',
|
||||
);
|
||||
warningWithoutStack(
|
||||
typeof subscribe === 'function',
|
||||
'Subscription must specify a subscribe function',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
typeof getCurrentValue === 'function',
|
||||
'Subscription must specify a getCurrentValue function',
|
||||
);
|
||||
warningWithoutStack(
|
||||
typeof subscribe === 'function',
|
||||
'Subscription must specify a subscribe function',
|
||||
);
|
||||
}
|
||||
|
||||
type Props = {
|
||||
children: (value: Value) => React$Element<any>,
|
||||
|
||||
@@ -284,16 +284,18 @@ function getPooledWarningPropertyDefinition(propName, getVal) {
|
||||
|
||||
function warn(action, result) {
|
||||
const warningCondition = false;
|
||||
warningWithoutStack(
|
||||
warningCondition,
|
||||
"This synthetic event is reused for performance reasons. If you're seeing this, " +
|
||||
"you're %s `%s` on a released/nullified synthetic event. %s. " +
|
||||
'If you must keep the original synthetic event around, use event.persist(). ' +
|
||||
'See https://fb.me/react-event-pooling for more information.',
|
||||
action,
|
||||
propName,
|
||||
result,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
warningCondition,
|
||||
"This synthetic event is reused for performance reasons. If you're seeing this, " +
|
||||
"you're %s `%s` on a released/nullified synthetic event. %s. " +
|
||||
'If you must keep the original synthetic event around, use event.persist(). ' +
|
||||
'See https://fb.me/react-event-pooling for more information.',
|
||||
action,
|
||||
propName,
|
||||
result,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
20
packages/react-dom/src/client/ReactDOM.js
vendored
20
packages/react-dom/src/client/ReactDOM.js
vendored
@@ -142,15 +142,17 @@ const ReactDOM: Object = {
|
||||
// Temporary alias since we already shipped React 16 RC with it.
|
||||
// TODO: remove in React 17.
|
||||
unstable_createPortal(...args) {
|
||||
if (!didWarnAboutUnstableCreatePortal) {
|
||||
didWarnAboutUnstableCreatePortal = true;
|
||||
lowPriorityWarningWithoutStack(
|
||||
false,
|
||||
'The ReactDOM.unstable_createPortal() alias has been deprecated, ' +
|
||||
'and will be removed in React 17+. Update your code to use ' +
|
||||
'ReactDOM.createPortal() instead. It has the exact same API, ' +
|
||||
'but without the "unstable_" prefix.',
|
||||
);
|
||||
if (__DEV__) {
|
||||
if (!didWarnAboutUnstableCreatePortal) {
|
||||
didWarnAboutUnstableCreatePortal = true;
|
||||
lowPriorityWarningWithoutStack(
|
||||
false,
|
||||
'The ReactDOM.unstable_createPortal() alias has been deprecated, ' +
|
||||
'and will be removed in React 17+. Update your code to use ' +
|
||||
'ReactDOM.createPortal() instead. It has the exact same API, ' +
|
||||
'but without the "unstable_" prefix.',
|
||||
);
|
||||
}
|
||||
}
|
||||
return createPortal(...args);
|
||||
},
|
||||
|
||||
48
packages/react-dom/src/client/ReactDOMSelect.js
vendored
48
packages/react-dom/src/client/ReactDOMSelect.js
vendored
@@ -40,30 +40,32 @@ const valuePropNames = ['value', 'defaultValue'];
|
||||
* Validation function for `value` and `defaultValue`.
|
||||
*/
|
||||
function checkSelectPropTypes(props) {
|
||||
ReactControlledValuePropTypes.checkPropTypes('select', props);
|
||||
if (__DEV__) {
|
||||
ReactControlledValuePropTypes.checkPropTypes('select', props);
|
||||
|
||||
for (let i = 0; i < valuePropNames.length; i++) {
|
||||
const propName = valuePropNames[i];
|
||||
if (props[propName] == null) {
|
||||
continue;
|
||||
}
|
||||
const isArray = Array.isArray(props[propName]);
|
||||
if (props.multiple && !isArray) {
|
||||
warning(
|
||||
false,
|
||||
'The `%s` prop supplied to <select> must be an array if ' +
|
||||
'`multiple` is true.%s',
|
||||
propName,
|
||||
getDeclarationErrorAddendum(),
|
||||
);
|
||||
} else if (!props.multiple && isArray) {
|
||||
warning(
|
||||
false,
|
||||
'The `%s` prop supplied to <select> must be a scalar ' +
|
||||
'value if `multiple` is false.%s',
|
||||
propName,
|
||||
getDeclarationErrorAddendum(),
|
||||
);
|
||||
for (let i = 0; i < valuePropNames.length; i++) {
|
||||
const propName = valuePropNames[i];
|
||||
if (props[propName] == null) {
|
||||
continue;
|
||||
}
|
||||
const isArray = Array.isArray(props[propName]);
|
||||
if (props.multiple && !isArray) {
|
||||
warning(
|
||||
false,
|
||||
'The `%s` prop supplied to <select> must be an array if ' +
|
||||
'`multiple` is true.%s',
|
||||
propName,
|
||||
getDeclarationErrorAddendum(),
|
||||
);
|
||||
} else if (!props.multiple && isArray) {
|
||||
warning(
|
||||
false,
|
||||
'The `%s` prop supplied to <select> must be a scalar ' +
|
||||
'value if `multiple` is false.%s',
|
||||
propName,
|
||||
getDeclarationErrorAddendum(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -687,12 +687,14 @@ function resolve(
|
||||
);
|
||||
}
|
||||
} else {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'%s.getChildContext(): childContextTypes must be defined in order to ' +
|
||||
'use getChildContext().',
|
||||
getComponentName(Component) || 'Unknown',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'%s.getChildContext(): childContextTypes must be defined in order to ' +
|
||||
'use getChildContext().',
|
||||
getComponentName(Component) || 'Unknown',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (childContext) {
|
||||
|
||||
@@ -392,16 +392,16 @@ export function useLayoutEffect(
|
||||
) {
|
||||
if (__DEV__) {
|
||||
currentHookNameInDev = 'useLayoutEffect';
|
||||
warning(
|
||||
false,
|
||||
'useLayoutEffect does nothing on the server, because its effect cannot ' +
|
||||
"be encoded into the server renderer's output format. This will lead " +
|
||||
'to a mismatch between the initial, non-hydrated UI and the intended ' +
|
||||
'UI. To avoid this, useLayoutEffect should only be used in ' +
|
||||
'components that render exclusively on the client. ' +
|
||||
'See https://fb.me/react-uselayouteffect-ssr for common fixes.',
|
||||
);
|
||||
}
|
||||
warning(
|
||||
false,
|
||||
'useLayoutEffect does nothing on the server, because its effect cannot ' +
|
||||
"be encoded into the server renderer's output format. This will lead " +
|
||||
'to a mismatch between the initial, non-hydrated UI and the intended ' +
|
||||
'UI. To avoid this, useLayoutEffect should only be used in ' +
|
||||
'components that render exclusively on the client. ' +
|
||||
'See https://fb.me/react-uselayouteffect-ssr for common fixes.',
|
||||
);
|
||||
}
|
||||
|
||||
function dispatchAction<A>(
|
||||
|
||||
@@ -128,37 +128,39 @@ export function validateShorthandPropertyCollisionInDev(
|
||||
styleUpdates,
|
||||
nextStyles,
|
||||
) {
|
||||
if (!warnAboutShorthandPropertyCollision) {
|
||||
return;
|
||||
}
|
||||
if (__DEV__) {
|
||||
if (!warnAboutShorthandPropertyCollision) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nextStyles) {
|
||||
return;
|
||||
}
|
||||
if (!nextStyles) {
|
||||
return;
|
||||
}
|
||||
|
||||
const expandedUpdates = expandShorthandMap(styleUpdates);
|
||||
const expandedStyles = expandShorthandMap(nextStyles);
|
||||
const warnedAbout = {};
|
||||
for (const key in expandedUpdates) {
|
||||
const originalKey = expandedUpdates[key];
|
||||
const correctOriginalKey = expandedStyles[key];
|
||||
if (correctOriginalKey && originalKey !== correctOriginalKey) {
|
||||
const warningKey = originalKey + ',' + correctOriginalKey;
|
||||
if (warnedAbout[warningKey]) {
|
||||
continue;
|
||||
const expandedUpdates = expandShorthandMap(styleUpdates);
|
||||
const expandedStyles = expandShorthandMap(nextStyles);
|
||||
const warnedAbout = {};
|
||||
for (const key in expandedUpdates) {
|
||||
const originalKey = expandedUpdates[key];
|
||||
const correctOriginalKey = expandedStyles[key];
|
||||
if (correctOriginalKey && originalKey !== correctOriginalKey) {
|
||||
const warningKey = originalKey + ',' + correctOriginalKey;
|
||||
if (warnedAbout[warningKey]) {
|
||||
continue;
|
||||
}
|
||||
warnedAbout[warningKey] = true;
|
||||
warning(
|
||||
false,
|
||||
'%s a style property during rerender (%s) when a ' +
|
||||
'conflicting property is set (%s) can lead to styling bugs. To ' +
|
||||
"avoid this, don't mix shorthand and non-shorthand properties " +
|
||||
'for the same value; instead, replace the shorthand with ' +
|
||||
'separate values.',
|
||||
isValueEmpty(styleUpdates[originalKey]) ? 'Removing' : 'Updating',
|
||||
originalKey,
|
||||
correctOriginalKey,
|
||||
);
|
||||
}
|
||||
warnedAbout[warningKey] = true;
|
||||
warning(
|
||||
false,
|
||||
'%s a style property during rerender (%s) when a ' +
|
||||
'conflicting property is set (%s) can lead to styling bugs. To ' +
|
||||
"avoid this, don't mix shorthand and non-shorthand properties " +
|
||||
'for the same value; instead, replace the shorthand with ' +
|
||||
'separate values.',
|
||||
isValueEmpty(styleUpdates[originalKey]) ? 'Removing' : 'Updating',
|
||||
originalKey,
|
||||
correctOriginalKey,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,22 +31,26 @@ function validateProperty(tagName, name) {
|
||||
// If this is an aria-* attribute, but is not listed in the known DOM
|
||||
// DOM properties, then it is an invalid aria-* attribute.
|
||||
if (correctName == null) {
|
||||
warning(
|
||||
false,
|
||||
'Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.',
|
||||
name,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.',
|
||||
name,
|
||||
);
|
||||
}
|
||||
warnedProperties[name] = true;
|
||||
return true;
|
||||
}
|
||||
// aria-* attributes should be lowercase; suggest the lowercase version.
|
||||
if (name !== correctName) {
|
||||
warning(
|
||||
false,
|
||||
'Invalid ARIA attribute `%s`. Did you mean `%s`?',
|
||||
name,
|
||||
correctName,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'Invalid ARIA attribute `%s`. Did you mean `%s`?',
|
||||
name,
|
||||
correctName,
|
||||
);
|
||||
}
|
||||
warnedProperties[name] = true;
|
||||
return true;
|
||||
}
|
||||
@@ -66,12 +70,14 @@ function validateProperty(tagName, name) {
|
||||
}
|
||||
// aria-* attributes should be lowercase; suggest the lowercase version.
|
||||
if (name !== standardName) {
|
||||
warning(
|
||||
false,
|
||||
'Unknown ARIA attribute `%s`. Did you mean `%s`?',
|
||||
name,
|
||||
standardName,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'Unknown ARIA attribute `%s`. Did you mean `%s`?',
|
||||
name,
|
||||
standardName,
|
||||
);
|
||||
}
|
||||
warnedProperties[name] = true;
|
||||
return true;
|
||||
}
|
||||
@@ -95,21 +101,25 @@ function warnInvalidARIAProps(type, props) {
|
||||
.join(', ');
|
||||
|
||||
if (invalidProps.length === 1) {
|
||||
warning(
|
||||
false,
|
||||
'Invalid aria prop %s on <%s> tag. ' +
|
||||
'For details, see https://fb.me/invalid-aria-prop',
|
||||
unknownPropString,
|
||||
type,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'Invalid aria prop %s on <%s> tag. ' +
|
||||
'For details, see https://fb.me/invalid-aria-prop',
|
||||
unknownPropString,
|
||||
type,
|
||||
);
|
||||
}
|
||||
} else if (invalidProps.length > 1) {
|
||||
warning(
|
||||
false,
|
||||
'Invalid aria props %s on <%s> tag. ' +
|
||||
'For details, see https://fb.me/invalid-aria-prop',
|
||||
unknownPropString,
|
||||
type,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'Invalid aria props %s on <%s> tag. ' +
|
||||
'For details, see https://fb.me/invalid-aria-prop',
|
||||
unknownPropString,
|
||||
type,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,21 +17,25 @@ export function validateProperties(type, props) {
|
||||
if (props != null && props.value === null && !didWarnValueNull) {
|
||||
didWarnValueNull = true;
|
||||
if (type === 'select' && props.multiple) {
|
||||
warning(
|
||||
false,
|
||||
'`value` prop on `%s` should not be null. ' +
|
||||
'Consider using an empty array when `multiple` is set to `true` ' +
|
||||
'to clear the component or `undefined` for uncontrolled components.',
|
||||
type,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'`value` prop on `%s` should not be null. ' +
|
||||
'Consider using an empty array when `multiple` is set to `true` ' +
|
||||
'to clear the component or `undefined` for uncontrolled components.',
|
||||
type,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
warning(
|
||||
false,
|
||||
'`value` prop on `%s` should not be null. ' +
|
||||
'Consider using an empty string to clear the component or `undefined` ' +
|
||||
'for uncontrolled components.',
|
||||
type,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'`value` prop on `%s` should not be null. ' +
|
||||
'Consider using an empty string to clear the component or `undefined` ' +
|
||||
'for uncontrolled components.',
|
||||
type,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,23 +267,27 @@ const warnUnknownProperties = function(type, props, canUseEventSystem) {
|
||||
.map(prop => '`' + prop + '`')
|
||||
.join(', ');
|
||||
if (unknownProps.length === 1) {
|
||||
warning(
|
||||
false,
|
||||
'Invalid value for prop %s on <%s> tag. Either remove it from the element, ' +
|
||||
'or pass a string or number value to keep it in the DOM. ' +
|
||||
'For details, see https://fb.me/react-attribute-behavior',
|
||||
unknownPropString,
|
||||
type,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'Invalid value for prop %s on <%s> tag. Either remove it from the element, ' +
|
||||
'or pass a string or number value to keep it in the DOM. ' +
|
||||
'For details, see https://fb.me/react-attribute-behavior',
|
||||
unknownPropString,
|
||||
type,
|
||||
);
|
||||
}
|
||||
} else if (unknownProps.length > 1) {
|
||||
warning(
|
||||
false,
|
||||
'Invalid values for props %s on <%s> tag. Either remove them from the element, ' +
|
||||
'or pass a string or number value to keep them in the DOM. ' +
|
||||
'For details, see https://fb.me/react-attribute-behavior',
|
||||
unknownPropString,
|
||||
type,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'Invalid values for props %s on <%s> tag. Either remove them from the element, ' +
|
||||
'or pass a string or number value to keep them in the DOM. ' +
|
||||
'For details, see https://fb.me/react-attribute-behavior',
|
||||
unknownPropString,
|
||||
type,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -361,12 +361,14 @@ const ReactTestUtils = {
|
||||
mockComponent: function(module, mockTagName) {
|
||||
if (!hasWarnedAboutDeprecatedMockComponent) {
|
||||
hasWarnedAboutDeprecatedMockComponent = true;
|
||||
lowPriorityWarningWithoutStack(
|
||||
false,
|
||||
'ReactTestUtils.mockComponent() is deprecated. ' +
|
||||
'Use shallow rendering or jest.mock() instead.\n\n' +
|
||||
'See https://fb.me/test-utils-mock-component for more information.',
|
||||
);
|
||||
if (__DEV__) {
|
||||
lowPriorityWarningWithoutStack(
|
||||
false,
|
||||
'ReactTestUtils.mockComponent() is deprecated. ' +
|
||||
'Use shallow rendering or jest.mock() instead.\n\n' +
|
||||
'See https://fb.me/test-utils-mock-component for more information.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
mockTagName = mockTagName || module.mockTagName || 'div';
|
||||
|
||||
@@ -179,12 +179,14 @@ export default function(
|
||||
}
|
||||
|
||||
if (maybeInstance.canonical) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: measureLayout on components using NativeMethodsMixin ' +
|
||||
'or ReactNative.NativeComponent is not currently supported in Fabric. ' +
|
||||
'measureLayout must be called on a native ref. Consider using forwardRef.',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: measureLayout on components using NativeMethodsMixin ' +
|
||||
'or ReactNative.NativeComponent is not currently supported in Fabric. ' +
|
||||
'measureLayout must be called on a native ref. Consider using forwardRef.',
|
||||
);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
let relativeNode;
|
||||
@@ -197,10 +199,12 @@ export default function(
|
||||
}
|
||||
|
||||
if (relativeNode == null) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: ref.measureLayout must be called with a node handle or a ref to a native component.',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: ref.measureLayout must be called with a node handle or a ref to a native component.',
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -243,10 +247,12 @@ export default function(
|
||||
}
|
||||
|
||||
if (maybeInstance.canonical) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: setNativeProps is not currently supported in Fabric',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: setNativeProps is not currently supported in Fabric',
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -165,11 +165,13 @@ const ReactFabric: ReactFabricType = {
|
||||
handle._nativeTag == null || handle._internalInstanceHandle == null;
|
||||
|
||||
if (invalid) {
|
||||
warningWithoutStack(
|
||||
!invalid,
|
||||
"dispatchCommand was called with a ref that isn't a " +
|
||||
'native component. Use React.forwardRef to get access to the underlying native component',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
!invalid,
|
||||
"dispatchCommand was called with a ref that isn't a " +
|
||||
'native component. Use React.forwardRef to get access to the underlying native component',
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -159,10 +159,12 @@ class ReactFabricHostComponent {
|
||||
typeof relativeToNativeNode === 'number' ||
|
||||
!(relativeToNativeNode instanceof ReactFabricHostComponent)
|
||||
) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: ref.measureLayout must be called with a ref to a native component.',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: ref.measureLayout must be called with a ref to a native component.',
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -176,10 +178,12 @@ class ReactFabricHostComponent {
|
||||
}
|
||||
|
||||
setNativeProps(nativeProps: Object) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: setNativeProps is not currently supported in Fabric',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: setNativeProps is not currently supported in Fabric',
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -190,12 +190,14 @@ export default function(
|
||||
}
|
||||
|
||||
if (maybeInstance.canonical) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: measureLayout on components using NativeMethodsMixin ' +
|
||||
'or ReactNative.NativeComponent is not currently supported in Fabric. ' +
|
||||
'measureLayout must be called on a native ref. Consider using forwardRef.',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: measureLayout on components using NativeMethodsMixin ' +
|
||||
'or ReactNative.NativeComponent is not currently supported in Fabric. ' +
|
||||
'measureLayout must be called on a native ref. Consider using forwardRef.',
|
||||
);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
let relativeNode;
|
||||
@@ -208,10 +210,12 @@ export default function(
|
||||
}
|
||||
|
||||
if (relativeNode == null) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: ref.measureLayout must be called with a node handle or a ref to a native component.',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: ref.measureLayout must be called with a node handle or a ref to a native component.',
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -254,10 +258,12 @@ export default function(
|
||||
}
|
||||
|
||||
if (maybeInstance.canonical) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: setNativeProps is not currently supported in Fabric',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: setNativeProps is not currently supported in Fabric',
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,10 +85,12 @@ class ReactNativeFiberHostComponent {
|
||||
}
|
||||
|
||||
if (relativeNode == null) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: ref.measureLayout must be called with a node handle or a ref to a native component.',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Warning: ref.measureLayout must be called with a node handle or a ref to a native component.',
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -172,11 +172,13 @@ const ReactNativeRenderer: ReactNativeType = {
|
||||
|
||||
dispatchCommand(handle: any, command: string, args: Array<any>) {
|
||||
if (handle._nativeTag == null) {
|
||||
warningWithoutStack(
|
||||
handle._nativeTag != null,
|
||||
"dispatchCommand was called with a ref that isn't a " +
|
||||
'native component. Use React.forwardRef to get access to the underlying native component',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
handle._nativeTag != null,
|
||||
"dispatchCommand was called with a ref that isn't a " +
|
||||
'native component. Use React.forwardRef to get access to the underlying native component',
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
14
packages/react-reconciler/src/ReactChildFiber.js
vendored
14
packages/react-reconciler/src/ReactChildFiber.js
vendored
@@ -243,12 +243,14 @@ function warnOnFunctionType() {
|
||||
}
|
||||
ownerHasFunctionTypeWarning[currentComponentErrorInfo] = true;
|
||||
|
||||
warning(
|
||||
false,
|
||||
'Functions are not valid as a React child. This may happen if ' +
|
||||
'you return a Component instead of <Component /> from render. ' +
|
||||
'Or maybe you meant to call this function rather than return it.',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'Functions are not valid as a React child. This may happen if ' +
|
||||
'you return a Component instead of <Component /> from render. ' +
|
||||
'Or maybe you meant to call this function rather than return it.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// This wrapper function exists because I expect to clone the code in each path
|
||||
|
||||
@@ -1398,11 +1398,13 @@ function mountIndeterminateComponent(
|
||||
|
||||
function validateFunctionComponentInDev(workInProgress: Fiber, Component: any) {
|
||||
if (Component) {
|
||||
warningWithoutStack(
|
||||
!Component.childContextTypes,
|
||||
'%s(...): childContextTypes cannot be defined on a function component.',
|
||||
Component.displayName || Component.name || 'Component',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
!Component.childContextTypes,
|
||||
'%s(...): childContextTypes cannot be defined on a function component.',
|
||||
Component.displayName || Component.name || 'Component',
|
||||
);
|
||||
}
|
||||
}
|
||||
if (workInProgress.ref !== null) {
|
||||
let info = '';
|
||||
@@ -1418,13 +1420,15 @@ function validateFunctionComponentInDev(workInProgress: Fiber, Component: any) {
|
||||
}
|
||||
if (!didWarnAboutFunctionRefs[warningKey]) {
|
||||
didWarnAboutFunctionRefs[warningKey] = true;
|
||||
warning(
|
||||
false,
|
||||
'Function components cannot be given refs. ' +
|
||||
'Attempts to access this ref will fail. ' +
|
||||
'Did you mean to use React.forwardRef()?%s',
|
||||
info,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'Function components cannot be given refs. ' +
|
||||
'Attempts to access this ref will fail. ' +
|
||||
'Did you mean to use React.forwardRef()?%s',
|
||||
info,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1435,12 +1439,14 @@ function validateFunctionComponentInDev(workInProgress: Fiber, Component: any) {
|
||||
const componentName = getComponentName(Component) || 'Unknown';
|
||||
|
||||
if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'%s: Support for defaultProps will be removed from function components ' +
|
||||
'in a future major release. Use JavaScript default parameters instead.',
|
||||
componentName,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'%s: Support for defaultProps will be removed from function components ' +
|
||||
'in a future major release. Use JavaScript default parameters instead.',
|
||||
componentName,
|
||||
);
|
||||
}
|
||||
didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true;
|
||||
}
|
||||
}
|
||||
@@ -1449,11 +1455,13 @@ function validateFunctionComponentInDev(workInProgress: Fiber, Component: any) {
|
||||
const componentName = getComponentName(Component) || 'Unknown';
|
||||
|
||||
if (!didWarnAboutGetDerivedStateOnFunctionComponent[componentName]) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'%s: Function components do not support getDerivedStateFromProps.',
|
||||
componentName,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'%s: Function components do not support getDerivedStateFromProps.',
|
||||
componentName,
|
||||
);
|
||||
}
|
||||
didWarnAboutGetDerivedStateOnFunctionComponent[componentName] = true;
|
||||
}
|
||||
}
|
||||
@@ -1465,11 +1473,13 @@ function validateFunctionComponentInDev(workInProgress: Fiber, Component: any) {
|
||||
const componentName = getComponentName(Component) || 'Unknown';
|
||||
|
||||
if (!didWarnAboutContextTypeOnFunctionComponent[componentName]) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'%s: Function components do not support contextType.',
|
||||
componentName,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'%s: Function components do not support contextType.',
|
||||
componentName,
|
||||
);
|
||||
}
|
||||
didWarnAboutContextTypeOnFunctionComponent[componentName] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,12 +280,14 @@ export function updateContainer(
|
||||
|
||||
callback = callback === undefined ? null : callback;
|
||||
if (callback !== null) {
|
||||
warningWithoutStack(
|
||||
typeof callback === 'function',
|
||||
'render(...): Expected the last optional `callback` argument to be a ' +
|
||||
'function. Instead received: %s.',
|
||||
callback,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
typeof callback === 'function',
|
||||
'render(...): Expected the last optional `callback` argument to be a ' +
|
||||
'function. Instead received: %s.',
|
||||
callback,
|
||||
);
|
||||
}
|
||||
update.callback = callback;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,29 +61,33 @@ function areHookInputsEqual(
|
||||
prevDeps: Array<mixed> | null,
|
||||
) {
|
||||
if (prevDeps === null) {
|
||||
warning(
|
||||
false,
|
||||
'%s received a final argument during this render, but not during ' +
|
||||
'the previous render. Even though the final argument is optional, ' +
|
||||
'its type cannot change between renders.',
|
||||
currentHookNameInDev,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'%s received a final argument during this render, but not during ' +
|
||||
'the previous render. Even though the final argument is optional, ' +
|
||||
'its type cannot change between renders.',
|
||||
currentHookNameInDev,
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't bother comparing lengths in prod because these arrays should be
|
||||
// passed inline.
|
||||
if (nextDeps.length !== prevDeps.length) {
|
||||
warning(
|
||||
false,
|
||||
'The final argument passed to %s changed size between renders. The ' +
|
||||
'order and size of this array must remain constant.\n\n' +
|
||||
'Previous: %s\n' +
|
||||
'Incoming: %s',
|
||||
currentHookNameInDev,
|
||||
`[${nextDeps.join(', ')}]`,
|
||||
`[${prevDeps.join(', ')}]`,
|
||||
);
|
||||
if (__DEV__) {
|
||||
// Don't bother comparing lengths in prod because these arrays should be
|
||||
// passed inline.
|
||||
if (nextDeps.length !== prevDeps.length) {
|
||||
warning(
|
||||
false,
|
||||
'The final argument passed to %s changed size between renders. The ' +
|
||||
'order and size of this array must remain constant.\n\n' +
|
||||
'Previous: %s\n' +
|
||||
'Incoming: %s',
|
||||
currentHookNameInDev,
|
||||
`[${nextDeps.join(', ')}]`,
|
||||
`[${prevDeps.join(', ')}]`,
|
||||
);
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < prevDeps.length && i < nextDeps.length; i++) {
|
||||
if (is(nextDeps[i], prevDeps[i])) {
|
||||
|
||||
@@ -50,14 +50,16 @@ function defineKeyPropWarningGetter(props, displayName) {
|
||||
const warnAboutAccessingKey = function() {
|
||||
if (!specialPropKeyWarningShown) {
|
||||
specialPropKeyWarningShown = true;
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'%s: `key` is not a prop. Trying to access it will result ' +
|
||||
'in `undefined` being returned. If you need to access the same ' +
|
||||
'value within the child component, you should pass it as a different ' +
|
||||
'prop. (https://fb.me/react-special-props)',
|
||||
displayName,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'%s: `key` is not a prop. Trying to access it will result ' +
|
||||
'in `undefined` being returned. If you need to access the same ' +
|
||||
'value within the child component, you should pass it as a different ' +
|
||||
'prop. (https://fb.me/react-special-props)',
|
||||
displayName,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
warnAboutAccessingKey.isReactWarning = true;
|
||||
@@ -71,14 +73,16 @@ function defineRefPropWarningGetter(props, displayName) {
|
||||
const warnAboutAccessingRef = function() {
|
||||
if (!specialPropRefWarningShown) {
|
||||
specialPropRefWarningShown = true;
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'%s: `ref` is not a prop. Trying to access it will result ' +
|
||||
'in `undefined` being returned. If you need to access the same ' +
|
||||
'value within the child component, you should pass it as a different ' +
|
||||
'prop. (https://fb.me/react-special-props)',
|
||||
displayName,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'%s: `ref` is not a prop. Trying to access it will result ' +
|
||||
'in `undefined` being returned. If you need to access the same ' +
|
||||
'value within the child component, you should pass it as a different ' +
|
||||
'prop. (https://fb.me/react-special-props)',
|
||||
displayName,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
warnAboutAccessingRef.isReactWarning = true;
|
||||
|
||||
@@ -225,18 +225,22 @@ function validatePropTypes(element) {
|
||||
setCurrentlyValidatingElement(null);
|
||||
} else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {
|
||||
propTypesMisspellWarningShown = true;
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?',
|
||||
name || 'Unknown',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
false,
|
||||
'Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?',
|
||||
name || 'Unknown',
|
||||
);
|
||||
}
|
||||
}
|
||||
if (typeof type.getDefaultProps === 'function') {
|
||||
warningWithoutStack(
|
||||
type.getDefaultProps.isReactClassApproved,
|
||||
'getDefaultProps is only used on classic React.createClass ' +
|
||||
'definitions. Use a static property named `defaultProps` instead.',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warningWithoutStack(
|
||||
type.getDefaultProps.isReactClassApproved,
|
||||
'getDefaultProps is only used on classic React.createClass ' +
|
||||
'definitions. Use a static property named `defaultProps` instead.',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,18 +255,22 @@ function validateFragmentProps(fragment) {
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i];
|
||||
if (key !== 'children' && key !== 'key') {
|
||||
warning(
|
||||
false,
|
||||
'Invalid prop `%s` supplied to `React.Fragment`. ' +
|
||||
'React.Fragment can only have `key` and `children` props.',
|
||||
key,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'Invalid prop `%s` supplied to `React.Fragment`. ' +
|
||||
'React.Fragment can only have `key` and `children` props.',
|
||||
key,
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fragment.ref !== null) {
|
||||
warning(false, 'Invalid attribute `ref` supplied to `React.Fragment`.');
|
||||
if (__DEV__) {
|
||||
warning(false, 'Invalid attribute `ref` supplied to `React.Fragment`.');
|
||||
}
|
||||
}
|
||||
|
||||
setCurrentlyValidatingElement(null);
|
||||
@@ -313,14 +321,16 @@ export function jsxWithValidation(
|
||||
typeString = typeof type;
|
||||
}
|
||||
|
||||
warning(
|
||||
false,
|
||||
'React.jsx: type is invalid -- expected a string (for ' +
|
||||
'built-in components) or a class/function (for composite ' +
|
||||
'components) but got: %s.%s',
|
||||
typeString,
|
||||
info,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'React.jsx: type is invalid -- expected a string (for ' +
|
||||
'built-in components) or a class/function (for composite ' +
|
||||
'components) but got: %s.%s',
|
||||
typeString,
|
||||
info,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const element = jsxDEV(type, props, key, source, self);
|
||||
@@ -350,12 +360,14 @@ export function jsxWithValidation(
|
||||
Object.freeze(children);
|
||||
}
|
||||
} else {
|
||||
warning(
|
||||
false,
|
||||
'React.jsx: Static children should always be an array. ' +
|
||||
'You are likely explicitly calling React.jsxs or React.jsxDEV. ' +
|
||||
'Use the Babel transform instead.',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'React.jsx: Static children should always be an array. ' +
|
||||
'You are likely explicitly calling React.jsxs or React.jsxDEV. ' +
|
||||
'Use the Babel transform instead.',
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
validateChildKeys(children, type);
|
||||
@@ -364,12 +376,14 @@ export function jsxWithValidation(
|
||||
}
|
||||
|
||||
if (hasOwnProperty.call(props, 'key')) {
|
||||
warning(
|
||||
false,
|
||||
'React.jsx: Spreading a key to JSX is a deprecated pattern. ' +
|
||||
'Explicitly pass a key after spreading props in your JSX call. ' +
|
||||
'E.g. <ComponentName {...props} key={key} />',
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'React.jsx: Spreading a key to JSX is a deprecated pattern. ' +
|
||||
'Explicitly pass a key after spreading props in your JSX call. ' +
|
||||
'E.g. <ComponentName {...props} key={key} />',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (type === REACT_FRAGMENT_TYPE) {
|
||||
@@ -431,14 +445,16 @@ export function createElementWithValidation(type, props, children) {
|
||||
typeString = typeof type;
|
||||
}
|
||||
|
||||
warning(
|
||||
false,
|
||||
'React.createElement: type is invalid -- expected a string (for ' +
|
||||
'built-in components) or a class/function (for composite ' +
|
||||
'components) but got: %s.%s',
|
||||
typeString,
|
||||
info,
|
||||
);
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
false,
|
||||
'React.createElement: type is invalid -- expected a string (for ' +
|
||||
'built-in components) or a class/function (for composite ' +
|
||||
'components) but got: %s.%s',
|
||||
typeString,
|
||||
info,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const element = createElement.apply(this, arguments);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
'use strict';
|
||||
|
||||
let babel = require('@babel/core');
|
||||
let wrapWarningWithEnvCheck = require('../wrap-warning-with-env-check');
|
||||
let wrapWarningWithEnvCheck = require('../lift-warning-conditional-argument');
|
||||
|
||||
function transform(input) {
|
||||
return babel.transform(input, {
|
||||
@@ -23,7 +23,7 @@ function compare(input, output) {
|
||||
|
||||
let oldEnv;
|
||||
|
||||
describe('wrap-warning-with-env-check', () => {
|
||||
describe('lift-warning-conditional-argument', () => {
|
||||
beforeEach(() => {
|
||||
oldEnv = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = '';
|
||||
@@ -36,14 +36,14 @@ describe('wrap-warning-with-env-check', () => {
|
||||
it('should wrap warning calls', () => {
|
||||
compare(
|
||||
"warning(condition, 'a %s b', 'c');",
|
||||
"__DEV__ ? !condition ? warning(false, 'a %s b', 'c') : void 0 : void 0;"
|
||||
"!condition ? warning(false, 'a %s b', 'c') : void 0;"
|
||||
);
|
||||
});
|
||||
|
||||
it('should wrap warningWithoutStack calls', () => {
|
||||
compare(
|
||||
"warningWithoutStack(condition, 'a %s b', 'c');",
|
||||
"__DEV__ ? !condition ? warningWithoutStack(false, 'a %s b', 'c') : void 0 : void 0;"
|
||||
"!condition ? warningWithoutStack(false, 'a %s b', 'c') : void 0;"
|
||||
);
|
||||
});
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
module.exports = function(babel, options) {
|
||||
const t = babel.types;
|
||||
|
||||
const DEV_EXPRESSION = t.identifier('__DEV__');
|
||||
|
||||
const SEEN_SYMBOL = Symbol('expression.seen');
|
||||
|
||||
return {
|
||||
@@ -34,10 +32,8 @@ module.exports = function(babel, options) {
|
||||
//
|
||||
// into this:
|
||||
//
|
||||
// if (__DEV__) {
|
||||
// if (!condition) {
|
||||
// warning(false, argument, argument);
|
||||
// }
|
||||
// if (!condition) {
|
||||
// warning(false, argument, argument);
|
||||
// }
|
||||
//
|
||||
// The goal is to strip out warning calls entirely in production
|
||||
@@ -50,13 +46,8 @@ module.exports = function(babel, options) {
|
||||
newNode[SEEN_SYMBOL] = true;
|
||||
path.replaceWith(
|
||||
t.ifStatement(
|
||||
DEV_EXPRESSION,
|
||||
t.blockStatement([
|
||||
t.ifStatement(
|
||||
t.unaryExpression('!', condition),
|
||||
t.expressionStatement(newNode)
|
||||
),
|
||||
])
|
||||
t.unaryExpression('!', condition),
|
||||
t.expressionStatement(newNode)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @emails react-core
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const rule = require('../no-production-logging');
|
||||
const RuleTester = require('eslint').RuleTester;
|
||||
const ruleTester = new RuleTester();
|
||||
|
||||
ruleTester.run('no-production-logging', rule, {
|
||||
valid: [
|
||||
/* wrapped calls */
|
||||
{
|
||||
code: 'if (__DEV__) { warningWithoutStack(test) }',
|
||||
},
|
||||
{
|
||||
code: 'if (__DEV__) { warning(test) }',
|
||||
},
|
||||
/* calls wrapped on an outer bound */
|
||||
{
|
||||
code: 'if (__DEV__) { if (potato) { while (true) { warning(test) } } }',
|
||||
},
|
||||
/* calls wrapped on an if with && */
|
||||
{
|
||||
code: 'if (banana && __DEV__ && potato && kitten) { warning(test) }',
|
||||
},
|
||||
/* don't do anything to arbitrary fn's or invariants */
|
||||
{
|
||||
code: 'normalFunctionCall(test)',
|
||||
},
|
||||
{
|
||||
code: 'invariant(test)',
|
||||
},
|
||||
],
|
||||
invalid: [
|
||||
{
|
||||
code: 'warningWithoutStack(test)',
|
||||
errors: [
|
||||
{
|
||||
message: `We don't emit warnings in production builds. Wrap warningWithoutStack() in an "if (__DEV__) {}" check`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
code: 'if (potato) { warningWithoutStack(test) }',
|
||||
errors: [
|
||||
{
|
||||
message: `We don't emit warnings in production builds. Wrap warningWithoutStack() in an "if (__DEV__) {}" check`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
code: 'warning(test)',
|
||||
errors: [
|
||||
{
|
||||
message: `We don't emit warnings in production builds. Wrap warning() in an "if (__DEV__) {}" check`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
code: 'if (__DEV__ || potato && true) { warning(test) }',
|
||||
errors: [
|
||||
{
|
||||
message: `We don't emit warnings in production builds. Wrap warning() in an "if (__DEV__) {}" check`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -5,5 +5,6 @@ module.exports = {
|
||||
'no-primitive-constructors': require('./no-primitive-constructors'),
|
||||
'no-to-warn-dev-within-to-throw': require('./no-to-warn-dev-within-to-throw'),
|
||||
'warning-and-invariant-args': require('./warning-and-invariant-args'),
|
||||
'no-production-logging': require('./no-production-logging'),
|
||||
},
|
||||
};
|
||||
|
||||
82
scripts/eslint-rules/no-production-logging.js
Normal file
82
scripts/eslint-rules/no-production-logging.js
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @emails react-core
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const LOGGER_FN_NAMES = [
|
||||
'warning',
|
||||
'warningWithoutStack',
|
||||
'lowPriorityWarning',
|
||||
'lowPriorityWarningWithoutStack',
|
||||
];
|
||||
const DEV_EXPRESSION = '__DEV__';
|
||||
|
||||
module.exports = function(context) {
|
||||
function traverseIf(node) {
|
||||
switch (node.type) {
|
||||
case 'Identifier':
|
||||
return [node.name];
|
||||
case 'LogicalExpression':
|
||||
if (node.operator === '&&') {
|
||||
return [...traverseIf(node.left), ...traverseIf(node.right)];
|
||||
}
|
||||
return [];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function hasIfInParents(node) {
|
||||
let done = false;
|
||||
while (!done) {
|
||||
if (!node.parent) {
|
||||
return false;
|
||||
}
|
||||
node = node.parent;
|
||||
if (
|
||||
node.type === 'IfStatement' &&
|
||||
traverseIf(node.test).includes(DEV_EXPRESSION)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function report(node) {
|
||||
context.report({
|
||||
node: node,
|
||||
message: `We don't emit warnings in production builds. Wrap {{identifier}}() in an "if (${DEV_EXPRESSION}) {}" check`,
|
||||
data: {
|
||||
identifier: node.callee.name,
|
||||
},
|
||||
fix: function(fixer) {
|
||||
return [
|
||||
fixer.insertTextBefore(node.parent, `if (${DEV_EXPRESSION}) {`),
|
||||
fixer.insertTextAfter(node.parent, '}'),
|
||||
];
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const isLoggerFunctionName = name => LOGGER_FN_NAMES.includes(name);
|
||||
|
||||
return {
|
||||
meta: {
|
||||
fixable: 'code',
|
||||
},
|
||||
CallExpression: function(node) {
|
||||
if (!isLoggerFunctionName(node.callee.name)) {
|
||||
return;
|
||||
}
|
||||
if (!hasIfInParents(node)) {
|
||||
report(node);
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -17,7 +17,7 @@ const pathToBabelPluginDevWithCode = require.resolve(
|
||||
'../error-codes/transform-error-messages'
|
||||
);
|
||||
const pathToBabelPluginWrapWarning = require.resolve(
|
||||
'../babel/wrap-warning-with-env-check'
|
||||
'../babel/lift-warning-conditional-argument'
|
||||
);
|
||||
const pathToBabelPluginAsyncToGenerator = require.resolve(
|
||||
'@babel/plugin-transform-async-to-generator'
|
||||
|
||||
@@ -125,7 +125,7 @@ function getBabelConfig(updateBabelOptions, bundleType, filename) {
|
||||
// Minify invariant messages
|
||||
require('../error-codes/transform-error-messages'),
|
||||
// Wrap warning() calls in a __DEV__ check so they are stripped from production.
|
||||
require('../babel/wrap-warning-with-env-check'),
|
||||
require('../babel/lift-warning-conditional-argument'),
|
||||
]),
|
||||
});
|
||||
case RN_OSS_DEV:
|
||||
@@ -142,7 +142,7 @@ function getBabelConfig(updateBabelOptions, bundleType, filename) {
|
||||
{noMinify: true},
|
||||
],
|
||||
// Wrap warning() calls in a __DEV__ check so they are stripped from production.
|
||||
require('../babel/wrap-warning-with-env-check'),
|
||||
require('../babel/lift-warning-conditional-argument'),
|
||||
]),
|
||||
});
|
||||
case UMD_DEV:
|
||||
@@ -158,7 +158,7 @@ function getBabelConfig(updateBabelOptions, bundleType, filename) {
|
||||
// Minify invariant messages
|
||||
require('../error-codes/transform-error-messages'),
|
||||
// Wrap warning() calls in a __DEV__ check so they are stripped from production.
|
||||
require('../babel/wrap-warning-with-env-check'),
|
||||
require('../babel/lift-warning-conditional-argument'),
|
||||
]),
|
||||
});
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user