Files
react/packages/shared/consoleWithStackDev.js
Sebastian Markbåge 0b5835a46f [Flight] Implement captureStackTrace and owner stacks on the Server (#30197)
Wire up owner stacks in Flight to the shared internals. This exposes it
to `captureOwnerStack()`.

In this case we install it permanently as we only allow one RSC renderer
which then supports async contexts. Same thing we do for owner.

This also ends up adding it to errors logged by React through
`consoleWithStackDev`. The plan is to eventually remove that but this is
inline with what we do in Fizz and Fiber already.

However, at the same time we've instrumented the console so we need to
strip them back out before sending to the client. This lets the client
control whether to add the stack back in or allowing
`console.createTask` to control it.

This is another reason we shouldn't append them from React but for now
we hack it by removing them after the fact.
2024-07-04 12:15:51 -04:00

69 lines
2.2 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import ReactSharedInternals from 'shared/ReactSharedInternals';
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
let suppressWarning = false;
export function setSuppressWarning(newSuppressWarning) {
if (__DEV__) {
suppressWarning = newSuppressWarning;
}
}
// In DEV, calls to console.warn and console.error get replaced
// by calls to these methods by a Babel plugin.
//
// In PROD (or in packages without access to React internals),
// they are left as they are instead.
export function warn(format, ...args) {
if (__DEV__) {
if (!suppressWarning) {
printWarning('warn', format, args, new Error('react-stack-top-frame'));
}
}
}
export function error(format, ...args) {
if (__DEV__) {
if (!suppressWarning) {
printWarning('error', format, args, new Error('react-stack-top-frame'));
}
}
}
// eslint-disable-next-line react-internal/no-production-logging
const supportsCreateTask = __DEV__ && enableOwnerStacks && !!console.createTask;
export let isWritingAppendedStack = false;
function printWarning(level, format, args, currentStack) {
// When changing this logic, you might want to also
// update consoleWithStackDev.www.js as well.
if (__DEV__) {
if (!supportsCreateTask && ReactSharedInternals.getCurrentStack) {
// We only add the current stack to the console when createTask is not supported.
// Since createTask requires DevTools to be open to work, this means that stacks
// can be lost while DevTools isn't open but we can't detect this.
const stack = ReactSharedInternals.getCurrentStack(currentStack);
if (stack !== '') {
isWritingAppendedStack = true;
format += '%s';
args = args.concat([stack]);
}
}
args.unshift(format);
// We intentionally don't use spread (or .apply) directly because it
// breaks IE9: https://github.com/facebook/react/issues/13610
// eslint-disable-next-line react-internal/no-production-logging
Function.prototype.apply.call(console[level], console, args);
isWritingAppendedStack = false;
}
}