From b061b597f77c979531a3f2c9c04ba435342b0043 Mon Sep 17 00:00:00 2001 From: Jack Pope Date: Fri, 12 Dec 2025 09:06:31 -0500 Subject: [PATCH 01/17] Upgrade nextjs for compiler playground (#35353) Upgrading due to CVE-2025-55183 and CVE-2025-67779 --- compiler/apps/playground/package.json | 6 ++--- compiler/apps/playground/yarn.lock | 34 +++++++++++++-------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/compiler/apps/playground/package.json b/compiler/apps/playground/package.json index e92826cbf5f..217153e6a21 100644 --- a/compiler/apps/playground/package.json +++ b/compiler/apps/playground/package.json @@ -35,13 +35,13 @@ "lru-cache": "^11.2.2", "lz-string": "^1.5.0", "monaco-editor": "^0.52.0", - "next": "15.5.7", + "next": "15.5.9", "notistack": "^3.0.0-alpha.7", "prettier": "^3.3.3", "pretty-format": "^29.3.1", "re-resizable": "^6.9.16", - "react": "19.2", - "react-dom": "19.2" + "react": "19.2.3", + "react-dom": "19.2.3" }, "devDependencies": { "@types/node": "18.11.9", diff --git a/compiler/apps/playground/yarn.lock b/compiler/apps/playground/yarn.lock index ce4928e3d03..be63ac56b61 100644 --- a/compiler/apps/playground/yarn.lock +++ b/compiler/apps/playground/yarn.lock @@ -715,10 +715,10 @@ dependencies: "@monaco-editor/loader" "^1.6.1" -"@next/env@15.5.7": - version "15.5.7" - resolved "https://registry.yarnpkg.com/@next/env/-/env-15.5.7.tgz#4168db34ae3bc9fd9ad3b951d327f4cfc38d4362" - integrity sha512-4h6Y2NyEkIEN7Z8YxkA27pq6zTkS09bUSYC0xjd0NpwFxjnIKeZEeH591o5WECSmjpUhLn3H2QLJcDye3Uzcvg== +"@next/env@15.5.9": + version "15.5.9" + resolved "https://registry.yarnpkg.com/@next/env/-/env-15.5.9.tgz#53c2c34dc17cd87b61f70c6cc211e303123b2ab8" + integrity sha512-4GlTZ+EJM7WaW2HEZcyU317tIQDjkQIyENDLxYJfSWlfqguN+dHkZgyQTV/7ykvobU7yEH5gKvreNrH4B6QgIg== "@next/eslint-plugin-next@15.5.2": version "15.5.2" @@ -3204,12 +3204,12 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -next@15.5.7: - version "15.5.7" - resolved "https://registry.yarnpkg.com/next/-/next-15.5.7.tgz#4507700b2bbcaf2c9fb7a9ad25c0dac2ba4a9a75" - integrity sha512-+t2/0jIJ48kUpGKkdlhgkv+zPTEOoXyr60qXe68eB/pl3CMJaLeIGjzp5D6Oqt25hCBiBTt8wEeeAzfJvUKnPQ== +next@15.5.9: + version "15.5.9" + resolved "https://registry.yarnpkg.com/next/-/next-15.5.9.tgz#1b80d05865cc27e710fb4dcfc6fd9e726ed12ad4" + integrity sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg== dependencies: - "@next/env" "15.5.7" + "@next/env" "15.5.9" "@swc/helpers" "0.5.15" caniuse-lite "^1.0.30001579" postcss "8.4.31" @@ -3582,10 +3582,10 @@ re-resizable@^6.9.16: resolved "https://registry.yarnpkg.com/re-resizable/-/re-resizable-6.10.0.tgz#d684a096ab438f1a93f59ad3a580a206b0ce31ee" integrity sha512-hysSK0xmA5nz24HBVztlk4yCqCLCvS32E6ZpWxVKop9x3tqCa4yAj1++facrmkOf62JsJHjmjABdKxXofYioCw== -react-dom@19.2: - version "19.2.0" - resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz#00ed1e959c365e9a9d48f8918377465466ec3af8" - integrity sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ== +react-dom@19.2.3: + version "19.2.3" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.2.3.tgz#f0b61d7e5c4a86773889fcc1853af3ed5f215b17" + integrity sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg== dependencies: scheduler "^0.27.0" @@ -3599,10 +3599,10 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== -react@19.2: - version "19.2.0" - resolved "https://registry.npmjs.org/react/-/react-19.2.0.tgz#d33dd1721698f4376ae57a54098cb47fc75d93a5" - integrity sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ== +react@19.2.3: + version "19.2.3" + resolved "https://registry.yarnpkg.com/react/-/react-19.2.3.tgz#d83e5e8e7a258cf6b4fe28640515f99b87cd19b8" + integrity sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA== read-cache@^1.0.0: version "1.0.0" From ba5b843692519a226347aecfb789d90fcb24b4bc Mon Sep 17 00:00:00 2001 From: "Sebastian \"Sebbie\" Silbermann" Date: Mon, 15 Dec 2025 11:45:17 +0100 Subject: [PATCH 02/17] [test] Exclude repository root from assertions (#35361) --- .eslintrc.js | 1 + packages/internal-test-utils/debugInfo.js | 6 +--- .../src/__tests__/ReactFlight-test.js | 5 +--- .../src/__tests__/ReactFlightDOMEdge-test.js | 28 +++++++++++++------ scripts/jest/setupTests.js | 4 +++ 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 86ad482eff9..dec7cd8f304 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -635,6 +635,7 @@ module.exports = { FocusOptions: 'readonly', OptionalEffectTiming: 'readonly', + __REACT_ROOT_PATH_TEST__: 'readonly', spyOnDev: 'readonly', spyOnDevAndProd: 'readonly', spyOnProd: 'readonly', diff --git a/packages/internal-test-utils/debugInfo.js b/packages/internal-test-utils/debugInfo.js index 75183ce4b6b..b749c8db861 100644 --- a/packages/internal-test-utils/debugInfo.js +++ b/packages/internal-test-utils/debugInfo.js @@ -1,9 +1,5 @@ 'use strict'; -const path = require('path'); - -const repoRoot = path.resolve(__dirname, '../../'); - type DebugInfoConfig = { ignoreProps?: boolean, ignoreRscStreamInfo?: boolean, @@ -34,7 +30,7 @@ function normalizeStack(stack) { const [name, file, line, col, enclosingLine, enclosingCol] = stack[i]; copy.push([ name, - file.replace(repoRoot, ''), + file.replace(__REACT_ROOT_PATH_TEST__, ''), line, col, enclosingLine, diff --git a/packages/react-client/src/__tests__/ReactFlight-test.js b/packages/react-client/src/__tests__/ReactFlight-test.js index d642a02c8c6..b2dcd69899b 100644 --- a/packages/react-client/src/__tests__/ReactFlight-test.js +++ b/packages/react-client/src/__tests__/ReactFlight-test.js @@ -10,8 +10,6 @@ 'use strict'; -const path = require('path'); - if (typeof Blob === 'undefined') { global.Blob = require('buffer').Blob; } @@ -33,9 +31,8 @@ function normalizeCodeLocInfo(str) { ); } -const repoRoot = path.resolve(__dirname, '../../../../'); function normalizeReactCodeLocInfo(str) { - const repoRootForRegexp = repoRoot.replace(/\//g, '\\/'); + const repoRootForRegexp = __REACT_ROOT_PATH_TEST__.replace(/\//g, '\\/'); const repoFileLocMatch = new RegExp(`${repoRootForRegexp}.+?:\\d+:\\d+`, 'g'); return str && str.replace(repoFileLocMatch, '**'); } diff --git a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js index a7290f9523d..995f0da37ec 100644 --- a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js +++ b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js @@ -39,6 +39,10 @@ function normalizeCodeLocInfo(str) { ); } +function normalizeSerializedContent(str) { + return str.replaceAll(__REACT_ROOT_PATH_TEST__, '**'); +} + describe('ReactFlightDOMEdge', () => { beforeEach(() => { // Mock performance.now for timing tests @@ -481,8 +485,10 @@ describe('ReactFlightDOMEdge', () => { ); const [stream1, stream2] = passThrough(stream).tee(); - const serializedContent = await readResult(stream1); - expect(serializedContent.length).toBeLessThan(1100); + const serializedContent = normalizeSerializedContent( + await readResult(stream1), + ); + expect(serializedContent.length).toBeLessThan(1075); const result = await ReactServerDOMClient.createFromReadableStream( stream2, @@ -551,9 +557,11 @@ describe('ReactFlightDOMEdge', () => { ); const [stream1, stream2] = passThrough(stream).tee(); - const serializedContent = await readResult(stream1); + const serializedContent = normalizeSerializedContent( + await readResult(stream1), + ); - expect(serializedContent.length).toBeLessThan(490); + expect(serializedContent.length).toBeLessThan(465); expect(timesRendered).toBeLessThan(5); const model = await ReactServerDOMClient.createFromReadableStream(stream2, { @@ -623,8 +631,10 @@ describe('ReactFlightDOMEdge', () => { ); const [stream1, stream2] = passThrough(stream).tee(); - const serializedContent = await readResult(stream1); - expect(serializedContent.length).toBeLessThan(__DEV__ ? 680 : 400); + const serializedContent = normalizeSerializedContent( + await readResult(stream1), + ); + expect(serializedContent.length).toBeLessThan(__DEV__ ? 630 : 400); expect(timesRendered).toBeLessThan(5); const model = await serverAct(() => @@ -657,8 +667,10 @@ describe('ReactFlightDOMEdge', () => { , ), ); - const serializedContent = await readResult(stream); - const expectedDebugInfoSize = __DEV__ ? 320 * 20 : 0; + const serializedContent = normalizeSerializedContent( + await readResult(stream), + ); + const expectedDebugInfoSize = __DEV__ ? 295 * 20 : 0; expect(serializedContent.length).toBeLessThan(150 + expectedDebugInfoSize); }); diff --git a/scripts/jest/setupTests.js b/scripts/jest/setupTests.js index 758ac5e0a01..c3d34089063 100644 --- a/scripts/jest/setupTests.js +++ b/scripts/jest/setupTests.js @@ -6,6 +6,7 @@ const { resetAllUnexpectedConsoleCalls, patchConsoleMethods, } = require('internal-test-utils/consoleMock'); +const path = require('path'); if (process.env.REACT_CLASS_EQUIVALENCE_TEST) { // Inside the class equivalence tester, we have a custom environment, let's @@ -18,6 +19,9 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) { const spyOn = jest.spyOn; const noop = jest.fn; + // Can be used to normalize paths in stackframes + global.__REACT_ROOT_PATH_TEST__ = path.resolve(__dirname, '../..'); + // Spying on console methods in production builds can mask errors. // This is why we added an explicit spyOnDev() helper. // It's too easy to accidentally use the more familiar spyOn() helper though, From bcf97c7564cbe0c903a16a8d6ff52f124f2f06ff Mon Sep 17 00:00:00 2001 From: emily8rown Date: Mon, 15 Dec 2025 13:41:43 +0000 Subject: [PATCH 03/17] Devtools disable log dimming strict mode setting (#35207) ## Summary Currently, every second console log is dimmed, receiving a special style that indicates to user that it was raising because of [React Strict Mode](https://react.dev/reference/react/StrictMode) second rendering. This introduces a setting to disable this. ## How did you test this change? Test in console-test.js https://github.com/user-attachments/assets/af6663ac-f79b-4824-95c0-d46b0c8dec12 Browser extension react devtools https://github.com/user-attachments/assets/7e2ecb7a-fbdf-4c72-ab45-7e3a1c6e5e44 React native dev tools: https://github.com/user-attachments/assets/d875b3ac-1f27-43f8-8d9d-12b2d65fa6e6 --------- Co-authored-by: Ruslan Lesiutin <28902667+hoxyq@users.noreply.github.com> --- packages/react-devtools-core/README.md | 4 +- .../contentScripts/hookSettingsInjector.js | 5 ++ packages/react-devtools-inline/src/backend.js | 5 ++ .../src/__tests__/console-test.js | 81 +++++++++++++++++++ .../src/__tests__/setupTests.js | 1 + .../src/backend/types.js | 1 + .../views/Settings/DebuggingSettings.js | 47 ++++++++++- .../views/Settings/SettingsShared.css | 5 ++ packages/react-devtools-shared/src/hook.js | 31 ++++--- 9 files changed, 165 insertions(+), 15 deletions(-) diff --git a/packages/react-devtools-core/README.md b/packages/react-devtools-core/README.md index f3487fefba7..21f4f697cf3 100644 --- a/packages/react-devtools-core/README.md +++ b/packages/react-devtools-core/README.md @@ -32,7 +32,7 @@ if (process.env.NODE_ENV !== 'production') { #### `Settings` | Spec | Default value | |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------| -|
{
appendComponentStack: boolean,
breakOnConsoleErrors: boolean,
showInlineWarningsAndErrors: boolean,
hideConsoleLogsInStrictMode: boolean
}
|
{
appendComponentStack: true,
breakOnConsoleErrors: false,
showInlineWarningsAndErrors: true,
hideConsoleLogsInStrictMode: false
}
| +|
{
appendComponentStack: boolean,
breakOnConsoleErrors: boolean,
showInlineWarningsAndErrors: boolean,
hideConsoleLogsInStrictMode: boolean,
disableSecondConsoleLogDimmingInStrictMode: boolean
}
|
{
appendComponentStack: true,
breakOnConsoleErrors: false,
showInlineWarningsAndErrors: true,
hideConsoleLogsInStrictMode: false,
disableSecondConsoleLogDimmingInStrictMode: false
}
| ### `connectToDevTools` options | Prop | Default | Description | @@ -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. diff --git a/packages/react-devtools-extensions/src/contentScripts/hookSettingsInjector.js b/packages/react-devtools-extensions/src/contentScripts/hookSettingsInjector.js index e26108edac7..da809f65cac 100644 --- a/packages/react-devtools-extensions/src/contentScripts/hookSettingsInjector.js +++ b/packages/react-devtools-extensions/src/contentScripts/hookSettingsInjector.js @@ -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', diff --git a/packages/react-devtools-inline/src/backend.js b/packages/react-devtools-inline/src/backend.js index 354970446db..849e103f218 100644 --- a/packages/react-devtools-inline/src/backend.js +++ b/packages/react-devtools-inline/src/backend.js @@ -27,6 +27,7 @@ function startActivation(contentWindow: any, bridge: BackendBridge) { componentFilters, showInlineWarningsAndErrors, hideConsoleLogsInStrictMode, + disableSecondConsoleLogDimmingInStrictMode, } = data; contentWindow.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__ = @@ -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. @@ -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); diff --git a/packages/react-devtools-shared/src/__tests__/console-test.js b/packages/react-devtools-shared/src/__tests__/console-test.js index 00d6d971267..c37285e855a 100644 --- a/packages/react-devtools-shared/src/__tests__/console-test.js +++ b/packages/react-devtools-shared/src/__tests__/console-test.js @@ -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
; + } + + act(() => + root.render( + + + , + ), + ); + + // 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
; + } + + act(() => + root.render( + + + , + ), + ); + + // 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', + ]); + }); }); diff --git a/packages/react-devtools-shared/src/__tests__/setupTests.js b/packages/react-devtools-shared/src/__tests__/setupTests.js index aad3fbc00ea..6efcefe2f74 100644 --- a/packages/react-devtools-shared/src/__tests__/setupTests.js +++ b/packages/react-devtools-shared/src/__tests__/setupTests.js @@ -248,6 +248,7 @@ beforeEach(() => { breakOnConsoleErrors: false, showInlineWarningsAndErrors: true, hideConsoleLogsInStrictMode: false, + disableSecondConsoleLogDimmingInStrictMode: false, }); const bridgeListeners = []; diff --git a/packages/react-devtools-shared/src/backend/types.js b/packages/react-devtools-shared/src/backend/types.js index 67d6a5f834b..00c66355b2d 100644 --- a/packages/react-devtools-shared/src/backend/types.js +++ b/packages/react-devtools-shared/src/backend/types.js @@ -597,4 +597,5 @@ export type DevToolsHookSettings = { breakOnConsoleErrors: boolean, showInlineWarningsAndErrors: boolean, hideConsoleLogsInStrictMode: boolean, + disableSecondConsoleLogDimmingInStrictMode: boolean, }; diff --git a/packages/react-devtools-shared/src/devtools/views/Settings/DebuggingSettings.js b/packages/react-devtools-shared/src/devtools/views/Settings/DebuggingSettings.js index 5dfce3a6dc2..34b08c5bfcd 100644 --- a/packages/react-devtools-shared/src/devtools/views/Settings/DebuggingSettings.js +++ b/packages/react-devtools-shared/src/devtools/views/Settings/DebuggingSettings.js @@ -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); @@ -47,6 +51,7 @@ export default function DebuggingSettings({ breakOnConsoleErrors, showInlineWarningsAndErrors, hideConsoleLogsInStrictMode, + disableSecondConsoleLogDimmingInStrictMode, }); }, [ store, @@ -54,6 +59,7 @@ export default function DebuggingSettings({ breakOnConsoleErrors, showInlineWarningsAndErrors, hideConsoleLogsInStrictMode, + disableSecondConsoleLogDimmingInStrictMode, ]); return ( @@ -105,12 +111,49 @@ export default function DebuggingSettings({ { + setHideConsoleLogsInStrictMode(currentTarget.checked); + if (currentTarget.checked) { + setDisableSecondConsoleLogDimmingInStrictMode(false); + } + }} + className={styles.SettingRowCheckbox} + /> + Hide logs during additional invocations in  + + Strict Mode + + +
+ +
+