Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include component stack to invariants #18315

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions packages/react-dom/src/client/ReactDOMInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
*/

// TODO: direct imports like some-package/src/* are bad. Fix me.
import {getCurrentFiberOwnerNameInDevOrNull} from 'react-reconciler/src/ReactCurrentFiber';
import {
getCurrentFiberStackInDev,
getCurrentFiberOwnerNameInDevOrNull,
} from 'react-reconciler/src/ReactCurrentFiber';
import invariant from 'shared/invariant';

import {setValueForProperty} from './DOMPropertyOperations';
Expand Down Expand Up @@ -381,7 +384,8 @@ function updateNamedCousins(rootNode, props) {
invariant(
otherProps,
'ReactDOMInput: Mixing React and non-React radio inputs with the ' +
'same `name` is not supported.',
'same `name` is not supported.%s',
getCurrentFiberStackInDev(),
);

// We need update the tracked value on the named cousin since the value
Expand Down
8 changes: 6 additions & 2 deletions packages/react-dom/src/client/ReactDOMTextarea.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
import invariant from 'shared/invariant';

import ReactControlledValuePropTypes from '../shared/ReactControlledValuePropTypes';
import {getCurrentFiberOwnerNameInDevOrNull} from 'react-reconciler/src/ReactCurrentFiber';
import {
getCurrentFiberStackInDev,
getCurrentFiberOwnerNameInDevOrNull,
} from 'react-reconciler/src/ReactCurrentFiber';
import {getToStringValue, toString} from './ToStringValue';
import type {ToStringValue} from './ToStringValue';

Expand Down Expand Up @@ -42,7 +45,8 @@ export function getHostProps(element: Element, props: Object) {
const node = ((element: any): TextAreaWithWrapperState);
invariant(
props.dangerouslySetInnerHTML == null,
'`dangerouslySetInnerHTML` does not make sense on <textarea>.',
'`dangerouslySetInnerHTML` does not make sense on <textarea>.%s',
getCurrentFiberStackInDev(),
);

// Always set children to the same thing. In IE9, the selection range will
Expand Down
4 changes: 3 additions & 1 deletion packages/react-dom/src/server/ReactPartialRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import type {ThreadID} from './ReactThreadIDAllocator';
import type {ReactElement} from 'shared/ReactElementType';
import type {LazyComponent} from 'react/src/ReactLazy';
import {getCurrentFiberStackInDev} from 'react-reconciler/src/ReactCurrentFiber';
import type {ReactProvider, ReactContext} from 'shared/ReactTypes';

import * as React from 'react';
Expand Down Expand Up @@ -1321,9 +1322,10 @@ class ReactDOMServerRenderer {
false,
'Element type is invalid: expected a string (for built-in ' +
'components) or a class/function (for composite components) ' +
'but got: %s.%s',
'but got: %s.%s%s',
elementType == null ? elementType : typeof elementType,
info,
getCurrentFiberStackInDev(),
);
}
}
Expand Down
12 changes: 8 additions & 4 deletions packages/react-reconciler/src/ReactChildFiber.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,9 @@ function coerceRef(
invariant(
inst,
'Missing owner for string ref %s. This error is likely caused by a ' +
'bug in React. Please file an issue.',
'bug in React. Please file an issue.%s',
mixedRef,
getCurrentFiberStackInDev(),
);
const stringRef = '' + mixedRef;
// Check if previous string ref matches new string ref
Expand Down Expand Up @@ -205,7 +206,8 @@ function coerceRef(
} else {
invariant(
typeof mixedRef === 'string',
'Expected ref to be a function, a string, an object returned by React.createRef(), or null.',
'Expected ref to be a function, a string, an object returned by React.createRef(), or null.%s',
getCurrentFiberStackInDev(),
);
invariant(
element._owner,
Expand All @@ -214,8 +216,9 @@ function coerceRef(
'1. You may be adding a ref to a function component\n' +
"2. You may be adding a ref to a component that was not created inside a component's render method\n" +
'3. You have multiple copies of React loaded\n' +
'See https://fb.me/react-refs-must-have-owner for more information.',
'See https://fb.me/react-refs-must-have-owner for more information.%s',
mixedRef,
getCurrentFiberStackInDev(),
);
}
}
Expand Down Expand Up @@ -954,7 +957,8 @@ function ChildReconciler(shouldTrackSideEffects) {
invariant(
typeof iteratorFn === 'function',
'An object is not an iterable. This error is likely caused by a bug in ' +
'React. Please file an issue.',
'React. Please file an issue.%s',
getCurrentFiberStackInDev(),
);

if (__DEV__) {
Expand Down
4 changes: 3 additions & 1 deletion packages/react-reconciler/src/ReactFiber.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {
} from 'shared/ReactTypes';
import type {RootTag} from 'shared/ReactRootTags';
import type {WorkTag} from 'shared/ReactWorkTags';
import {getCurrentFiberStackInDev} from 'react-reconciler/src/ReactCurrentFiber';
import type {TypeOfMode} from './ReactTypeOfMode';
import type {SideEffectTag} from 'shared/ReactSideEffectTags';
import type {ExpirationTime} from './ReactFiberExpirationTime';
Expand Down Expand Up @@ -737,9 +738,10 @@ export function createFiberFromTypeAndProps(
false,
'Element type is invalid: expected a string (for built-in ' +
'components) or a class/function (for composite components) ' +
'but got: %s.%s',
'but got: %s.%s%s',
type == null ? type : typeof type,
info,
getCurrentFiberStackInDev(),
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ describe('ReactIncrementalErrorHandling', () => {
return str && str.replace(/\(at .+?:\d+\)/g, '(at **)');
}

function stripStack(comp) {
let compStripped = JSON.parse(JSON.stringify(comp));
const prop = compStripped[0].prop;
compStripped[0].prop =
(prop && prop.replace(/in .+? \(at .+?:\d+\)/g, '').trim()) || '';
return compStripped;
}

it('recovers from errors asynchronously', () => {
class ErrorBoundary extends React.Component {
state = {error: null};
Expand Down Expand Up @@ -1257,7 +1265,7 @@ describe('ReactIncrementalErrorHandling', () => {
// React retries once on error
'Warning: React.createElement: type is invalid -- expected a string',
]);
expect(ReactNoop.getChildren()).toEqual([
expect(stripStack(ReactNoop.getChildren())).toEqual([
span(
'Element type is invalid: expected a string (for built-in components) or ' +
'a class/function (for composite components) but got: undefined.' +
Expand Down Expand Up @@ -1306,7 +1314,7 @@ describe('ReactIncrementalErrorHandling', () => {
// React retries once on error
'Warning: React.createElement: type is invalid -- expected a string',
]);
expect(ReactNoop.getChildren()).toEqual([
expect(stripStack(ReactNoop.getChildren())).toEqual([
span(
'Element type is invalid: expected a string (for built-in components) or ' +
'a class/function (for composite components) but got: undefined.' +
Expand Down
14 changes: 7 additions & 7 deletions scripts/error-codes/codes.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@
"87": "Cannot provide a checkedLink and a valueLink. If you want to use checkedLink, you probably don't want to use valueLink and vice versa.",
"88": "Cannot provide a valueLink and a value or onChange event. If you want to use value or onChange, you probably don't want to use valueLink.",
"89": "Cannot provide a checkedLink and a checked property or onChange event. If you want to use checked or onChange, you probably don't want to use checkedLink",
"90": "ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.",
"91": "`dangerouslySetInnerHTML` does not make sense on <textarea>.",
"90": "ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.%s",
"91": "`dangerouslySetInnerHTML` does not make sense on <textarea>.%s",
"92": "If you supply `defaultValue` on a <textarea>, do not pass children.",
"93": "<textarea> can only have at most one child.",
"94": "Expected %s listener to be a function, instead got type %s",
Expand Down Expand Up @@ -129,7 +129,7 @@
"127": "ReactUpdates: must provide a batching strategy",
"128": "ReactUpdates: must provide a batchedUpdates() function",
"129": "ReactUpdates: must provide an isBatchingUpdates boolean attribute",
"130": "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s",
"130": "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s%s",
"131": "Encountered invalid React node of type %s",
"132": "Ended a touch event which was not counted in trackedTouchCount.",
"133": "Touch object is missing identifier",
Expand All @@ -146,10 +146,10 @@
"144": "Item must have been set",
"145": "hostContainerInfo should be populated before getPublicInstance is called.",
"146": "React Component in warnForMissingKey should have a _store. This error is likely caused by a bug in React. Please file an issue.",
"147": "Missing owner for string ref %s. This error is likely caused by a bug in React. Please file an issue.",
"147": "Missing owner for string ref %s. This error is likely caused by a bug in React. Please file an issue.%s",
"148": "Expected ref to be a function or a string.",
"149": "Element ref was specified as a string (%s) but no owner was set. You may have multiple copies of React loaded. (details: https://fb.me/react-refs-must-have-owner).",
"150": "An object is not an iterable. This error is likely caused by a bug in React. Please file an issue.",
"150": "An object is not an iterable. This error is likely caused by a bug in React. Please file an issue.%s",
"151": "An iterable object provided no iterator.",
"152": "%s(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.",
"153": "Resuming work not yet implemented.",
Expand Down Expand Up @@ -282,13 +282,13 @@
"281": "Finished root should have a work-in-progress. This error is likely caused by a bug in React. Please file an issue.",
"282": "If the root does not have an updateQueue, we should have already bailed out. This error is likely caused by a bug in React. Please file an issue.",
"283": "Element type is invalid. Received a promise that resolves to: %s. Promise elements must resolve to a class or function.",
"284": "Expected ref to be a function, a string, an object returned by React.createRef(), or null.",
"284": "Expected ref to be a function, a string, an object returned by React.createRef(), or null.%s",
"285": "The root failed to unmount after an error. This is likely a bug in React. Please file an issue.",
"286": "%s(...): the first argument must be a React class instance. Instead received: %s.",
"287": "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `schedule/tracking` module with `schedule/tracking-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling",
"288": "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `schedule/tracing` module with `schedule/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling",
"289": "Function components cannot have refs.",
"290": "Element ref was specified as a string (%s) but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information.",
"290": "Element ref was specified as a string (%s) but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information.%s",
"291": "Log of yielded values is not empty. Call expect(Scheduler).toHaveYielded(...) first.",
"292": "The matcher `toHaveYielded` expects an instance of React Test Renderer.\n\nTry: expect(Scheduler).toHaveYielded(expectedYields)",
"293": "Context can only be read while React is rendering, e.g. inside the render method or getDerivedStateFromProps.",
Expand Down