Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/react-devtools-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ if (process.env.NODE_ENV !== 'production') {
#### `Settings`
| Spec | Default value |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| <pre>{<br> appendComponentStack: boolean,<br> breakOnConsoleErrors: boolean,<br> showInlineWarningsAndErrors: boolean,<br> hideConsoleLogsInStrictMode: boolean<br>}</pre> | <pre>{<br> appendComponentStack: true,<br> breakOnConsoleErrors: false,<br> showInlineWarningsAndErrors: true,<br> hideConsoleLogsInStrictMode: false<br>}</pre> |
| <pre>{<br> appendComponentStack: boolean,<br> breakOnConsoleErrors: boolean,<br> showInlineWarningsAndErrors: boolean,<br> hideConsoleLogsInStrictMode: boolean,<br> disableSecondConsoleLogDimmingInStrictMode: boolean<br>}</pre> | <pre>{<br> appendComponentStack: true,<br> breakOnConsoleErrors: false,<br> showInlineWarningsAndErrors: true,<br> hideConsoleLogsInStrictMode: false,<br> disableSecondConsoleLogDimmingInStrictMode: false<br>}</pre> |

### `connectToDevTools` options
| Prop | Default | Description |
Expand All @@ -53,7 +53,7 @@ if (process.env.NODE_ENV !== 'production') {
| `onSubscribe` | Function, which receives listener (function, with a single argument) as an argument. Called when backend subscribes to messages from the other end (frontend). |
| `onUnsubscribe` | Function, which receives listener (function) as an argument. Called when backend unsubscribes to messages from the other end (frontend). |
| `onMessage` | Function, which receives 2 arguments: event (string) and payload (any). Called when backend emits a message, which should be sent to the frontend. |
| `onSettingsUpdated` | A callback that will be called when the user updates the settings in the UI. You can use it for persisting user settings. |
| `onSettingsUpdated` | A callback that will be called when the user updates the settings in the UI. You can use it for persisting user settings. |

Unlike `connectToDevTools`, `connectWithCustomMessagingProtocol` returns a callback, which can be used for unsubscribing the backend from the global DevTools hook.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ async function messageListener(event: MessageEvent) {
if (typeof settings.hideConsoleLogsInStrictMode !== 'boolean') {
settings.hideConsoleLogsInStrictMode = false;
}
if (
typeof settings.disableSecondConsoleLogDimmingInStrictMode !== 'boolean'
) {
settings.disableSecondConsoleLogDimmingInStrictMode = false;
}

window.postMessage({
source: 'react-devtools-hook-settings-injector',
Expand Down
5 changes: 5 additions & 0 deletions packages/react-devtools-inline/src/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ function startActivation(contentWindow: any, bridge: BackendBridge) {
componentFilters,
showInlineWarningsAndErrors,
hideConsoleLogsInStrictMode,
disableSecondConsoleLogDimmingInStrictMode,
} = data;

contentWindow.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__ =
Expand All @@ -38,6 +39,8 @@ function startActivation(contentWindow: any, bridge: BackendBridge) {
showInlineWarningsAndErrors;
contentWindow.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ =
hideConsoleLogsInStrictMode;
contentWindow.__REACT_DEVTOOLS_DISABLE_SECOND_CONSOLE_LOG_DIMMING_IN_STRICT_MODE__ =
disableSecondConsoleLogDimmingInStrictMode;

// TRICKY
// The backend entry point may be required in the context of an iframe or the parent window.
Expand All @@ -53,6 +56,8 @@ function startActivation(contentWindow: any, bridge: BackendBridge) {
showInlineWarningsAndErrors;
window.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ =
hideConsoleLogsInStrictMode;
window.__REACT_DEVTOOLS_DISABLE_SECOND_CONSOLE_LOG_DIMMING_IN_STRICT_MODE__ =
disableSecondConsoleLogDimmingInStrictMode;
}

finishActivation(contentWindow, bridge);
Expand Down
81 changes: 81 additions & 0 deletions packages/react-devtools-shared/src/__tests__/console-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -733,4 +733,85 @@ describe('console', () => {
: 'in Child (at **)\n in Intermediate (at **)\n in Parent (at **)',
]);
});

it('should not dim console logs if disableSecondConsoleLogDimmingInStrictMode is enabled', () => {
global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = false;
global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.hideConsoleLogsInStrictMode =
false;
global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.disableSecondConsoleLogDimmingInStrictMode =
true;

const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);

function App() {
console.log('log');
console.warn('warn');
console.error('error');
return <div />;
}

act(() =>
root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
),
);

// Both logs should be called (double logging)
expect(global.consoleLogMock).toHaveBeenCalledTimes(2);
expect(global.consoleWarnMock).toHaveBeenCalledTimes(2);
expect(global.consoleErrorMock).toHaveBeenCalledTimes(2);

// The second log should NOT have dimming (no ANSI codes)
expect(global.consoleLogMock.mock.calls[1]).toEqual(['log']);
expect(global.consoleWarnMock.mock.calls[1]).toEqual(['warn']);
expect(global.consoleErrorMock.mock.calls[1]).toEqual(['error']);
});

it('should dim console logs if disableSecondConsoleLogDimmingInStrictMode is disabled', () => {
global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = false;
global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.hideConsoleLogsInStrictMode =
false;
global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.disableSecondConsoleLogDimmingInStrictMode =
false;

const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);

function App() {
console.log('log');
console.warn('warn');
console.error('error');
return <div />;
}

act(() =>
root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
),
);

// Both logs should be called (double logging)
expect(global.consoleLogMock).toHaveBeenCalledTimes(2);
expect(global.consoleWarnMock).toHaveBeenCalledTimes(2);
expect(global.consoleErrorMock).toHaveBeenCalledTimes(2);

// The second log should have dimming (ANSI codes present)
expect(global.consoleLogMock.mock.calls[1]).toEqual([
'\x1b[2;38;2;124;124;124m%s\x1b[0m',
'log',
]);
expect(global.consoleWarnMock.mock.calls[1]).toEqual([
'\x1b[2;38;2;124;124;124m%s\x1b[0m',
'warn',
]);
expect(global.consoleErrorMock.mock.calls[1]).toEqual([
'\x1b[2;38;2;124;124;124m%s\x1b[0m',
'error',
]);
});
});
1 change: 1 addition & 0 deletions packages/react-devtools-shared/src/__tests__/setupTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ beforeEach(() => {
breakOnConsoleErrors: false,
showInlineWarningsAndErrors: true,
hideConsoleLogsInStrictMode: false,
disableSecondConsoleLogDimmingInStrictMode: false,
});

