mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +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."
|
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 {
|
} else {
|
||||||
expect(message).toMatchInlineSnapshot(`
|
expect(message).toMatchInlineSnapshot(`
|
||||||
"asserConsoleLogsCleared(expected)
|
"asserConsoleLogsCleared(expected)
|
||||||
|
|
@ -937,20 +926,6 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||||
+ B
|
+ B
|
||||||
+ C
|
+ 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."
|
You must call one of the assertConsoleDev helpers between each act call."
|
||||||
`);
|
`);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -959,16 +934,10 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||||
|
|
||||||
console.warn was called without assertConsoleWarnDev:
|
console.warn was called without assertConsoleWarnDev:
|
||||||
+ A%s,
|
+ A%s,
|
||||||
+ in Yield (at **)
|
|
||||||
+ in div (at **)
|
|
||||||
+ in App (at **)
|
+ in App (at **)
|
||||||
+ B%s,
|
+ B%s,
|
||||||
+ in Yield (at **)
|
|
||||||
+ in div (at **)
|
|
||||||
+ in App (at **)
|
+ in App (at **)
|
||||||
+ C%s,
|
+ C%s,
|
||||||
+ in Yield (at **)
|
|
||||||
+ in div (at **)
|
|
||||||
+ in App (at **)
|
+ in App (at **)
|
||||||
|
|
||||||
You must call one of the assertConsoleDev helpers between each act call."
|
You must call one of the assertConsoleDev helpers between each act call."
|
||||||
|
|
@ -1023,33 +992,6 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||||
+ B
|
+ B
|
||||||
+ C
|
+ 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."
|
You must call one of the assertConsoleDev helpers between each act call."
|
||||||
`);
|
`);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1063,30 +1005,18 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||||
|
|
||||||
console.warn was called without assertConsoleWarnDev:
|
console.warn was called without assertConsoleWarnDev:
|
||||||
+ A%s,
|
+ A%s,
|
||||||
+ in Yield (at **)
|
|
||||||
+ in div (at **)
|
|
||||||
+ in App (at **)
|
+ in App (at **)
|
||||||
+ B%s,
|
+ B%s,
|
||||||
+ in Yield (at **)
|
|
||||||
+ in div (at **)
|
|
||||||
+ in App (at **)
|
+ in App (at **)
|
||||||
+ C%s,
|
+ C%s,
|
||||||
+ in Yield (at **)
|
|
||||||
+ in div (at **)
|
|
||||||
+ in App (at **)
|
+ in App (at **)
|
||||||
|
|
||||||
console.error was called without assertConsoleErrorDev:
|
console.error was called without assertConsoleErrorDev:
|
||||||
+ A%s,
|
+ A%s,
|
||||||
+ in Yield (at **)
|
|
||||||
+ in div (at **)
|
|
||||||
+ in App (at **)
|
+ in App (at **)
|
||||||
+ B%s,
|
+ B%s,
|
||||||
+ in Yield (at **)
|
|
||||||
+ in div (at **)
|
|
||||||
+ in App (at **)
|
+ in App (at **)
|
||||||
+ C%s,
|
+ C%s,
|
||||||
+ in Yield (at **)
|
|
||||||
+ in div (at **)
|
|
||||||
+ in App (at **)
|
+ in App (at **)
|
||||||
|
|
||||||
You must call one of the assertConsoleDev helpers between each act call."
|
You must call one of the assertConsoleDev helpers between each act call."
|
||||||
|
|
@ -1927,20 +1857,6 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||||
+ Not asserted
|
+ Not asserted
|
||||||
+ 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."
|
You must call one of the assertConsoleDev helpers between each act call."
|
||||||
`);
|
`);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1950,13 +1866,10 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||||
console.warn was called without assertConsoleWarnDev:
|
console.warn was called without assertConsoleWarnDev:
|
||||||
+ Not asserted%s,
|
+ Not asserted%s,
|
||||||
+ in Yield (at **)
|
+ in Yield (at **)
|
||||||
+ in div (at **)
|
|
||||||
+ Not asserted%s,
|
+ Not asserted%s,
|
||||||
+ in Yield (at **)
|
+ in Yield (at **)
|
||||||
+ in div (at **)
|
|
||||||
+ Not asserted%s,
|
+ Not asserted%s,
|
||||||
+ in Yield (at **)
|
+ in Yield (at **)
|
||||||
+ in div (at **)
|
|
||||||
|
|
||||||
You must call one of the assertConsoleDev helpers between each act call."
|
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."
|
You must call one of the assertConsoleDev helpers between each act call."
|
||||||
`);
|
`);
|
||||||
} else if (gate(flags => flags.enableOwnerStacks)) {
|
} else {
|
||||||
expect(message).toMatchInlineSnapshot(`
|
expect(message).toMatchInlineSnapshot(`
|
||||||
"asserConsoleLogsCleared(expected)
|
"asserConsoleLogsCleared(expected)
|
||||||
|
|
||||||
|
|
@ -2034,26 +1947,6 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||||
|
|
||||||
You must call one of the assertConsoleDev helpers between each act call."
|
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."
|
You must call one of the assertConsoleDev helpers between each act call."
|
||||||
`);
|
`);
|
||||||
} else if (gate(flags => flags.enableOwnerStacks)) {
|
} else {
|
||||||
expect(message).toMatchInlineSnapshot(`
|
expect(message).toMatchInlineSnapshot(`
|
||||||
"asserConsoleLogsCleared(expected)
|
"asserConsoleLogsCleared(expected)
|
||||||
|
|
||||||
|
|
@ -2133,45 +2026,6 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||||
|
|
||||||
You must call one of the assertConsoleDev helpers between each act call."
|
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
|
||||||
+ 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."
|
You must call one of the assertConsoleDev helpers between each act call."
|
||||||
`);
|
`);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -3075,13 +2915,10 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||||
console.error was called without assertConsoleErrorDev:
|
console.error was called without assertConsoleErrorDev:
|
||||||
+ Not asserted%s,
|
+ Not asserted%s,
|
||||||
+ in Yield (at **)
|
+ in Yield (at **)
|
||||||
+ in div (at **)
|
|
||||||
+ Not asserted%s,
|
+ Not asserted%s,
|
||||||
+ in Yield (at **)
|
+ in Yield (at **)
|
||||||
+ in div (at **)
|
|
||||||
+ Not asserted%s,
|
+ Not asserted%s,
|
||||||
+ in Yield (at **)
|
+ in Yield (at **)
|
||||||
+ in div (at **)
|
|
||||||
|
|
||||||
You must call one of the assertConsoleDev helpers between each act call."
|
You must call one of the assertConsoleDev helpers between each act call."
|
||||||
`);
|
`);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* eslint-disable react-internal/no-production-logging */
|
/* eslint-disable react-internal/no-production-logging */
|
||||||
|
|
||||||
const chalk = require('chalk');
|
const chalk = require('chalk');
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
const shouldIgnoreConsoleError = require('./shouldIgnoreConsoleError');
|
const shouldIgnoreConsoleError = require('./shouldIgnoreConsoleError');
|
||||||
|
|
@ -38,25 +39,16 @@ const patchConsoleMethod = (methodName, logged) => {
|
||||||
(methodName === 'error' || methodName === 'warn')
|
(methodName === 'error' || methodName === 'warn')
|
||||||
) {
|
) {
|
||||||
const React = require('react');
|
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) {
|
if (React.captureOwnerStack) {
|
||||||
// enableOwnerStacks enabled. When it's always on, we can assume this case.
|
|
||||||
const stack = React.captureOwnerStack();
|
const stack = React.captureOwnerStack();
|
||||||
if (stack) {
|
if (stack) {
|
||||||
format += '%s';
|
format += '%s';
|
||||||
args.push(stack);
|
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" +
|
"boolean, but instead received: [ 'Hi', 100 ]\n\n" +
|
||||||
'To use non-primitive values as keys, you must pass a hash ' +
|
'To use non-primitive values as keys, you must pass a hash ' +
|
||||||
'function as the second argument to createResource().\n' +
|
'function as the second argument to createResource().\n' +
|
||||||
' in App (at **)' +
|
' in App (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: '\n in Suspense (at **)'),
|
|
||||||
|
|
||||||
...(gate('enableSiblingPrerendering')
|
...(gate('enableSiblingPrerendering')
|
||||||
? [
|
? [
|
||||||
'Invalid key type. Expected a string, number, symbol, or ' +
|
'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 {
|
import {
|
||||||
enablePostpone,
|
enablePostpone,
|
||||||
enableOwnerStacks,
|
|
||||||
enableProfilerTimer,
|
enableProfilerTimer,
|
||||||
enableComponentPerformanceTrack,
|
enableComponentPerformanceTrack,
|
||||||
} from 'shared/ReactFeatureFlags';
|
} from 'shared/ReactFeatureFlags';
|
||||||
|
|
@ -755,7 +754,7 @@ function createElement(
|
||||||
configurable: false,
|
configurable: false,
|
||||||
enumerable: false,
|
enumerable: false,
|
||||||
writable: true,
|
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.
|
// debugInfo contains Server Component debug information.
|
||||||
Object.defineProperty(element, '_debugInfo', {
|
Object.defineProperty(element, '_debugInfo', {
|
||||||
|
|
@ -765,79 +764,68 @@ function createElement(
|
||||||
value: null,
|
value: null,
|
||||||
});
|
});
|
||||||
let env = response._rootEnvironmentName;
|
let env = response._rootEnvironmentName;
|
||||||
if (enableOwnerStacks) {
|
if (owner !== null && owner.env != null) {
|
||||||
if (owner !== null && owner.env != null) {
|
// Interestingly we don't actually have the environment name of where
|
||||||
// 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
|
||||||
// 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
|
||||||
// it must be the same environment as the owner. We could send it separately
|
// but it seems a bit unnecessary for this edge case.
|
||||||
// but it seems a bit unnecessary for this edge case.
|
env = owner.env;
|
||||||
env = owner.env;
|
}
|
||||||
}
|
let normalizedStackTrace: null | Error = null;
|
||||||
let normalizedStackTrace: null | Error = null;
|
if (owner === null && response._debugRootStack != null) {
|
||||||
if (owner === null && response._debugRootStack != null) {
|
// We override the stack if we override the owner since the stack where the root JSX
|
||||||
// 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.
|
||||||
// was created on the server isn't very useful but where the request was made is.
|
normalizedStackTrace = response._debugRootStack;
|
||||||
normalizedStackTrace = response._debugRootStack;
|
} else if (stack !== null) {
|
||||||
} else if (stack !== null) {
|
// We create a fake stack and then create an Error object inside of it.
|
||||||
// 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
|
||||||
// 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
|
||||||
// of the browser and the stack frames will have been registered with
|
// source mapping information.
|
||||||
// source mapping information.
|
// This can unfortunately happen within a user space callstack which will
|
||||||
// This can unfortunately happen within a user space callstack which will
|
// remain on the stack.
|
||||||
// remain on the stack.
|
normalizedStackTrace = createFakeJSXCallStackInDEV(response, stack, env);
|
||||||
normalizedStackTrace = createFakeJSXCallStackInDEV(
|
}
|
||||||
response,
|
Object.defineProperty(element, '_debugStack', {
|
||||||
stack,
|
configurable: false,
|
||||||
env,
|
enumerable: false,
|
||||||
);
|
writable: true,
|
||||||
}
|
value: normalizedStackTrace,
|
||||||
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,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
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
|
// This owner should ideally have already been initialized to avoid getting
|
||||||
// user stack frames on the stack.
|
// user stack frames on the stack.
|
||||||
if (owner !== null) {
|
const ownerTask =
|
||||||
initializeFakeStack(response, owner);
|
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) {
|
if (initializingHandler !== null) {
|
||||||
|
|
@ -863,13 +851,11 @@ function createElement(
|
||||||
name: getComponentNameFromType(element.type) || '',
|
name: getComponentNameFromType(element.type) || '',
|
||||||
owner: element._owner,
|
owner: element._owner,
|
||||||
};
|
};
|
||||||
if (enableOwnerStacks) {
|
// $FlowFixMe[cannot-write]
|
||||||
|
erroredComponent.debugStack = element._debugStack;
|
||||||
|
if (supportsCreateTask) {
|
||||||
// $FlowFixMe[cannot-write]
|
// $FlowFixMe[cannot-write]
|
||||||
erroredComponent.debugStack = element._debugStack;
|
erroredComponent.debugTask = element._debugTask;
|
||||||
if (supportsCreateTask) {
|
|
||||||
// $FlowFixMe[cannot-write]
|
|
||||||
erroredComponent.debugTask = element._debugTask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
erroredChunk._debugInfo = [erroredComponent];
|
erroredChunk._debugInfo = [erroredComponent];
|
||||||
}
|
}
|
||||||
|
|
@ -1057,13 +1043,11 @@ function waitForReference<T>(
|
||||||
name: getComponentNameFromType(element.type) || '',
|
name: getComponentNameFromType(element.type) || '',
|
||||||
owner: element._owner,
|
owner: element._owner,
|
||||||
};
|
};
|
||||||
if (enableOwnerStacks) {
|
// $FlowFixMe[cannot-write]
|
||||||
|
erroredComponent.debugStack = element._debugStack;
|
||||||
|
if (supportsCreateTask) {
|
||||||
// $FlowFixMe[cannot-write]
|
// $FlowFixMe[cannot-write]
|
||||||
erroredComponent.debugStack = element._debugStack;
|
erroredComponent.debugTask = element._debugTask;
|
||||||
if (supportsCreateTask) {
|
|
||||||
// $FlowFixMe[cannot-write]
|
|
||||||
erroredComponent.debugTask = element._debugTask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const chunkDebugInfo: ReactDebugInfo =
|
const chunkDebugInfo: ReactDebugInfo =
|
||||||
chunk._debugInfo || (chunk._debugInfo = []);
|
chunk._debugInfo || (chunk._debugInfo = []);
|
||||||
|
|
@ -1223,13 +1207,11 @@ function loadServerReference<A: Iterable<any>, T>(
|
||||||
name: getComponentNameFromType(element.type) || '',
|
name: getComponentNameFromType(element.type) || '',
|
||||||
owner: element._owner,
|
owner: element._owner,
|
||||||
};
|
};
|
||||||
if (enableOwnerStacks) {
|
// $FlowFixMe[cannot-write]
|
||||||
|
erroredComponent.debugStack = element._debugStack;
|
||||||
|
if (supportsCreateTask) {
|
||||||
// $FlowFixMe[cannot-write]
|
// $FlowFixMe[cannot-write]
|
||||||
erroredComponent.debugStack = element._debugStack;
|
erroredComponent.debugTask = element._debugTask;
|
||||||
if (supportsCreateTask) {
|
|
||||||
// $FlowFixMe[cannot-write]
|
|
||||||
erroredComponent.debugTask = element._debugTask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const chunkDebugInfo: ReactDebugInfo =
|
const chunkDebugInfo: ReactDebugInfo =
|
||||||
chunk._debugInfo || (chunk._debugInfo = []);
|
chunk._debugInfo || (chunk._debugInfo = []);
|
||||||
|
|
@ -1609,8 +1591,8 @@ function parseModelTuple(
|
||||||
tuple[2],
|
tuple[2],
|
||||||
tuple[3],
|
tuple[3],
|
||||||
__DEV__ ? (tuple: any)[4] : null,
|
__DEV__ ? (tuple: any)[4] : null,
|
||||||
__DEV__ && enableOwnerStacks ? (tuple: any)[5] : null,
|
__DEV__ ? (tuple: any)[5] : null,
|
||||||
__DEV__ && enableOwnerStacks ? (tuple: any)[6] : 0,
|
__DEV__ ? (tuple: any)[6] : 0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
|
|
@ -2083,27 +2065,6 @@ function stopStream(
|
||||||
controller.close(row === '' ? '"$undefined"' : row);
|
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};
|
type ErrorWithDigest = Error & {digest?: string};
|
||||||
function resolveErrorProd(response: Response): Error {
|
function resolveErrorProd(response: Response): Error {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
|
|
@ -2202,34 +2163,20 @@ function resolvePostponeDev(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let postponeInstance: Postpone;
|
let postponeInstance: Postpone;
|
||||||
if (!enableOwnerStacks) {
|
const callStack = buildFakeCallStack(
|
||||||
// Executing Error within a native stack isn't really limited to owner stacks
|
response,
|
||||||
// but we gate it behind the same flag for now while iterating.
|
stack,
|
||||||
// eslint-disable-next-line react-internal/prod-error-codes
|
env,
|
||||||
postponeInstance = (Error(reason || ''): any);
|
// $FlowFixMe[incompatible-use]
|
||||||
postponeInstance.$$typeof = REACT_POSTPONE_TYPE;
|
Error.bind(null, reason || ''),
|
||||||
// For backwards compat we use the V8 formatting when the flag is off.
|
);
|
||||||
postponeInstance.stack = formatV8Stack(
|
const rootTask = response._debugRootTask;
|
||||||
postponeInstance.name,
|
if (rootTask != null) {
|
||||||
postponeInstance.message,
|
postponeInstance = rootTask.run(callStack);
|
||||||
stack,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
const callStack = buildFakeCallStack(
|
postponeInstance = callStack();
|
||||||
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.$$typeof = REACT_POSTPONE_TYPE;
|
||||||
const chunks = response._chunks;
|
const chunks = response._chunks;
|
||||||
const chunk = chunks.get(id);
|
const chunk = chunks.get(id);
|
||||||
if (!chunk) {
|
if (!chunk) {
|
||||||
|
|
@ -2248,8 +2195,7 @@ function resolveHint<Code: HintCode>(
|
||||||
dispatchHint(code, hintModel);
|
dispatchHint(code, hintModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
const supportsCreateTask =
|
const supportsCreateTask = __DEV__ && !!(console: any).createTask;
|
||||||
__DEV__ && enableOwnerStacks && !!(console: any).createTask;
|
|
||||||
|
|
||||||
type FakeFunction<T> = (() => T) => T;
|
type FakeFunction<T> = (() => T) => T;
|
||||||
const fakeFunctionCache: Map<string, FakeFunction<any>> = __DEV__
|
const fakeFunctionCache: Map<string, FakeFunction<any>> = __DEV__
|
||||||
|
|
@ -2590,15 +2536,11 @@ function resolveDebugInfo(
|
||||||
let currentOwnerInDEV: null | ReactComponentInfo = null;
|
let currentOwnerInDEV: null | ReactComponentInfo = null;
|
||||||
function getCurrentStackInDEV(): string {
|
function getCurrentStackInDEV(): string {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
if (enableOwnerStacks) {
|
const owner: null | ReactComponentInfo = currentOwnerInDEV;
|
||||||
const owner: null | ReactComponentInfo = currentOwnerInDEV;
|
if (owner === null) {
|
||||||
if (owner === null) {
|
return '';
|
||||||
return '';
|
|
||||||
}
|
|
||||||
return getOwnerStackByComponentInfoInDev(owner);
|
|
||||||
}
|
}
|
||||||
// We don't have Parent Stacks in Flight.
|
return getOwnerStackByComponentInfoInDev(owner);
|
||||||
return '';
|
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -321,9 +321,7 @@ describe('ReactFlight', () => {
|
||||||
env: 'Server',
|
env: 'Server',
|
||||||
key: null,
|
key: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
stack: gate(flag => flag.enableOwnerStacks)
|
stack: ' in Object.<anonymous> (at **)',
|
||||||
? ' in Object.<anonymous> (at **)'
|
|
||||||
: undefined,
|
|
||||||
props: {
|
props: {
|
||||||
firstName: 'Seb',
|
firstName: 'Seb',
|
||||||
lastName: 'Smith',
|
lastName: 'Smith',
|
||||||
|
|
@ -367,9 +365,7 @@ describe('ReactFlight', () => {
|
||||||
env: 'Server',
|
env: 'Server',
|
||||||
key: null,
|
key: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
stack: gate(flag => flag.enableOwnerStacks)
|
stack: ' in Object.<anonymous> (at **)',
|
||||||
? ' in Object.<anonymous> (at **)'
|
|
||||||
: undefined,
|
|
||||||
props: {
|
props: {
|
||||||
firstName: 'Seb',
|
firstName: 'Seb',
|
||||||
lastName: 'Smith',
|
lastName: 'Smith',
|
||||||
|
|
@ -1400,30 +1396,19 @@ describe('ReactFlight', () => {
|
||||||
environmentName: 'Server',
|
environmentName: 'Server',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
findSourceMapURLCalls: gate(flags => flags.enableOwnerStacks)
|
findSourceMapURLCalls: [
|
||||||
? [
|
[__filename, 'Server'],
|
||||||
[__filename, 'Server'],
|
[__filename, 'Server'],
|
||||||
[__filename, 'Server'],
|
// TODO: What should we request here? The outer (<anonymous>) or the inner (inspected-page.html)?
|
||||||
// TODO: What should we request here? The outer (<anonymous>) or the inner (inspected-page.html)?
|
['inspected-page.html:29:11), <anonymous>', 'Server'],
|
||||||
['inspected-page.html:29:11), <anonymous>', 'Server'],
|
[
|
||||||
[
|
'file://~/(some)(really)(exotic-directory)/ReactFlight-test.js',
|
||||||
'file://~/(some)(really)(exotic-directory)/ReactFlight-test.js',
|
'Server',
|
||||||
'Server',
|
],
|
||||||
],
|
['file:///testing.js', 'Server'],
|
||||||
['file:///testing.js', 'Server'],
|
['', 'Server'],
|
||||||
['', 'Server'],
|
[__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'],
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
expect(errors.map(getErrorForJestMatcher)).toEqual([
|
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' +
|
'Check the render method of `Component`. See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
' in Component (at **)\n' +
|
' in Component (at **)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: ' in Indirection (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
@ -1538,46 +1520,26 @@ describe('ReactFlight', () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const transport = ReactNoopFlightServer.render(<input value={obj} />);
|
const transport = ReactNoopFlightServer.render(<input value={obj} />);
|
||||||
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' +
|
|
||||||
' ^^^^^^^^^^^^^^^',
|
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReactNoopFlightClient.read(transport);
|
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
|
||||||
assertConsoleErrorDev([
|
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
'Objects with toJSON methods are not supported. ' +
|
'Objects with toJSON methods are not supported. ' +
|
||||||
'Convert it manually to a simple value before passing it to props.\n' +
|
'Convert it manually to a simple value before passing it to props.\n' +
|
||||||
' <input value={{toJSON: ...}}>\n' +
|
' <input value={{toJSON: ...}}>\n' +
|
||||||
' ^^^^^^^^^^^^^^^\n' +
|
' ^^^^^^^^^^^^^^^',
|
||||||
' at (<anonymous>)',
|
],
|
||||||
]);
|
{withoutStack: true},
|
||||||
} else {
|
);
|
||||||
assertConsoleErrorDev(
|
|
||||||
[
|
ReactNoopFlightClient.read(transport);
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
assertConsoleErrorDev([
|
||||||
'Objects with toJSON methods are not supported. ' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
'Convert it manually to a simple value before passing it to props.\n' +
|
'Objects with toJSON methods are not supported. ' +
|
||||||
' <input value={{toJSON: ...}}>\n' +
|
'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. ' +
|
' ^^^^^^^^^^^^^^^\n' +
|
||||||
'Objects with toJSON methods are not supported. ' +
|
' at (<anonymous>)',
|
||||||
'Convert it manually to a simple value before passing it to props.\n' +
|
]);
|
||||||
' <input value={{toJSON: ...}}>\n' +
|
|
||||||
' ^^^^^^^^^^^^^^^',
|
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should warn in DEV if a toJSON instance is passed to a host component child', () => {
|
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(
|
const transport = ReactNoopFlightServer.render(
|
||||||
<div>Womp womp: {new MyError('spaghetti')}</div>,
|
<div>Womp womp: {new MyError('spaghetti')}</div>,
|
||||||
);
|
);
|
||||||
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' +
|
|
||||||
' ^^^^^^^',
|
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReactNoopFlightClient.read(transport);
|
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
|
||||||
assertConsoleErrorDev([
|
|
||||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||||
' <div>Womp womp: {Error}</div>\n' +
|
' <div>Womp womp: {Error}</div>\n' +
|
||||||
' ^^^^^^^\n' +
|
' ^^^^^^^',
|
||||||
' at (<anonymous>)',
|
],
|
||||||
]);
|
{withoutStack: true},
|
||||||
} else {
|
);
|
||||||
assertConsoleErrorDev(
|
|
||||||
[
|
ReactNoopFlightClient.read(transport);
|
||||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
assertConsoleErrorDev([
|
||||||
' <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' +
|
||||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
' ^^^^^^^\n' +
|
||||||
' <div>Womp womp: {Error}</div>\n' +
|
' at (<anonymous>)',
|
||||||
' ^^^^^^^',
|
]);
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should warn in DEV if a special object is passed to a host component', () => {
|
it('should warn in DEV if a special object is passed to a host component', () => {
|
||||||
const transport = ReactNoopFlightServer.render(<input value={Math} />);
|
const transport = ReactNoopFlightServer.render(<input value={Math} />);
|
||||||
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' +
|
|
||||||
' ^^^^^^',
|
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReactNoopFlightClient.read(transport);
|
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
|
||||||
assertConsoleErrorDev([
|
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
'Math objects are not supported.\n' +
|
'Math objects are not supported.\n' +
|
||||||
' <input value={Math}>\n' +
|
' <input value={Math}>\n' +
|
||||||
' ^^^^^^\n' +
|
' ^^^^^^',
|
||||||
' at (<anonymous>)',
|
],
|
||||||
]);
|
{withoutStack: true},
|
||||||
} else {
|
);
|
||||||
assertConsoleErrorDev(
|
|
||||||
[
|
ReactNoopFlightClient.read(transport);
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
assertConsoleErrorDev([
|
||||||
'Math objects are not supported.\n' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
' <input value={Math}>\n' +
|
'Math objects are not supported.\n' +
|
||||||
' ^^^^^^',
|
' <input value={Math}>\n' +
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
' ^^^^^^\n' +
|
||||||
'Math objects are not supported.\n' +
|
' at (<anonymous>)',
|
||||||
' <input value={Math}>\n' +
|
]);
|
||||||
' ^^^^^^',
|
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should warn in DEV if an object with symbols is passed to a host component', () => {
|
it('should warn in DEV if an object with symbols is passed to a host component', () => {
|
||||||
const transport = ReactNoopFlightServer.render(
|
const transport = ReactNoopFlightServer.render(
|
||||||
<input value={{[Symbol.iterator]: {}}} />,
|
<input value={{[Symbol.iterator]: {}}} />,
|
||||||
);
|
);
|
||||||
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' +
|
|
||||||
' ^^^^',
|
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReactNoopFlightClient.read(transport);
|
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
|
||||||
assertConsoleErrorDev([
|
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||||
' <input value={{}}>\n' +
|
' <input value={{}}>\n' +
|
||||||
' ^^^^\n' +
|
' ^^^^',
|
||||||
' at (<anonymous>)',
|
],
|
||||||
]);
|
{withoutStack: true},
|
||||||
} else {
|
);
|
||||||
assertConsoleErrorDev(
|
|
||||||
[
|
ReactNoopFlightClient.read(transport);
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
assertConsoleErrorDev([
|
||||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
' <input value={{}}>\n' +
|
'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. ' +
|
' ^^^^\n' +
|
||||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
' at (<anonymous>)',
|
||||||
' <input value={{}}>\n' +
|
]);
|
||||||
' ^^^^',
|
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should warn in DEV if a toJSON instance is passed to a Client Component', () => {
|
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 Client = clientReference(ClientImpl);
|
||||||
const transport = ReactNoopFlightServer.render(<Client value={obj} />);
|
const transport = ReactNoopFlightServer.render(<Client value={obj} />);
|
||||||
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' +
|
|
||||||
' ^^^^^^^^^^^^^^^',
|
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReactNoopFlightClient.read(transport);
|
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
|
||||||
assertConsoleErrorDev([
|
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
'Objects with toJSON methods are not supported. ' +
|
'Objects with toJSON methods are not supported. ' +
|
||||||
'Convert it manually to a simple value before passing it to props.\n' +
|
'Convert it manually to a simple value before passing it to props.\n' +
|
||||||
' <... value={{toJSON: ...}}>\n' +
|
' <... value={{toJSON: ...}}>\n' +
|
||||||
' ^^^^^^^^^^^^^^^\n' +
|
' ^^^^^^^^^^^^^^^',
|
||||||
' at (<anonymous>)',
|
],
|
||||||
]);
|
{withoutStack: true},
|
||||||
} else {
|
);
|
||||||
assertConsoleErrorDev(
|
|
||||||
[
|
ReactNoopFlightClient.read(transport);
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
assertConsoleErrorDev([
|
||||||
'Objects with toJSON methods are not supported. ' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
'Convert it manually to a simple value before passing it to props.\n' +
|
'Objects with toJSON methods are not supported. ' +
|
||||||
' <... value={{toJSON: ...}}>\n' +
|
'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. ' +
|
' ^^^^^^^^^^^^^^^\n' +
|
||||||
'Objects with toJSON methods are not supported. ' +
|
' at (<anonymous>)',
|
||||||
'Convert it manually to a simple value before passing it to props.\n' +
|
]);
|
||||||
' <... value={{toJSON: ...}}>\n' +
|
|
||||||
' ^^^^^^^^^^^^^^^',
|
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should warn in DEV if a toJSON instance is passed to a Client Component child', () => {
|
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(
|
const transport = ReactNoopFlightServer.render(
|
||||||
<Client>Current date: {obj}</Client>,
|
<Client>Current date: {obj}</Client>,
|
||||||
);
|
);
|
||||||
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' +
|
|
||||||
' ^^^^^^^^^^^^^^^',
|
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReactNoopFlightClient.read(transport);
|
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
|
||||||
assertConsoleErrorDev([
|
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
'Objects with toJSON methods are not supported. ' +
|
'Objects with toJSON methods are not supported. ' +
|
||||||
'Convert it manually to a simple value before passing it to props.\n' +
|
'Convert it manually to a simple value before passing it to props.\n' +
|
||||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
' <>Current date: {{toJSON: ...}}</>\n' +
|
||||||
' ^^^^^^^^^^^^^^^\n' +
|
' ^^^^^^^^^^^^^^^',
|
||||||
' at (<anonymous>)',
|
],
|
||||||
]);
|
{withoutStack: true},
|
||||||
} else {
|
);
|
||||||
assertConsoleErrorDev(
|
|
||||||
[
|
ReactNoopFlightClient.read(transport);
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
assertConsoleErrorDev([
|
||||||
'Objects with toJSON methods are not supported. ' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
'Convert it manually to a simple value before passing it to props.\n' +
|
'Objects with toJSON methods are not supported. ' +
|
||||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
'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. ' +
|
' ^^^^^^^^^^^^^^^\n' +
|
||||||
'Objects with toJSON methods are not supported. ' +
|
' at (<anonymous>)',
|
||||||
'Convert it manually to a simple value before passing it to props.\n' +
|
]);
|
||||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
|
||||||
' ^^^^^^^^^^^^^^^',
|
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should warn in DEV if a special object is passed to a Client Component', () => {
|
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 Client = clientReference(ClientImpl);
|
||||||
const transport = ReactNoopFlightServer.render(<Client value={Math} />);
|
const transport = ReactNoopFlightServer.render(<Client value={Math} />);
|
||||||
|
assertConsoleErrorDev(
|
||||||
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([
|
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
'Math objects are not supported.\n' +
|
'Math objects are not supported.\n' +
|
||||||
' <... value={Math}>\n' +
|
' <... value={Math}>\n' +
|
||||||
' ^^^^^^\n' +
|
' ^^^^^^',
|
||||||
' at (<anonymous>)',
|
],
|
||||||
]);
|
{withoutStack: true},
|
||||||
} else {
|
);
|
||||||
assertConsoleErrorDev(
|
|
||||||
[
|
ReactNoopFlightClient.read(transport);
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
assertConsoleErrorDev([
|
||||||
'Math objects are not supported.\n' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
' <... value={Math}>\n' +
|
'Math objects are not supported.\n' +
|
||||||
' ^^^^^^',
|
' <... value={Math}>\n' +
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
' ^^^^^^\n' +
|
||||||
'Math objects are not supported.\n' +
|
' at (<anonymous>)',
|
||||||
' <... value={Math}>\n' +
|
]);
|
||||||
' ^^^^^^',
|
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should warn in DEV if an object with symbols is passed to a Client Component', () => {
|
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(
|
const transport = ReactNoopFlightServer.render(
|
||||||
<Client value={{[Symbol.iterator]: {}}} />,
|
<Client value={{[Symbol.iterator]: {}}} />,
|
||||||
);
|
);
|
||||||
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' +
|
|
||||||
' ^^^^',
|
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReactNoopFlightClient.read(transport);
|
|
||||||
|
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
|
||||||
assertConsoleErrorDev([
|
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||||
' <... value={{}}>\n' +
|
' <... value={{}}>\n' +
|
||||||
' ^^^^\n',
|
' ^^^^',
|
||||||
]);
|
],
|
||||||
} else {
|
{withoutStack: true},
|
||||||
assertConsoleErrorDev(
|
);
|
||||||
[
|
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
ReactNoopFlightClient.read(transport);
|
||||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
|
||||||
' <... value={{}}>\n' +
|
assertConsoleErrorDev([
|
||||||
' ^^^^',
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
' <... value={{}}>\n' +
|
||||||
' <... value={{}}>\n' +
|
' ^^^^\n',
|
||||||
' ^^^^',
|
]);
|
||||||
],
|
|
||||||
{withoutStack: true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should warn in DEV if a special object is passed to a nested object in Client Component', () => {
|
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);
|
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' +
|
|
||||||
' ^^^^',
|
|
||||||
{withoutStack: true},
|
|
||||||
],
|
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||||
' <... value={{}}>\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},
|
{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', () => {
|
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>]} />,
|
<Client value={['looooong string takes up noise', Math, <h1>hi</h1>]} />,
|
||||||
);
|
);
|
||||||
ReactNoopFlightClient.read(transport);
|
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' +
|
|
||||||
' [..., Math, <h1/>]\n' +
|
|
||||||
' ^^^^',
|
|
||||||
{withoutStack: true},
|
|
||||||
],
|
|
||||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||||
'Math objects are not supported.\n' +
|
'Math objects are not supported.\n' +
|
||||||
' [..., Math, <h1/>]\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},
|
{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', () => {
|
it('should NOT warn in DEV for key getters', () => {
|
||||||
|
|
@ -2012,26 +1813,16 @@ describe('ReactFlight', () => {
|
||||||
jest.resetModules();
|
jest.resetModules();
|
||||||
jest.mock('react', () => React);
|
jest.mock('react', () => React);
|
||||||
ReactNoopFlightClient.read(transport);
|
ReactNoopFlightClient.read(transport);
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
assertConsoleErrorDev([
|
||||||
assertConsoleErrorDev([
|
'Each child in a list should have a unique "key" prop. ' +
|
||||||
'Each child in a list should have a unique "key" prop. ' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
' in NoKey (at **)',
|
||||||
' in NoKey (at **)',
|
'Each child in a list should have a unique "key" prop. ' +
|
||||||
'Each child in a list should have a unique "key" prop. ' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
' in NoKey (at **)',
|
||||||
' 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 **)',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// @gate !__DEV__ || enableOwnerStacks
|
|
||||||
it('should warn in DEV a child is missing keys on a fragment', () => {
|
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.
|
// While we're on the server we need to have the Server version active to track component stacks.
|
||||||
jest.resetModules();
|
jest.resetModules();
|
||||||
|
|
@ -2046,23 +1837,14 @@ describe('ReactFlight', () => {
|
||||||
jest.resetModules();
|
jest.resetModules();
|
||||||
jest.mock('react', () => React);
|
jest.mock('react', () => React);
|
||||||
ReactNoopFlightClient.read(transport);
|
ReactNoopFlightClient.read(transport);
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
assertConsoleErrorDev([
|
||||||
assertConsoleErrorDev([
|
'Each child in a list should have a unique "key" prop. ' +
|
||||||
'Each child in a list should have a unique "key" prop. ' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
' in Fragment (at **)',
|
||||||
' in Fragment (at **)',
|
'Each child in a list should have a unique "key" prop. ' +
|
||||||
'Each child in a list should have a unique "key" prop. ' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
' in Fragment (at **)',
|
||||||
' 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 **)',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should warn in DEV a child is missing keys in client component', async () => {
|
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));
|
ReactNoop.render(await ReactNoopFlightClient.read(transport));
|
||||||
});
|
});
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
assertConsoleErrorDev([
|
||||||
assertConsoleErrorDev([
|
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
'Check the top-level render call using <ParentClient>. ' +
|
||||||
'Check the top-level render call using <ParentClient>. ' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
' in div (at **)',
|
||||||
' 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 **)',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should error if a class instance is passed to a host component', () => {
|
it('should error if a class instance is passed to a host component', () => {
|
||||||
|
|
@ -3039,9 +2813,7 @@ describe('ReactFlight', () => {
|
||||||
env: 'Server',
|
env: 'Server',
|
||||||
key: null,
|
key: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
stack: gate(flag => flag.enableOwnerStacks)
|
stack: ' in Object.<anonymous> (at **)',
|
||||||
? ' in Object.<anonymous> (at **)'
|
|
||||||
: undefined,
|
|
||||||
props: {
|
props: {
|
||||||
transport: expect.arrayContaining([]),
|
transport: expect.arrayContaining([]),
|
||||||
},
|
},
|
||||||
|
|
@ -3063,9 +2835,7 @@ describe('ReactFlight', () => {
|
||||||
env: 'third-party',
|
env: 'third-party',
|
||||||
key: null,
|
key: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
stack: gate(flag => flag.enableOwnerStacks)
|
stack: ' in Object.<anonymous> (at **)',
|
||||||
? ' in Object.<anonymous> (at **)'
|
|
||||||
: undefined,
|
|
||||||
props: {},
|
props: {},
|
||||||
},
|
},
|
||||||
{time: 14},
|
{time: 14},
|
||||||
|
|
@ -3082,9 +2852,7 @@ describe('ReactFlight', () => {
|
||||||
env: 'third-party',
|
env: 'third-party',
|
||||||
key: null,
|
key: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
stack: gate(flag => flag.enableOwnerStacks)
|
stack: ' in myLazy (at **)\n in lazyInitializer (at **)',
|
||||||
? ' in myLazy (at **)\n in lazyInitializer (at **)'
|
|
||||||
: undefined,
|
|
||||||
props: {},
|
props: {},
|
||||||
},
|
},
|
||||||
{time: 16},
|
{time: 16},
|
||||||
|
|
@ -3100,9 +2868,7 @@ describe('ReactFlight', () => {
|
||||||
env: 'third-party',
|
env: 'third-party',
|
||||||
key: '3',
|
key: '3',
|
||||||
owner: null,
|
owner: null,
|
||||||
stack: gate(flag => flag.enableOwnerStacks)
|
stack: ' in Object.<anonymous> (at **)',
|
||||||
? ' in Object.<anonymous> (at **)'
|
|
||||||
: undefined,
|
|
||||||
props: {},
|
props: {},
|
||||||
},
|
},
|
||||||
{time: 12},
|
{time: 12},
|
||||||
|
|
@ -3176,9 +2942,7 @@ describe('ReactFlight', () => {
|
||||||
env: 'Server',
|
env: 'Server',
|
||||||
key: null,
|
key: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
stack: gate(flag => flag.enableOwnerStacks)
|
stack: ' in Object.<anonymous> (at **)',
|
||||||
? ' in Object.<anonymous> (at **)'
|
|
||||||
: undefined,
|
|
||||||
props: {
|
props: {
|
||||||
transport: expect.arrayContaining([]),
|
transport: expect.arrayContaining([]),
|
||||||
},
|
},
|
||||||
|
|
@ -3198,9 +2962,7 @@ describe('ReactFlight', () => {
|
||||||
env: 'Server',
|
env: 'Server',
|
||||||
key: 'keyed',
|
key: 'keyed',
|
||||||
owner: null,
|
owner: null,
|
||||||
stack: gate(flag => flag.enableOwnerStacks)
|
stack: ' in ServerComponent (at **)',
|
||||||
? ' in ServerComponent (at **)'
|
|
||||||
: undefined,
|
|
||||||
props: {
|
props: {
|
||||||
children: {},
|
children: {},
|
||||||
},
|
},
|
||||||
|
|
@ -3219,9 +2981,7 @@ describe('ReactFlight', () => {
|
||||||
env: 'third-party',
|
env: 'third-party',
|
||||||
key: null,
|
key: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
stack: gate(flag => flag.enableOwnerStacks)
|
stack: ' in Object.<anonymous> (at **)',
|
||||||
? ' in Object.<anonymous> (at **)'
|
|
||||||
: undefined,
|
|
||||||
props: {},
|
props: {},
|
||||||
},
|
},
|
||||||
{time: 12},
|
{time: 12},
|
||||||
|
|
@ -3335,19 +3095,13 @@ describe('ReactFlight', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(sawReactPrefix).toBe(false);
|
expect(sawReactPrefix).toBe(false);
|
||||||
if (__DEV__ && gate(flags => flags.enableOwnerStacks)) {
|
if (__DEV__) {
|
||||||
expect(environments.slice(0, 4)).toEqual([
|
expect(environments.slice(0, 4)).toEqual([
|
||||||
'Server',
|
'Server',
|
||||||
'third-party',
|
'third-party',
|
||||||
'third-party',
|
'third-party',
|
||||||
'third-party',
|
'third-party',
|
||||||
]);
|
]);
|
||||||
} else if (__DEV__) {
|
|
||||||
expect(environments.slice(0, 3)).toEqual([
|
|
||||||
'third-party',
|
|
||||||
'third-party',
|
|
||||||
'third-party',
|
|
||||||
]);
|
|
||||||
} else {
|
} else {
|
||||||
expect(environments).toEqual([]);
|
expect(environments).toEqual([]);
|
||||||
}
|
}
|
||||||
|
|
@ -3384,9 +3138,7 @@ describe('ReactFlight', () => {
|
||||||
env: 'A',
|
env: 'A',
|
||||||
key: null,
|
key: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
stack: gate(flag => flag.enableOwnerStacks)
|
stack: ' in Object.<anonymous> (at **)',
|
||||||
? ' in Object.<anonymous> (at **)'
|
|
||||||
: undefined,
|
|
||||||
props: {},
|
props: {},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -3402,7 +3154,7 @@ describe('ReactFlight', () => {
|
||||||
expect(ReactNoop).toMatchRenderedOutput(<div>hi</div>);
|
expect(ReactNoop).toMatchRenderedOutput(<div>hi</div>);
|
||||||
});
|
});
|
||||||
|
|
||||||
// @gate __DEV__ && enableOwnerStacks
|
// @gate __DEV__
|
||||||
it('replays logs, but not onError logs', async () => {
|
it('replays logs, but not onError logs', async () => {
|
||||||
function foo() {
|
function foo() {
|
||||||
return 'hello';
|
return 'hello';
|
||||||
|
|
@ -3574,9 +3326,7 @@ describe('ReactFlight', () => {
|
||||||
env: 'Server',
|
env: 'Server',
|
||||||
key: null,
|
key: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
stack: gate(flag => flag.enableOwnerStacks)
|
stack: ' in Object.<anonymous> (at **)',
|
||||||
? ' in Object.<anonymous> (at **)'
|
|
||||||
: undefined,
|
|
||||||
props: {
|
props: {
|
||||||
firstName: 'Seb',
|
firstName: 'Seb',
|
||||||
},
|
},
|
||||||
|
|
@ -3590,9 +3340,7 @@ describe('ReactFlight', () => {
|
||||||
env: 'Server',
|
env: 'Server',
|
||||||
key: null,
|
key: null,
|
||||||
owner: greetInfo,
|
owner: greetInfo,
|
||||||
stack: gate(flag => flag.enableOwnerStacks)
|
stack: ' in Greeting (at **)',
|
||||||
? ' in Greeting (at **)'
|
|
||||||
: undefined,
|
|
||||||
props: {
|
props: {
|
||||||
children: expect.objectContaining({
|
children: expect.objectContaining({
|
||||||
type: 'span',
|
type: 'span',
|
||||||
|
|
@ -3617,7 +3365,7 @@ describe('ReactFlight', () => {
|
||||||
expect(ReactNoop).toMatchRenderedOutput(<span>Hello, Seb</span>);
|
expect(ReactNoop).toMatchRenderedOutput(<span>Hello, Seb</span>);
|
||||||
});
|
});
|
||||||
|
|
||||||
// @gate __DEV__ && enableOwnerStacks
|
// @gate __DEV__
|
||||||
it('can get the component owner stacks during rendering in dev', () => {
|
it('can get the component owner stacks during rendering in dev', () => {
|
||||||
let stack;
|
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 () => {
|
it('can track owner for a flight response created in another render', async () => {
|
||||||
jest.resetModules();
|
jest.resetModules();
|
||||||
jest.mock('react', () => ReactServer);
|
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 () => {
|
it('can get the component owner stacks for onError in dev', async () => {
|
||||||
const thrownError = new Error('hi');
|
const thrownError = new Error('hi');
|
||||||
let caughtError;
|
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)', () => {
|
it('should include only one component stack in replayed logs (if DevTools or polyfill adds them)', () => {
|
||||||
class MyError extends Error {
|
class MyError extends Error {
|
||||||
toJSON() {
|
toJSON() {
|
||||||
|
|
|
||||||
|
|
@ -2347,10 +2347,7 @@ describe('ReactHooksInspectionIntegration', () => {
|
||||||
|
|
||||||
await act(async () => await LazyFoo);
|
await act(async () => await LazyFoo);
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Foo: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.' +
|
'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 **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const childFiber = renderer.root._currentFiber();
|
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.
|
// 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.
|
// 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 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.
|
// but only return them when needed, sending hundreds of component stacks is beyond the Bridge's bandwidth.
|
||||||
|
|
||||||
// Postprocess Profile data
|
// Postprocess Profile data
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,6 @@
|
||||||
import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
|
import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
|
||||||
import type {HydrationDiffNode} from 'react-reconciler/src/ReactFiberHydrationDiffs';
|
import type {HydrationDiffNode} from 'react-reconciler/src/ReactFiberHydrationDiffs';
|
||||||
|
|
||||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
current,
|
current,
|
||||||
runWithFiberInDEV,
|
runWithFiberInDEV,
|
||||||
|
|
@ -615,7 +613,7 @@ function validateDOMNesting(
|
||||||
ancestorDescription,
|
ancestorDescription,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (enableOwnerStacks && child) {
|
if (child) {
|
||||||
// For debugging purposes find the nearest ancestor that caused the issue.
|
// For debugging purposes find the nearest ancestor that caused the issue.
|
||||||
// The stack trace of this ancestor can be useful to find the cause.
|
// 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.
|
// If the parent is a direct parent in the same owner, we don't bother.
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@ import {
|
||||||
enableLegacyFBSupport,
|
enableLegacyFBSupport,
|
||||||
enableCreateEventHandleAPI,
|
enableCreateEventHandleAPI,
|
||||||
enableScopeAPI,
|
enableScopeAPI,
|
||||||
enableOwnerStacks,
|
|
||||||
disableCommentsAsDOMContainers,
|
disableCommentsAsDOMContainers,
|
||||||
enableScrollEndPolyfill,
|
enableScrollEndPolyfill,
|
||||||
} from 'shared/ReactFeatureFlags';
|
} from 'shared/ReactFeatureFlags';
|
||||||
|
|
@ -275,7 +274,7 @@ function processDispatchQueueItemsInOrder(
|
||||||
if (instance !== previousInstance && event.isPropagationStopped()) {
|
if (instance !== previousInstance && event.isPropagationStopped()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (__DEV__ && enableOwnerStacks && instance !== null) {
|
if (__DEV__ && instance !== null) {
|
||||||
runWithFiberInDEV(
|
runWithFiberInDEV(
|
||||||
instance,
|
instance,
|
||||||
executeDispatch,
|
executeDispatch,
|
||||||
|
|
@ -294,7 +293,7 @@ function processDispatchQueueItemsInOrder(
|
||||||
if (instance !== previousInstance && event.isPropagationStopped()) {
|
if (instance !== previousInstance && event.isPropagationStopped()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (__DEV__ && enableOwnerStacks && instance !== null) {
|
if (__DEV__ && instance !== null) {
|
||||||
runWithFiberInDEV(
|
runWithFiberInDEV(
|
||||||
instance,
|
instance,
|
||||||
executeDispatch,
|
executeDispatch,
|
||||||
|
|
|
||||||
|
|
@ -75,8 +75,7 @@ describe('ReactChildReconciler', () => {
|
||||||
'This may happen if you return fn instead of <fn /> from render. ' +
|
'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' +
|
'Or maybe you meant to call this function rather than return it.\n' +
|
||||||
' <h1>{fn}</h1>\n' +
|
' <h1>{fn}</h1>\n' +
|
||||||
' in h1 (at **)' +
|
' in h1 (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in div (at **)'),
|
|
||||||
]);
|
]);
|
||||||
const node = container.firstChild;
|
const node = container.firstChild;
|
||||||
|
|
||||||
|
|
@ -100,7 +99,6 @@ describe('ReactChildReconciler', () => {
|
||||||
'Keys should be unique so that components maintain their identity across updates. ' +
|
'Keys should be unique so that components maintain their identity across updates. ' +
|
||||||
'Non-unique keys may cause children to be duplicated and/or omitted — ' +
|
'Non-unique keys may cause children to be duplicated and/or omitted — ' +
|
||||||
'the behavior is unsupported and could change in a future version.\n' +
|
'the behavior is unsupported and could change in a future version.\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in div (at **)\n') +
|
|
||||||
' in div (at **)\n' +
|
' in div (at **)\n' +
|
||||||
' in Component (at **)',
|
' in Component (at **)',
|
||||||
]);
|
]);
|
||||||
|
|
@ -137,11 +135,7 @@ describe('ReactChildReconciler', () => {
|
||||||
'duplicated and/or omitted — the behavior is unsupported and ' +
|
'duplicated and/or omitted — the behavior is unsupported and ' +
|
||||||
'could change in a future version.\n' +
|
'could change in a future version.\n' +
|
||||||
' in div (at **)\n' +
|
' in div (at **)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks) ? '' : ' in div (at **)\n') +
|
|
||||||
' in Component (at **)\n' +
|
' in Component (at **)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: ' in Parent (at **)\n') +
|
|
||||||
' in GrandParent (at **)',
|
' in GrandParent (at **)',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
@ -165,7 +159,6 @@ describe('ReactChildReconciler', () => {
|
||||||
'duplicated and/or omitted — the behavior is unsupported and ' +
|
'duplicated and/or omitted — the behavior is unsupported and ' +
|
||||||
'could change in a future version.\n' +
|
'could change in a future version.\n' +
|
||||||
' in div (at **)\n' +
|
' in div (at **)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks) ? '' : ' in div (at **)\n') +
|
|
||||||
' in Component (at **)',
|
' in Component (at **)',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
@ -201,11 +194,7 @@ describe('ReactChildReconciler', () => {
|
||||||
'duplicated and/or omitted — the behavior is unsupported and ' +
|
'duplicated and/or omitted — the behavior is unsupported and ' +
|
||||||
'could change in a future version.\n' +
|
'could change in a future version.\n' +
|
||||||
' in div (at **)\n' +
|
' in div (at **)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks) ? '' : ' in div (at **)\n') +
|
|
||||||
' in Component (at **)\n' +
|
' in Component (at **)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: ' in Parent (at **)\n') +
|
|
||||||
' in GrandParent (at **)',
|
' in GrandParent (at **)',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -407,17 +407,6 @@ describe('ReactComponent', () => {
|
||||||
|
|
||||||
const X = undefined;
|
const X = undefined;
|
||||||
const XElement = <X />;
|
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 expect(async () => {
|
||||||
await act(() => {
|
await act(() => {
|
||||||
root.render(XElement);
|
root.render(XElement);
|
||||||
|
|
@ -433,15 +422,6 @@ describe('ReactComponent', () => {
|
||||||
|
|
||||||
const Y = null;
|
const Y = null;
|
||||||
const YElement = <Y />;
|
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 expect(async () => {
|
||||||
await act(() => {
|
await act(() => {
|
||||||
root.render(YElement);
|
root.render(YElement);
|
||||||
|
|
@ -453,15 +433,6 @@ describe('ReactComponent', () => {
|
||||||
|
|
||||||
const Z = true;
|
const Z = true;
|
||||||
const ZElement = <Z />;
|
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 expect(async () => {
|
||||||
await act(() => {
|
await act(() => {
|
||||||
root.render(ZElement);
|
root.render(ZElement);
|
||||||
|
|
@ -506,26 +477,6 @@ describe('ReactComponent', () => {
|
||||||
'\n\nCheck the render method of `Bar`.'
|
'\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 () => {
|
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' +
|
'Or maybe you meant to call this function rather than return it.\n' +
|
||||||
' <span>{Foo}</span>\n' +
|
' <span>{Foo}</span>\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: ' in div (at **)\n') +
|
|
||||||
' in Foo (at **)',
|
' in Foo (at **)',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
@ -753,9 +701,6 @@ describe('ReactComponent', () => {
|
||||||
'Or maybe you meant to call this function rather than return it.\n' +
|
'Or maybe you meant to call this function rather than return it.\n' +
|
||||||
' <span>{Foo}</span>\n' +
|
' <span>{Foo}</span>\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: ' in div (at **)\n') +
|
|
||||||
' in Foo (at **)',
|
' in Foo (at **)',
|
||||||
]);
|
]);
|
||||||
await act(() => {
|
await act(() => {
|
||||||
|
|
|
||||||
|
|
@ -1396,9 +1396,6 @@ describe('ReactCompositeComponent', () => {
|
||||||
'Cannot update a component (`A`) while rendering a different component (`B`). ' +
|
'Cannot update a component (`A`) while rendering a different component (`B`). ' +
|
||||||
'To locate the bad setState() call inside `B`, ' +
|
'To locate the bad setState() call inside `B`, ' +
|
||||||
'follow the stack trace as described in https://react.dev/link/setstate-in-render\n' +
|
'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 **)',
|
' in Parent (at **)',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -545,7 +545,6 @@ describe('ReactDOM', () => {
|
||||||
// ReactDOM(App > div > span)
|
// ReactDOM(App > div > span)
|
||||||
'Invalid ARIA attribute `ariaTypo`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
'Invalid ARIA attribute `ariaTypo`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks) ? '' : ' in div (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
// ReactDOM(App > div > ServerEntry) >>> ReactDOMServer(Child) >>> ReactDOMServer(App2) >>> ReactDOMServer(blink)
|
// 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' +
|
'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)
|
// ReactDOM(App > div > font)
|
||||||
'Invalid ARIA attribute `ariaTypo5`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
'Invalid ARIA attribute `ariaTypo5`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||||
' in font (at **)\n' +
|
' in font (at **)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks) ? '' : ' in div (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1845,8 +1845,7 @@ describe('ReactDOMComponent', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'The tag <menuitem> is unrecognized in this browser. ' +
|
'The tag <menuitem> is unrecognized in this browser. ' +
|
||||||
'If you meant to render a React component, start its name with an uppercase letter.\n' +
|
'If you meant to render a React component, start its name with an uppercase letter.\n' +
|
||||||
' in menuitem (at **)' +
|
' in menuitem (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in menu (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -2242,10 +2241,7 @@ describe('ReactDOMComponent', () => {
|
||||||
'> <div>\n' +
|
'> <div>\n' +
|
||||||
'> <tr>\n' +
|
'> <tr>\n' +
|
||||||
' ...\n' +
|
' ...\n' +
|
||||||
'\n in tr (at **)' +
|
'\n in tr (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: '\n in div (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -2264,10 +2260,7 @@ describe('ReactDOMComponent', () => {
|
||||||
'In HTML, <p> cannot be a descendant of <p>.\n' +
|
'In HTML, <p> cannot be a descendant of <p>.\n' +
|
||||||
'This will cause a hydration error.' +
|
'This will cause a hydration error.' +
|
||||||
// There is no outer `p` here because root container is not part of the stack.
|
// There is no outer `p` here because root container is not part of the stack.
|
||||||
'\n in p (at **)' +
|
'\n in p (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: '\n in span (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -2294,92 +2287,48 @@ describe('ReactDOMComponent', () => {
|
||||||
await act(() => {
|
await act(() => {
|
||||||
root.render(<Foo />);
|
root.render(<Foo />);
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev(
|
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 ' +
|
||||||
'In HTML, <tr> cannot be a child of ' +
|
'by the browser.\n' +
|
||||||
'<table>. Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated ' +
|
'This will cause a hydration error.\n' +
|
||||||
'by the browser.\n' +
|
'\n' +
|
||||||
'This will cause a hydration error.\n' +
|
' <Foo>\n' +
|
||||||
'\n' +
|
'> <table>\n' +
|
||||||
' <Foo>\n' +
|
' <Row>\n' +
|
||||||
'> <table>\n' +
|
'> <tr>\n' +
|
||||||
' <Row>\n' +
|
' ...\n' +
|
||||||
'> <tr>\n' +
|
'\n in tr (at **)' +
|
||||||
' ...\n' +
|
'\n in Row (at **)' +
|
||||||
'\n in tr (at **)' +
|
'\n in Foo (at **)',
|
||||||
'\n in Row (at **)' +
|
'<table> cannot contain a nested <tr>.\nSee this log for the ancestor stack trace.' +
|
||||||
'\n in Foo (at **)',
|
'\n in table (at **)' +
|
||||||
'<table> cannot contain a nested <tr>.\nSee this log for the ancestor stack trace.' +
|
'\n in Foo (at **)',
|
||||||
'\n in table (at **)' +
|
'In HTML, text nodes cannot be a ' +
|
||||||
'\n in Foo (at **)',
|
'child of <tr>.\n' +
|
||||||
'In HTML, text nodes cannot be a ' +
|
'This will cause a hydration error.\n' +
|
||||||
'child of <tr>.\n' +
|
'\n' +
|
||||||
'This will cause a hydration error.\n' +
|
' <Foo>\n' +
|
||||||
'\n' +
|
' <table>\n' +
|
||||||
' <Foo>\n' +
|
' <Row>\n' +
|
||||||
' <table>\n' +
|
' <tr>\n' +
|
||||||
' <Row>\n' +
|
'> x\n' +
|
||||||
' <tr>\n' +
|
' ...\n' +
|
||||||
'> x\n' +
|
'\n in tr (at **)' +
|
||||||
' ...\n' +
|
'\n in Row (at **)' +
|
||||||
'\n in tr (at **)' +
|
'\n in Foo (at **)',
|
||||||
'\n in Row (at **)' +
|
'In HTML, whitespace text nodes cannot ' +
|
||||||
'\n in Foo (at **)',
|
"be a child of <table>. Make sure you don't have any extra " +
|
||||||
'In HTML, whitespace text nodes cannot ' +
|
'whitespace between tags on each line of your source code.\n' +
|
||||||
"be a child of <table>. Make sure you don't have any extra " +
|
'This will cause a hydration error.\n' +
|
||||||
'whitespace between tags on each line of your source code.\n' +
|
'\n' +
|
||||||
'This will cause a hydration error.\n' +
|
' <Foo>\n' +
|
||||||
'\n' +
|
'> <table>\n' +
|
||||||
' <Foo>\n' +
|
' <Row>\n' +
|
||||||
'> <table>\n' +
|
'> {" "}\n' +
|
||||||
' <Row>\n' +
|
'\n in table (at **)' +
|
||||||
'> {" "}\n' +
|
'\n in Foo (at **)',
|
||||||
'\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 **)',
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('warns nicely for updating table rows to use text', async () => {
|
it('warns nicely for updating table rows to use text', async () => {
|
||||||
|
|
@ -2445,12 +2394,7 @@ describe('ReactDOMComponent', () => {
|
||||||
' <tr>\n' +
|
' <tr>\n' +
|
||||||
'> text\n' +
|
'> text\n' +
|
||||||
'\n in tr (at **)' +
|
'\n in tr (at **)' +
|
||||||
'\n in Row (at **)' +
|
'\n in Row (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: '\n in tbody (at **)' +
|
|
||||||
'\n in table (at **)' +
|
|
||||||
'\n in Foo (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -2477,49 +2421,28 @@ describe('ReactDOMComponent', () => {
|
||||||
await act(() => {
|
await act(() => {
|
||||||
root.render(<App1 />);
|
root.render(<App1 />);
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev(
|
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' +
|
||||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
'This will cause a hydration error.\n' +
|
||||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
'\n' +
|
||||||
'This will cause a hydration error.\n' +
|
' <App1>\n' +
|
||||||
'\n' +
|
' <Viz1>\n' +
|
||||||
' <App1>\n' +
|
'> <table>\n' +
|
||||||
' <Viz1>\n' +
|
' <FancyRow>\n' +
|
||||||
'> <table>\n' +
|
' <Row>\n' +
|
||||||
' <FancyRow>\n' +
|
'> <tr>\n' +
|
||||||
' <Row>\n' +
|
'\n in tr (at **)' +
|
||||||
'> <tr>\n' +
|
'\n in Row (at **)' +
|
||||||
'\n in tr (at **)' +
|
'\n in FancyRow (at **)' +
|
||||||
'\n in Row (at **)' +
|
'\n in Viz1 (at **)' +
|
||||||
'\n in FancyRow (at **)' +
|
'\n in App1 (at **)',
|
||||||
'\n in Viz1 (at **)' +
|
'<table> cannot contain a nested <tr>.\n' +
|
||||||
'\n in App1 (at **)',
|
'See this log for the ancestor stack trace.\n' +
|
||||||
'<table> cannot contain a nested <tr>.\n' +
|
' in table (at **)\n' +
|
||||||
'See this log for the ancestor stack trace.\n' +
|
' in Viz1 (at **)\n' +
|
||||||
' in table (at **)\n' +
|
' in App1 (at **)',
|
||||||
' 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 **)',
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('gives useful context in warnings 2', async () => {
|
it('gives useful context in warnings 2', async () => {
|
||||||
|
|
@ -2558,57 +2481,32 @@ describe('ReactDOMComponent', () => {
|
||||||
await act(() => {
|
await act(() => {
|
||||||
root.render(<App2 />);
|
root.render(<App2 />);
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev(
|
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' +
|
||||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
'This will cause a hydration error.\n' +
|
||||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
'\n' +
|
||||||
'This will cause a hydration error.\n' +
|
' <App2>\n' +
|
||||||
'\n' +
|
' <Viz2>\n' +
|
||||||
' <App2>\n' +
|
' <FancyTable>\n' +
|
||||||
' <Viz2>\n' +
|
' <Table>\n' +
|
||||||
' <FancyTable>\n' +
|
'> <table>\n' +
|
||||||
' <Table>\n' +
|
' <FancyRow>\n' +
|
||||||
'> <table>\n' +
|
' <Row>\n' +
|
||||||
' <FancyRow>\n' +
|
'> <tr>\n' +
|
||||||
' <Row>\n' +
|
'\n in tr (at **)' +
|
||||||
'> <tr>\n' +
|
'\n in Row (at **)' +
|
||||||
'\n in tr (at **)' +
|
'\n in FancyRow (at **)' +
|
||||||
'\n in Row (at **)' +
|
'\n in Viz2 (at **)' +
|
||||||
'\n in FancyRow (at **)' +
|
'\n in App2 (at **)',
|
||||||
'\n in Viz2 (at **)' +
|
'<table> cannot contain a nested <tr>.\n' +
|
||||||
'\n in App2 (at **)',
|
'See this log for the ancestor stack trace.\n' +
|
||||||
'<table> cannot contain a nested <tr>.\n' +
|
' in table (at **)\n' +
|
||||||
'See this log for the ancestor stack trace.\n' +
|
' in Table (at **)\n' +
|
||||||
' in table (at **)\n' +
|
' in FancyTable (at **)\n' +
|
||||||
' in Table (at **)\n' +
|
' in Viz2 (at **)\n' +
|
||||||
' in FancyTable (at **)\n' +
|
' in App2 (at **)',
|
||||||
' 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 **)',
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('gives useful context in warnings 3', async () => {
|
it('gives useful context in warnings 3', async () => {
|
||||||
|
|
@ -2640,47 +2538,26 @@ describe('ReactDOMComponent', () => {
|
||||||
</FancyTable>,
|
</FancyTable>,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev(
|
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' +
|
||||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
'This will cause a hydration error.\n' +
|
||||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
'\n' +
|
||||||
'This will cause a hydration error.\n' +
|
' <FancyTable>\n' +
|
||||||
'\n' +
|
' <Table>\n' +
|
||||||
' <FancyTable>\n' +
|
'> <table>\n' +
|
||||||
' <Table>\n' +
|
' <FancyRow>\n' +
|
||||||
'> <table>\n' +
|
' <Row>\n' +
|
||||||
' <FancyRow>\n' +
|
'> <tr>\n' +
|
||||||
' <Row>\n' +
|
'\n in tr (at **)' +
|
||||||
'> <tr>\n' +
|
'\n in Row (at **)' +
|
||||||
'\n in tr (at **)' +
|
'\n in FancyRow (at **)',
|
||||||
'\n in Row (at **)' +
|
'<table> cannot contain a nested <tr>.\n' +
|
||||||
'\n in FancyRow (at **)',
|
'See this log for the ancestor stack trace.' +
|
||||||
'<table> cannot contain a nested <tr>.\n' +
|
'\n in table (at **)' +
|
||||||
'See this log for the ancestor stack trace.' +
|
'\n in Table (at **)' +
|
||||||
'\n in table (at **)' +
|
'\n in FancyTable (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 **)',
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('gives useful context in warnings 4', async () => {
|
it('gives useful context in warnings 4', async () => {
|
||||||
|
|
@ -2701,39 +2578,22 @@ describe('ReactDOMComponent', () => {
|
||||||
</table>,
|
</table>,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev(
|
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' +
|
||||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
'This will cause a hydration error.\n' +
|
||||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
'\n' +
|
||||||
'This will cause a hydration error.\n' +
|
'> <table>\n' +
|
||||||
'\n' +
|
' <FancyRow>\n' +
|
||||||
'> <table>\n' +
|
' <Row>\n' +
|
||||||
' <FancyRow>\n' +
|
'> <tr>\n' +
|
||||||
' <Row>\n' +
|
'\n in tr (at **)' +
|
||||||
'> <tr>\n' +
|
'\n in Row (at **)' +
|
||||||
'\n in tr (at **)' +
|
'\n in FancyRow (at **)',
|
||||||
'\n in Row (at **)' +
|
'<table> cannot contain a nested <tr>.\n' +
|
||||||
'\n in FancyRow (at **)',
|
'See this log for the ancestor stack trace.' +
|
||||||
'<table> cannot contain a nested <tr>.\n' +
|
'\n in table (at **)',
|
||||||
'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 **)',
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('gives useful context in warnings 5', async () => {
|
it('gives useful context in warnings 5', async () => {
|
||||||
|
|
@ -2758,39 +2618,22 @@ describe('ReactDOMComponent', () => {
|
||||||
</FancyTable>,
|
</FancyTable>,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev(
|
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' +
|
||||||
'In HTML, <tr> cannot be a child of <table>. ' +
|
'This will cause a hydration error.\n' +
|
||||||
'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\n' +
|
'\n' +
|
||||||
'This will cause a hydration error.\n' +
|
' <FancyTable>\n' +
|
||||||
'\n' +
|
' <Table>\n' +
|
||||||
' <FancyTable>\n' +
|
'> <table>\n' +
|
||||||
' <Table>\n' +
|
'> <tr>\n' +
|
||||||
'> <table>\n' +
|
'\n in tr (at **)',
|
||||||
'> <tr>\n' +
|
'<table> cannot contain a nested <tr>.\n' +
|
||||||
'\n in tr (at **)',
|
'See this log for the ancestor stack trace.' +
|
||||||
'<table> cannot contain a nested <tr>.\n' +
|
'\n in table (at **)' +
|
||||||
'See this log for the ancestor stack trace.' +
|
'\n in Table (at **)' +
|
||||||
'\n in table (at **)' +
|
'\n in FancyTable (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 **)',
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
class Link extends React.Component {
|
class Link extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -2807,40 +2650,22 @@ describe('ReactDOMComponent', () => {
|
||||||
</Link>,
|
</Link>,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev(
|
assertConsoleErrorDev([
|
||||||
gate(flags => flags.enableOwnerStacks)
|
'In HTML, <a> cannot be a descendant of <a>.\n' +
|
||||||
? [
|
'This will cause a hydration error.\n' +
|
||||||
'In HTML, <a> cannot be a descendant of <a>.\n' +
|
'\n' +
|
||||||
'This will cause a hydration error.\n' +
|
' <Link>\n' +
|
||||||
'\n' +
|
'> <a>\n' +
|
||||||
' <Link>\n' +
|
' <div>\n' +
|
||||||
'> <a>\n' +
|
' <Link>\n' +
|
||||||
' <div>\n' +
|
'> <a>\n' +
|
||||||
' <Link>\n' +
|
'\n in a (at **)' +
|
||||||
'> <a>\n' +
|
'\n in Link (at **)',
|
||||||
'\n in a (at **)' +
|
'<a> cannot contain a nested <a>.\n' +
|
||||||
'\n in Link (at **)',
|
'See this log for the ancestor stack trace.' +
|
||||||
'<a> cannot contain a nested <a>.\n' +
|
'\n in a (at **)' +
|
||||||
'See this log for the ancestor stack trace.' +
|
'\n in Link (at **)',
|
||||||
'\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 **)',
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should warn about incorrect casing on properties (ssr)', () => {
|
it('should warn about incorrect casing on properties (ssr)', () => {
|
||||||
|
|
@ -3099,11 +2924,9 @@ describe('ReactDOMComponent', () => {
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Invalid DOM property `class`. Did you mean `className`?\n' +
|
'Invalid DOM property `class`. Did you mean `className`?\n' +
|
||||||
' in span (at **)' +
|
' in span (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in div (at **)'),
|
|
||||||
'Invalid event handler property `onclick`. Did you mean `onClick`?\n' +
|
'Invalid event handler property `onclick`. Did you mean `onClick`?\n' +
|
||||||
' in strong (at **)' +
|
' in strong (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in div (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -3119,12 +2942,10 @@ describe('ReactDOMComponent', () => {
|
||||||
);
|
);
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Invalid DOM property `class`. Did you mean `className`?\n' +
|
'Invalid DOM property `class`. Did you mean `className`?\n' +
|
||||||
' in span (at **)' +
|
' in span (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in div (at **)'),
|
|
||||||
'Invalid event handler property `onclick`. ' +
|
'Invalid event handler property `onclick`. ' +
|
||||||
'React events use the camelCase naming convention, for example `onClick`.\n' +
|
'React events use the camelCase naming convention, for example `onClick`.\n' +
|
||||||
' in strong (at **)' +
|
' in strong (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in div (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -3175,12 +2996,10 @@ describe('ReactDOMComponent', () => {
|
||||||
'Invalid DOM property `class`. Did you mean `className`?\n' +
|
'Invalid DOM property `class`. Did you mean `className`?\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
' in Child1 (at **)\n' +
|
' in Child1 (at **)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in div (at **)\n') +
|
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
'Invalid event handler property `onclick`. Did you mean `onClick`?\n' +
|
'Invalid event handler property `onclick`. Did you mean `onClick`?\n' +
|
||||||
' in strong (at **)\n' +
|
' in strong (at **)\n' +
|
||||||
' in Child3 (at **)\n' +
|
' in Child3 (at **)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in div (at **)\n') +
|
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
@ -3230,13 +3049,11 @@ describe('ReactDOMComponent', () => {
|
||||||
'Invalid DOM property `class`. Did you mean `className`?\n' +
|
'Invalid DOM property `class`. Did you mean `className`?\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
' in Child1 (at **)\n' +
|
' in Child1 (at **)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in div (at **)\n') +
|
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
'Invalid event handler property `onclick`. ' +
|
'Invalid event handler property `onclick`. ' +
|
||||||
'React events use the camelCase naming convention, for example `onClick`.\n' +
|
'React events use the camelCase naming convention, for example `onClick`.\n' +
|
||||||
' in strong (at **)\n' +
|
' in strong (at **)\n' +
|
||||||
' in Child3 (at **)\n' +
|
' in Child3 (at **)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in div (at **)\n') +
|
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
@ -3362,8 +3179,7 @@ describe('ReactDOMComponent', () => {
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Invalid DOM property `arabic-form`. Did you mean `arabicForm`?\n' +
|
'Invalid DOM property `arabic-form`. Did you mean `arabicForm`?\n' +
|
||||||
' in text (at **)' +
|
' in text (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in svg (at **)'),
|
|
||||||
]);
|
]);
|
||||||
const text = el.querySelector('text');
|
const text = el.querySelector('text');
|
||||||
|
|
||||||
|
|
@ -3844,8 +3660,7 @@ describe('ReactDOMComponent', () => {
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Invalid DOM property `x-height`. Did you mean `xHeight`?\n' +
|
'Invalid DOM property `x-height`. Did you mean `xHeight`?\n' +
|
||||||
' in font-face (at **)' +
|
' in font-face (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in svg (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(el.querySelector('font-face').hasAttribute('x-height')).toBe(
|
expect(el.querySelector('font-face').hasAttribute('x-height')).toBe(
|
||||||
|
|
@ -3871,8 +3686,7 @@ describe('ReactDOMComponent', () => {
|
||||||
'whatever="false" or whatever={value.toString()}.\n\n' +
|
'whatever="false" or whatever={value.toString()}.\n\n' +
|
||||||
'If you used to conditionally omit it with whatever={condition && value}, ' +
|
'If you used to conditionally omit it with whatever={condition && value}, ' +
|
||||||
'pass whatever={condition ? value : undefined} instead.\n' +
|
'pass whatever={condition ? value : undefined} instead.\n' +
|
||||||
' in font-face (at **)' +
|
' in font-face (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in svg (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(el.querySelector('font-face').hasAttribute('whatever')).toBe(
|
expect(el.querySelector('font-face').hasAttribute('whatever')).toBe(
|
||||||
|
|
|
||||||
|
|
@ -751,7 +751,6 @@ describe('ReactDOMFiber', () => {
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
'Component uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in Component (at **)\n') +
|
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
]);
|
]);
|
||||||
expect(container.innerHTML).toBe('');
|
expect(container.innerHTML).toBe('');
|
||||||
|
|
|
||||||
|
|
@ -386,7 +386,6 @@ describe('ReactDOMFizzForm', () => {
|
||||||
'Cannot specify a formTarget for a button that specifies a function as a formAction. ' +
|
'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' +
|
'The function will always be executed in the same window.\n' +
|
||||||
' in input (at **)\n' +
|
' in input (at **)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in form (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
let root;
|
let root;
|
||||||
|
|
|
||||||
|
|
@ -1843,15 +1843,9 @@ describe('ReactDOMFizzServer', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'<inCorrectTag /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.' +
|
'<inCorrectTag /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.' +
|
||||||
'\n' +
|
'\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in inCorrectTag (at **)\n' +
|
||||||
? ' in inCorrectTag (at **)\n' +
|
' in C (at **)\n' +
|
||||||
' in C (at **)\n' +
|
' in A (at **)',
|
||||||
' in A (at **)'
|
|
||||||
: ' in inCorrectTag (at **)\n' +
|
|
||||||
' in C (at **)\n' +
|
|
||||||
' in Suspense (at **)\n' +
|
|
||||||
' in div (at **)\n' +
|
|
||||||
' in A (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await act(() => {
|
await act(() => {
|
||||||
|
|
@ -1862,17 +1856,11 @@ describe('ReactDOMFizzServer', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Each child in a list should have a unique "key" prop.\n\nCheck the render method of `B`.' +
|
'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' +
|
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in span (at **)\n' +
|
||||||
? ' in span (at **)\n' +
|
' in mapper (at **)\n' +
|
||||||
' in mapper (at **)\n' +
|
' in Array.map (at **)\n' +
|
||||||
' in Array.map (at **)\n' +
|
' in B (at **)\n' +
|
||||||
' in B (at **)\n' +
|
' in A (at **)',
|
||||||
' in A (at **)'
|
|
||||||
: ' in span (at **)\n' +
|
|
||||||
' in B (at **)\n' +
|
|
||||||
' in Suspense (at **)\n' +
|
|
||||||
' in div (at **)\n' +
|
|
||||||
' in A (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(getVisibleChildren(container)).toEqual(
|
expect(getVisibleChildren(container)).toEqual(
|
||||||
|
|
@ -1954,13 +1942,7 @@ describe('ReactDOMFizzServer', () => {
|
||||||
' in TestProvider (at **)',
|
' in TestProvider (at **)',
|
||||||
'TestConsumer uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in TestConsumer (at **)' +
|
' in TestConsumer (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in TestProvider (at **)' +
|
|
||||||
'\n in Suspense (at **)' +
|
|
||||||
'\n in div (at **)' +
|
|
||||||
'\n in TestProvider (at **)'),
|
|
||||||
]);
|
]);
|
||||||
expect(getVisibleChildren(container)).toEqual(
|
expect(getVisibleChildren(container)).toEqual(
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -5871,7 +5853,6 @@ describe('ReactDOMFizzServer', () => {
|
||||||
'If your `children` prop is using this form try rewriting it using a template string: ' +
|
'If your `children` prop is using this form try rewriting it using a template string: ' +
|
||||||
'<title>{`hello ${nameOfUser}`}</title>.\n' +
|
'<title>{`hello ${nameOfUser}`}</title>.\n' +
|
||||||
' in title (at **)\n' +
|
' in title (at **)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in head (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -5917,7 +5898,6 @@ describe('ReactDOMFizzServer', () => {
|
||||||
'React Component try moving the <title> tag into that component. ' +
|
'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' +
|
'If the `children` of <title> is some HTML markup change it to be Text only to be valid HTML.\n' +
|
||||||
' in title (at **)\n' +
|
' in title (at **)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in head (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
// object titles are toStringed when float is on
|
// 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 ' +
|
'string or number value if so. Otherwise implement a `toString` method that React can ' +
|
||||||
'use to produce a valid <title>.\n' +
|
'use to produce a valid <title>.\n' +
|
||||||
' in title (at **)\n' +
|
' in title (at **)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in head (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
// object titles are toStringed when float is on
|
// object titles are toStringed when float is on
|
||||||
|
|
@ -6545,23 +6524,11 @@ describe('ReactDOMFizzServer', () => {
|
||||||
|
|
||||||
assertConsoleErrorDev([
|
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.' +
|
'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(
|
componentStack(['script', 'App']),
|
||||||
gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ['script', 'App']
|
|
||||||
: ['script', 'body', 'html', '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.' +
|
'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(
|
componentStack(['script', 'App']),
|
||||||
gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ['script', 'App']
|
|
||||||
: ['script', 'body', 'html', '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.' +
|
'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(
|
componentStack(['script', 'App']),
|
||||||
gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ['script', 'App']
|
|
||||||
: ['script', 'body', 'html', 'App'],
|
|
||||||
),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -8544,7 +8511,7 @@ describe('ReactDOMFizzServer', () => {
|
||||||
expect(document.body.textContent).toBe('HelloWorld');
|
expect(document.body.textContent).toBe('HelloWorld');
|
||||||
});
|
});
|
||||||
|
|
||||||
// @gate __DEV__ && enableOwnerStacks
|
// @gate __DEV__
|
||||||
it('can get the component owner stacks during rendering in dev', async () => {
|
it('can get the component owner stacks during rendering in dev', async () => {
|
||||||
let stack;
|
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 () => {
|
it('can get the component owner stacks for onError in dev', async () => {
|
||||||
const thrownError = new Error('hi');
|
const thrownError = new Error('hi');
|
||||||
let caughtError;
|
let caughtError;
|
||||||
|
|
@ -9111,56 +9078,30 @@ describe('ReactDOMFizzServer', () => {
|
||||||
</body>
|
</body>
|
||||||
</html>,
|
</html>,
|
||||||
);
|
);
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
assertConsoleErrorDev([
|
||||||
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.',
|
||||||
'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},
|
||||||
{withoutStack: true},
|
],
|
||||||
],
|
'In HTML, <meta> cannot be a child of <html>.\nThis will cause a hydration error.' +
|
||||||
'In HTML, <meta> cannot be a child of <html>.\nThis will cause a hydration error.' +
|
'\n' +
|
||||||
'\n' +
|
'\n <App>' +
|
||||||
'\n <App>' +
|
'\n> <html>' +
|
||||||
'\n> <html>' +
|
'\n <Suspense fallback="this fallb...">' +
|
||||||
'\n <Suspense fallback="this fallb...">' +
|
'\n <meta>' +
|
||||||
'\n <meta>' +
|
'\n> <meta itemProp="" content="before">' +
|
||||||
'\n> <meta itemProp="" content="before">' +
|
'\n ...' +
|
||||||
'\n ...' +
|
'\n' +
|
||||||
'\n' +
|
'\n in meta (at **)' +
|
||||||
'\n in meta (at **)' +
|
'\n in App (at **)',
|
||||||
'\n in App (at **)',
|
'<html> cannot contain a nested <meta>.\nSee this log for the ancestor stack trace.' +
|
||||||
'<html> cannot contain a nested <meta>.\nSee this log for the ancestor stack trace.' +
|
'\n in html (at **)' +
|
||||||
'\n in html (at **)' +
|
'\n in App (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.',
|
||||||
'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},
|
||||||
{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 **)',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
await root.unmount();
|
await root.unmount();
|
||||||
expect(getVisibleChildren(document)).toEqual(
|
expect(getVisibleChildren(document)).toEqual(
|
||||||
|
|
@ -9253,56 +9194,30 @@ describe('ReactDOMFizzServer', () => {
|
||||||
</body>
|
</body>
|
||||||
</html>,
|
</html>,
|
||||||
);
|
);
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
assertConsoleErrorDev([
|
||||||
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.',
|
||||||
'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},
|
||||||
{withoutStack: true},
|
],
|
||||||
],
|
'In HTML, <meta> cannot be a child of <html>.\nThis will cause a hydration error.' +
|
||||||
'In HTML, <meta> cannot be a child of <html>.\nThis will cause a hydration error.' +
|
'\n' +
|
||||||
'\n' +
|
'\n <App>' +
|
||||||
'\n <App>' +
|
'\n> <html>' +
|
||||||
'\n> <html>' +
|
'\n <Suspense fallback="this fallb...">' +
|
||||||
'\n <Suspense fallback="this fallb...">' +
|
'\n <meta>' +
|
||||||
'\n <meta>' +
|
'\n> <meta itemProp="" content="before">' +
|
||||||
'\n> <meta itemProp="" content="before">' +
|
'\n ...' +
|
||||||
'\n ...' +
|
'\n' +
|
||||||
'\n' +
|
'\n in meta (at **)' +
|
||||||
'\n in meta (at **)' +
|
'\n in App (at **)',
|
||||||
'\n in App (at **)',
|
'<html> cannot contain a nested <meta>.\nSee this log for the ancestor stack trace.' +
|
||||||
'<html> cannot contain a nested <meta>.\nSee this log for the ancestor stack trace.' +
|
'\n in html (at **)' +
|
||||||
'\n in html (at **)' +
|
'\n in App (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.',
|
||||||
'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},
|
||||||
{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 **)',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
await root.unmount();
|
await root.unmount();
|
||||||
expect(getVisibleChildren(document)).toEqual(
|
expect(getVisibleChildren(document)).toEqual(
|
||||||
|
|
|
||||||
|
|
@ -529,8 +529,7 @@ describe('ReactDOMFloat', () => {
|
||||||
'> <template>\n' +
|
'> <template>\n' +
|
||||||
' ...\n' +
|
' ...\n' +
|
||||||
'\n' +
|
'\n' +
|
||||||
' in template (at **)' +
|
' in template (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -555,8 +554,7 @@ describe('ReactDOMFloat', () => {
|
||||||
' <body>\n' +
|
' <body>\n' +
|
||||||
'> <style>\n' +
|
'> <style>\n' +
|
||||||
'\n' +
|
'\n' +
|
||||||
' in style (at **)' +
|
' in style (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -596,8 +594,7 @@ describe('ReactDOMFloat', () => {
|
||||||
' <body>\n' +
|
' <body>\n' +
|
||||||
'> <script href="foo">\n' +
|
'> <script href="foo">\n' +
|
||||||
'\n' +
|
'\n' +
|
||||||
' in script (at **)' +
|
' in script (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -2269,21 +2266,11 @@ body {
|
||||||
'spell it as lowercase `nonstandardattr` instead. If you accidentally passed it from a ' +
|
'spell it as lowercase `nonstandardattr` instead. If you accidentally passed it from a ' +
|
||||||
'parent component, remove it from the DOM element.\n' +
|
'parent component, remove it from the DOM element.\n' +
|
||||||
' in link (at **)\n' +
|
' in link (at **)\n' +
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: ' in div (at **)\n' +
|
|
||||||
' in body (at **)\n' +
|
|
||||||
' in html (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
'Invalid values for props `shouldnotincludefunctions`, `norsymbols` on <link> tag. ' +
|
'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. ' +
|
'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' +
|
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||||
' in link (at **)\n' +
|
' in link (at **)\n' +
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: ' in div (at **)\n' +
|
|
||||||
' in body (at **)\n' +
|
|
||||||
' in html (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -2642,8 +2629,7 @@ body {
|
||||||
'> <html>\n' +
|
'> <html>\n' +
|
||||||
'> <meta itemProp="foo">' +
|
'> <meta itemProp="foo">' +
|
||||||
'\n' +
|
'\n' +
|
||||||
'\n in meta (at **)' +
|
'\n in meta (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -2668,8 +2654,7 @@ body {
|
||||||
'> <html>\n' +
|
'> <html>\n' +
|
||||||
'> <title itemProp="foo">' +
|
'> <title itemProp="foo">' +
|
||||||
'\n' +
|
'\n' +
|
||||||
'\n in title (at **)' +
|
'\n in title (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -2694,8 +2679,7 @@ body {
|
||||||
'> <html>\n' +
|
'> <html>\n' +
|
||||||
'> <style itemProp="foo">' +
|
'> <style itemProp="foo">' +
|
||||||
'\n' +
|
'\n' +
|
||||||
'\n in style (at **)' +
|
'\n in style (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -2720,8 +2704,7 @@ body {
|
||||||
'> <html>\n' +
|
'> <html>\n' +
|
||||||
'> <link itemProp="foo">\n' +
|
'> <link itemProp="foo">\n' +
|
||||||
'\n' +
|
'\n' +
|
||||||
' in link (at **)' +
|
' in link (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -2746,8 +2729,7 @@ body {
|
||||||
'> <html>\n' +
|
'> <html>\n' +
|
||||||
'> <script itemProp="foo">\n' +
|
'> <script itemProp="foo">\n' +
|
||||||
'\n' +
|
'\n' +
|
||||||
' in script (at **)' +
|
' in script (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -4844,9 +4826,6 @@ body {
|
||||||
'React encountered a hoistable style tag for the same href as a preload: "foo". ' +
|
'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' +
|
'When using a style tag to inline styles you should not also preload it as a stylsheet.\n' +
|
||||||
' in style (at **)\n' +
|
' in style (at **)\n' +
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: ' in body (at **)\n' + ' in html (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -7753,64 +7732,43 @@ body {
|
||||||
'If your intent was to have React hoist and deduplciate this stylesheet using the ' +
|
'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, ' +
|
'`precedence` prop ensure there is a non-empty string `href` prop as well, ' +
|
||||||
'otherwise remove the `precedence` prop.\n' +
|
'otherwise remove the `precedence` prop.\n' +
|
||||||
' in link (at **)' +
|
' in link (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in body (at **)' + '\n in html (at **)'),
|
|
||||||
'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and ' +
|
'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. ' +
|
'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 ' +
|
'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, ' +
|
'`precedence` prop ensure there is a non-empty string `href` prop as well, ' +
|
||||||
'otherwise remove the `precedence` prop.\n' +
|
'otherwise remove the `precedence` prop.\n' +
|
||||||
' in link (at **)' +
|
' in link (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in body (at **)' + '\n in html (at **)'),
|
|
||||||
'An empty string ("") was passed to the href attribute. ' +
|
'An empty string ("") was passed to the href attribute. ' +
|
||||||
'To fix this, either do not render the element at all or ' +
|
'To fix this, either do not render the element at all or ' +
|
||||||
'pass null to href instead of an empty string.\n' +
|
'pass null to href instead of an empty string.\n' +
|
||||||
' in link (at **)' +
|
' in link (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in body (at **)' + '\n in html (at **)'),
|
|
||||||
'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and ' +
|
'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and ' +
|
||||||
'`onLoad` and `onError` props. The presence of loading and error handlers indicates ' +
|
'`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 ' +
|
'an intent to manage the stylesheet loading state from your from your Component code ' +
|
||||||
'and React will not hoist or deduplicate this stylesheet. ' +
|
'and React will not hoist or deduplicate this stylesheet. ' +
|
||||||
'If your intent was to have React hoist and deduplciate this stylesheet using the ' +
|
'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' +
|
'`precedence` prop remove the `onLoad` and `onError` props, otherwise remove the `precedence` prop.\n' +
|
||||||
' in link (at **)' +
|
' in link (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in body (at **)' + '\n in html (at **)'),
|
|
||||||
'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and ' +
|
'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and ' +
|
||||||
'`onLoad` prop. The presence of loading and error handlers indicates an intent to ' +
|
'`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 ' +
|
'manage the stylesheet loading state from your from your Component code and ' +
|
||||||
'React will not hoist or deduplicate this stylesheet. ' +
|
'React will not hoist or deduplicate this stylesheet. ' +
|
||||||
'If your intent was to have React hoist and deduplciate this stylesheet using the ' +
|
'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' +
|
'`precedence` prop remove the `onLoad` prop, otherwise remove the `precedence` prop.\n' +
|
||||||
' in link (at **)' +
|
' in link (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in body (at **)' + '\n in html (at **)'),
|
|
||||||
'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and `onError` prop. ' +
|
'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 ' +
|
'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. ' +
|
'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` ' +
|
'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' +
|
'prop remove the `onError` prop, otherwise remove the `precedence` prop.\n' +
|
||||||
' in link (at **)' +
|
' in link (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in body (at **)' + '\n in html (at **)'),
|
|
||||||
'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and a `disabled` prop. ' +
|
'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 ' +
|
'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. ' +
|
'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` ' +
|
'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' +
|
'prop remove the `disabled` prop, otherwise remove the `precedence` prop.\n' +
|
||||||
' in link (at **)' +
|
' in link (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in body (at **)' + '\n in html (at **)'),
|
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -7836,8 +7794,7 @@ body {
|
||||||
'loading state from your from your Component code and React will not hoist or deduplicate this 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` ' +
|
'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' +
|
'prop remove the `onLoad` and `onError` props, otherwise remove the `precedence` prop.\n' +
|
||||||
' in body (at **)' +
|
' in body (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -8429,10 +8386,7 @@ background-color: green;
|
||||||
'using the `precedence` prop to not have any spaces but ecountered spaces instead. ' +
|
'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. ' +
|
'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' +
|
'The href for the <style> where this ocurred is "foo bar".\n' +
|
||||||
' in style (at **)' +
|
' in style (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in body (at **)' + '\n in html (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -391,8 +391,7 @@ describe('ReactDOMForm', () => {
|
||||||
'> <form action={function outerAction}>\n' +
|
'> <form action={function outerAction}>\n' +
|
||||||
' <input>\n' +
|
' <input>\n' +
|
||||||
'> <form action={function innerAction} ref={{current:null}}>\n' +
|
'> <form action={function innerAction} ref={{current:null}}>\n' +
|
||||||
'\n in form (at **)' +
|
'\n in form (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in form (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await submit(ref.current);
|
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. ' +
|
'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. ' +
|
'React needs it to encode which action should be invoked. ' +
|
||||||
'It will get overridden.\n' +
|
'It will get overridden.\n' +
|
||||||
' in input (at **)' +
|
' in input (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in form (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await submit(inputRef.current);
|
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. ' +
|
'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' +
|
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||||
' in button (at **)\n' +
|
' in button (at **)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in form (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
await submit(buttonRef.current);
|
await submit(buttonRef.current);
|
||||||
|
|
|
||||||
|
|
@ -59,10 +59,7 @@ describe('ReactDOMOption', () => {
|
||||||
'> <div>\n' +
|
'> <div>\n' +
|
||||||
' ...\n' +
|
' ...\n' +
|
||||||
'\n' +
|
'\n' +
|
||||||
' in div (at **)' +
|
' in div (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: '\n in option (at **)'),
|
|
||||||
]);
|
]);
|
||||||
expect(container.firstChild.innerHTML).toBe('1 <div></div> 2');
|
expect(container.firstChild.innerHTML).toBe('1 <div></div> 2');
|
||||||
await renderIntoDocument(el);
|
await renderIntoDocument(el);
|
||||||
|
|
@ -279,10 +276,7 @@ describe('ReactDOMOption', () => {
|
||||||
'> <div ref={{current:null}}>\n' +
|
'> <div ref={{current:null}}>\n' +
|
||||||
' ...\n' +
|
' ...\n' +
|
||||||
'\n' +
|
'\n' +
|
||||||
' in div (at **)' +
|
' in div (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: '\n in option (at **)' + '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
option = container.firstChild.firstChild;
|
option = container.firstChild.firstChild;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -794,7 +794,6 @@ describe('ReactDOMSelect', () => {
|
||||||
'Use the `defaultValue` or `value` props on <select> instead of ' +
|
'Use the `defaultValue` or `value` props on <select> instead of ' +
|
||||||
'setting `selected` on <option>.\n' +
|
'setting `selected` on <option>.\n' +
|
||||||
' in option (at **)\n' +
|
' in option (at **)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in select (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -1072,8 +1071,7 @@ describe('ReactDOMSelect', () => {
|
||||||
'Invalid value for prop `value` on <option> tag. ' +
|
'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. ' +
|
'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' +
|
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const node = container.firstChild;
|
const node = container.firstChild;
|
||||||
|
|
@ -1096,8 +1094,7 @@ describe('ReactDOMSelect', () => {
|
||||||
'Invalid value for prop `value` on <option> tag. ' +
|
'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. ' +
|
'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' +
|
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let node = container.firstChild;
|
let node = container.firstChild;
|
||||||
|
|
@ -1134,8 +1131,7 @@ describe('ReactDOMSelect', () => {
|
||||||
'Invalid value for prop `value` on <option> tag. ' +
|
'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. ' +
|
'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' +
|
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const node = container.firstChild;
|
const node = container.firstChild;
|
||||||
|
|
@ -1158,8 +1154,7 @@ describe('ReactDOMSelect', () => {
|
||||||
'Invalid value for prop `value` on <option> tag. ' +
|
'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. ' +
|
'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' +
|
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let node = container.firstChild;
|
let node = container.firstChild;
|
||||||
|
|
@ -1199,8 +1194,7 @@ describe('ReactDOMSelect', () => {
|
||||||
'Invalid value for prop `value` on <option> tag. ' +
|
'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. ' +
|
'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' +
|
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const node = container.firstChild;
|
const node = container.firstChild;
|
||||||
|
|
@ -1223,8 +1217,7 @@ describe('ReactDOMSelect', () => {
|
||||||
'Invalid value for prop `value` on <option> tag. ' +
|
'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. ' +
|
'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' +
|
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const node = container.firstChild;
|
const node = container.firstChild;
|
||||||
|
|
@ -1247,8 +1240,7 @@ describe('ReactDOMSelect', () => {
|
||||||
'Invalid value for prop `value` on <option> tag. ' +
|
'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. ' +
|
'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' +
|
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let node = container.firstChild;
|
let node = container.firstChild;
|
||||||
|
|
@ -1284,8 +1276,7 @@ describe('ReactDOMSelect', () => {
|
||||||
'Invalid value for prop `value` on <option> tag. ' +
|
'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. ' +
|
'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' +
|
'For details, see https://react.dev/link/attribute-behavior \n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let node = container.firstChild;
|
let node = container.firstChild;
|
||||||
|
|
@ -1366,12 +1357,10 @@ describe('ReactDOMSelect', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||||
' This value must be coerced to a string before using it here.\n' +
|
' This value must be coerced to a string before using it here.\n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||||
' This value must be coerced to a string before using it here.\n' +
|
' This value must be coerced to a string before using it here.\n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1395,12 +1384,10 @@ describe('ReactDOMSelect', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||||
' This value must be coerced to a string before using it here.\n' +
|
' This value must be coerced to a string before using it here.\n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||||
' This value must be coerced to a string before using it here.\n' +
|
' This value must be coerced to a string before using it here.\n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1467,8 +1454,7 @@ describe('ReactDOMSelect', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||||
' This value must be coerced to a string before using it here.\n' +
|
' This value must be coerced to a string before using it here.\n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1508,8 +1494,7 @@ describe('ReactDOMSelect', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||||
' This value must be coerced to a string before using it here.\n' +
|
' This value must be coerced to a string before using it here.\n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
'Form field values (value, checked, defaultValue, or defaultChecked props)' +
|
'Form field values (value, checked, defaultValue, or defaultChecked props)' +
|
||||||
' must be strings, not TemporalLike. ' +
|
' must be strings, not TemporalLike. ' +
|
||||||
'This value must be coerced to a string before using it here.\n' +
|
'This value must be coerced to a string before using it here.\n' +
|
||||||
|
|
@ -1563,12 +1548,10 @@ describe('ReactDOMSelect', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||||
' This value must be coerced to a string before using it here.\n' +
|
' This value must be coerced to a string before using it here.\n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||||
' This value must be coerced to a string before using it here.\n' +
|
' This value must be coerced to a string before using it here.\n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1591,12 +1574,10 @@ describe('ReactDOMSelect', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||||
' This value must be coerced to a string before using it here.\n' +
|
' This value must be coerced to a string before using it here.\n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||||
' This value must be coerced to a string before using it here.\n' +
|
' This value must be coerced to a string before using it here.\n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1670,12 +1651,10 @@ describe('ReactDOMSelect', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||||
' This value must be coerced to a string before using it here.\n' +
|
' This value must be coerced to a string before using it here.\n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
'The provided `value` attribute is an unsupported type TemporalLike.' +
|
||||||
' This value must be coerced to a string before using it here.\n' +
|
' This value must be coerced to a string before using it here.\n' +
|
||||||
' in option (at **)' +
|
' in option (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in select (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -995,18 +995,6 @@ describe('ReactDOMServerIntegration', () => {
|
||||||
async render => {
|
async render => {
|
||||||
let EmptyComponent = {};
|
let EmptyComponent = {};
|
||||||
EmptyComponent = <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);
|
await render(EmptyComponent);
|
||||||
},
|
},
|
||||||
'Element type is invalid: expected a string (for built-in components) or a class/function ' +
|
'Element type is invalid: expected a string (for built-in components) or a class/function ' +
|
||||||
|
|
@ -1022,16 +1010,6 @@ describe('ReactDOMServerIntegration', () => {
|
||||||
async render => {
|
async render => {
|
||||||
let NullComponent = null;
|
let NullComponent = null;
|
||||||
NullComponent = <NullComponent />;
|
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);
|
await render(NullComponent);
|
||||||
},
|
},
|
||||||
'Element type is invalid: expected a string (for built-in components) or a class/function ' +
|
'Element type is invalid: expected a string (for built-in components) or a class/function ' +
|
||||||
|
|
@ -1043,19 +1021,6 @@ describe('ReactDOMServerIntegration', () => {
|
||||||
async render => {
|
async render => {
|
||||||
let UndefinedComponent = undefined;
|
let UndefinedComponent = undefined;
|
||||||
UndefinedComponent = <UndefinedComponent />;
|
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);
|
await render(UndefinedComponent);
|
||||||
},
|
},
|
||||||
'Element type is invalid: expected a string (for built-in components) or a class/function ' +
|
'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 ' +
|
'usually means you called setState() outside componentWillMount() on ' +
|
||||||
'the server. This is a no-op.\n\n' +
|
'the server. This is a no-op.\n\n' +
|
||||||
'Please check the code for the Outer component.\n' +
|
'Please check the code for the Outer component.\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in Inner (at **)\n') +
|
|
||||||
' in Outer (at **)',
|
' in Outer (at **)',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1923,11 +1923,6 @@ describe('ReactDOMServerPartialHydration', () => {
|
||||||
"Can't perform a React state update on a component that hasn't mounted yet. " +
|
"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 ' +
|
'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' +
|
'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 **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -171,8 +171,7 @@ describe('ReactDOM HostSingleton', () => {
|
||||||
'children of these components will likely fail in unpredictable ways. ' +
|
'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, ' +
|
'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' +
|
'ensure any previous ones have unmounted first.\n' +
|
||||||
' in head (at **)' +
|
' in head (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in html (at **)'),
|
|
||||||
]);
|
]);
|
||||||
expect(getVisibleChildren(document)).toEqual(
|
expect(getVisibleChildren(document)).toEqual(
|
||||||
<html>
|
<html>
|
||||||
|
|
|
||||||
|
|
@ -60,11 +60,13 @@ describe('ReactDeprecationWarnings', () => {
|
||||||
</div>,
|
</div>,
|
||||||
);
|
);
|
||||||
await waitForAll([]);
|
await waitForAll([]);
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev(
|
||||||
'FunctionalComponent: Support for defaultProps ' +
|
[
|
||||||
'will be removed from memo components in a future major ' +
|
'FunctionalComponent: Support for defaultProps ' +
|
||||||
'release. Use JavaScript default parameters instead.\n' +
|
'will be removed from memo components in a future major ' +
|
||||||
' in div (at **)',
|
'release. Use JavaScript default parameters instead.',
|
||||||
]);
|
],
|
||||||
|
{withoutStack: true},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2381,17 +2381,6 @@ describe('ReactErrorBoundaries', () => {
|
||||||
'class/function (for composite components) but got: null.',
|
'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 () => {
|
await expect(async () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
const root = ReactDOMClient.createRoot(container);
|
const root = ReactDOMClient.createRoot(container);
|
||||||
|
|
@ -2403,18 +2392,6 @@ describe('ReactErrorBoundaries', () => {
|
||||||
'expected a string (for built-in components) or a ' +
|
'expected a string (for built-in components) or a ' +
|
||||||
'class/function (for composite components) but got: undefined.',
|
'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 () => {
|
it('renders empty output if error boundary does not handle the error', async () => {
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,6 @@ describe('ReactFunctionComponent', () => {
|
||||||
' in GrandParent (at **)',
|
' in GrandParent (at **)',
|
||||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'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 Parent (at **)\n' +
|
||||||
' in GrandParent (at **)',
|
' in GrandParent (at **)',
|
||||||
]);
|
]);
|
||||||
|
|
@ -260,7 +259,6 @@ describe('ReactFunctionComponent', () => {
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
'Child uses the legacy contextTypes API which will be removed soon. ' +
|
'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' +
|
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in Child (at **)\n' +
|
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
]);
|
]);
|
||||||
expect(el.textContent).toBe('en');
|
expect(el.textContent).toBe('en');
|
||||||
|
|
|
||||||
|
|
@ -121,13 +121,9 @@ describe('ReactLegacyCompositeComponent', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Child uses the legacy childContextTypes API which will soon be removed. ' +
|
'Child uses the legacy childContextTypes API which will soon be removed. ' +
|
||||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in Child (at **)\n') +
|
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
'Grandchild uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'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 **)',
|
' in Parent (at **)',
|
||||||
]);
|
]);
|
||||||
expect(findDOMNode(component).innerHTML).toBe('bar');
|
expect(findDOMNode(component).innerHTML).toBe('bar');
|
||||||
|
|
@ -200,10 +196,7 @@ describe('ReactLegacyCompositeComponent', () => {
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in Child (at **)' +
|
' in Child (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in Middle (at **)' + '\n in Parent (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await act(() => {
|
await act(() => {
|
||||||
|
|
@ -268,15 +261,9 @@ describe('ReactLegacyCompositeComponent', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Parent uses the legacy childContextTypes API which will soon be removed. ' +
|
'Parent uses the legacy childContextTypes API which will soon be removed. ' +
|
||||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in Parent (at **)\n') +
|
|
||||||
' in Wrapper (at **)',
|
' in Wrapper (at **)',
|
||||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'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 **)',
|
' in Wrapper (at **)',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -361,15 +348,12 @@ describe('ReactLegacyCompositeComponent', () => {
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
'Child uses the legacy childContextTypes API which will soon be removed. ' +
|
'Child uses the legacy childContextTypes API which will soon be removed. ' +
|
||||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in Child (at **)\n') +
|
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in Child (at **)\n') +
|
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
'Grandchild uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'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 Child (at **)\n' +
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
]);
|
]);
|
||||||
|
|
@ -441,7 +425,6 @@ describe('ReactLegacyCompositeComponent', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in Child (at **)\n') +
|
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,16 +104,10 @@ describe('ReactLegacyContextDisabled', () => {
|
||||||
' in LegacyProvider (at **)',
|
' in LegacyProvider (at **)',
|
||||||
'LegacyClsConsumer uses the legacy contextTypes API which was removed in React 19. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in LegacyClsConsumer (at **)' +
|
' in LegacyClsConsumer (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n' + ' in span (at **)\n' + ' in LegacyProvider (at **)'),
|
|
||||||
'LegacyFnConsumer uses the legacy contextTypes API which was removed in React 19. ' +
|
'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' +
|
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in LegacyFnConsumer (at **)' +
|
' in LegacyFnConsumer (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n' + ' in span (at **)\n' + ' in LegacyProvider (at **)'),
|
|
||||||
]);
|
]);
|
||||||
expect(container.textContent).toBe('{}undefinedundefined');
|
expect(container.textContent).toBe('{}undefinedundefined');
|
||||||
expect(lifecycleContextLog).toEqual([]);
|
expect(lifecycleContextLog).toEqual([]);
|
||||||
|
|
@ -151,16 +145,10 @@ describe('ReactLegacyContextDisabled', () => {
|
||||||
' in LegacyProvider (at **)',
|
' in LegacyProvider (at **)',
|
||||||
'LegacyClsConsumer uses the legacy contextTypes API which was removed in React 19. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in LegacyClsConsumer (at **)' +
|
' in LegacyClsConsumer (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n' + ' in span (at **)\n' + ' in LegacyProvider (at **)'),
|
|
||||||
'LegacyFnConsumer uses the legacy contextTypes API which was removed in React 19. ' +
|
'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' +
|
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in LegacyFnConsumer (at **)' +
|
' in LegacyFnConsumer (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n' + ' in span (at **)\n' + ' in LegacyProvider (at **)'),
|
|
||||||
]);
|
]);
|
||||||
expect(text).toBe('<span>{}<!-- -->undefined<!-- -->undefined</span>');
|
expect(text).toBe('<span>{}<!-- -->undefined<!-- -->undefined</span>');
|
||||||
expect(lifecycleContextLog).toEqual([{}, {}, {}]);
|
expect(lifecycleContextLog).toEqual([{}, {}, {}]);
|
||||||
|
|
|
||||||
|
|
@ -2112,16 +2112,6 @@ describe('ReactLegacyErrorBoundaries', () => {
|
||||||
ReactDOM.render(<X />, container);
|
ReactDOM.render(<X />, container);
|
||||||
});
|
});
|
||||||
}).rejects.toThrow('got: null');
|
}).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 () => {
|
await expect(async () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
|
|
@ -2129,16 +2119,6 @@ describe('ReactLegacyErrorBoundaries', () => {
|
||||||
ReactDOM.render(<Y />, container);
|
ReactDOM.render(<Y />, container);
|
||||||
});
|
});
|
||||||
}).rejects.toThrow('got: undefined');
|
}).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
|
// @gate !disableLegacyMode
|
||||||
|
|
|
||||||
|
|
@ -228,13 +228,7 @@ describe('ReactMultiChild', () => {
|
||||||
'across updates. Non-unique keys may cause children to be ' +
|
'across updates. Non-unique keys may cause children to be ' +
|
||||||
'duplicated and/or omitted — the behavior is unsupported and ' +
|
'duplicated and/or omitted — the behavior is unsupported and ' +
|
||||||
'could change in a future version.\n' +
|
'could change in a future version.\n' +
|
||||||
' in div (at **)' +
|
' in div (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: '\n in div (at **)' +
|
|
||||||
'\n in WrapperComponent (at **)' +
|
|
||||||
'\n in div (at **)' +
|
|
||||||
'\n in Parent (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -290,13 +284,7 @@ describe('ReactMultiChild', () => {
|
||||||
'across updates. Non-unique keys may cause children to be ' +
|
'across updates. Non-unique keys may cause children to be ' +
|
||||||
'duplicated and/or omitted — the behavior is unsupported and ' +
|
'duplicated and/or omitted — the behavior is unsupported and ' +
|
||||||
'could change in a future version.\n' +
|
'could change in a future version.\n' +
|
||||||
' in div (at **)' +
|
' in div (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: '\n in div (at **)' +
|
|
||||||
'\n in WrapperComponent (at **)' +
|
|
||||||
'\n in div (at **)' +
|
|
||||||
'\n in Parent (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -758,20 +758,12 @@ describe('ReactDOMServer', () => {
|
||||||
'<inPUT /> is using incorrect casing. ' +
|
'<inPUT /> is using incorrect casing. ' +
|
||||||
'Use PascalCase for React components, ' +
|
'Use PascalCase for React components, ' +
|
||||||
'or lowercase for HTML elements.\n' +
|
'or lowercase for HTML elements.\n' +
|
||||||
' in inPUT (at **)' +
|
' in inPUT (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in div (at **)'),
|
|
||||||
// linearGradient doesn't warn
|
// linearGradient doesn't warn
|
||||||
'<iFrame /> is using incorrect casing. ' +
|
'<iFrame /> is using incorrect casing. ' +
|
||||||
'Use PascalCase for React components, ' +
|
'Use PascalCase for React components, ' +
|
||||||
'or lowercase for HTML elements.\n' +
|
'or lowercase for HTML elements.\n' +
|
||||||
' in iFrame (at **)' +
|
' 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 **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -869,30 +861,14 @@ describe('ReactDOMServer', () => {
|
||||||
ReactDOMServer.renderToString(<App />);
|
ReactDOMServer.renderToString(<App />);
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Invalid ARIA attribute `ariaTypo`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
'Invalid ARIA attribute `ariaTypo`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in span (at **)\n' +
|
||||||
? ' in span (at **)\n' +
|
' in B (at **)\n' +
|
||||||
' in B (at **)\n' +
|
' in Child (at **)\n' +
|
||||||
' in Child (at **)\n' +
|
' in App (at **)',
|
||||||
' 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 **)'),
|
|
||||||
'Invalid ARIA attribute `ariaTypo2`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
'Invalid ARIA attribute `ariaTypo2`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in span (at **)\n' +
|
||||||
? ' in span (at **)\n' +
|
' in Child (at **)\n' +
|
||||||
' in Child (at **)\n' +
|
' in App (at **)',
|
||||||
' in App (at **)'
|
|
||||||
: ' in span (at **)\n' +
|
|
||||||
' in Child (at **)\n' +
|
|
||||||
' in span (at **)\n' +
|
|
||||||
' in div (at **)\n' +
|
|
||||||
' in App (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -929,47 +905,30 @@ describe('ReactDOMServer', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
// ReactDOMServer(App > div > span)
|
// ReactDOMServer(App > div > span)
|
||||||
'Invalid ARIA attribute `ariaTypo`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
'Invalid ARIA attribute `ariaTypo`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in span (at **)\n' +
|
||||||
? ' in span (at **)\n' + ' in App (at **)'
|
' in App (at **)',
|
||||||
: ' in span (at **)\n' +
|
|
||||||
' in div (at **)\n' +
|
|
||||||
' in App (at **)'),
|
|
||||||
// ReactDOMServer(App > div > Child) >>> ReactDOMServer(App2) >>> ReactDOMServer(blink)
|
// ReactDOMServer(App > div > Child) >>> ReactDOMServer(App2) >>> ReactDOMServer(blink)
|
||||||
'Invalid ARIA attribute `ariaTypo2`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
'Invalid ARIA attribute `ariaTypo2`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in blink (at **)\n' +
|
||||||
? ' in blink (at **)\n' +
|
' in App2 (at **)\n' +
|
||||||
' in App2 (at **)\n' +
|
' in Child (at **)\n' +
|
||||||
' in Child (at **)\n' +
|
' in App (at **)',
|
||||||
' in App (at **)'
|
|
||||||
: ' in blink (at **)'),
|
|
||||||
// ReactDOMServer(App > div > Child) >>> ReactDOMServer(App2 > Child2 > span)
|
// ReactDOMServer(App > div > Child) >>> ReactDOMServer(App2 > Child2 > span)
|
||||||
'Invalid ARIA attribute `ariaTypo3`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
'Invalid ARIA attribute `ariaTypo3`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in span (at **)\n' +
|
||||||
? ' in span (at **)\n' +
|
' in Child2 (at **)\n' +
|
||||||
' in Child2 (at **)\n' +
|
' in App2 (at **)\n' +
|
||||||
' in App2 (at **)\n' +
|
' in Child (at **)\n' +
|
||||||
' in Child (at **)\n' +
|
' in App (at **)',
|
||||||
' in App (at **)'
|
|
||||||
: ' in span (at **)\n' +
|
|
||||||
' in Child2 (at **)\n' +
|
|
||||||
' in App2 (at **)'),
|
|
||||||
// ReactDOMServer(App > div > Child > span)
|
// ReactDOMServer(App > div > Child > span)
|
||||||
'Invalid ARIA attribute `ariaTypo4`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
'Invalid ARIA attribute `ariaTypo4`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in span (at **)\n' +
|
||||||
? ' in span (at **)\n' +
|
' in Child (at **)\n' +
|
||||||
' in Child (at **)\n' +
|
' in App (at **)',
|
||||||
' in App (at **)'
|
|
||||||
: ' in span (at **)\n' +
|
|
||||||
' in Child (at **)\n' +
|
|
||||||
' in div (at **)\n' +
|
|
||||||
' in App (at **)'),
|
|
||||||
// ReactDOMServer(App > div > font)
|
// ReactDOMServer(App > div > font)
|
||||||
'Invalid ARIA attribute `ariaTypo5`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
'Invalid ARIA attribute `ariaTypo5`. ARIA attributes follow the pattern aria-* and must be lowercase.\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in font (at **)\n' +
|
||||||
? ' in font (at **)\n' + ' in App (at **)'
|
' in App (at **)',
|
||||||
: ' in font (at **)\n' +
|
|
||||||
' in div (at **)\n' +
|
|
||||||
' in App (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1877,9 +1877,7 @@ describe('ReactUpdates', () => {
|
||||||
const originalConsoleError = console.error;
|
const originalConsoleError = console.error;
|
||||||
console.error = e => {
|
console.error = e => {
|
||||||
error = e;
|
error = e;
|
||||||
ownerStack = gate(flags => flags.enableOwnerStacks)
|
ownerStack = React.captureOwnerStack();
|
||||||
? React.captureOwnerStack()
|
|
||||||
: null;
|
|
||||||
debugStack = new Error().stack;
|
debugStack = new Error().stack;
|
||||||
Scheduler.log('stop');
|
Scheduler.log('stop');
|
||||||
};
|
};
|
||||||
|
|
@ -1895,11 +1893,7 @@ describe('ReactUpdates', () => {
|
||||||
expect(error).toContain('Maximum update depth exceeded');
|
expect(error).toContain('Maximum update depth exceeded');
|
||||||
// The currently executing effect should be on the native stack
|
// The currently executing effect should be on the native stack
|
||||||
expect(debugStack).toContain('at myEffect');
|
expect(debugStack).toContain('at myEffect');
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
expect(ownerStack).toContain('at App');
|
||||||
expect(ownerStack).toContain('at App');
|
|
||||||
} else {
|
|
||||||
expect(ownerStack).toBe(null);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can have nested updates if they do not cross the limit', async () => {
|
it('can have nested updates if they do not cross the limit', async () => {
|
||||||
|
|
|
||||||
|
|
@ -121,34 +121,20 @@ describe('validateDOMNesting', () => {
|
||||||
);
|
);
|
||||||
expectWarnings(
|
expectWarnings(
|
||||||
['div', 'ul', 'li', 'div', 'li'],
|
['div', 'ul', 'li', 'div', 'li'],
|
||||||
gate(flags => flags.enableOwnerStacks)
|
|
||||||
? [
|
[
|
||||||
'In HTML, <li> cannot be a descendant of <li>.\n' +
|
'In HTML, <li> cannot be a descendant of <li>.\n' +
|
||||||
'This will cause a hydration error.\n' +
|
'This will cause a hydration error.\n' +
|
||||||
'\n' +
|
'\n' +
|
||||||
' <ul>\n' +
|
' <ul>\n' +
|
||||||
'> <li>\n' +
|
'> <li>\n' +
|
||||||
' <div>\n' +
|
' <div>\n' +
|
||||||
'> <li>\n' +
|
'> <li>\n' +
|
||||||
'\n' +
|
'\n' +
|
||||||
' in li (at **)',
|
' in li (at **)',
|
||||||
'<li> cannot contain a nested <li>.\nSee this log for the ancestor stack trace.\n' +
|
'<li> cannot contain a nested <li>.\nSee this log for the ancestor stack trace.\n' +
|
||||||
' in li (at **)',
|
' 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 **)',
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
expectWarnings(
|
expectWarnings(
|
||||||
['div', 'html'],
|
['div', 'html'],
|
||||||
|
|
@ -208,28 +194,16 @@ describe('validateDOMNesting', () => {
|
||||||
);
|
);
|
||||||
expectWarnings(
|
expectWarnings(
|
||||||
['svg', 'foreignObject', 'body', 'p'],
|
['svg', 'foreignObject', 'body', 'p'],
|
||||||
gate(flags => flags.enableOwnerStacks)
|
[
|
||||||
? [
|
// TODO, this should say "In SVG",
|
||||||
// TODO, this should say "In SVG",
|
'In HTML, <body> cannot be a child of <foreignObject>.\n' +
|
||||||
'In HTML, <body> cannot be a child of <foreignObject>.\n' +
|
'This will cause a hydration error.\n' +
|
||||||
'This will cause a hydration error.\n' +
|
'\n' +
|
||||||
'\n' +
|
'> <foreignObject>\n' +
|
||||||
'> <foreignObject>\n' +
|
'> <body>\n' +
|
||||||
'> <body>\n' +
|
'\n' +
|
||||||
'\n' +
|
' in body (at **)',
|
||||||
' 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 **)',
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -233,9 +233,7 @@ if (!__EXPERIMENTAL__) {
|
||||||
'\n in div (at **)',
|
'\n in div (at **)',
|
||||||
);
|
);
|
||||||
expect(normalizeCodeLocInfo(caughtErrors[0].ownerStack)).toBe(
|
expect(normalizeCodeLocInfo(caughtErrors[0].ownerStack)).toBe(
|
||||||
__DEV__ && gate(flags => flags.enableOwnerStacks)
|
__DEV__ ? '\n in Bar (at **)' + '\n in Foo (at **)' : null,
|
||||||
? '\n in Bar (at **)' + '\n in Foo (at **)'
|
|
||||||
: null,
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -269,9 +269,7 @@ if (!__EXPERIMENTAL__) {
|
||||||
: '\n in div (at **)' + '\n in div (at **)',
|
: '\n in div (at **)' + '\n in div (at **)',
|
||||||
);
|
);
|
||||||
expect(normalizeCodeLocInfo(caughtErrors[0].ownerStack)).toBe(
|
expect(normalizeCodeLocInfo(caughtErrors[0].ownerStack)).toBe(
|
||||||
__DEV__ && gate(flags => flags.enableOwnerStacks)
|
__DEV__ ? '\n in Bar (at **)' + '\n in Foo (at **)' : null,
|
||||||
? '\n in Bar (at **)' + '\n in Foo (at **)'
|
|
||||||
: null,
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -875,10 +875,7 @@ describe('ReactFabric', () => {
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Text strings must be rendered within a <Text> component.\n' +
|
'Text strings must be rendered within a <Text> component.\n' +
|
||||||
' in RCTScrollView (at **)' +
|
' in RCTScrollView (at **)',
|
||||||
(gate(flags => !flags.enableOwnerStacks)
|
|
||||||
? '\n in RCTText (at **)'
|
|
||||||
: ''),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@
|
||||||
|
|
||||||
import isArray from 'shared/isArray';
|
import isArray from 'shared/isArray';
|
||||||
|
|
||||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
|
||||||
|
|
||||||
import {runWithFiberInDEV} from 'react-reconciler/src/ReactCurrentFiber';
|
import {runWithFiberInDEV} from 'react-reconciler/src/ReactCurrentFiber';
|
||||||
|
|
||||||
let hasError = false;
|
let hasError = false;
|
||||||
|
|
@ -99,7 +97,7 @@ export function executeDispatchesInOrder(event) {
|
||||||
// Listeners and Instances are two parallel arrays that are always in sync.
|
// Listeners and Instances are two parallel arrays that are always in sync.
|
||||||
const listener = dispatchListeners[i];
|
const listener = dispatchListeners[i];
|
||||||
const instance = dispatchInstances[i];
|
const instance = dispatchInstances[i];
|
||||||
if (__DEV__ && enableOwnerStacks && instance !== null) {
|
if (__DEV__ && instance !== null) {
|
||||||
runWithFiberInDEV(instance, executeDispatch, event, listener, instance);
|
runWithFiberInDEV(instance, executeDispatch, event, listener, instance);
|
||||||
} else {
|
} else {
|
||||||
executeDispatch(event, listener, instance);
|
executeDispatch(event, listener, instance);
|
||||||
|
|
@ -108,7 +106,7 @@ export function executeDispatchesInOrder(event) {
|
||||||
} else if (dispatchListeners) {
|
} else if (dispatchListeners) {
|
||||||
const listener = dispatchListeners;
|
const listener = dispatchListeners;
|
||||||
const instance = dispatchInstances;
|
const instance = dispatchInstances;
|
||||||
if (__DEV__ && enableOwnerStacks && instance !== null) {
|
if (__DEV__ && instance !== null) {
|
||||||
runWithFiberInDEV(instance, executeDispatch, event, listener, instance);
|
runWithFiberInDEV(instance, executeDispatch, event, listener, instance);
|
||||||
} else {
|
} else {
|
||||||
executeDispatch(event, listener, instance);
|
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 {
|
import {
|
||||||
enableAsyncIterableChildren,
|
enableAsyncIterableChildren,
|
||||||
disableLegacyMode,
|
disableLegacyMode,
|
||||||
enableOwnerStacks,
|
|
||||||
} from 'shared/ReactFeatureFlags';
|
} from 'shared/ReactFeatureFlags';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|
@ -488,9 +487,7 @@ function createChildReconciler(
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
// We treat the parent as the owner for stack purposes.
|
// We treat the parent as the owner for stack purposes.
|
||||||
created._debugOwner = returnFiber;
|
created._debugOwner = returnFiber;
|
||||||
if (enableOwnerStacks) {
|
created._debugTask = returnFiber._debugTask;
|
||||||
created._debugTask = returnFiber._debugTask;
|
|
||||||
}
|
|
||||||
created._debugInfo = currentDebugInfo;
|
created._debugInfo = currentDebugInfo;
|
||||||
}
|
}
|
||||||
return created;
|
return created;
|
||||||
|
|
@ -609,9 +606,7 @@ function createChildReconciler(
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
// We treat the parent as the owner for stack purposes.
|
// We treat the parent as the owner for stack purposes.
|
||||||
created._debugOwner = returnFiber;
|
created._debugOwner = returnFiber;
|
||||||
if (enableOwnerStacks) {
|
created._debugTask = returnFiber._debugTask;
|
||||||
created._debugTask = returnFiber._debugTask;
|
|
||||||
}
|
|
||||||
created._debugInfo = currentDebugInfo;
|
created._debugInfo = currentDebugInfo;
|
||||||
}
|
}
|
||||||
return created;
|
return created;
|
||||||
|
|
@ -649,9 +644,7 @@ function createChildReconciler(
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
// We treat the parent as the owner for stack purposes.
|
// We treat the parent as the owner for stack purposes.
|
||||||
created._debugOwner = returnFiber;
|
created._debugOwner = returnFiber;
|
||||||
if (enableOwnerStacks) {
|
created._debugTask = returnFiber._debugTask;
|
||||||
created._debugTask = returnFiber._debugTask;
|
|
||||||
}
|
|
||||||
created._debugInfo = currentDebugInfo;
|
created._debugInfo = currentDebugInfo;
|
||||||
}
|
}
|
||||||
return created;
|
return created;
|
||||||
|
|
@ -718,9 +711,7 @@ function createChildReconciler(
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
// We treat the parent as the owner for stack purposes.
|
// We treat the parent as the owner for stack purposes.
|
||||||
created._debugOwner = returnFiber;
|
created._debugOwner = returnFiber;
|
||||||
if (enableOwnerStacks) {
|
created._debugTask = returnFiber._debugTask;
|
||||||
created._debugTask = returnFiber._debugTask;
|
|
||||||
}
|
|
||||||
const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
|
const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
|
||||||
created._debugInfo = currentDebugInfo;
|
created._debugInfo = currentDebugInfo;
|
||||||
currentDebugInfo = prevDebugInfo;
|
currentDebugInfo = prevDebugInfo;
|
||||||
|
|
@ -1605,9 +1596,7 @@ function createChildReconciler(
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
// We treat the parent as the owner for stack purposes.
|
// We treat the parent as the owner for stack purposes.
|
||||||
created._debugOwner = returnFiber;
|
created._debugOwner = returnFiber;
|
||||||
if (enableOwnerStacks) {
|
created._debugTask = returnFiber._debugTask;
|
||||||
created._debugTask = returnFiber._debugTask;
|
|
||||||
}
|
|
||||||
created._debugInfo = currentDebugInfo;
|
created._debugInfo = currentDebugInfo;
|
||||||
}
|
}
|
||||||
return created;
|
return created;
|
||||||
|
|
@ -1685,9 +1674,7 @@ function createChildReconciler(
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
// We treat the parent as the owner for stack purposes.
|
// We treat the parent as the owner for stack purposes.
|
||||||
created._debugOwner = returnFiber;
|
created._debugOwner = returnFiber;
|
||||||
if (enableOwnerStacks) {
|
created._debugTask = returnFiber._debugTask;
|
||||||
created._debugTask = returnFiber._debugTask;
|
|
||||||
}
|
|
||||||
created._debugInfo = currentDebugInfo;
|
created._debugInfo = currentDebugInfo;
|
||||||
}
|
}
|
||||||
validateFragmentProps(element, created, returnFiber);
|
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
|
// thing when it's thrown from the same async component but not if you await
|
||||||
// a promise started from a different component/task.
|
// a promise started from a different component/task.
|
||||||
throwFiber._debugOwner = returnFiber._debugOwner;
|
throwFiber._debugOwner = returnFiber._debugOwner;
|
||||||
if (enableOwnerStacks) {
|
throwFiber._debugTask = returnFiber._debugTask;
|
||||||
throwFiber._debugTask = returnFiber._debugTask;
|
|
||||||
}
|
|
||||||
if (debugInfo != null) {
|
if (debugInfo != null) {
|
||||||
for (let i = debugInfo.length - 1; i >= 0; i--) {
|
for (let i = debugInfo.length - 1; i >= 0; i--) {
|
||||||
if (typeof debugInfo[i].stack === 'string') {
|
if (typeof debugInfo[i].stack === 'string') {
|
||||||
throwFiber._debugOwner = (debugInfo[i]: any);
|
throwFiber._debugOwner = (debugInfo[i]: any);
|
||||||
if (enableOwnerStacks) {
|
throwFiber._debugTask = debugInfo[i].debugTask;
|
||||||
throwFiber._debugTask = debugInfo[i].debugTask;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,8 @@
|
||||||
import type {Fiber} from './ReactInternalTypes';
|
import type {Fiber} from './ReactInternalTypes';
|
||||||
|
|
||||||
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
||||||
import {
|
import {getOwnerStackByFiberInDev} from './ReactFiberComponentStack';
|
||||||
getStackByFiberInDevAndProd,
|
|
||||||
getOwnerStackByFiberInDev,
|
|
||||||
} from './ReactFiberComponentStack';
|
|
||||||
import {getComponentNameFromOwner} from 'react-reconciler/src/getComponentNameFromFiber';
|
import {getComponentNameFromOwner} from 'react-reconciler/src/getComponentNameFromFiber';
|
||||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
|
||||||
|
|
||||||
export let current: Fiber | null = null;
|
export let current: Fiber | null = null;
|
||||||
export let isRendering: boolean = false;
|
export let isRendering: boolean = false;
|
||||||
|
|
@ -42,10 +38,7 @@ function getCurrentFiberStackInDev(): string {
|
||||||
// and it is guaranteed to be the work-in-progress version.
|
// and it is guaranteed to be the work-in-progress version.
|
||||||
// TODO: The above comment is not actually true. We might be
|
// TODO: The above comment is not actually true. We might be
|
||||||
// in a commit phase or preemptive set state callback.
|
// in a commit phase or preemptive set state callback.
|
||||||
if (enableOwnerStacks) {
|
return getOwnerStackByFiberInDev(current);
|
||||||
return getOwnerStackByFiberInDev(current);
|
|
||||||
}
|
|
||||||
return getStackByFiberInDevAndProd(current);
|
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
@ -63,12 +56,10 @@ export function runWithFiberInDEV<A0, A1, A2, A3, A4, T>(
|
||||||
const previousFiber = current;
|
const previousFiber = current;
|
||||||
setCurrentFiber(fiber);
|
setCurrentFiber(fiber);
|
||||||
try {
|
try {
|
||||||
if (enableOwnerStacks) {
|
if (fiber !== null && fiber._debugTask) {
|
||||||
if (fiber !== null && fiber._debugTask) {
|
return fiber._debugTask.run(
|
||||||
return fiber._debugTask.run(
|
callback.bind(null, arg0, arg1, arg2, arg3, arg4),
|
||||||
callback.bind(null, arg0, arg1, arg2, arg3, arg4),
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return callback(arg0, arg1, arg2, arg3, arg4);
|
return callback(arg0, arg1, arg2, arg3, arg4);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
||||||
25
packages/react-reconciler/src/ReactFiber.js
vendored
25
packages/react-reconciler/src/ReactFiber.js
vendored
|
|
@ -40,7 +40,6 @@ import {
|
||||||
enableRenderableContext,
|
enableRenderableContext,
|
||||||
disableLegacyMode,
|
disableLegacyMode,
|
||||||
enableObjectFiber,
|
enableObjectFiber,
|
||||||
enableOwnerStacks,
|
|
||||||
enableViewTransition,
|
enableViewTransition,
|
||||||
} from 'shared/ReactFeatureFlags';
|
} from 'shared/ReactFeatureFlags';
|
||||||
import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
|
import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
|
||||||
|
|
@ -202,10 +201,8 @@ function FiberNode(
|
||||||
// This isn't directly used but is handy for debugging internals:
|
// This isn't directly used but is handy for debugging internals:
|
||||||
this._debugInfo = null;
|
this._debugInfo = null;
|
||||||
this._debugOwner = null;
|
this._debugOwner = null;
|
||||||
if (enableOwnerStacks) {
|
this._debugStack = null;
|
||||||
this._debugStack = null;
|
this._debugTask = null;
|
||||||
this._debugTask = null;
|
|
||||||
}
|
|
||||||
this._debugNeedsRemount = false;
|
this._debugNeedsRemount = false;
|
||||||
this._debugHookTypes = null;
|
this._debugHookTypes = null;
|
||||||
if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
|
if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
|
||||||
|
|
@ -293,10 +290,8 @@ function createFiberImplObject(
|
||||||
// This isn't directly used but is handy for debugging internals:
|
// This isn't directly used but is handy for debugging internals:
|
||||||
fiber._debugInfo = null;
|
fiber._debugInfo = null;
|
||||||
fiber._debugOwner = null;
|
fiber._debugOwner = null;
|
||||||
if (enableOwnerStacks) {
|
fiber._debugStack = null;
|
||||||
fiber._debugStack = null;
|
fiber._debugTask = null;
|
||||||
fiber._debugTask = null;
|
|
||||||
}
|
|
||||||
fiber._debugNeedsRemount = false;
|
fiber._debugNeedsRemount = false;
|
||||||
fiber._debugHookTypes = null;
|
fiber._debugHookTypes = null;
|
||||||
if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
|
if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
|
||||||
|
|
@ -352,10 +347,8 @@ export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {
|
||||||
// DEV-only fields
|
// DEV-only fields
|
||||||
|
|
||||||
workInProgress._debugOwner = current._debugOwner;
|
workInProgress._debugOwner = current._debugOwner;
|
||||||
if (enableOwnerStacks) {
|
workInProgress._debugStack = current._debugStack;
|
||||||
workInProgress._debugStack = current._debugStack;
|
workInProgress._debugTask = current._debugTask;
|
||||||
workInProgress._debugTask = current._debugTask;
|
|
||||||
}
|
|
||||||
workInProgress._debugHookTypes = current._debugHookTypes;
|
workInProgress._debugHookTypes = current._debugHookTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -766,10 +759,8 @@ export function createFiberFromElement(
|
||||||
);
|
);
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
fiber._debugOwner = element._owner;
|
fiber._debugOwner = element._owner;
|
||||||
if (enableOwnerStacks) {
|
fiber._debugStack = element._debugStack;
|
||||||
fiber._debugStack = element._debugStack;
|
fiber._debugTask = element._debugTask;
|
||||||
fiber._debugTask = element._debugTask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return fiber;
|
return fiber;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,6 @@ import {
|
||||||
enableRenderableContext,
|
enableRenderableContext,
|
||||||
disableLegacyMode,
|
disableLegacyMode,
|
||||||
disableDefaultPropsExceptForClasses,
|
disableDefaultPropsExceptForClasses,
|
||||||
enableOwnerStacks,
|
|
||||||
enableHydrationLaneScheduling,
|
enableHydrationLaneScheduling,
|
||||||
enableViewTransition,
|
enableViewTransition,
|
||||||
} from 'shared/ReactFeatureFlags';
|
} from 'shared/ReactFeatureFlags';
|
||||||
|
|
@ -3782,10 +3781,8 @@ function beginWork(
|
||||||
workInProgress.mode,
|
workInProgress.mode,
|
||||||
workInProgress.lanes,
|
workInProgress.lanes,
|
||||||
);
|
);
|
||||||
if (enableOwnerStacks) {
|
copiedFiber._debugStack = workInProgress._debugStack;
|
||||||
copiedFiber._debugStack = workInProgress._debugStack;
|
copiedFiber._debugTask = workInProgress._debugTask;
|
||||||
copiedFiber._debugTask = workInProgress._debugTask;
|
|
||||||
}
|
|
||||||
return remountFiber(current, workInProgress, copiedFiber);
|
return remountFiber(current, workInProgress, copiedFiber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,7 @@
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {enableViewTransition} from 'shared/ReactFeatureFlags';
|
||||||
enableOwnerStacks,
|
|
||||||
enableViewTransition,
|
|
||||||
} from 'shared/ReactFeatureFlags';
|
|
||||||
import type {Fiber} from './ReactInternalTypes';
|
import type {Fiber} from './ReactInternalTypes';
|
||||||
import type {ReactComponentInfo} from 'shared/ReactTypes';
|
import type {ReactComponentInfo} from 'shared/ReactTypes';
|
||||||
|
|
||||||
|
|
@ -101,7 +98,7 @@ function describeFunctionComponentFrameWithoutLineNumber(fn: Function): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getOwnerStackByFiberInDev(workInProgress: Fiber): string {
|
export function getOwnerStackByFiberInDev(workInProgress: Fiber): string {
|
||||||
if (!enableOwnerStacks || !__DEV__) {
|
if (!__DEV__) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,6 @@ import reportGlobalError from 'shared/reportGlobalError';
|
||||||
|
|
||||||
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
||||||
|
|
||||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
|
||||||
|
|
||||||
import {bindToConsole} from './ReactFiberConfig';
|
import {bindToConsole} from './ReactFiberConfig';
|
||||||
|
|
||||||
// Side-channel since I'm not sure we want to make this part of the public API
|
// 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' +
|
'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.';
|
'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 {
|
try {
|
||||||
console.warn(
|
console.warn(
|
||||||
'%s\n\n%s\n',
|
'%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.
|
// We let our console.error wrapper add the component stack to the end.
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
if (!enableOwnerStacks) {
|
// ignore
|
||||||
ReactSharedInternals.getCurrentStack = prevGetCurrentStack;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -97,18 +81,6 @@ export function defaultOnCaughtError(
|
||||||
errorBoundaryName || 'Anonymous'
|
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 {
|
try {
|
||||||
if (
|
if (
|
||||||
typeof error === 'object' &&
|
typeof error === 'object' &&
|
||||||
|
|
@ -138,9 +110,7 @@ export function defaultOnCaughtError(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (!enableOwnerStacks) {
|
// ignore
|
||||||
ReactSharedInternals.getCurrentStack = prevGetCurrentStack;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// In production, we print the error directly.
|
// In production, we print the error directly.
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ describe('ErrorBoundaryReconciliation', () => {
|
||||||
let ReactTestRenderer;
|
let ReactTestRenderer;
|
||||||
let span;
|
let span;
|
||||||
let act;
|
let act;
|
||||||
let assertConsoleErrorDev;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.resetModules();
|
jest.resetModules();
|
||||||
|
|
@ -14,8 +13,6 @@ describe('ErrorBoundaryReconciliation', () => {
|
||||||
ReactTestRenderer = require('react-test-renderer');
|
ReactTestRenderer = require('react-test-renderer');
|
||||||
React = require('react');
|
React = require('react');
|
||||||
act = require('internal-test-utils').act;
|
act = require('internal-test-utils').act;
|
||||||
assertConsoleErrorDev =
|
|
||||||
require('internal-test-utils').assertConsoleErrorDev;
|
|
||||||
DidCatchErrorBoundary = class extends React.Component {
|
DidCatchErrorBoundary = class extends React.Component {
|
||||||
state = {error: null};
|
state = {error: null};
|
||||||
componentDidCatch(error) {
|
componentDidCatch(error) {
|
||||||
|
|
@ -68,9 +65,6 @@ describe('ErrorBoundaryReconciliation', () => {
|
||||||
</ErrorBoundary>,
|
</ErrorBoundary>,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
if (gate(flags => !flags.enableOwnerStacks)) {
|
|
||||||
assertConsoleErrorDev(['invalid', 'invalid']);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Fallback = fallbackTagName;
|
const Fallback = fallbackTagName;
|
||||||
expect(renderer).toMatchRenderedOutput(<Fallback prop="ErrorBoundary" />);
|
expect(renderer).toMatchRenderedOutput(<Fallback prop="ErrorBoundary" />);
|
||||||
|
|
|
||||||
|
|
@ -168,9 +168,7 @@ describe('ReactFragment', () => {
|
||||||
'Foo',
|
'Foo',
|
||||||
'CatchingBoundary',
|
'CatchingBoundary',
|
||||||
]),
|
]),
|
||||||
gate(flags => flags.enableOwnerStacks) && __DEV__
|
__DEV__ ? componentStack(['Bar', 'Foo']) : null,
|
||||||
? componentStack(['Bar', 'Foo'])
|
|
||||||
: null,
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -744,19 +744,12 @@ describe('ReactFragment', () => {
|
||||||
ReactNoop.render(<Foo condition={false} />);
|
ReactNoop.render(<Foo condition={false} />);
|
||||||
await waitForAll([]);
|
await waitForAll([]);
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
gate('enableOwnerStacks')
|
'Each child in a list should have a unique "key" prop.\n' +
|
||||||
? 'Each child in a list should have a unique "key" prop.\n' +
|
'\n' +
|
||||||
'\n' +
|
'Check the render method of `div`. ' +
|
||||||
'Check the render method of `div`. ' +
|
'It was passed a child from Foo. ' +
|
||||||
'It was passed a child from Foo. ' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
' in Foo (at **)',
|
||||||
' 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 **)',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(ops).toEqual([]);
|
expect(ops).toEqual([]);
|
||||||
|
|
|
||||||
|
|
@ -1236,24 +1236,20 @@ describe('ReactHooks', () => {
|
||||||
'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
|
'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
|
||||||
'In function components, you can read it directly in the function body, ' +
|
'In function components, you can read it directly in the function body, ' +
|
||||||
'but not inside Hooks like useReducer() or useMemo().\n' +
|
'but not inside Hooks like useReducer() or useMemo().\n' +
|
||||||
' in App (at **)' +
|
' in App (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
|
||||||
'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +
|
'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. ' +
|
'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' +
|
'For more information, see https://react.dev/link/rules-of-hooks\n' +
|
||||||
' in App (at **)' +
|
' in App (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
|
||||||
'Context can only be read while React is rendering. ' +
|
'Context can only be read while React is rendering. ' +
|
||||||
'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
|
'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
|
||||||
'In function components, you can read it directly in the function body, ' +
|
'In function components, you can read it directly in the function body, ' +
|
||||||
'but not inside Hooks like useReducer() or useMemo().\n' +
|
'but not inside Hooks like useReducer() or useMemo().\n' +
|
||||||
' in App (at **)' +
|
' in App (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
|
||||||
'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +
|
'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. ' +
|
'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' +
|
'For more information, see https://react.dev/link/rules-of-hooks\n' +
|
||||||
' in App (at **)' +
|
' in App (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function Valid() {
|
function Valid() {
|
||||||
|
|
@ -1293,24 +1289,20 @@ describe('ReactHooks', () => {
|
||||||
'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
|
'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
|
||||||
'In function components, you can read it directly in the function body, ' +
|
'In function components, you can read it directly in the function body, ' +
|
||||||
'but not inside Hooks like useReducer() or useMemo().\n' +
|
'but not inside Hooks like useReducer() or useMemo().\n' +
|
||||||
' in App (at **)' +
|
' in App (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
|
||||||
'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +
|
'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. ' +
|
'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' +
|
'For more information, see https://react.dev/link/rules-of-hooks\n' +
|
||||||
' in App (at **)' +
|
' in App (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
|
||||||
'Context can only be read while React is rendering. ' +
|
'Context can only be read while React is rendering. ' +
|
||||||
'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
|
'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
|
||||||
'In function components, you can read it directly in the function body, ' +
|
'In function components, you can read it directly in the function body, ' +
|
||||||
'but not inside Hooks like useReducer() or useMemo().\n' +
|
'but not inside Hooks like useReducer() or useMemo().\n' +
|
||||||
' in App (at **)' +
|
' in App (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
|
||||||
'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +
|
'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. ' +
|
'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' +
|
'For more information, see https://react.dev/link/rules-of-hooks\n' +
|
||||||
' in App (at **)' +
|
' in App (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in Boundary (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1803,14 +1803,10 @@ describe('ReactIncremental', () => {
|
||||||
' in Intl (at **)',
|
' in Intl (at **)',
|
||||||
'ShowLocale uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in ShowLocale (at **)' +
|
' in ShowLocale (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in Intl (at **)'),
|
|
||||||
'ShowBoth uses the legacy contextTypes API which will be removed soon. ' +
|
'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' +
|
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in ShowBoth (at **)' +
|
' in ShowBoth (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in div (at **)' + '\n in Intl (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
ReactNoop.render(
|
ReactNoop.render(
|
||||||
|
|
@ -1865,16 +1861,10 @@ describe('ReactIncremental', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Router uses the legacy childContextTypes API which will soon be removed. ' +
|
'Router uses the legacy childContextTypes API which will soon be removed. ' +
|
||||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in Router (at **)' +
|
' in Router (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in Intl (at **)'),
|
|
||||||
'ShowRoute uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(gate('enableOwnerStacks')
|
' in Indirection (at **)',
|
||||||
? ' in Indirection (at **)'
|
|
||||||
: ' in ShowRoute (at **)\n' +
|
|
||||||
' in Indirection (at **)\n' +
|
|
||||||
' in Router (at **)\n' +
|
|
||||||
' in Intl (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1972,8 +1962,7 @@ describe('ReactIncremental', () => {
|
||||||
' in Intl (at **)',
|
' in Intl (at **)',
|
||||||
'ShowLocale uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in ShowLocale (at **)' +
|
' in ShowLocale (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in Intl (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await waitForAll([
|
await waitForAll([
|
||||||
|
|
@ -2068,22 +2057,10 @@ describe('ReactIncremental', () => {
|
||||||
' in Intl (at **)',
|
' in Intl (at **)',
|
||||||
'ShowLocaleClass uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in ShowLocaleClass (at **)' +
|
' in ShowLocaleClass (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in Stateful (at **)' +
|
|
||||||
'\n in IndirectionClass (at **)' +
|
|
||||||
'\n in IndirectionFn (at **)' +
|
|
||||||
' in Intl (at **)'),
|
|
||||||
'ShowLocaleFn uses the legacy contextTypes API which will be removed soon. ' +
|
'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' +
|
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in ShowLocaleFn (at **)' +
|
' in ShowLocaleFn (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in Stateful (at **)' +
|
|
||||||
'\n in IndirectionClass (at **)' +
|
|
||||||
'\n in IndirectionFn (at **)' +
|
|
||||||
' in Intl (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
statefulInst.setState({x: 1});
|
statefulInst.setState({x: 1});
|
||||||
|
|
@ -2174,26 +2151,14 @@ describe('ReactIncremental', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Intl uses the legacy childContextTypes API which will soon be removed. ' +
|
'Intl uses the legacy childContextTypes API which will soon be removed. ' +
|
||||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in Intl (at **)\n') +
|
|
||||||
' in Stateful (at **)',
|
' in Stateful (at **)',
|
||||||
'ShowLocaleClass uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in ShowLocaleClass (at **)' +
|
' in ShowLocaleClass (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in IndirectionClass (at **)' +
|
|
||||||
'\n in IndirectionFn (at **)' +
|
|
||||||
'\n in Intl (at **)' +
|
|
||||||
'\n in Stateful (at **)'),
|
|
||||||
'ShowLocaleFn uses the legacy contextTypes API which will be removed soon. ' +
|
'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' +
|
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in ShowLocaleFn (at **)' +
|
' in ShowLocaleFn (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in IndirectionClass (at **)' +
|
|
||||||
'\n in IndirectionFn (at **)' +
|
|
||||||
'\n in Intl (at **)' +
|
|
||||||
'\n in Stateful (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
statefulInst.setState({locale: 'gr'});
|
statefulInst.setState({locale: 'gr'});
|
||||||
|
|
@ -2255,7 +2220,6 @@ describe('ReactIncremental', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Child uses the legacy childContextTypes API which will soon be removed. ' +
|
'Child uses the legacy childContextTypes API which will soon be removed. ' +
|
||||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in Child (at **)\n') +
|
|
||||||
' in Middle (at **)\n' +
|
' in Middle (at **)\n' +
|
||||||
' in Root (at **)',
|
' in Root (at **)',
|
||||||
]);
|
]);
|
||||||
|
|
@ -2309,7 +2273,6 @@ describe('ReactIncremental', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'ContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
'ContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
||||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in ContextProvider (at **)\n') +
|
|
||||||
' in Root (at **)',
|
' in Root (at **)',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -2511,10 +2474,7 @@ describe('ReactIncremental', () => {
|
||||||
' in TopContextProvider (at **)',
|
' in TopContextProvider (at **)',
|
||||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in Child (at **)' +
|
' in Child (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in Middle (at **)' + '\n in TopContextProvider (at **)'),
|
|
||||||
]);
|
]);
|
||||||
instance.updateCount();
|
instance.updateCount();
|
||||||
await waitForAll(['count:1']);
|
await waitForAll(['count:1']);
|
||||||
|
|
@ -2578,17 +2538,10 @@ describe('ReactIncremental', () => {
|
||||||
' in TopContextProvider (at **)',
|
' in TopContextProvider (at **)',
|
||||||
'MiddleContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
'MiddleContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
||||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in MiddleContextProvider (at **)' +
|
' in MiddleContextProvider (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in TopContextProvider (at **)'),
|
|
||||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in Child (at **)' +
|
' in Child (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in MiddleContextProvider (at **)' +
|
|
||||||
'\n in TopContextProvider (at **)'),
|
|
||||||
]);
|
]);
|
||||||
instance.updateCount();
|
instance.updateCount();
|
||||||
await waitForAll(['count:1']);
|
await waitForAll(['count:1']);
|
||||||
|
|
@ -2661,19 +2614,10 @@ describe('ReactIncremental', () => {
|
||||||
' in TopContextProvider (at **)',
|
' in TopContextProvider (at **)',
|
||||||
'MiddleContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
'MiddleContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
||||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in MiddleContextProvider (at **)' +
|
' in MiddleContextProvider (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in MiddleScu (at **)' +
|
|
||||||
'\n in TopContextProvider (at **)'),
|
|
||||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in Child (at **)' +
|
' in Child (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in MiddleContextProvider (at **)' +
|
|
||||||
'\n in MiddleScu (at **)' +
|
|
||||||
'\n in TopContextProvider (at **)'),
|
|
||||||
]);
|
]);
|
||||||
instance.updateCount();
|
instance.updateCount();
|
||||||
await waitForAll([]);
|
await waitForAll([]);
|
||||||
|
|
@ -2756,19 +2700,10 @@ describe('ReactIncremental', () => {
|
||||||
' in TopContextProvider (at **)',
|
' in TopContextProvider (at **)',
|
||||||
'MiddleContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
'MiddleContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
||||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in MiddleContextProvider (at **)' +
|
' in MiddleContextProvider (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in MiddleScu (at **)' +
|
|
||||||
'\n in TopContextProvider (at **)'),
|
|
||||||
'Child uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in Child (at **)' +
|
' in Child (at **)',
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: '\n in MiddleContextProvider (at **)' +
|
|
||||||
'\n in MiddleScu (at **)' +
|
|
||||||
'\n in TopContextProvider (at **)'),
|
|
||||||
]);
|
]);
|
||||||
topInstance.updateCount();
|
topInstance.updateCount();
|
||||||
await waitForAll([]);
|
await waitForAll([]);
|
||||||
|
|
|
||||||
|
|
@ -1222,8 +1222,7 @@ describe('ReactIncrementalErrorHandling', () => {
|
||||||
' in Provider (at **)',
|
' in Provider (at **)',
|
||||||
'Connector uses the legacy contextTypes API which will be removed soon. ' +
|
'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' +
|
'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
' in Connector (at **)' +
|
' in Connector (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in Provider (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// If the context stack does not unwind, span will get 'abcde'
|
// If the context stack does not unwind, span will get 'abcde'
|
||||||
|
|
@ -1254,23 +1253,6 @@ describe('ReactIncrementalErrorHandling', () => {
|
||||||
</ErrorBoundary>,
|
</ErrorBoundary>,
|
||||||
);
|
);
|
||||||
await waitForAll([]);
|
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(
|
expect(ReactNoop).toMatchRenderedOutput(
|
||||||
<span
|
<span
|
||||||
|
|
@ -1319,23 +1301,7 @@ describe('ReactIncrementalErrorHandling', () => {
|
||||||
</ErrorBoundary>,
|
</ErrorBoundary>,
|
||||||
);
|
);
|
||||||
await waitForAll([]);
|
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(
|
expect(ReactNoop).toMatchRenderedOutput(
|
||||||
<span
|
<span
|
||||||
prop={
|
prop={
|
||||||
|
|
@ -1354,17 +1320,6 @@ describe('ReactIncrementalErrorHandling', () => {
|
||||||
it('recovers from uncaught reconciler errors', async () => {
|
it('recovers from uncaught reconciler errors', async () => {
|
||||||
const InvalidType = undefined;
|
const InvalidType = undefined;
|
||||||
ReactNoop.render(<InvalidType />);
|
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(
|
await waitForThrow(
|
||||||
'Element type is invalid: expected a string (for built-in components) or ' +
|
'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.
|
// The component stack is not added without the polyfill/devtools.
|
||||||
// expect.stringMatching(
|
// expect.stringMatching(
|
||||||
// new RegExp(
|
// new RegExp(
|
||||||
// gate(flags => flags.enableOwnerStacks)
|
// '\\s+(in|at) ErrorThrowingComponent'
|
||||||
// ? '\\s+(in|at) ErrorThrowingComponent'
|
|
||||||
// : '\\s+(in|at) ErrorThrowingComponent (.*)\n' +
|
|
||||||
// '\\s+(in|at) span(.*)\n' +
|
|
||||||
// '\\s+(in|at) div(.*)',
|
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
);
|
);
|
||||||
|
|
@ -143,11 +139,7 @@ describe('ReactIncrementalErrorLogging', () => {
|
||||||
// The component stack is not added without the polyfill/devtools.
|
// The component stack is not added without the polyfill/devtools.
|
||||||
// expect.stringMatching(
|
// expect.stringMatching(
|
||||||
// new RegExp(
|
// new RegExp(
|
||||||
// gate(flags => flags.enableOwnerStacks)
|
// '\\s+(in|at) ErrorThrowingComponent'
|
||||||
// ? '\\s+(in|at) ErrorThrowingComponent'
|
|
||||||
// : '\\s+(in|at) ErrorThrowingComponent (.*)\n' +
|
|
||||||
// '\\s+(in|at) span(.*)\n' +
|
|
||||||
// '\\s+(in|at) div(.*)',
|
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
);
|
);
|
||||||
|
|
@ -204,12 +196,7 @@ describe('ReactIncrementalErrorLogging', () => {
|
||||||
// The component stack is not added without the polyfill/devtools.
|
// The component stack is not added without the polyfill/devtools.
|
||||||
// expect.stringMatching(
|
// expect.stringMatching(
|
||||||
// new RegExp(
|
// new RegExp(
|
||||||
// gate(flags => flags.enableOwnerStacks)
|
// '\\s+(in|at) ErrorThrowingComponent'
|
||||||
// ? '\\s+(in|at) ErrorThrowingComponent'
|
|
||||||
// : '\\s+(in|at) ErrorThrowingComponent (.*)\n' +
|
|
||||||
// '\\s+(in|at) span(.*)\n' +
|
|
||||||
// '\\s+(in|at) ErrorBoundary(.*)\n' +
|
|
||||||
// '\\s+(in|at) div(.*)',
|
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
);
|
);
|
||||||
|
|
@ -287,11 +274,7 @@ describe('ReactIncrementalErrorLogging', () => {
|
||||||
),
|
),
|
||||||
// The component stack is not added without the polyfill/devtools.
|
// The component stack is not added without the polyfill/devtools.
|
||||||
// expect.stringMatching(
|
// expect.stringMatching(
|
||||||
// gate(flag => flag.enableOwnerStacks)
|
// new RegExp('\\s+(in|at) Foo')
|
||||||
// ? new RegExp('\\s+(in|at) Foo')
|
|
||||||
// : new RegExp(
|
|
||||||
// '\\s+(in|at) Foo (.*)\n' + '\\s+(in|at) ErrorBoundary(.*)',
|
|
||||||
// ),
|
|
||||||
// ),
|
// ),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -240,9 +240,6 @@ describe('ReactLazy', () => {
|
||||||
' }\n\n' +
|
' }\n\n' +
|
||||||
'Your code should look like: \n ' +
|
'Your code should look like: \n ' +
|
||||||
"const MyComponent = lazy(() => import('./MyComponent'))\n" +
|
"const MyComponent = lazy(() => import('./MyComponent'))\n" +
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: ' in Lazy (at **)\n' + ' in Suspense (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
'lazy: Expected the result of a dynamic import() call. ' +
|
'lazy: Expected the result of a dynamic import() call. ' +
|
||||||
'Instead received: function Text(props) {\n' +
|
'Instead received: function Text(props) {\n' +
|
||||||
|
|
@ -251,9 +248,6 @@ describe('ReactLazy', () => {
|
||||||
' }\n\n' +
|
' }\n\n' +
|
||||||
'Your code should look like: \n ' +
|
'Your code should look like: \n ' +
|
||||||
"const MyComponent = lazy(() => import('./MyComponent'))\n" +
|
"const MyComponent = lazy(() => import('./MyComponent'))\n" +
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: ' in Lazy (at **)\n' + ' in Suspense (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
expect(root).not.toMatchRenderedOutput('Hi');
|
expect(root).not.toMatchRenderedOutput('Hi');
|
||||||
|
|
@ -749,8 +743,7 @@ describe('ReactLazy', () => {
|
||||||
'T: Support for defaultProps ' +
|
'T: Support for defaultProps ' +
|
||||||
'will be removed from function components in a future major ' +
|
'will be removed from function components in a future major ' +
|
||||||
'release. Use JavaScript default parameters instead.\n' +
|
'release. Use JavaScript default parameters instead.\n' +
|
||||||
' in T (at **)\n' +
|
' in T (at **)',
|
||||||
' in Suspense (at **)',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(root).toMatchRenderedOutput('Hi Bye');
|
expect(root).toMatchRenderedOutput('Hi Bye');
|
||||||
|
|
@ -855,11 +848,15 @@ describe('ReactLazy', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function verifyResolvesProps(
|
// @gate !disableDefaultPropsExceptForClasses
|
||||||
Add,
|
it('resolves props for function component with defaultProps', async () => {
|
||||||
shouldWarnAboutFunctionDefaultProps,
|
function Add(props) {
|
||||||
shouldWarnAboutMemoDefaultProps,
|
expect(props.innerWithDefault).toBe(42);
|
||||||
) {
|
return props.inner + props.outer;
|
||||||
|
}
|
||||||
|
Add.defaultProps = {
|
||||||
|
innerWithDefault: 42,
|
||||||
|
};
|
||||||
const LazyAdd = lazy(() => fakeImport(Add));
|
const LazyAdd = lazy(() => fakeImport(Add));
|
||||||
const root = ReactTestRenderer.create(
|
const root = ReactTestRenderer.create(
|
||||||
<Suspense fallback={<Text text="Loading..." />}>
|
<Suspense fallback={<Text text="Loading..." />}>
|
||||||
|
|
@ -876,18 +873,10 @@ describe('ReactLazy', () => {
|
||||||
// Mount
|
// Mount
|
||||||
await act(() => resolveFakeImport(Add));
|
await act(() => resolveFakeImport(Add));
|
||||||
|
|
||||||
if (shouldWarnAboutFunctionDefaultProps) {
|
assertConsoleErrorDev([
|
||||||
assertConsoleErrorDev([
|
'Add: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.\n' +
|
||||||
'Add: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.\n' +
|
' in Add (at **)',
|
||||||
' 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 **)',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(root).toMatchRenderedOutput('22');
|
expect(root).toMatchRenderedOutput('22');
|
||||||
|
|
||||||
|
|
@ -899,25 +888,38 @@ describe('ReactLazy', () => {
|
||||||
);
|
);
|
||||||
await waitForAll([]);
|
await waitForAll([]);
|
||||||
expect(root).toMatchRenderedOutput('0');
|
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 () => {
|
it('resolves props for function component without defaultProps', async () => {
|
||||||
function Add(props) {
|
function Add(props) {
|
||||||
return props.inner + props.outer;
|
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 () => {
|
it('resolves props for class component with defaultProps', async () => {
|
||||||
|
|
@ -930,7 +932,32 @@ describe('ReactLazy', () => {
|
||||||
Add.defaultProps = {
|
Add.defaultProps = {
|
||||||
innerWithDefault: 42,
|
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 () => {
|
it('resolves props for class component without defaultProps', async () => {
|
||||||
|
|
@ -939,7 +966,32 @@ describe('ReactLazy', () => {
|
||||||
return this.props.inner + this.props.outer;
|
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
|
// @gate !disableDefaultPropsExceptForClasses
|
||||||
|
|
@ -952,7 +1004,32 @@ describe('ReactLazy', () => {
|
||||||
Add.defaultProps = {
|
Add.defaultProps = {
|
||||||
innerWithDefault: 42,
|
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 () => {
|
it('resolves props for forwardRef component without defaultProps', async () => {
|
||||||
|
|
@ -960,7 +1037,33 @@ describe('ReactLazy', () => {
|
||||||
return props.inner + props.outer;
|
return props.inner + props.outer;
|
||||||
});
|
});
|
||||||
Add.displayName = 'Add';
|
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
|
// @gate !disableDefaultPropsExceptForClasses
|
||||||
|
|
@ -973,7 +1076,39 @@ describe('ReactLazy', () => {
|
||||||
Add.defaultProps = {
|
Add.defaultProps = {
|
||||||
innerWithDefault: 42,
|
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 () => {
|
it('resolves props for outer memo component without defaultProps', async () => {
|
||||||
|
|
@ -981,7 +1116,32 @@ describe('ReactLazy', () => {
|
||||||
return props.inner + props.outer;
|
return props.inner + props.outer;
|
||||||
};
|
};
|
||||||
Add = React.memo(Add);
|
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
|
// @gate !disableDefaultPropsExceptForClasses
|
||||||
|
|
@ -994,7 +1154,40 @@ describe('ReactLazy', () => {
|
||||||
Add.defaultProps = {
|
Add.defaultProps = {
|
||||||
innerWithDefault: 42,
|
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 () => {
|
it('resolves props for inner memo component without defaultProps', async () => {
|
||||||
|
|
@ -1002,7 +1195,32 @@ describe('ReactLazy', () => {
|
||||||
return props.inner + props.outer;
|
return props.inner + props.outer;
|
||||||
};
|
};
|
||||||
Add.displayName = 'Add';
|
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
|
// @gate !disableDefaultPropsExceptForClasses
|
||||||
|
|
@ -1030,12 +1248,13 @@ describe('ReactLazy', () => {
|
||||||
// Mount
|
// Mount
|
||||||
await act(() => resolveFakeImport(T));
|
await act(() => resolveFakeImport(T));
|
||||||
assertLog(['Inner default text']);
|
assertLog(['Inner default text']);
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev(
|
||||||
'T: Support for defaultProps will be removed from function components in a future major release. ' +
|
[
|
||||||
'Use JavaScript default parameters instead.\n' +
|
'T: Support for defaultProps will be removed from function components in a future major release. ' +
|
||||||
' in T (at **)\n' +
|
'Use JavaScript default parameters instead.',
|
||||||
' in Suspense (at **)',
|
],
|
||||||
]);
|
{withoutStack: true},
|
||||||
|
);
|
||||||
expect(root).toMatchRenderedOutput('Inner default text');
|
expect(root).toMatchRenderedOutput('Inner default text');
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
|
|
@ -1074,11 +1293,7 @@ describe('ReactLazy', () => {
|
||||||
'\n' +
|
'\n' +
|
||||||
'Check the render method of `Foo`. ' +
|
'Check the render method of `Foo`. ' +
|
||||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in Foo (at **)',
|
||||||
? ' in Foo (at **)'
|
|
||||||
: ' in Text (at **)\n' +
|
|
||||||
' in Foo (at **)\n' +
|
|
||||||
' in Suspense (at **)'),
|
|
||||||
]);
|
]);
|
||||||
expect(root).toMatchRenderedOutput(<div>AB</div>);
|
expect(root).toMatchRenderedOutput(<div>AB</div>);
|
||||||
});
|
});
|
||||||
|
|
@ -1154,11 +1369,13 @@ describe('ReactLazy', () => {
|
||||||
|
|
||||||
// Mount
|
// Mount
|
||||||
await act(() => resolveFakeImport(Add));
|
await act(() => resolveFakeImport(Add));
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev(
|
||||||
'Unknown: Support for defaultProps will be removed from memo components in a future major release. ' +
|
[
|
||||||
'Use JavaScript default parameters instead.\n' +
|
'Unknown: Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||||
' in Suspense (at **)',
|
'Use JavaScript default parameters instead.',
|
||||||
]);
|
],
|
||||||
|
{withoutStack: true},
|
||||||
|
);
|
||||||
expect(root).toMatchRenderedOutput('4');
|
expect(root).toMatchRenderedOutput('4');
|
||||||
|
|
||||||
// Update (shallowly equal)
|
// Update (shallowly equal)
|
||||||
|
|
@ -1243,14 +1460,15 @@ describe('ReactLazy', () => {
|
||||||
|
|
||||||
// Mount
|
// Mount
|
||||||
await act(() => resolveFakeImport(Add));
|
await act(() => resolveFakeImport(Add));
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev(
|
||||||
'Memo: Support for defaultProps will be removed from memo components in a future major release. ' +
|
[
|
||||||
'Use JavaScript default parameters instead.\n' +
|
'Memo: Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||||
' in Suspense (at **)',
|
'Use JavaScript default parameters instead.',
|
||||||
'Unknown: Support for defaultProps will be removed from memo components in a future major release. ' +
|
'Unknown: Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||||
'Use JavaScript default parameters instead.\n' +
|
'Use JavaScript default parameters instead.',
|
||||||
' in Suspense (at **)',
|
],
|
||||||
]);
|
{withoutStack: true},
|
||||||
|
);
|
||||||
expect(root).toMatchRenderedOutput('4');
|
expect(root).toMatchRenderedOutput('4');
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
|
|
|
||||||
|
|
@ -407,12 +407,22 @@ describe('memo', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
assertLog(['Loading...', 15]);
|
assertLog(['Loading...', 15]);
|
||||||
assertConsoleErrorDev([
|
if (label === 'lazy') {
|
||||||
'Counter: Support for defaultProps will be removed from memo components in a future major release. ' +
|
assertConsoleErrorDev(
|
||||||
'Use JavaScript default parameters instead.\n' +
|
[
|
||||||
(label === 'lazy' ? '' : ' in Indirection (at **)\n') +
|
'Counter: Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||||
' in Suspense (at **)',
|
'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} />);
|
expect(ReactNoop).toMatchRenderedOutput(<span prop={15} />);
|
||||||
|
|
||||||
// Should bail out because props have not changed
|
// Should bail out because props have not changed
|
||||||
|
|
@ -475,12 +485,14 @@ describe('memo', () => {
|
||||||
</div>,
|
</div>,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev(
|
||||||
'Inner: ' +
|
[
|
||||||
'Support for defaultProps will be removed from memo components in a future major release. ' +
|
'Inner: ' +
|
||||||
'Use JavaScript default parameters instead.\n' +
|
'Support for defaultProps will be removed from memo components in a future major release. ' +
|
||||||
' in div (at **)',
|
'Use JavaScript default parameters instead.',
|
||||||
]);
|
],
|
||||||
|
{withoutStack: true},
|
||||||
|
);
|
||||||
expect(root).toMatchRenderedOutput(<div>111</div>);
|
expect(root).toMatchRenderedOutput(<div>111</div>);
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
|
|
@ -576,9 +588,7 @@ describe('memo', () => {
|
||||||
'Each child in a list should have a unique "key" prop. ' +
|
'Each child in a list should have a unique "key" prop. ' +
|
||||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
(gate('enableOwnerStacks')
|
' in **/ReactMemo-test.js:**:** (at **)',
|
||||||
? ' in **/ReactMemo-test.js:**:** (at **)'
|
|
||||||
: ' in p (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -597,8 +607,7 @@ describe('memo', () => {
|
||||||
'\n\nCheck the top-level render call using <Inner>. It was passed a child from Inner. ' +
|
'\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' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
' in Inner (at **)' +
|
' in Inner (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -619,8 +628,7 @@ describe('memo', () => {
|
||||||
'\n\nCheck the top-level render call using <Inner>. It was passed a child from Inner. ' +
|
'\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' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
' in Inner (at **)' +
|
' in Inner (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -640,8 +648,7 @@ describe('memo', () => {
|
||||||
'\n\nCheck the top-level render call using <Outer>. It was passed a child from Outer. ' +
|
'\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' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
' in Outer (at **)' +
|
' in Outer (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -663,8 +670,7 @@ describe('memo', () => {
|
||||||
'\n\nCheck the top-level render call using <Inner>. It was passed a child from Inner. ' +
|
'\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' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
' in Inner (at **)' +
|
' in Inner (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ describe('ReactOwnerStacks', () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// @gate __DEV__ && enableOwnerStacks
|
// @gate __DEV__
|
||||||
it('can get the component owner stacks during rendering in dev', async () => {
|
it('can get the component owner stacks during rendering in dev', async () => {
|
||||||
let stack;
|
let stack;
|
||||||
|
|
||||||
|
|
@ -75,7 +75,7 @@ describe('ReactOwnerStacks', () => {
|
||||||
|
|
||||||
it('returns null outside of render', async () => {
|
it('returns null outside of render', async () => {
|
||||||
// Awkward to gate since some builds will have `captureOwnerStack` return null in prod
|
// Awkward to gate since some builds will have `captureOwnerStack` return null in prod
|
||||||
if (__DEV__ && gate('enableOwnerStacks')) {
|
if (__DEV__) {
|
||||||
expect(React.captureOwnerStack()).toBe(null);
|
expect(React.captureOwnerStack()).toBe(null);
|
||||||
|
|
||||||
await act(() => {
|
await act(() => {
|
||||||
|
|
|
||||||
|
|
@ -257,9 +257,6 @@ describe('ReactUse', () => {
|
||||||
'A component was suspended by an uncached promise. Creating ' +
|
'A component was suspended by an uncached promise. Creating ' +
|
||||||
'promises inside a Client Component or hook is not yet ' +
|
'promises inside a Client Component or hook is not yet ' +
|
||||||
'supported, except via a Suspense-compatible library or framework.\n' +
|
'supported, except via a Suspense-compatible library or framework.\n' +
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: ' in Async (at **)\n' + ' in Suspense (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
assertLog(['ABC']);
|
assertLog(['ABC']);
|
||||||
|
|
@ -430,20 +427,10 @@ describe('ReactUse', () => {
|
||||||
'A component was suspended by an uncached promise. Creating ' +
|
'A component was suspended by an uncached promise. Creating ' +
|
||||||
'promises inside a Client Component or hook is not yet ' +
|
'promises inside a Client Component or hook is not yet ' +
|
||||||
'supported, except via a Suspense-compatible library or framework.\n' +
|
'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 **)',
|
' in App (at **)',
|
||||||
'A component was suspended by an uncached promise. Creating ' +
|
'A component was suspended by an uncached promise. Creating ' +
|
||||||
'promises inside a Client Component or hook is not yet ' +
|
'promises inside a Client Component or hook is not yet ' +
|
||||||
'supported, except via a Suspense-compatible library or framework.\n' +
|
'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 **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
assertLog([
|
assertLog([
|
||||||
|
|
@ -617,8 +604,7 @@ describe('ReactUse', () => {
|
||||||
'A component was suspended by an uncached promise. ' +
|
'A component was suspended by an uncached promise. ' +
|
||||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||||
'except via a Suspense-compatible library or framework.\n' +
|
'except via a Suspense-compatible library or framework.\n' +
|
||||||
' in App (at **)\n' +
|
' in App (at **)',
|
||||||
' in Suspense (at **)',
|
|
||||||
]);
|
]);
|
||||||
expect(root).toMatchRenderedOutput('Async');
|
expect(root).toMatchRenderedOutput('Async');
|
||||||
});
|
});
|
||||||
|
|
@ -667,8 +653,7 @@ describe('ReactUse', () => {
|
||||||
'A component was suspended by an uncached promise. ' +
|
'A component was suspended by an uncached promise. ' +
|
||||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||||
'except via a Suspense-compatible library or framework.\n' +
|
'except via a Suspense-compatible library or framework.\n' +
|
||||||
' in App (at **)\n' +
|
' in App (at **)',
|
||||||
' in Suspense (at **)',
|
|
||||||
]);
|
]);
|
||||||
expect(root).toMatchRenderedOutput('Async');
|
expect(root).toMatchRenderedOutput('Async');
|
||||||
});
|
});
|
||||||
|
|
@ -1216,8 +1201,7 @@ describe('ReactUse', () => {
|
||||||
'A component was suspended by an uncached promise. ' +
|
'A component was suspended by an uncached promise. ' +
|
||||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||||
'except via a Suspense-compatible library or framework.\n' +
|
'except via a Suspense-compatible library or framework.\n' +
|
||||||
' in AsyncText (at **)\n' +
|
' in AsyncText (at **)',
|
||||||
' in Suspense (at **)',
|
|
||||||
]);
|
]);
|
||||||
expect(root).toMatchRenderedOutput('A(Loading B...)');
|
expect(root).toMatchRenderedOutput('A(Loading B...)');
|
||||||
|
|
||||||
|
|
@ -1243,9 +1227,7 @@ describe('ReactUse', () => {
|
||||||
'A component was suspended by an uncached promise. ' +
|
'A component was suspended by an uncached promise. ' +
|
||||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||||
'except via a Suspense-compatible library or framework.\n' +
|
'except via a Suspense-compatible library or framework.\n' +
|
||||||
' in AsyncText (at **)\n' +
|
' in AsyncText (at **)',
|
||||||
' in Suspense (at **)\n' +
|
|
||||||
' in Suspense (at **)',
|
|
||||||
]);
|
]);
|
||||||
expect(root).toMatchRenderedOutput('AB(Loading C...)');
|
expect(root).toMatchRenderedOutput('AB(Loading C...)');
|
||||||
|
|
||||||
|
|
@ -1263,10 +1245,7 @@ describe('ReactUse', () => {
|
||||||
'A component was suspended by an uncached promise. ' +
|
'A component was suspended by an uncached promise. ' +
|
||||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||||
'except via a Suspense-compatible library or framework.\n' +
|
'except via a Suspense-compatible library or framework.\n' +
|
||||||
' in AsyncText (at **)\n' +
|
' in AsyncText (at **)',
|
||||||
' in Suspense (at **)\n' +
|
|
||||||
' in Suspense (at **)\n' +
|
|
||||||
' in Suspense (at **)',
|
|
||||||
]);
|
]);
|
||||||
expect(root).toMatchRenderedOutput('ABC');
|
expect(root).toMatchRenderedOutput('ABC');
|
||||||
});
|
});
|
||||||
|
|
@ -1301,16 +1280,10 @@ describe('ReactUse', () => {
|
||||||
'A component was suspended by an uncached promise. ' +
|
'A component was suspended by an uncached promise. ' +
|
||||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||||
'except via a Suspense-compatible library or framework.\n' +
|
'except via a Suspense-compatible library or framework.\n' +
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: ' in Async (at **)\n' + ' in Suspense (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
'A component was suspended by an uncached promise. ' +
|
'A component was suspended by an uncached promise. ' +
|
||||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||||
'except via a Suspense-compatible library or framework.\n' +
|
'except via a Suspense-compatible library or framework.\n' +
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: ' in Async (at **)\n' + ' in Suspense (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
expect(root).toMatchRenderedOutput('A1');
|
expect(root).toMatchRenderedOutput('A1');
|
||||||
|
|
@ -1685,10 +1658,6 @@ describe('ReactUse', () => {
|
||||||
'A component was suspended by an uncached promise. ' +
|
'A component was suspended by an uncached promise. ' +
|
||||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||||
'except via a Suspense-compatible library or framework.\n' +
|
'except via a Suspense-compatible library or framework.\n' +
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: ' in **/ReactUse-test.js:**:** (at **)\n' +
|
|
||||||
' in Suspense (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
expect(root).toMatchRenderedOutput('Async');
|
expect(root).toMatchRenderedOutput('Async');
|
||||||
|
|
@ -1723,10 +1692,6 @@ describe('ReactUse', () => {
|
||||||
'A component was suspended by an uncached promise. ' +
|
'A component was suspended by an uncached promise. ' +
|
||||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||||
'except via a Suspense-compatible library or framework.\n' +
|
'except via a Suspense-compatible library or framework.\n' +
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: ' in **/ReactUse-test.js:**:** (at **)\n' +
|
|
||||||
' in Suspense (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
expect(root).toMatchRenderedOutput('Async');
|
expect(root).toMatchRenderedOutput('Async');
|
||||||
|
|
@ -1752,10 +1717,6 @@ describe('ReactUse', () => {
|
||||||
'A component was suspended by an uncached promise. ' +
|
'A component was suspended by an uncached promise. ' +
|
||||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||||
'except via a Suspense-compatible library or framework.\n' +
|
'except via a Suspense-compatible library or framework.\n' +
|
||||||
(gate('enableOwnerStacks')
|
|
||||||
? ''
|
|
||||||
: ' in **/ReactUse-test.js:**:** (at **)\n' +
|
|
||||||
' in Suspense (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
expect(root).toMatchRenderedOutput('Async!');
|
expect(root).toMatchRenderedOutput('Async!');
|
||||||
|
|
@ -1810,36 +1771,17 @@ describe('ReactUse', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'ContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
'ContextProvider uses the legacy childContextTypes API which will soon be removed. ' +
|
||||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(gate('enableOwnerStacks') ? '' : ' in ContextProvider (at **)\n') +
|
|
||||||
' in App (at **)',
|
' in App (at **)',
|
||||||
'Async uses the legacy contextTypes API which will be removed soon. ' +
|
'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' +
|
'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 **)',
|
' in App (at **)',
|
||||||
'A component was suspended by an uncached promise. ' +
|
'A component was suspended by an uncached promise. ' +
|
||||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||||
'except via a Suspense-compatible library or framework.\n' +
|
'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 **)',
|
' in App (at **)',
|
||||||
'A component was suspended by an uncached promise. ' +
|
'A component was suspended by an uncached promise. ' +
|
||||||
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
'Creating promises inside a Client Component or hook is not yet supported, ' +
|
||||||
'except via a Suspense-compatible library or framework.\n' +
|
'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 **)',
|
' in App (at **)',
|
||||||
]);
|
]);
|
||||||
expect(root).toMatchRenderedOutput(
|
expect(root).toMatchRenderedOutput(
|
||||||
|
|
@ -1921,8 +1863,7 @@ describe('ReactUse', () => {
|
||||||
'Only Server Components can be async at the moment. ' +
|
'Only Server Components can be async at the moment. ' +
|
||||||
"This error is often caused by accidentally adding `'use client'` " +
|
"This error is often caused by accidentally adding `'use client'` " +
|
||||||
'to a module that was originally written for the server.\n' +
|
'to a module that was originally written for the server.\n' +
|
||||||
' in AsyncClientComponent (at **)' +
|
' in AsyncClientComponent (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in ErrorBoundary (at **)'),
|
|
||||||
]);
|
]);
|
||||||
assertLog([
|
assertLog([
|
||||||
'An unknown Component is an async Client Component. ' +
|
'An unknown Component is an async Client Component. ' +
|
||||||
|
|
@ -1977,8 +1918,7 @@ describe('ReactUse', () => {
|
||||||
'Only Server Components can be async at the moment. ' +
|
'Only Server Components can be async at the moment. ' +
|
||||||
"This error is often caused by accidentally adding `'use client'` " +
|
"This error is often caused by accidentally adding `'use client'` " +
|
||||||
'to a module that was originally written for the server.\n' +
|
'to a module that was originally written for the server.\n' +
|
||||||
' in AsyncClientComponent (at **)' +
|
' in AsyncClientComponent (at **)',
|
||||||
(gate('enableOwnerStacks') ? '' : '\n in ErrorBoundary (at **)'),
|
|
||||||
]);
|
]);
|
||||||
assertLog([
|
assertLog([
|
||||||
'An unknown Component is an async Client Component. ' +
|
'An unknown Component is an async Client Component. ' +
|
||||||
|
|
|
||||||
|
|
@ -1170,25 +1170,15 @@ describe('ReactFlightDOMBrowser', () => {
|
||||||
);
|
);
|
||||||
const result = await ReactServerDOMClient.createFromReadableStream(stream);
|
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(() => {
|
await act(() => {
|
||||||
root.render(result);
|
root.render(result);
|
||||||
});
|
});
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
assertConsoleErrorDev([
|
||||||
assertConsoleErrorDev([
|
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
'Check the top-level render call using <ParentClient>. ' +
|
||||||
'Check the top-level render call using <ParentClient>. ' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
' in div (at **)',
|
||||||
' in div (at **)',
|
]);
|
||||||
]);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('basic use(promise)', async () => {
|
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 () => {
|
it('can get the component owner stacks asynchronously', async () => {
|
||||||
let stack;
|
let stack;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,7 @@ import {
|
||||||
REACT_VIEW_TRANSITION_TYPE,
|
REACT_VIEW_TRANSITION_TYPE,
|
||||||
} from 'shared/ReactSymbols';
|
} from 'shared/ReactSymbols';
|
||||||
|
|
||||||
import {
|
import {enableViewTransition} from 'shared/ReactFeatureFlags';
|
||||||
enableOwnerStacks,
|
|
||||||
enableViewTransition,
|
|
||||||
} from 'shared/ReactFeatureFlags';
|
|
||||||
|
|
||||||
import {formatOwnerStack} from 'shared/ReactOwnerStackFrames';
|
import {formatOwnerStack} from 'shared/ReactOwnerStackFrames';
|
||||||
|
|
||||||
|
|
@ -134,7 +131,7 @@ function describeFunctionComponentFrameWithoutLineNumber(fn: Function): string {
|
||||||
export function getOwnerStackByComponentStackNodeInDev(
|
export function getOwnerStackByComponentStackNodeInDev(
|
||||||
componentStack: ComponentStackNode,
|
componentStack: ComponentStackNode,
|
||||||
): string {
|
): string {
|
||||||
if (!enableOwnerStacks || !__DEV__) {
|
if (!__DEV__) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
114
packages/react-server/src/ReactFizzServer.js
vendored
114
packages/react-server/src/ReactFizzServer.js
vendored
|
|
@ -165,7 +165,6 @@ import {
|
||||||
enableRenderableContext,
|
enableRenderableContext,
|
||||||
disableDefaultPropsExceptForClasses,
|
disableDefaultPropsExceptForClasses,
|
||||||
enableAsyncIterableChildren,
|
enableAsyncIterableChildren,
|
||||||
enableOwnerStacks,
|
|
||||||
enableViewTransition,
|
enableViewTransition,
|
||||||
} from 'shared/ReactFeatureFlags';
|
} from 'shared/ReactFeatureFlags';
|
||||||
|
|
||||||
|
|
@ -787,7 +786,7 @@ function createRenderTask(
|
||||||
if (!disableLegacyContext) {
|
if (!disableLegacyContext) {
|
||||||
task.legacyContext = legacyContext;
|
task.legacyContext = legacyContext;
|
||||||
}
|
}
|
||||||
if (__DEV__ && enableOwnerStacks) {
|
if (__DEV__) {
|
||||||
task.debugTask = debugTask;
|
task.debugTask = debugTask;
|
||||||
}
|
}
|
||||||
abortSet.add(task);
|
abortSet.add(task);
|
||||||
|
|
@ -840,7 +839,7 @@ function createReplayTask(
|
||||||
if (!disableLegacyContext) {
|
if (!disableLegacyContext) {
|
||||||
task.legacyContext = legacyContext;
|
task.legacyContext = legacyContext;
|
||||||
}
|
}
|
||||||
if (__DEV__ && enableOwnerStacks) {
|
if (__DEV__) {
|
||||||
task.debugTask = debugTask;
|
task.debugTask = debugTask;
|
||||||
}
|
}
|
||||||
abortSet.add(task);
|
abortSet.add(task);
|
||||||
|
|
@ -875,12 +874,9 @@ function getCurrentStackInDEV(): string {
|
||||||
if (currentTaskInDEV === null || currentTaskInDEV.componentStack === null) {
|
if (currentTaskInDEV === null || currentTaskInDEV.componentStack === null) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
if (enableOwnerStacks) {
|
return getOwnerStackByComponentStackNodeInDev(
|
||||||
return getOwnerStackByComponentStackNodeInDev(
|
currentTaskInDEV.componentStack,
|
||||||
currentTaskInDEV.componentStack,
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
return getStackByComponentStackNode(currentTaskInDEV.componentStack);
|
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
@ -907,18 +903,16 @@ function pushServerComponentStack(
|
||||||
if (typeof componentInfo.name !== 'string') {
|
if (typeof componentInfo.name !== 'string') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (enableOwnerStacks && componentInfo.debugStack === undefined) {
|
if (componentInfo.debugStack === undefined) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
task.componentStack = {
|
task.componentStack = {
|
||||||
parent: task.componentStack,
|
parent: task.componentStack,
|
||||||
type: componentInfo,
|
type: componentInfo,
|
||||||
owner: componentInfo.owner,
|
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 element: any = node;
|
||||||
const type = element.type;
|
const type = element.type;
|
||||||
const owner = __DEV__ ? element._owner : null;
|
const owner = __DEV__ ? element._owner : null;
|
||||||
const stack = __DEV__ && enableOwnerStacks ? element._debugStack : null;
|
const stack = __DEV__ ? element._debugStack : null;
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
pushServerComponentStack(task, element._debugInfo);
|
pushServerComponentStack(task, element._debugInfo);
|
||||||
if (enableOwnerStacks) {
|
task.debugTask = element._debugTask;
|
||||||
task.debugTask = element._debugTask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
task.componentStack = createComponentStackFromType(
|
task.componentStack = createComponentStackFromType(
|
||||||
task.componentStack,
|
task.componentStack,
|
||||||
|
|
@ -1056,7 +1048,7 @@ function logPostpone(
|
||||||
// If this callback errors, we intentionally let that error bubble up to become a fatal error
|
// 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.
|
// so that someone fixes the error reporting instead of hiding it.
|
||||||
const onPostpone = request.onPostpone;
|
const onPostpone = request.onPostpone;
|
||||||
if (__DEV__ && enableOwnerStacks && debugTask) {
|
if (__DEV__ && debugTask) {
|
||||||
debugTask.run(onPostpone.bind(null, reason, postponeInfo));
|
debugTask.run(onPostpone.bind(null, reason, postponeInfo));
|
||||||
} else {
|
} else {
|
||||||
onPostpone(reason, postponeInfo);
|
onPostpone(reason, postponeInfo);
|
||||||
|
|
@ -1073,7 +1065,7 @@ function logRecoverableError(
|
||||||
// so that someone fixes the error reporting instead of hiding it.
|
// so that someone fixes the error reporting instead of hiding it.
|
||||||
const onError = request.onError;
|
const onError = request.onError;
|
||||||
const errorDigest =
|
const errorDigest =
|
||||||
__DEV__ && enableOwnerStacks && debugTask
|
__DEV__ && debugTask
|
||||||
? debugTask.run(onError.bind(null, error, errorInfo))
|
? debugTask.run(onError.bind(null, error, errorInfo))
|
||||||
: onError(error, errorInfo);
|
: onError(error, errorInfo);
|
||||||
if (errorDigest != null && typeof errorDigest !== 'string') {
|
if (errorDigest != null && typeof errorDigest !== 'string') {
|
||||||
|
|
@ -1101,7 +1093,7 @@ function fatalError(
|
||||||
// It's also called if React itself or its host configs errors.
|
// It's also called if React itself or its host configs errors.
|
||||||
const onShellError = request.onShellError;
|
const onShellError = request.onShellError;
|
||||||
const onFatalError = request.onFatalError;
|
const onFatalError = request.onFatalError;
|
||||||
if (__DEV__ && enableOwnerStacks && debugTask) {
|
if (__DEV__ && debugTask) {
|
||||||
debugTask.run(onShellError.bind(null, error));
|
debugTask.run(onShellError.bind(null, error));
|
||||||
debugTask.run(onFatalError.bind(null, error));
|
debugTask.run(onFatalError.bind(null, error));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1261,7 +1253,7 @@ function renderSuspenseBoundary(
|
||||||
task.componentStack,
|
task.componentStack,
|
||||||
task.isFallback,
|
task.isFallback,
|
||||||
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
pushComponentStack(suspendedPrimaryTask);
|
pushComponentStack(suspendedPrimaryTask);
|
||||||
request.pingedTasks.push(suspendedPrimaryTask);
|
request.pingedTasks.push(suspendedPrimaryTask);
|
||||||
|
|
@ -1334,7 +1326,7 @@ function renderSuspenseBoundary(
|
||||||
request,
|
request,
|
||||||
postponeInstance.message,
|
postponeInstance.message,
|
||||||
thrownInfo,
|
thrownInfo,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
// TODO: Figure out a better signal than a magic digest value.
|
// TODO: Figure out a better signal than a magic digest value.
|
||||||
errorDigest = 'POSTPONE';
|
errorDigest = 'POSTPONE';
|
||||||
|
|
@ -1343,7 +1335,7 @@ function renderSuspenseBoundary(
|
||||||
request,
|
request,
|
||||||
error,
|
error,
|
||||||
thrownInfo,
|
thrownInfo,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
encodeErrorForBoundary(
|
encodeErrorForBoundary(
|
||||||
|
|
@ -1387,7 +1379,7 @@ function renderSuspenseBoundary(
|
||||||
task.componentStack,
|
task.componentStack,
|
||||||
true,
|
true,
|
||||||
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
pushComponentStack(suspendedFallbackTask);
|
pushComponentStack(suspendedFallbackTask);
|
||||||
// TODO: This should be queued at a separate lower priority queue so that we only work
|
// TODO: This should be queued at a separate lower priority queue so that we only work
|
||||||
|
|
@ -1485,7 +1477,7 @@ function replaySuspenseBoundary(
|
||||||
request,
|
request,
|
||||||
postponeInstance.message,
|
postponeInstance.message,
|
||||||
thrownInfo,
|
thrownInfo,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
// TODO: Figure out a better signal than a magic digest value.
|
// TODO: Figure out a better signal than a magic digest value.
|
||||||
errorDigest = 'POSTPONE';
|
errorDigest = 'POSTPONE';
|
||||||
|
|
@ -1494,7 +1486,7 @@ function replaySuspenseBoundary(
|
||||||
request,
|
request,
|
||||||
error,
|
error,
|
||||||
thrownInfo,
|
thrownInfo,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
encodeErrorForBoundary(
|
encodeErrorForBoundary(
|
||||||
|
|
@ -1545,7 +1537,7 @@ function replaySuspenseBoundary(
|
||||||
task.componentStack,
|
task.componentStack,
|
||||||
true,
|
true,
|
||||||
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
|
|
||||||
pushComponentStack(suspendedFallbackTask);
|
pushComponentStack(suspendedFallbackTask);
|
||||||
|
|
@ -1587,7 +1579,7 @@ function renderPreamble(
|
||||||
task.componentStack,
|
task.componentStack,
|
||||||
task.isFallback,
|
task.isFallback,
|
||||||
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
pushComponentStack(preambleTask);
|
pushComponentStack(preambleTask);
|
||||||
request.pingedTasks.push(preambleTask);
|
request.pingedTasks.push(preambleTask);
|
||||||
|
|
@ -2489,7 +2481,7 @@ function replayElement(
|
||||||
thrownInfo,
|
thrownInfo,
|
||||||
childNodes,
|
childNodes,
|
||||||
childSlots,
|
childSlots,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
task.replay = replay;
|
task.replay = replay;
|
||||||
|
|
@ -2654,15 +2646,14 @@ function renderNodeDestructive(
|
||||||
task.childIndex = childIndex;
|
task.childIndex = childIndex;
|
||||||
|
|
||||||
const previousComponentStack = task.componentStack;
|
const previousComponentStack = task.componentStack;
|
||||||
const previousDebugTask =
|
const previousDebugTask = __DEV__ ? task.debugTask : null;
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null;
|
|
||||||
|
|
||||||
pushComponentStack(task);
|
pushComponentStack(task);
|
||||||
|
|
||||||
retryNode(request, task);
|
retryNode(request, task);
|
||||||
|
|
||||||
task.componentStack = previousComponentStack;
|
task.componentStack = previousComponentStack;
|
||||||
if (__DEV__ && enableOwnerStacks) {
|
if (__DEV__) {
|
||||||
task.debugTask = previousDebugTask;
|
task.debugTask = previousDebugTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2689,8 +2680,7 @@ function retryNode(request: Request, task: Task): void {
|
||||||
const refProp = props.ref;
|
const refProp = props.ref;
|
||||||
const ref = refProp !== undefined ? refProp : null;
|
const ref = refProp !== undefined ? refProp : null;
|
||||||
|
|
||||||
const debugTask: null | ConsoleTask =
|
const debugTask: null | ConsoleTask = __DEV__ ? task.debugTask : null;
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null;
|
|
||||||
|
|
||||||
const name = getComponentNameFromType(type);
|
const name = getComponentNameFromType(type);
|
||||||
const keyOrIndex =
|
const keyOrIndex =
|
||||||
|
|
@ -3002,7 +2992,7 @@ function replayFragment(
|
||||||
thrownInfo,
|
thrownInfo,
|
||||||
childNodes,
|
childNodes,
|
||||||
childSlots,
|
childSlots,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
task.replay = replay;
|
task.replay = replay;
|
||||||
|
|
@ -3094,7 +3084,7 @@ function warnForMissingKey(request: Request, task: Task, child: mixed): void {
|
||||||
task.componentStack,
|
task.componentStack,
|
||||||
(child: any).type,
|
(child: any).type,
|
||||||
(child: any)._owner,
|
(child: any)._owner,
|
||||||
enableOwnerStacks ? (child: any)._debugStack : null,
|
(child: any)._debugStack,
|
||||||
);
|
);
|
||||||
task.componentStack = stackFrame;
|
task.componentStack = stackFrame;
|
||||||
console.error(
|
console.error(
|
||||||
|
|
@ -3117,9 +3107,7 @@ function renderChildrenArray(
|
||||||
const previousComponentStack = task.componentStack;
|
const previousComponentStack = task.componentStack;
|
||||||
let previousDebugTask = null;
|
let previousDebugTask = null;
|
||||||
if (__DEV__) {
|
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
|
// We read debugInfo from task.node instead of children because it might have been an
|
||||||
// unwrapped iterable so we read from the original node.
|
// unwrapped iterable so we read from the original node.
|
||||||
pushServerComponentStack(task, (task.node: any)._debugInfo);
|
pushServerComponentStack(task, (task.node: any)._debugInfo);
|
||||||
|
|
@ -3137,9 +3125,7 @@ function renderChildrenArray(
|
||||||
task.keyPath = prevKeyPath;
|
task.keyPath = prevKeyPath;
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
task.componentStack = previousComponentStack;
|
task.componentStack = previousComponentStack;
|
||||||
if (enableOwnerStacks) {
|
task.debugTask = previousDebugTask;
|
||||||
task.debugTask = previousDebugTask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -3173,9 +3159,7 @@ function renderChildrenArray(
|
||||||
task.keyPath = prevKeyPath;
|
task.keyPath = prevKeyPath;
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
task.componentStack = previousComponentStack;
|
task.componentStack = previousComponentStack;
|
||||||
if (enableOwnerStacks) {
|
task.debugTask = previousDebugTask;
|
||||||
task.debugTask = previousDebugTask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -3198,9 +3182,7 @@ function renderChildrenArray(
|
||||||
task.keyPath = prevKeyPath;
|
task.keyPath = prevKeyPath;
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
task.componentStack = previousComponentStack;
|
task.componentStack = previousComponentStack;
|
||||||
if (enableOwnerStacks) {
|
task.debugTask = previousDebugTask;
|
||||||
task.debugTask = previousDebugTask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3394,12 +3376,7 @@ function injectPostponedHole(
|
||||||
reason: string,
|
reason: string,
|
||||||
thrownInfo: ThrownInfo,
|
thrownInfo: ThrownInfo,
|
||||||
): Segment {
|
): Segment {
|
||||||
logPostpone(
|
logPostpone(request, reason, thrownInfo, __DEV__ ? task.debugTask : null);
|
||||||
request,
|
|
||||||
reason,
|
|
||||||
thrownInfo,
|
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
|
||||||
);
|
|
||||||
// Something suspended, we'll need to create a new segment and resolve it later.
|
// Something suspended, we'll need to create a new segment and resolve it later.
|
||||||
const segment = task.blockedSegment;
|
const segment = task.blockedSegment;
|
||||||
const insertionIndex = segment.chunks.length;
|
const insertionIndex = segment.chunks.length;
|
||||||
|
|
@ -3440,7 +3417,7 @@ function spawnNewSuspendedReplayTask(
|
||||||
task.componentStack,
|
task.componentStack,
|
||||||
task.isFallback,
|
task.isFallback,
|
||||||
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3482,7 +3459,7 @@ function spawnNewSuspendedRenderTask(
|
||||||
task.componentStack,
|
task.componentStack,
|
||||||
task.isFallback,
|
task.isFallback,
|
||||||
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
!disableLegacyContext ? task.legacyContext : emptyContextObject,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3504,8 +3481,7 @@ function renderNode(
|
||||||
const previousKeyPath = task.keyPath;
|
const previousKeyPath = task.keyPath;
|
||||||
const previousTreeContext = task.treeContext;
|
const previousTreeContext = task.treeContext;
|
||||||
const previousComponentStack = task.componentStack;
|
const previousComponentStack = task.componentStack;
|
||||||
const previousDebugTask =
|
const previousDebugTask = __DEV__ ? task.debugTask : null;
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null;
|
|
||||||
let x;
|
let x;
|
||||||
// Store how much we've pushed at this point so we can reset it in case something
|
// Store how much we've pushed at this point so we can reset it in case something
|
||||||
// suspended partially through writing something.
|
// suspended partially through writing something.
|
||||||
|
|
@ -3551,7 +3527,7 @@ function renderNode(
|
||||||
task.keyPath = previousKeyPath;
|
task.keyPath = previousKeyPath;
|
||||||
task.treeContext = previousTreeContext;
|
task.treeContext = previousTreeContext;
|
||||||
task.componentStack = previousComponentStack;
|
task.componentStack = previousComponentStack;
|
||||||
if (__DEV__ && enableOwnerStacks) {
|
if (__DEV__) {
|
||||||
task.debugTask = previousDebugTask;
|
task.debugTask = previousDebugTask;
|
||||||
}
|
}
|
||||||
// Restore all active ReactContexts to what they were before.
|
// Restore all active ReactContexts to what they were before.
|
||||||
|
|
@ -3584,7 +3560,7 @@ function renderNode(
|
||||||
task.keyPath = previousKeyPath;
|
task.keyPath = previousKeyPath;
|
||||||
task.treeContext = previousTreeContext;
|
task.treeContext = previousTreeContext;
|
||||||
task.componentStack = previousComponentStack;
|
task.componentStack = previousComponentStack;
|
||||||
if (__DEV__ && enableOwnerStacks) {
|
if (__DEV__) {
|
||||||
task.debugTask = previousDebugTask;
|
task.debugTask = previousDebugTask;
|
||||||
}
|
}
|
||||||
// Restore all active ReactContexts to what they were before.
|
// Restore all active ReactContexts to what they were before.
|
||||||
|
|
@ -3642,7 +3618,7 @@ function renderNode(
|
||||||
task.keyPath = previousKeyPath;
|
task.keyPath = previousKeyPath;
|
||||||
task.treeContext = previousTreeContext;
|
task.treeContext = previousTreeContext;
|
||||||
task.componentStack = previousComponentStack;
|
task.componentStack = previousComponentStack;
|
||||||
if (__DEV__ && enableOwnerStacks) {
|
if (__DEV__) {
|
||||||
task.debugTask = previousDebugTask;
|
task.debugTask = previousDebugTask;
|
||||||
}
|
}
|
||||||
// Restore all active ReactContexts to what they were before.
|
// Restore all active ReactContexts to what they were before.
|
||||||
|
|
@ -3681,7 +3657,7 @@ function renderNode(
|
||||||
task.keyPath = previousKeyPath;
|
task.keyPath = previousKeyPath;
|
||||||
task.treeContext = previousTreeContext;
|
task.treeContext = previousTreeContext;
|
||||||
task.componentStack = previousComponentStack;
|
task.componentStack = previousComponentStack;
|
||||||
if (__DEV__ && enableOwnerStacks) {
|
if (__DEV__) {
|
||||||
task.debugTask = previousDebugTask;
|
task.debugTask = previousDebugTask;
|
||||||
}
|
}
|
||||||
// Restore all active ReactContexts to what they were before.
|
// Restore all active ReactContexts to what they were before.
|
||||||
|
|
@ -3714,7 +3690,7 @@ function renderNode(
|
||||||
task.keyPath = previousKeyPath;
|
task.keyPath = previousKeyPath;
|
||||||
task.treeContext = previousTreeContext;
|
task.treeContext = previousTreeContext;
|
||||||
task.componentStack = previousComponentStack;
|
task.componentStack = previousComponentStack;
|
||||||
if (__DEV__ && enableOwnerStacks) {
|
if (__DEV__) {
|
||||||
task.debugTask = previousDebugTask;
|
task.debugTask = previousDebugTask;
|
||||||
}
|
}
|
||||||
// Restore all active ReactContexts to what they were before.
|
// Restore all active ReactContexts to what they were before.
|
||||||
|
|
@ -4421,14 +4397,14 @@ function retryRenderTask(
|
||||||
request,
|
request,
|
||||||
postponeInstance.message,
|
postponeInstance.message,
|
||||||
thrownInfo,
|
thrownInfo,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
logRecoverableError(
|
logRecoverableError(
|
||||||
request,
|
request,
|
||||||
x,
|
x,
|
||||||
thrownInfo,
|
thrownInfo,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4464,7 +4440,7 @@ function retryRenderTask(
|
||||||
request,
|
request,
|
||||||
postponeInstance.message,
|
postponeInstance.message,
|
||||||
postponeInfo,
|
postponeInfo,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
trackPostpone(request, trackedPostpones, task, segment);
|
trackPostpone(request, trackedPostpones, task, segment);
|
||||||
finishedTask(request, task.blockedBoundary, segment);
|
finishedTask(request, task.blockedBoundary, segment);
|
||||||
|
|
@ -4481,7 +4457,7 @@ function retryRenderTask(
|
||||||
task.blockedBoundary,
|
task.blockedBoundary,
|
||||||
x,
|
x,
|
||||||
errorInfo,
|
errorInfo,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -4560,7 +4536,7 @@ function retryReplayTask(request: Request, task: ReplayTask): void {
|
||||||
errorInfo,
|
errorInfo,
|
||||||
task.replay.nodes,
|
task.replay.nodes,
|
||||||
task.replay.slots,
|
task.replay.slots,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
request.pendingRootTasks--;
|
request.pendingRootTasks--;
|
||||||
if (request.pendingRootTasks === 0) {
|
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,
|
enablePostpone,
|
||||||
enableHalt,
|
enableHalt,
|
||||||
enableTaint,
|
enableTaint,
|
||||||
enableOwnerStacks,
|
|
||||||
enableProfilerTimer,
|
enableProfilerTimer,
|
||||||
enableComponentPerformanceTrack,
|
enableComponentPerformanceTrack,
|
||||||
} from 'shared/ReactFeatureFlags';
|
} from 'shared/ReactFeatureFlags';
|
||||||
|
|
@ -254,15 +253,11 @@ if (__DEV__ && typeof console === 'object' && console !== null) {
|
||||||
|
|
||||||
function getCurrentStackInDEV(): string {
|
function getCurrentStackInDEV(): string {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
if (enableOwnerStacks) {
|
const owner: null | ReactComponentInfo = resolveOwner();
|
||||||
const owner: null | ReactComponentInfo = resolveOwner();
|
if (owner === null) {
|
||||||
if (owner === null) {
|
return '';
|
||||||
return '';
|
|
||||||
}
|
|
||||||
return getOwnerStackByComponentInfoInDev(owner);
|
|
||||||
}
|
}
|
||||||
// We don't have Parent Stacks in Flight.
|
return getOwnerStackByComponentInfoInDev(owner);
|
||||||
return '';
|
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
@ -624,8 +619,8 @@ function serializeThenable(
|
||||||
task.implicitSlot,
|
task.implicitSlot,
|
||||||
request.abortableTasks,
|
request.abortableTasks,
|
||||||
__DEV__ ? task.debugOwner : null,
|
__DEV__ ? task.debugOwner : null,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugStack : null,
|
__DEV__ ? task.debugStack : null,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
// If this came from Flight, forward any debug info into this new row.
|
// If this came from Flight, forward any debug info into this new row.
|
||||||
|
|
@ -744,8 +739,8 @@ function serializeReadableStream(
|
||||||
task.implicitSlot,
|
task.implicitSlot,
|
||||||
request.abortableTasks,
|
request.abortableTasks,
|
||||||
__DEV__ ? task.debugOwner : null,
|
__DEV__ ? task.debugOwner : null,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugStack : null,
|
__DEV__ ? task.debugStack : null,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
request.abortableTasks.delete(streamTask);
|
request.abortableTasks.delete(streamTask);
|
||||||
|
|
||||||
|
|
@ -834,8 +829,8 @@ function serializeAsyncIterable(
|
||||||
task.implicitSlot,
|
task.implicitSlot,
|
||||||
request.abortableTasks,
|
request.abortableTasks,
|
||||||
__DEV__ ? task.debugOwner : null,
|
__DEV__ ? task.debugOwner : null,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugStack : null,
|
__DEV__ ? task.debugStack : null,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
request.abortableTasks.delete(streamTask);
|
request.abortableTasks.delete(streamTask);
|
||||||
|
|
||||||
|
|
@ -1035,23 +1030,21 @@ function callWithDebugContextInDEV<A, T>(
|
||||||
key: null,
|
key: null,
|
||||||
owner: task.debugOwner,
|
owner: task.debugOwner,
|
||||||
};
|
};
|
||||||
if (enableOwnerStacks) {
|
// $FlowFixMe[cannot-write]
|
||||||
// $FlowFixMe[cannot-write]
|
componentDebugInfo.stack =
|
||||||
componentDebugInfo.stack =
|
task.debugStack === null
|
||||||
task.debugStack === null
|
? null
|
||||||
? null
|
: filterStackTrace(request, task.debugStack, 1);
|
||||||
: filterStackTrace(request, task.debugStack, 1);
|
// $FlowFixMe[cannot-write]
|
||||||
// $FlowFixMe[cannot-write]
|
componentDebugInfo.debugStack = task.debugStack;
|
||||||
componentDebugInfo.debugStack = task.debugStack;
|
// $FlowFixMe[cannot-write]
|
||||||
// $FlowFixMe[cannot-write]
|
componentDebugInfo.debugTask = task.debugTask;
|
||||||
componentDebugInfo.debugTask = task.debugTask;
|
|
||||||
}
|
|
||||||
const debugTask = task.debugTask;
|
const debugTask = task.debugTask;
|
||||||
// We don't need the async component storage context here so we only set the
|
// We don't need the async component storage context here so we only set the
|
||||||
// synchronous tracking of owner.
|
// synchronous tracking of owner.
|
||||||
setCurrentOwner(componentDebugInfo);
|
setCurrentOwner(componentDebugInfo);
|
||||||
try {
|
try {
|
||||||
if (enableOwnerStacks && debugTask) {
|
if (debugTask) {
|
||||||
return debugTask.run(callback.bind(null, arg));
|
return debugTask.run(callback.bind(null, arg));
|
||||||
}
|
}
|
||||||
return callback(arg);
|
return callback(arg);
|
||||||
|
|
@ -1238,22 +1231,18 @@ function renderFunctionComponent<Props>(
|
||||||
key: key,
|
key: key,
|
||||||
owner: task.debugOwner,
|
owner: task.debugOwner,
|
||||||
}: ReactComponentInfo);
|
}: ReactComponentInfo);
|
||||||
if (enableOwnerStacks) {
|
// $FlowFixMe[cannot-write]
|
||||||
// $FlowFixMe[cannot-write]
|
componentDebugInfo.stack =
|
||||||
componentDebugInfo.stack =
|
task.debugStack === null
|
||||||
task.debugStack === null
|
? null
|
||||||
? null
|
: filterStackTrace(request, task.debugStack, 1);
|
||||||
: filterStackTrace(request, task.debugStack, 1);
|
// $FlowFixMe[cannot-write]
|
||||||
// $FlowFixMe[cannot-write]
|
componentDebugInfo.props = props;
|
||||||
componentDebugInfo.props = props;
|
// $FlowFixMe[cannot-write]
|
||||||
// $FlowFixMe[cannot-write]
|
componentDebugInfo.debugStack = task.debugStack;
|
||||||
componentDebugInfo.debugStack = task.debugStack;
|
// $FlowFixMe[cannot-write]
|
||||||
// $FlowFixMe[cannot-write]
|
componentDebugInfo.debugTask = task.debugTask;
|
||||||
componentDebugInfo.debugTask = task.debugTask;
|
|
||||||
} else {
|
|
||||||
// $FlowFixMe[cannot-write]
|
|
||||||
componentDebugInfo.props = props;
|
|
||||||
}
|
|
||||||
// We outline this model eagerly so that we can refer to by reference as an owner.
|
// 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
|
// 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.
|
// 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.
|
// We've emitted the latest environment for this task so we track that.
|
||||||
task.environmentName = componentEnv;
|
task.environmentName = componentEnv;
|
||||||
|
|
||||||
if (enableOwnerStacks && validated === 2) {
|
if (validated === 2) {
|
||||||
warnForMissingKey(request, key, componentDebugInfo, task.debugTask);
|
warnForMissingKey(request, key, componentDebugInfo, task.debugTask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prepareToUseHooksForComponent(prevThenableState, componentDebugInfo);
|
prepareToUseHooksForComponent(prevThenableState, componentDebugInfo);
|
||||||
if (supportsComponentStorage) {
|
if (supportsComponentStorage) {
|
||||||
// Run the component in an Async Context that tracks the current owner.
|
// Run the component in an Async Context that tracks the current owner.
|
||||||
if (enableOwnerStacks && task.debugTask) {
|
if (task.debugTask) {
|
||||||
result = task.debugTask.run(
|
result = task.debugTask.run(
|
||||||
// $FlowFixMe[method-unbinding]
|
// $FlowFixMe[method-unbinding]
|
||||||
componentStorage.run.bind(
|
componentStorage.run.bind(
|
||||||
|
|
@ -1300,7 +1289,7 @@ function renderFunctionComponent<Props>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (enableOwnerStacks && task.debugTask) {
|
if (task.debugTask) {
|
||||||
result = task.debugTask.run(
|
result = task.debugTask.run(
|
||||||
callComponentInDEV.bind(null, Component, props, componentDebugInfo),
|
callComponentInDEV.bind(null, Component, props, componentDebugInfo),
|
||||||
);
|
);
|
||||||
|
|
@ -1387,7 +1376,7 @@ function warnForMissingKey(
|
||||||
|
|
||||||
if (supportsComponentStorage) {
|
if (supportsComponentStorage) {
|
||||||
// Run the component in an Async Context that tracks the current owner.
|
// Run the component in an Async Context that tracks the current owner.
|
||||||
if (enableOwnerStacks && debugTask) {
|
if (debugTask) {
|
||||||
debugTask.run(
|
debugTask.run(
|
||||||
// $FlowFixMe[method-unbinding]
|
// $FlowFixMe[method-unbinding]
|
||||||
componentStorage.run.bind(
|
componentStorage.run.bind(
|
||||||
|
|
@ -1409,7 +1398,7 @@ function warnForMissingKey(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (enableOwnerStacks && debugTask) {
|
if (debugTask) {
|
||||||
debugTask.run(
|
debugTask.run(
|
||||||
callComponentInDEV.bind(null, logKeyError, null, componentDebugInfo),
|
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
|
// We have a Server Component that specifies a key but we're now splitting
|
||||||
// the tree using a fragment.
|
// the tree using a fragment.
|
||||||
const fragment = __DEV__
|
const fragment = __DEV__
|
||||||
? enableOwnerStacks
|
? [
|
||||||
? [
|
REACT_ELEMENT_TYPE,
|
||||||
REACT_ELEMENT_TYPE,
|
REACT_FRAGMENT_TYPE,
|
||||||
REACT_FRAGMENT_TYPE,
|
task.keyPath,
|
||||||
task.keyPath,
|
{children},
|
||||||
{children},
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
0,
|
||||||
0,
|
]
|
||||||
]
|
|
||||||
: [
|
|
||||||
REACT_ELEMENT_TYPE,
|
|
||||||
REACT_FRAGMENT_TYPE,
|
|
||||||
task.keyPath,
|
|
||||||
{children},
|
|
||||||
null,
|
|
||||||
]
|
|
||||||
: [REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE, task.keyPath, {children}];
|
: [REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE, task.keyPath, {children}];
|
||||||
if (!task.implicitSlot) {
|
if (!task.implicitSlot) {
|
||||||
// If this was keyed inside a set. I.e. the outer Server Component was keyed
|
// 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
|
// We have a Server Component that specifies a key but we're now splitting
|
||||||
// the tree using a fragment.
|
// the tree using a fragment.
|
||||||
const fragment = __DEV__
|
const fragment = __DEV__
|
||||||
? enableOwnerStacks
|
? [
|
||||||
? [
|
REACT_ELEMENT_TYPE,
|
||||||
REACT_ELEMENT_TYPE,
|
REACT_FRAGMENT_TYPE,
|
||||||
REACT_FRAGMENT_TYPE,
|
task.keyPath,
|
||||||
task.keyPath,
|
{children},
|
||||||
{children},
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
0,
|
||||||
0,
|
]
|
||||||
]
|
|
||||||
: [
|
|
||||||
REACT_ELEMENT_TYPE,
|
|
||||||
REACT_FRAGMENT_TYPE,
|
|
||||||
task.keyPath,
|
|
||||||
{children},
|
|
||||||
null,
|
|
||||||
]
|
|
||||||
: [REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE, task.keyPath, {children}];
|
: [REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE, task.keyPath, {children}];
|
||||||
if (!task.implicitSlot) {
|
if (!task.implicitSlot) {
|
||||||
// If this was keyed inside a set. I.e. the outer Server Component was keyed
|
// If this was keyed inside a set. I.e. the outer Server Component was keyed
|
||||||
|
|
@ -1586,19 +1559,17 @@ function renderClientElement(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const element = __DEV__
|
const element = __DEV__
|
||||||
? enableOwnerStacks
|
? [
|
||||||
? [
|
REACT_ELEMENT_TYPE,
|
||||||
REACT_ELEMENT_TYPE,
|
type,
|
||||||
type,
|
key,
|
||||||
key,
|
props,
|
||||||
props,
|
task.debugOwner,
|
||||||
task.debugOwner,
|
task.debugStack === null
|
||||||
task.debugStack === null
|
? null
|
||||||
? null
|
: filterStackTrace(request, task.debugStack, 1),
|
||||||
: filterStackTrace(request, task.debugStack, 1),
|
validated,
|
||||||
validated,
|
]
|
||||||
]
|
|
||||||
: [REACT_ELEMENT_TYPE, type, key, props, task.debugOwner]
|
|
||||||
: [REACT_ELEMENT_TYPE, type, key, props];
|
: [REACT_ELEMENT_TYPE, type, key, props];
|
||||||
if (task.implicitSlot && key !== null) {
|
if (task.implicitSlot && key !== null) {
|
||||||
// The root Server Component had no key so it was in an implicit slot.
|
// 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,
|
task.implicitSlot,
|
||||||
request.abortableTasks,
|
request.abortableTasks,
|
||||||
__DEV__ ? task.debugOwner : null,
|
__DEV__ ? task.debugOwner : null,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugStack : null,
|
__DEV__ ? task.debugStack : null,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
|
|
||||||
retryTask(request, newTask);
|
retryTask(request, newTask);
|
||||||
|
|
@ -1694,7 +1665,7 @@ function renderElement(
|
||||||
} else if (type === REACT_FRAGMENT_TYPE && key === null) {
|
} else if (type === REACT_FRAGMENT_TYPE && key === null) {
|
||||||
// For key-less fragments, we add a small optimization to avoid serializing
|
// For key-less fragments, we add a small optimization to avoid serializing
|
||||||
// it as a wrapper.
|
// it as a wrapper.
|
||||||
if (__DEV__ && enableOwnerStacks && validated === 2) {
|
if (__DEV__ && validated === 2) {
|
||||||
// Create a fake owner node for the error stack.
|
// Create a fake owner node for the error stack.
|
||||||
const componentDebugInfo: ReactComponentInfo = {
|
const componentDebugInfo: ReactComponentInfo = {
|
||||||
name: 'Fragment',
|
name: 'Fragment',
|
||||||
|
|
@ -1900,10 +1871,8 @@ function createTask(
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
task.environmentName = request.environmentName();
|
task.environmentName = request.environmentName();
|
||||||
task.debugOwner = debugOwner;
|
task.debugOwner = debugOwner;
|
||||||
if (enableOwnerStacks) {
|
task.debugStack = debugStack;
|
||||||
task.debugStack = debugStack;
|
task.debugTask = debugTask;
|
||||||
task.debugTask = debugTask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
abortSet.add(task);
|
abortSet.add(task);
|
||||||
return task;
|
return task;
|
||||||
|
|
@ -2348,8 +2317,8 @@ function renderModel(
|
||||||
task.implicitSlot,
|
task.implicitSlot,
|
||||||
request.abortableTasks,
|
request.abortableTasks,
|
||||||
__DEV__ ? task.debugOwner : null,
|
__DEV__ ? task.debugOwner : null,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugStack : null,
|
__DEV__ ? task.debugStack : null,
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null,
|
__DEV__ ? task.debugTask : null,
|
||||||
);
|
);
|
||||||
const ping = newTask.ping;
|
const ping = newTask.ping;
|
||||||
(x: any).then(ping, ping);
|
(x: any).then(ping, ping);
|
||||||
|
|
@ -2487,10 +2456,8 @@ function renderModelDestructive(
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
task.debugOwner = element._owner;
|
task.debugOwner = element._owner;
|
||||||
if (enableOwnerStacks) {
|
task.debugStack = element._debugStack;
|
||||||
task.debugStack = element._debugStack;
|
task.debugTask = element._debugTask;
|
||||||
task.debugTask = element._debugTask;
|
|
||||||
}
|
|
||||||
// TODO: Pop this. Since we currently don't have a point where we can pop the stack
|
// 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
|
// 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
|
// are not elements. Leading to the wrong attribution on the server. We could fix
|
||||||
|
|
@ -2506,7 +2473,7 @@ function renderModelDestructive(
|
||||||
element.key,
|
element.key,
|
||||||
ref,
|
ref,
|
||||||
props,
|
props,
|
||||||
__DEV__ && enableOwnerStacks ? element._store.validated : 0,
|
__DEV__ ? element._store.validated : 0,
|
||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
typeof newChild === 'object' &&
|
typeof newChild === 'object' &&
|
||||||
|
|
@ -3291,10 +3258,8 @@ function outlineComponentInfo(
|
||||||
key: componentInfo.key,
|
key: componentInfo.key,
|
||||||
owner: componentInfo.owner,
|
owner: componentInfo.owner,
|
||||||
};
|
};
|
||||||
if (enableOwnerStacks) {
|
// $FlowFixMe[cannot-write]
|
||||||
// $FlowFixMe[cannot-write]
|
componentDebugInfo.stack = componentInfo.stack;
|
||||||
componentDebugInfo.stack = componentInfo.stack;
|
|
||||||
}
|
|
||||||
// Ensure we serialize props after the stack to favor the stack being complete.
|
// Ensure we serialize props after the stack to favor the stack being complete.
|
||||||
// $FlowFixMe[cannot-write]
|
// $FlowFixMe[cannot-write]
|
||||||
componentDebugInfo.props = componentInfo.props;
|
componentDebugInfo.props = componentInfo.props;
|
||||||
|
|
@ -3435,33 +3400,23 @@ function renderConsoleValue(
|
||||||
doNotLimit.add(element._owner);
|
doNotLimit.add(element._owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableOwnerStacks) {
|
let debugStack: null | ReactStackTrace = null;
|
||||||
let debugStack: null | ReactStackTrace = null;
|
if (element._debugStack != null) {
|
||||||
if (element._debugStack != null) {
|
// Outline the debug stack so that it doesn't get cut off.
|
||||||
// Outline the debug stack so that it doesn't get cut off.
|
debugStack = filterStackTrace(request, element._debugStack, 1);
|
||||||
debugStack = filterStackTrace(request, element._debugStack, 1);
|
doNotLimit.add(debugStack);
|
||||||
doNotLimit.add(debugStack);
|
for (let i = 0; i < debugStack.length; i++) {
|
||||||
for (let i = 0; i < debugStack.length; i++) {
|
doNotLimit.add(debugStack[i]);
|
||||||
doNotLimit.add(debugStack[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return [
|
|
||||||
REACT_ELEMENT_TYPE,
|
|
||||||
element.type,
|
|
||||||
element.key,
|
|
||||||
element.props,
|
|
||||||
element._owner,
|
|
||||||
debugStack,
|
|
||||||
element._store.validated,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
REACT_ELEMENT_TYPE,
|
REACT_ELEMENT_TYPE,
|
||||||
element.type,
|
element.type,
|
||||||
element.key,
|
element.key,
|
||||||
element.props,
|
element.props,
|
||||||
element._owner,
|
element._owner,
|
||||||
|
debugStack,
|
||||||
|
element._store.validated,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
|
||||||
import {captureOwnerStack as captureOwnerStackImpl} from './src/ReactClient';
|
import {captureOwnerStack as captureOwnerStackImpl} from './src/ReactClient';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
|
__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
|
||||||
__COMPILER_RUNTIME,
|
__COMPILER_RUNTIME,
|
||||||
|
|
@ -72,7 +72,7 @@ export {useMemoCache as c} from './src/ReactHooks';
|
||||||
|
|
||||||
// Only export captureOwnerStack in development.
|
// Only export captureOwnerStack in development.
|
||||||
let captureOwnerStack: ?() => null | string;
|
let captureOwnerStack: ?() => null | string;
|
||||||
if (__DEV__ && enableOwnerStacks) {
|
if (__DEV__) {
|
||||||
captureOwnerStack = captureOwnerStackImpl;
|
captureOwnerStack = captureOwnerStackImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,18 +7,17 @@
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
|
||||||
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
||||||
|
|
||||||
export function captureOwnerStack(): null | string {
|
export function captureOwnerStack(): null | string {
|
||||||
if (!enableOwnerStacks || !__DEV__) {
|
if (__DEV__) {
|
||||||
return null;
|
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;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
export {default as __SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './ReactSharedInternalsServer';
|
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 {forEach, map, count, toArray, only} from './ReactChildren';
|
||||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
|
||||||
import {captureOwnerStack as captureOwnerStackImpl} from './ReactOwnerStack';
|
import {captureOwnerStack as captureOwnerStackImpl} from './ReactOwnerStack';
|
||||||
import {
|
import {
|
||||||
REACT_FRAGMENT_TYPE,
|
REACT_FRAGMENT_TYPE,
|
||||||
|
|
@ -39,9 +38,8 @@ const Children = {
|
||||||
only,
|
only,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Only export captureOwnerStack if the flag is on, to support feature detection.
|
|
||||||
let captureOwnerStack: ?() => null | string;
|
let captureOwnerStack: ?() => null | string;
|
||||||
if (__DEV__ && enableOwnerStacks) {
|
if (__DEV__) {
|
||||||
captureOwnerStack = captureOwnerStackImpl;
|
captureOwnerStack = captureOwnerStackImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -333,16 +333,6 @@ describe('ReactChildren', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const instance = <div>{threeDivIterable}</div>;
|
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);
|
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' +
|
'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.' +
|
'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' +
|
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
' in div (at **)' +
|
' in div (at **)',
|
||||||
(gate(flag => flag.enableOwnerStacks) ? '' : '\n in div (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -894,22 +883,13 @@ describe('ReactChildren', () => {
|
||||||
</ComponentRenderingMappedChildren>,
|
</ComponentRenderingMappedChildren>,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev(
|
assertConsoleErrorDev([
|
||||||
gate(flags => flags.enableOwnerStacks)
|
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||||
? [
|
'Check the render method of `ComponentRenderingMappedChildren`.' +
|
||||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
'Check the render method of `ComponentRenderingMappedChildren`.' +
|
' in div (at **)\n' +
|
||||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
' in **/ReactChildren-test.js:**:** (at **)',
|
||||||
' 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 **)',
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not warn for mapped static children without keys', async () => {
|
it('does not warn for mapped static children without keys', async () => {
|
||||||
|
|
@ -953,21 +933,12 @@ describe('ReactChildren', () => {
|
||||||
</ComponentRenderingClonedChildren>,
|
</ComponentRenderingClonedChildren>,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev(
|
assertConsoleErrorDev([
|
||||||
gate(flags => flags.enableOwnerStacks)
|
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||||
? [
|
'Check the render method of `ComponentRenderingClonedChildren`.' +
|
||||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
'Check the render method of `ComponentRenderingClonedChildren`.' +
|
' in div (at **)',
|
||||||
' 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 **)',
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not warn for cloned static children without keys', async () => {
|
it('does not warn for cloned static children without keys', async () => {
|
||||||
|
|
@ -1005,21 +976,12 @@ describe('ReactChildren', () => {
|
||||||
</ComponentRenderingFlattenedChildren>,
|
</ComponentRenderingFlattenedChildren>,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev(
|
assertConsoleErrorDev([
|
||||||
gate(flags => flags.enableOwnerStacks)
|
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||||
? [
|
'Check the render method of `ComponentRenderingFlattenedChildren`.' +
|
||||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
'Check the render method of `ComponentRenderingFlattenedChildren`.' +
|
' in div (at **)',
|
||||||
' 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 **)',
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not warn for flattened static children without keys', async () => {
|
it('does not warn for flattened static children without keys', async () => {
|
||||||
|
|
|
||||||
|
|
@ -266,26 +266,14 @@ describe 'ReactCoffeeScriptClass', ->
|
||||||
|
|
||||||
test React.createElement(Outer), 'SPAN', 'foo'
|
test React.createElement(Outer), 'SPAN', 'foo'
|
||||||
|
|
||||||
if featureFlags.enableOwnerStacks
|
assertConsoleErrorDev([
|
||||||
assertConsoleErrorDev([
|
'Outer uses the legacy childContextTypes API which will soon be removed.
|
||||||
'Outer uses the legacy childContextTypes API which will soon be removed.
|
Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
' in Outer (at **)',
|
||||||
' in Outer (at **)',
|
'Foo uses the legacy contextTypes API which will soon be removed.
|
||||||
'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' +
|
||||||
Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
' in Outer (at **)',
|
||||||
' 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 **)',
|
|
||||||
]);
|
|
||||||
|
|
||||||
|
|
||||||
it 'renders only once when setting state in componentWillMount', ->
|
it 'renders only once when setting state in componentWillMount', ->
|
||||||
renderCount = 0
|
renderCount = 0
|
||||||
|
|
@ -578,24 +566,13 @@ describe 'ReactCoffeeScriptClass', ->
|
||||||
React.createElement Bar
|
React.createElement Bar
|
||||||
|
|
||||||
test React.createElement(Foo), 'DIV', 'bar-through-context'
|
test React.createElement(Foo), 'DIV', 'bar-through-context'
|
||||||
if featureFlags.enableOwnerStacks
|
assertConsoleErrorDev [
|
||||||
assertConsoleErrorDev [
|
'Foo uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.
|
||||||
'Foo uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.
|
(https://react.dev/link/legacy-context)\n' +
|
||||||
(https://react.dev/link/legacy-context)\n' +
|
' in Foo (at **)',
|
||||||
' in Foo (at **)',
|
'Bar uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.
|
||||||
'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' +
|
||||||
(https://react.dev/link/legacy-context)\n' +
|
' in Foo (at **)'
|
||||||
' 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 **)'
|
|
||||||
]
|
|
||||||
|
|
||||||
undefined
|
undefined
|
||||||
|
|
|
||||||
|
|
@ -78,9 +78,7 @@ describe('ReactContextValidator', () => {
|
||||||
' in ComponentInFooBarContext (at **)',
|
' in ComponentInFooBarContext (at **)',
|
||||||
'Component uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in ComponentInFooBarContext (at **)',
|
||||||
? ' in ComponentInFooBarContext (at **)'
|
|
||||||
: ' in Component (at **)'),
|
|
||||||
]);
|
]);
|
||||||
expect(instance.childRef.current.context).toEqual({foo: 'abc'});
|
expect(instance.childRef.current.context).toEqual({foo: 'abc'});
|
||||||
});
|
});
|
||||||
|
|
@ -159,9 +157,7 @@ describe('ReactContextValidator', () => {
|
||||||
' in Parent (at **)',
|
' in Parent (at **)',
|
||||||
'Component uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in Parent (at **)',
|
||||||
? ' in Parent (at **)'
|
|
||||||
: ' in Component (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(constructorContext).toEqual({foo: 'abc'});
|
expect(constructorContext).toEqual({foo: 'abc'});
|
||||||
|
|
@ -282,21 +278,12 @@ describe('ReactContextValidator', () => {
|
||||||
' in ParentContextProvider (at **)',
|
' in ParentContextProvider (at **)',
|
||||||
'MiddleMissingContext uses the legacy childContextTypes API which will soon be removed. ' +
|
'MiddleMissingContext uses the legacy childContextTypes API which will soon be removed. ' +
|
||||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
'Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: ' in MiddleMissingContext (at **)\n') +
|
|
||||||
' in ParentContextProvider (at **)',
|
' in ParentContextProvider (at **)',
|
||||||
'MiddleMissingContext.childContextTypes is specified but there is no getChildContext() method on the instance. ' +
|
'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' +
|
'You can either define getChildContext() on MiddleMissingContext or remove childContextTypes from it.\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: ' in MiddleMissingContext (at **)\n') +
|
|
||||||
' in ParentContextProvider (at **)',
|
' in ParentContextProvider (at **)',
|
||||||
'ChildContextConsumer uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'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 MiddleMissingContext (at **)\n' +
|
||||||
' in ParentContextProvider (at **)',
|
' in ParentContextProvider (at **)',
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -77,13 +77,7 @@ describe('ReactCreateElement', () => {
|
||||||
'in `undefined` being returned. If you need to access the same ' +
|
'in `undefined` being returned. If you need to access the same ' +
|
||||||
'value within the child component, you should pass it as a different ' +
|
'value within the child component, you should pass it as a different ' +
|
||||||
'prop. (https://react.dev/link/special-props)\n' +
|
'prop. (https://react.dev/link/special-props)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in Parent (at **)',
|
||||||
? [' in Parent (at **)']
|
|
||||||
: [
|
|
||||||
' in Child (at **)\n' +
|
|
||||||
' in div (at **)\n' +
|
|
||||||
' in Parent (at **)',
|
|
||||||
]),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,10 +46,7 @@ describe('ReactCreateRef', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Unexpected ref object provided for div. ' +
|
'Unexpected ref object provided for div. ' +
|
||||||
'Use either a ref-setter function or React.createRef().\n' +
|
'Use either a ref-setter function or React.createRef().\n' +
|
||||||
' in div (at **)' +
|
' in div (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: '\n in Wrapper (at **)'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
ReactDOM.flushSync(() => {
|
ReactDOM.flushSync(() => {
|
||||||
|
|
@ -62,10 +59,7 @@ describe('ReactCreateRef', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Unexpected ref object provided for ExampleComponent. ' +
|
'Unexpected ref object provided for ExampleComponent. ' +
|
||||||
'Use either a ref-setter function or React.createRef().\n' +
|
'Use either a ref-setter function or React.createRef().\n' +
|
||||||
' in ExampleComponent (at **)' +
|
' in ExampleComponent (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: '\n in Wrapper (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -305,9 +305,6 @@ describe('ReactES6Class', () => {
|
||||||
' in Outer (at **)',
|
' in Outer (at **)',
|
||||||
'Foo uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'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 **)',
|
' in Outer (at **)',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
@ -638,9 +635,6 @@ describe('ReactES6Class', () => {
|
||||||
' in Foo (at **)',
|
' in Foo (at **)',
|
||||||
'Bar uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'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 **)',
|
' in Foo (at **)',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -46,19 +46,11 @@ describe('ReactElementValidator', () => {
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
assertConsoleErrorDev(
|
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' +
|
||||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
' in ComponentClass (at **)',
|
||||||
'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 **)',
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('warns for keys for arrays of elements with owner info', async () => {
|
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)));
|
await act(() => root.render(React.createElement(ComponentWrapper)));
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Each child in a list should have a unique "key" prop.' +
|
'Each child in a list should have a unique "key" prop.' +
|
||||||
'\n\nCheck the render method of `' +
|
'\n\nCheck the render method of `ComponentClass`. ' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? 'ComponentClass'
|
|
||||||
: 'InnerClass') +
|
|
||||||
'`. ' +
|
|
||||||
'It was passed a child from ComponentWrapper. ' +
|
'It was passed a child from ComponentWrapper. ' +
|
||||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in ComponentWrapper (at **)',
|
||||||
? ' in ComponentWrapper (at **)'
|
|
||||||
: ' in ComponentClass (at **)\n' +
|
|
||||||
' in InnerClass (at **)\n' +
|
|
||||||
' in ComponentWrapper (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -109,16 +93,12 @@ describe('ReactElementValidator', () => {
|
||||||
const root = ReactDOMClient.createRoot(document.createElement('div'));
|
const root = ReactDOMClient.createRoot(document.createElement('div'));
|
||||||
await act(() => root.render(<Anonymous>{divs}</Anonymous>));
|
await act(() => root.render(<Anonymous>{divs}</Anonymous>));
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
gate(flags => flags.enableOwnerStacks)
|
// For owner stacks the parent being validated is the div.
|
||||||
? // For owner stacks the parent being validated is the div.
|
'Each child in a list should have a unique ' +
|
||||||
'Each child in a list should have a unique ' +
|
'"key" prop.' +
|
||||||
'"key" prop.' +
|
'\n\nCheck the top-level render call using <div>. ' +
|
||||||
'\n\nCheck the top-level render call using <div>. ' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
' in div (at **)',
|
||||||
' 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 **)',
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -158,9 +138,6 @@ describe('ReactElementValidator', () => {
|
||||||
'https://react.dev/link/warning-keys for more information.\n' +
|
'https://react.dev/link/warning-keys for more information.\n' +
|
||||||
' in div (at **)\n' +
|
' in div (at **)\n' +
|
||||||
' in Component (at **)\n' +
|
' in Component (at **)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
|
||||||
? ''
|
|
||||||
: ' in Parent (at **)\n') +
|
|
||||||
' in GrandParent (at **)',
|
' in GrandParent (at **)',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
@ -206,35 +183,12 @@ describe('ReactElementValidator', () => {
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(React.createElement(ComponentClass, null, iterable)),
|
root.render(React.createElement(ComponentClass, null, iterable)),
|
||||||
);
|
);
|
||||||
assertConsoleErrorDev(
|
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. ' +
|
||||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
'Check the render method of `ComponentClass`. It was passed a child from div. ' +
|
' in ComponentClass (at **)',
|
||||||
'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 **)',
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not warns for arrays of elements with keys', () => {
|
it('does not warns for arrays of elements with keys', () => {
|
||||||
|
|
@ -373,13 +327,6 @@ describe('ReactElementValidator', () => {
|
||||||
];
|
];
|
||||||
for (let i = 0; i < cases.length; i++) {
|
for (let i = 0; i < cases.length; i++) {
|
||||||
await act(async () => root.render(cases[i][0]()));
|
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(
|
expect(errors).toEqual(
|
||||||
|
|
@ -468,21 +415,6 @@ describe('ReactElementValidator', () => {
|
||||||
'or a class/function (for composite components) but got: null.' +
|
'or a class/function (for composite components) but got: null.' +
|
||||||
(__DEV__ ? '\n\nCheck the render method of `ParentComp`.' : ''),
|
(__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 () => {
|
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', () => {
|
it('does not blow up on key warning with undefined type', () => {
|
||||||
const Foo = undefined;
|
const Foo = undefined;
|
||||||
void (<Foo>{[<div />]}</Foo>);
|
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', () => {
|
it('does not call lazy initializers eagerly', () => {
|
||||||
|
|
|
||||||
|
|
@ -49,13 +49,9 @@ describe('ReactJSXElementValidator', () => {
|
||||||
root.render(<Component>{[<Component />, <Component />]}</Component>);
|
root.render(<Component>{[<Component />, <Component />]}</Component>);
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
gate(flags => flags.enableOwnerStacks)
|
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||||
? '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' +
|
||||||
'Check the render method of `Component`. See https://react.dev/link/warning-keys for more information.\n' +
|
' in Component (at **)',
|
||||||
' 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 **)',
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -79,17 +75,9 @@ describe('ReactJSXElementValidator', () => {
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Each child in a list should have a unique "key" prop.' +
|
'Each child in a list should have a unique "key" prop.' +
|
||||||
'\n\nCheck the render method of `' +
|
'\n\nCheck the render method of `Component`. ' +
|
||||||
(gate(flag => flag.enableOwnerStacks)
|
|
||||||
? 'Component'
|
|
||||||
: 'InnerComponent') +
|
|
||||||
'`. ' +
|
|
||||||
'It was passed a child from ComponentWrapper. See https://react.dev/link/warning-keys for more information.\n' +
|
'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 ComponentWrapper (at **)'
|
|
||||||
: ' in Component (at **)\n' +
|
|
||||||
' in InnerComponent (at **)\n' +
|
|
||||||
' in ComponentWrapper (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -112,34 +100,12 @@ describe('ReactJSXElementValidator', () => {
|
||||||
await act(() => {
|
await act(() => {
|
||||||
root.render(<Component>{iterable}</Component>);
|
root.render(<Component>{iterable}</Component>);
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev(
|
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. ' +
|
||||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
'Check the render method of `Component`. It was passed a child from div. ' +
|
' in Component (at **)',
|
||||||
'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 **)',
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not warn for arrays of elements with keys', async () => {
|
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 ' +
|
'in `undefined` being returned. If you need to access the same ' +
|
||||||
'value within the child component, you should pass it as a different ' +
|
'value within the child component, you should pass it as a different ' +
|
||||||
'prop. (https://react.dev/link/special-props)\n' +
|
'prop. (https://react.dev/link/special-props)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in Parent (at **)',
|
||||||
? ' in Parent (at **)'
|
|
||||||
: ' in Child (at **)\n' +
|
|
||||||
' in div (at **)\n' +
|
|
||||||
' in Parent (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -279,9 +275,6 @@ describe('ReactJSXRuntime', () => {
|
||||||
assertConsoleErrorDev([
|
assertConsoleErrorDev([
|
||||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
'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' +
|
'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 **)',
|
' in Parent (at **)',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1042,67 +1042,30 @@ describe('context legacy', () => {
|
||||||
root.render(<Root />);
|
root.render(<Root />);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (gate(flags => flags.enableOwnerStacks)) {
|
assertConsoleErrorDev([
|
||||||
assertConsoleErrorDev([
|
'LegacyContextProvider uses the legacy childContextTypes API ' +
|
||||||
'LegacyContextProvider uses the legacy childContextTypes API ' +
|
'which will soon be removed. Use React.createContext() instead. ' +
|
||||||
'which will soon be removed. Use React.createContext() instead. ' +
|
'(https://react.dev/link/legacy-context)' +
|
||||||
'(https://react.dev/link/legacy-context)' +
|
'\n in Root (at **)',
|
||||||
'\n in Root (at **)',
|
'LegacyContextConsumer uses the legacy contextTypes API which ' +
|
||||||
'LegacyContextConsumer uses the legacy contextTypes API which ' +
|
'will soon be removed. Use React.createContext() with static ' +
|
||||||
'will soon be removed. Use React.createContext() with static ' +
|
'contextType instead. (https://react.dev/link/legacy-context)' +
|
||||||
'contextType instead. (https://react.dev/link/legacy-context)' +
|
'\n in LegacyContextProvider (at **)' +
|
||||||
'\n in LegacyContextProvider (at **)' +
|
'\n in Root (at **)',
|
||||||
'\n in Root (at **)',
|
'FunctionalLegacyContextConsumer uses the legacy contextTypes ' +
|
||||||
'FunctionalLegacyContextConsumer uses the legacy contextTypes ' +
|
'API which will be removed soon. Use React.createContext() ' +
|
||||||
'API which will be removed soon. Use React.createContext() ' +
|
'with React.useContext() instead. (https://react.dev/link/legacy-context)' +
|
||||||
'with React.useContext() instead. (https://react.dev/link/legacy-context)' +
|
'\n in LegacyContextProvider (at **)' +
|
||||||
'\n in LegacyContextProvider (at **)' +
|
'\n in Root (at **)',
|
||||||
'\n in Root (at **)',
|
'Legacy context API has been detected within a strict-mode tree.' +
|
||||||
'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 ' +
|
||||||
'\n\nThe old API will be supported in all 16.x releases, but applications ' +
|
'using it should migrate to the new version.' +
|
||||||
'using it should migrate to the new version.' +
|
'\n\nPlease update the following components: ' +
|
||||||
'\n\nPlease update the following components: ' +
|
'FunctionalLegacyContextConsumer, LegacyContextConsumer, LegacyContextProvider' +
|
||||||
'FunctionalLegacyContextConsumer, LegacyContextConsumer, LegacyContextProvider' +
|
'\n\nLearn more about this warning here: ' +
|
||||||
'\n\nLearn more about this warning here: ' +
|
'https://react.dev/link/legacy-context' +
|
||||||
'https://react.dev/link/legacy-context' +
|
'\n in Root (at **)',
|
||||||
'\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 **)',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dedupe
|
// Dedupe
|
||||||
await act(() => {
|
await act(() => {
|
||||||
|
|
|
||||||
|
|
@ -528,10 +528,7 @@ describe('ReactTypeScriptClass', function () {
|
||||||
' in ProvideChildContextTypes (at **)',
|
' in ProvideChildContextTypes (at **)',
|
||||||
'StateBasedOnContext uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(ReactFeatureFlags.enableOwnerStacks
|
' in ProvideChildContextTypes.createElement (at **)',
|
||||||
? ' in ProvideChildContextTypes.createElement (at **)'
|
|
||||||
: ' in StateBasedOnContext (at **)\n') +
|
|
||||||
' in ProvideChildContextTypes (at **)',
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -724,10 +721,7 @@ describe('ReactTypeScriptClass', function () {
|
||||||
' in ProvideContext (at **)',
|
' in ProvideContext (at **)',
|
||||||
'ReadContext uses the legacy contextTypes API which will soon be removed. ' +
|
'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' +
|
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||||
(ReactFeatureFlags.enableOwnerStacks
|
' in ProvideContext.createElement (at **)',
|
||||||
? ' in ProvideContext.createElement (at **)'
|
|
||||||
: ' in ReadContext (at **)\n') +
|
|
||||||
' in ProvideContext (at **)',
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -348,14 +348,10 @@ describe('create-react-class-integration', () => {
|
||||||
root.render(<Outer />);
|
root.render(<Outer />);
|
||||||
});
|
});
|
||||||
assertConsoleErrorDev([
|
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.',
|
],
|
||||||
{withoutStack: true},
|
|
||||||
]
|
|
||||||
: 'Component uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',
|
|
||||||
),
|
|
||||||
'Component uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.',
|
'Component uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.',
|
||||||
]);
|
]);
|
||||||
expect(container.firstChild.className).toBe('foo');
|
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. ' +
|
'\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' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
(gate(flags => flags.enableOwnerStacks)
|
' in **/forwardRef-test.js:**:** (at **)',
|
||||||
? ' in **/forwardRef-test.js:**:** (at **)'
|
|
||||||
: ' in p (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). ' +
|
'\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' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
' in Inner (at **)' +
|
' in Inner (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (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). ' +
|
'\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' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
' in Inner (at **)' +
|
' in Inner (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -278,8 +274,7 @@ describe('forwardRef', () => {
|
||||||
'\n\nCheck the top-level render call using <Outer>. It was passed a child from Outer. ' +
|
'\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' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
' in Outer (at **)' +
|
' in Outer (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -301,8 +296,7 @@ describe('forwardRef', () => {
|
||||||
'\n\nCheck the top-level render call using <Outer>. It was passed a child from Outer. ' +
|
'\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' +
|
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||||
' in span (at **)\n' +
|
' in span (at **)\n' +
|
||||||
' in Inner (at **)' +
|
' in Inner (at **)',
|
||||||
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,25 +10,17 @@ import ReactSharedInternals from 'shared/ReactSharedInternals';
|
||||||
import hasOwnProperty from 'shared/hasOwnProperty';
|
import hasOwnProperty from 'shared/hasOwnProperty';
|
||||||
import assign from 'shared/assign';
|
import assign from 'shared/assign';
|
||||||
import {
|
import {
|
||||||
getIteratorFn,
|
|
||||||
REACT_ELEMENT_TYPE,
|
REACT_ELEMENT_TYPE,
|
||||||
REACT_FRAGMENT_TYPE,
|
REACT_FRAGMENT_TYPE,
|
||||||
REACT_LAZY_TYPE,
|
REACT_LAZY_TYPE,
|
||||||
} from 'shared/ReactSymbols';
|
} from 'shared/ReactSymbols';
|
||||||
import {checkKeyStringCoercion} from 'shared/CheckStringCoercion';
|
import {checkKeyStringCoercion} from 'shared/CheckStringCoercion';
|
||||||
import isValidElementType from 'shared/isValidElementType';
|
|
||||||
import isArray from 'shared/isArray';
|
import isArray from 'shared/isArray';
|
||||||
import {describeUnknownElementTypeFrameInDEV} from 'shared/ReactComponentStackFrame';
|
import {disableDefaultPropsExceptForClasses} from 'shared/ReactFeatureFlags';
|
||||||
import {
|
|
||||||
disableDefaultPropsExceptForClasses,
|
|
||||||
enableOwnerStacks,
|
|
||||||
} from 'shared/ReactFeatureFlags';
|
|
||||||
|
|
||||||
const REACT_CLIENT_REFERENCE = Symbol.for('react.client.reference');
|
|
||||||
|
|
||||||
const createTask =
|
const createTask =
|
||||||
// eslint-disable-next-line react-internal/no-production-logging
|
// 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
|
? // eslint-disable-next-line react-internal/no-production-logging
|
||||||
console.createTask
|
console.createTask
|
||||||
: () => null;
|
: () => null;
|
||||||
|
|
@ -261,20 +253,18 @@ function ReactElement(
|
||||||
writable: true,
|
writable: true,
|
||||||
value: null,
|
value: null,
|
||||||
});
|
});
|
||||||
if (enableOwnerStacks) {
|
Object.defineProperty(element, '_debugStack', {
|
||||||
Object.defineProperty(element, '_debugStack', {
|
configurable: false,
|
||||||
configurable: false,
|
enumerable: false,
|
||||||
enumerable: false,
|
writable: true,
|
||||||
writable: true,
|
value: debugStack,
|
||||||
value: debugStack,
|
});
|
||||||
});
|
Object.defineProperty(element, '_debugTask', {
|
||||||
Object.defineProperty(element, '_debugTask', {
|
configurable: false,
|
||||||
configurable: false,
|
enumerable: false,
|
||||||
enumerable: false,
|
writable: true,
|
||||||
writable: true,
|
value: debugTask,
|
||||||
value: debugTask,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
if (Object.freeze) {
|
if (Object.freeze) {
|
||||||
Object.freeze(element.props);
|
Object.freeze(element.props);
|
||||||
Object.freeze(element);
|
Object.freeze(element);
|
||||||
|
|
@ -390,8 +380,8 @@ export function jsxProdSignatureRunningInDevWithDynamicChildren(
|
||||||
isStaticChildren,
|
isStaticChildren,
|
||||||
source,
|
source,
|
||||||
self,
|
self,
|
||||||
__DEV__ && enableOwnerStacks ? Error('react-stack-top-frame') : undefined,
|
__DEV__ && Error('react-stack-top-frame'),
|
||||||
__DEV__ && enableOwnerStacks ? createTask(getTaskName(type)) : undefined,
|
__DEV__ && createTask(getTaskName(type)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -412,8 +402,8 @@ export function jsxProdSignatureRunningInDevWithStaticChildren(
|
||||||
isStaticChildren,
|
isStaticChildren,
|
||||||
source,
|
source,
|
||||||
self,
|
self,
|
||||||
__DEV__ && enableOwnerStacks ? Error('react-stack-top-frame') : undefined,
|
__DEV__ && Error('react-stack-top-frame'),
|
||||||
__DEV__ && enableOwnerStacks ? createTask(getTaskName(type)) : undefined,
|
__DEV__ && createTask(getTaskName(type)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -434,8 +424,8 @@ export function jsxDEV(type, config, maybeKey, isStaticChildren, source, self) {
|
||||||
isStaticChildren,
|
isStaticChildren,
|
||||||
source,
|
source,
|
||||||
self,
|
self,
|
||||||
__DEV__ && enableOwnerStacks ? Error('react-stack-top-frame') : undefined,
|
__DEV__ && Error('react-stack-top-frame'),
|
||||||
__DEV__ && enableOwnerStacks ? createTask(getTaskName(type)) : undefined,
|
__DEV__ && createTask(getTaskName(type)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -450,80 +440,37 @@ function jsxDEVImpl(
|
||||||
debugTask,
|
debugTask,
|
||||||
) {
|
) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
if (!enableOwnerStacks && !isValidElementType(type)) {
|
// We don't warn for invalid element type here because with owner stacks,
|
||||||
// This is an invalid element type.
|
// 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.
|
||||||
// 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.";
|
|
||||||
}
|
|
||||||
|
|
||||||
let typeString;
|
// Skip key warning if the type isn't valid since our key validation logic
|
||||||
if (type === null) {
|
// doesn't expect a non-string/function type and can throw confusing
|
||||||
typeString = 'null';
|
// errors. We don't want exception behavior to differ between dev and
|
||||||
} else if (isArray(type)) {
|
// prod. (Rendering will throw with a helpful message and as soon as the
|
||||||
typeString = 'array';
|
// type is fixed, the key warnings will appear.)
|
||||||
} else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
|
// With owner stacks, we no longer need the type here so this comment is
|
||||||
typeString = `<${getComponentNameFromType(type.type) || 'Unknown'} />`;
|
// no longer true. Which is why we can run this even for invalid types.
|
||||||
info =
|
const children = config.children;
|
||||||
' Did you accidentally export a JSX literal instead of a component?';
|
if (children !== undefined) {
|
||||||
} else {
|
if (isStaticChildren) {
|
||||||
typeString = typeof type;
|
if (isArray(children)) {
|
||||||
}
|
for (let i = 0; i < children.length; i++) {
|
||||||
|
validateChildKeys(children[i], type);
|
||||||
|
}
|
||||||
|
|
||||||
console.error(
|
if (Object.freeze) {
|
||||||
'React.jsx: type is invalid -- expected a string (for ' +
|
Object.freeze(children);
|
||||||
'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.',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} 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) {
|
export function createElement(type, config, children) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
if (!enableOwnerStacks && !isValidElementType(type)) {
|
// We don't warn for invalid element type here because with owner stacks,
|
||||||
// This is just an optimistic check that provides a better stack trace before
|
// we error in the renderer. The renderer is the only one that knows what
|
||||||
// owner stacks. It's really up to the renderer if it's a valid element type.
|
// types are valid for this particular renderer so we let it error there.
|
||||||
// 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.";
|
|
||||||
}
|
|
||||||
|
|
||||||
let typeString;
|
// Skip key warning if the type isn't valid since our key validation logic
|
||||||
if (type === null) {
|
// doesn't expect a non-string/function type and can throw confusing
|
||||||
typeString = 'null';
|
// errors. We don't want exception behavior to differ between dev and
|
||||||
} else if (isArray(type)) {
|
// prod. (Rendering will throw with a helpful message and as soon as the
|
||||||
typeString = 'array';
|
// type is fixed, the key warnings will appear.)
|
||||||
} else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
|
for (let i = 2; i < arguments.length; i++) {
|
||||||
typeString = `<${getComponentNameFromType(type.type) || 'Unknown'} />`;
|
validateChildKeys(arguments[i], type);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlike the jsx() runtime, createElement() doesn't warn about key spread.
|
// Unlike the jsx() runtime, createElement() doesn't warn about key spread.
|
||||||
|
|
@ -795,8 +700,8 @@ export function createElement(type, config, children) {
|
||||||
undefined,
|
undefined,
|
||||||
getOwner(),
|
getOwner(),
|
||||||
props,
|
props,
|
||||||
__DEV__ && enableOwnerStacks ? Error('react-stack-top-frame') : undefined,
|
__DEV__ && Error('react-stack-top-frame'),
|
||||||
__DEV__ && enableOwnerStacks ? createTask(getTaskName(type)) : undefined,
|
__DEV__ && createTask(getTaskName(type)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -808,8 +713,8 @@ export function cloneAndReplaceKey(oldElement, newKey) {
|
||||||
undefined,
|
undefined,
|
||||||
!__DEV__ ? undefined : oldElement._owner,
|
!__DEV__ ? undefined : oldElement._owner,
|
||||||
oldElement.props,
|
oldElement.props,
|
||||||
__DEV__ && enableOwnerStacks ? oldElement._debugStack : undefined,
|
__DEV__ && oldElement._debugStack,
|
||||||
__DEV__ && enableOwnerStacks ? oldElement._debugTask : undefined,
|
__DEV__ && oldElement._debugTask,
|
||||||
);
|
);
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
// The cloned element should inherit the original element's key validation.
|
// The cloned element should inherit the original element's key validation.
|
||||||
|
|
@ -914,8 +819,8 @@ export function cloneElement(element, config, children) {
|
||||||
undefined,
|
undefined,
|
||||||
owner,
|
owner,
|
||||||
props,
|
props,
|
||||||
__DEV__ && enableOwnerStacks ? element._debugStack : undefined,
|
__DEV__ && element._debugStack,
|
||||||
__DEV__ && enableOwnerStacks ? element._debugTask : undefined,
|
__DEV__ && element._debugTask,
|
||||||
);
|
);
|
||||||
|
|
||||||
for (let i = 2; i < arguments.length; i++) {
|
for (let i = 2; i < arguments.length; i++) {
|
||||||
|
|
@ -936,51 +841,13 @@ export function cloneElement(element, config, children) {
|
||||||
*/
|
*/
|
||||||
function validateChildKeys(node, parentType) {
|
function validateChildKeys(node, parentType) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
if (enableOwnerStacks) {
|
// With owner stacks is, no warnings happens. All we do is
|
||||||
// When owner stacks is enabled no warnings happens. All we do is
|
// mark elements as being in a valid static child position so they
|
||||||
// mark elements as being in a valid static child position so they
|
// don't need keys.
|
||||||
// don't need keys.
|
if (isValidElement(node)) {
|
||||||
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.
|
|
||||||
if (node._store) {
|
if (node._store) {
|
||||||
node._store.validated = 1;
|
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
|
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 {describeBuiltInComponentFrame} from 'shared/ReactComponentStackFrame';
|
||||||
|
|
||||||
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
|
|
||||||
|
|
||||||
import {formatOwnerStack} from 'shared/ReactOwnerStackFrames';
|
import {formatOwnerStack} from 'shared/ReactOwnerStackFrames';
|
||||||
|
|
||||||
export function getOwnerStackByComponentInfoInDev(
|
export function getOwnerStackByComponentInfoInDev(
|
||||||
componentInfo: ReactComponentInfo,
|
componentInfo: ReactComponentInfo,
|
||||||
): string {
|
): string {
|
||||||
if (!enableOwnerStacks || !__DEV__) {
|
if (!__DEV__) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -7,25 +7,12 @@
|
||||||
* @flow
|
* @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 {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev';
|
||||||
|
|
||||||
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
||||||
|
|
||||||
import DefaultPrepareStackTrace from 'shared/DefaultPrepareStackTrace';
|
import DefaultPrepareStackTrace from 'shared/DefaultPrepareStackTrace';
|
||||||
|
|
||||||
import {enableViewTransition} from 'shared/ReactFeatureFlags';
|
|
||||||
|
|
||||||
let prefix;
|
let prefix;
|
||||||
let suffix;
|
let suffix;
|
||||||
export function describeBuiltInComponentFrame(name: string): string {
|
export function describeBuiltInComponentFrame(name: string): string {
|
||||||
|
|
@ -300,53 +287,3 @@ export function describeClassComponentFrame(ctor: Function): string {
|
||||||
export function describeFunctionComponentFrame(fn: Function): string {
|
export function describeFunctionComponentFrame(fn: Function): string {
|
||||||
return describeNativeComponentFrame(fn, false);
|
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 enablePersistedModeClonedFlag = false;
|
||||||
|
|
||||||
export const enableOwnerStacks = true;
|
|
||||||
|
|
||||||
export const enableShallowPropDiffing = false;
|
export const enableShallowPropDiffing = false;
|
||||||
|
|
||||||
export const enableSiblingPrerendering = true;
|
export const enableSiblingPrerendering = true;
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,6 @@ export const {
|
||||||
enableLazyPublicInstanceInFabric,
|
enableLazyPublicInstanceInFabric,
|
||||||
} = dynamicFlags;
|
} = dynamicFlags;
|
||||||
|
|
||||||
// These two can be removed
|
|
||||||
export const enableOwnerStacks = true;
|
|
||||||
|
|
||||||
// The rest of the flags are static for better dead code elimination.
|
// The rest of the flags are static for better dead code elimination.
|
||||||
export const disableClientCache = true;
|
export const disableClientCache = true;
|
||||||
export const disableCommentsAsDOMContainers = true;
|
export const disableCommentsAsDOMContainers = true;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ export const enableLegacyFBSupport = false;
|
||||||
export const enableLegacyHidden = false;
|
export const enableLegacyHidden = false;
|
||||||
export const enableNoCloningMemoCache = false;
|
export const enableNoCloningMemoCache = false;
|
||||||
export const enableObjectFiber = false;
|
export const enableObjectFiber = false;
|
||||||
export const enableOwnerStacks = true;
|
|
||||||
export const enablePersistedModeClonedFlag = false;
|
export const enablePersistedModeClonedFlag = false;
|
||||||
export const enablePostpone = false;
|
export const enablePostpone = false;
|
||||||
export const enableReactTestRendererWarning = false;
|
export const enableReactTestRendererWarning = false;
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,6 @@ export const enableReactTestRendererWarning = true;
|
||||||
export const disableDefaultPropsExceptForClasses = true;
|
export const disableDefaultPropsExceptForClasses = true;
|
||||||
|
|
||||||
export const enableObjectFiber = false;
|
export const enableObjectFiber = false;
|
||||||
export const enableOwnerStacks = true;
|
|
||||||
|
|
||||||
// Flow magic to verify the exports of this file match the original version.
|
// Flow magic to verify the exports of this file match the original version.
|
||||||
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
|
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,6 @@ export const enableLegacyFBSupport = false;
|
||||||
export const enableLegacyHidden = false;
|
export const enableLegacyHidden = false;
|
||||||
export const enableNoCloningMemoCache = false;
|
export const enableNoCloningMemoCache = false;
|
||||||
export const enableObjectFiber = false;
|
export const enableObjectFiber = false;
|
||||||
export const enableOwnerStacks = true;
|
|
||||||
export const enablePersistedModeClonedFlag = false;
|
export const enablePersistedModeClonedFlag = false;
|
||||||
export const enablePostpone = false;
|
export const enablePostpone = false;
|
||||||
export const enableProfilerCommitHooks = __PROFILE__;
|
export const enableProfilerCommitHooks = __PROFILE__;
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,6 @@ export const disableDefaultPropsExceptForClasses = true;
|
||||||
export const renameElementSymbol = false;
|
export const renameElementSymbol = false;
|
||||||
|
|
||||||
export const enableObjectFiber = false;
|
export const enableObjectFiber = false;
|
||||||
export const enableOwnerStacks = true;
|
|
||||||
export const enableShallowPropDiffing = false;
|
export const enableShallowPropDiffing = false;
|
||||||
export const enableSiblingPrerendering = true;
|
export const enableSiblingPrerendering = true;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,6 @@ export const {
|
||||||
// On WWW, __EXPERIMENTAL__ is used for a new modern build.
|
// On WWW, __EXPERIMENTAL__ is used for a new modern build.
|
||||||
// It's not used anywhere in production yet.
|
// It's not used anywhere in production yet.
|
||||||
|
|
||||||
// Can remove these two
|
|
||||||
export const enableOwnerStacks = true;
|
|
||||||
|
|
||||||
export const enableProfilerTimer = __PROFILE__;
|
export const enableProfilerTimer = __PROFILE__;
|
||||||
export const enableProfilerCommitHooks = __PROFILE__;
|
export const enableProfilerCommitHooks = __PROFILE__;
|
||||||
export const enableProfilerNestedUpdatePhase = __PROFILE__;
|
export const enableProfilerNestedUpdatePhase = __PROFILE__;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ import {
|
||||||
const REACT_CLIENT_REFERENCE: symbol = Symbol.for('react.client.reference');
|
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.
|
// 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 {
|
export default function isValidElementType(type: mixed): boolean {
|
||||||
if (typeof type === 'string' || typeof type === 'function') {
|
if (typeof type === 'string' || typeof type === 'function') {
|
||||||
return true;
|
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
|
// Flags that aren't currently used, but we still want to force variants to keep the
|
||||||
// code live.
|
// code live.
|
||||||
actual.disableInputAttributeSyncing = __VARIANT__;
|
actual.disableInputAttributeSyncing = __VARIANT__;
|
||||||
actual.enableOwnerStacks = __VARIANT__;
|
|
||||||
|
|
||||||
// These are hardcoded to true for the next release,
|
// These are hardcoded to true for the next release,
|
||||||
// but still run the tests against both variants until
|
// but still run the tests against both variants until
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,6 @@ jest.mock('shared/ReactFeatureFlags', () => {
|
||||||
'shared/forks/ReactFeatureFlags.native-fb.js'
|
'shared/forks/ReactFeatureFlags.native-fb.js'
|
||||||
);
|
);
|
||||||
|
|
||||||
actual.enableOwnerStacks = __VARIANT__;
|
|
||||||
|
|
||||||
// Lots of tests use these, but we don't want to expose it to RN.
|
// 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.
|
// 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
|
// Since the xplat tests run with the www entry points, some of these flags
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user