mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Protect against passing component stack twice
This is a leftover from #13161 that I forgot to include. It ensures we don't accidentally write code in the old way and end up passing the stack twice.
This commit is contained in:
@@ -161,5 +161,13 @@ describe('toWarnDev', () => {
|
||||
}).toWarnDev('Hi', {withoutStack: true});
|
||||
}).toThrow('Received 0 arguments for a message with 1 placeholders');
|
||||
});
|
||||
|
||||
it('fails if stack is passed twice', () => {
|
||||
expect(() => {
|
||||
expect(() => {
|
||||
console.error('Hi %s%s', '\n in div', '\n in div');
|
||||
}).toWarnDev('Hi');
|
||||
}).toThrow('Received more than one component stack for a warning');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -24,7 +24,9 @@ const createMatcherFor = consoleMethod =>
|
||||
const warningsWithoutComponentStack = [];
|
||||
const warningsWithComponentStack = [];
|
||||
const unexpectedWarnings = [];
|
||||
|
||||
let lastWarningWithMismatchingFormat = null;
|
||||
let lastWarningWithExtraComponentStack = null;
|
||||
|
||||
// Catch errors thrown by the callback,
|
||||
// But only rethrow them if all test expectations have been satisfied.
|
||||
@@ -32,6 +34,9 @@ const createMatcherFor = consoleMethod =>
|
||||
// and result in a test that passes when it shouldn't.
|
||||
let caughtError;
|
||||
|
||||
const isLikelyAComponentStack = message =>
|
||||
typeof message === 'string' && message.includes('\n in ');
|
||||
|
||||
const consoleSpy = (format, ...args) => {
|
||||
const message = util.format(format, ...args);
|
||||
const normalizedMessage = normalizeCodeLocInfo(message);
|
||||
@@ -49,13 +54,25 @@ const createMatcherFor = consoleMethod =>
|
||||
};
|
||||
}
|
||||
|
||||
// Protect against accidentally passing a component stack
|
||||
// to warning() which already injects the component stack.
|
||||
if (
|
||||
args.length >= 2 &&
|
||||
isLikelyAComponentStack(args[args.length - 1]) &&
|
||||
isLikelyAComponentStack(args[args.length - 2])
|
||||
) {
|
||||
lastWarningWithExtraComponentStack = {
|
||||
format,
|
||||
};
|
||||
}
|
||||
|
||||
for (let index = 0; index < expectedMessages.length; index++) {
|
||||
const expectedMessage = expectedMessages[index];
|
||||
if (
|
||||
normalizedMessage === expectedMessage ||
|
||||
normalizedMessage.includes(expectedMessage)
|
||||
) {
|
||||
if (normalizedMessage.includes('\n in ')) {
|
||||
if (isLikelyAComponentStack(normalizedMessage)) {
|
||||
warningsWithComponentStack.push(normalizedMessage);
|
||||
} else {
|
||||
warningsWithoutComponentStack.push(normalizedMessage);
|
||||
@@ -191,6 +208,17 @@ const createMatcherFor = consoleMethod =>
|
||||
};
|
||||
}
|
||||
|
||||
if (lastWarningWithExtraComponentStack !== null) {
|
||||
return {
|
||||
message: () =>
|
||||
`Received more than one component stack for a warning:\n ${this.utils.printReceived(
|
||||
lastWarningWithExtraComponentStack.format
|
||||
)}\nDid you accidentally pass a stack to warning() as the last argument? ` +
|
||||
`Don't forget warning() already injects the component stack automatically.`,
|
||||
pass: false,
|
||||
};
|
||||
}
|
||||
|
||||
return {pass: true};
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user