const bridgeListeners = [];
Expand Down
1 change: 1 addition & 0 deletions packages/react-devtools-shared/src/backend/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -597,4 +597,5 @@ export type DevToolsHookSettings = {
breakOnConsoleErrors: boolean,
showInlineWarningsAndErrors: boolean,
hideConsoleLogsInStrictMode: boolean,
disableSecondConsoleLogDimmingInStrictMode: boolean,
};
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export default function DebuggingSettings({
useState(usedHookSettings.hideConsoleLogsInStrictMode);
const [showInlineWarningsAndErrors, setShowInlineWarningsAndErrors] =
useState(usedHookSettings.showInlineWarningsAndErrors);
const [
disableSecondConsoleLogDimmingInStrictMode,
setDisableSecondConsoleLogDimmingInStrictMode,
] = useState(usedHookSettings.disableSecondConsoleLogDimmingInStrictMode);

useEffect(() => {
store.setShouldShowWarningsAndErrors(showInlineWarningsAndErrors);
Expand All @@ -47,13 +51,15 @@ export default function DebuggingSettings({
breakOnConsoleErrors,
showInlineWarningsAndErrors,
hideConsoleLogsInStrictMode,
disableSecondConsoleLogDimmingInStrictMode,
});
}, [
store,
appendComponentStack,
breakOnConsoleErrors,
showInlineWarningsAndErrors,
hideConsoleLogsInStrictMode,
disableSecondConsoleLogDimmingInStrictMode,
]);

return (
Expand Down Expand Up @@ -105,12 +111,49 @@ export default function DebuggingSettings({
<input
type="checkbox"
checked={hideConsoleLogsInStrictMode}
onChange={({currentTarget}) => {
setHideConsoleLogsInStrictMode(currentTarget.checked);
if (currentTarget.checked) {
setDisableSecondConsoleLogDimmingInStrictMode(false);
}
}}
className={styles.SettingRowCheckbox}
/>
Hide logs during additional invocations in&nbsp;
<a
className={styles.StrictModeLink}
target="_blank"
rel="noopener noreferrer"
href="https://react.dev/reference/react/StrictMode">
Strict Mode
</a>
</label>
</div>

<div
className={
hideConsoleLogsInStrictMode
? `${styles.SettingDisabled} ${styles.SettingWrapper}`
: styles.SettingWrapper
}>
<label
className={
hideConsoleLogsInStrictMode
? `${styles.SettingDisabled} ${styles.SettingRow}`
: styles.SettingRow
}>
<input
type="checkbox"
checked={disableSecondConsoleLogDimmingInStrictMode}
disabled={hideConsoleLogsInStrictMode}
onChange={({currentTarget}) =>
setHideConsoleLogsInStrictMode(currentTarget.checked)
setDisableSecondConsoleLogDimmingInStrictMode(
currentTarget.checked,
)
}
className={styles.SettingRowCheckbox}
/>
Hide logs during additional invocations in&nbsp;
Disable log dimming during additional invocations in&nbsp;
<a
className={styles.StrictModeLink}
target="_blank"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
margin: 0.125rem 0.25rem 0.125rem 0;
}

.SettingDisabled {
opacity: 0.5;
cursor: not-allowed;
}

.OptionGroup {
display: inline-flex;
flex-direction: row;
Expand Down
31 changes: 20 additions & 11 deletions packages/react-devtools-shared/src/hook.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,17 +367,22 @@ export function installHook(
return;
}

// Dim the text color of the double logs if we're not hiding them.
// Firefox doesn't support ANSI escape sequences
if (__IS_FIREFOX__) {
originalMethod(
...formatWithStyles(args, FIREFOX_CONSOLE_DIMMING_COLOR),
);
if (settings.disableSecondConsoleLogDimmingInStrictMode) {
// Don't dim the console logs
originalMethod(...args);
} else {
originalMethod(
ANSI_STYLE_DIMMING_TEMPLATE,
...formatConsoleArguments(...args),
);
// Dim the text color of the double logs if we're not hiding them.
// Firefox doesn't support ANSI escape sequences
if (__IS_FIREFOX__) {
originalMethod(
...formatWithStyles(args, FIREFOX_CONSOLE_DIMMING_COLOR),
);
} else {
originalMethod(
ANSI_STYLE_DIMMING_TEMPLATE,
...formatConsoleArguments(...args),
);
}
}
};

Expand Down Expand Up @@ -579,7 +584,10 @@ export function installHook(
debugger;
}

if (isRunningDuringStrictModeInvocation) {
if (
isRunningDuringStrictModeInvocation &&
!settings.disableSecondConsoleLogDimmingInStrictMode
) {
// Dim the text color of the double logs if we're not hiding them.
// Firefox doesn't support ANSI escape sequences
if (__IS_FIREFOX__) {
Expand Down Expand Up @@ -667,6 +675,7 @@ export function installHook(
breakOnConsoleErrors: false,
showInlineWarningsAndErrors: true,
hideConsoleLogsInStrictMode: false,
disableSecondConsoleLogDimmingInStrictMode: false,
};
patchConsoleForErrorsAndWarnings();
} else {
Expand Down