Files
react/packages/react-client/src/ReactClientConsoleConfigServer.js
Sebastian Markbåge e8df0cf9f7 Switch to binding the console with badging instead of calling it directly (#30461)
This is a major nit but this avoids an extra stack frame when we're
replaying logs.

Normally the `printToConsole` frame doesn't show up because it'd be
ignore listed.

<img width="421" alt="Screenshot 2024-07-25 at 11 49 39 AM"
src="https://github.com/user-attachments/assets/81334c2f-e19e-476a-871e-c4db9dee294e">

When you expand to show ignore listed frames a ton of other frames show
up.

<img width="516" alt="Screenshot 2024-07-25 at 11 49 47 AM"
src="https://github.com/user-attachments/assets/2ab8bdfb-464c-408d-9176-ee2fabc114b6">

The annoying thing about this frame is that it's at the top of the stack
where as typically framework stuff ends up at the bottom and something
you can ignore. The user space stack comes first.

With this fix there's no longer any `printToConsole` frame.

<img width="590" alt="Screenshot 2024-07-25 at 12 09 09 PM"
src="https://github.com/user-attachments/assets/b8365d53-31f3-43df-abce-172d608d3c9c">

Am I wiling to eat the added complexity and slightly slower performance
for this nit? Definitely.
2024-07-25 12:32:16 -04:00

74 lines
1.9 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.
*
* @flow
*/
// 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.
const badgeStyle =
// We use a fixed background if light-dark is not supported, otherwise
// we use a transparent background.
'background: #e6e6e6;' +
'background: light-dark(rgba(0,0,0,0.1), rgba(255,255,255,0.25));' +
'color: #000000;' +
'color: light-dark(#000000, #ffffff);' +
'border-radius: 2px';
const resetStyle = '';
const pad = ' ';
const bind = Function.prototype.bind;
export function bindToConsole(
methodName: string,
args: Array<any>,
badgeName: string,
): () => any {
let offset = 0;
switch (methodName) {
case 'dir':
case 'dirxml':
case 'groupEnd':
case 'table': {
// These methods cannot be colorized because they don't take a formatting string.
// $FlowFixMe
return bind.apply(console[methodName], [console].concat(args)); // eslint-disable-line react-internal/no-production-logging
}
case 'assert': {
// assert takes formatting options as the second argument.
offset = 1;
}
}
const newArgs = args.slice(0);
if (typeof newArgs[offset] === 'string') {
newArgs.splice(
offset,
1,
badgeFormat + newArgs[offset],
badgeStyle,
pad + badgeName + pad,
resetStyle,
);
} else {
newArgs.splice(
offset,
0,
badgeFormat,
badgeStyle,
pad + badgeName + pad,
resetStyle,
);
}
// The "this" binding in the "bind";
newArgs.unshift(console);
// $FlowFixMe
return bind.apply(console[methodName], newArgs); // eslint-disable-line react-internal/no-production-logging
}