Skip to content
17 changes: 11 additions & 6 deletions packages/internal-test-utils/consoleMock.js
Original file line number Diff line number Diff line change
Expand Up @@ -418,13 +418,18 @@ export function createLogAssertion(
let argIndex = 0;
// console.* could have been called with a non-string e.g. `console.error(new Error())`
// eslint-disable-next-line react-internal/safe-string-coercion
String(format).replace(/%s/g, () => argIndex++);
String(format).replace(/%s|%c/g, () => argIndex++);
if (argIndex !== args.length) {
logsMismatchingFormat.push({
format,
args,
expectedArgCount: argIndex,
});
if (format.includes('%c%s')) {
// We intentionally use mismatching formatting when printing badging because we don't know
// the best default to use for different types because the default varies by platform.
} else {
logsMismatchingFormat.push({
format,
args,
expectedArgCount: argIndex,
});
}
}

// Check for extra component stacks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
* @flow
*/

import {warn, error} from 'shared/consoleWithStackDev';

const badgeFormat = '%c%s%c ';
// Same badge styling as DevTools.
const badgeStyle =
Expand Down Expand Up @@ -63,7 +65,14 @@ export function printToConsole(
);
}

// eslint-disable-next-line react-internal/no-production-logging
console[methodName].apply(console, newArgs);
return;
if (methodName === 'error') {
// eslint-disable-next-line react-internal/no-production-logging
error.apply(console, newArgs);
} else if (methodName === 'warn') {
// eslint-disable-next-line react-internal/no-production-logging
warn.apply(console, newArgs);
} else {
// eslint-disable-next-line react-internal/no-production-logging
console[methodName].apply(console, newArgs);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
* @flow
*/

import {warn, error} from 'shared/consoleWithStackDev';

const badgeFormat = '[%s] ';
const pad = ' ';

Expand Down Expand Up @@ -44,7 +46,14 @@ export function printToConsole(
newArgs.splice(offset, 0, badgeFormat, pad + badgeName + pad);
}

// eslint-disable-next-line react-internal/no-production-logging
console[methodName].apply(console, newArgs);
return;
if (methodName === 'error') {
// eslint-disable-next-line react-internal/no-production-logging
error.apply(console, newArgs);
} else if (methodName === 'warn') {
// eslint-disable-next-line react-internal/no-production-logging
warn.apply(console, newArgs);
} else {
// eslint-disable-next-line react-internal/no-production-logging
console[methodName].apply(console, newArgs);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
* @flow
*/

import {warn, error} from 'shared/consoleWithStackDev';

// This flips color using ANSI, then sets a color styling, then resets.
const badgeFormat = '\x1b[0m\x1b[7m%c%s\x1b[0m%c ';
// Same badge styling as DevTools.
Expand Down Expand Up @@ -64,7 +66,14 @@ export function printToConsole(
);
}

// eslint-disable-next-line react-internal/no-production-logging
console[methodName].apply(console, newArgs);
return;
if (methodName === 'error') {
// eslint-disable-next-line react-internal/no-production-logging
error.apply(console, newArgs);
} else if (methodName === 'warn') {
// eslint-disable-next-line react-internal/no-production-logging
warn.apply(console, newArgs);
} else {
// eslint-disable-next-line react-internal/no-production-logging
console[methodName].apply(console, newArgs);
}
}
5 changes: 5 additions & 0 deletions packages/react-client/src/ReactFlightClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -1730,6 +1730,7 @@ function resolveErrorDev(
digest: string,
message: string,
stack: string,
env: string,
): void {
if (!__DEV__) {
// These errors should never make it into a build so we don't need to encode them in codes.json
Expand Down Expand Up @@ -1769,6 +1770,7 @@ function resolveErrorDev(
}

(error: any).digest = digest;
(error: any).environmentName = env;
const errorWithDigest: ErrorWithDigest = (error: any);
const chunks = response._chunks;
const chunk = chunks.get(id);
Expand Down Expand Up @@ -2058,6 +2060,8 @@ function resolveConsoleEntry(
task.run(callStack);
return;
}
// TODO: Set the current owner so that consoleWithStackDev adds the component
// stack during the replay - if needed.
}
const rootTask = response._debugRootTask;
if (rootTask != null) {
Expand Down Expand Up @@ -2200,6 +2204,7 @@ function processFullRow(
errorInfo.digest,
errorInfo.message,
errorInfo.stack,
errorInfo.env,
);
} else {
resolveErrorProd(response, id, errorInfo.digest);
Expand Down
2 changes: 2 additions & 0 deletions packages/react-client/src/__tests__/ReactFlight-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ describe('ReactFlight', () => {
this.props.expectedMessage,
);
expect(this.state.error.digest).toBe('a dev digest');
expect(this.state.error.environmentName).toBe('Server');
} else {
expect(this.state.error.message).toBe(
'An error occurred in the Server Components render. The specific message is omitted in production' +
Expand All @@ -143,6 +144,7 @@ describe('ReactFlight', () => {
expectedDigest = '[]';
}
expect(this.state.error.digest).toContain(expectedDigest);
expect(this.state.error.environmentName).toBe(undefined);
expect(this.state.error.stack).toBe(
'Error: ' + this.state.error.message,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

export * from 'react-client/src/ReactFlightClientStreamConfigWeb';
export * from 'react-client/src/ReactFlightClientConsoleConfigBrowser';
export * from 'react-client/src/ReactClientConsoleConfigBrowser';
export * from 'react-server-dom-esm/src/ReactFlightClientConfigBundlerESM';
export * from 'react-server-dom-esm/src/ReactFlightClientConfigTargetESMBrowser';
export * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

export * from 'react-client/src/ReactFlightClientStreamConfigWeb';
export * from 'react-client/src/ReactFlightClientConsoleConfigBrowser';
export * from 'react-client/src/ReactClientConsoleConfigBrowser';
export * from 'react-server-dom-turbopack/src/ReactFlightClientConfigBundlerTurbopack';
export * from 'react-server-dom-turbopack/src/ReactFlightClientConfigBundlerTurbopackBrowser';
export * from 'react-server-dom-turbopack/src/ReactFlightClientConfigTargetTurbopackBrowser';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

export * from 'react-client/src/ReactFlightClientStreamConfigWeb';
export * from 'react-client/src/ReactFlightClientConsoleConfigBrowser';
export * from 'react-client/src/ReactClientConsoleConfigBrowser';
export * from 'react-server-dom-webpack/src/ReactFlightClientConfigBundlerWebpack';
export * from 'react-server-dom-webpack/src/ReactFlightClientConfigBundlerWebpackBrowser';
export * from 'react-server-dom-webpack/src/ReactFlightClientConfigTargetWebpackBrowser';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

export * from 'react-client/src/ReactFlightClientStreamConfigWeb';
export * from 'react-client/src/ReactFlightClientConsoleConfigPlain';
export * from 'react-client/src/ReactClientConsoleConfigPlain';
export * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';

export type Response = any;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

export * from 'react-client/src/ReactFlightClientStreamConfigWeb';
export * from 'react-client/src/ReactFlightClientConsoleConfigServer';
export * from 'react-client/src/ReactClientConsoleConfigServer';
export * from 'react-server-dom-turbopack/src/ReactFlightClientConfigBundlerTurbopack';
export * from 'react-server-dom-turbopack/src/ReactFlightClientConfigBundlerTurbopackServer';
export * from 'react-server-dom-turbopack/src/ReactFlightClientConfigTargetTurbopackServer';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

export * from 'react-client/src/ReactFlightClientStreamConfigWeb';
export * from 'react-client/src/ReactFlightClientConsoleConfigServer';
export * from 'react-client/src/ReactClientConsoleConfigServer';
export * from 'react-server-dom-webpack/src/ReactFlightClientConfigBundlerWebpack';
export * from 'react-server-dom-webpack/src/ReactFlightClientConfigBundlerWebpackServer';
export * from 'react-server-dom-webpack/src/ReactFlightClientConfigTargetWebpackServer';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

export * from 'react-client/src/ReactFlightClientStreamConfigWeb';
export * from 'react-client/src/ReactFlightClientConsoleConfigBrowser';
export * from 'react-client/src/ReactClientConsoleConfigBrowser';
export * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';

export type Response = any;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

export * from 'react-client/src/ReactFlightClientStreamConfigNode';
export * from 'react-client/src/ReactFlightClientConsoleConfigServer';
export * from 'react-client/src/ReactClientConsoleConfigServer';
export * from 'react-server-dom-esm/src/ReactFlightClientConfigBundlerESM';
export * from 'react-server-dom-esm/src/ReactFlightClientConfigTargetESMServer';
export * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

export * from 'react-client/src/ReactFlightClientStreamConfigNode';
export * from 'react-client/src/ReactFlightClientConsoleConfigServer';
export * from 'react-client/src/ReactClientConsoleConfigServer';
export * from 'react-server-dom-turbopack/src/ReactFlightClientConfigBundlerTurbopack';
export * from 'react-server-dom-turbopack/src/ReactFlightClientConfigBundlerTurbopackServer';
export * from 'react-server-dom-turbopack/src/ReactFlightClientConfigTargetTurbopackServer';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

export * from 'react-client/src/ReactFlightClientStreamConfigNode';
export * from 'react-client/src/ReactFlightClientConsoleConfigServer';
export * from 'react-client/src/ReactClientConsoleConfigServer';
export * from 'react-server-dom-turbopack/src/ReactFlightClientConfigBundlerNode';
export * from 'react-server-dom-turbopack/src/ReactFlightClientConfigTargetTurbopackServer';
export * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

export * from 'react-client/src/ReactFlightClientStreamConfigNode';
export * from 'react-client/src/ReactFlightClientConsoleConfigServer';
export * from 'react-client/src/ReactClientConsoleConfigServer';
export * from 'react-server-dom-webpack/src/ReactFlightClientConfigBundlerWebpack';
export * from 'react-server-dom-webpack/src/ReactFlightClientConfigBundlerWebpackServer';
export * from 'react-server-dom-webpack/src/ReactFlightClientConfigTargetWebpackServer';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

export * from 'react-client/src/ReactFlightClientStreamConfigNode';
export * from 'react-client/src/ReactFlightClientConsoleConfigServer';
export * from 'react-client/src/ReactClientConsoleConfigServer';
export * from 'react-server-dom-webpack/src/ReactFlightClientConfigBundlerNode';
export * from 'react-server-dom-webpack/src/ReactFlightClientConfigTargetWebpackServer';
export * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';
Expand Down
5 changes: 5 additions & 0 deletions packages/react-noop-renderer/src/createReactNoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,11 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
NotPendingTransition: (null: TransitionStatus),

resetFormInstance(form: Instance) {},

printToConsole(methodName, args, badgeName) {
// eslint-disable-next-line react-internal/no-production-logging
console[methodName].apply(console, args);
},
};

const hostConfig = useMutation
Expand Down
36 changes: 29 additions & 7 deletions packages/react-reconciler/src/ReactFiberErrorLogger.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import ReactSharedInternals from 'shared/ReactSharedInternals';

import {enableOwnerStacks} from 'shared/ReactFeatureFlags';

import {printToConsole} from './ReactFiberConfig';

// Side-channel since I'm not sure we want to make this part of the public API
let componentName: null | string = null;
let errorBoundaryName: null | string = null;
Expand Down Expand Up @@ -94,13 +96,33 @@ export function defaultOnCaughtError(
}.`;

if (enableOwnerStacks) {
console.error(
'%o\n\n%s\n\n%s\n',
error,
componentNameMessage,
recreateMessage,
// We let our consoleWithStackDev wrapper add the component stack to the end.
);
if (
typeof error === 'object' &&
error !== null &&
typeof error.environmentName === 'string'
) {
// This was a Server error. We print the environment name in a badge just like we do with
// replays of console logs to indicate that the source of this throw as actually the Server.
printToConsole(
'error',
[
'%o\n\n%s\n\n%s\n',
error,
componentNameMessage,
recreateMessage,
// We let our consoleWithStackDev wrapper add the component stack to the end.
],
error.environmentName,
);
} else {
console.error(
'%o\n\n%s\n\n%s\n',
error,
componentNameMessage,
recreateMessage,
// We let our consoleWithStackDev wrapper add the component stack to the end.
);
}
} else {
// 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
*/

export * from 'react-art/src/ReactFiberConfigART';
export * from 'react-client/src/ReactClientConsoleConfigBrowser';
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export const suspendInstance = $$$config.suspendInstance;
export const waitForCommitToBeReady = $$$config.waitForCommitToBeReady;
export const NotPendingTransition = $$$config.NotPendingTransition;
export const resetFormInstance = $$$config.resetFormInstance;
export const printToConsole = $$$config.printToConsole;

// -------------------
// Microtasks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
*/

export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM';
export * from 'react-client/src/ReactClientConsoleConfigBrowser';
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
*/

export * from 'react-native-renderer/src/ReactFiberConfigFabric';
export * from 'react-client/src/ReactClientConsoleConfigPlain';
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
*/

export * from 'react-native-renderer/src/ReactFiberConfigNative';
export * from 'react-client/src/ReactClientConsoleConfigPlain';
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
*/

export * from 'react-test-renderer/src/ReactFiberConfigTestHost';
export * from 'react-client/src/ReactClientConsoleConfigPlain';
Loading