From a26ec058bcddf16a0632e9fe6de817d27d302ff2 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 2 Aug 2021 13:15:53 -0700 Subject: [PATCH 1/6] Initial strict mode implementation --- .../react-devtools-core/src/standalone.js | 4 + .../react-devtools-extensions/src/main.js | 4 + packages/react-devtools-inline/src/backend.js | 3 + .../react-devtools-inline/src/frontend.js | 2 + .../src/backend/agent.js | 25 ++- .../src/backend/console.js | 151 ++++++++++++------ .../src/backend/renderer.js | 20 ++- .../src/backend/types.js | 2 + packages/react-devtools-shared/src/bridge.js | 1 + .../react-devtools-shared/src/constants.js | 3 + .../views/Settings/DebuggingSettings.js | 15 +- .../views/Settings/SettingsContext.js | 17 ++ .../views/Settings/SettingsShared.css | 3 +- packages/react-devtools-shared/src/hook.js | 21 ++- packages/react-devtools-shared/src/utils.js | 20 +++ .../react-devtools-shell/src/app/console.js | 4 + .../react-devtools-shell/src/app/index.js | 3 +- .../src/ReactFiberBeginWork.new.js | 24 +-- .../src/ReactFiberBeginWork.old.js | 24 +-- .../src/ReactFiberClassComponent.new.js | 14 +- .../src/ReactFiberClassComponent.old.js | 14 +- .../src/ReactFiberHooks.new.js | 7 +- .../src/ReactFiberHooks.old.js | 7 +- .../src/ReactFiberReconciler.js | 11 ++ .../src/ReactFiberReconciler.new.js | 11 ++ .../src/ReactFiberReconciler.old.js | 11 ++ .../src/ReactUpdateQueue.new.js | 11 +- .../src/ReactUpdateQueue.old.js | 11 +- 28 files changed, 297 insertions(+), 146 deletions(-) diff --git a/packages/react-devtools-core/src/standalone.js b/packages/react-devtools-core/src/standalone.js index 2e9e6a1056bf1..35d21b3a8a2ee 100644 --- a/packages/react-devtools-core/src/standalone.js +++ b/packages/react-devtools-core/src/standalone.js @@ -21,6 +21,7 @@ import { getBreakOnConsoleErrors, getSavedComponentFilters, getShowInlineWarningsAndErrors, + getHideConsoleLogsInStrictMode, } from 'react-devtools-shared/src/utils'; import {Server} from 'ws'; import {join} from 'path'; @@ -310,6 +311,9 @@ function startServer( )}; window.__REACT_DEVTOOLS_SHOW_INLINE_WARNINGS_AND_ERRORS__ = ${JSON.stringify( getShowInlineWarningsAndErrors(), + )}; + window.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ = ${JSON.stringify( + getHideConsoleLogsInStrictMode(), )};`; response.end( diff --git a/packages/react-devtools-extensions/src/main.js b/packages/react-devtools-extensions/src/main.js index 7cb92c27b6cb9..2b8d3a0c2b9e3 100644 --- a/packages/react-devtools-extensions/src/main.js +++ b/packages/react-devtools-extensions/src/main.js @@ -11,6 +11,7 @@ import { getBreakOnConsoleErrors, getSavedComponentFilters, getShowInlineWarningsAndErrors, + getHideConsoleLogsInStrictMode, } from 'react-devtools-shared/src/utils'; import { localStorageGetItem, @@ -42,6 +43,9 @@ function syncSavedPreferences() { )}; window.__REACT_DEVTOOLS_SHOW_INLINE_WARNINGS_AND_ERRORS__ = ${JSON.stringify( getShowInlineWarningsAndErrors(), + )}; + window.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ = ${JSON.stringify( + getHideConsoleLogsInStrictMode(), )};`, ); } diff --git a/packages/react-devtools-inline/src/backend.js b/packages/react-devtools-inline/src/backend.js index 7a5bd57b928eb..a6466d82709fc 100644 --- a/packages/react-devtools-inline/src/backend.js +++ b/packages/react-devtools-inline/src/backend.js @@ -25,12 +25,14 @@ function startActivation(contentWindow: window) { breakOnConsoleErrors, componentFilters, showInlineWarningsAndErrors, + hideConsoleLogsInStrictMode, } = data; contentWindow.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__ = appendComponentStack; contentWindow.__REACT_DEVTOOLS_BREAK_ON_CONSOLE_ERRORS__ = breakOnConsoleErrors; contentWindow.__REACT_DEVTOOLS_COMPONENT_FILTERS__ = componentFilters; contentWindow.__REACT_DEVTOOLS_SHOW_INLINE_WARNINGS_AND_ERRORS__ = showInlineWarningsAndErrors; + contentWindow.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ = hideConsoleLogsInStrictMode; // TRICKY // The backend entry point may be required in the context of an iframe or the parent window. @@ -43,6 +45,7 @@ function startActivation(contentWindow: window) { window.__REACT_DEVTOOLS_BREAK_ON_CONSOLE_ERRORS__ = breakOnConsoleErrors; window.__REACT_DEVTOOLS_COMPONENT_FILTERS__ = componentFilters; window.__REACT_DEVTOOLS_SHOW_INLINE_WARNINGS_AND_ERRORS__ = showInlineWarningsAndErrors; + window.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ = hideConsoleLogsInStrictMode; } finishActivation(contentWindow); diff --git a/packages/react-devtools-inline/src/frontend.js b/packages/react-devtools-inline/src/frontend.js index 79bda7ecd8fb8..0249fb878f9bb 100644 --- a/packages/react-devtools-inline/src/frontend.js +++ b/packages/react-devtools-inline/src/frontend.js @@ -10,6 +10,7 @@ import { getBreakOnConsoleErrors, getSavedComponentFilters, getShowInlineWarningsAndErrors, + getHideConsoleLogsInStrictMode, } from 'react-devtools-shared/src/utils'; import { MESSAGE_TYPE_GET_SAVED_PREFERENCES, @@ -88,6 +89,7 @@ export function initialize( breakOnConsoleErrors: getBreakOnConsoleErrors(), componentFilters: getSavedComponentFilters(), showInlineWarningsAndErrors: getShowInlineWarningsAndErrors(), + hideConsoleLogsInStrictMode: getHideConsoleLogsInStrictMode(), }, '*', ); diff --git a/packages/react-devtools-shared/src/backend/agent.js b/packages/react-devtools-shared/src/backend/agent.js index f5a91e0d7c16a..8438a6f8d6c80 100644 --- a/packages/react-devtools-shared/src/backend/agent.js +++ b/packages/react-devtools-shared/src/backend/agent.js @@ -25,7 +25,7 @@ import { initialize as setupTraceUpdates, toggleEnabled as setTraceUpdatesEnabled, } from './views/TraceUpdates'; -import {patch as patchConsole, unpatch as unpatchConsole} from './console'; +import {patch as patchConsole} from './console'; import {currentBridgeProtocol} from 'react-devtools-shared/src/bridge'; import type {BackendBridge} from 'react-devtools-shared/src/bridge'; @@ -635,28 +635,23 @@ export default class Agent extends EventEmitter<{| appendComponentStack, breakOnConsoleErrors, showInlineWarningsAndErrors, + hideConsoleLogsInStrictMode, }: {| appendComponentStack: boolean, breakOnConsoleErrors: boolean, showInlineWarningsAndErrors: boolean, + hideConsoleLogsInStrictMode: boolean, |}) => { // If the frontend preference has change, // or in the case of React Native- if the backend is just finding out the preference- - // then install or uninstall the console overrides. + // then reinstall the console overrides. // It's safe to call these methods multiple times, so we don't need to worry about that. - if ( - appendComponentStack || - breakOnConsoleErrors || - showInlineWarningsAndErrors - ) { - patchConsole({ - appendComponentStack, - breakOnConsoleErrors, - showInlineWarningsAndErrors, - }); - } else { - unpatchConsole(); - } + patchConsole({ + appendComponentStack, + breakOnConsoleErrors, + showInlineWarningsAndErrors, + hideConsoleLogsInStrictMode, + }); }; updateComponentFilters = (componentFilters: Array) => { diff --git a/packages/react-devtools-shared/src/backend/console.js b/packages/react-devtools-shared/src/backend/console.js index fcfb944bce230..88d76dafa3969 100644 --- a/packages/react-devtools-shared/src/backend/console.js +++ b/packages/react-devtools-shared/src/backend/console.js @@ -9,11 +9,16 @@ import type {Fiber} from 'react-reconciler/src/ReactInternalTypes'; import type {CurrentDispatcherRef, ReactRenderer, WorkTagMap} from './types'; +import {format} from './utils'; import {getInternalReactConstants} from './renderer'; import {getStackByFiberInDevAndProd} from './DevToolsFiberComponentStack'; -const APPEND_STACK_TO_METHODS = ['error', 'trace', 'warn']; +const OVERRIDE_CONSOLE_METHODS = ['error', 'trace', 'warn', 'log']; +const DIMMED_NODE_CONSOLE_COLOR = '\x1b[2m%s\x1b[0m'; +const DIMMED_WARNING_COLOR = 'rgba(250, 180, 50, .5)'; +const DIMMED_ERROR_COLOR = 'rgba(250, 123, 130, .5)'; +const DIMMED_LOG_COLOR = 'rgba(125, 125, 125, 0.5)'; // React's custom built component stack strings match "\s{4}in" // Chrome's prefix matches "\s{4}at" @@ -39,6 +44,7 @@ const injectedRenderers: Map< getCurrentFiber: () => Fiber | null, onErrorOrWarning: ?OnErrorOrWarning, workTagMap: WorkTagMap, + getIsStrictMode: ?() => boolean, |}, > = new Map(); @@ -50,6 +56,11 @@ for (const method in console) { let unpatchFn: null | (() => void) = null; +let isNode = false; +try { + isNode = this === global; +} catch (error) {} + // Enables e.g. Jest tests to inject a mock console object. export function dangerous_setTargetConsoleForTesting( targetConsoleForTesting: Object, @@ -72,6 +83,7 @@ export function registerRenderer( const { currentDispatcherRef, getCurrentFiber, + getIsStrictMode, findFiberByHostInstance, version, } = renderer; @@ -89,6 +101,7 @@ export function registerRenderer( injectedRenderers.set(renderer, { currentDispatcherRef, getCurrentFiber, + getIsStrictMode, workTagMap: ReactTypeOfWork, onErrorOrWarning, }); @@ -99,6 +112,7 @@ const consoleSettingsRef = { appendComponentStack: false, breakOnConsoleErrors: false, showInlineWarningsAndErrors: false, + hideConsoleLogsInStrictMode: false, }; // Patches console methods to append component stack for the current fiber. @@ -107,16 +121,19 @@ export function patch({ appendComponentStack, breakOnConsoleErrors, showInlineWarningsAndErrors, + hideConsoleLogsInStrictMode, }: { appendComponentStack: boolean, breakOnConsoleErrors: boolean, showInlineWarningsAndErrors: boolean, + hideConsoleLogsInStrictMode: boolean, }): void { // Settings may change after we've patched the console. // Using a shared ref allows the patch function to read the latest values. consoleSettingsRef.appendComponentStack = appendComponentStack; consoleSettingsRef.breakOnConsoleErrors = breakOnConsoleErrors; consoleSettingsRef.showInlineWarningsAndErrors = showInlineWarningsAndErrors; + consoleSettingsRef.hideConsoleLogsInStrictMode = hideConsoleLogsInStrictMode; if (unpatchFn !== null) { // Don't patch twice. @@ -134,68 +151,78 @@ export function patch({ } }; - APPEND_STACK_TO_METHODS.forEach(method => { + OVERRIDE_CONSOLE_METHODS.forEach(method => { try { - const originalMethod = (originalConsoleMethods[method] = - targetConsole[method]); + const originalMethod = (originalConsoleMethods[method] = targetConsole[ + method + ].__REACT_DEVTOOLS_ORIGINAL_METHOD__ + ? targetConsole[method].__REACT_DEVTOOLS_ORIGINAL_METHOD__ + : targetConsole[method]); const overrideMethod = (...args) => { let shouldAppendWarningStack = false; - if (consoleSettingsRef.appendComponentStack) { - const lastArg = args.length > 0 ? args[args.length - 1] : null; - const alreadyHasComponentStack = - typeof lastArg === 'string' && isStringComponentStack(lastArg); - - // If we are ever called with a string that already has a component stack, - // e.g. a React error/warning, don't append a second stack. - shouldAppendWarningStack = !alreadyHasComponentStack; + if (method !== 'log') { + if (consoleSettingsRef.appendComponentStack) { + const lastArg = args.length > 0 ? args[args.length - 1] : null; + const alreadyHasComponentStack = + typeof lastArg === 'string' && isStringComponentStack(lastArg); + + // If we are ever called with a string that already has a component stack, + // e.g. a React error/warning, don't append a second stack. + shouldAppendWarningStack = !alreadyHasComponentStack; + } } const shouldShowInlineWarningsAndErrors = consoleSettingsRef.showInlineWarningsAndErrors && (method === 'error' || method === 'warn'); - if (shouldAppendWarningStack || shouldShowInlineWarningsAndErrors) { - // Search for the first renderer that has a current Fiber. - // We don't handle the edge case of stacks for more than one (e.g. interleaved renderers?) - // eslint-disable-next-line no-for-of-loops/no-for-of-loops - for (const { - currentDispatcherRef, - getCurrentFiber, - onErrorOrWarning, - workTagMap, - } of injectedRenderers.values()) { - const current: ?Fiber = getCurrentFiber(); - if (current != null) { - try { - if (shouldShowInlineWarningsAndErrors) { - // patch() is called by two places: (1) the hook and (2) the renderer backend. - // The backend is what implements a message queue, so it's the only one that injects onErrorOrWarning. - if (typeof onErrorOrWarning === 'function') { - onErrorOrWarning( - current, - ((method: any): 'error' | 'warn'), - // Copy args before we mutate them (e.g. adding the component stack) - args.slice(), - ); - } - } + let isInStrictMode = false; - if (shouldAppendWarningStack) { - const componentStack = getStackByFiberInDevAndProd( - workTagMap, + // Search for the first renderer that has a current Fiber. + // We don't handle the edge case of stacks for more than one (e.g. interleaved renderers?) + // eslint-disable-next-line no-for-of-loops/no-for-of-loops + for (const { + currentDispatcherRef, + getCurrentFiber, + onErrorOrWarning, + workTagMap, + getIsStrictMode, + } of injectedRenderers.values()) { + const current: ?Fiber = getCurrentFiber(); + if (current != null) { + try { + if (typeof getIsStrictMode === 'function' && getIsStrictMode()) { + isInStrictMode = true; + } + + if (shouldShowInlineWarningsAndErrors) { + // patch() is called by two places: (1) the hook and (2) the renderer backend. + // The backend is what implements a message queue, so it's the only one that injects onErrorOrWarning. + if (typeof onErrorOrWarning === 'function') { + onErrorOrWarning( current, - currentDispatcherRef, + ((method: any): 'error' | 'warn'), + // Copy args before we mutate them (e.g. adding the component stack) + args.slice(), ); - if (componentStack !== '') { - args.push(componentStack); - } } - } catch (error) { - // Don't let a DevTools or React internal error interfere with logging. - } finally { - break; } + + if (shouldAppendWarningStack) { + const componentStack = getStackByFiberInDevAndProd( + workTagMap, + current, + currentDispatcherRef, + ); + if (componentStack !== '') { + args.push(componentStack); + } + } + } catch (error) { + // Don't let a DevTools or React internal error interfere with logging. + } finally { + break; } } } @@ -209,7 +236,33 @@ export function patch({ debugger; } - originalMethod(...args); + if (isInStrictMode) { + if (!consoleSettingsRef.hideConsoleLogsInStrictMode) { + // Dim the text color of the double logs if we're not + // hiding them. + if (isNode) { + originalMethod(DIMMED_NODE_CONSOLE_COLOR, format(...args)); + } else { + let color; + switch (method) { + case 'warn': + color = DIMMED_WARNING_COLOR; + break; + case 'error': + color = DIMMED_ERROR_COLOR; + break; + case 'log': + default: + color = DIMMED_LOG_COLOR; + break; + } + + originalMethod(`%c${format(...args)}`, `color: ${color}`); + } + } + } else { + originalMethod(...args); + } }; overrideMethod.__REACT_DEVTOOLS_ORIGINAL_METHOD__ = originalMethod; diff --git a/packages/react-devtools-shared/src/backend/renderer.js b/packages/react-devtools-shared/src/backend/renderer.js index 62341ce300ec0..49e742ec63392 100644 --- a/packages/react-devtools-shared/src/backend/renderer.js +++ b/packages/react-devtools-shared/src/backend/renderer.js @@ -740,17 +740,15 @@ export function attach( window.__REACT_DEVTOOLS_BREAK_ON_CONSOLE_ERRORS__ === true; const showInlineWarningsAndErrors = window.__REACT_DEVTOOLS_SHOW_INLINE_WARNINGS_AND_ERRORS__ !== false; - if ( - appendComponentStack || - breakOnConsoleErrors || - showInlineWarningsAndErrors - ) { - patchConsole({ - appendComponentStack, - breakOnConsoleErrors, - showInlineWarningsAndErrors, - }); - } + const hideConsoleLogsInStrictMode = + window.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ === true; + + patchConsole({ + appendComponentStack, + breakOnConsoleErrors, + showInlineWarningsAndErrors, + hideConsoleLogsInStrictMode, + }); } const debug = ( diff --git a/packages/react-devtools-shared/src/backend/types.js b/packages/react-devtools-shared/src/backend/types.js index 27bbc8ce253c8..0a7166d040983 100644 --- a/packages/react-devtools-shared/src/backend/types.js +++ b/packages/react-devtools-shared/src/backend/types.js @@ -136,6 +136,8 @@ export type ReactRenderer = { // Only injected by React v16.9+ in DEV mode. // Enables DevTools to append owners-only component stack to error messages. getCurrentFiber?: () => Fiber | null, + + getIsStrictMode?: () => boolean, // 17.0.2+ reconcilerVersion?: string, // Uniquely identifies React DOM v15. diff --git a/packages/react-devtools-shared/src/bridge.js b/packages/react-devtools-shared/src/bridge.js index cfcfa79e1f2d5..d069b188dd0ee 100644 --- a/packages/react-devtools-shared/src/bridge.js +++ b/packages/react-devtools-shared/src/bridge.js @@ -164,6 +164,7 @@ type UpdateConsolePatchSettingsParams = {| appendComponentStack: boolean, breakOnConsoleErrors: boolean, showInlineWarningsAndErrors: boolean, + hideConsoleLogsInStrictMode: boolean, |}; export type BackendEvents = {| diff --git a/packages/react-devtools-shared/src/constants.js b/packages/react-devtools-shared/src/constants.js index 04962c204e287..930ff54102357 100644 --- a/packages/react-devtools-shared/src/constants.js +++ b/packages/react-devtools-shared/src/constants.js @@ -44,6 +44,9 @@ export const LOCAL_STORAGE_SHOW_INLINE_WARNINGS_AND_ERRORS_KEY = export const LOCAL_STORAGE_TRACE_UPDATES_ENABLED_KEY = 'React::DevTools::traceUpdatesEnabled'; +export const LOCAL_STORAGE_HIDE_CONSOLE_LOGS_IN_STRICT_MODE = + 'React::DevTools::hideConsoleLogsInStrictMode'; + export const PROFILER_EXPORT_VERSION = 5; export const CHANGE_LOG_URL = 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 8d5da190be457..46b8b343721ff 100644 --- a/packages/react-devtools-shared/src/devtools/views/Settings/DebuggingSettings.js +++ b/packages/react-devtools-shared/src/devtools/views/Settings/DebuggingSettings.js @@ -17,10 +17,12 @@ export default function DebuggingSettings(_: {||}) { const { appendComponentStack, breakOnConsoleErrors, + hideConsoleLogsInStrictMode, setAppendComponentStack, setBreakOnConsoleErrors, setShowInlineWarningsAndErrors, showInlineWarningsAndErrors, + sethideConsoleLogsInStrictMode, } = useContext(SettingsContext); return ( @@ -64,8 +66,17 @@ export default function DebuggingSettings(_: {||}) { -
- These settings require DevTools to override native console APIs. +
+
); diff --git a/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js b/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js index a433ac220ffe3..7c3348d49069e 100644 --- a/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js +++ b/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js @@ -23,6 +23,7 @@ import { LOCAL_STORAGE_SHOULD_PATCH_CONSOLE_KEY, LOCAL_STORAGE_TRACE_UPDATES_ENABLED_KEY, LOCAL_STORAGE_SHOW_INLINE_WARNINGS_AND_ERRORS_KEY, + LOCAL_STORAGE_HIDE_CONSOLE_LOGS_IN_STRICT_MODE, } from 'react-devtools-shared/src/constants'; import {useLocalStorage} from '../hooks'; import {BridgeContext} from '../context'; @@ -49,6 +50,9 @@ type Context = {| parseHookNames: boolean, setParseHookNames: (value: boolean) => void, + hideConsoleLogsInStrictMode: boolean, + sethideConsoleLogsInStrictMode: (value: boolean) => void, + showInlineWarningsAndErrors: boolean, setShowInlineWarningsAndErrors: (value: boolean) => void, @@ -104,6 +108,13 @@ function SettingsContextController({ LOCAL_STORAGE_PARSE_HOOK_NAMES_KEY, false, ); + const [ + hideConsoleLogsInStrictMode, + sethideConsoleLogsInStrictMode, + ] = useLocalStorage( + LOCAL_STORAGE_HIDE_CONSOLE_LOGS_IN_STRICT_MODE, + false, + ); const [ showInlineWarningsAndErrors, setShowInlineWarningsAndErrors, @@ -169,12 +180,14 @@ function SettingsContextController({ appendComponentStack, breakOnConsoleErrors, showInlineWarningsAndErrors, + hideConsoleLogsInStrictMode, }); }, [ bridge, appendComponentStack, breakOnConsoleErrors, showInlineWarningsAndErrors, + hideConsoleLogsInStrictMode, ]); useEffect(() => { @@ -199,6 +212,8 @@ function SettingsContextController({ setTraceUpdatesEnabled, setShowInlineWarningsAndErrors, showInlineWarningsAndErrors, + sethideConsoleLogsInStrictMode, + hideConsoleLogsInStrictMode, theme, browserTheme, traceUpdatesEnabled, @@ -216,6 +231,8 @@ function SettingsContextController({ setTraceUpdatesEnabled, setShowInlineWarningsAndErrors, showInlineWarningsAndErrors, + sethideConsoleLogsInStrictMode, + hideConsoleLogsInStrictMode, theme, browserTheme, traceUpdatesEnabled, diff --git a/packages/react-devtools-shared/src/devtools/views/Settings/SettingsShared.css b/packages/react-devtools-shared/src/devtools/views/Settings/SettingsShared.css index 58ad5d15d37ad..3ddaf13907702 100644 --- a/packages/react-devtools-shared/src/devtools/views/Settings/SettingsShared.css +++ b/packages/react-devtools-shared/src/devtools/views/Settings/SettingsShared.css @@ -128,8 +128,7 @@ background-color: var(--color-toggle-text); } -.ReleaseNotes, -.ConsoleAPIWarning { +.ReleaseNotes { width: 100%; background-color: var(--color-background-hover); padding: 0.25rem 0.5rem; diff --git a/packages/react-devtools-shared/src/hook.js b/packages/react-devtools-shared/src/hook.js index 4ba54fe31085c..4f308811bda12 100644 --- a/packages/react-devtools-shared/src/hook.js +++ b/packages/react-devtools-shared/src/hook.js @@ -184,6 +184,8 @@ export function installHook(target: any): DevToolsHook | null { window.__REACT_DEVTOOLS_BREAK_ON_CONSOLE_ERRORS__ === true; const showInlineWarningsAndErrors = window.__REACT_DEVTOOLS_SHOW_INLINE_WARNINGS_AND_ERRORS__ !== false; + const hideConsoleLogsInStrictMode = + window.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ === true; // The installHook() function is injected by being stringified in the browser, // so imports outside of this function do not get included. @@ -192,18 +194,13 @@ export function installHook(target: any): DevToolsHook | null { // but Webpack wraps imports with an object (e.g. _backend_console__WEBPACK_IMPORTED_MODULE_0__) // and the object itself will be undefined as well for the reasons mentioned above, // so we use try/catch instead. - if ( - appendComponentStack || - breakOnConsoleErrors || - showInlineWarningsAndErrors - ) { - registerRendererWithConsole(renderer); - patchConsole({ - appendComponentStack, - breakOnConsoleErrors, - showInlineWarningsAndErrors, - }); - } + registerRendererWithConsole(renderer); + patchConsole({ + appendComponentStack, + breakOnConsoleErrors, + showInlineWarningsAndErrors, + hideConsoleLogsInStrictMode, + }); } catch (error) {} } diff --git a/packages/react-devtools-shared/src/utils.js b/packages/react-devtools-shared/src/utils.js index 573679f635ab8..901aecbac6d06 100644 --- a/packages/react-devtools-shared/src/utils.js +++ b/packages/react-devtools-shared/src/utils.js @@ -37,6 +37,7 @@ import { LOCAL_STORAGE_SHOULD_BREAK_ON_CONSOLE_ERRORS, LOCAL_STORAGE_SHOULD_PATCH_CONSOLE_KEY, LOCAL_STORAGE_SHOW_INLINE_WARNINGS_AND_ERRORS_KEY, + LOCAL_STORAGE_HIDE_CONSOLE_LOGS_IN_STRICT_MODE, } from './constants'; import {ComponentFilterElementType, ElementTypeHostComponent} from './types'; import { @@ -317,6 +318,25 @@ export function setBreakOnConsoleErrors(value: boolean): void { ); } +export function getHideConsoleLogsInStrictMode(): boolean { + try { + const raw = localStorageGetItem( + LOCAL_STORAGE_HIDE_CONSOLE_LOGS_IN_STRICT_MODE, + ); + if (raw != null) { + return JSON.parse(raw); + } + } catch (error) {} + return false; +} + +export function sethideConsoleLogsInStrictMode(value: boolean): void { + localStorageSetItem( + LOCAL_STORAGE_HIDE_CONSOLE_LOGS_IN_STRICT_MODE, + JSON.stringify(value), + ); +} + export function getShowInlineWarningsAndErrors(): boolean { try { const raw = localStorageGetItem( diff --git a/packages/react-devtools-shell/src/app/console.js b/packages/react-devtools-shell/src/app/console.js index 39ee34ee5a509..9f1244bf164e1 100644 --- a/packages/react-devtools-shell/src/app/console.js +++ b/packages/react-devtools-shell/src/app/console.js @@ -37,3 +37,7 @@ export function ignoreErrors(errorsToIgnore: Array): void { export function ignoreWarnings(warningsToIgnore: Array): void { ignoreStrings('warn', warningsToIgnore); } + +export function ignoreLogs(logsToIgnore: Array): void { + ignoreStrings('log', logsToIgnore); +} diff --git a/packages/react-devtools-shell/src/app/index.js b/packages/react-devtools-shell/src/app/index.js index d00ffde4a5ded..805cd0a2a707e 100644 --- a/packages/react-devtools-shell/src/app/index.js +++ b/packages/react-devtools-shell/src/app/index.js @@ -19,7 +19,7 @@ import ToDoList from './ToDoList'; import Toggle from './Toggle'; import ErrorBoundaries from './ErrorBoundaries'; import SuspenseTree from './SuspenseTree'; -import {ignoreErrors, ignoreWarnings} from './console'; +import {ignoreErrors, ignoreLogs, ignoreWarnings} from './console'; import './styles.css'; @@ -32,6 +32,7 @@ ignoreErrors([ 'Warning: %s is deprecated in StrictMode.', // findDOMNode ]); ignoreWarnings(['Warning: componentWillReceiveProps has been renamed']); +ignoreLogs([]); const roots = []; diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js index cadf7d252d830..d9874bba34119 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js @@ -151,7 +151,11 @@ import { getOffscreenContainerProps, } from './ReactFiberHostConfig'; import type {SuspenseInstance} from './ReactFiberHostConfig'; -import {shouldError, shouldSuspend} from './ReactFiberReconciler'; +import { + shouldError, + shouldSuspend, + setIsStrictModeForDevtools, +} from './ReactFiberReconciler'; import {pushHostContext, pushHostContainer} from './ReactFiberHostContext.new'; import { suspenseStackCursor, @@ -235,8 +239,6 @@ import {createClassErrorUpdate} from './ReactFiberThrow.new'; import {completeSuspendedOffscreenHostContainer} from './ReactFiberCompleteWork.new'; import is from 'shared/objectIs'; -import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev'; - const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; let didReceiveUpdate: boolean = false; @@ -379,7 +381,7 @@ function updateForwardRef( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { nextChildren = renderWithHooks( current, @@ -390,7 +392,7 @@ function updateForwardRef( renderLanes, ); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } setIsRendering(false); @@ -984,7 +986,7 @@ function updateFunctionComponent( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { nextChildren = renderWithHooks( current, @@ -995,7 +997,7 @@ function updateFunctionComponent( renderLanes, ); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } setIsRendering(false); @@ -1201,11 +1203,11 @@ function finishClassComponent( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { instance.render(); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } setIsRendering(false); @@ -1741,7 +1743,7 @@ function mountIndeterminateComponent( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { value = renderWithHooks( null, @@ -1752,7 +1754,7 @@ function mountIndeterminateComponent( renderLanes, ); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } } diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js index 962f592a32556..74037fbe966f2 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js @@ -151,7 +151,11 @@ import { getOffscreenContainerProps, } from './ReactFiberHostConfig'; import type {SuspenseInstance} from './ReactFiberHostConfig'; -import {shouldError, shouldSuspend} from './ReactFiberReconciler'; +import { + shouldError, + shouldSuspend, + setIsStrictModeForDevtools, +} from './ReactFiberReconciler'; import {pushHostContext, pushHostContainer} from './ReactFiberHostContext.old'; import { suspenseStackCursor, @@ -235,8 +239,6 @@ import {createClassErrorUpdate} from './ReactFiberThrow.old'; import {completeSuspendedOffscreenHostContainer} from './ReactFiberCompleteWork.old'; import is from 'shared/objectIs'; -import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev'; - const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; let didReceiveUpdate: boolean = false; @@ -379,7 +381,7 @@ function updateForwardRef( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { nextChildren = renderWithHooks( current, @@ -390,7 +392,7 @@ function updateForwardRef( renderLanes, ); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } setIsRendering(false); @@ -984,7 +986,7 @@ function updateFunctionComponent( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { nextChildren = renderWithHooks( current, @@ -995,7 +997,7 @@ function updateFunctionComponent( renderLanes, ); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } setIsRendering(false); @@ -1201,11 +1203,11 @@ function finishClassComponent( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { instance.render(); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } setIsRendering(false); @@ -1741,7 +1743,7 @@ function mountIndeterminateComponent( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { value = renderWithHooks( null, @@ -1752,7 +1754,7 @@ function mountIndeterminateComponent( renderLanes, ); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } } diff --git a/packages/react-reconciler/src/ReactFiberClassComponent.new.js b/packages/react-reconciler/src/ReactFiberClassComponent.new.js index 3d10472c0441c..490fa5f430f21 100644 --- a/packages/react-reconciler/src/ReactFiberClassComponent.new.js +++ b/packages/react-reconciler/src/ReactFiberClassComponent.new.js @@ -38,6 +38,7 @@ import getComponentNameFromType from 'shared/getComponentNameFromType'; import invariant from 'shared/invariant'; import isArray from 'shared/isArray'; import {REACT_CONTEXT_TYPE, REACT_PROVIDER_TYPE} from 'shared/ReactSymbols'; +import {setIsStrictModeForDevtools} from './ReactFiberReconciler'; import {resolveDefaultProps} from './ReactFiberLazyComponent.new'; import { @@ -75,7 +76,6 @@ import { } from './ReactFiberWorkLoop.new'; import {logForceUpdateScheduled, logStateUpdateScheduled} from './DebugTracing'; -import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev'; import { markForceUpdateScheduled, markStateUpdateScheduled, @@ -175,12 +175,12 @@ function applyDerivedStateFromProps( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { // Invoke the function an extra time to help detect side-effects. partialState = getDerivedStateFromProps(nextProps, prevState); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } warnOnUndefinedDerivedState(ctor, partialState); @@ -328,7 +328,7 @@ function checkShouldComponentUpdate( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { // Invoke the function an extra time to help detect side-effects. shouldUpdate = instance.shouldComponentUpdate( @@ -337,7 +337,7 @@ function checkShouldComponentUpdate( nextContext, ); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } if (shouldUpdate === undefined) { @@ -662,11 +662,11 @@ function constructClassInstance( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { instance = new ctor(props, context); // eslint-disable-line no-new } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } } diff --git a/packages/react-reconciler/src/ReactFiberClassComponent.old.js b/packages/react-reconciler/src/ReactFiberClassComponent.old.js index ab80913c7b6b6..8c08eb581892b 100644 --- a/packages/react-reconciler/src/ReactFiberClassComponent.old.js +++ b/packages/react-reconciler/src/ReactFiberClassComponent.old.js @@ -38,6 +38,7 @@ import getComponentNameFromType from 'shared/getComponentNameFromType'; import invariant from 'shared/invariant'; import isArray from 'shared/isArray'; import {REACT_CONTEXT_TYPE, REACT_PROVIDER_TYPE} from 'shared/ReactSymbols'; +import {setIsStrictModeForDevtools} from './ReactFiberReconciler'; import {resolveDefaultProps} from './ReactFiberLazyComponent.old'; import { @@ -75,7 +76,6 @@ import { } from './ReactFiberWorkLoop.old'; import {logForceUpdateScheduled, logStateUpdateScheduled} from './DebugTracing'; -import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev'; import { markForceUpdateScheduled, markStateUpdateScheduled, @@ -175,12 +175,12 @@ function applyDerivedStateFromProps( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { // Invoke the function an extra time to help detect side-effects. partialState = getDerivedStateFromProps(nextProps, prevState); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } warnOnUndefinedDerivedState(ctor, partialState); @@ -328,7 +328,7 @@ function checkShouldComponentUpdate( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { // Invoke the function an extra time to help detect side-effects. shouldUpdate = instance.shouldComponentUpdate( @@ -337,7 +337,7 @@ function checkShouldComponentUpdate( nextContext, ); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } if (shouldUpdate === undefined) { @@ -662,11 +662,11 @@ function constructClassInstance( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { instance = new ctor(props, context); // eslint-disable-line no-new } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } } diff --git a/packages/react-reconciler/src/ReactFiberHooks.new.js b/packages/react-reconciler/src/ReactFiberHooks.new.js index 7e86ac98bfaa0..b19530e24b5d1 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.new.js +++ b/packages/react-reconciler/src/ReactFiberHooks.new.js @@ -113,6 +113,7 @@ import { entangleTransitions, } from './ReactUpdateQueue.new'; import {pushInterleavedQueue} from './ReactFiberInterleavedUpdates.new'; +import {getIsStrictModeForDevtools} from './ReactFiberReconciler.new'; const {ReactCurrentDispatcher, ReactCurrentBatchConfig} = ReactSharedInternals; @@ -1021,9 +1022,9 @@ function readFromUnsubscribedMutableSource( // dev, we can present a more accurate error message. if (__DEV__) { // eslint-disable-next-line react-internal/no-production-logging - if (console.log.__reactDisabledLog) { - // If the logs are disabled, this is the dev-only double render. This is - // only reachable if there was a mutation during render. Show a helpful + if (getIsStrictModeForDevtools()) { + // If getIsStrictModeForDevtools is true, this is the dev-only double render + // This is only reachable if there was a mutation during render. Show a helpful // error message. // // Something interesting to note: because we only double render in diff --git a/packages/react-reconciler/src/ReactFiberHooks.old.js b/packages/react-reconciler/src/ReactFiberHooks.old.js index cc5fa6149a007..fb1e9b86883a9 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.old.js +++ b/packages/react-reconciler/src/ReactFiberHooks.old.js @@ -113,6 +113,7 @@ import { entangleTransitions, } from './ReactUpdateQueue.old'; import {pushInterleavedQueue} from './ReactFiberInterleavedUpdates.old'; +import {getIsStrictModeForDevtools} from './ReactFiberReconciler.old'; const {ReactCurrentDispatcher, ReactCurrentBatchConfig} = ReactSharedInternals; @@ -1021,9 +1022,9 @@ function readFromUnsubscribedMutableSource( // dev, we can present a more accurate error message. if (__DEV__) { // eslint-disable-next-line react-internal/no-production-logging - if (console.log.__reactDisabledLog) { - // If the logs are disabled, this is the dev-only double render. This is - // only reachable if there was a mutation during render. Show a helpful + if (getIsStrictModeForDevtools()) { + // If getIsStrictModeForDevtools is true, this is the dev-only double render + // This is only reachable if there was a mutation during render. Show a helpful // error message. // // Something interesting to note: because we only double render in diff --git a/packages/react-reconciler/src/ReactFiberReconciler.js b/packages/react-reconciler/src/ReactFiberReconciler.js index d25783164e984..033b9eb0adbec 100644 --- a/packages/react-reconciler/src/ReactFiberReconciler.js +++ b/packages/react-reconciler/src/ReactFiberReconciler.js @@ -49,6 +49,8 @@ import { registerMutableSourceForHydration as registerMutableSourceForHydration_old, runWithPriority as runWithPriority_old, getCurrentUpdatePriority as getCurrentUpdatePriority_old, + getIsStrictModeForDevtools as getIsStrictModeForDevtools_old, + setIsStrictModeForDevtools as setIsStrictModeForDevtools_old, } from './ReactFiberReconciler.old'; import { @@ -86,6 +88,8 @@ import { registerMutableSourceForHydration as registerMutableSourceForHydration_new, runWithPriority as runWithPriority_new, getCurrentUpdatePriority as getCurrentUpdatePriority_new, + getIsStrictModeForDevtools as getIsStrictModeForDevtools_new, + setIsStrictModeForDevtools as setIsStrictModeForDevtools_new, } from './ReactFiberReconciler.new'; export const createContainer = enableNewReconciler @@ -190,3 +194,10 @@ export const registerMutableSourceForHydration = enableNewReconciler export const runWithPriority = enableNewReconciler ? runWithPriority_new : runWithPriority_old; + +export const getIsStrictModeForDevtools = enableNewReconciler + ? getIsStrictModeForDevtools_new + : getIsStrictModeForDevtools_old; +export const setIsStrictModeForDevtools = enableNewReconciler + ? setIsStrictModeForDevtools_new + : setIsStrictModeForDevtools_old; diff --git a/packages/react-reconciler/src/ReactFiberReconciler.new.js b/packages/react-reconciler/src/ReactFiberReconciler.new.js index 90503a183d943..3ad0f3aefae27 100644 --- a/packages/react-reconciler/src/ReactFiberReconciler.new.js +++ b/packages/react-reconciler/src/ReactFiberReconciler.new.js @@ -458,6 +458,8 @@ export function shouldSuspend(fiber: Fiber): boolean { return shouldSuspendImpl(fiber); } +let isStrictMode = false; + let overrideHookState = null; let overrideHookStateDeletePath = null; let overrideHookStateRenamePath = null; @@ -707,6 +709,14 @@ function getCurrentFiberForDevTools() { return ReactCurrentFiberCurrent; } +export function getIsStrictModeForDevtools() { + return isStrictMode; +} + +export function setIsStrictModeForDevtools(newIsStrictMode: boolean) { + isStrictMode = newIsStrictMode; +} + export function injectIntoDevTools(devToolsConfig: DevToolsConfig): boolean { const {findFiberByHostInstance} = devToolsConfig; const {ReactCurrentDispatcher} = ReactSharedInternals; @@ -736,6 +746,7 @@ export function injectIntoDevTools(devToolsConfig: DevToolsConfig): boolean { setRefreshHandler: __DEV__ ? setRefreshHandler : null, // Enables DevTools to append owner stacks to error messages in DEV mode. getCurrentFiber: __DEV__ ? getCurrentFiberForDevTools : null, + getIsStrictMode: __DEV__ ? getIsStrictModeForDevtools : null, // Enables DevTools to detect reconciler version rather than renderer version // which may not match for third party renderers. reconcilerVersion: ReactVersion, diff --git a/packages/react-reconciler/src/ReactFiberReconciler.old.js b/packages/react-reconciler/src/ReactFiberReconciler.old.js index 2608bc260264f..3d5c324139f57 100644 --- a/packages/react-reconciler/src/ReactFiberReconciler.old.js +++ b/packages/react-reconciler/src/ReactFiberReconciler.old.js @@ -458,6 +458,8 @@ export function shouldSuspend(fiber: Fiber): boolean { return shouldSuspendImpl(fiber); } +let isStrictMode = false; + let overrideHookState = null; let overrideHookStateDeletePath = null; let overrideHookStateRenamePath = null; @@ -707,6 +709,14 @@ function getCurrentFiberForDevTools() { return ReactCurrentFiberCurrent; } +export function getIsStrictModeForDevtools() { + return isStrictMode; +} + +export function setIsStrictModeForDevtools(newIsStrictMode: boolean) { + isStrictMode = newIsStrictMode; +} + export function injectIntoDevTools(devToolsConfig: DevToolsConfig): boolean { const {findFiberByHostInstance} = devToolsConfig; const {ReactCurrentDispatcher} = ReactSharedInternals; @@ -736,6 +746,7 @@ export function injectIntoDevTools(devToolsConfig: DevToolsConfig): boolean { setRefreshHandler: __DEV__ ? setRefreshHandler : null, // Enables DevTools to append owner stacks to error messages in DEV mode. getCurrentFiber: __DEV__ ? getCurrentFiberForDevTools : null, + getIsStrictMode: __DEV__ ? getIsStrictModeForDevtools : null, // Enables DevTools to detect reconciler version rather than renderer version // which may not match for third party renderers. reconcilerVersion: ReactVersion, diff --git a/packages/react-reconciler/src/ReactUpdateQueue.new.js b/packages/react-reconciler/src/ReactUpdateQueue.new.js index 0b694d8f68edd..a42384322fcdb 100644 --- a/packages/react-reconciler/src/ReactUpdateQueue.new.js +++ b/packages/react-reconciler/src/ReactUpdateQueue.new.js @@ -110,11 +110,10 @@ import { isInterleavedUpdate, } from './ReactFiberWorkLoop.new'; import {pushInterleavedQueue} from './ReactFiberInterleavedUpdates.new'; +import {setIsStrictModeForDevtools} from './ReactFiberReconciler'; import invariant from 'shared/invariant'; -import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev'; - export type Update = {| // TODO: Temporary field. Will remove this by storing a map of // transition -> event time on the root. @@ -394,11 +393,11 @@ function getStateFromUpdate( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { payload.call(instance, prevState, nextProps); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } exitDisallowedContextReadInDEV(); @@ -427,11 +426,11 @@ function getStateFromUpdate( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { payload.call(instance, prevState, nextProps); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } exitDisallowedContextReadInDEV(); diff --git a/packages/react-reconciler/src/ReactUpdateQueue.old.js b/packages/react-reconciler/src/ReactUpdateQueue.old.js index 9456a0a7c9703..724dfa0d7171b 100644 --- a/packages/react-reconciler/src/ReactUpdateQueue.old.js +++ b/packages/react-reconciler/src/ReactUpdateQueue.old.js @@ -110,11 +110,10 @@ import { isInterleavedUpdate, } from './ReactFiberWorkLoop.old'; import {pushInterleavedQueue} from './ReactFiberInterleavedUpdates.old'; +import {setIsStrictModeForDevtools} from './ReactFiberReconciler'; import invariant from 'shared/invariant'; -import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev'; - export type Update = {| // TODO: Temporary field. Will remove this by storing a map of // transition -> event time on the root. @@ -394,11 +393,11 @@ function getStateFromUpdate( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { payload.call(instance, prevState, nextProps); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } exitDisallowedContextReadInDEV(); @@ -427,11 +426,11 @@ function getStateFromUpdate( debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictLegacyMode ) { - disableLogs(); + setIsStrictModeForDevtools(true); try { payload.call(instance, prevState, nextProps); } finally { - reenableLogs(); + setIsStrictModeForDevtools(false); } } exitDisallowedContextReadInDEV(); From 0f9208b2566b9f6637b9efc1e8838bb8ea894dc1 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 2 Aug 2021 10:31:17 -0700 Subject: [PATCH 2/6] Initialize backend/frontend early in devtools shell so settings are synced during initial render --- packages/react-devtools-inline/README.md | 9 +++++---- packages/react-devtools-shell/src/devtools.js | 14 ++++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/react-devtools-inline/README.md b/packages/react-devtools-inline/README.md index 22cff37fb7500..88b2c93b7cb05 100644 --- a/packages/react-devtools-inline/README.md +++ b/packages/react-devtools-inline/README.md @@ -83,14 +83,15 @@ const { contentWindow } = iframe; // This must be called before React is loaded into that frame. initializeBackend(contentWindow); -// React application can be injected into