mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 00:20:04 +01:00
[flags] remove enableOwnerStacks (#32426)
Bassed off: https://github.com/facebook/react/pull/32425
Wait to land internally.
[Commit to
review.](66aa6a4dbb)
This has landed everywhere
This commit is contained in:
parent
d48c69246c
commit
e0fe347967
|
|
@ -857,17 +857,6 @@ describe('ReactInternalTestUtils console assertions', () => {
|
|||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
} else if (gate(flags => flags.enableOwnerStacks)) {
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"asserConsoleLogsCleared(expected)
|
||||
|
||||
console.log was called without assertConsoleLogDev:
|
||||
+ Not asserted
|
||||
+ Not asserted
|
||||
+ Not asserted
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
} else {
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"asserConsoleLogsCleared(expected)
|
||||
|
|
@ -937,20 +926,6 @@ describe('ReactInternalTestUtils console assertions', () => {
|
|||
+ B
|
||||
+ C
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
} else if (gate(flags => flags.enableOwnerStacks)) {
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"asserConsoleLogsCleared(expected)
|
||||
|
||||
console.warn was called without assertConsoleWarnDev:
|
||||
+ A%s,
|
||||
+ in App (at **)
|
||||
+ B%s,
|
||||
+ in App (at **)
|
||||
+ C%s,
|
||||
+ in App (at **)
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
} else {
|
||||
|
|
@ -959,16 +934,10 @@ describe('ReactInternalTestUtils console assertions', () => {
|
|||
|
||||
console.warn was called without assertConsoleWarnDev:
|
||||
+ A%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
+ B%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
+ C%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
|
|
@ -1023,33 +992,6 @@ describe('ReactInternalTestUtils console assertions', () => {
|
|||
+ B
|
||||
+ C
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
} else if (gate(flags => flags.enableOwnerStacks)) {
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"asserConsoleLogsCleared(expected)
|
||||
|
||||
console.log was called without assertConsoleLogDev:
|
||||
+ A
|
||||
+ B
|
||||
+ C
|
||||
|
||||
console.warn was called without assertConsoleWarnDev:
|
||||
+ A%s,
|
||||
+ in App (at **)
|
||||
+ B%s,
|
||||
+ in App (at **)
|
||||
+ C%s,
|
||||
+ in App (at **)
|
||||
|
||||
console.error was called without assertConsoleErrorDev:
|
||||
+ A%s,
|
||||
+ in App (at **)
|
||||
+ B%s,
|
||||
+ in App (at **)
|
||||
+ C%s,
|
||||
+ in App (at **)
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
} else {
|
||||
|
|
@ -1063,30 +1005,18 @@ describe('ReactInternalTestUtils console assertions', () => {
|
|||
|
||||
console.warn was called without assertConsoleWarnDev:
|
||||
+ A%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
+ B%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
+ C%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
|
||||
console.error was called without assertConsoleErrorDev:
|
||||
+ A%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
+ B%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
+ C%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
|
|
@ -1927,20 +1857,6 @@ describe('ReactInternalTestUtils console assertions', () => {
|
|||
+ Not asserted
|
||||
+ Not asserted
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
} else if (gate(flags => flags.enableOwnerStacks)) {
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"asserConsoleLogsCleared(expected)
|
||||
|
||||
console.warn was called without assertConsoleWarnDev:
|
||||
+ Not asserted%s,
|
||||
+ in Yield (at **)
|
||||
+ Not asserted%s,
|
||||
+ in Yield (at **)
|
||||
+ Not asserted%s,
|
||||
+ in Yield (at **)
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
} else {
|
||||
|
|
@ -1950,13 +1866,10 @@ describe('ReactInternalTestUtils console assertions', () => {
|
|||
console.warn was called without assertConsoleWarnDev:
|
||||
+ Not asserted%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ Not asserted%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ Not asserted%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
|
|
@ -2020,7 +1933,7 @@ describe('ReactInternalTestUtils console assertions', () => {
|
|||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
} else if (gate(flags => flags.enableOwnerStacks)) {
|
||||
} else {
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"asserConsoleLogsCleared(expected)
|
||||
|
||||
|
|
@ -2034,26 +1947,6 @@ describe('ReactInternalTestUtils console assertions', () => {
|
|||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
} else {
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"asserConsoleLogsCleared(expected)
|
||||
|
||||
console.error was called without assertConsoleErrorDev:
|
||||
+ A%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
+ B%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
+ C%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -2106,7 +1999,7 @@ describe('ReactInternalTestUtils console assertions', () => {
|
|||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
} else if (gate(flags => flags.enableOwnerStacks)) {
|
||||
} else {
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"asserConsoleLogsCleared(expected)
|
||||
|
||||
|
|
@ -2133,45 +2026,6 @@ describe('ReactInternalTestUtils console assertions', () => {
|
|||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
} else {
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"asserConsoleLogsCleared(expected)
|
||||
|
||||
console.log was called without assertConsoleLogDev:
|
||||
+ A
|
||||
+ B
|
||||
+ C
|
||||
|
||||
console.warn was called without assertConsoleWarnDev:
|
||||
+ A%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
+ B%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
+ C%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
|
||||
console.error was called without assertConsoleErrorDev:
|
||||
+ A%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
+ B%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
+ C%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ in App (at **)
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -3052,20 +2906,6 @@ describe('ReactInternalTestUtils console assertions', () => {
|
|||
+ Not asserted
|
||||
+ Not asserted
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
} else if (gate(flags => flags.enableOwnerStacks)) {
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"asserConsoleLogsCleared(expected)
|
||||
|
||||
console.error was called without assertConsoleErrorDev:
|
||||
+ Not asserted%s,
|
||||
+ in Yield (at **)
|
||||
+ Not asserted%s,
|
||||
+ in Yield (at **)
|
||||
+ Not asserted%s,
|
||||
+ in Yield (at **)
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
} else {
|
||||
|
|
@ -3075,13 +2915,10 @@ describe('ReactInternalTestUtils console assertions', () => {
|
|||
console.error was called without assertConsoleErrorDev:
|
||||
+ Not asserted%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ Not asserted%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
+ Not asserted%s,
|
||||
+ in Yield (at **)
|
||||
+ in div (at **)
|
||||
|
||||
You must call one of the assertConsoleDev helpers between each act call."
|
||||
`);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
/* eslint-disable react-internal/no-production-logging */
|
||||
|
||||
const chalk = require('chalk');
|
||||
const util = require('util');
|
||||
const shouldIgnoreConsoleError = require('./shouldIgnoreConsoleError');
|
||||
|
|
@ -38,25 +39,16 @@ const patchConsoleMethod = (methodName, logged) => {
|
|||
(methodName === 'error' || methodName === 'warn')
|
||||
) {
|
||||
const React = require('react');
|
||||
|
||||
// Ideally we could remove this check, but we have some tests like
|
||||
// useSyncExternalStoreShared-test that tests against React 17,
|
||||
// which doesn't have the captureOwnerStack method.
|
||||
if (React.captureOwnerStack) {
|
||||
// enableOwnerStacks enabled. When it's always on, we can assume this case.
|
||||
const stack = React.captureOwnerStack();
|
||||
if (stack) {
|
||||
format += '%s';
|
||||
args.push(stack);
|
||||
}
|
||||
} else {
|
||||
// Otherwise we have to use internals to emulate parent stacks.
|
||||
const ReactSharedInternals =
|
||||
React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE ||
|
||||
React.__SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
|
||||
if (ReactSharedInternals && ReactSharedInternals.getCurrentStack) {
|
||||
const stack = ReactSharedInternals.getCurrentStack();
|
||||
if (stack !== '') {
|
||||
format += '%s';
|
||||
args.push(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -203,11 +203,7 @@ describe('ReactCache', () => {
|
|||
"boolean, but instead received: [ 'Hi', 100 ]\n\n" +
|
||||
'To use non-primitive values as keys, you must pass a hash ' +
|
||||
'function as the second argument to createResource().\n' +
|
||||
' in App (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: '\n in Suspense (at **)'),
|
||||
|
||||
' in App (at **)',
|
||||
...(gate('enableSiblingPrerendering')
|
||||
? [
|
||||
'Invalid key type. Expected a string, number, symbol, or ' +
|
||||
|
|
|
|||
236
packages/react-client/src/ReactFlightClient.js
vendored
236
packages/react-client/src/ReactFlightClient.js
vendored
|
|
@ -45,7 +45,6 @@ import type {TemporaryReferenceSet} from './ReactFlightTemporaryReferences';
|
|||
|
||||
import {
|
||||
enablePostpone,
|
||||
enableOwnerStacks,
|
||||
enableProfilerTimer,
|
||||
enableComponentPerformanceTrack,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
|
|
@ -755,7 +754,7 @@ function createElement(
|
|||
configurable: false,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: enableOwnerStacks ? validated : 1, // Whether the element has already been validated on the server.
|
||||
value: validated, // Whether the element has already been validated on the server.
|
||||
});
|
||||
// debugInfo contains Server Component debug information.
|
||||
Object.defineProperty(element, '_debugInfo', {
|
||||
|
|
@ -765,79 +764,68 @@ function createElement(
|
|||
value: null,
|
||||
});
|
||||
let env = response._rootEnvironmentName;
|
||||
if (enableOwnerStacks) {
|
||||
if (owner !== null && owner.env != null) {
|
||||
// Interestingly we don't actually have the environment name of where
|
||||
// this JSX was created if it doesn't have an owner but if it does
|
||||
// it must be the same environment as the owner. We could send it separately
|
||||
// but it seems a bit unnecessary for this edge case.
|
||||
env = owner.env;
|
||||
}
|
||||
let normalizedStackTrace: null | Error = null;
|
||||
if (owner === null && response._debugRootStack != null) {
|
||||
// We override the stack if we override the owner since the stack where the root JSX
|
||||
// was created on the server isn't very useful but where the request was made is.
|
||||
normalizedStackTrace = response._debugRootStack;
|
||||
} else if (stack !== null) {
|
||||
// We create a fake stack and then create an Error object inside of it.
|
||||
// This means that the stack trace is now normalized into the native format
|
||||
// of the browser and the stack frames will have been registered with
|
||||
// source mapping information.
|
||||
// This can unfortunately happen within a user space callstack which will
|
||||
// remain on the stack.
|
||||
normalizedStackTrace = createFakeJSXCallStackInDEV(
|
||||
response,
|
||||
stack,
|
||||
env,
|
||||
);
|
||||
}
|
||||
Object.defineProperty(element, '_debugStack', {
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: normalizedStackTrace,
|
||||
});
|
||||
|
||||
let task: null | ConsoleTask = null;
|
||||
if (supportsCreateTask && stack !== null) {
|
||||
const createTaskFn = (console: any).createTask.bind(
|
||||
console,
|
||||
getTaskName(type),
|
||||
);
|
||||
const callStack = buildFakeCallStack(
|
||||
response,
|
||||
stack,
|
||||
env,
|
||||
createTaskFn,
|
||||
);
|
||||
// This owner should ideally have already been initialized to avoid getting
|
||||
// user stack frames on the stack.
|
||||
const ownerTask =
|
||||
owner === null ? null : initializeFakeTask(response, owner, env);
|
||||
if (ownerTask === null) {
|
||||
const rootTask = response._debugRootTask;
|
||||
if (rootTask != null) {
|
||||
task = rootTask.run(callStack);
|
||||
} else {
|
||||
task = callStack();
|
||||
}
|
||||
} else {
|
||||
task = ownerTask.run(callStack);
|
||||
}
|
||||
}
|
||||
Object.defineProperty(element, '_debugTask', {
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: task,
|
||||
});
|
||||
if (owner !== null && owner.env != null) {
|
||||
// Interestingly we don't actually have the environment name of where
|
||||
// this JSX was created if it doesn't have an owner but if it does
|
||||
// it must be the same environment as the owner. We could send it separately
|
||||
// but it seems a bit unnecessary for this edge case.
|
||||
env = owner.env;
|
||||
}
|
||||
let normalizedStackTrace: null | Error = null;
|
||||
if (owner === null && response._debugRootStack != null) {
|
||||
// We override the stack if we override the owner since the stack where the root JSX
|
||||
// was created on the server isn't very useful but where the request was made is.
|
||||
normalizedStackTrace = response._debugRootStack;
|
||||
} else if (stack !== null) {
|
||||
// We create a fake stack and then create an Error object inside of it.
|
||||
// This means that the stack trace is now normalized into the native format
|
||||
// of the browser and the stack frames will have been registered with
|
||||
// source mapping information.
|
||||
// This can unfortunately happen within a user space callstack which will
|
||||
// remain on the stack.
|
||||
normalizedStackTrace = createFakeJSXCallStackInDEV(response, stack, env);
|
||||
}
|
||||
Object.defineProperty(element, '_debugStack', {
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: normalizedStackTrace,
|
||||
});
|
||||
|
||||
let task: null | ConsoleTask = null;
|
||||
if (supportsCreateTask && stack !== null) {
|
||||
const createTaskFn = (console: any).createTask.bind(
|
||||
console,
|
||||
getTaskName(type),
|
||||
);
|
||||
const callStack = buildFakeCallStack(response, stack, env, createTaskFn);
|
||||
// This owner should ideally have already been initialized to avoid getting
|
||||
// user stack frames on the stack.
|
||||
if (owner !== null) {
|
||||
initializeFakeStack(response, owner);
|
||||
const ownerTask =
|
||||
owner === null ? null : initializeFakeTask(response, owner, env);
|
||||
if (ownerTask === null) {
|
||||
const rootTask = response._debugRootTask;
|
||||
if (rootTask != null) {
|
||||
task = rootTask.run(callStack);
|
||||
} else {
|
||||
task = callStack();
|
||||
}
|
||||
} else {
|
||||
task = ownerTask.run(callStack);
|
||||
}
|
||||
}
|
||||
Object.defineProperty(element, '_debugTask', {
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: task,
|
||||
});
|
||||
|
||||
// This owner should ideally have already been initialized to avoid getting
|
||||
// user stack frames on the stack.
|
||||
if (owner !== null) {
|
||||
initializeFakeStack(response, owner);
|
||||
}
|
||||
}
|
||||
|
||||
if (initializingHandler !== null) {
|
||||
|
|
@ -863,13 +851,11 @@ function createElement(
|
|||
name: getComponentNameFromType(element.type) || '',
|
||||
owner: element._owner,
|
||||
};
|
||||
if (enableOwnerStacks) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
erroredComponent.debugStack = element._debugStack;
|
||||
if (supportsCreateTask) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
erroredComponent.debugStack = element._debugStack;
|
||||
if (supportsCreateTask) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
erroredComponent.debugTask = element._debugTask;
|
||||
}
|
||||
erroredComponent.debugTask = element._debugTask;
|
||||
}
|
||||
erroredChunk._debugInfo = [erroredComponent];
|
||||
}
|
||||
|
|
@ -1057,13 +1043,11 @@ function waitForReference<T>(
|
|||
name: getComponentNameFromType(element.type) || '',
|
||||
owner: element._owner,
|
||||
};
|
||||
if (enableOwnerStacks) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
erroredComponent.debugStack = element._debugStack;
|
||||
if (supportsCreateTask) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
erroredComponent.debugStack = element._debugStack;
|
||||
if (supportsCreateTask) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
erroredComponent.debugTask = element._debugTask;
|
||||
}
|
||||
erroredComponent.debugTask = element._debugTask;
|
||||
}
|
||||
const chunkDebugInfo: ReactDebugInfo =
|
||||
chunk._debugInfo || (chunk._debugInfo = []);
|
||||
|
|
@ -1223,13 +1207,11 @@ function loadServerReference<A: Iterable<any>, T>(
|
|||
name: getComponentNameFromType(element.type) || '',
|
||||
owner: element._owner,
|
||||
};
|
||||
if (enableOwnerStacks) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
erroredComponent.debugStack = element._debugStack;
|
||||
if (supportsCreateTask) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
erroredComponent.debugStack = element._debugStack;
|
||||
if (supportsCreateTask) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
erroredComponent.debugTask = element._debugTask;
|
||||
}
|
||||
erroredComponent.debugTask = element._debugTask;
|
||||
}
|
||||
const chunkDebugInfo: ReactDebugInfo =
|
||||
chunk._debugInfo || (chunk._debugInfo = []);
|
||||
|
|
@ -1609,8 +1591,8 @@ function parseModelTuple(
|
|||
tuple[2],
|
||||
tuple[3],
|
||||
__DEV__ ? (tuple: any)[4] : null,
|
||||
__DEV__ && enableOwnerStacks ? (tuple: any)[5] : null,
|
||||
__DEV__ && enableOwnerStacks ? (tuple: any)[6] : 0,
|
||||
__DEV__ ? (tuple: any)[5] : null,
|
||||
__DEV__ ? (tuple: any)[6] : 0,
|
||||
);
|
||||
}
|
||||
return value;
|
||||
|
|
@ -2083,27 +2065,6 @@ function stopStream(
|
|||
controller.close(row === '' ? '"$undefined"' : row);
|
||||
}
|
||||
|
||||
function formatV8Stack(
|
||||
errorName: string,
|
||||
errorMessage: string,
|
||||
stack: null | ReactStackTrace,
|
||||
): string {
|
||||
let v8StyleStack = errorName + ': ' + errorMessage;
|
||||
if (stack) {
|
||||
for (let i = 0; i < stack.length; i++) {
|
||||
const frame = stack[i];
|
||||
const [name, filename, line, col] = frame;
|
||||
if (!name) {
|
||||
v8StyleStack += '\n at ' + filename + ':' + line + ':' + col;
|
||||
} else {
|
||||
v8StyleStack +=
|
||||
'\n at ' + name + ' (' + filename + ':' + line + ':' + col + ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
return v8StyleStack;
|
||||
}
|
||||
|
||||
type ErrorWithDigest = Error & {digest?: string};
|
||||
function resolveErrorProd(response: Response): Error {
|
||||
if (__DEV__) {
|
||||
|
|
@ -2202,34 +2163,20 @@ function resolvePostponeDev(
|
|||
);
|
||||
}
|
||||
let postponeInstance: Postpone;
|
||||
if (!enableOwnerStacks) {
|
||||
// Executing Error within a native stack isn't really limited to owner stacks
|
||||
// but we gate it behind the same flag for now while iterating.
|
||||
// eslint-disable-next-line react-internal/prod-error-codes
|
||||
postponeInstance = (Error(reason || ''): any);
|
||||
postponeInstance.$$typeof = REACT_POSTPONE_TYPE;
|
||||
// For backwards compat we use the V8 formatting when the flag is off.
|
||||
postponeInstance.stack = formatV8Stack(
|
||||
postponeInstance.name,
|
||||
postponeInstance.message,
|
||||
stack,
|
||||
);
|
||||
const callStack = buildFakeCallStack(
|
||||
response,
|
||||
stack,
|
||||
env,
|
||||
// $FlowFixMe[incompatible-use]
|
||||
Error.bind(null, reason || ''),
|
||||
);
|
||||
const rootTask = response._debugRootTask;
|
||||
if (rootTask != null) {
|
||||
postponeInstance = rootTask.run(callStack);
|
||||
} else {
|
||||
const callStack = buildFakeCallStack(
|
||||
response,
|
||||
stack,
|
||||
env,
|
||||
// $FlowFixMe[incompatible-use]
|
||||
Error.bind(null, reason || ''),
|
||||
);
|
||||
const rootTask = response._debugRootTask;
|
||||
if (rootTask != null) {
|
||||
postponeInstance = rootTask.run(callStack);
|
||||
} else {
|
||||
postponeInstance = callStack();
|
||||
}
|
||||
postponeInstance.$$typeof = REACT_POSTPONE_TYPE;
|
||||
postponeInstance = callStack();
|
||||
}
|
||||
postponeInstance.$$typeof = REACT_POSTPONE_TYPE;
|
||||
const chunks = response._chunks;
|
||||
const chunk = chunks.get(id);
|
||||
if (!chunk) {
|
||||
|
|
@ -2248,8 +2195,7 @@ function resolveHint<Code: HintCode>(
|
|||
dispatchHint(code, hintModel);
|
||||
}
|
||||
|
||||
const supportsCreateTask =
|
||||
__DEV__ && enableOwnerStacks && !!(console: any).createTask;
|
||||
const supportsCreateTask = __DEV__ && !!(console: any).createTask;
|
||||
|
||||
type FakeFunction<T> = (() => T) => T;
|
||||
const fakeFunctionCache: Map<string, FakeFunction<any>> = __DEV__
|
||||
|
|
@ -2590,15 +2536,11 @@ function resolveDebugInfo(
|
|||
let currentOwnerInDEV: null | ReactComponentInfo = null;
|
||||
function getCurrentStackInDEV(): string {
|
||||
if (__DEV__) {
|
||||
if (enableOwnerStacks) {
|
||||
const owner: null | ReactComponentInfo = currentOwnerInDEV;
|
||||
if (owner === null) {
|
||||
return '';
|
||||
}
|
||||
return getOwnerStackByComponentInfoInDev(owner);
|
||||
const owner: null | ReactComponentInfo = currentOwnerInDEV;
|
||||
if (owner === null) {
|
||||
return '';
|
||||
}
|
||||
// We don't have Parent Stacks in Flight.
|
||||
return '';
|
||||
return getOwnerStackByComponentInfoInDev(owner);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -321,9 +321,7 @@ describe('ReactFlight', () => {
|
|||
env: 'Server',
|
||||
key: null,
|
||||
owner: null,
|
||||
stack: gate(flag => flag.enableOwnerStacks)
|
||||
? ' in Object.<anonymous> (at **)'
|
||||
: undefined,
|
||||
stack: ' in Object.<anonymous> (at **)',
|
||||
props: {
|
||||
firstName: 'Seb',
|
||||
lastName: 'Smith',
|
||||
|
|
@ -367,9 +365,7 @@ describe('ReactFlight', () => {
|
|||
env: 'Server',
|
||||
key: null,
|
||||
owner: null,
|
||||
stack: gate(flag => flag.enableOwnerStacks)
|
||||
? ' in Object.<anonymous> (at **)'
|
||||
: undefined,
|
||||
stack: ' in Object.<anonymous> (at **)',
|
||||
props: {
|
||||
firstName: 'Seb',
|
||||
lastName: 'Smith',
|
||||
|
|
@ -1400,30 +1396,19 @@ describe('ReactFlight', () => {
|
|||
environmentName: 'Server',
|
||||
},
|
||||
],
|
||||
findSourceMapURLCalls: gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
[__filename, 'Server'],
|
||||
[__filename, 'Server'],
|
||||
// TODO: What should we request here? The outer (<anonymous>) or the inner (inspected-page.html)?
|
||||
['inspected-page.html:29:11), <anonymous>', 'Server'],
|
||||
[
|
||||
'file://~/(some)(really)(exotic-directory)/ReactFlight-test.js',
|
||||
'Server',
|
||||
],
|
||||
['file:///testing.js', 'Server'],
|
||||
['', 'Server'],
|
||||
[__filename, 'Server'],
|
||||
]
|
||||
: [
|
||||
// TODO: What should we request here? The outer (<anonymous>) or the inner (inspected-page.html)?
|
||||
['inspected-page.html:29:11), <anonymous>', 'Server'],
|
||||
[
|
||||
'file://~/(some)(really)(exotic-directory)/ReactFlight-test.js',
|
||||
'Server',
|
||||
],
|
||||
['file:///testing.js', 'Server'],
|
||||
['', 'Server'],
|
||||
],
|
||||
findSourceMapURLCalls: [
|
||||
[__filename, 'Server'],
|
||||
[__filename, 'Server'],
|
||||
// TODO: What should we request here? The outer (<anonymous>) or the inner (inspected-page.html)?
|
||||
['inspected-page.html:29:11), <anonymous>', 'Server'],
|
||||
[
|
||||
'file://~/(some)(really)(exotic-directory)/ReactFlight-test.js',
|
||||
'Server',
|
||||
],
|
||||
['file:///testing.js', 'Server'],
|
||||
['', 'Server'],
|
||||
[__filename, 'Server'],
|
||||
],
|
||||
});
|
||||
} else {
|
||||
expect(errors.map(getErrorForJestMatcher)).toEqual([
|
||||
|
|
@ -1475,9 +1460,6 @@ describe('ReactFlight', () => {
|
|||
'Check the render method of `Component`. See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in span (at **)\n' +
|
||||
' in Component (at **)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: ' in Indirection (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
});
|
||||
|
|
@ -1538,46 +1520,26 @@ describe('ReactFlight', () => {
|
|||
},
|
||||
};
|
||||
const transport = ReactNoopFlightServer.render(<input value={obj} />);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <input value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <input value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <input value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <input value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <input value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn in DEV if a toJSON instance is passed to a host component child', () => {
|
||||
|
|
@ -1589,120 +1551,68 @@ describe('ReactFlight', () => {
|
|||
const transport = ReactNoopFlightServer.render(
|
||||
<div>Womp womp: {new MyError('spaghetti')}</div>,
|
||||
);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^',
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
' ^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn in DEV if a special object is passed to a host component', () => {
|
||||
const transport = ReactNoopFlightServer.render(<input value={Math} />);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn in DEV if an object with symbols is passed to a host component', () => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<input value={{[Symbol.iterator]: {}}} />,
|
||||
);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <input value={{}}>\n' +
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <input value={{}}>\n' +
|
||||
' ^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <input value={{}}>\n' +
|
||||
' ^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <input value={{}}>\n' +
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <input value={{}}>\n' +
|
||||
' ^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn in DEV if a toJSON instance is passed to a Client Component', () => {
|
||||
|
|
@ -1716,46 +1626,26 @@ describe('ReactFlight', () => {
|
|||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
const transport = ReactNoopFlightServer.render(<Client value={obj} />);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <... value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <... value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <... value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <... value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <... value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn in DEV if a toJSON instance is passed to a Client Component child', () => {
|
||||
|
|
@ -1771,46 +1661,26 @@ describe('ReactFlight', () => {
|
|||
const transport = ReactNoopFlightServer.render(
|
||||
<Client>Current date: {obj}</Client>,
|
||||
);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
||||
' ^^^^^^^^^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
||||
' ^^^^^^^^^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn in DEV if a special object is passed to a Client Component', () => {
|
||||
|
|
@ -1819,43 +1689,24 @@ describe('ReactFlight', () => {
|
|||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
const transport = ReactNoopFlightServer.render(<Client value={Math} />);
|
||||
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn in DEV if an object with symbols is passed to a Client Component', () => {
|
||||
|
|
@ -1867,42 +1718,24 @@ describe('ReactFlight', () => {
|
|||
const transport = ReactNoopFlightServer.render(
|
||||
<Client value={{[Symbol.iterator]: {}}} />,
|
||||
);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^\n',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^\n',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn in DEV if a special object is passed to a nested object in Client Component', () => {
|
||||
|
|
@ -1915,36 +1748,20 @@ describe('ReactFlight', () => {
|
|||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
{withoutStack: true},
|
||||
],
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
],
|
||||
' ^^^^',
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
],
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn in DEV if a special object is passed to a nested array in Client Component', () => {
|
||||
|
|
@ -1956,36 +1773,20 @@ describe('ReactFlight', () => {
|
|||
<Client value={['looooong string takes up noise', Math, <h1>hi</h1>]} />,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' [..., Math, <h1/>]\n' +
|
||||
' ^^^^',
|
||||
{withoutStack: true},
|
||||
],
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' [..., Math, <h1/>]\n' +
|
||||
' ^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' [..., Math, <h1/>]\n' +
|
||||
' ^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' [..., Math, <h1/>]\n' +
|
||||
' ^^^^',
|
||||
],
|
||||
' ^^^^',
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
],
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' [..., Math, <h1/>]\n' +
|
||||
' ^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should NOT warn in DEV for key getters', () => {
|
||||
|
|
@ -2012,26 +1813,16 @@ describe('ReactFlight', () => {
|
|||
jest.resetModules();
|
||||
jest.mock('react', () => React);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in NoKey (at **)',
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in NoKey (at **)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <div>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in NoKey (at **)',
|
||||
]);
|
||||
}
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in NoKey (at **)',
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in NoKey (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
// @gate !__DEV__ || enableOwnerStacks
|
||||
it('should warn in DEV a child is missing keys on a fragment', () => {
|
||||
// While we're on the server we need to have the Server version active to track component stacks.
|
||||
jest.resetModules();
|
||||
|
|
@ -2046,23 +1837,14 @@ describe('ReactFlight', () => {
|
|||
jest.resetModules();
|
||||
jest.mock('react', () => React);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Fragment (at **)',
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Fragment (at **)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <div>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Fragment (at **)',
|
||||
]);
|
||||
}
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Fragment (at **)',
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Fragment (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn in DEV a child is missing keys in client component', async () => {
|
||||
|
|
@ -2079,20 +1861,12 @@ describe('ReactFlight', () => {
|
|||
|
||||
ReactNoop.render(await ReactNoopFlightClient.read(transport));
|
||||
});
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ParentClient>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
}
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ParentClient>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should error if a class instance is passed to a host component', () => {
|
||||
|
|
@ -3039,9 +2813,7 @@ describe('ReactFlight', () => {
|
|||
env: 'Server',
|
||||
key: null,
|
||||
owner: null,
|
||||
stack: gate(flag => flag.enableOwnerStacks)
|
||||
? ' in Object.<anonymous> (at **)'
|
||||
: undefined,
|
||||
stack: ' in Object.<anonymous> (at **)',
|
||||
props: {
|
||||
transport: expect.arrayContaining([]),
|
||||
},
|
||||
|
|
@ -3063,9 +2835,7 @@ describe('ReactFlight', () => {
|
|||
env: 'third-party',
|
||||
key: null,
|
||||
owner: null,
|
||||
stack: gate(flag => flag.enableOwnerStacks)
|
||||
? ' in Object.<anonymous> (at **)'
|
||||
: undefined,
|
||||
stack: ' in Object.<anonymous> (at **)',
|
||||
props: {},
|
||||
},
|
||||
{time: 14},
|
||||
|
|
@ -3082,9 +2852,7 @@ describe('ReactFlight', () => {
|
|||
env: 'third-party',
|
||||
key: null,
|
||||
owner: null,
|
||||
stack: gate(flag => flag.enableOwnerStacks)
|
||||
? ' in myLazy (at **)\n in lazyInitializer (at **)'
|
||||
: undefined,
|
||||
stack: ' in myLazy (at **)\n in lazyInitializer (at **)',
|
||||
props: {},
|
||||
},
|
||||
{time: 16},
|
||||
|
|
@ -3100,9 +2868,7 @@ describe('ReactFlight', () => {
|
|||
env: 'third-party',
|
||||
key: '3',
|
||||
owner: null,
|
||||
stack: gate(flag => flag.enableOwnerStacks)
|
||||
? ' in Object.<anonymous> (at **)'
|
||||
: undefined,
|
||||
stack: ' in Object.<anonymous> (at **)',
|
||||
props: {},
|
||||
},
|
||||
{time: 12},
|
||||
|
|
@ -3176,9 +2942,7 @@ describe('ReactFlight', () => {
|
|||
env: 'Server',
|
||||
key: null,
|
||||
owner: null,
|
||||
stack: gate(flag => flag.enableOwnerStacks)
|
||||
? ' in Object.<anonymous> (at **)'
|
||||
: undefined,
|
||||
stack: ' in Object.<anonymous> (at **)',
|
||||
props: {
|
||||
transport: expect.arrayContaining([]),
|
||||
},
|
||||
|
|
@ -3198,9 +2962,7 @@ describe('ReactFlight', () => {
|
|||
env: 'Server',
|
||||
key: 'keyed',
|
||||
owner: null,
|
||||
stack: gate(flag => flag.enableOwnerStacks)
|
||||
? ' in ServerComponent (at **)'
|
||||
: undefined,
|
||||
stack: ' in ServerComponent (at **)',
|
||||
props: {
|
||||
children: {},
|
||||
},
|
||||
|
|
@ -3219,9 +2981,7 @@ describe('ReactFlight', () => {
|
|||
env: 'third-party',
|
||||
key: null,
|
||||
owner: null,
|
||||
stack: gate(flag => flag.enableOwnerStacks)
|
||||
? ' in Object.<anonymous> (at **)'
|
||||
: undefined,
|
||||
stack: ' in Object.<anonymous> (at **)',
|
||||
props: {},
|
||||
},
|
||||
{time: 12},
|
||||
|
|
@ -3335,19 +3095,13 @@ describe('ReactFlight', () => {
|
|||
});
|
||||
|
||||
expect(sawReactPrefix).toBe(false);
|
||||
if (__DEV__ && gate(flags => flags.enableOwnerStacks)) {
|
||||
if (__DEV__) {
|
||||
expect(environments.slice(0, 4)).toEqual([
|
||||
'Server',
|
||||
'third-party',
|
||||
'third-party',
|
||||
'third-party',
|
||||
]);
|
||||
} else if (__DEV__) {
|
||||
expect(environments.slice(0, 3)).toEqual([
|
||||
'third-party',
|
||||
'third-party',
|
||||
'third-party',
|
||||
]);
|
||||
} else {
|
||||
expect(environments).toEqual([]);
|
||||
}
|
||||
|
|
@ -3384,9 +3138,7 @@ describe('ReactFlight', () => {
|
|||
env: 'A',
|
||||
key: null,
|
||||
owner: null,
|
||||
stack: gate(flag => flag.enableOwnerStacks)
|
||||
? ' in Object.<anonymous> (at **)'
|
||||
: undefined,
|
||||
stack: ' in Object.<anonymous> (at **)',
|
||||
props: {},
|
||||
},
|
||||
{
|
||||
|
|
@ -3402,7 +3154,7 @@ describe('ReactFlight', () => {
|
|||
expect(ReactNoop).toMatchRenderedOutput(<div>hi</div>);
|
||||
});
|
||||
|
||||
// @gate __DEV__ && enableOwnerStacks
|
||||
// @gate __DEV__
|
||||
it('replays logs, but not onError logs', async () => {
|
||||
function foo() {
|
||||
return 'hello';
|
||||
|
|
@ -3574,9 +3326,7 @@ describe('ReactFlight', () => {
|
|||
env: 'Server',
|
||||
key: null,
|
||||
owner: null,
|
||||
stack: gate(flag => flag.enableOwnerStacks)
|
||||
? ' in Object.<anonymous> (at **)'
|
||||
: undefined,
|
||||
stack: ' in Object.<anonymous> (at **)',
|
||||
props: {
|
||||
firstName: 'Seb',
|
||||
},
|
||||
|
|
@ -3590,9 +3340,7 @@ describe('ReactFlight', () => {
|
|||
env: 'Server',
|
||||
key: null,
|
||||
owner: greetInfo,
|
||||
stack: gate(flag => flag.enableOwnerStacks)
|
||||
? ' in Greeting (at **)'
|
||||
: undefined,
|
||||
stack: ' in Greeting (at **)',
|
||||
props: {
|
||||
children: expect.objectContaining({
|
||||
type: 'span',
|
||||
|
|
@ -3617,7 +3365,7 @@ describe('ReactFlight', () => {
|
|||
expect(ReactNoop).toMatchRenderedOutput(<span>Hello, Seb</span>);
|
||||
});
|
||||
|
||||
// @gate __DEV__ && enableOwnerStacks
|
||||
// @gate __DEV__
|
||||
it('can get the component owner stacks during rendering in dev', () => {
|
||||
let stack;
|
||||
|
||||
|
|
@ -3649,7 +3397,7 @@ describe('ReactFlight', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// @gate __DEV__ && enableOwnerStacks
|
||||
// @gate __DEV__
|
||||
it('can track owner for a flight response created in another render', async () => {
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => ReactServer);
|
||||
|
|
@ -3712,7 +3460,7 @@ describe('ReactFlight', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// @gate __DEV__ && enableOwnerStacks
|
||||
// @gate __DEV__
|
||||
it('can get the component owner stacks for onError in dev', async () => {
|
||||
const thrownError = new Error('hi');
|
||||
let caughtError;
|
||||
|
|
@ -3754,7 +3502,6 @@ describe('ReactFlight', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// @gate (enableOwnerStacks) || !__DEV__
|
||||
it('should include only one component stack in replayed logs (if DevTools or polyfill adds them)', () => {
|
||||
class MyError extends Error {
|
||||
toJSON() {
|
||||
|
|
|
|||
|
|
@ -2347,10 +2347,7 @@ describe('ReactHooksInspectionIntegration', () => {
|
|||
|
||||
await act(async () => await LazyFoo);
|
||||
assertConsoleErrorDev([
|
||||
'Foo: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: '\n in Foo (at **)\n' + ' in Suspense (at **)'),
|
||||
'Foo: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.',
|
||||
]);
|
||||
|
||||
const childFiber = renderer.root._currentFiber();
|
||||
|
|
|
|||
|
|
@ -917,7 +917,7 @@ export function createProfilingHooks({
|
|||
// Creating a cache of component stacks won't help, generating a single stack is already expensive enough.
|
||||
// We should find a way to lazily generate component stacks on demand, when user inspects a specific event.
|
||||
// If we succeed with moving React DevTools Timeline Profiler to Performance panel, then Timeline Profiler would probably be removed.
|
||||
// If not, then once enableOwnerStacks is adopted, revisit this again and cache component stacks per Fiber,
|
||||
// Now that owner stacks are adopted, revisit this again and cache component stacks per Fiber,
|
||||
// but only return them when needed, sending hundreds of component stacks is beyond the Bridge's bandwidth.
|
||||
|
||||
// Postprocess Profile data
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@
|
|||
import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
|
||||
import type {HydrationDiffNode} from 'react-reconciler/src/ReactFiberHydrationDiffs';
|
||||
|
||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
||||
|
||||
import {
|
||||
current,
|
||||
runWithFiberInDEV,
|
||||
|
|
@ -615,7 +613,7 @@ function validateDOMNesting(
|
|||
ancestorDescription,
|
||||
);
|
||||
}
|
||||
if (enableOwnerStacks && child) {
|
||||
if (child) {
|
||||
// For debugging purposes find the nearest ancestor that caused the issue.
|
||||
// The stack trace of this ancestor can be useful to find the cause.
|
||||
// If the parent is a direct parent in the same owner, we don't bother.
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ import {
|
|||
enableLegacyFBSupport,
|
||||
enableCreateEventHandleAPI,
|
||||
enableScopeAPI,
|
||||
enableOwnerStacks,
|
||||
disableCommentsAsDOMContainers,
|
||||
enableScrollEndPolyfill,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
|
|
@ -275,7 +274,7 @@ function processDispatchQueueItemsInOrder(
|
|||
if (instance !== previousInstance && event.isPropagationStopped()) {
|
||||
return;
|
||||
}
|
||||
if (__DEV__ && enableOwnerStacks && instance !== null) {
|
||||
if (__DEV__ && instance !== null) {
|
||||
runWithFiberInDEV(
|
||||
instance,
|
||||
executeDispatch,
|
||||
|
|
@ -294,7 +293,7 @@ function processDispatchQueueItemsInOrder(
|
|||
if (instance !== previousInstance && event.isPropagationStopped()) {
|
||||
return;
|
||||
}
|
||||
if (__DEV__ && enableOwnerStacks && instance !== null) {
|
||||
if (__DEV__ && instance !== null) {
|
||||
runWithFiberInDEV(
|
||||
instance,
|
||||
executeDispatch,
|
||||
|
|
|
|||
|
|
@ -75,8 +75,7 @@ describe('ReactChildReconciler', () => {
|
|||
'This may happen if you return fn instead of <fn /> from render. ' +
|
||||
'Or maybe you meant to call this function rather than return it.\n' +
|
||||
' <h1>{fn}</h1>\n' +
|
||||
' in h1 (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in div (at **)'),
|
||||
' in h1 (at **)',
|
||||
]);
|
||||
const node = container.firstChild;
|
||||
|
||||
|
|
@ -100,7 +99,6 @@ describe('ReactChildReconciler', () => {
|
|||
'Keys should be unique so that components maintain their identity across updates. ' +
|
||||
'Non-unique keys may cause children to be duplicated and/or omitted — ' +
|
||||
'the behavior is unsupported and could change in a future version.\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in div (at **)\n') +
|
||||
' in div (at **)\n' +
|
||||
' in Component (at **)',
|
||||
]);
|
||||
|
|
@ -137,11 +135,7 @@ describe('ReactChildReconciler', () => {
|
|||
'duplicated and/or omitted — the behavior is unsupported and ' +
|
||||
'could change in a future version.\n' +
|
||||
' in div (at **)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks) ? '' : ' in div (at **)\n') +
|
||||
' in Component (at **)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: ' in Parent (at **)\n') +
|
||||
' in GrandParent (at **)',
|
||||
]);
|
||||
});
|
||||
|
|
@ -165,7 +159,6 @@ describe('ReactChildReconciler', () => {
|
|||
'duplicated and/or omitted — the behavior is unsupported and ' +
|
||||
'could change in a future version.\n' +
|
||||
' in div (at **)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks) ? '' : ' in div (at **)\n') +
|
||||
' in Component (at **)',
|
||||
]);
|
||||
});
|
||||
|
|
@ -201,11 +194,7 @@ describe('ReactChildReconciler', () => {
|
|||
'duplicated and/or omitted — the behavior is unsupported and ' +
|
||||
'could change in a future version.\n' +
|
||||
' in div (at **)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks) ? '' : ' in div (at **)\n') +
|
||||
' in Component (at **)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: ' in Parent (at **)\n') +
|
||||
' in GrandParent (at **)',
|
||||
]);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -407,17 +407,6 @@ describe('ReactComponent', () => {
|
|||
|
||||
const X = undefined;
|
||||
const XElement = <X />;
|
||||
if (gate(flags => !flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'React.jsx: type is invalid -- expected a string (for built-in components) ' +
|
||||
'or a class/function (for composite components) but got: undefined. ' +
|
||||
"You likely forgot to export your component from the file it's defined in, " +
|
||||
'or you might have mixed up default and named imports.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
root.render(XElement);
|
||||
|
|
@ -433,15 +422,6 @@ describe('ReactComponent', () => {
|
|||
|
||||
const Y = null;
|
||||
const YElement = <Y />;
|
||||
if (gate(flags => !flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'React.jsx: type is invalid -- expected a string (for built-in components) ' +
|
||||
'or a class/function (for composite components) but got: null.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
root.render(YElement);
|
||||
|
|
@ -453,15 +433,6 @@ describe('ReactComponent', () => {
|
|||
|
||||
const Z = true;
|
||||
const ZElement = <Z />;
|
||||
if (gate(flags => !flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'React.jsx: type is invalid -- expected a string (for built-in components) ' +
|
||||
'or a class/function (for composite components) but got: boolean.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
root.render(ZElement);
|
||||
|
|
@ -506,26 +477,6 @@ describe('ReactComponent', () => {
|
|||
'\n\nCheck the render method of `Bar`.'
|
||||
: ''),
|
||||
);
|
||||
if (!gate('enableOwnerStacks')) {
|
||||
assertConsoleErrorDev([
|
||||
'React.jsx: type is invalid -- expected a string (for built-in components) ' +
|
||||
'or a class/function (for composite components) but got: undefined.' +
|
||||
(__DEV__
|
||||
? " You likely forgot to export your component from the file it's defined in, " +
|
||||
'or you might have mixed up default and named imports.\n' +
|
||||
' in Bar (at **)\n' +
|
||||
' in Foo (at **)'
|
||||
: ''),
|
||||
'React.jsx: type is invalid -- expected a string (for built-in components) ' +
|
||||
'or a class/function (for composite components) but got: undefined.' +
|
||||
(__DEV__
|
||||
? " You likely forgot to export your component from the file it's defined in, " +
|
||||
'or you might have mixed up default and named imports.\n' +
|
||||
' in Bar (at **)\n' +
|
||||
' in Foo (at **)'
|
||||
: ''),
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
it('throws if a plain object is used as a child', async () => {
|
||||
|
|
@ -693,9 +644,6 @@ describe('ReactComponent', () => {
|
|||
'Or maybe you meant to call this function rather than return it.\n' +
|
||||
' <span>{Foo}</span>\n' +
|
||||
' in span (at **)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: ' in div (at **)\n') +
|
||||
' in Foo (at **)',
|
||||
]);
|
||||
});
|
||||
|
|
@ -753,9 +701,6 @@ describe('ReactComponent', () => {
|
|||
'Or maybe you meant to call this function rather than return it.\n' +
|
||||
' <span>{Foo}</span>\n' +
|
||||
' in span (at **)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: ' in div (at **)\n') +
|
||||
' in Foo (at **)',
|
||||
]);
|
||||
await act(() => {
|
||||
|
|
|
|||
|
|
@ -1396,9 +1396,6 @@ describe('ReactCompositeComponent', () => {
|
|||
'Cannot update a component (`A`) while rendering a different component (`B`). ' +
|
||||
'To locate the bad setState() call inside `B`, ' +
|
||||
'follow the stack trace as described in https://react.dev/link/setstate-in-render\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in B (at **)\n' + ' in div (at **)\n') +
|
||||
' in Parent (at **)',
|
||||
]);
|
||||
|
||||
|
|
|
|||
|
|
@ -545,7 +545,6 @@ describe('ReactDOM', () => {
|
|||
// ReactDOM(App > div > span)
|
||||
'Invalid ARIA attribute `ariaTypo`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||
' in span (at **)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks) ? '' : ' in div (at **)\n') +
|
||||
' in App (at **)',
|
||||
// ReactDOM(App > div > ServerEntry) >>> ReactDOMServer(Child) >>> ReactDOMServer(App2) >>> ReactDOMServer(blink)
|
||||
'Invalid ARIA attribute `ariaTypo2`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||
|
|
@ -562,7 +561,6 @@ describe('ReactDOM', () => {
|
|||
// ReactDOM(App > div > font)
|
||||
'Invalid ARIA attribute `ariaTypo5`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||
' in font (at **)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks) ? '' : ' in div (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1845,8 +1845,7 @@ describe('ReactDOMComponent', () => {
|
|||
assertConsoleErrorDev([
|
||||
'The tag <menuitem> is unrecognized in this browser. ' +
|
||||
'If you meant to render a React component, start its name with an uppercase letter.\n' +
|
||||
' in menuitem (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in menu (at **)'),
|
||||
' in menuitem (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -2242,10 +2241,7 @@ describe('ReactDOMComponent', () => {
|
|||
'> <div>\n' +
|
||||
'> <tr>\n' +
|
||||
' ...\n' +
|
||||
'\n in tr (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: '\n in div (at **)'),
|
||||
'\n in tr (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -2264,10 +2260,7 @@ describe('ReactDOMComponent', () => {
|
|||
'In HTML, <p> cannot be a descendant of <p>.\n' +
|
||||
'This will cause a hydration error.' +
|
||||
// There is no outer `p` here because root container is not part of the stack.
|
||||
'\n in p (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: '\n in span (at **)'),
|
||||
'\n in p (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -2294,92 +2287,48 @@ describe('ReactDOMComponent', () => {
|
|||
await act(() => {
|
||||
root.render(<Foo />);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'In HTML, <tr> cannot be a child of ' +
|
||||
'<table>. Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated ' +
|
||||
'by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <Foo>\n' +
|
||||
'> <table>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
' ...\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in Foo (at **)',
|
||||
'<table> cannot contain a nested <tr>.\nSee this log for the ancestor stack trace.' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Foo (at **)',
|
||||
'In HTML, text nodes cannot be a ' +
|
||||
'child of <tr>.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <Foo>\n' +
|
||||
' <table>\n' +
|
||||
' <Row>\n' +
|
||||
' <tr>\n' +
|
||||
'> x\n' +
|
||||
' ...\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in Foo (at **)',
|
||||
'In HTML, whitespace text nodes cannot ' +
|
||||
"be a child of <table>. Make sure you don't have any extra " +
|
||||
'whitespace between tags on each line of your source code.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <Foo>\n' +
|
||||
'> <table>\n' +
|
||||
' <Row>\n' +
|
||||
'> {" "}\n' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Foo (at **)',
|
||||
]
|
||||
: [
|
||||
'In HTML, <tr> cannot be a child of ' +
|
||||
'<table>. Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated ' +
|
||||
'by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <Foo>\n' +
|
||||
'> <table>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
' ...\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Foo (at **)',
|
||||
'In HTML, text nodes cannot be a ' +
|
||||
'child of <tr>.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <Foo>\n' +
|
||||
' <table>\n' +
|
||||
' <Row>\n' +
|
||||
' <tr>\n' +
|
||||
'> x\n' +
|
||||
' ...\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Foo (at **)',
|
||||
'In HTML, whitespace text nodes cannot ' +
|
||||
"be a child of <table>. Make sure you don't have any extra " +
|
||||
'whitespace between tags on each line of your source code.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <Foo>\n' +
|
||||
'> <table>\n' +
|
||||
' <Row>\n' +
|
||||
'> {" "}\n' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Foo (at **)',
|
||||
],
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'In HTML, <tr> cannot be a child of ' +
|
||||
'<table>. Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated ' +
|
||||
'by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <Foo>\n' +
|
||||
'> <table>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
' ...\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in Foo (at **)',
|
||||
'<table> cannot contain a nested <tr>.\nSee this log for the ancestor stack trace.' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Foo (at **)',
|
||||
'In HTML, text nodes cannot be a ' +
|
||||
'child of <tr>.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <Foo>\n' +
|
||||
' <table>\n' +
|
||||
' <Row>\n' +
|
||||
' <tr>\n' +
|
||||
'> x\n' +
|
||||
' ...\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in Foo (at **)',
|
||||
'In HTML, whitespace text nodes cannot ' +
|
||||
"be a child of <table>. Make sure you don't have any extra " +
|
||||
'whitespace between tags on each line of your source code.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <Foo>\n' +
|
||||
'> <table>\n' +
|
||||
' <Row>\n' +
|
||||
'> {" "}\n' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Foo (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('warns nicely for updating table rows to use text', async () => {
|
||||
|
|
@ -2445,12 +2394,7 @@ describe('ReactDOMComponent', () => {
|
|||
' <tr>\n' +
|
||||
'> text\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: '\n in tbody (at **)' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Foo (at **)'),
|
||||
'\n in Row (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -2477,49 +2421,28 @@ describe('ReactDOMComponent', () => {
|
|||
await act(() => {
|
||||
root.render(<App1 />);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <App1>\n' +
|
||||
' <Viz1>\n' +
|
||||
'> <table>\n' +
|
||||
' <FancyRow>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in FancyRow (at **)' +
|
||||
'\n in Viz1 (at **)' +
|
||||
'\n in App1 (at **)',
|
||||
'<table> cannot contain a nested <tr>.\n' +
|
||||
'See this log for the ancestor stack trace.\n' +
|
||||
' in table (at **)\n' +
|
||||
' in Viz1 (at **)\n' +
|
||||
' in App1 (at **)',
|
||||
]
|
||||
: [
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <App1>\n' +
|
||||
' <Viz1>\n' +
|
||||
'> <table>\n' +
|
||||
' <FancyRow>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in FancyRow (at **)' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Viz1 (at **)' +
|
||||
'\n in App1 (at **)',
|
||||
],
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <App1>\n' +
|
||||
' <Viz1>\n' +
|
||||
'> <table>\n' +
|
||||
' <FancyRow>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in FancyRow (at **)' +
|
||||
'\n in Viz1 (at **)' +
|
||||
'\n in App1 (at **)',
|
||||
'<table> cannot contain a nested <tr>.\n' +
|
||||
'See this log for the ancestor stack trace.\n' +
|
||||
' in table (at **)\n' +
|
||||
' in Viz1 (at **)\n' +
|
||||
' in App1 (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('gives useful context in warnings 2', async () => {
|
||||
|
|
@ -2558,57 +2481,32 @@ describe('ReactDOMComponent', () => {
|
|||
await act(() => {
|
||||
root.render(<App2 />);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <App2>\n' +
|
||||
' <Viz2>\n' +
|
||||
' <FancyTable>\n' +
|
||||
' <Table>\n' +
|
||||
'> <table>\n' +
|
||||
' <FancyRow>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in FancyRow (at **)' +
|
||||
'\n in Viz2 (at **)' +
|
||||
'\n in App2 (at **)',
|
||||
'<table> cannot contain a nested <tr>.\n' +
|
||||
'See this log for the ancestor stack trace.\n' +
|
||||
' in table (at **)\n' +
|
||||
' in Table (at **)\n' +
|
||||
' in FancyTable (at **)\n' +
|
||||
' in Viz2 (at **)\n' +
|
||||
' in App2 (at **)',
|
||||
]
|
||||
: [
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <App2>\n' +
|
||||
' <Viz2>\n' +
|
||||
' <FancyTable>\n' +
|
||||
' <Table>\n' +
|
||||
'> <table>\n' +
|
||||
' <FancyRow>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in FancyRow (at **)' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Table (at **)' +
|
||||
'\n in FancyTable (at **)' +
|
||||
'\n in Viz2 (at **)' +
|
||||
'\n in App2 (at **)',
|
||||
],
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <App2>\n' +
|
||||
' <Viz2>\n' +
|
||||
' <FancyTable>\n' +
|
||||
' <Table>\n' +
|
||||
'> <table>\n' +
|
||||
' <FancyRow>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in FancyRow (at **)' +
|
||||
'\n in Viz2 (at **)' +
|
||||
'\n in App2 (at **)',
|
||||
'<table> cannot contain a nested <tr>.\n' +
|
||||
'See this log for the ancestor stack trace.\n' +
|
||||
' in table (at **)\n' +
|
||||
' in Table (at **)\n' +
|
||||
' in FancyTable (at **)\n' +
|
||||
' in Viz2 (at **)\n' +
|
||||
' in App2 (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('gives useful context in warnings 3', async () => {
|
||||
|
|
@ -2640,47 +2538,26 @@ describe('ReactDOMComponent', () => {
|
|||
</FancyTable>,
|
||||
);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <FancyTable>\n' +
|
||||
' <Table>\n' +
|
||||
'> <table>\n' +
|
||||
' <FancyRow>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in FancyRow (at **)',
|
||||
'<table> cannot contain a nested <tr>.\n' +
|
||||
'See this log for the ancestor stack trace.' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Table (at **)' +
|
||||
'\n in FancyTable (at **)',
|
||||
]
|
||||
: [
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <FancyTable>\n' +
|
||||
' <Table>\n' +
|
||||
'> <table>\n' +
|
||||
' <FancyRow>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in FancyRow (at **)' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Table (at **)' +
|
||||
'\n in FancyTable (at **)',
|
||||
],
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <FancyTable>\n' +
|
||||
' <Table>\n' +
|
||||
'> <table>\n' +
|
||||
' <FancyRow>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in FancyRow (at **)',
|
||||
'<table> cannot contain a nested <tr>.\n' +
|
||||
'See this log for the ancestor stack trace.' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Table (at **)' +
|
||||
'\n in FancyTable (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('gives useful context in warnings 4', async () => {
|
||||
|
|
@ -2701,39 +2578,22 @@ describe('ReactDOMComponent', () => {
|
|||
</table>,
|
||||
);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
'> <table>\n' +
|
||||
' <FancyRow>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in FancyRow (at **)',
|
||||
'<table> cannot contain a nested <tr>.\n' +
|
||||
'See this log for the ancestor stack trace.' +
|
||||
'\n in table (at **)',
|
||||
]
|
||||
: [
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
'> <table>\n' +
|
||||
' <FancyRow>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in FancyRow (at **)' +
|
||||
'\n in table (at **)',
|
||||
],
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
'> <table>\n' +
|
||||
' <FancyRow>\n' +
|
||||
' <Row>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in Row (at **)' +
|
||||
'\n in FancyRow (at **)',
|
||||
'<table> cannot contain a nested <tr>.\n' +
|
||||
'See this log for the ancestor stack trace.' +
|
||||
'\n in table (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('gives useful context in warnings 5', async () => {
|
||||
|
|
@ -2758,39 +2618,22 @@ describe('ReactDOMComponent', () => {
|
|||
</FancyTable>,
|
||||
);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <FancyTable>\n' +
|
||||
' <Table>\n' +
|
||||
'> <table>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)',
|
||||
'<table> cannot contain a nested <tr>.\n' +
|
||||
'See this log for the ancestor stack trace.' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Table (at **)' +
|
||||
'\n in FancyTable (at **)',
|
||||
]
|
||||
: [
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <FancyTable>\n' +
|
||||
' <Table>\n' +
|
||||
'> <table>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Table (at **)' +
|
||||
'\n in FancyTable (at **)',
|
||||
],
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <FancyTable>\n' +
|
||||
' <Table>\n' +
|
||||
'> <table>\n' +
|
||||
'> <tr>\n' +
|
||||
'\n in tr (at **)',
|
||||
'<table> cannot contain a nested <tr>.\n' +
|
||||
'See this log for the ancestor stack trace.' +
|
||||
'\n in table (at **)' +
|
||||
'\n in Table (at **)' +
|
||||
'\n in FancyTable (at **)',
|
||||
]);
|
||||
|
||||
class Link extends React.Component {
|
||||
render() {
|
||||
|
|
@ -2807,40 +2650,22 @@ describe('ReactDOMComponent', () => {
|
|||
</Link>,
|
||||
);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'In HTML, <a> cannot be a descendant of <a>.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <Link>\n' +
|
||||
'> <a>\n' +
|
||||
' <div>\n' +
|
||||
' <Link>\n' +
|
||||
'> <a>\n' +
|
||||
'\n in a (at **)' +
|
||||
'\n in Link (at **)',
|
||||
'<a> cannot contain a nested <a>.\n' +
|
||||
'See this log for the ancestor stack trace.' +
|
||||
'\n in a (at **)' +
|
||||
'\n in Link (at **)',
|
||||
]
|
||||
: [
|
||||
'In HTML, <a> cannot be a descendant of <a>.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <Link>\n' +
|
||||
'> <a>\n' +
|
||||
' <div>\n' +
|
||||
' <Link>\n' +
|
||||
'> <a>\n' +
|
||||
'\n in a (at **)' +
|
||||
'\n in Link (at **)' +
|
||||
'\n in div (at **)' +
|
||||
'\n in a (at **)' +
|
||||
'\n in Link (at **)',
|
||||
],
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'In HTML, <a> cannot be a descendant of <a>.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <Link>\n' +
|
||||
'> <a>\n' +
|
||||
' <div>\n' +
|
||||
' <Link>\n' +
|
||||
'> <a>\n' +
|
||||
'\n in a (at **)' +
|
||||
'\n in Link (at **)',
|
||||
'<a> cannot contain a nested <a>.\n' +
|
||||
'See this log for the ancestor stack trace.' +
|
||||
'\n in a (at **)' +
|
||||
'\n in Link (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn about incorrect casing on properties (ssr)', () => {
|
||||
|
|
@ -3099,11 +2924,9 @@ describe('ReactDOMComponent', () => {
|
|||
});
|
||||
assertConsoleErrorDev([
|
||||
'Invalid DOM property `class`. Did you mean `className`?\n' +
|
||||
' in span (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in div (at **)'),
|
||||
' in span (at **)',
|
||||
'Invalid event handler property `onclick`. Did you mean `onClick`?\n' +
|
||||
' in strong (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in div (at **)'),
|
||||
' in strong (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -3119,12 +2942,10 @@ describe('ReactDOMComponent', () => {
|
|||
);
|
||||
assertConsoleErrorDev([
|
||||
'Invalid DOM property `class`. Did you mean `className`?\n' +
|
||||
' in span (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in div (at **)'),
|
||||
' in span (at **)',
|
||||
'Invalid event handler property `onclick`. ' +
|
||||
'React events use the camelCase naming convention, for example `onClick`.\n' +
|
||||
' in strong (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in div (at **)'),
|
||||
' in strong (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -3175,12 +2996,10 @@ describe('ReactDOMComponent', () => {
|
|||
'Invalid DOM property `class`. Did you mean `className`?\n' +
|
||||
' in span (at **)\n' +
|
||||
' in Child1 (at **)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in div (at **)\n') +
|
||||
' in Parent (at **)',
|
||||
'Invalid event handler property `onclick`. Did you mean `onClick`?\n' +
|
||||
' in strong (at **)\n' +
|
||||
' in Child3 (at **)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in div (at **)\n') +
|
||||
' in Parent (at **)',
|
||||
]);
|
||||
});
|
||||
|
|
@ -3230,13 +3049,11 @@ describe('ReactDOMComponent', () => {
|
|||
'Invalid DOM property `class`. Did you mean `className`?\n' +
|
||||
' in span (at **)\n' +
|
||||
' in Child1 (at **)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in div (at **)\n') +
|
||||
' in Parent (at **)',
|
||||
'Invalid event handler property `onclick`. ' +
|
||||
'React events use the camelCase naming convention, for example `onClick`.\n' +
|
||||
' in strong (at **)\n' +
|
||||
' in Child3 (at **)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in div (at **)\n') +
|
||||
' in Parent (at **)',
|
||||
]);
|
||||
});
|
||||
|
|
@ -3362,8 +3179,7 @@ describe('ReactDOMComponent', () => {
|
|||
});
|
||||
assertConsoleErrorDev([
|
||||
'Invalid DOM property `arabic-form`. Did you mean `arabicForm`?\n' +
|
||||
' in text (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in svg (at **)'),
|
||||
' in text (at **)',
|
||||
]);
|
||||
const text = el.querySelector('text');
|
||||
|
||||
|
|
@ -3844,8 +3660,7 @@ describe('ReactDOMComponent', () => {
|
|||
});
|
||||
assertConsoleErrorDev([
|
||||
'Invalid DOM property `x-height`. Did you mean `xHeight`?\n' +
|
||||
' in font-face (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in svg (at **)'),
|
||||
' in font-face (at **)',
|
||||
]);
|
||||
|
||||
expect(el.querySelector('font-face').hasAttribute('x-height')).toBe(
|
||||
|
|
@ -3871,8 +3686,7 @@ describe('ReactDOMComponent', () => {
|
|||
'whatever="false" or whatever={value.toString()}.\n\n' +
|
||||
'If you used to conditionally omit it with whatever={condition && value}, ' +
|
||||
'pass whatever={condition ? value : undefined} instead.\n' +
|
||||
' in font-face (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in svg (at **)'),
|
||||
' in font-face (at **)',
|
||||
]);
|
||||
|
||||
expect(el.querySelector('font-face').hasAttribute('whatever')).toBe(
|
||||
|
|
|
|||
|
|
@ -751,7 +751,6 @@ describe('ReactDOMFiber', () => {
|
|||
' in Parent (at **)',
|
||||
'Component uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in Component (at **)\n') +
|
||||
' in Parent (at **)',
|
||||
]);
|
||||
expect(container.innerHTML).toBe('');
|
||||
|
|
|
|||
|
|
@ -386,7 +386,6 @@ describe('ReactDOMFizzForm', () => {
|
|||
'Cannot specify a formTarget for a button that specifies a function as a formAction. ' +
|
||||
'The function will always be executed in the same window.\n' +
|
||||
' in input (at **)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in form (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
let root;
|
||||
|
|
|
|||
|
|
@ -1843,15 +1843,9 @@ describe('ReactDOMFizzServer', () => {
|
|||
assertConsoleErrorDev([
|
||||
'<inCorrectTag /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.' +
|
||||
'\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in inCorrectTag (at **)\n' +
|
||||
' in C (at **)\n' +
|
||||
' in A (at **)'
|
||||
: ' in inCorrectTag (at **)\n' +
|
||||
' in C (at **)\n' +
|
||||
' in Suspense (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in A (at **)'),
|
||||
' in inCorrectTag (at **)\n' +
|
||||
' in C (at **)\n' +
|
||||
' in A (at **)',
|
||||
]);
|
||||
|
||||
await act(() => {
|
||||
|
|
@ -1862,17 +1856,11 @@ describe('ReactDOMFizzServer', () => {
|
|||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\nCheck the render method of `B`.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in span (at **)\n' +
|
||||
' in mapper (at **)\n' +
|
||||
' in Array.map (at **)\n' +
|
||||
' in B (at **)\n' +
|
||||
' in A (at **)'
|
||||
: ' in span (at **)\n' +
|
||||
' in B (at **)\n' +
|
||||
' in Suspense (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in A (at **)'),
|
||||
' in span (at **)\n' +
|
||||
' in mapper (at **)\n' +
|
||||
' in Array.map (at **)\n' +
|
||||
' in B (at **)\n' +
|
||||
' in A (at **)',
|
||||
]);
|
||||
|
||||
expect(getVisibleChildren(container)).toEqual(
|
||||
|
|
@ -1954,13 +1942,7 @@ describe('ReactDOMFizzServer', () => {
|
|||
' in TestProvider (at **)',
|
||||
'TestConsumer uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in TestConsumer (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in TestProvider (at **)' +
|
||||
'\n in Suspense (at **)' +
|
||||
'\n in div (at **)' +
|
||||
'\n in TestProvider (at **)'),
|
||||
' in TestConsumer (at **)',
|
||||
]);
|
||||
expect(getVisibleChildren(container)).toEqual(
|
||||
<div>
|
||||
|
|
@ -5871,7 +5853,6 @@ describe('ReactDOMFizzServer', () => {
|
|||
'If your `children` prop is using this form try rewriting it using a template string: ' +
|
||||
'<title>{`hello ${nameOfUser}`}</title>.\n' +
|
||||
' in title (at **)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in head (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
|
||||
|
|
@ -5917,7 +5898,6 @@ describe('ReactDOMFizzServer', () => {
|
|||
'React Component try moving the <title> tag into that component. ' +
|
||||
'If the `children` of <title> is some HTML markup change it to be Text only to be valid HTML.\n' +
|
||||
' in title (at **)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in head (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
// object titles are toStringed when float is on
|
||||
|
|
@ -5961,7 +5941,6 @@ describe('ReactDOMFizzServer', () => {
|
|||
'string or number value if so. Otherwise implement a `toString` method that React can ' +
|
||||
'use to produce a valid <title>.\n' +
|
||||
' in title (at **)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in head (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
// object titles are toStringed when float is on
|
||||
|
|
@ -6545,23 +6524,11 @@ describe('ReactDOMFizzServer', () => {
|
|||
|
||||
assertConsoleErrorDev([
|
||||
'A script element was rendered with a number for children. If script element has children it must be a single string. Consider using dangerouslySetInnerHTML or passing a plain string as children.' +
|
||||
componentStack(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? ['script', 'App']
|
||||
: ['script', 'body', 'html', 'App'],
|
||||
),
|
||||
componentStack(['script', 'App']),
|
||||
'A script element was rendered with an array for children. If script element has children it must be a single string. Consider using dangerouslySetInnerHTML or passing a plain string as children.' +
|
||||
componentStack(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? ['script', 'App']
|
||||
: ['script', 'body', 'html', 'App'],
|
||||
),
|
||||
componentStack(['script', 'App']),
|
||||
'A script element was rendered with something unexpected for children. If script element has children it must be a single string. Consider using dangerouslySetInnerHTML or passing a plain string as children.' +
|
||||
componentStack(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? ['script', 'App']
|
||||
: ['script', 'body', 'html', 'App'],
|
||||
),
|
||||
componentStack(['script', 'App']),
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -8544,7 +8511,7 @@ describe('ReactDOMFizzServer', () => {
|
|||
expect(document.body.textContent).toBe('HelloWorld');
|
||||
});
|
||||
|
||||
// @gate __DEV__ && enableOwnerStacks
|
||||
// @gate __DEV__
|
||||
it('can get the component owner stacks during rendering in dev', async () => {
|
||||
let stack;
|
||||
|
||||
|
|
@ -8577,7 +8544,7 @@ describe('ReactDOMFizzServer', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// @gate __DEV__ && enableOwnerStacks
|
||||
// @gate __DEV__
|
||||
it('can get the component owner stacks for onError in dev', async () => {
|
||||
const thrownError = new Error('hi');
|
||||
let caughtError;
|
||||
|
|
@ -9111,56 +9078,30 @@ describe('ReactDOMFizzServer', () => {
|
|||
</body>
|
||||
</html>,
|
||||
);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'In HTML, <meta> cannot be a child of <html>.\nThis will cause a hydration error.' +
|
||||
'\n' +
|
||||
'\n <App>' +
|
||||
'\n> <html>' +
|
||||
'\n <Suspense fallback="this fallb...">' +
|
||||
'\n <meta>' +
|
||||
'\n> <meta itemProp="" content="before">' +
|
||||
'\n ...' +
|
||||
'\n' +
|
||||
'\n in meta (at **)' +
|
||||
'\n in App (at **)',
|
||||
'<html> cannot contain a nested <meta>.\nSee this log for the ancestor stack trace.' +
|
||||
'\n in html (at **)' +
|
||||
'\n in App (at **)',
|
||||
[
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev([
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.' +
|
||||
'\n in Suspense (at **)' +
|
||||
'\n in html (at **)' +
|
||||
'\n in App (at **)',
|
||||
'In HTML, <meta> cannot be a child of <html>.\nThis will cause a hydration error.' +
|
||||
'\n' +
|
||||
'\n <App>' +
|
||||
'\n> <html>' +
|
||||
'\n <Suspense fallback="this fallb...">' +
|
||||
'\n <meta>' +
|
||||
'\n> <meta itemProp="" content="before">' +
|
||||
'\n ...' +
|
||||
'\n' +
|
||||
'\n in meta (at **)' +
|
||||
'\n in Suspense (at **)' +
|
||||
'\n in html (at **)' +
|
||||
'\n in App (at **)',
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.' +
|
||||
'\n in Suspense (at **)' +
|
||||
'\n in html (at **)' +
|
||||
'\n in App (at **)',
|
||||
]);
|
||||
}
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'In HTML, <meta> cannot be a child of <html>.\nThis will cause a hydration error.' +
|
||||
'\n' +
|
||||
'\n <App>' +
|
||||
'\n> <html>' +
|
||||
'\n <Suspense fallback="this fallb...">' +
|
||||
'\n <meta>' +
|
||||
'\n> <meta itemProp="" content="before">' +
|
||||
'\n ...' +
|
||||
'\n' +
|
||||
'\n in meta (at **)' +
|
||||
'\n in App (at **)',
|
||||
'<html> cannot contain a nested <meta>.\nSee this log for the ancestor stack trace.' +
|
||||
'\n in html (at **)' +
|
||||
'\n in App (at **)',
|
||||
[
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
]);
|
||||
|
||||
await root.unmount();
|
||||
expect(getVisibleChildren(document)).toEqual(
|
||||
|
|
@ -9253,56 +9194,30 @@ describe('ReactDOMFizzServer', () => {
|
|||
</body>
|
||||
</html>,
|
||||
);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'In HTML, <meta> cannot be a child of <html>.\nThis will cause a hydration error.' +
|
||||
'\n' +
|
||||
'\n <App>' +
|
||||
'\n> <html>' +
|
||||
'\n <Suspense fallback="this fallb...">' +
|
||||
'\n <meta>' +
|
||||
'\n> <meta itemProp="" content="before">' +
|
||||
'\n ...' +
|
||||
'\n' +
|
||||
'\n in meta (at **)' +
|
||||
'\n in App (at **)',
|
||||
'<html> cannot contain a nested <meta>.\nSee this log for the ancestor stack trace.' +
|
||||
'\n in html (at **)' +
|
||||
'\n in App (at **)',
|
||||
[
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev([
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.' +
|
||||
'\n in Suspense (at **)' +
|
||||
'\n in html (at **)' +
|
||||
'\n in App (at **)',
|
||||
'In HTML, <meta> cannot be a child of <html>.\nThis will cause a hydration error.' +
|
||||
'\n' +
|
||||
'\n <App>' +
|
||||
'\n> <html>' +
|
||||
'\n <Suspense fallback="this fallb...">' +
|
||||
'\n <meta>' +
|
||||
'\n> <meta itemProp="" content="before">' +
|
||||
'\n ...' +
|
||||
'\n' +
|
||||
'\n in meta (at **)' +
|
||||
'\n in Suspense (at **)' +
|
||||
'\n in html (at **)' +
|
||||
'\n in App (at **)',
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.' +
|
||||
'\n in Suspense (at **)' +
|
||||
'\n in html (at **)' +
|
||||
'\n in App (at **)',
|
||||
]);
|
||||
}
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'In HTML, <meta> cannot be a child of <html>.\nThis will cause a hydration error.' +
|
||||
'\n' +
|
||||
'\n <App>' +
|
||||
'\n> <html>' +
|
||||
'\n <Suspense fallback="this fallb...">' +
|
||||
'\n <meta>' +
|
||||
'\n> <meta itemProp="" content="before">' +
|
||||
'\n ...' +
|
||||
'\n' +
|
||||
'\n in meta (at **)' +
|
||||
'\n in App (at **)',
|
||||
'<html> cannot contain a nested <meta>.\nSee this log for the ancestor stack trace.' +
|
||||
'\n in html (at **)' +
|
||||
'\n in App (at **)',
|
||||
[
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
]);
|
||||
|
||||
await root.unmount();
|
||||
expect(getVisibleChildren(document)).toEqual(
|
||||
|
|
|
|||
|
|
@ -529,8 +529,7 @@ describe('ReactDOMFloat', () => {
|
|||
'> <template>\n' +
|
||||
' ...\n' +
|
||||
'\n' +
|
||||
' in template (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
||||
' in template (at **)',
|
||||
]);
|
||||
|
||||
root.render(
|
||||
|
|
@ -555,8 +554,7 @@ describe('ReactDOMFloat', () => {
|
|||
' <body>\n' +
|
||||
'> <style>\n' +
|
||||
'\n' +
|
||||
' in style (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
||||
' in style (at **)',
|
||||
]);
|
||||
|
||||
root.render(
|
||||
|
|
@ -596,8 +594,7 @@ describe('ReactDOMFloat', () => {
|
|||
' <body>\n' +
|
||||
'> <script href="foo">\n' +
|
||||
'\n' +
|
||||
' in script (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
||||
' in script (at **)',
|
||||
]);
|
||||
|
||||
root.render(
|
||||
|
|
@ -2269,21 +2266,11 @@ body {
|
|||
'spell it as lowercase `nonstandardattr` instead. If you accidentally passed it from a ' +
|
||||
'parent component, remove it from the DOM element.\n' +
|
||||
' in link (at **)\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in div (at **)\n' +
|
||||
' in body (at **)\n' +
|
||||
' in html (at **)\n') +
|
||||
' in App (at **)',
|
||||
'Invalid values for props `shouldnotincludefunctions`, `norsymbols` on <link> tag. ' +
|
||||
'Either remove them from the element, or pass a string or number value to keep them in the DOM. ' +
|
||||
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||
' in link (at **)\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in div (at **)\n' +
|
||||
' in body (at **)\n' +
|
||||
' in html (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
|
||||
|
|
@ -2642,8 +2629,7 @@ body {
|
|||
'> <html>\n' +
|
||||
'> <meta itemProp="foo">' +
|
||||
'\n' +
|
||||
'\n in meta (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
||||
'\n in meta (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -2668,8 +2654,7 @@ body {
|
|||
'> <html>\n' +
|
||||
'> <title itemProp="foo">' +
|
||||
'\n' +
|
||||
'\n in title (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
||||
'\n in title (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -2694,8 +2679,7 @@ body {
|
|||
'> <html>\n' +
|
||||
'> <style itemProp="foo">' +
|
||||
'\n' +
|
||||
'\n in style (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
||||
'\n in style (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -2720,8 +2704,7 @@ body {
|
|||
'> <html>\n' +
|
||||
'> <link itemProp="foo">\n' +
|
||||
'\n' +
|
||||
' in link (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
||||
' in link (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -2746,8 +2729,7 @@ body {
|
|||
'> <html>\n' +
|
||||
'> <script itemProp="foo">\n' +
|
||||
'\n' +
|
||||
' in script (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
||||
' in script (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -4844,9 +4826,6 @@ body {
|
|||
'React encountered a hoistable style tag for the same href as a preload: "foo". ' +
|
||||
'When using a style tag to inline styles you should not also preload it as a stylsheet.\n' +
|
||||
' in style (at **)\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in body (at **)\n' + ' in html (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
|
||||
|
|
@ -7753,64 +7732,43 @@ body {
|
|||
'If your intent was to have React hoist and deduplciate this stylesheet using the ' +
|
||||
'`precedence` prop ensure there is a non-empty string `href` prop as well, ' +
|
||||
'otherwise remove the `precedence` prop.\n' +
|
||||
' in link (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in body (at **)' + '\n in html (at **)'),
|
||||
' in link (at **)',
|
||||
'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and ' +
|
||||
'expected the `href` prop to be a non-empty string but ecountered an empty string instead. ' +
|
||||
'If your intent was to have React hoist and deduplciate this stylesheet using the ' +
|
||||
'`precedence` prop ensure there is a non-empty string `href` prop as well, ' +
|
||||
'otherwise remove the `precedence` prop.\n' +
|
||||
' in link (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in body (at **)' + '\n in html (at **)'),
|
||||
' in link (at **)',
|
||||
'An empty string ("") was passed to the href attribute. ' +
|
||||
'To fix this, either do not render the element at all or ' +
|
||||
'pass null to href instead of an empty string.\n' +
|
||||
' in link (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in body (at **)' + '\n in html (at **)'),
|
||||
' in link (at **)',
|
||||
'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and ' +
|
||||
'`onLoad` and `onError` props. The presence of loading and error handlers indicates ' +
|
||||
'an intent to manage the stylesheet loading state from your from your Component code ' +
|
||||
'and React will not hoist or deduplicate this stylesheet. ' +
|
||||
'If your intent was to have React hoist and deduplciate this stylesheet using the ' +
|
||||
'`precedence` prop remove the `onLoad` and `onError` props, otherwise remove the `precedence` prop.\n' +
|
||||
' in link (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in body (at **)' + '\n in html (at **)'),
|
||||
' in link (at **)',
|
||||
'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and ' +
|
||||
'`onLoad` prop. The presence of loading and error handlers indicates an intent to ' +
|
||||
'manage the stylesheet loading state from your from your Component code and ' +
|
||||
'React will not hoist or deduplicate this stylesheet. ' +
|
||||
'If your intent was to have React hoist and deduplciate this stylesheet using the ' +
|
||||
'`precedence` prop remove the `onLoad` prop, otherwise remove the `precedence` prop.\n' +
|
||||
' in link (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in body (at **)' + '\n in html (at **)'),
|
||||
' in link (at **)',
|
||||
'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and `onError` prop. ' +
|
||||
'The presence of loading and error handlers indicates an intent to manage the stylesheet loading state ' +
|
||||
'from your from your Component code and React will not hoist or deduplicate this stylesheet. ' +
|
||||
'If your intent was to have React hoist and deduplciate this stylesheet using the `precedence` ' +
|
||||
'prop remove the `onError` prop, otherwise remove the `precedence` prop.\n' +
|
||||
' in link (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in body (at **)' + '\n in html (at **)'),
|
||||
' in link (at **)',
|
||||
'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and a `disabled` prop. ' +
|
||||
'The presence of the `disabled` prop indicates an intent to manage the stylesheet active state from ' +
|
||||
'your from your Component code and React will not hoist or deduplicate this stylesheet. ' +
|
||||
'If your intent was to have React hoist and deduplciate this stylesheet using the `precedence` ' +
|
||||
'prop remove the `disabled` prop, otherwise remove the `precedence` prop.\n' +
|
||||
' in link (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in body (at **)' + '\n in html (at **)'),
|
||||
' in link (at **)',
|
||||
].filter(Boolean),
|
||||
);
|
||||
|
||||
|
|
@ -7836,8 +7794,7 @@ body {
|
|||
'loading state from your from your Component code and React will not hoist or deduplicate this stylesheet. ' +
|
||||
'If your intent was to have React hoist and deduplciate this stylesheet using the `precedence` ' +
|
||||
'prop remove the `onLoad` and `onError` props, otherwise remove the `precedence` prop.\n' +
|
||||
' in body (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
||||
' in body (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -8429,10 +8386,7 @@ background-color: green;
|
|||
'using the `precedence` prop to not have any spaces but ecountered spaces instead. ' +
|
||||
'using spaces in this prop will cause hydration of this style to fail on the client. ' +
|
||||
'The href for the <style> where this ocurred is "foo bar".\n' +
|
||||
' in style (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in body (at **)' + '\n in html (at **)'),
|
||||
' in style (at **)',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -391,8 +391,7 @@ describe('ReactDOMForm', () => {
|
|||
'> <form action={function outerAction}>\n' +
|
||||
' <input>\n' +
|
||||
'> <form action={function innerAction} ref={{current:null}}>\n' +
|
||||
'\n in form (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in form (at **)'),
|
||||
'\n in form (at **)',
|
||||
]);
|
||||
|
||||
await submit(ref.current);
|
||||
|
|
@ -588,8 +587,7 @@ describe('ReactDOMForm', () => {
|
|||
'Cannot specify a "name" prop for a button that specifies a function as a formAction. ' +
|
||||
'React needs it to encode which action should be invoked. ' +
|
||||
'It will get overridden.\n' +
|
||||
' in input (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in form (at **)'),
|
||||
' in input (at **)',
|
||||
]);
|
||||
|
||||
await submit(inputRef.current);
|
||||
|
|
@ -1971,7 +1969,6 @@ describe('ReactDOMForm', () => {
|
|||
'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +
|
||||
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||
' in button (at **)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in form (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
await submit(buttonRef.current);
|
||||
|
|
|
|||
|
|
@ -59,10 +59,7 @@ describe('ReactDOMOption', () => {
|
|||
'> <div>\n' +
|
||||
' ...\n' +
|
||||
'\n' +
|
||||
' in div (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: '\n in option (at **)'),
|
||||
' in div (at **)',
|
||||
]);
|
||||
expect(container.firstChild.innerHTML).toBe('1 <div></div> 2');
|
||||
await renderIntoDocument(el);
|
||||
|
|
@ -279,10 +276,7 @@ describe('ReactDOMOption', () => {
|
|||
'> <div ref={{current:null}}>\n' +
|
||||
' ...\n' +
|
||||
'\n' +
|
||||
' in div (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: '\n in option (at **)' + '\n in select (at **)'),
|
||||
' in div (at **)',
|
||||
]);
|
||||
option = container.firstChild.firstChild;
|
||||
|
||||
|
|
|
|||
|
|
@ -794,7 +794,6 @@ describe('ReactDOMSelect', () => {
|
|||
'Use the `defaultValue` or `value` props on <select> instead of ' +
|
||||
'setting `selected` on <option>.\n' +
|
||||
' in option (at **)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in select (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
|
||||
|
|
@ -1072,8 +1071,7 @@ describe('ReactDOMSelect', () => {
|
|||
'Invalid value for prop `value` on <option> tag. ' +
|
||||
'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +
|
||||
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
]);
|
||||
|
||||
const node = container.firstChild;
|
||||
|
|
@ -1096,8 +1094,7 @@ describe('ReactDOMSelect', () => {
|
|||
'Invalid value for prop `value` on <option> tag. ' +
|
||||
'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +
|
||||
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
]);
|
||||
|
||||
let node = container.firstChild;
|
||||
|
|
@ -1134,8 +1131,7 @@ describe('ReactDOMSelect', () => {
|
|||
'Invalid value for prop `value` on <option> tag. ' +
|
||||
'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +
|
||||
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
]);
|
||||
|
||||
const node = container.firstChild;
|
||||
|
|
@ -1158,8 +1154,7 @@ describe('ReactDOMSelect', () => {
|
|||
'Invalid value for prop `value` on <option> tag. ' +
|
||||
'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +
|
||||
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
]);
|
||||
|
||||
let node = container.firstChild;
|
||||
|
|
@ -1199,8 +1194,7 @@ describe('ReactDOMSelect', () => {
|
|||
'Invalid value for prop `value` on <option> tag. ' +
|
||||
'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +
|
||||
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
]);
|
||||
|
||||
const node = container.firstChild;
|
||||
|
|
@ -1223,8 +1217,7 @@ describe('ReactDOMSelect', () => {
|
|||
'Invalid value for prop `value` on <option> tag. ' +
|
||||
'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +
|
||||
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
]);
|
||||
|
||||
const node = container.firstChild;
|
||||
|
|
@ -1247,8 +1240,7 @@ describe('ReactDOMSelect', () => {
|
|||
'Invalid value for prop `value` on <option> tag. ' +
|
||||
'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +
|
||||
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
]);
|
||||
|
||||
let node = container.firstChild;
|
||||
|
|
@ -1284,8 +1276,7 @@ describe('ReactDOMSelect', () => {
|
|||
'Invalid value for prop `value` on <option> tag. ' +
|
||||
'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +
|
||||
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
]);
|
||||
|
||||
let node = container.firstChild;
|
||||
|
|
@ -1366,12 +1357,10 @@ describe('ReactDOMSelect', () => {
|
|||
assertConsoleErrorDev([
|
||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||
' This value must be coerced to a string before using it here.\n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||
' This value must be coerced to a string before using it here.\n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -1395,12 +1384,10 @@ describe('ReactDOMSelect', () => {
|
|||
assertConsoleErrorDev([
|
||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||
' This value must be coerced to a string before using it here.\n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||
' This value must be coerced to a string before using it here.\n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -1467,8 +1454,7 @@ describe('ReactDOMSelect', () => {
|
|||
assertConsoleErrorDev([
|
||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||
' This value must be coerced to a string before using it here.\n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -1508,8 +1494,7 @@ describe('ReactDOMSelect', () => {
|
|||
assertConsoleErrorDev([
|
||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||
' This value must be coerced to a string before using it here.\n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
'Form field values (value, checked, defaultValue, or defaultChecked props)' +
|
||||
' must be strings, not TemporalLike. ' +
|
||||
'This value must be coerced to a string before using it here.\n' +
|
||||
|
|
@ -1563,12 +1548,10 @@ describe('ReactDOMSelect', () => {
|
|||
assertConsoleErrorDev([
|
||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||
' This value must be coerced to a string before using it here.\n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||
' This value must be coerced to a string before using it here.\n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -1591,12 +1574,10 @@ describe('ReactDOMSelect', () => {
|
|||
assertConsoleErrorDev([
|
||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||
' This value must be coerced to a string before using it here.\n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||
' This value must be coerced to a string before using it here.\n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -1670,12 +1651,10 @@ describe('ReactDOMSelect', () => {
|
|||
assertConsoleErrorDev([
|
||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||
' This value must be coerced to a string before using it here.\n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||
' This value must be coerced to a string before using it here.\n' +
|
||||
' in option (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
||||
' in option (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -995,18 +995,6 @@ describe('ReactDOMServerIntegration', () => {
|
|||
async render => {
|
||||
let EmptyComponent = {};
|
||||
EmptyComponent = <EmptyComponent />;
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? []
|
||||
: [
|
||||
'React.jsx: type is invalid -- expected a string ' +
|
||||
'(for built-in components) or a class/function (for composite ' +
|
||||
'components) but got: object. You likely forgot to export your ' +
|
||||
"component from the file it's defined in, or you might have mixed up " +
|
||||
'default and named imports.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
await render(EmptyComponent);
|
||||
},
|
||||
'Element type is invalid: expected a string (for built-in components) or a class/function ' +
|
||||
|
|
@ -1022,16 +1010,6 @@ describe('ReactDOMServerIntegration', () => {
|
|||
async render => {
|
||||
let NullComponent = null;
|
||||
NullComponent = <NullComponent />;
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? []
|
||||
: [
|
||||
'React.jsx: type is invalid -- expected a string ' +
|
||||
'(for built-in components) or a class/function (for composite ' +
|
||||
'components) but got: null.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
await render(NullComponent);
|
||||
},
|
||||
'Element type is invalid: expected a string (for built-in components) or a class/function ' +
|
||||
|
|
@ -1043,19 +1021,6 @@ describe('ReactDOMServerIntegration', () => {
|
|||
async render => {
|
||||
let UndefinedComponent = undefined;
|
||||
UndefinedComponent = <UndefinedComponent />;
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? []
|
||||
: [
|
||||
'React.jsx: type is invalid -- expected a string ' +
|
||||
'(for built-in components) or a class/function (for composite ' +
|
||||
'components) but got: undefined. You likely forgot to export your ' +
|
||||
"component from the file it's defined in, or you might have mixed up " +
|
||||
'default and named imports.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
|
||||
await render(UndefinedComponent);
|
||||
},
|
||||
'Element type is invalid: expected a string (for built-in components) or a class/function ' +
|
||||
|
|
|
|||
|
|
@ -286,7 +286,6 @@ describe('ReactDOMServerLifecycles', () => {
|
|||
'usually means you called setState() outside componentWillMount() on ' +
|
||||
'the server. This is a no-op.\n\n' +
|
||||
'Please check the code for the Outer component.\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in Inner (at **)\n') +
|
||||
' in Outer (at **)',
|
||||
]);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1923,11 +1923,6 @@ describe('ReactDOMServerPartialHydration', () => {
|
|||
"Can't perform a React state update on a component that hasn't mounted yet. " +
|
||||
'This indicates that you have a side-effect in your render function that ' +
|
||||
'asynchronously later calls tries to update the component. Move this work to useEffect instead.\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Child (at **)\n' +
|
||||
' in Suspense (at **)\n' +
|
||||
' in div (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
|
||||
|
|
|
|||
|
|
@ -171,8 +171,7 @@ describe('ReactDOM HostSingleton', () => {
|
|||
'children of these components will likely fail in unpredictable ways. ' +
|
||||
'Please only render a single instance of <head> and if you need to mount a new one, ' +
|
||||
'ensure any previous ones have unmounted first.\n' +
|
||||
' in head (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
||||
' in head (at **)',
|
||||
]);
|
||||
expect(getVisibleChildren(document)).toEqual(
|
||||
<html>
|
||||
|
|
|
|||
|
|
@ -60,11 +60,13 @@ describe('ReactDeprecationWarnings', () => {
|
|||
</div>,
|
||||
);
|
||||
await waitForAll([]);
|
||||
assertConsoleErrorDev([
|
||||
'FunctionalComponent: Support for defaultProps ' +
|
||||
'will be removed from memo components in a future major ' +
|
||||
'release. Use JavaScript default parameters instead.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'FunctionalComponent: Support for defaultProps ' +
|
||||
'will be removed from memo components in a future major ' +
|
||||
'release. Use JavaScript default parameters instead.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2381,17 +2381,6 @@ describe('ReactErrorBoundaries', () => {
|
|||
'class/function (for composite components) but got: null.',
|
||||
);
|
||||
|
||||
if (!gate('enableOwnerStacks')) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'React.jsx: type is invalid -- expected a string ' +
|
||||
'(for built-in components) or a class/function ' +
|
||||
'(for composite components) but got: null.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
await expect(async () => {
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
|
|
@ -2403,18 +2392,6 @@ describe('ReactErrorBoundaries', () => {
|
|||
'expected a string (for built-in components) or a ' +
|
||||
'class/function (for composite components) but got: undefined.',
|
||||
);
|
||||
if (!gate('enableOwnerStacks')) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'React.jsx: type is invalid -- expected a string ' +
|
||||
'(for built-in components) or a class/function ' +
|
||||
'(for composite components) but got: undefined. ' +
|
||||
"You likely forgot to export your component from the file it's defined in, " +
|
||||
'or you might have mixed up default and named imports.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('renders empty output if error boundary does not handle the error', async () => {
|
||||
|
|
|
|||
|
|
@ -116,7 +116,6 @@ describe('ReactFunctionComponent', () => {
|
|||
' in GrandParent (at **)',
|
||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in Child (at **)\n') +
|
||||
' in Parent (at **)\n' +
|
||||
' in GrandParent (at **)',
|
||||
]);
|
||||
|
|
@ -260,7 +259,6 @@ describe('ReactFunctionComponent', () => {
|
|||
' in Parent (at **)',
|
||||
'Child uses the legacy contextTypes API which will be removed soon. ' +
|
||||
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Child (at **)\n' +
|
||||
' in Parent (at **)',
|
||||
]);
|
||||
expect(el.textContent).toBe('en');
|
||||
|
|
|
|||
|
|
@ -121,13 +121,9 @@ describe('ReactLegacyCompositeComponent', () => {
|
|||
assertConsoleErrorDev([
|
||||
'Child uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in Child (at **)\n') +
|
||||
' in Parent (at **)',
|
||||
'Grandchild uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Grandchild (at **)\n' + ' in Child (at **)\n') +
|
||||
' in Parent (at **)',
|
||||
]);
|
||||
expect(findDOMNode(component).innerHTML).toBe('bar');
|
||||
|
|
@ -200,10 +196,7 @@ describe('ReactLegacyCompositeComponent', () => {
|
|||
' in Parent (at **)',
|
||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Child (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in Middle (at **)' + '\n in Parent (at **)'),
|
||||
' in Child (at **)',
|
||||
]);
|
||||
|
||||
await act(() => {
|
||||
|
|
@ -268,15 +261,9 @@ describe('ReactLegacyCompositeComponent', () => {
|
|||
assertConsoleErrorDev([
|
||||
'Parent uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in Parent (at **)\n') +
|
||||
' in Wrapper (at **)',
|
||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Child (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in Parent (at **)\n') +
|
||||
' in Wrapper (at **)',
|
||||
]);
|
||||
|
||||
|
|
@ -361,15 +348,12 @@ describe('ReactLegacyCompositeComponent', () => {
|
|||
' in Parent (at **)',
|
||||
'Child uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in Child (at **)\n') +
|
||||
' in Parent (at **)',
|
||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in Child (at **)\n') +
|
||||
' in Parent (at **)',
|
||||
'Grandchild uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in Grandchild (at **)\n') +
|
||||
' in Child (at **)\n' +
|
||||
' in Parent (at **)',
|
||||
]);
|
||||
|
|
@ -441,7 +425,6 @@ describe('ReactLegacyCompositeComponent', () => {
|
|||
assertConsoleErrorDev([
|
||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in Child (at **)\n') +
|
||||
' in Parent (at **)',
|
||||
]);
|
||||
|
||||
|
|
|
|||
|
|
@ -104,16 +104,10 @@ describe('ReactLegacyContextDisabled', () => {
|
|||
' in LegacyProvider (at **)',
|
||||
'LegacyClsConsumer uses the legacy contextTypes API which was removed in React 19. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in LegacyClsConsumer (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n' + ' in span (at **)\n' + ' in LegacyProvider (at **)'),
|
||||
' in LegacyClsConsumer (at **)',
|
||||
'LegacyFnConsumer uses the legacy contextTypes API which was removed in React 19. ' +
|
||||
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in LegacyFnConsumer (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n' + ' in span (at **)\n' + ' in LegacyProvider (at **)'),
|
||||
' in LegacyFnConsumer (at **)',
|
||||
]);
|
||||
expect(container.textContent).toBe('{}undefinedundefined');
|
||||
expect(lifecycleContextLog).toEqual([]);
|
||||
|
|
@ -151,16 +145,10 @@ describe('ReactLegacyContextDisabled', () => {
|
|||
' in LegacyProvider (at **)',
|
||||
'LegacyClsConsumer uses the legacy contextTypes API which was removed in React 19. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in LegacyClsConsumer (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n' + ' in span (at **)\n' + ' in LegacyProvider (at **)'),
|
||||
' in LegacyClsConsumer (at **)',
|
||||
'LegacyFnConsumer uses the legacy contextTypes API which was removed in React 19. ' +
|
||||
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in LegacyFnConsumer (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n' + ' in span (at **)\n' + ' in LegacyProvider (at **)'),
|
||||
' in LegacyFnConsumer (at **)',
|
||||
]);
|
||||
expect(text).toBe('<span>{}<!-- -->undefined<!-- -->undefined</span>');
|
||||
expect(lifecycleContextLog).toEqual([{}, {}, {}]);
|
||||
|
|
|
|||
|
|
@ -2112,16 +2112,6 @@ describe('ReactLegacyErrorBoundaries', () => {
|
|||
ReactDOM.render(<X />, container);
|
||||
});
|
||||
}).rejects.toThrow('got: null');
|
||||
if (gate(flags => !flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'React.jsx: type is invalid -- expected a string ' +
|
||||
'(for built-in components) or a class/function ' +
|
||||
'(for composite components) but got: null.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
await expect(async () => {
|
||||
const container = document.createElement('div');
|
||||
|
|
@ -2129,16 +2119,6 @@ describe('ReactLegacyErrorBoundaries', () => {
|
|||
ReactDOM.render(<Y />, container);
|
||||
});
|
||||
}).rejects.toThrow('got: undefined');
|
||||
if (gate(flags => !flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'React.jsx: type is invalid -- expected a string ' +
|
||||
'(for built-in components) or a class/function ' +
|
||||
'(for composite components) but got: undefined.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// @gate !disableLegacyMode
|
||||
|
|
|
|||
|
|
@ -228,13 +228,7 @@ describe('ReactMultiChild', () => {
|
|||
'across updates. Non-unique keys may cause children to be ' +
|
||||
'duplicated and/or omitted — the behavior is unsupported and ' +
|
||||
'could change in a future version.\n' +
|
||||
' in div (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: '\n in div (at **)' +
|
||||
'\n in WrapperComponent (at **)' +
|
||||
'\n in div (at **)' +
|
||||
'\n in Parent (at **)'),
|
||||
' in div (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -290,13 +284,7 @@ describe('ReactMultiChild', () => {
|
|||
'across updates. Non-unique keys may cause children to be ' +
|
||||
'duplicated and/or omitted — the behavior is unsupported and ' +
|
||||
'could change in a future version.\n' +
|
||||
' in div (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: '\n in div (at **)' +
|
||||
'\n in WrapperComponent (at **)' +
|
||||
'\n in div (at **)' +
|
||||
'\n in Parent (at **)'),
|
||||
' in div (at **)',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -758,20 +758,12 @@ describe('ReactDOMServer', () => {
|
|||
'<inPUT /> is using incorrect casing. ' +
|
||||
'Use PascalCase for React components, ' +
|
||||
'or lowercase for HTML elements.\n' +
|
||||
' in inPUT (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in div (at **)'),
|
||||
' in inPUT (at **)',
|
||||
// linearGradient doesn't warn
|
||||
'<iFrame /> is using incorrect casing. ' +
|
||||
'Use PascalCase for React components, ' +
|
||||
'or lowercase for HTML elements.\n' +
|
||||
' in iFrame (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in foreignObject (at **)' +
|
||||
'\n in g (at **)' +
|
||||
'\n in CompositeG (at **)' +
|
||||
'\n in svg (at **)' +
|
||||
'\n in div (at **)'),
|
||||
' in iFrame (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -869,30 +861,14 @@ describe('ReactDOMServer', () => {
|
|||
ReactDOMServer.renderToString(<App />);
|
||||
assertConsoleErrorDev([
|
||||
'Invalid ARIA attribute `ariaTypo`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in span (at **)\n' +
|
||||
' in B (at **)\n' +
|
||||
' in Child (at **)\n' +
|
||||
' in App (at **)'
|
||||
: ' in span (at **)\n' +
|
||||
' in b (at **)\n' +
|
||||
' in C (at **)\n' +
|
||||
' in font (at **)\n' +
|
||||
' in B (at **)\n' +
|
||||
' in Child (at **)\n' +
|
||||
' in span (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in App (at **)'),
|
||||
' in span (at **)\n' +
|
||||
' in B (at **)\n' +
|
||||
' in Child (at **)\n' +
|
||||
' in App (at **)',
|
||||
'Invalid ARIA attribute `ariaTypo2`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in span (at **)\n' +
|
||||
' in Child (at **)\n' +
|
||||
' in App (at **)'
|
||||
: ' in span (at **)\n' +
|
||||
' in Child (at **)\n' +
|
||||
' in span (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in App (at **)'),
|
||||
' in span (at **)\n' +
|
||||
' in Child (at **)\n' +
|
||||
' in App (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -929,47 +905,30 @@ describe('ReactDOMServer', () => {
|
|||
assertConsoleErrorDev([
|
||||
// ReactDOMServer(App > div > span)
|
||||
'Invalid ARIA attribute `ariaTypo`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in span (at **)\n' + ' in App (at **)'
|
||||
: ' in span (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in App (at **)'),
|
||||
' in span (at **)\n' +
|
||||
' in App (at **)',
|
||||
// ReactDOMServer(App > div > Child) >>> ReactDOMServer(App2) >>> ReactDOMServer(blink)
|
||||
'Invalid ARIA attribute `ariaTypo2`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in blink (at **)\n' +
|
||||
' in App2 (at **)\n' +
|
||||
' in Child (at **)\n' +
|
||||
' in App (at **)'
|
||||
: ' in blink (at **)'),
|
||||
' in blink (at **)\n' +
|
||||
' in App2 (at **)\n' +
|
||||
' in Child (at **)\n' +
|
||||
' in App (at **)',
|
||||
// ReactDOMServer(App > div > Child) >>> ReactDOMServer(App2 > Child2 > span)
|
||||
'Invalid ARIA attribute `ariaTypo3`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in span (at **)\n' +
|
||||
' in Child2 (at **)\n' +
|
||||
' in App2 (at **)\n' +
|
||||
' in Child (at **)\n' +
|
||||
' in App (at **)'
|
||||
: ' in span (at **)\n' +
|
||||
' in Child2 (at **)\n' +
|
||||
' in App2 (at **)'),
|
||||
' in span (at **)\n' +
|
||||
' in Child2 (at **)\n' +
|
||||
' in App2 (at **)\n' +
|
||||
' in Child (at **)\n' +
|
||||
' in App (at **)',
|
||||
// ReactDOMServer(App > div > Child > span)
|
||||
'Invalid ARIA attribute `ariaTypo4`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in span (at **)\n' +
|
||||
' in Child (at **)\n' +
|
||||
' in App (at **)'
|
||||
: ' in span (at **)\n' +
|
||||
' in Child (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in App (at **)'),
|
||||
' in span (at **)\n' +
|
||||
' in Child (at **)\n' +
|
||||
' in App (at **)',
|
||||
// ReactDOMServer(App > div > font)
|
||||
'Invalid ARIA attribute `ariaTypo5`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in font (at **)\n' + ' in App (at **)'
|
||||
: ' in font (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in App (at **)'),
|
||||
' in font (at **)\n' +
|
||||
' in App (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1877,9 +1877,7 @@ describe('ReactUpdates', () => {
|
|||
const originalConsoleError = console.error;
|
||||
console.error = e => {
|
||||
error = e;
|
||||
ownerStack = gate(flags => flags.enableOwnerStacks)
|
||||
? React.captureOwnerStack()
|
||||
: null;
|
||||
ownerStack = React.captureOwnerStack();
|
||||
debugStack = new Error().stack;
|
||||
Scheduler.log('stop');
|
||||
};
|
||||
|
|
@ -1895,11 +1893,7 @@ describe('ReactUpdates', () => {
|
|||
expect(error).toContain('Maximum update depth exceeded');
|
||||
// The currently executing effect should be on the native stack
|
||||
expect(debugStack).toContain('at myEffect');
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
expect(ownerStack).toContain('at App');
|
||||
} else {
|
||||
expect(ownerStack).toBe(null);
|
||||
}
|
||||
expect(ownerStack).toContain('at App');
|
||||
});
|
||||
|
||||
it('can have nested updates if they do not cross the limit', async () => {
|
||||
|
|
|
|||
|
|
@ -121,34 +121,20 @@ describe('validateDOMNesting', () => {
|
|||
);
|
||||
expectWarnings(
|
||||
['div', 'ul', 'li', 'div', 'li'],
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'In HTML, <li> cannot be a descendant of <li>.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <ul>\n' +
|
||||
'> <li>\n' +
|
||||
' <div>\n' +
|
||||
'> <li>\n' +
|
||||
'\n' +
|
||||
' in li (at **)',
|
||||
'<li> cannot contain a nested <li>.\nSee this log for the ancestor stack trace.\n' +
|
||||
' in li (at **)',
|
||||
]
|
||||
: [
|
||||
'In HTML, <li> cannot be a descendant of <li>.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <ul>\n' +
|
||||
'> <li>\n' +
|
||||
' <div>\n' +
|
||||
'> <li>\n' +
|
||||
'\n' +
|
||||
' in li (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in li (at **)\n' +
|
||||
' in ul (at **)',
|
||||
],
|
||||
|
||||
[
|
||||
'In HTML, <li> cannot be a descendant of <li>.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
' <ul>\n' +
|
||||
'> <li>\n' +
|
||||
' <div>\n' +
|
||||
'> <li>\n' +
|
||||
'\n' +
|
||||
' in li (at **)',
|
||||
'<li> cannot contain a nested <li>.\nSee this log for the ancestor stack trace.\n' +
|
||||
' in li (at **)',
|
||||
],
|
||||
);
|
||||
expectWarnings(
|
||||
['div', 'html'],
|
||||
|
|
@ -208,28 +194,16 @@ describe('validateDOMNesting', () => {
|
|||
);
|
||||
expectWarnings(
|
||||
['svg', 'foreignObject', 'body', 'p'],
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
// TODO, this should say "In SVG",
|
||||
'In HTML, <body> cannot be a child of <foreignObject>.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
'> <foreignObject>\n' +
|
||||
'> <body>\n' +
|
||||
'\n' +
|
||||
' in body (at **)',
|
||||
]
|
||||
: [
|
||||
// TODO, this should say "In SVG",
|
||||
'In HTML, <body> cannot be a child of <foreignObject>.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
'> <foreignObject>\n' +
|
||||
'> <body>\n' +
|
||||
'\n' +
|
||||
' in body (at **)\n' +
|
||||
' in foreignObject (at **)',
|
||||
],
|
||||
[
|
||||
// TODO, this should say "In SVG",
|
||||
'In HTML, <body> cannot be a child of <foreignObject>.\n' +
|
||||
'This will cause a hydration error.\n' +
|
||||
'\n' +
|
||||
'> <foreignObject>\n' +
|
||||
'> <body>\n' +
|
||||
'\n' +
|
||||
' in body (at **)',
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -233,9 +233,7 @@ if (!__EXPERIMENTAL__) {
|
|||
'\n in div (at **)',
|
||||
);
|
||||
expect(normalizeCodeLocInfo(caughtErrors[0].ownerStack)).toBe(
|
||||
__DEV__ && gate(flags => flags.enableOwnerStacks)
|
||||
? '\n in Bar (at **)' + '\n in Foo (at **)'
|
||||
: null,
|
||||
__DEV__ ? '\n in Bar (at **)' + '\n in Foo (at **)' : null,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -269,9 +269,7 @@ if (!__EXPERIMENTAL__) {
|
|||
: '\n in div (at **)' + '\n in div (at **)',
|
||||
);
|
||||
expect(normalizeCodeLocInfo(caughtErrors[0].ownerStack)).toBe(
|
||||
__DEV__ && gate(flags => flags.enableOwnerStacks)
|
||||
? '\n in Bar (at **)' + '\n in Foo (at **)'
|
||||
: null,
|
||||
__DEV__ ? '\n in Bar (at **)' + '\n in Foo (at **)' : null,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -875,10 +875,7 @@ describe('ReactFabric', () => {
|
|||
});
|
||||
assertConsoleErrorDev([
|
||||
'Text strings must be rendered within a <Text> component.\n' +
|
||||
' in RCTScrollView (at **)' +
|
||||
(gate(flags => !flags.enableOwnerStacks)
|
||||
? '\n in RCTText (at **)'
|
||||
: ''),
|
||||
' in RCTScrollView (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
import isArray from 'shared/isArray';
|
||||
|
||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
||||
|
||||
import {runWithFiberInDEV} from 'react-reconciler/src/ReactCurrentFiber';
|
||||
|
||||
let hasError = false;
|
||||
|
|
@ -99,7 +97,7 @@ export function executeDispatchesInOrder(event) {
|
|||
// Listeners and Instances are two parallel arrays that are always in sync.
|
||||
const listener = dispatchListeners[i];
|
||||
const instance = dispatchInstances[i];
|
||||
if (__DEV__ && enableOwnerStacks && instance !== null) {
|
||||
if (__DEV__ && instance !== null) {
|
||||
runWithFiberInDEV(instance, executeDispatch, event, listener, instance);
|
||||
} else {
|
||||
executeDispatch(event, listener, instance);
|
||||
|
|
@ -108,7 +106,7 @@ export function executeDispatchesInOrder(event) {
|
|||
} else if (dispatchListeners) {
|
||||
const listener = dispatchListeners;
|
||||
const instance = dispatchInstances;
|
||||
if (__DEV__ && enableOwnerStacks && instance !== null) {
|
||||
if (__DEV__ && instance !== null) {
|
||||
runWithFiberInDEV(instance, executeDispatch, event, listener, instance);
|
||||
} else {
|
||||
executeDispatch(event, listener, instance);
|
||||
|
|
|
|||
33
packages/react-reconciler/src/ReactChildFiber.js
vendored
33
packages/react-reconciler/src/ReactChildFiber.js
vendored
|
|
@ -47,7 +47,6 @@ import isArray from 'shared/isArray';
|
|||
import {
|
||||
enableAsyncIterableChildren,
|
||||
disableLegacyMode,
|
||||
enableOwnerStacks,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
|
||||
import {
|
||||
|
|
@ -488,9 +487,7 @@ function createChildReconciler(
|
|||
if (__DEV__) {
|
||||
// We treat the parent as the owner for stack purposes.
|
||||
created._debugOwner = returnFiber;
|
||||
if (enableOwnerStacks) {
|
||||
created._debugTask = returnFiber._debugTask;
|
||||
}
|
||||
created._debugTask = returnFiber._debugTask;
|
||||
created._debugInfo = currentDebugInfo;
|
||||
}
|
||||
return created;
|
||||
|
|
@ -609,9 +606,7 @@ function createChildReconciler(
|
|||
if (__DEV__) {
|
||||
// We treat the parent as the owner for stack purposes.
|
||||
created._debugOwner = returnFiber;
|
||||
if (enableOwnerStacks) {
|
||||
created._debugTask = returnFiber._debugTask;
|
||||
}
|
||||
created._debugTask = returnFiber._debugTask;
|
||||
created._debugInfo = currentDebugInfo;
|
||||
}
|
||||
return created;
|
||||
|
|
@ -649,9 +644,7 @@ function createChildReconciler(
|
|||
if (__DEV__) {
|
||||
// We treat the parent as the owner for stack purposes.
|
||||
created._debugOwner = returnFiber;
|
||||
if (enableOwnerStacks) {
|
||||
created._debugTask = returnFiber._debugTask;
|
||||
}
|
||||
created._debugTask = returnFiber._debugTask;
|
||||
created._debugInfo = currentDebugInfo;
|
||||
}
|
||||
return created;
|
||||
|
|
@ -718,9 +711,7 @@ function createChildReconciler(
|
|||
if (__DEV__) {
|
||||
// We treat the parent as the owner for stack purposes.
|
||||
created._debugOwner = returnFiber;
|
||||
if (enableOwnerStacks) {
|
||||
created._debugTask = returnFiber._debugTask;
|
||||
}
|
||||
created._debugTask = returnFiber._debugTask;
|
||||
const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
|
||||
created._debugInfo = currentDebugInfo;
|
||||
currentDebugInfo = prevDebugInfo;
|
||||
|
|
@ -1605,9 +1596,7 @@ function createChildReconciler(
|
|||
if (__DEV__) {
|
||||
// We treat the parent as the owner for stack purposes.
|
||||
created._debugOwner = returnFiber;
|
||||
if (enableOwnerStacks) {
|
||||
created._debugTask = returnFiber._debugTask;
|
||||
}
|
||||
created._debugTask = returnFiber._debugTask;
|
||||
created._debugInfo = currentDebugInfo;
|
||||
}
|
||||
return created;
|
||||
|
|
@ -1685,9 +1674,7 @@ function createChildReconciler(
|
|||
if (__DEV__) {
|
||||
// We treat the parent as the owner for stack purposes.
|
||||
created._debugOwner = returnFiber;
|
||||
if (enableOwnerStacks) {
|
||||
created._debugTask = returnFiber._debugTask;
|
||||
}
|
||||
created._debugTask = returnFiber._debugTask;
|
||||
created._debugInfo = currentDebugInfo;
|
||||
}
|
||||
validateFragmentProps(element, created, returnFiber);
|
||||
|
|
@ -1980,16 +1967,12 @@ function createChildReconciler(
|
|||
// thing when it's thrown from the same async component but not if you await
|
||||
// a promise started from a different component/task.
|
||||
throwFiber._debugOwner = returnFiber._debugOwner;
|
||||
if (enableOwnerStacks) {
|
||||
throwFiber._debugTask = returnFiber._debugTask;
|
||||
}
|
||||
throwFiber._debugTask = returnFiber._debugTask;
|
||||
if (debugInfo != null) {
|
||||
for (let i = debugInfo.length - 1; i >= 0; i--) {
|
||||
if (typeof debugInfo[i].stack === 'string') {
|
||||
throwFiber._debugOwner = (debugInfo[i]: any);
|
||||
if (enableOwnerStacks) {
|
||||
throwFiber._debugTask = debugInfo[i].debugTask;
|
||||
}
|
||||
throwFiber._debugTask = debugInfo[i].debugTask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,12 +10,8 @@
|
|||
import type {Fiber} from './ReactInternalTypes';
|
||||
|
||||
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
||||
import {
|
||||
getStackByFiberInDevAndProd,
|
||||
getOwnerStackByFiberInDev,
|
||||
} from './ReactFiberComponentStack';
|
||||
import {getOwnerStackByFiberInDev} from './ReactFiberComponentStack';
|
||||
import {getComponentNameFromOwner} from 'react-reconciler/src/getComponentNameFromFiber';
|
||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
||||
|
||||
export let current: Fiber | null = null;
|
||||
export let isRendering: boolean = false;
|
||||
|
|
@ -42,10 +38,7 @@ function getCurrentFiberStackInDev(): string {
|
|||
// and it is guaranteed to be the work-in-progress version.
|
||||
// TODO: The above comment is not actually true. We might be
|
||||
// in a commit phase or preemptive set state callback.
|
||||
if (enableOwnerStacks) {
|
||||
return getOwnerStackByFiberInDev(current);
|
||||
}
|
||||
return getStackByFiberInDevAndProd(current);
|
||||
return getOwnerStackByFiberInDev(current);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
|
@ -63,12 +56,10 @@ export function runWithFiberInDEV<A0, A1, A2, A3, A4, T>(
|
|||
const previousFiber = current;
|
||||
setCurrentFiber(fiber);
|
||||
try {
|
||||
if (enableOwnerStacks) {
|
||||
if (fiber !== null && fiber._debugTask) {
|
||||
return fiber._debugTask.run(
|
||||
callback.bind(null, arg0, arg1, arg2, arg3, arg4),
|
||||
);
|
||||
}
|
||||
if (fiber !== null && fiber._debugTask) {
|
||||
return fiber._debugTask.run(
|
||||
callback.bind(null, arg0, arg1, arg2, arg3, arg4),
|
||||
);
|
||||
}
|
||||
return callback(arg0, arg1, arg2, arg3, arg4);
|
||||
} finally {
|
||||
|
|
|
|||
25
packages/react-reconciler/src/ReactFiber.js
vendored
25
packages/react-reconciler/src/ReactFiber.js
vendored
|
|
@ -40,7 +40,6 @@ import {
|
|||
enableRenderableContext,
|
||||
disableLegacyMode,
|
||||
enableObjectFiber,
|
||||
enableOwnerStacks,
|
||||
enableViewTransition,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
|
||||
|
|
@ -202,10 +201,8 @@ function FiberNode(
|
|||
// This isn't directly used but is handy for debugging internals:
|
||||
this._debugInfo = null;
|
||||
this._debugOwner = null;
|
||||
if (enableOwnerStacks) {
|
||||
this._debugStack = null;
|
||||
this._debugTask = null;
|
||||
}
|
||||
this._debugStack = null;
|
||||
this._debugTask = null;
|
||||
this._debugNeedsRemount = false;
|
||||
this._debugHookTypes = null;
|
||||
if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
|
||||
|
|
@ -293,10 +290,8 @@ function createFiberImplObject(
|
|||
// This isn't directly used but is handy for debugging internals:
|
||||
fiber._debugInfo = null;
|
||||
fiber._debugOwner = null;
|
||||
if (enableOwnerStacks) {
|
||||
fiber._debugStack = null;
|
||||
fiber._debugTask = null;
|
||||
}
|
||||
fiber._debugStack = null;
|
||||
fiber._debugTask = null;
|
||||
fiber._debugNeedsRemount = false;
|
||||
fiber._debugHookTypes = null;
|
||||
if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
|
||||
|
|
@ -352,10 +347,8 @@ export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {
|
|||
// DEV-only fields
|
||||
|
||||
workInProgress._debugOwner = current._debugOwner;
|
||||
if (enableOwnerStacks) {
|
||||
workInProgress._debugStack = current._debugStack;
|
||||
workInProgress._debugTask = current._debugTask;
|
||||
}
|
||||
workInProgress._debugStack = current._debugStack;
|
||||
workInProgress._debugTask = current._debugTask;
|
||||
workInProgress._debugHookTypes = current._debugHookTypes;
|
||||
}
|
||||
|
||||
|
|
@ -766,10 +759,8 @@ export function createFiberFromElement(
|
|||
);
|
||||
if (__DEV__) {
|
||||
fiber._debugOwner = element._owner;
|
||||
if (enableOwnerStacks) {
|
||||
fiber._debugStack = element._debugStack;
|
||||
fiber._debugTask = element._debugTask;
|
||||
}
|
||||
fiber._debugStack = element._debugStack;
|
||||
fiber._debugTask = element._debugTask;
|
||||
}
|
||||
return fiber;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,6 @@ import {
|
|||
enableRenderableContext,
|
||||
disableLegacyMode,
|
||||
disableDefaultPropsExceptForClasses,
|
||||
enableOwnerStacks,
|
||||
enableHydrationLaneScheduling,
|
||||
enableViewTransition,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
|
|
@ -3782,10 +3781,8 @@ function beginWork(
|
|||
workInProgress.mode,
|
||||
workInProgress.lanes,
|
||||
);
|
||||
if (enableOwnerStacks) {
|
||||
copiedFiber._debugStack = workInProgress._debugStack;
|
||||
copiedFiber._debugTask = workInProgress._debugTask;
|
||||
}
|
||||
copiedFiber._debugStack = workInProgress._debugStack;
|
||||
copiedFiber._debugTask = workInProgress._debugTask;
|
||||
return remountFiber(current, workInProgress, copiedFiber);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,7 @@
|
|||
* @flow
|
||||
*/
|
||||
|
||||
import {
|
||||
enableOwnerStacks,
|
||||
enableViewTransition,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import {enableViewTransition} from 'shared/ReactFeatureFlags';
|
||||
import type {Fiber} from './ReactInternalTypes';
|
||||
import type {ReactComponentInfo} from 'shared/ReactTypes';
|
||||
|
||||
|
|
@ -101,7 +98,7 @@ function describeFunctionComponentFrameWithoutLineNumber(fn: Function): string {
|
|||
}
|
||||
|
||||
export function getOwnerStackByFiberInDev(workInProgress: Fiber): string {
|
||||
if (!enableOwnerStacks || !__DEV__) {
|
||||
if (!__DEV__) {
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@ import reportGlobalError from 'shared/reportGlobalError';
|
|||
|
||||
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
||||
|
||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
||||
|
||||
import {bindToConsole} from './ReactFiberConfig';
|
||||
|
||||
// Side-channel since I'm not sure we want to make this part of the public API
|
||||
|
|
@ -46,18 +44,6 @@ export function defaultOnUncaughtError(
|
|||
'Consider adding an error boundary to your tree to customize error handling behavior.\n' +
|
||||
'Visit https://react.dev/link/error-boundaries to learn more about error boundaries.';
|
||||
|
||||
const prevGetCurrentStack = ReactSharedInternals.getCurrentStack;
|
||||
if (!enableOwnerStacks) {
|
||||
// The current Fiber is disconnected at this point which means that console printing
|
||||
// cannot add a component stack since it terminates at the deletion node. This is not
|
||||
// a problem for owner stacks which are not disconnected but for the parent component
|
||||
// stacks we need to use the snapshot we've previously extracted.
|
||||
const componentStack =
|
||||
errorInfo.componentStack != null ? errorInfo.componentStack : '';
|
||||
ReactSharedInternals.getCurrentStack = function () {
|
||||
return componentStack;
|
||||
};
|
||||
}
|
||||
try {
|
||||
console.warn(
|
||||
'%s\n\n%s\n',
|
||||
|
|
@ -66,9 +52,7 @@ export function defaultOnUncaughtError(
|
|||
// We let our console.error wrapper add the component stack to the end.
|
||||
);
|
||||
} finally {
|
||||
if (!enableOwnerStacks) {
|
||||
ReactSharedInternals.getCurrentStack = prevGetCurrentStack;
|
||||
}
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -97,18 +81,6 @@ export function defaultOnCaughtError(
|
|||
errorBoundaryName || 'Anonymous'
|
||||
}.`;
|
||||
|
||||
const prevGetCurrentStack = ReactSharedInternals.getCurrentStack;
|
||||
if (!enableOwnerStacks) {
|
||||
// The current Fiber is disconnected at this point which means that console printing
|
||||
// cannot add a component stack since it terminates at the deletion node. This is not
|
||||
// a problem for owner stacks which are not disconnected but for the parent component
|
||||
// stacks we need to use the snapshot we've previously extracted.
|
||||
const componentStack =
|
||||
errorInfo.componentStack != null ? errorInfo.componentStack : '';
|
||||
ReactSharedInternals.getCurrentStack = function () {
|
||||
return componentStack;
|
||||
};
|
||||
}
|
||||
try {
|
||||
if (
|
||||
typeof error === 'object' &&
|
||||
|
|
@ -138,9 +110,7 @@ export function defaultOnCaughtError(
|
|||
);
|
||||
}
|
||||
} finally {
|
||||
if (!enableOwnerStacks) {
|
||||
ReactSharedInternals.getCurrentStack = prevGetCurrentStack;
|
||||
}
|
||||
// ignore
|
||||
}
|
||||
} else {
|
||||
// In production, we print the error directly.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ describe('ErrorBoundaryReconciliation', () => {
|
|||
let ReactTestRenderer;
|
||||
let span;
|
||||
let act;
|
||||
let assertConsoleErrorDev;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
|
|
@ -14,8 +13,6 @@ describe('ErrorBoundaryReconciliation', () => {
|
|||
ReactTestRenderer = require('react-test-renderer');
|
||||
React = require('react');
|
||||
act = require('internal-test-utils').act;
|
||||
assertConsoleErrorDev =
|
||||
require('internal-test-utils').assertConsoleErrorDev;
|
||||
DidCatchErrorBoundary = class extends React.Component {
|
||||
state = {error: null};
|
||||
componentDidCatch(error) {
|
||||
|
|
@ -68,9 +65,6 @@ describe('ErrorBoundaryReconciliation', () => {
|
|||
</ErrorBoundary>,
|
||||
);
|
||||
});
|
||||
if (gate(flags => !flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(['invalid', 'invalid']);
|
||||
}
|
||||
|
||||
const Fallback = fallbackTagName;
|
||||
expect(renderer).toMatchRenderedOutput(<Fallback prop="ErrorBoundary" />);
|
||||
|
|
|
|||
|
|
@ -168,9 +168,7 @@ describe('ReactFragment', () => {
|
|||
'Foo',
|
||||
'CatchingBoundary',
|
||||
]),
|
||||
gate(flags => flags.enableOwnerStacks) && __DEV__
|
||||
? componentStack(['Bar', 'Foo'])
|
||||
: null,
|
||||
__DEV__ ? componentStack(['Bar', 'Foo']) : null,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -744,19 +744,12 @@ describe('ReactFragment', () => {
|
|||
ReactNoop.render(<Foo condition={false} />);
|
||||
await waitForAll([]);
|
||||
assertConsoleErrorDev([
|
||||
gate('enableOwnerStacks')
|
||||
? 'Each child in a list should have a unique "key" prop.\n' +
|
||||
'\n' +
|
||||
'Check the render method of `div`. ' +
|
||||
'It was passed a child from Foo. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Foo (at **)'
|
||||
: 'Each child in a list should have a unique "key" prop.\n' +
|
||||
'\n' +
|
||||
'Check the render method of `Foo`. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Stateful (at **)\n' +
|
||||
' in Foo (at **)',
|
||||
'Each child in a list should have a unique "key" prop.\n' +
|
||||
'\n' +
|
||||
'Check the render method of `div`. ' +
|
||||
'It was passed a child from Foo. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Foo (at **)',
|
||||
]);
|
||||
|
||||
expect(ops).toEqual([]);
|
||||
|
|
|
|||
|
|
@ -1236,24 +1236,20 @@ describe('ReactHooks', () => {
|
|||
'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
|
||||
'In function components, you can read it directly in the function body, ' +
|
||||
'but not inside Hooks like useReducer() or useMemo().\n' +
|
||||
' in App (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
||||
' in App (at **)',
|
||||
'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +
|
||||
'You can only call Hooks at the top level of your React function. ' +
|
||||
'For more information, see https://react.dev/link/rules-of-hooks\n' +
|
||||
' in App (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
||||
' in App (at **)',
|
||||
'Context can only be read while React is rendering. ' +
|
||||
'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
|
||||
'In function components, you can read it directly in the function body, ' +
|
||||
'but not inside Hooks like useReducer() or useMemo().\n' +
|
||||
' in App (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
||||
' in App (at **)',
|
||||
'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +
|
||||
'You can only call Hooks at the top level of your React function. ' +
|
||||
'For more information, see https://react.dev/link/rules-of-hooks\n' +
|
||||
' in App (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
||||
' in App (at **)',
|
||||
]);
|
||||
|
||||
function Valid() {
|
||||
|
|
@ -1293,24 +1289,20 @@ describe('ReactHooks', () => {
|
|||
'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
|
||||
'In function components, you can read it directly in the function body, ' +
|
||||
'but not inside Hooks like useReducer() or useMemo().\n' +
|
||||
' in App (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
||||
' in App (at **)',
|
||||
'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +
|
||||
'You can only call Hooks at the top level of your React function. ' +
|
||||
'For more information, see https://react.dev/link/rules-of-hooks\n' +
|
||||
' in App (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
||||
' in App (at **)',
|
||||
'Context can only be read while React is rendering. ' +
|
||||
'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
|
||||
'In function components, you can read it directly in the function body, ' +
|
||||
'but not inside Hooks like useReducer() or useMemo().\n' +
|
||||
' in App (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
||||
' in App (at **)',
|
||||
'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +
|
||||
'You can only call Hooks at the top level of your React function. ' +
|
||||
'For more information, see https://react.dev/link/rules-of-hooks\n' +
|
||||
' in App (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
||||
' in App (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1803,14 +1803,10 @@ describe('ReactIncremental', () => {
|
|||
' in Intl (at **)',
|
||||
'ShowLocale uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in ShowLocale (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in Intl (at **)'),
|
||||
' in ShowLocale (at **)',
|
||||
'ShowBoth uses the legacy contextTypes API which will be removed soon. ' +
|
||||
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in ShowBoth (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in div (at **)' + '\n in Intl (at **)'),
|
||||
' in ShowBoth (at **)',
|
||||
]);
|
||||
|
||||
ReactNoop.render(
|
||||
|
|
@ -1865,16 +1861,10 @@ describe('ReactIncremental', () => {
|
|||
assertConsoleErrorDev([
|
||||
'Router uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Router (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in Intl (at **)'),
|
||||
' in Router (at **)',
|
||||
'ShowRoute uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ' in Indirection (at **)'
|
||||
: ' in ShowRoute (at **)\n' +
|
||||
' in Indirection (at **)\n' +
|
||||
' in Router (at **)\n' +
|
||||
' in Intl (at **)'),
|
||||
' in Indirection (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -1972,8 +1962,7 @@ describe('ReactIncremental', () => {
|
|||
' in Intl (at **)',
|
||||
'ShowLocale uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in ShowLocale (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in Intl (at **)'),
|
||||
' in ShowLocale (at **)',
|
||||
]);
|
||||
|
||||
await waitForAll([
|
||||
|
|
@ -2068,22 +2057,10 @@ describe('ReactIncremental', () => {
|
|||
' in Intl (at **)',
|
||||
'ShowLocaleClass uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in ShowLocaleClass (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in Stateful (at **)' +
|
||||
'\n in IndirectionClass (at **)' +
|
||||
'\n in IndirectionFn (at **)' +
|
||||
' in Intl (at **)'),
|
||||
' in ShowLocaleClass (at **)',
|
||||
'ShowLocaleFn uses the legacy contextTypes API which will be removed soon. ' +
|
||||
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in ShowLocaleFn (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in Stateful (at **)' +
|
||||
'\n in IndirectionClass (at **)' +
|
||||
'\n in IndirectionFn (at **)' +
|
||||
' in Intl (at **)'),
|
||||
' in ShowLocaleFn (at **)',
|
||||
]);
|
||||
|
||||
statefulInst.setState({x: 1});
|
||||
|
|
@ -2174,26 +2151,14 @@ describe('ReactIncremental', () => {
|
|||
assertConsoleErrorDev([
|
||||
'Intl uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in Intl (at **)\n') +
|
||||
' in Stateful (at **)',
|
||||
'ShowLocaleClass uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in ShowLocaleClass (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in IndirectionClass (at **)' +
|
||||
'\n in IndirectionFn (at **)' +
|
||||
'\n in Intl (at **)' +
|
||||
'\n in Stateful (at **)'),
|
||||
' in ShowLocaleClass (at **)',
|
||||
|
||||
'ShowLocaleFn uses the legacy contextTypes API which will be removed soon. ' +
|
||||
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in ShowLocaleFn (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in IndirectionClass (at **)' +
|
||||
'\n in IndirectionFn (at **)' +
|
||||
'\n in Intl (at **)' +
|
||||
'\n in Stateful (at **)'),
|
||||
' in ShowLocaleFn (at **)',
|
||||
]);
|
||||
|
||||
statefulInst.setState({locale: 'gr'});
|
||||
|
|
@ -2255,7 +2220,6 @@ describe('ReactIncremental', () => {
|
|||
assertConsoleErrorDev([
|
||||
'Child uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in Child (at **)\n') +
|
||||
' in Middle (at **)\n' +
|
||||
' in Root (at **)',
|
||||
]);
|
||||
|
|
@ -2309,7 +2273,6 @@ describe('ReactIncremental', () => {
|
|||
assertConsoleErrorDev([
|
||||
'ContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in ContextProvider (at **)\n') +
|
||||
' in Root (at **)',
|
||||
]);
|
||||
|
||||
|
|
@ -2511,10 +2474,7 @@ describe('ReactIncremental', () => {
|
|||
' in TopContextProvider (at **)',
|
||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Child (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in Middle (at **)' + '\n in TopContextProvider (at **)'),
|
||||
' in Child (at **)',
|
||||
]);
|
||||
instance.updateCount();
|
||||
await waitForAll(['count:1']);
|
||||
|
|
@ -2578,17 +2538,10 @@ describe('ReactIncremental', () => {
|
|||
' in TopContextProvider (at **)',
|
||||
'MiddleContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in MiddleContextProvider (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in TopContextProvider (at **)'),
|
||||
' in MiddleContextProvider (at **)',
|
||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Child (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in MiddleContextProvider (at **)' +
|
||||
'\n in TopContextProvider (at **)'),
|
||||
' in Child (at **)',
|
||||
]);
|
||||
instance.updateCount();
|
||||
await waitForAll(['count:1']);
|
||||
|
|
@ -2661,19 +2614,10 @@ describe('ReactIncremental', () => {
|
|||
' in TopContextProvider (at **)',
|
||||
'MiddleContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in MiddleContextProvider (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in MiddleScu (at **)' +
|
||||
'\n in TopContextProvider (at **)'),
|
||||
' in MiddleContextProvider (at **)',
|
||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Child (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in MiddleContextProvider (at **)' +
|
||||
'\n in MiddleScu (at **)' +
|
||||
'\n in TopContextProvider (at **)'),
|
||||
' in Child (at **)',
|
||||
]);
|
||||
instance.updateCount();
|
||||
await waitForAll([]);
|
||||
|
|
@ -2756,19 +2700,10 @@ describe('ReactIncremental', () => {
|
|||
' in TopContextProvider (at **)',
|
||||
'MiddleContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in MiddleContextProvider (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in MiddleScu (at **)' +
|
||||
'\n in TopContextProvider (at **)'),
|
||||
' in MiddleContextProvider (at **)',
|
||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Child (at **)' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: '\n in MiddleContextProvider (at **)' +
|
||||
'\n in MiddleScu (at **)' +
|
||||
'\n in TopContextProvider (at **)'),
|
||||
' in Child (at **)',
|
||||
]);
|
||||
topInstance.updateCount();
|
||||
await waitForAll([]);
|
||||
|
|
|
|||
|
|
@ -1222,8 +1222,7 @@ describe('ReactIncrementalErrorHandling', () => {
|
|||
' in Provider (at **)',
|
||||
'Connector uses the legacy contextTypes API which will be removed soon. ' +
|
||||
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Connector (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in Provider (at **)'),
|
||||
' in Connector (at **)',
|
||||
]);
|
||||
|
||||
// If the context stack does not unwind, span will get 'abcde'
|
||||
|
|
@ -1254,23 +1253,6 @@ describe('ReactIncrementalErrorHandling', () => {
|
|||
</ErrorBoundary>,
|
||||
);
|
||||
await waitForAll([]);
|
||||
if (gate(flags => !flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'React.jsx: type is invalid -- expected a string (for built-in components) ' +
|
||||
'or a class/function (for composite components) but got: undefined. ' +
|
||||
"You likely forgot to export your component from the file it's defined in, " +
|
||||
'or you might have mixed up default and named imports.\n' +
|
||||
' in BrokenRender (at **)\n' +
|
||||
' in ErrorBoundary (at **)',
|
||||
// React retries once on error
|
||||
'React.jsx: type is invalid -- expected a string (for built-in components) ' +
|
||||
'or a class/function (for composite components) but got: undefined. ' +
|
||||
"You likely forgot to export your component from the file it's defined in, " +
|
||||
'or you might have mixed up default and named imports.\n' +
|
||||
' in BrokenRender (at **)\n' +
|
||||
' in ErrorBoundary (at **)',
|
||||
]);
|
||||
}
|
||||
|
||||
expect(ReactNoop).toMatchRenderedOutput(
|
||||
<span
|
||||
|
|
@ -1319,23 +1301,7 @@ describe('ReactIncrementalErrorHandling', () => {
|
|||
</ErrorBoundary>,
|
||||
);
|
||||
await waitForAll([]);
|
||||
if (gate(flags => !flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'React.jsx: type is invalid -- expected a string (for built-in components) ' +
|
||||
'or a class/function (for composite components) but got: undefined. ' +
|
||||
"You likely forgot to export your component from the file it's defined in, " +
|
||||
'or you might have mixed up default and named imports.\n' +
|
||||
' in BrokenRender (at **)\n' +
|
||||
' in ErrorBoundary (at **)',
|
||||
// React retries once on error
|
||||
'React.jsx: type is invalid -- expected a string (for built-in components) ' +
|
||||
'or a class/function (for composite components) but got: undefined. ' +
|
||||
"You likely forgot to export your component from the file it's defined in, " +
|
||||
'or you might have mixed up default and named imports.\n' +
|
||||
' in BrokenRender (at **)\n' +
|
||||
' in ErrorBoundary (at **)',
|
||||
]);
|
||||
}
|
||||
|
||||
expect(ReactNoop).toMatchRenderedOutput(
|
||||
<span
|
||||
prop={
|
||||
|
|
@ -1354,17 +1320,6 @@ describe('ReactIncrementalErrorHandling', () => {
|
|||
it('recovers from uncaught reconciler errors', async () => {
|
||||
const InvalidType = undefined;
|
||||
ReactNoop.render(<InvalidType />);
|
||||
if (gate(flags => !flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'React.jsx: type is invalid -- expected a string (for built-in components) ' +
|
||||
'or a class/function (for composite components) but got: undefined. ' +
|
||||
"You likely forgot to export your component from the file it's defined in, " +
|
||||
'or you might have mixed up default and named imports.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
await waitForThrow(
|
||||
'Element type is invalid: expected a string (for built-in components) or ' +
|
||||
|
|
|
|||
|
|
@ -94,11 +94,7 @@ describe('ReactIncrementalErrorLogging', () => {
|
|||
// The component stack is not added without the polyfill/devtools.
|
||||
// expect.stringMatching(
|
||||
// new RegExp(
|
||||
// gate(flags => flags.enableOwnerStacks)
|
||||
// ? '\\s+(in|at) ErrorThrowingComponent'
|
||||
// : '\\s+(in|at) ErrorThrowingComponent (.*)\n' +
|
||||
// '\\s+(in|at) span(.*)\n' +
|
||||
// '\\s+(in|at) div(.*)',
|
||||
// '\\s+(in|at) ErrorThrowingComponent'
|
||||
// ),
|
||||
// ),
|
||||
);
|
||||
|
|
@ -143,11 +139,7 @@ describe('ReactIncrementalErrorLogging', () => {
|
|||
// The component stack is not added without the polyfill/devtools.
|
||||
// expect.stringMatching(
|
||||
// new RegExp(
|
||||
// gate(flags => flags.enableOwnerStacks)
|
||||
// ? '\\s+(in|at) ErrorThrowingComponent'
|
||||
// : '\\s+(in|at) ErrorThrowingComponent (.*)\n' +
|
||||
// '\\s+(in|at) span(.*)\n' +
|
||||
// '\\s+(in|at) div(.*)',
|
||||
// '\\s+(in|at) ErrorThrowingComponent'
|
||||
// ),
|
||||
// ),
|
||||
);
|
||||
|
|
@ -204,12 +196,7 @@ describe('ReactIncrementalErrorLogging', () => {
|
|||
// The component stack is not added without the polyfill/devtools.
|
||||
// expect.stringMatching(
|
||||
// new RegExp(
|
||||
// gate(flags => flags.enableOwnerStacks)
|
||||
// ? '\\s+(in|at) ErrorThrowingComponent'
|
||||
// : '\\s+(in|at) ErrorThrowingComponent (.*)\n' +
|
||||
// '\\s+(in|at) span(.*)\n' +
|
||||
// '\\s+(in|at) ErrorBoundary(.*)\n' +
|
||||
// '\\s+(in|at) div(.*)',
|
||||
// '\\s+(in|at) ErrorThrowingComponent'
|
||||
// ),
|
||||
// ),
|
||||
);
|
||||
|
|
@ -287,11 +274,7 @@ describe('ReactIncrementalErrorLogging', () => {
|
|||
),
|
||||
// The component stack is not added without the polyfill/devtools.
|
||||
// expect.stringMatching(
|
||||
// gate(flag => flag.enableOwnerStacks)
|
||||
// ? new RegExp('\\s+(in|at) Foo')
|
||||
// : new RegExp(
|
||||
// '\\s+(in|at) Foo (.*)\n' + '\\s+(in|at) ErrorBoundary(.*)',
|
||||
// ),
|
||||
// new RegExp('\\s+(in|at) Foo')
|
||||
// ),
|
||||
);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -240,9 +240,6 @@ describe('ReactLazy', () => {
|
|||
' }\n\n' +
|
||||
'Your code should look like: \n ' +
|
||||
"const MyComponent = lazy(() => import('./MyComponent'))\n" +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Lazy (at **)\n' + ' in Suspense (at **)\n') +
|
||||
' in App (at **)',
|
||||
'lazy: Expected the result of a dynamic import() call. ' +
|
||||
'Instead received: function Text(props) {\n' +
|
||||
|
|
@ -251,9 +248,6 @@ describe('ReactLazy', () => {
|
|||
' }\n\n' +
|
||||
'Your code should look like: \n ' +
|
||||
"const MyComponent = lazy(() => import('./MyComponent'))\n" +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Lazy (at **)\n' + ' in Suspense (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
expect(root).not.toMatchRenderedOutput('Hi');
|
||||
|
|
@ -749,8 +743,7 @@ describe('ReactLazy', () => {
|
|||
'T: Support for defaultProps ' +
|
||||
'will be removed from function components in a future major ' +
|
||||
'release. Use JavaScript default parameters instead.\n' +
|
||||
' in T (at **)\n' +
|
||||
' in Suspense (at **)',
|
||||
' in T (at **)',
|
||||
]);
|
||||
|
||||
expect(root).toMatchRenderedOutput('Hi Bye');
|
||||
|
|
@ -855,11 +848,15 @@ describe('ReactLazy', () => {
|
|||
);
|
||||
});
|
||||
|
||||
async function verifyResolvesProps(
|
||||
Add,
|
||||
shouldWarnAboutFunctionDefaultProps,
|
||||
shouldWarnAboutMemoDefaultProps,
|
||||
) {
|
||||
// @gate !disableDefaultPropsExceptForClasses
|
||||
it('resolves props for function component with defaultProps', async () => {
|
||||
function Add(props) {
|
||||
expect(props.innerWithDefault).toBe(42);
|
||||
return props.inner + props.outer;
|
||||
}
|
||||
Add.defaultProps = {
|
||||
innerWithDefault: 42,
|
||||
};
|
||||
const LazyAdd = lazy(() => fakeImport(Add));
|
||||
const root = ReactTestRenderer.create(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
|
|
@ -876,18 +873,10 @@ describe('ReactLazy', () => {
|
|||
// Mount
|
||||
await act(() => resolveFakeImport(Add));
|
||||
|
||||
if (shouldWarnAboutFunctionDefaultProps) {
|
||||
assertConsoleErrorDev([
|
||||
'Add: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.\n' +
|
||||
' in Add (at **)\n' +
|
||||
' in Suspense (at **)',
|
||||
]);
|
||||
} else if (shouldWarnAboutMemoDefaultProps) {
|
||||
assertConsoleErrorDev([
|
||||
'Add: Support for defaultProps will be removed from memo components in a future major release. Use JavaScript default parameters instead.\n' +
|
||||
' in Suspense (at **)',
|
||||
]);
|
||||
}
|
||||
assertConsoleErrorDev([
|
||||
'Add: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.\n' +
|
||||
' in Add (at **)',
|
||||
]);
|
||||
|
||||
expect(root).toMatchRenderedOutput('22');
|
||||
|
||||
|
|
@ -899,25 +888,38 @@ describe('ReactLazy', () => {
|
|||
);
|
||||
await waitForAll([]);
|
||||
expect(root).toMatchRenderedOutput('0');
|
||||
}
|
||||
|
||||
// @gate !disableDefaultPropsExceptForClasses
|
||||
it('resolves props for function component with defaultProps', async () => {
|
||||
function Add(props) {
|
||||
expect(props.innerWithDefault).toBe(42);
|
||||
return props.inner + props.outer;
|
||||
}
|
||||
Add.defaultProps = {
|
||||
innerWithDefault: 42,
|
||||
};
|
||||
await verifyResolvesProps(Add, true);
|
||||
});
|
||||
|
||||
it('resolves props for function component without defaultProps', async () => {
|
||||
function Add(props) {
|
||||
return props.inner + props.outer;
|
||||
}
|
||||
await verifyResolvesProps(Add);
|
||||
const LazyAdd = lazy(() => fakeImport(Add));
|
||||
const root = ReactTestRenderer.create(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner="2" outer="2" />
|
||||
</Suspense>,
|
||||
{
|
||||
unstable_isConcurrent: true,
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAll(['Loading...']);
|
||||
expect(root).not.toMatchRenderedOutput('22');
|
||||
|
||||
// Mount
|
||||
await act(() => resolveFakeImport(Add));
|
||||
|
||||
expect(root).toMatchRenderedOutput('22');
|
||||
|
||||
// Update
|
||||
root.update(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner={false} outer={false} />
|
||||
</Suspense>,
|
||||
);
|
||||
await waitForAll([]);
|
||||
expect(root).toMatchRenderedOutput('0');
|
||||
});
|
||||
|
||||
it('resolves props for class component with defaultProps', async () => {
|
||||
|
|
@ -930,7 +932,32 @@ describe('ReactLazy', () => {
|
|||
Add.defaultProps = {
|
||||
innerWithDefault: 42,
|
||||
};
|
||||
await verifyResolvesProps(Add);
|
||||
const LazyAdd = lazy(() => fakeImport(Add));
|
||||
const root = ReactTestRenderer.create(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner="2" outer="2" />
|
||||
</Suspense>,
|
||||
{
|
||||
unstable_isConcurrent: true,
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAll(['Loading...']);
|
||||
expect(root).not.toMatchRenderedOutput('22');
|
||||
|
||||
// Mount
|
||||
await act(() => resolveFakeImport(Add));
|
||||
|
||||
expect(root).toMatchRenderedOutput('22');
|
||||
|
||||
// Update
|
||||
root.update(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner={false} outer={false} />
|
||||
</Suspense>,
|
||||
);
|
||||
await waitForAll([]);
|
||||
expect(root).toMatchRenderedOutput('0');
|
||||
});
|
||||
|
||||
it('resolves props for class component without defaultProps', async () => {
|
||||
|
|
@ -939,7 +966,32 @@ describe('ReactLazy', () => {
|
|||
return this.props.inner + this.props.outer;
|
||||
}
|
||||
}
|
||||
await verifyResolvesProps(Add);
|
||||
const LazyAdd = lazy(() => fakeImport(Add));
|
||||
const root = ReactTestRenderer.create(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner="2" outer="2" />
|
||||
</Suspense>,
|
||||
{
|
||||
unstable_isConcurrent: true,
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAll(['Loading...']);
|
||||
expect(root).not.toMatchRenderedOutput('22');
|
||||
|
||||
// Mount
|
||||
await act(() => resolveFakeImport(Add));
|
||||
|
||||
expect(root).toMatchRenderedOutput('22');
|
||||
|
||||
// Update
|
||||
root.update(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner={false} outer={false} />
|
||||
</Suspense>,
|
||||
);
|
||||
await waitForAll([]);
|
||||
expect(root).toMatchRenderedOutput('0');
|
||||
});
|
||||
|
||||
// @gate !disableDefaultPropsExceptForClasses
|
||||
|
|
@ -952,7 +1004,32 @@ describe('ReactLazy', () => {
|
|||
Add.defaultProps = {
|
||||
innerWithDefault: 42,
|
||||
};
|
||||
await verifyResolvesProps(Add);
|
||||
const LazyAdd = lazy(() => fakeImport(Add));
|
||||
const root = ReactTestRenderer.create(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner="2" outer="2" />
|
||||
</Suspense>,
|
||||
{
|
||||
unstable_isConcurrent: true,
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAll(['Loading...']);
|
||||
expect(root).not.toMatchRenderedOutput('22');
|
||||
|
||||
// Mount
|
||||
await act(() => resolveFakeImport(Add));
|
||||
|
||||
expect(root).toMatchRenderedOutput('22');
|
||||
|
||||
// Update
|
||||
root.update(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner={false} outer={false} />
|
||||
</Suspense>,
|
||||
);
|
||||
await waitForAll([]);
|
||||
expect(root).toMatchRenderedOutput('0');
|
||||
});
|
||||
|
||||
it('resolves props for forwardRef component without defaultProps', async () => {
|
||||
|
|
@ -960,7 +1037,33 @@ describe('ReactLazy', () => {
|
|||
return props.inner + props.outer;
|
||||
});
|
||||
Add.displayName = 'Add';
|
||||
await verifyResolvesProps(Add);
|
||||
|
||||
const LazyAdd = lazy(() => fakeImport(Add));
|
||||
const root = ReactTestRenderer.create(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner="2" outer="2" />
|
||||
</Suspense>,
|
||||
{
|
||||
unstable_isConcurrent: true,
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAll(['Loading...']);
|
||||
expect(root).not.toMatchRenderedOutput('22');
|
||||
|
||||
// Mount
|
||||
await act(() => resolveFakeImport(Add));
|
||||
|
||||
expect(root).toMatchRenderedOutput('22');
|
||||
|
||||
// Update
|
||||
root.update(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner={false} outer={false} />
|
||||
</Suspense>,
|
||||
);
|
||||
await waitForAll([]);
|
||||
expect(root).toMatchRenderedOutput('0');
|
||||
});
|
||||
|
||||
// @gate !disableDefaultPropsExceptForClasses
|
||||
|
|
@ -973,7 +1076,39 @@ describe('ReactLazy', () => {
|
|||
Add.defaultProps = {
|
||||
innerWithDefault: 42,
|
||||
};
|
||||
await verifyResolvesProps(Add, false, true);
|
||||
const LazyAdd = lazy(() => fakeImport(Add));
|
||||
const root = ReactTestRenderer.create(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner="2" outer="2" />
|
||||
</Suspense>,
|
||||
{
|
||||
unstable_isConcurrent: true,
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAll(['Loading...']);
|
||||
expect(root).not.toMatchRenderedOutput('22');
|
||||
|
||||
// Mount
|
||||
await act(() => resolveFakeImport(Add));
|
||||
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Add: Support for defaultProps will be removed from memo components in a future major release. Use JavaScript default parameters instead.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
|
||||
expect(root).toMatchRenderedOutput('22');
|
||||
|
||||
// Update
|
||||
root.update(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner={false} outer={false} />
|
||||
</Suspense>,
|
||||
);
|
||||
await waitForAll([]);
|
||||
expect(root).toMatchRenderedOutput('0');
|
||||
});
|
||||
|
||||
it('resolves props for outer memo component without defaultProps', async () => {
|
||||
|
|
@ -981,7 +1116,32 @@ describe('ReactLazy', () => {
|
|||
return props.inner + props.outer;
|
||||
};
|
||||
Add = React.memo(Add);
|
||||
await verifyResolvesProps(Add);
|
||||
const LazyAdd = lazy(() => fakeImport(Add));
|
||||
const root = ReactTestRenderer.create(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner="2" outer="2" />
|
||||
</Suspense>,
|
||||
{
|
||||
unstable_isConcurrent: true,
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAll(['Loading...']);
|
||||
expect(root).not.toMatchRenderedOutput('22');
|
||||
|
||||
// Mount
|
||||
await act(() => resolveFakeImport(Add));
|
||||
|
||||
expect(root).toMatchRenderedOutput('22');
|
||||
|
||||
// Update
|
||||
root.update(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner={false} outer={false} />
|
||||
</Suspense>,
|
||||
);
|
||||
await waitForAll([]);
|
||||
expect(root).toMatchRenderedOutput('0');
|
||||
});
|
||||
|
||||
// @gate !disableDefaultPropsExceptForClasses
|
||||
|
|
@ -994,7 +1154,40 @@ describe('ReactLazy', () => {
|
|||
Add.defaultProps = {
|
||||
innerWithDefault: 42,
|
||||
};
|
||||
await verifyResolvesProps(React.memo(Add), true);
|
||||
const MemoAdd = React.memo(Add);
|
||||
const LazyAdd = lazy(() => fakeImport(MemoAdd));
|
||||
const root = ReactTestRenderer.create(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner="2" outer="2" />
|
||||
</Suspense>,
|
||||
{
|
||||
unstable_isConcurrent: true,
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAll(['Loading...']);
|
||||
expect(root).not.toMatchRenderedOutput('22');
|
||||
|
||||
// Mount
|
||||
await act(() => resolveFakeImport(MemoAdd));
|
||||
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Add: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
|
||||
expect(root).toMatchRenderedOutput('22');
|
||||
|
||||
// Update
|
||||
root.update(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner={false} outer={false} />
|
||||
</Suspense>,
|
||||
);
|
||||
await waitForAll([]);
|
||||
expect(root).toMatchRenderedOutput('0');
|
||||
});
|
||||
|
||||
it('resolves props for inner memo component without defaultProps', async () => {
|
||||
|
|
@ -1002,7 +1195,32 @@ describe('ReactLazy', () => {
|
|||
return props.inner + props.outer;
|
||||
};
|
||||
Add.displayName = 'Add';
|
||||
await verifyResolvesProps(React.memo(Add));
|
||||
const LazyAdd = lazy(() => fakeImport(Add));
|
||||
const root = ReactTestRenderer.create(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner="2" outer="2" />
|
||||
</Suspense>,
|
||||
{
|
||||
unstable_isConcurrent: true,
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAll(['Loading...']);
|
||||
expect(root).not.toMatchRenderedOutput('22');
|
||||
|
||||
// Mount
|
||||
await act(() => resolveFakeImport(Add));
|
||||
|
||||
expect(root).toMatchRenderedOutput('22');
|
||||
|
||||
// Update
|
||||
root.update(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<LazyAdd inner={false} outer={false} />
|
||||
</Suspense>,
|
||||
);
|
||||
await waitForAll([]);
|
||||
expect(root).toMatchRenderedOutput('0');
|
||||
});
|
||||
|
||||
// @gate !disableDefaultPropsExceptForClasses
|
||||
|
|
@ -1030,12 +1248,13 @@ describe('ReactLazy', () => {
|
|||
// Mount
|
||||
await act(() => resolveFakeImport(T));
|
||||
assertLog(['Inner default text']);
|
||||
assertConsoleErrorDev([
|
||||
'T: Support for defaultProps will be removed from function components in a future major release. ' +
|
||||
'Use JavaScript default parameters instead.\n' +
|
||||
' in T (at **)\n' +
|
||||
' in Suspense (at **)',
|
||||
]);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'T: Support for defaultProps will be removed from function components in a future major release. ' +
|
||||
'Use JavaScript default parameters instead.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
expect(root).toMatchRenderedOutput('Inner default text');
|
||||
|
||||
// Update
|
||||
|
|
@ -1074,11 +1293,7 @@ describe('ReactLazy', () => {
|
|||
'\n' +
|
||||
'Check the render method of `Foo`. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in Foo (at **)'
|
||||
: ' in Text (at **)\n' +
|
||||
' in Foo (at **)\n' +
|
||||
' in Suspense (at **)'),
|
||||
' in Foo (at **)',
|
||||
]);
|
||||
expect(root).toMatchRenderedOutput(<div>AB</div>);
|
||||
});
|
||||
|
|
@ -1154,11 +1369,13 @@ describe('ReactLazy', () => {
|
|||
|
||||
// Mount
|
||||
await act(() => resolveFakeImport(Add));
|
||||
assertConsoleErrorDev([
|
||||
'Unknown: Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||
'Use JavaScript default parameters instead.\n' +
|
||||
' in Suspense (at **)',
|
||||
]);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Unknown: Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||
'Use JavaScript default parameters instead.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
expect(root).toMatchRenderedOutput('4');
|
||||
|
||||
// Update (shallowly equal)
|
||||
|
|
@ -1243,14 +1460,15 @@ describe('ReactLazy', () => {
|
|||
|
||||
// Mount
|
||||
await act(() => resolveFakeImport(Add));
|
||||
assertConsoleErrorDev([
|
||||
'Memo: Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||
'Use JavaScript default parameters instead.\n' +
|
||||
' in Suspense (at **)',
|
||||
'Unknown: Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||
'Use JavaScript default parameters instead.\n' +
|
||||
' in Suspense (at **)',
|
||||
]);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Memo: Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||
'Use JavaScript default parameters instead.',
|
||||
'Unknown: Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||
'Use JavaScript default parameters instead.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
expect(root).toMatchRenderedOutput('4');
|
||||
|
||||
// Update
|
||||
|
|
|
|||
|
|
@ -407,12 +407,22 @@ describe('memo', () => {
|
|||
);
|
||||
});
|
||||
assertLog(['Loading...', 15]);
|
||||
assertConsoleErrorDev([
|
||||
'Counter: Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||
'Use JavaScript default parameters instead.\n' +
|
||||
(label === 'lazy' ? '' : ' in Indirection (at **)\n') +
|
||||
' in Suspense (at **)',
|
||||
]);
|
||||
if (label === 'lazy') {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Counter: Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||
'Use JavaScript default parameters instead.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
} else {
|
||||
assertConsoleErrorDev([
|
||||
'Counter: Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||
'Use JavaScript default parameters instead.\n' +
|
||||
' in Indirection (at **)',
|
||||
]);
|
||||
}
|
||||
|
||||
expect(ReactNoop).toMatchRenderedOutput(<span prop={15} />);
|
||||
|
||||
// Should bail out because props have not changed
|
||||
|
|
@ -475,12 +485,14 @@ describe('memo', () => {
|
|||
</div>,
|
||||
);
|
||||
});
|
||||
assertConsoleErrorDev([
|
||||
'Inner: ' +
|
||||
'Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||
'Use JavaScript default parameters instead.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Inner: ' +
|
||||
'Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||
'Use JavaScript default parameters instead.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
expect(root).toMatchRenderedOutput(<div>111</div>);
|
||||
|
||||
await act(async () => {
|
||||
|
|
@ -576,9 +588,7 @@ describe('memo', () => {
|
|||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in span (at **)\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ' in **/ReactMemo-test.js:**:** (at **)'
|
||||
: ' in p (at **)'),
|
||||
' in **/ReactMemo-test.js:**:** (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -597,8 +607,7 @@ describe('memo', () => {
|
|||
'\n\nCheck the top-level render call using <Inner>. It was passed a child from Inner. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in span (at **)\n' +
|
||||
' in Inner (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
||||
' in Inner (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -619,8 +628,7 @@ describe('memo', () => {
|
|||
'\n\nCheck the top-level render call using <Inner>. It was passed a child from Inner. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in span (at **)\n' +
|
||||
' in Inner (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
||||
' in Inner (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -640,8 +648,7 @@ describe('memo', () => {
|
|||
'\n\nCheck the top-level render call using <Outer>. It was passed a child from Outer. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in span (at **)\n' +
|
||||
' in Outer (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
||||
' in Outer (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -663,8 +670,7 @@ describe('memo', () => {
|
|||
'\n\nCheck the top-level render call using <Inner>. It was passed a child from Inner. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in span (at **)\n' +
|
||||
' in Inner (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
||||
' in Inner (at **)',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ describe('ReactOwnerStacks', () => {
|
|||
}
|
||||
});
|
||||
|
||||
// @gate __DEV__ && enableOwnerStacks
|
||||
// @gate __DEV__
|
||||
it('can get the component owner stacks during rendering in dev', async () => {
|
||||
let stack;
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ describe('ReactOwnerStacks', () => {
|
|||
|
||||
it('returns null outside of render', async () => {
|
||||
// Awkward to gate since some builds will have `captureOwnerStack` return null in prod
|
||||
if (__DEV__ && gate('enableOwnerStacks')) {
|
||||
if (__DEV__) {
|
||||
expect(React.captureOwnerStack()).toBe(null);
|
||||
|
||||
await act(() => {
|
||||
|
|
|
|||
|
|
@ -257,9 +257,6 @@ describe('ReactUse', () => {
|
|||
'A component was suspended by an uncached promise. Creating ' +
|
||||
'promises inside a Client Component or hook is not yet ' +
|
||||
'supported, except via a Suspense-compatible library or framework.\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Async (at **)\n' + ' in Suspense (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
assertLog(['ABC']);
|
||||
|
|
@ -430,20 +427,10 @@ describe('ReactUse', () => {
|
|||
'A component was suspended by an uncached promise. Creating ' +
|
||||
'promises inside a Client Component or hook is not yet ' +
|
||||
'supported, except via a Suspense-compatible library or framework.\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Async (at **)\n' +
|
||||
' in ErrorBoundary (at **)\n' +
|
||||
' in Suspense (at **)\n') +
|
||||
' in App (at **)',
|
||||
'A component was suspended by an uncached promise. Creating ' +
|
||||
'promises inside a Client Component or hook is not yet ' +
|
||||
'supported, except via a Suspense-compatible library or framework.\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Async (at **)\n' +
|
||||
' in ErrorBoundary (at **)\n' +
|
||||
' in Suspense (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
assertLog([
|
||||
|
|
@ -617,8 +604,7 @@ describe('ReactUse', () => {
|
|||
'A component was suspended by an uncached promise. ' +
|
||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||
'except via a Suspense-compatible library or framework.\n' +
|
||||
' in App (at **)\n' +
|
||||
' in Suspense (at **)',
|
||||
' in App (at **)',
|
||||
]);
|
||||
expect(root).toMatchRenderedOutput('Async');
|
||||
});
|
||||
|
|
@ -667,8 +653,7 @@ describe('ReactUse', () => {
|
|||
'A component was suspended by an uncached promise. ' +
|
||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||
'except via a Suspense-compatible library or framework.\n' +
|
||||
' in App (at **)\n' +
|
||||
' in Suspense (at **)',
|
||||
' in App (at **)',
|
||||
]);
|
||||
expect(root).toMatchRenderedOutput('Async');
|
||||
});
|
||||
|
|
@ -1216,8 +1201,7 @@ describe('ReactUse', () => {
|
|||
'A component was suspended by an uncached promise. ' +
|
||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||
'except via a Suspense-compatible library or framework.\n' +
|
||||
' in AsyncText (at **)\n' +
|
||||
' in Suspense (at **)',
|
||||
' in AsyncText (at **)',
|
||||
]);
|
||||
expect(root).toMatchRenderedOutput('A(Loading B...)');
|
||||
|
||||
|
|
@ -1243,9 +1227,7 @@ describe('ReactUse', () => {
|
|||
'A component was suspended by an uncached promise. ' +
|
||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||
'except via a Suspense-compatible library or framework.\n' +
|
||||
' in AsyncText (at **)\n' +
|
||||
' in Suspense (at **)\n' +
|
||||
' in Suspense (at **)',
|
||||
' in AsyncText (at **)',
|
||||
]);
|
||||
expect(root).toMatchRenderedOutput('AB(Loading C...)');
|
||||
|
||||
|
|
@ -1263,10 +1245,7 @@ describe('ReactUse', () => {
|
|||
'A component was suspended by an uncached promise. ' +
|
||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||
'except via a Suspense-compatible library or framework.\n' +
|
||||
' in AsyncText (at **)\n' +
|
||||
' in Suspense (at **)\n' +
|
||||
' in Suspense (at **)\n' +
|
||||
' in Suspense (at **)',
|
||||
' in AsyncText (at **)',
|
||||
]);
|
||||
expect(root).toMatchRenderedOutput('ABC');
|
||||
});
|
||||
|
|
@ -1301,16 +1280,10 @@ describe('ReactUse', () => {
|
|||
'A component was suspended by an uncached promise. ' +
|
||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||
'except via a Suspense-compatible library or framework.\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Async (at **)\n' + ' in Suspense (at **)\n') +
|
||||
' in App (at **)',
|
||||
'A component was suspended by an uncached promise. ' +
|
||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||
'except via a Suspense-compatible library or framework.\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Async (at **)\n' + ' in Suspense (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
expect(root).toMatchRenderedOutput('A1');
|
||||
|
|
@ -1685,10 +1658,6 @@ describe('ReactUse', () => {
|
|||
'A component was suspended by an uncached promise. ' +
|
||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||
'except via a Suspense-compatible library or framework.\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in **/ReactUse-test.js:**:** (at **)\n' +
|
||||
' in Suspense (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
expect(root).toMatchRenderedOutput('Async');
|
||||
|
|
@ -1723,10 +1692,6 @@ describe('ReactUse', () => {
|
|||
'A component was suspended by an uncached promise. ' +
|
||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||
'except via a Suspense-compatible library or framework.\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in **/ReactUse-test.js:**:** (at **)\n' +
|
||||
' in Suspense (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
expect(root).toMatchRenderedOutput('Async');
|
||||
|
|
@ -1752,10 +1717,6 @@ describe('ReactUse', () => {
|
|||
'A component was suspended by an uncached promise. ' +
|
||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||
'except via a Suspense-compatible library or framework.\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in **/ReactUse-test.js:**:** (at **)\n' +
|
||||
' in Suspense (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
expect(root).toMatchRenderedOutput('Async!');
|
||||
|
|
@ -1810,36 +1771,17 @@ describe('ReactUse', () => {
|
|||
assertConsoleErrorDev([
|
||||
'ContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks') ? '' : ' in ContextProvider (at **)\n') +
|
||||
' in App (at **)',
|
||||
'Async uses the legacy contextTypes API which will be removed soon. ' +
|
||||
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Async (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in Suspense (at **)\n' +
|
||||
' in ContextProvider (at **)\n') +
|
||||
' in App (at **)',
|
||||
'A component was suspended by an uncached promise. ' +
|
||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||
'except via a Suspense-compatible library or framework.\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Async (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in Suspense (at **)\n' +
|
||||
' in ContextProvider (at **)\n') +
|
||||
' in App (at **)',
|
||||
'A component was suspended by an uncached promise. ' +
|
||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||
'except via a Suspense-compatible library or framework.\n' +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Async (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in Suspense (at **)\n' +
|
||||
' in ContextProvider (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
expect(root).toMatchRenderedOutput(
|
||||
|
|
@ -1921,8 +1863,7 @@ describe('ReactUse', () => {
|
|||
'Only Server Components can be async at the moment. ' +
|
||||
"This error is often caused by accidentally adding `'use client'` " +
|
||||
'to a module that was originally written for the server.\n' +
|
||||
' in AsyncClientComponent (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in ErrorBoundary (at **)'),
|
||||
' in AsyncClientComponent (at **)',
|
||||
]);
|
||||
assertLog([
|
||||
'An unknown Component is an async Client Component. ' +
|
||||
|
|
@ -1977,8 +1918,7 @@ describe('ReactUse', () => {
|
|||
'Only Server Components can be async at the moment. ' +
|
||||
"This error is often caused by accidentally adding `'use client'` " +
|
||||
'to a module that was originally written for the server.\n' +
|
||||
' in AsyncClientComponent (at **)' +
|
||||
(gate('enableOwnerStacks') ? '' : '\n in ErrorBoundary (at **)'),
|
||||
' in AsyncClientComponent (at **)',
|
||||
]);
|
||||
assertLog([
|
||||
'An unknown Component is an async Client Component. ' +
|
||||
|
|
|
|||
|
|
@ -1170,25 +1170,15 @@ describe('ReactFlightDOMBrowser', () => {
|
|||
);
|
||||
const result = await ReactServerDOMClient.createFromReadableStream(stream);
|
||||
|
||||
if (!gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
}
|
||||
|
||||
await act(() => {
|
||||
root.render(result);
|
||||
});
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ParentClient>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
}
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ParentClient>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('basic use(promise)', async () => {
|
||||
|
|
|
|||
|
|
@ -1020,7 +1020,7 @@ describe('ReactFlightDOMEdge', () => {
|
|||
}
|
||||
});
|
||||
|
||||
// @gate __DEV__ && enableOwnerStacks
|
||||
// @gate __DEV__
|
||||
it('can get the component owner stacks asynchronously', async () => {
|
||||
let stack;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,10 +26,7 @@ import {
|
|||
REACT_VIEW_TRANSITION_TYPE,
|
||||
} from 'shared/ReactSymbols';
|
||||
|
||||
import {
|
||||
enableOwnerStacks,
|
||||
enableViewTransition,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import {enableViewTransition} from 'shared/ReactFeatureFlags';
|
||||
|
||||
import {formatOwnerStack} from 'shared/ReactOwnerStackFrames';
|
||||
|
||||
|
|
@ -134,7 +131,7 @@ function describeFunctionComponentFrameWithoutLineNumber(fn: Function): string {
|
|||
export function getOwnerStackByComponentStackNodeInDev(
|
||||
componentStack: ComponentStackNode,
|
||||
): string {
|
||||
if (!enableOwnerStacks || !__DEV__) {
|
||||
if (!__DEV__) {
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
|
|
|
|||
114
packages/react-server/src/ReactFizzServer.js
vendored
114
packages/react-server/src/ReactFizzServer.js
vendored
|
|
@ -165,7 +165,6 @@ import {
|
|||
enableRenderableContext,
|
||||
disableDefaultPropsExceptForClasses,
|
||||
enableAsyncIterableChildren,
|
||||
enableOwnerStacks,
|
||||
enableViewTransition,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
|
||||
|
|
@ -787,7 +786,7 @@ function createRenderTask(
|
|||
if (!disableLegacyContext) {
|
||||
task.legacyContext = legacyContext;
|
||||
}
|
||||
if (__DEV__ && enableOwnerStacks) {
|
||||
if (__DEV__) {
|
||||
task.debugTask = debugTask;
|
||||
}
|
||||
abortSet.add(task);
|
||||
|
|
@ -840,7 +839,7 @@ function createReplayTask(
|
|||
if (!disableLegacyContext) {
|
||||
task.legacyContext = legacyContext;
|
||||
}
|
||||
if (__DEV__ && enableOwnerStacks) {
|
||||
if (__DEV__) {
|
||||
task.debugTask = debugTask;
|
||||
}
|
||||
abortSet.add(task);
|
||||
|
|
@ -875,12 +874,9 @@ function getCurrentStackInDEV(): string {
|
|||
if (currentTaskInDEV === null || currentTaskInDEV.componentStack === null) {
|
||||
return '';
|
||||
}
|
||||
if (enableOwnerStacks) {
|
||||
return getOwnerStackByComponentStackNodeInDev(
|
||||
currentTaskInDEV.componentStack,
|
||||
);
|
||||
}
|
||||
return getStackByComponentStackNode(currentTaskInDEV.componentStack);
|
||||
return getOwnerStackByComponentStackNodeInDev(
|
||||
currentTaskInDEV.componentStack,
|
||||
);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
|
@ -907,18 +903,16 @@ function pushServerComponentStack(
|
|||
if (typeof componentInfo.name !== 'string') {
|
||||
continue;
|
||||
}
|
||||
if (enableOwnerStacks && componentInfo.debugStack === undefined) {
|
||||
if (componentInfo.debugStack === undefined) {
|
||||
continue;
|
||||
}
|
||||
task.componentStack = {
|
||||
parent: task.componentStack,
|
||||
type: componentInfo,
|
||||
owner: componentInfo.owner,
|
||||
stack: enableOwnerStacks ? componentInfo.debugStack : null,
|
||||
stack: componentInfo.debugStack,
|
||||
};
|
||||
if (enableOwnerStacks) {
|
||||
task.debugTask = (componentInfo.debugTask: any);
|
||||
}
|
||||
task.debugTask = (componentInfo.debugTask: any);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -934,12 +928,10 @@ function pushComponentStack(task: Task): void {
|
|||
const element: any = node;
|
||||
const type = element.type;
|
||||
const owner = __DEV__ ? element._owner : null;
|
||||
const stack = __DEV__ && enableOwnerStacks ? element._debugStack : null;
|
||||
const stack = __DEV__ ? element._debugStack : null;
|
||||
if (__DEV__) {
|
||||
pushServerComponentStack(task, element._debugInfo);
|
||||
if (enableOwnerStacks) {
|
||||
task.debugTask = element._debugTask;
|
||||
}
|
||||
task.debugTask = element._debugTask;
|
||||
}
|
||||
task.componentStack = createComponentStackFromType(
|
||||
task.componentStack,
|
||||
|
|
@ -1056,7 +1048,7 @@ function logPostpone(
|
|||
// If this callback errors, we intentionally let that error bubble up to become a fatal error
|
||||
// so that someone fixes the error reporting instead of hiding it.
|
||||
const onPostpone = request.onPostpone;
|
||||
if (__DEV__ && enableOwnerStacks && debugTask) {
|
||||
if (__DEV__ && debugTask) {
|
||||
debugTask.run(onPostpone.bind(null, reason, postponeInfo));
|
||||
} else {
|
||||
onPostpone(reason, postponeInfo);
|
||||
|
|
@ -1073,7 +1065,7 @@ function logRecoverableError(
|
|||
// so that someone fixes the error reporting instead of hiding it.
|
||||
const onError = request.onError;
|
||||
const errorDigest =
|
||||
__DEV__ && enableOwnerStacks && debugTask
|
||||
__DEV__ && debugTask
|
||||
? debugTask.run(onError.bind(null, error, errorInfo))
|
||||
: onError(error, errorInfo);
|
||||
if (errorDigest != null && typeof errorDigest !== 'string') {
|
||||
|
|
@ -1101,7 +1093,7 @@ function fatalError(
|
|||
// It's also called if React itself or its host configs errors.
|
||||
const onShellError = request.onShellError;
|
||||
const onFatalError = request.onFatalError;
|
||||
if (__DEV__ && enableOwnerStacks && debugTask) {
|
||||
if (__DEV__ && debugTask) {
|
||||
debugTask.run(onShellError.bind(null, error));
|
||||
debugTask.run(onFatalError.bind(null, error));
|
||||
} else {
|
||||
|
|
@ -1261,7 +1253,7 @@ function renderSuspenseBoundary(
|
|||
task.componentStack,
|
||||
task.isFallback,
|
||||
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
pushComponentStack(suspendedPrimaryTask);
|
||||
request.pingedTasks.push(suspendedPrimaryTask);
|
||||
|
|
@ -1334,7 +1326,7 @@ function renderSuspenseBoundary(
|
|||
request,
|
||||
postponeInstance.message,
|
||||
thrownInfo,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
// TODO: Figure out a better signal than a magic digest value.
|
||||
errorDigest = 'POSTPONE';
|
||||
|
|
@ -1343,7 +1335,7 @@ function renderSuspenseBoundary(
|
|||
request,
|
||||
error,
|
||||
thrownInfo,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
}
|
||||
encodeErrorForBoundary(
|
||||
|
|
@ -1387,7 +1379,7 @@ function renderSuspenseBoundary(
|
|||
task.componentStack,
|
||||
true,
|
||||
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
pushComponentStack(suspendedFallbackTask);
|
||||
// TODO: This should be queued at a separate lower priority queue so that we only work
|
||||
|
|
@ -1485,7 +1477,7 @@ function replaySuspenseBoundary(
|
|||
request,
|
||||
postponeInstance.message,
|
||||
thrownInfo,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
// TODO: Figure out a better signal than a magic digest value.
|
||||
errorDigest = 'POSTPONE';
|
||||
|
|
@ -1494,7 +1486,7 @@ function replaySuspenseBoundary(
|
|||
request,
|
||||
error,
|
||||
thrownInfo,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
}
|
||||
encodeErrorForBoundary(
|
||||
|
|
@ -1545,7 +1537,7 @@ function replaySuspenseBoundary(
|
|||
task.componentStack,
|
||||
true,
|
||||
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
|
||||
pushComponentStack(suspendedFallbackTask);
|
||||
|
|
@ -1587,7 +1579,7 @@ function renderPreamble(
|
|||
task.componentStack,
|
||||
task.isFallback,
|
||||
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
pushComponentStack(preambleTask);
|
||||
request.pingedTasks.push(preambleTask);
|
||||
|
|
@ -2489,7 +2481,7 @@ function replayElement(
|
|||
thrownInfo,
|
||||
childNodes,
|
||||
childSlots,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
}
|
||||
task.replay = replay;
|
||||
|
|
@ -2654,15 +2646,14 @@ function renderNodeDestructive(
|
|||
task.childIndex = childIndex;
|
||||
|
||||
const previousComponentStack = task.componentStack;
|
||||
const previousDebugTask =
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null;
|
||||
const previousDebugTask = __DEV__ ? task.debugTask : null;
|
||||
|
||||
pushComponentStack(task);
|
||||
|
||||
retryNode(request, task);
|
||||
|
||||
task.componentStack = previousComponentStack;
|
||||
if (__DEV__ && enableOwnerStacks) {
|
||||
if (__DEV__) {
|
||||
task.debugTask = previousDebugTask;
|
||||
}
|
||||
}
|
||||
|
|
@ -2689,8 +2680,7 @@ function retryNode(request: Request, task: Task): void {
|
|||
const refProp = props.ref;
|
||||
const ref = refProp !== undefined ? refProp : null;
|
||||
|
||||
const debugTask: null | ConsoleTask =
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null;
|
||||
const debugTask: null | ConsoleTask = __DEV__ ? task.debugTask : null;
|
||||
|
||||
const name = getComponentNameFromType(type);
|
||||
const keyOrIndex =
|
||||
|
|
@ -3002,7 +2992,7 @@ function replayFragment(
|
|||
thrownInfo,
|
||||
childNodes,
|
||||
childSlots,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
}
|
||||
task.replay = replay;
|
||||
|
|
@ -3094,7 +3084,7 @@ function warnForMissingKey(request: Request, task: Task, child: mixed): void {
|
|||
task.componentStack,
|
||||
(child: any).type,
|
||||
(child: any)._owner,
|
||||
enableOwnerStacks ? (child: any)._debugStack : null,
|
||||
(child: any)._debugStack,
|
||||
);
|
||||
task.componentStack = stackFrame;
|
||||
console.error(
|
||||
|
|
@ -3117,9 +3107,7 @@ function renderChildrenArray(
|
|||
const previousComponentStack = task.componentStack;
|
||||
let previousDebugTask = null;
|
||||
if (__DEV__) {
|
||||
if (enableOwnerStacks) {
|
||||
previousDebugTask = task.debugTask;
|
||||
}
|
||||
previousDebugTask = task.debugTask;
|
||||
// We read debugInfo from task.node instead of children because it might have been an
|
||||
// unwrapped iterable so we read from the original node.
|
||||
pushServerComponentStack(task, (task.node: any)._debugInfo);
|
||||
|
|
@ -3137,9 +3125,7 @@ function renderChildrenArray(
|
|||
task.keyPath = prevKeyPath;
|
||||
if (__DEV__) {
|
||||
task.componentStack = previousComponentStack;
|
||||
if (enableOwnerStacks) {
|
||||
task.debugTask = previousDebugTask;
|
||||
}
|
||||
task.debugTask = previousDebugTask;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -3173,9 +3159,7 @@ function renderChildrenArray(
|
|||
task.keyPath = prevKeyPath;
|
||||
if (__DEV__) {
|
||||
task.componentStack = previousComponentStack;
|
||||
if (enableOwnerStacks) {
|
||||
task.debugTask = previousDebugTask;
|
||||
}
|
||||
task.debugTask = previousDebugTask;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -3198,9 +3182,7 @@ function renderChildrenArray(
|
|||
task.keyPath = prevKeyPath;
|
||||
if (__DEV__) {
|
||||
task.componentStack = previousComponentStack;
|
||||
if (enableOwnerStacks) {
|
||||
task.debugTask = previousDebugTask;
|
||||
}
|
||||
task.debugTask = previousDebugTask;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3394,12 +3376,7 @@ function injectPostponedHole(
|
|||
reason: string,
|
||||
thrownInfo: ThrownInfo,
|
||||
): Segment {
|
||||
logPostpone(
|
||||
request,
|
||||
reason,
|
||||
thrownInfo,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
);
|
||||
logPostpone(request, reason, thrownInfo, __DEV__ ? task.debugTask : null);
|
||||
// Something suspended, we'll need to create a new segment and resolve it later.
|
||||
const segment = task.blockedSegment;
|
||||
const insertionIndex = segment.chunks.length;
|
||||
|
|
@ -3440,7 +3417,7 @@ function spawnNewSuspendedReplayTask(
|
|||
task.componentStack,
|
||||
task.isFallback,
|
||||
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -3482,7 +3459,7 @@ function spawnNewSuspendedRenderTask(
|
|||
task.componentStack,
|
||||
task.isFallback,
|
||||
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -3504,8 +3481,7 @@ function renderNode(
|
|||
const previousKeyPath = task.keyPath;
|
||||
const previousTreeContext = task.treeContext;
|
||||
const previousComponentStack = task.componentStack;
|
||||
const previousDebugTask =
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null;
|
||||
const previousDebugTask = __DEV__ ? task.debugTask : null;
|
||||
let x;
|
||||
// Store how much we've pushed at this point so we can reset it in case something
|
||||
// suspended partially through writing something.
|
||||
|
|
@ -3551,7 +3527,7 @@ function renderNode(
|
|||
task.keyPath = previousKeyPath;
|
||||
task.treeContext = previousTreeContext;
|
||||
task.componentStack = previousComponentStack;
|
||||
if (__DEV__ && enableOwnerStacks) {
|
||||
if (__DEV__) {
|
||||
task.debugTask = previousDebugTask;
|
||||
}
|
||||
// Restore all active ReactContexts to what they were before.
|
||||
|
|
@ -3584,7 +3560,7 @@ function renderNode(
|
|||
task.keyPath = previousKeyPath;
|
||||
task.treeContext = previousTreeContext;
|
||||
task.componentStack = previousComponentStack;
|
||||
if (__DEV__ && enableOwnerStacks) {
|
||||
if (__DEV__) {
|
||||
task.debugTask = previousDebugTask;
|
||||
}
|
||||
// Restore all active ReactContexts to what they were before.
|
||||
|
|
@ -3642,7 +3618,7 @@ function renderNode(
|
|||
task.keyPath = previousKeyPath;
|
||||
task.treeContext = previousTreeContext;
|
||||
task.componentStack = previousComponentStack;
|
||||
if (__DEV__ && enableOwnerStacks) {
|
||||
if (__DEV__) {
|
||||
task.debugTask = previousDebugTask;
|
||||
}
|
||||
// Restore all active ReactContexts to what they were before.
|
||||
|
|
@ -3681,7 +3657,7 @@ function renderNode(
|
|||
task.keyPath = previousKeyPath;
|
||||
task.treeContext = previousTreeContext;
|
||||
task.componentStack = previousComponentStack;
|
||||
if (__DEV__ && enableOwnerStacks) {
|
||||
if (__DEV__) {
|
||||
task.debugTask = previousDebugTask;
|
||||
}
|
||||
// Restore all active ReactContexts to what they were before.
|
||||
|
|
@ -3714,7 +3690,7 @@ function renderNode(
|
|||
task.keyPath = previousKeyPath;
|
||||
task.treeContext = previousTreeContext;
|
||||
task.componentStack = previousComponentStack;
|
||||
if (__DEV__ && enableOwnerStacks) {
|
||||
if (__DEV__) {
|
||||
task.debugTask = previousDebugTask;
|
||||
}
|
||||
// Restore all active ReactContexts to what they were before.
|
||||
|
|
@ -4421,14 +4397,14 @@ function retryRenderTask(
|
|||
request,
|
||||
postponeInstance.message,
|
||||
thrownInfo,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
} else {
|
||||
logRecoverableError(
|
||||
request,
|
||||
x,
|
||||
thrownInfo,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -4464,7 +4440,7 @@ function retryRenderTask(
|
|||
request,
|
||||
postponeInstance.message,
|
||||
postponeInfo,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
trackPostpone(request, trackedPostpones, task, segment);
|
||||
finishedTask(request, task.blockedBoundary, segment);
|
||||
|
|
@ -4481,7 +4457,7 @@ function retryRenderTask(
|
|||
task.blockedBoundary,
|
||||
x,
|
||||
errorInfo,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
return;
|
||||
} finally {
|
||||
|
|
@ -4560,7 +4536,7 @@ function retryReplayTask(request: Request, task: ReplayTask): void {
|
|||
errorInfo,
|
||||
task.replay.nodes,
|
||||
task.replay.slots,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
request.pendingRootTasks--;
|
||||
if (request.pendingRootTasks === 0) {
|
||||
|
|
|
|||
219
packages/react-server/src/ReactFlightServer.js
vendored
219
packages/react-server/src/ReactFlightServer.js
vendored
|
|
@ -17,7 +17,6 @@ import {
|
|||
enablePostpone,
|
||||
enableHalt,
|
||||
enableTaint,
|
||||
enableOwnerStacks,
|
||||
enableProfilerTimer,
|
||||
enableComponentPerformanceTrack,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
|
|
@ -254,15 +253,11 @@ if (__DEV__ && typeof console === 'object' && console !== null) {
|
|||
|
||||
function getCurrentStackInDEV(): string {
|
||||
if (__DEV__) {
|
||||
if (enableOwnerStacks) {
|
||||
const owner: null | ReactComponentInfo = resolveOwner();
|
||||
if (owner === null) {
|
||||
return '';
|
||||
}
|
||||
return getOwnerStackByComponentInfoInDev(owner);
|
||||
const owner: null | ReactComponentInfo = resolveOwner();
|
||||
if (owner === null) {
|
||||
return '';
|
||||
}
|
||||
// We don't have Parent Stacks in Flight.
|
||||
return '';
|
||||
return getOwnerStackByComponentInfoInDev(owner);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
|
@ -624,8 +619,8 @@ function serializeThenable(
|
|||
task.implicitSlot,
|
||||
request.abortableTasks,
|
||||
__DEV__ ? task.debugOwner : null,
|
||||
__DEV__ && enableOwnerStacks ? task.debugStack : null,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugStack : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
if (__DEV__) {
|
||||
// If this came from Flight, forward any debug info into this new row.
|
||||
|
|
@ -744,8 +739,8 @@ function serializeReadableStream(
|
|||
task.implicitSlot,
|
||||
request.abortableTasks,
|
||||
__DEV__ ? task.debugOwner : null,
|
||||
__DEV__ && enableOwnerStacks ? task.debugStack : null,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugStack : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
request.abortableTasks.delete(streamTask);
|
||||
|
||||
|
|
@ -834,8 +829,8 @@ function serializeAsyncIterable(
|
|||
task.implicitSlot,
|
||||
request.abortableTasks,
|
||||
__DEV__ ? task.debugOwner : null,
|
||||
__DEV__ && enableOwnerStacks ? task.debugStack : null,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugStack : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
request.abortableTasks.delete(streamTask);
|
||||
|
||||
|
|
@ -1035,23 +1030,21 @@ function callWithDebugContextInDEV<A, T>(
|
|||
key: null,
|
||||
owner: task.debugOwner,
|
||||
};
|
||||
if (enableOwnerStacks) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.stack =
|
||||
task.debugStack === null
|
||||
? null
|
||||
: filterStackTrace(request, task.debugStack, 1);
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.debugStack = task.debugStack;
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.debugTask = task.debugTask;
|
||||
}
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.stack =
|
||||
task.debugStack === null
|
||||
? null
|
||||
: filterStackTrace(request, task.debugStack, 1);
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.debugStack = task.debugStack;
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.debugTask = task.debugTask;
|
||||
const debugTask = task.debugTask;
|
||||
// We don't need the async component storage context here so we only set the
|
||||
// synchronous tracking of owner.
|
||||
setCurrentOwner(componentDebugInfo);
|
||||
try {
|
||||
if (enableOwnerStacks && debugTask) {
|
||||
if (debugTask) {
|
||||
return debugTask.run(callback.bind(null, arg));
|
||||
}
|
||||
return callback(arg);
|
||||
|
|
@ -1238,22 +1231,18 @@ function renderFunctionComponent<Props>(
|
|||
key: key,
|
||||
owner: task.debugOwner,
|
||||
}: ReactComponentInfo);
|
||||
if (enableOwnerStacks) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.stack =
|
||||
task.debugStack === null
|
||||
? null
|
||||
: filterStackTrace(request, task.debugStack, 1);
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.props = props;
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.debugStack = task.debugStack;
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.debugTask = task.debugTask;
|
||||
} else {
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.props = props;
|
||||
}
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.stack =
|
||||
task.debugStack === null
|
||||
? null
|
||||
: filterStackTrace(request, task.debugStack, 1);
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.props = props;
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.debugStack = task.debugStack;
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.debugTask = task.debugTask;
|
||||
|
||||
// We outline this model eagerly so that we can refer to by reference as an owner.
|
||||
// If we had a smarter way to dedupe we might not have to do this if there ends up
|
||||
// being no references to this as an owner.
|
||||
|
|
@ -1271,14 +1260,14 @@ function renderFunctionComponent<Props>(
|
|||
// We've emitted the latest environment for this task so we track that.
|
||||
task.environmentName = componentEnv;
|
||||
|
||||
if (enableOwnerStacks && validated === 2) {
|
||||
if (validated === 2) {
|
||||
warnForMissingKey(request, key, componentDebugInfo, task.debugTask);
|
||||
}
|
||||
}
|
||||
prepareToUseHooksForComponent(prevThenableState, componentDebugInfo);
|
||||
if (supportsComponentStorage) {
|
||||
// Run the component in an Async Context that tracks the current owner.
|
||||
if (enableOwnerStacks && task.debugTask) {
|
||||
if (task.debugTask) {
|
||||
result = task.debugTask.run(
|
||||
// $FlowFixMe[method-unbinding]
|
||||
componentStorage.run.bind(
|
||||
|
|
@ -1300,7 +1289,7 @@ function renderFunctionComponent<Props>(
|
|||
);
|
||||
}
|
||||
} else {
|
||||
if (enableOwnerStacks && task.debugTask) {
|
||||
if (task.debugTask) {
|
||||
result = task.debugTask.run(
|
||||
callComponentInDEV.bind(null, Component, props, componentDebugInfo),
|
||||
);
|
||||
|
|
@ -1387,7 +1376,7 @@ function warnForMissingKey(
|
|||
|
||||
if (supportsComponentStorage) {
|
||||
// Run the component in an Async Context that tracks the current owner.
|
||||
if (enableOwnerStacks && debugTask) {
|
||||
if (debugTask) {
|
||||
debugTask.run(
|
||||
// $FlowFixMe[method-unbinding]
|
||||
componentStorage.run.bind(
|
||||
|
|
@ -1409,7 +1398,7 @@ function warnForMissingKey(
|
|||
);
|
||||
}
|
||||
} else {
|
||||
if (enableOwnerStacks && debugTask) {
|
||||
if (debugTask) {
|
||||
debugTask.run(
|
||||
callComponentInDEV.bind(null, logKeyError, null, componentDebugInfo),
|
||||
);
|
||||
|
|
@ -1445,23 +1434,15 @@ function renderFragment(
|
|||
// We have a Server Component that specifies a key but we're now splitting
|
||||
// the tree using a fragment.
|
||||
const fragment = __DEV__
|
||||
? enableOwnerStacks
|
||||
? [
|
||||
REACT_ELEMENT_TYPE,
|
||||
REACT_FRAGMENT_TYPE,
|
||||
task.keyPath,
|
||||
{children},
|
||||
null,
|
||||
null,
|
||||
0,
|
||||
]
|
||||
: [
|
||||
REACT_ELEMENT_TYPE,
|
||||
REACT_FRAGMENT_TYPE,
|
||||
task.keyPath,
|
||||
{children},
|
||||
null,
|
||||
]
|
||||
? [
|
||||
REACT_ELEMENT_TYPE,
|
||||
REACT_FRAGMENT_TYPE,
|
||||
task.keyPath,
|
||||
{children},
|
||||
null,
|
||||
null,
|
||||
0,
|
||||
]
|
||||
: [REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE, task.keyPath, {children}];
|
||||
if (!task.implicitSlot) {
|
||||
// If this was keyed inside a set. I.e. the outer Server Component was keyed
|
||||
|
|
@ -1517,23 +1498,15 @@ function renderAsyncFragment(
|
|||
// We have a Server Component that specifies a key but we're now splitting
|
||||
// the tree using a fragment.
|
||||
const fragment = __DEV__
|
||||
? enableOwnerStacks
|
||||
? [
|
||||
REACT_ELEMENT_TYPE,
|
||||
REACT_FRAGMENT_TYPE,
|
||||
task.keyPath,
|
||||
{children},
|
||||
null,
|
||||
null,
|
||||
0,
|
||||
]
|
||||
: [
|
||||
REACT_ELEMENT_TYPE,
|
||||
REACT_FRAGMENT_TYPE,
|
||||
task.keyPath,
|
||||
{children},
|
||||
null,
|
||||
]
|
||||
? [
|
||||
REACT_ELEMENT_TYPE,
|
||||
REACT_FRAGMENT_TYPE,
|
||||
task.keyPath,
|
||||
{children},
|
||||
null,
|
||||
null,
|
||||
0,
|
||||
]
|
||||
: [REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE, task.keyPath, {children}];
|
||||
if (!task.implicitSlot) {
|
||||
// If this was keyed inside a set. I.e. the outer Server Component was keyed
|
||||
|
|
@ -1586,19 +1559,17 @@ function renderClientElement(
|
|||
}
|
||||
}
|
||||
const element = __DEV__
|
||||
? enableOwnerStacks
|
||||
? [
|
||||
REACT_ELEMENT_TYPE,
|
||||
type,
|
||||
key,
|
||||
props,
|
||||
task.debugOwner,
|
||||
task.debugStack === null
|
||||
? null
|
||||
: filterStackTrace(request, task.debugStack, 1),
|
||||
validated,
|
||||
]
|
||||
: [REACT_ELEMENT_TYPE, type, key, props, task.debugOwner]
|
||||
? [
|
||||
REACT_ELEMENT_TYPE,
|
||||
type,
|
||||
key,
|
||||
props,
|
||||
task.debugOwner,
|
||||
task.debugStack === null
|
||||
? null
|
||||
: filterStackTrace(request, task.debugStack, 1),
|
||||
validated,
|
||||
]
|
||||
: [REACT_ELEMENT_TYPE, type, key, props];
|
||||
if (task.implicitSlot && key !== null) {
|
||||
// The root Server Component had no key so it was in an implicit slot.
|
||||
|
|
@ -1626,8 +1597,8 @@ function outlineTask(request: Request, task: Task): ReactJSONValue {
|
|||
task.implicitSlot,
|
||||
request.abortableTasks,
|
||||
__DEV__ ? task.debugOwner : null,
|
||||
__DEV__ && enableOwnerStacks ? task.debugStack : null,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugStack : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
|
||||
retryTask(request, newTask);
|
||||
|
|
@ -1694,7 +1665,7 @@ function renderElement(
|
|||
} else if (type === REACT_FRAGMENT_TYPE && key === null) {
|
||||
// For key-less fragments, we add a small optimization to avoid serializing
|
||||
// it as a wrapper.
|
||||
if (__DEV__ && enableOwnerStacks && validated === 2) {
|
||||
if (__DEV__ && validated === 2) {
|
||||
// Create a fake owner node for the error stack.
|
||||
const componentDebugInfo: ReactComponentInfo = {
|
||||
name: 'Fragment',
|
||||
|
|
@ -1900,10 +1871,8 @@ function createTask(
|
|||
if (__DEV__) {
|
||||
task.environmentName = request.environmentName();
|
||||
task.debugOwner = debugOwner;
|
||||
if (enableOwnerStacks) {
|
||||
task.debugStack = debugStack;
|
||||
task.debugTask = debugTask;
|
||||
}
|
||||
task.debugStack = debugStack;
|
||||
task.debugTask = debugTask;
|
||||
}
|
||||
abortSet.add(task);
|
||||
return task;
|
||||
|
|
@ -2348,8 +2317,8 @@ function renderModel(
|
|||
task.implicitSlot,
|
||||
request.abortableTasks,
|
||||
__DEV__ ? task.debugOwner : null,
|
||||
__DEV__ && enableOwnerStacks ? task.debugStack : null,
|
||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
||||
__DEV__ ? task.debugStack : null,
|
||||
__DEV__ ? task.debugTask : null,
|
||||
);
|
||||
const ping = newTask.ping;
|
||||
(x: any).then(ping, ping);
|
||||
|
|
@ -2487,10 +2456,8 @@ function renderModelDestructive(
|
|||
|
||||
if (__DEV__) {
|
||||
task.debugOwner = element._owner;
|
||||
if (enableOwnerStacks) {
|
||||
task.debugStack = element._debugStack;
|
||||
task.debugTask = element._debugTask;
|
||||
}
|
||||
task.debugStack = element._debugStack;
|
||||
task.debugTask = element._debugTask;
|
||||
// TODO: Pop this. Since we currently don't have a point where we can pop the stack
|
||||
// this debug information will be used for errors inside sibling properties that
|
||||
// are not elements. Leading to the wrong attribution on the server. We could fix
|
||||
|
|
@ -2506,7 +2473,7 @@ function renderModelDestructive(
|
|||
element.key,
|
||||
ref,
|
||||
props,
|
||||
__DEV__ && enableOwnerStacks ? element._store.validated : 0,
|
||||
__DEV__ ? element._store.validated : 0,
|
||||
);
|
||||
if (
|
||||
typeof newChild === 'object' &&
|
||||
|
|
@ -3291,10 +3258,8 @@ function outlineComponentInfo(
|
|||
key: componentInfo.key,
|
||||
owner: componentInfo.owner,
|
||||
};
|
||||
if (enableOwnerStacks) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.stack = componentInfo.stack;
|
||||
}
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.stack = componentInfo.stack;
|
||||
// Ensure we serialize props after the stack to favor the stack being complete.
|
||||
// $FlowFixMe[cannot-write]
|
||||
componentDebugInfo.props = componentInfo.props;
|
||||
|
|
@ -3435,33 +3400,23 @@ function renderConsoleValue(
|
|||
doNotLimit.add(element._owner);
|
||||
}
|
||||
|
||||
if (enableOwnerStacks) {
|
||||
let debugStack: null | ReactStackTrace = null;
|
||||
if (element._debugStack != null) {
|
||||
// Outline the debug stack so that it doesn't get cut off.
|
||||
debugStack = filterStackTrace(request, element._debugStack, 1);
|
||||
doNotLimit.add(debugStack);
|
||||
for (let i = 0; i < debugStack.length; i++) {
|
||||
doNotLimit.add(debugStack[i]);
|
||||
}
|
||||
let debugStack: null | ReactStackTrace = null;
|
||||
if (element._debugStack != null) {
|
||||
// Outline the debug stack so that it doesn't get cut off.
|
||||
debugStack = filterStackTrace(request, element._debugStack, 1);
|
||||
doNotLimit.add(debugStack);
|
||||
for (let i = 0; i < debugStack.length; i++) {
|
||||
doNotLimit.add(debugStack[i]);
|
||||
}
|
||||
return [
|
||||
REACT_ELEMENT_TYPE,
|
||||
element.type,
|
||||
element.key,
|
||||
element.props,
|
||||
element._owner,
|
||||
debugStack,
|
||||
element._store.validated,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
REACT_ELEMENT_TYPE,
|
||||
element.type,
|
||||
element.key,
|
||||
element.props,
|
||||
element._owner,
|
||||
debugStack,
|
||||
element._store.validated,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
* @flow
|
||||
*/
|
||||
|
||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
||||
import {captureOwnerStack as captureOwnerStackImpl} from './src/ReactClient';
|
||||
|
||||
export {
|
||||
__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
|
||||
__COMPILER_RUNTIME,
|
||||
|
|
@ -72,7 +72,7 @@ export {useMemoCache as c} from './src/ReactHooks';
|
|||
|
||||
// Only export captureOwnerStack in development.
|
||||
let captureOwnerStack: ?() => null | string;
|
||||
if (__DEV__ && enableOwnerStacks) {
|
||||
if (__DEV__) {
|
||||
captureOwnerStack = captureOwnerStackImpl;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,18 +7,17 @@
|
|||
* @flow
|
||||
*/
|
||||
|
||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
||||
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
||||
|
||||
export function captureOwnerStack(): null | string {
|
||||
if (!enableOwnerStacks || !__DEV__) {
|
||||
return null;
|
||||
if (__DEV__) {
|
||||
const getCurrentStack = ReactSharedInternals.getCurrentStack;
|
||||
if (getCurrentStack === null) {
|
||||
return null;
|
||||
}
|
||||
// The current stack will be the owner stack which it is always here.
|
||||
return getCurrentStack();
|
||||
}
|
||||
const getCurrentStack = ReactSharedInternals.getCurrentStack;
|
||||
if (getCurrentStack === null) {
|
||||
return null;
|
||||
}
|
||||
// The current stack will be the owner stack if enableOwnerStacks is true
|
||||
// which it is always here. Otherwise it's the parent stack.
|
||||
return getCurrentStack();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
export {default as __SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './ReactSharedInternalsServer';
|
||||
|
||||
import {forEach, map, count, toArray, only} from './ReactChildren';
|
||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
||||
import {captureOwnerStack as captureOwnerStackImpl} from './ReactOwnerStack';
|
||||
import {
|
||||
REACT_FRAGMENT_TYPE,
|
||||
|
|
@ -39,9 +38,8 @@ const Children = {
|
|||
only,
|
||||
};
|
||||
|
||||
// Only export captureOwnerStack if the flag is on, to support feature detection.
|
||||
let captureOwnerStack: ?() => null | string;
|
||||
if (__DEV__ && enableOwnerStacks) {
|
||||
if (__DEV__) {
|
||||
captureOwnerStack = captureOwnerStackImpl;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -333,16 +333,6 @@ describe('ReactChildren', () => {
|
|||
}
|
||||
|
||||
const instance = <div>{threeDivIterable}</div>;
|
||||
assertConsoleErrorDev(
|
||||
// With the flag on this doesn't warn eagerly but only when rendered
|
||||
gate(flag => flag.enableOwnerStacks)
|
||||
? []
|
||||
: [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <div>. See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
],
|
||||
);
|
||||
|
||||
React.Children.forEach(instance.props.children, callback, context);
|
||||
|
||||
|
|
@ -369,8 +359,7 @@ describe('ReactChildren', () => {
|
|||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <div>. It was passed a child from div.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)' +
|
||||
(gate(flag => flag.enableOwnerStacks) ? '' : '\n in div (at **)'),
|
||||
' in div (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -894,22 +883,13 @@ describe('ReactChildren', () => {
|
|||
</ComponentRenderingMappedChildren>,
|
||||
);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentRenderingMappedChildren`.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)\n' +
|
||||
' in **/ReactChildren-test.js:**:** (at **)',
|
||||
]
|
||||
: [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ComponentRenderingMappedChildren>.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
],
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentRenderingMappedChildren`.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)\n' +
|
||||
' in **/ReactChildren-test.js:**:** (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not warn for mapped static children without keys', async () => {
|
||||
|
|
@ -953,21 +933,12 @@ describe('ReactChildren', () => {
|
|||
</ComponentRenderingClonedChildren>,
|
||||
);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentRenderingClonedChildren`.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]
|
||||
: [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ComponentRenderingClonedChildren>.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
],
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentRenderingClonedChildren`.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not warn for cloned static children without keys', async () => {
|
||||
|
|
@ -1005,21 +976,12 @@ describe('ReactChildren', () => {
|
|||
</ComponentRenderingFlattenedChildren>,
|
||||
);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentRenderingFlattenedChildren`.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]
|
||||
: [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ComponentRenderingFlattenedChildren>.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
],
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentRenderingFlattenedChildren`.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not warn for flattened static children without keys', async () => {
|
||||
|
|
|
|||
|
|
@ -266,26 +266,14 @@ describe 'ReactCoffeeScriptClass', ->
|
|||
|
||||
test React.createElement(Outer), 'SPAN', 'foo'
|
||||
|
||||
if featureFlags.enableOwnerStacks
|
||||
assertConsoleErrorDev([
|
||||
'Outer uses the legacy childContextTypes API which will soon be removed.
|
||||
Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Outer (at **)',
|
||||
'Foo uses the legacy contextTypes API which will soon be removed.
|
||||
Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Outer (at **)',
|
||||
]);
|
||||
else
|
||||
assertConsoleErrorDev([
|
||||
'Outer uses the legacy childContextTypes API which will soon be removed.
|
||||
Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Outer (at **)',
|
||||
'Foo uses the legacy contextTypes API which will soon be removed.
|
||||
Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Foo (at **)\n' +
|
||||
' in Outer (at **)',
|
||||
]);
|
||||
|
||||
assertConsoleErrorDev([
|
||||
'Outer uses the legacy childContextTypes API which will soon be removed.
|
||||
Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Outer (at **)',
|
||||
'Foo uses the legacy contextTypes API which will soon be removed.
|
||||
Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Outer (at **)',
|
||||
]);
|
||||
|
||||
it 'renders only once when setting state in componentWillMount', ->
|
||||
renderCount = 0
|
||||
|
|
@ -578,24 +566,13 @@ describe 'ReactCoffeeScriptClass', ->
|
|||
React.createElement Bar
|
||||
|
||||
test React.createElement(Foo), 'DIV', 'bar-through-context'
|
||||
if featureFlags.enableOwnerStacks
|
||||
assertConsoleErrorDev [
|
||||
'Foo uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.
|
||||
(https://react.dev/link/legacy-context)\n' +
|
||||
' in Foo (at **)',
|
||||
'Bar uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.
|
||||
(https://react.dev/link/legacy-context)\n' +
|
||||
' in Foo (at **)'
|
||||
]
|
||||
else
|
||||
assertConsoleErrorDev [
|
||||
'Foo uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.
|
||||
(https://react.dev/link/legacy-context)\n' +
|
||||
' in Foo (at **)',
|
||||
'Bar uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.
|
||||
(https://react.dev/link/legacy-context)\n' +
|
||||
' in Bar (at **)\n' +
|
||||
' in Foo (at **)'
|
||||
]
|
||||
assertConsoleErrorDev [
|
||||
'Foo uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.
|
||||
(https://react.dev/link/legacy-context)\n' +
|
||||
' in Foo (at **)',
|
||||
'Bar uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.
|
||||
(https://react.dev/link/legacy-context)\n' +
|
||||
' in Foo (at **)'
|
||||
]
|
||||
|
||||
undefined
|
||||
|
|
|
|||
|
|
@ -78,9 +78,7 @@ describe('ReactContextValidator', () => {
|
|||
' in ComponentInFooBarContext (at **)',
|
||||
'Component uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in ComponentInFooBarContext (at **)'
|
||||
: ' in Component (at **)'),
|
||||
' in ComponentInFooBarContext (at **)',
|
||||
]);
|
||||
expect(instance.childRef.current.context).toEqual({foo: 'abc'});
|
||||
});
|
||||
|
|
@ -159,9 +157,7 @@ describe('ReactContextValidator', () => {
|
|||
' in Parent (at **)',
|
||||
'Component uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in Parent (at **)'
|
||||
: ' in Component (at **)'),
|
||||
' in Parent (at **)',
|
||||
]);
|
||||
|
||||
expect(constructorContext).toEqual({foo: 'abc'});
|
||||
|
|
@ -282,21 +278,12 @@ describe('ReactContextValidator', () => {
|
|||
' in ParentContextProvider (at **)',
|
||||
'MiddleMissingContext uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: ' in MiddleMissingContext (at **)\n') +
|
||||
' in ParentContextProvider (at **)',
|
||||
'MiddleMissingContext.childContextTypes is specified but there is no getChildContext() method on the instance. ' +
|
||||
'You can either define getChildContext() on MiddleMissingContext or remove childContextTypes from it.\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: ' in MiddleMissingContext (at **)\n') +
|
||||
' in ParentContextProvider (at **)',
|
||||
'ChildContextConsumer uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: ' in ChildContextConsumer (at **)\n') +
|
||||
' in MiddleMissingContext (at **)\n' +
|
||||
' in ParentContextProvider (at **)',
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -77,13 +77,7 @@ describe('ReactCreateElement', () => {
|
|||
'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://react.dev/link/special-props)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? [' in Parent (at **)']
|
||||
: [
|
||||
' in Child (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in Parent (at **)',
|
||||
]),
|
||||
' in Parent (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -46,10 +46,7 @@ describe('ReactCreateRef', () => {
|
|||
assertConsoleErrorDev([
|
||||
'Unexpected ref object provided for div. ' +
|
||||
'Use either a ref-setter function or React.createRef().\n' +
|
||||
' in div (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: '\n in Wrapper (at **)'),
|
||||
' in div (at **)',
|
||||
]);
|
||||
|
||||
ReactDOM.flushSync(() => {
|
||||
|
|
@ -62,10 +59,7 @@ describe('ReactCreateRef', () => {
|
|||
assertConsoleErrorDev([
|
||||
'Unexpected ref object provided for ExampleComponent. ' +
|
||||
'Use either a ref-setter function or React.createRef().\n' +
|
||||
' in ExampleComponent (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: '\n in Wrapper (at **)'),
|
||||
' in ExampleComponent (at **)',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -305,9 +305,6 @@ describe('ReactES6Class', () => {
|
|||
' in Outer (at **)',
|
||||
'Foo uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: ' in Foo (at **)\n') +
|
||||
' in Outer (at **)',
|
||||
]);
|
||||
});
|
||||
|
|
@ -638,9 +635,6 @@ describe('ReactES6Class', () => {
|
|||
' in Foo (at **)',
|
||||
'Bar uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: ' in Bar (at **)\n') +
|
||||
' in Foo (at **)',
|
||||
]);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -46,19 +46,11 @@ describe('ReactElementValidator', () => {
|
|||
]),
|
||||
),
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentClass`. See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in ComponentClass (at **)',
|
||||
]
|
||||
: [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ComponentClass>. See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in ComponentClass (at **)',
|
||||
],
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentClass`. See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in ComponentClass (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('warns for keys for arrays of elements with owner info', async () => {
|
||||
|
|
@ -83,18 +75,10 @@ describe('ReactElementValidator', () => {
|
|||
await act(() => root.render(React.createElement(ComponentWrapper)));
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.' +
|
||||
'\n\nCheck the render method of `' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? 'ComponentClass'
|
||||
: 'InnerClass') +
|
||||
'`. ' +
|
||||
'\n\nCheck the render method of `ComponentClass`. ' +
|
||||
'It was passed a child from ComponentWrapper. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in ComponentWrapper (at **)'
|
||||
: ' in ComponentClass (at **)\n' +
|
||||
' in InnerClass (at **)\n' +
|
||||
' in ComponentWrapper (at **)'),
|
||||
' in ComponentWrapper (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -109,16 +93,12 @@ describe('ReactElementValidator', () => {
|
|||
const root = ReactDOMClient.createRoot(document.createElement('div'));
|
||||
await act(() => root.render(<Anonymous>{divs}</Anonymous>));
|
||||
assertConsoleErrorDev([
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? // For owner stacks the parent being validated is the div.
|
||||
'Each child in a list should have a unique ' +
|
||||
'"key" prop.' +
|
||||
'\n\nCheck the top-level render call using <div>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)'
|
||||
: 'Each child in a list should have a unique ' +
|
||||
'"key" prop. See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
// For owner stacks the parent being validated is the div.
|
||||
'Each child in a list should have a unique ' +
|
||||
'"key" prop.' +
|
||||
'\n\nCheck the top-level render call using <div>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -158,9 +138,6 @@ describe('ReactElementValidator', () => {
|
|||
'https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)\n' +
|
||||
' in Component (at **)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: ' in Parent (at **)\n') +
|
||||
' in GrandParent (at **)',
|
||||
]);
|
||||
});
|
||||
|
|
@ -206,35 +183,12 @@ describe('ReactElementValidator', () => {
|
|||
await act(() =>
|
||||
root.render(React.createElement(ComponentClass, null, iterable)),
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
gate(flag => flag.enableOwnerStacks)
|
||||
? [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentClass`. It was passed a child from div. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in ComponentClass (at **)',
|
||||
]
|
||||
: // Since each pass generates a new element, it doesn't get marked as
|
||||
// validated and it gets rechecked each time.
|
||||
[
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ComponentClass>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in ComponentClass (at **)',
|
||||
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentClass`. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in ComponentClass (at **)\n' +
|
||||
' in ComponentClass (at **)',
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentClass`. It was passed a child from div. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in ComponentClass (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in ComponentClass (at **)',
|
||||
],
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentClass`. It was passed a child from div. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in ComponentClass (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not warns for arrays of elements with keys', () => {
|
||||
|
|
@ -373,13 +327,6 @@ describe('ReactElementValidator', () => {
|
|||
];
|
||||
for (let i = 0; i < cases.length; i++) {
|
||||
await act(async () => root.render(cases[i][0]()));
|
||||
assertConsoleErrorDev(
|
||||
gate(flag => flag.enableOwnerStacks)
|
||||
? // We don't need these extra warnings because we already have the errors.
|
||||
[]
|
||||
: [cases[i][1]],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
expect(errors).toEqual(
|
||||
|
|
@ -468,21 +415,6 @@ describe('ReactElementValidator', () => {
|
|||
'or a class/function (for composite components) but got: null.' +
|
||||
(__DEV__ ? '\n\nCheck the render method of `ParentComp`.' : ''),
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
gate(flag => flag.enableOwnerStacks)
|
||||
? // We don't need these extra warnings because we already have the errors.
|
||||
[]
|
||||
: [
|
||||
'React.createElement: type is invalid -- expected a string ' +
|
||||
'(for built-in components) or a class/function (for composite ' +
|
||||
'components) but got: null.\n' +
|
||||
' in ParentComp (at **)',
|
||||
'React.createElement: type is invalid -- expected a string ' +
|
||||
'(for built-in components) or a class/function (for composite ' +
|
||||
'components) but got: null.\n' +
|
||||
' in ParentComp (at **)',
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
it('warns for fragments with illegal attributes', async () => {
|
||||
|
|
@ -559,18 +491,6 @@ describe('ReactElementValidator', () => {
|
|||
it('does not blow up on key warning with undefined type', () => {
|
||||
const Foo = undefined;
|
||||
void (<Foo>{[<div />]}</Foo>);
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? []
|
||||
: [
|
||||
'React.jsx: type is invalid -- expected a string ' +
|
||||
'(for built-in components) or a class/function (for composite ' +
|
||||
'components) but got: undefined. You likely forgot to export your ' +
|
||||
"component from the file it's defined in, or you might have mixed up " +
|
||||
'default and named imports.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
});
|
||||
|
||||
it('does not call lazy initializers eagerly', () => {
|
||||
|
|
|
|||
|
|
@ -49,13 +49,9 @@ describe('ReactJSXElementValidator', () => {
|
|||
root.render(<Component>{[<Component />, <Component />]}</Component>);
|
||||
});
|
||||
assertConsoleErrorDev([
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? 'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `Component`. See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Component (at **)'
|
||||
: 'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <Component>. See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Component (at **)',
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `Component`. See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Component (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -79,17 +75,9 @@ describe('ReactJSXElementValidator', () => {
|
|||
});
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.' +
|
||||
'\n\nCheck the render method of `' +
|
||||
(gate(flag => flag.enableOwnerStacks)
|
||||
? 'Component'
|
||||
: 'InnerComponent') +
|
||||
'`. ' +
|
||||
'\n\nCheck the render method of `Component`. ' +
|
||||
'It was passed a child from ComponentWrapper. See https://react.dev/link/warning-keys for more information.\n' +
|
||||
(gate(flag => flag.enableOwnerStacks)
|
||||
? ' in ComponentWrapper (at **)'
|
||||
: ' in Component (at **)\n' +
|
||||
' in InnerComponent (at **)\n' +
|
||||
' in ComponentWrapper (at **)'),
|
||||
' in ComponentWrapper (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -112,34 +100,12 @@ describe('ReactJSXElementValidator', () => {
|
|||
await act(() => {
|
||||
root.render(<Component>{iterable}</Component>);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
gate(flag => flag.enableOwnerStacks)
|
||||
? [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `Component`. It was passed a child from div. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Component (at **)',
|
||||
]
|
||||
: // Since each pass generates a new element, it doesn't get marked as
|
||||
// validated and it gets rechecked each time.
|
||||
[
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <Component>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Component (at **)',
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `Component`. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Component (at **)\n' +
|
||||
' in Component (at **)',
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `Component`. It was passed a child from div. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Component (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in Component (at **)',
|
||||
],
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `Component`. It was passed a child from div. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Component (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not warn for arrays of elements with keys', async () => {
|
||||
|
|
|
|||
|
|
@ -215,11 +215,7 @@ describe('ReactJSXRuntime', () => {
|
|||
'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://react.dev/link/special-props)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in Parent (at **)'
|
||||
: ' in Child (at **)\n' +
|
||||
' in div (at **)\n' +
|
||||
' in Parent (at **)'),
|
||||
' in Parent (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -279,9 +275,6 @@ describe('ReactJSXRuntime', () => {
|
|||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `Parent`. See https://react.dev/link/warning-keys for more information.\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: ' in Child (at **)\n') +
|
||||
' in Parent (at **)',
|
||||
]);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1042,67 +1042,30 @@ describe('context legacy', () => {
|
|||
root.render(<Root />);
|
||||
});
|
||||
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'LegacyContextProvider uses the legacy childContextTypes API ' +
|
||||
'which will soon be removed. Use React.createContext() instead. ' +
|
||||
'(https://react.dev/link/legacy-context)' +
|
||||
'\n in Root (at **)',
|
||||
'LegacyContextConsumer uses the legacy contextTypes API which ' +
|
||||
'will soon be removed. Use React.createContext() with static ' +
|
||||
'contextType instead. (https://react.dev/link/legacy-context)' +
|
||||
'\n in LegacyContextProvider (at **)' +
|
||||
'\n in Root (at **)',
|
||||
'FunctionalLegacyContextConsumer uses the legacy contextTypes ' +
|
||||
'API which will be removed soon. Use React.createContext() ' +
|
||||
'with React.useContext() instead. (https://react.dev/link/legacy-context)' +
|
||||
'\n in LegacyContextProvider (at **)' +
|
||||
'\n in Root (at **)',
|
||||
'Legacy context API has been detected within a strict-mode tree.' +
|
||||
'\n\nThe old API will be supported in all 16.x releases, but applications ' +
|
||||
'using it should migrate to the new version.' +
|
||||
'\n\nPlease update the following components: ' +
|
||||
'FunctionalLegacyContextConsumer, LegacyContextConsumer, LegacyContextProvider' +
|
||||
'\n\nLearn more about this warning here: ' +
|
||||
'https://react.dev/link/legacy-context' +
|
||||
'\n in Root (at **)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev([
|
||||
'LegacyContextProvider uses the legacy childContextTypes API ' +
|
||||
'which will soon be removed. Use React.createContext() instead. ' +
|
||||
'(https://react.dev/link/legacy-context)' +
|
||||
'\n in LegacyContextProvider (at **)' +
|
||||
'\n in div (at **)' +
|
||||
'\n in Root (at **)',
|
||||
'LegacyContextConsumer uses the legacy contextTypes API which ' +
|
||||
'will soon be removed. Use React.createContext() with static ' +
|
||||
'contextType instead. (https://react.dev/link/legacy-context)' +
|
||||
'\n in LegacyContextConsumer (at **)' +
|
||||
'\n in div (at **)' +
|
||||
'\n in LegacyContextProvider (at **)' +
|
||||
'\n in div (at **)' +
|
||||
'\n in Root (at **)',
|
||||
'FunctionalLegacyContextConsumer uses the legacy contextTypes ' +
|
||||
'API which will be removed soon. Use React.createContext() ' +
|
||||
'with React.useContext() instead. (https://react.dev/link/legacy-context)' +
|
||||
'\n in FunctionalLegacyContextConsumer (at **)' +
|
||||
'\n in div (at **)' +
|
||||
'\n in LegacyContextProvider (at **)' +
|
||||
'\n in div (at **)' +
|
||||
'\n in Root (at **)',
|
||||
'Legacy context API has been detected within a strict-mode tree.' +
|
||||
'\n\nThe old API will be supported in all 16.x releases, but applications ' +
|
||||
'using it should migrate to the new version.' +
|
||||
'\n\nPlease update the following components: ' +
|
||||
'FunctionalLegacyContextConsumer, LegacyContextConsumer, LegacyContextProvider' +
|
||||
'\n\nLearn more about this warning here: ' +
|
||||
'https://react.dev/link/legacy-context' +
|
||||
'\n in LegacyContextProvider (at **)' +
|
||||
'\n in div (at **)' +
|
||||
'\n in Root (at **)',
|
||||
]);
|
||||
}
|
||||
assertConsoleErrorDev([
|
||||
'LegacyContextProvider uses the legacy childContextTypes API ' +
|
||||
'which will soon be removed. Use React.createContext() instead. ' +
|
||||
'(https://react.dev/link/legacy-context)' +
|
||||
'\n in Root (at **)',
|
||||
'LegacyContextConsumer uses the legacy contextTypes API which ' +
|
||||
'will soon be removed. Use React.createContext() with static ' +
|
||||
'contextType instead. (https://react.dev/link/legacy-context)' +
|
||||
'\n in LegacyContextProvider (at **)' +
|
||||
'\n in Root (at **)',
|
||||
'FunctionalLegacyContextConsumer uses the legacy contextTypes ' +
|
||||
'API which will be removed soon. Use React.createContext() ' +
|
||||
'with React.useContext() instead. (https://react.dev/link/legacy-context)' +
|
||||
'\n in LegacyContextProvider (at **)' +
|
||||
'\n in Root (at **)',
|
||||
'Legacy context API has been detected within a strict-mode tree.' +
|
||||
'\n\nThe old API will be supported in all 16.x releases, but applications ' +
|
||||
'using it should migrate to the new version.' +
|
||||
'\n\nPlease update the following components: ' +
|
||||
'FunctionalLegacyContextConsumer, LegacyContextConsumer, LegacyContextProvider' +
|
||||
'\n\nLearn more about this warning here: ' +
|
||||
'https://react.dev/link/legacy-context' +
|
||||
'\n in Root (at **)',
|
||||
]);
|
||||
|
||||
// Dedupe
|
||||
await act(() => {
|
||||
|
|
|
|||
|
|
@ -528,10 +528,7 @@ describe('ReactTypeScriptClass', function () {
|
|||
' in ProvideChildContextTypes (at **)',
|
||||
'StateBasedOnContext uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(ReactFeatureFlags.enableOwnerStacks
|
||||
? ' in ProvideChildContextTypes.createElement (at **)'
|
||||
: ' in StateBasedOnContext (at **)\n') +
|
||||
' in ProvideChildContextTypes (at **)',
|
||||
' in ProvideChildContextTypes.createElement (at **)',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
|
@ -724,10 +721,7 @@ describe('ReactTypeScriptClass', function () {
|
|||
' in ProvideContext (at **)',
|
||||
'ReadContext uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
(ReactFeatureFlags.enableOwnerStacks
|
||||
? ' in ProvideContext.createElement (at **)'
|
||||
: ' in ReadContext (at **)\n') +
|
||||
' in ProvideContext (at **)',
|
||||
' in ProvideContext.createElement (at **)',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -348,14 +348,10 @@ describe('create-react-class-integration', () => {
|
|||
root.render(<Outer />);
|
||||
});
|
||||
assertConsoleErrorDev([
|
||||
gate(flags =>
|
||||
flags.enableOwnerStacks
|
||||
? [
|
||||
'Component uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',
|
||||
{withoutStack: true},
|
||||
]
|
||||
: 'Component uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',
|
||||
),
|
||||
[
|
||||
'Component uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'Component uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.',
|
||||
]);
|
||||
expect(container.firstChild.className).toBe('foo');
|
||||
|
|
|
|||
|
|
@ -213,9 +213,7 @@ describe('forwardRef', () => {
|
|||
'\n\nCheck the top-level render call using <ForwardRef>. It was passed a child from ForwardRef. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in span (at **)\n' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ' in **/forwardRef-test.js:**:** (at **)'
|
||||
: ' in p (at **)'),
|
||||
' in **/forwardRef-test.js:**:** (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -235,8 +233,7 @@ describe('forwardRef', () => {
|
|||
'\n\nCheck the top-level render call using <ForwardRef(Inner)>. It was passed a child from ForwardRef(Inner). ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in span (at **)\n' +
|
||||
' in Inner (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
||||
' in Inner (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -257,8 +254,7 @@ describe('forwardRef', () => {
|
|||
'\n\nCheck the top-level render call using <ForwardRef(Inner)>. It was passed a child from ForwardRef(Inner). ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in span (at **)\n' +
|
||||
' in Inner (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
||||
' in Inner (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -278,8 +274,7 @@ describe('forwardRef', () => {
|
|||
'\n\nCheck the top-level render call using <Outer>. It was passed a child from Outer. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in span (at **)\n' +
|
||||
' in Outer (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
||||
' in Outer (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -301,8 +296,7 @@ describe('forwardRef', () => {
|
|||
'\n\nCheck the top-level render call using <Outer>. It was passed a child from Outer. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in span (at **)\n' +
|
||||
' in Inner (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
||||
' in Inner (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -10,25 +10,17 @@ import ReactSharedInternals from 'shared/ReactSharedInternals';
|
|||
import hasOwnProperty from 'shared/hasOwnProperty';
|
||||
import assign from 'shared/assign';
|
||||
import {
|
||||
getIteratorFn,
|
||||
REACT_ELEMENT_TYPE,
|
||||
REACT_FRAGMENT_TYPE,
|
||||
REACT_LAZY_TYPE,
|
||||
} from 'shared/ReactSymbols';
|
||||
import {checkKeyStringCoercion} from 'shared/CheckStringCoercion';
|
||||
import isValidElementType from 'shared/isValidElementType';
|
||||
import isArray from 'shared/isArray';
|
||||
import {describeUnknownElementTypeFrameInDEV} from 'shared/ReactComponentStackFrame';
|
||||
import {
|
||||
disableDefaultPropsExceptForClasses,
|
||||
enableOwnerStacks,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
|
||||
const REACT_CLIENT_REFERENCE = Symbol.for('react.client.reference');
|
||||
import {disableDefaultPropsExceptForClasses} from 'shared/ReactFeatureFlags';
|
||||
|
||||
const createTask =
|
||||
// eslint-disable-next-line react-internal/no-production-logging
|
||||
__DEV__ && enableOwnerStacks && console.createTask
|
||||
__DEV__ && console.createTask
|
||||
? // eslint-disable-next-line react-internal/no-production-logging
|
||||
console.createTask
|
||||
: () => null;
|
||||
|
|
@ -261,20 +253,18 @@ function ReactElement(
|
|||
writable: true,
|
||||
value: null,
|
||||
});
|
||||
if (enableOwnerStacks) {
|
||||
Object.defineProperty(element, '_debugStack', {
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: debugStack,
|
||||
});
|
||||
Object.defineProperty(element, '_debugTask', {
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: debugTask,
|
||||
});
|
||||
}
|
||||
Object.defineProperty(element, '_debugStack', {
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: debugStack,
|
||||
});
|
||||
Object.defineProperty(element, '_debugTask', {
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: debugTask,
|
||||
});
|
||||
if (Object.freeze) {
|
||||
Object.freeze(element.props);
|
||||
Object.freeze(element);
|
||||
|
|
@ -390,8 +380,8 @@ export function jsxProdSignatureRunningInDevWithDynamicChildren(
|
|||
isStaticChildren,
|
||||
source,
|
||||
self,
|
||||
__DEV__ && enableOwnerStacks ? Error('react-stack-top-frame') : undefined,
|
||||
__DEV__ && enableOwnerStacks ? createTask(getTaskName(type)) : undefined,
|
||||
__DEV__ && Error('react-stack-top-frame'),
|
||||
__DEV__ && createTask(getTaskName(type)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -412,8 +402,8 @@ export function jsxProdSignatureRunningInDevWithStaticChildren(
|
|||
isStaticChildren,
|
||||
source,
|
||||
self,
|
||||
__DEV__ && enableOwnerStacks ? Error('react-stack-top-frame') : undefined,
|
||||
__DEV__ && enableOwnerStacks ? createTask(getTaskName(type)) : undefined,
|
||||
__DEV__ && Error('react-stack-top-frame'),
|
||||
__DEV__ && createTask(getTaskName(type)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -434,8 +424,8 @@ export function jsxDEV(type, config, maybeKey, isStaticChildren, source, self) {
|
|||
isStaticChildren,
|
||||
source,
|
||||
self,
|
||||
__DEV__ && enableOwnerStacks ? Error('react-stack-top-frame') : undefined,
|
||||
__DEV__ && enableOwnerStacks ? createTask(getTaskName(type)) : undefined,
|
||||
__DEV__ && Error('react-stack-top-frame'),
|
||||
__DEV__ && createTask(getTaskName(type)),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -450,80 +440,37 @@ function jsxDEVImpl(
|
|||
debugTask,
|
||||
) {
|
||||
if (__DEV__) {
|
||||
if (!enableOwnerStacks && !isValidElementType(type)) {
|
||||
// This is an invalid element type.
|
||||
//
|
||||
// We warn here so that we can get better stack traces but with enableOwnerStacks
|
||||
// enabled we don't need this because we get good stacks if we error in the
|
||||
// renderer anyway. The renderer is the only one that knows what types are valid
|
||||
// for this particular renderer so we let it error there instead.
|
||||
//
|
||||
// We warn in this case but don't throw. We expect the element creation to
|
||||
// succeed and there will likely be errors in render.
|
||||
let info = '';
|
||||
if (
|
||||
type === undefined ||
|
||||
(typeof type === 'object' &&
|
||||
type !== null &&
|
||||
Object.keys(type).length === 0)
|
||||
) {
|
||||
info +=
|
||||
' You likely forgot to export your component from the file ' +
|
||||
"it's defined in, or you might have mixed up default and named imports.";
|
||||
}
|
||||
// We don't warn for invalid element type here because with owner stacks,
|
||||
// we error in the renderer. The renderer is the only one that knows what
|
||||
// types are valid for this particular renderer so we let it error there.
|
||||
|
||||
let typeString;
|
||||
if (type === null) {
|
||||
typeString = 'null';
|
||||
} else if (isArray(type)) {
|
||||
typeString = 'array';
|
||||
} else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
|
||||
typeString = `<${getComponentNameFromType(type.type) || 'Unknown'} />`;
|
||||
info =
|
||||
' Did you accidentally export a JSX literal instead of a component?';
|
||||
} else {
|
||||
typeString = typeof type;
|
||||
}
|
||||
// Skip key warning if the type isn't valid since our key validation logic
|
||||
// doesn't expect a non-string/function type and can throw confusing
|
||||
// errors. We don't want exception behavior to differ between dev and
|
||||
// prod. (Rendering will throw with a helpful message and as soon as the
|
||||
// type is fixed, the key warnings will appear.)
|
||||
// With owner stacks, we no longer need the type here so this comment is
|
||||
// no longer true. Which is why we can run this even for invalid types.
|
||||
const children = config.children;
|
||||
if (children !== undefined) {
|
||||
if (isStaticChildren) {
|
||||
if (isArray(children)) {
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
validateChildKeys(children[i], type);
|
||||
}
|
||||
|
||||
console.error(
|
||||
'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,
|
||||
);
|
||||
} else {
|
||||
// This is a valid element type.
|
||||
|
||||
// Skip key warning if the type isn't valid since our key validation logic
|
||||
// doesn't expect a non-string/function type and can throw confusing
|
||||
// errors. We don't want exception behavior to differ between dev and
|
||||
// prod. (Rendering will throw with a helpful message and as soon as the
|
||||
// type is fixed, the key warnings will appear.)
|
||||
// When enableOwnerStacks is on, we no longer need the type here so this
|
||||
// comment is no longer true. Which is why we can run this even for invalid
|
||||
// types.
|
||||
const children = config.children;
|
||||
if (children !== undefined) {
|
||||
if (isStaticChildren) {
|
||||
if (isArray(children)) {
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
validateChildKeys(children[i], type);
|
||||
}
|
||||
|
||||
if (Object.freeze) {
|
||||
Object.freeze(children);
|
||||
}
|
||||
} else {
|
||||
console.error(
|
||||
'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 (Object.freeze) {
|
||||
Object.freeze(children);
|
||||
}
|
||||
} else {
|
||||
validateChildKeys(children, type);
|
||||
console.error(
|
||||
'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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -640,59 +587,17 @@ function jsxDEVImpl(
|
|||
*/
|
||||
export function createElement(type, config, children) {
|
||||
if (__DEV__) {
|
||||
if (!enableOwnerStacks && !isValidElementType(type)) {
|
||||
// This is just an optimistic check that provides a better stack trace before
|
||||
// owner stacks. It's really up to the renderer if it's a valid element type.
|
||||
// When owner stacks are enabled, we instead warn in the renderer and it'll
|
||||
// have the stack trace of the JSX element anyway.
|
||||
//
|
||||
// This is an invalid element type.
|
||||
//
|
||||
// We warn in this case but don't throw. We expect the element creation to
|
||||
// succeed and there will likely be errors in render.
|
||||
let info = '';
|
||||
if (
|
||||
type === undefined ||
|
||||
(typeof type === 'object' &&
|
||||
type !== null &&
|
||||
Object.keys(type).length === 0)
|
||||
) {
|
||||
info +=
|
||||
' You likely forgot to export your component from the file ' +
|
||||
"it's defined in, or you might have mixed up default and named imports.";
|
||||
}
|
||||
// We don't warn for invalid element type here because with owner stacks,
|
||||
// we error in the renderer. The renderer is the only one that knows what
|
||||
// types are valid for this particular renderer so we let it error there.
|
||||
|
||||
let typeString;
|
||||
if (type === null) {
|
||||
typeString = 'null';
|
||||
} else if (isArray(type)) {
|
||||
typeString = 'array';
|
||||
} else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
|
||||
typeString = `<${getComponentNameFromType(type.type) || 'Unknown'} />`;
|
||||
info =
|
||||
' Did you accidentally export a JSX literal instead of a component?';
|
||||
} else {
|
||||
typeString = typeof type;
|
||||
}
|
||||
|
||||
console.error(
|
||||
'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,
|
||||
);
|
||||
} else {
|
||||
// This is a valid element type.
|
||||
|
||||
// Skip key warning if the type isn't valid since our key validation logic
|
||||
// doesn't expect a non-string/function type and can throw confusing
|
||||
// errors. We don't want exception behavior to differ between dev and
|
||||
// prod. (Rendering will throw with a helpful message and as soon as the
|
||||
// type is fixed, the key warnings will appear.)
|
||||
for (let i = 2; i < arguments.length; i++) {
|
||||
validateChildKeys(arguments[i], type);
|
||||
}
|
||||
// Skip key warning if the type isn't valid since our key validation logic
|
||||
// doesn't expect a non-string/function type and can throw confusing
|
||||
// errors. We don't want exception behavior to differ between dev and
|
||||
// prod. (Rendering will throw with a helpful message and as soon as the
|
||||
// type is fixed, the key warnings will appear.)
|
||||
for (let i = 2; i < arguments.length; i++) {
|
||||
validateChildKeys(arguments[i], type);
|
||||
}
|
||||
|
||||
// Unlike the jsx() runtime, createElement() doesn't warn about key spread.
|
||||
|
|
@ -795,8 +700,8 @@ export function createElement(type, config, children) {
|
|||
undefined,
|
||||
getOwner(),
|
||||
props,
|
||||
__DEV__ && enableOwnerStacks ? Error('react-stack-top-frame') : undefined,
|
||||
__DEV__ && enableOwnerStacks ? createTask(getTaskName(type)) : undefined,
|
||||
__DEV__ && Error('react-stack-top-frame'),
|
||||
__DEV__ && createTask(getTaskName(type)),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -808,8 +713,8 @@ export function cloneAndReplaceKey(oldElement, newKey) {
|
|||
undefined,
|
||||
!__DEV__ ? undefined : oldElement._owner,
|
||||
oldElement.props,
|
||||
__DEV__ && enableOwnerStacks ? oldElement._debugStack : undefined,
|
||||
__DEV__ && enableOwnerStacks ? oldElement._debugTask : undefined,
|
||||
__DEV__ && oldElement._debugStack,
|
||||
__DEV__ && oldElement._debugTask,
|
||||
);
|
||||
if (__DEV__) {
|
||||
// The cloned element should inherit the original element's key validation.
|
||||
|
|
@ -914,8 +819,8 @@ export function cloneElement(element, config, children) {
|
|||
undefined,
|
||||
owner,
|
||||
props,
|
||||
__DEV__ && enableOwnerStacks ? element._debugStack : undefined,
|
||||
__DEV__ && enableOwnerStacks ? element._debugTask : undefined,
|
||||
__DEV__ && element._debugStack,
|
||||
__DEV__ && element._debugTask,
|
||||
);
|
||||
|
||||
for (let i = 2; i < arguments.length; i++) {
|
||||
|
|
@ -936,51 +841,13 @@ export function cloneElement(element, config, children) {
|
|||
*/
|
||||
function validateChildKeys(node, parentType) {
|
||||
if (__DEV__) {
|
||||
if (enableOwnerStacks) {
|
||||
// When owner stacks is enabled no warnings happens. All we do is
|
||||
// mark elements as being in a valid static child position so they
|
||||
// don't need keys.
|
||||
if (isValidElement(node)) {
|
||||
if (node._store) {
|
||||
node._store.validated = 1;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (typeof node !== 'object' || !node) {
|
||||
return;
|
||||
}
|
||||
if (node.$$typeof === REACT_CLIENT_REFERENCE) {
|
||||
// This is a reference to a client component so it's unknown.
|
||||
} else if (isArray(node)) {
|
||||
for (let i = 0; i < node.length; i++) {
|
||||
const child = node[i];
|
||||
if (isValidElement(child)) {
|
||||
validateExplicitKey(child, parentType);
|
||||
}
|
||||
}
|
||||
} else if (isValidElement(node)) {
|
||||
// This element was passed in a valid location.
|
||||
// With owner stacks is, no warnings happens. All we do is
|
||||
// mark elements as being in a valid static child position so they
|
||||
// don't need keys.
|
||||
if (isValidElement(node)) {
|
||||
if (node._store) {
|
||||
node._store.validated = 1;
|
||||
}
|
||||
} else {
|
||||
const iteratorFn = getIteratorFn(node);
|
||||
if (typeof iteratorFn === 'function') {
|
||||
// Entry iterators used to provide implicit keys,
|
||||
// but now we print a separate warning for them later.
|
||||
if (iteratorFn !== node.entries) {
|
||||
const iterator = iteratorFn.call(node);
|
||||
if (iterator !== node) {
|
||||
let step;
|
||||
while (!(step = iterator.next()).done) {
|
||||
if (isValidElement(step.value)) {
|
||||
validateExplicitKey(step.value, parentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -999,92 +866,3 @@ export function isValidElement(object) {
|
|||
object.$$typeof === REACT_ELEMENT_TYPE
|
||||
);
|
||||
}
|
||||
|
||||
const ownerHasKeyUseWarning = {};
|
||||
|
||||
/**
|
||||
* Warn if the element doesn't have an explicit key assigned to it.
|
||||
* This element is in an array. The array could grow and shrink or be
|
||||
* reordered. All children that haven't already been validated are required to
|
||||
* have a "key" property assigned to it. Error statuses are cached so a warning
|
||||
* will only be shown once.
|
||||
*
|
||||
* @internal
|
||||
* @param {ReactElement} element Element that requires a key.
|
||||
* @param {*} parentType element's parent's type.
|
||||
*/
|
||||
function validateExplicitKey(element, parentType) {
|
||||
if (enableOwnerStacks) {
|
||||
// Skip. Will verify in renderer instead.
|
||||
return;
|
||||
}
|
||||
if (__DEV__) {
|
||||
if (!element._store || element._store.validated || element.key != null) {
|
||||
return;
|
||||
}
|
||||
element._store.validated = 1;
|
||||
|
||||
const currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);
|
||||
if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {
|
||||
return;
|
||||
}
|
||||
ownerHasKeyUseWarning[currentComponentErrorInfo] = true;
|
||||
|
||||
// Usually the current owner is the offender, but if it accepts children as a
|
||||
// property, it may be the creator of the child that's responsible for
|
||||
// assigning it a key.
|
||||
let childOwner = '';
|
||||
if (element && element._owner != null && element._owner !== getOwner()) {
|
||||
let ownerName = null;
|
||||
if (typeof element._owner.tag === 'number') {
|
||||
ownerName = getComponentNameFromType(element._owner.type);
|
||||
} else if (typeof element._owner.name === 'string') {
|
||||
ownerName = element._owner.name;
|
||||
}
|
||||
// Give the component that originally created this child.
|
||||
childOwner = ` It was passed a child from ${ownerName}.`;
|
||||
}
|
||||
|
||||
const prevGetCurrentStack = ReactSharedInternals.getCurrentStack;
|
||||
ReactSharedInternals.getCurrentStack = function () {
|
||||
const owner = element._owner;
|
||||
// Add an extra top frame while an element is being validated
|
||||
let stack = describeUnknownElementTypeFrameInDEV(
|
||||
element.type,
|
||||
owner ? owner.type : null,
|
||||
);
|
||||
// Delegate to the injected renderer-specific implementation
|
||||
if (prevGetCurrentStack) {
|
||||
stack += prevGetCurrentStack() || '';
|
||||
}
|
||||
return stack;
|
||||
};
|
||||
console.error(
|
||||
'Each child in a list should have a unique "key" prop.' +
|
||||
'%s%s See https://react.dev/link/warning-keys for more information.',
|
||||
currentComponentErrorInfo,
|
||||
childOwner,
|
||||
);
|
||||
ReactSharedInternals.getCurrentStack = prevGetCurrentStack;
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentComponentErrorInfo(parentType) {
|
||||
if (__DEV__) {
|
||||
let info = '';
|
||||
const owner = getOwner();
|
||||
if (owner) {
|
||||
const name = getComponentNameFromType(owner.type);
|
||||
if (name) {
|
||||
info = '\n\nCheck the render method of `' + name + '`.';
|
||||
}
|
||||
}
|
||||
if (!info) {
|
||||
const parentName = getComponentNameFromType(parentType);
|
||||
if (parentName) {
|
||||
info = `\n\nCheck the top-level render call using <${parentName}>.`;
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,14 +11,12 @@ import type {ReactComponentInfo} from 'shared/ReactTypes';
|
|||
|
||||
import {describeBuiltInComponentFrame} from 'shared/ReactComponentStackFrame';
|
||||
|
||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
||||
|
||||
import {formatOwnerStack} from 'shared/ReactOwnerStackFrames';
|
||||
|
||||
export function getOwnerStackByComponentInfoInDev(
|
||||
componentInfo: ReactComponentInfo,
|
||||
): string {
|
||||
if (!enableOwnerStacks || !__DEV__) {
|
||||
if (!__DEV__) {
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -7,25 +7,12 @@
|
|||
* @flow
|
||||
*/
|
||||
|
||||
import type {LazyComponent} from 'react/src/ReactLazy';
|
||||
|
||||
import {
|
||||
REACT_SUSPENSE_TYPE,
|
||||
REACT_SUSPENSE_LIST_TYPE,
|
||||
REACT_FORWARD_REF_TYPE,
|
||||
REACT_MEMO_TYPE,
|
||||
REACT_LAZY_TYPE,
|
||||
REACT_VIEW_TRANSITION_TYPE,
|
||||
} from 'shared/ReactSymbols';
|
||||
|
||||
import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev';
|
||||
|
||||
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
||||
|
||||
import DefaultPrepareStackTrace from 'shared/DefaultPrepareStackTrace';
|
||||
|
||||
import {enableViewTransition} from 'shared/ReactFeatureFlags';
|
||||
|
||||
let prefix;
|
||||
let suffix;
|
||||
export function describeBuiltInComponentFrame(name: string): string {
|
||||
|
|
@ -300,53 +287,3 @@ export function describeClassComponentFrame(ctor: Function): string {
|
|||
export function describeFunctionComponentFrame(fn: Function): string {
|
||||
return describeNativeComponentFrame(fn, false);
|
||||
}
|
||||
|
||||
function shouldConstruct(Component: Function) {
|
||||
const prototype = Component.prototype;
|
||||
return !!(prototype && prototype.isReactComponent);
|
||||
}
|
||||
|
||||
// TODO: Delete this once the key warning no longer uses it. I.e. when enableOwnerStacks ship.
|
||||
export function describeUnknownElementTypeFrameInDEV(type: any): string {
|
||||
if (!__DEV__) {
|
||||
return '';
|
||||
}
|
||||
if (type == null) {
|
||||
return '';
|
||||
}
|
||||
if (typeof type === 'function') {
|
||||
return describeNativeComponentFrame(type, shouldConstruct(type));
|
||||
}
|
||||
if (typeof type === 'string') {
|
||||
return describeBuiltInComponentFrame(type);
|
||||
}
|
||||
switch (type) {
|
||||
case REACT_SUSPENSE_TYPE:
|
||||
return describeBuiltInComponentFrame('Suspense');
|
||||
case REACT_SUSPENSE_LIST_TYPE:
|
||||
return describeBuiltInComponentFrame('SuspenseList');
|
||||
case REACT_VIEW_TRANSITION_TYPE:
|
||||
if (enableViewTransition) {
|
||||
return describeBuiltInComponentFrame('ViewTransition');
|
||||
}
|
||||
}
|
||||
if (typeof type === 'object') {
|
||||
switch (type.$$typeof) {
|
||||
case REACT_FORWARD_REF_TYPE:
|
||||
return describeFunctionComponentFrame(type.render);
|
||||
case REACT_MEMO_TYPE:
|
||||
// Memo may contain any component type so we recursively resolve it.
|
||||
return describeUnknownElementTypeFrameInDEV(type.type);
|
||||
case REACT_LAZY_TYPE: {
|
||||
const lazyComponent: LazyComponent<any, any> = (type: any);
|
||||
const payload = lazyComponent._payload;
|
||||
const init = lazyComponent._init;
|
||||
try {
|
||||
// Lazy may contain any component type so we recursively resolve it.
|
||||
return describeUnknownElementTypeFrameInDEV(init(payload));
|
||||
} catch (x) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,8 +136,6 @@ export const passChildrenWhenCloningPersistedNodes = false;
|
|||
*/
|
||||
export const enablePersistedModeClonedFlag = false;
|
||||
|
||||
export const enableOwnerStacks = true;
|
||||
|
||||
export const enableShallowPropDiffing = false;
|
||||
|
||||
export const enableSiblingPrerendering = true;
|
||||
|
|
|
|||
|
|
@ -32,9 +32,6 @@ export const {
|
|||
enableLazyPublicInstanceInFabric,
|
||||
} = dynamicFlags;
|
||||
|
||||
// These two can be removed
|
||||
export const enableOwnerStacks = true;
|
||||
|
||||
// The rest of the flags are static for better dead code elimination.
|
||||
export const disableClientCache = true;
|
||||
export const disableCommentsAsDOMContainers = true;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ export const enableLegacyFBSupport = false;
|
|||
export const enableLegacyHidden = false;
|
||||
export const enableNoCloningMemoCache = false;
|
||||
export const enableObjectFiber = false;
|
||||
export const enableOwnerStacks = true;
|
||||
export const enablePersistedModeClonedFlag = false;
|
||||
export const enablePostpone = false;
|
||||
export const enableReactTestRendererWarning = false;
|
||||
|
|
|
|||
|
|
@ -91,7 +91,6 @@ export const enableReactTestRendererWarning = true;
|
|||
export const disableDefaultPropsExceptForClasses = true;
|
||||
|
||||
export const enableObjectFiber = false;
|
||||
export const enableOwnerStacks = true;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ export const enableLegacyFBSupport = false;
|
|||
export const enableLegacyHidden = false;
|
||||
export const enableNoCloningMemoCache = false;
|
||||
export const enableObjectFiber = false;
|
||||
export const enableOwnerStacks = true;
|
||||
export const enablePersistedModeClonedFlag = false;
|
||||
export const enablePostpone = false;
|
||||
export const enableProfilerCommitHooks = __PROFILE__;
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@ export const disableDefaultPropsExceptForClasses = true;
|
|||
export const renameElementSymbol = false;
|
||||
|
||||
export const enableObjectFiber = false;
|
||||
export const enableOwnerStacks = true;
|
||||
export const enableShallowPropDiffing = false;
|
||||
export const enableSiblingPrerendering = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,9 +43,6 @@ export const {
|
|||
// On WWW, __EXPERIMENTAL__ is used for a new modern build.
|
||||
// It's not used anywhere in production yet.
|
||||
|
||||
// Can remove these two
|
||||
export const enableOwnerStacks = true;
|
||||
|
||||
export const enableProfilerTimer = __PROFILE__;
|
||||
export const enableProfilerCommitHooks = __PROFILE__;
|
||||
export const enableProfilerNestedUpdatePhase = __PROFILE__;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ import {
|
|||
const REACT_CLIENT_REFERENCE: symbol = Symbol.for('react.client.reference');
|
||||
|
||||
// This function is deprecated. Don't use. Only the renderer knows what a valid type is.
|
||||
// TODO: Delete this when enableOwnerStacks ships.
|
||||
// TODO: Delete this now that owner stacks shipped.
|
||||
export default function isValidElementType(type: mixed): boolean {
|
||||
if (typeof type === 'string' || typeof type === 'function') {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ jest.mock('shared/ReactFeatureFlags', () => {
|
|||
// Flags that aren't currently used, but we still want to force variants to keep the
|
||||
// code live.
|
||||
actual.disableInputAttributeSyncing = __VARIANT__;
|
||||
actual.enableOwnerStacks = __VARIANT__;
|
||||
|
||||
// These are hardcoded to true for the next release,
|
||||
// but still run the tests against both variants until
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ jest.mock('shared/ReactFeatureFlags', () => {
|
|||
'shared/forks/ReactFeatureFlags.native-fb.js'
|
||||
);
|
||||
|
||||
actual.enableOwnerStacks = __VARIANT__;
|
||||
|
||||
// Lots of tests use these, but we don't want to expose it to RN.
|
||||
// Ideally, tests for xplat wouldn't use react-dom, but many of our tests do.
|
||||
// Since the xplat tests run with the www entry points, some of these flags
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user