From 50be9376e442acc675e6fa72ca01b8d34442e86d Mon Sep 17 00:00:00 2001 From: sebmarkbage Date: Sun, 26 May 2024 22:00:37 +0000 Subject: [PATCH] [Fiber] Enable Native console.createTask Stacks When Available (#29223) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stacked on #29206 and #29221. This disables appending owner stacks to console when `console.createTask` is available in the environment. Instead we rely on native "async" stacks that end up looking like this with source maps and ignore list enabled. Screenshot 2024-05-22 at 4 00 27 PM Unfortunately Chrome requires a string name for each async stack and, worse, a suffix of `(async)` is automatically added which is very confusing since it seems like it might be an async component or something which it is not. In this case it's not so bad because it's nice to refer to the host component which otherwise doesn't have a stack frame since it's internal. However, if there were more owners here there would also be a ` (async)` which ends up being kind of duplicative. If the Chrome DevTools is not open from the start of the app, then `console.createTask` is disabled and so you lose the stack for those errors (or those parents if the devtools is opened later). Unlike our appended ones that are always added. That's unfortunate and likely to be a bit of a DX issue but it's also nice that it saves on perf in DEV mode for those cases. Framework dialogs can still surface the stack since we also track it in user space in parallel. This currently doesn't track Server Components yet. We need a more clever hack for that part in a follow up. I think I probably need to also add something to React DevTools to disable its stacks for this case too. Since it looks for stacks in the console.error and adds a stack otherwise. Since we don't add them anymore from the runtime, the DevTools adds them instead. DiffTrain build for commit https://github.com/facebook/react/commit/ea6e05912aa43a0bbfbee381752caa1817a41a86. --- .../cjs/ReactTestRenderer-dev.js | 38 +++++++----- .../react/react/cjs/JSXDEVRuntime-dev.js | 7 ++- .../vendor/react/react/cjs/JSXRuntime-dev.js | 7 ++- .../vendor/react/react/cjs/React-dev.js | 9 ++- .../Libraries/Renderer/REVISION | 2 +- .../implementations/ReactFabric-dev.fb.js | 58 ++++++++++--------- .../ReactNativeRenderer-dev.fb.js | 56 ++++++++++-------- 7 files changed, 102 insertions(+), 75 deletions(-) diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-test-renderer/cjs/ReactTestRenderer-dev.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-test-renderer/cjs/ReactTestRenderer-dev.js index af48dd7cbb66f..cbfc4fbf06ef4 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-test-renderer/cjs/ReactTestRenderer-dev.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-test-renderer/cjs/ReactTestRenderer-dev.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<1b15d797a9023201acc95022ba001e0f>> + * @generated SignedSource<<5d2de112982cec5eac69c9d1f8e71fe5>> */ 'use strict'; @@ -22,6 +22,20 @@ var Scheduler$1 = require('scheduler'); var ReactSharedInternals = React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE; +var debugRenderPhaseSideEffectsForStrictMode = false; +var enableSchedulingProfiler = true; +var enableProfilerTimer = true; +var enableProfilerCommitHooks = true; +var enableProfilerNestedUpdatePhase = true; +var enableAsyncIterableChildren = false; +var syncLaneExpirationMs = 250; +var transitionLaneExpirationMs = 5000; +var enableLazyContextPropagation = false; +var enableLegacyHidden = false; +var enableAsyncActions = true; +var disableLegacyMode = false; +var enableOwnerStacks = false; // Flow magic to verify the exports of this file match the original version. + // by calls to these methods by a Babel plugin. // // In PROD (or in packages without access to React internals), @@ -48,7 +62,7 @@ function error(format) { printWarning('error', format, args); } } -} +} // eslint-disable-next-line react-internal/no-production-logging function printWarning(level, format, args) { // When changing this logic, you might want to also @@ -57,6 +71,9 @@ function printWarning(level, format, args) { var isErrorLogger = format === '%s\n\n%s\n' || format === '%o\n\n%s\n\n%s\n'; if (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. var stack = ReactSharedInternals.getCurrentStack(); if (stack !== '') { @@ -139,19 +156,6 @@ function set(key, value) { key._reactInternals = value; } -var debugRenderPhaseSideEffectsForStrictMode = false; -var enableSchedulingProfiler = true; -var enableProfilerTimer = true; -var enableProfilerCommitHooks = true; -var enableProfilerNestedUpdatePhase = true; -var enableAsyncIterableChildren = false; -var syncLaneExpirationMs = 250; -var transitionLaneExpirationMs = 5000; -var enableLazyContextPropagation = false; -var enableLegacyHidden = false; -var enableAsyncActions = true; -var disableLegacyMode = false; - var FunctionComponent = 0; var ClassComponent = 1; var HostRoot = 3; // Root of a host tree. Could be nested inside another node. @@ -1058,6 +1062,8 @@ function runWithFiberInDEV(fiber, callback, arg0, arg1, arg2, arg3, arg4) { setCurrentFiber(fiber); try { + if (enableOwnerStacks) ; + return callback(arg0, arg1, arg2, arg3, arg4); } finally { current = previousFiber; @@ -23456,7 +23462,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition return root; } -var ReactVersion = '19.0.0-rc-aa7289e4'; +var ReactVersion = '19.0.0-rc-44b67cc6'; /* * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react/cjs/JSXDEVRuntime-dev.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react/cjs/JSXDEVRuntime-dev.js index a7275fa027a13..86e8dc5cd18ab 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react/cjs/JSXDEVRuntime-dev.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react/cjs/JSXDEVRuntime-dev.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<498b38ab8fbbf44800642c8dc0009e44>> + * @generated SignedSource<> */ 'use strict'; @@ -82,7 +82,7 @@ function error(format) { printWarning('error', format, args); } } -} +} // eslint-disable-next-line react-internal/no-production-logging function printWarning(level, format, args) { // When changing this logic, you might want to also @@ -91,6 +91,9 @@ function printWarning(level, format, args) { var isErrorLogger = format === '%s\n\n%s\n' || format === '%o\n\n%s\n\n%s\n'; if (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. var stack = ReactSharedInternals.getCurrentStack(); if (stack !== '') { diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react/cjs/JSXRuntime-dev.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react/cjs/JSXRuntime-dev.js index 0c53a715c50b4..ccc9133a3794b 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react/cjs/JSXRuntime-dev.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react/cjs/JSXRuntime-dev.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<0a367e8c426be018f37ef2a753bebe30>> + * @generated SignedSource<<92915fe99444450e2d1431f2c1ba40f2>> */ 'use strict'; @@ -82,7 +82,7 @@ function error(format) { printWarning('error', format, args); } } -} +} // eslint-disable-next-line react-internal/no-production-logging function printWarning(level, format, args) { // When changing this logic, you might want to also @@ -91,6 +91,9 @@ function printWarning(level, format, args) { var isErrorLogger = format === '%s\n\n%s\n' || format === '%o\n\n%s\n\n%s\n'; if (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. var stack = ReactSharedInternals.getCurrentStack(); if (stack !== '') { diff --git a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react/cjs/React-dev.js b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react/cjs/React-dev.js index febccfea496a5..5c34f1407bd70 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react/cjs/React-dev.js +++ b/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react/cjs/React-dev.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<43472d2aa5457c3ff87b82ad5ff89a40>> + * @generated SignedSource<> */ 'use strict'; @@ -24,7 +24,7 @@ if ( } var dynamicFlagsUntyped = require('ReactNativeInternalFeatureFlags'); -var ReactVersion = '19.0.0-rc-28be327b'; +var ReactVersion = '19.0.0-rc-86d4e19f'; // Re-export dynamic flags from the internal module. var dynamicFlags = dynamicFlagsUntyped; // We destructure each value before re-exporting to avoid a dynamic look-up on @@ -125,7 +125,7 @@ function error(format) { printWarning('error', format, args); } } -} +} // eslint-disable-next-line react-internal/no-production-logging function printWarning(level, format, args) { // When changing this logic, you might want to also @@ -134,6 +134,9 @@ function printWarning(level, format, args) { var isErrorLogger = format === '%s\n\n%s\n' || format === '%o\n\n%s\n\n%s\n'; if (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. var stack = ReactSharedInternals.getCurrentStack(); if (stack !== '') { diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION index 62bef87d144b9..7ebb26ed718bf 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION @@ -1 +1 @@ -b078c810c787cf13d9bd1958f083b4e3a162a720 +ea6e05912aa43a0bbfbee381752caa1817a41a86 diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.fb.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.fb.js index 6f87cb96950ae..ebd33c47a0389 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.fb.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<66f3250cfa263c3a4528924d68e4197c>> + * @generated SignedSource<> */ 'use strict'; @@ -30,6 +30,30 @@ var Scheduler = require('scheduler'); var ReactSharedInternals = React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE; +// Re-export dynamic flags from the internal module. +var dynamicFlags = dynamicFlagsUntyped; // We destructure each value before re-exporting to avoid a dynamic look-up on +// the exports object every time a flag is read. + +var alwaysThrottleRetries = dynamicFlags.alwaysThrottleRetries, + consoleManagedByDevToolsDuringStrictMode = dynamicFlags.consoleManagedByDevToolsDuringStrictMode, + disableDefaultPropsExceptForClasses = dynamicFlags.disableDefaultPropsExceptForClasses, + enableAddPropertiesFastPath = dynamicFlags.enableAddPropertiesFastPath, + enableDeferRootSchedulingToMicrotask = dynamicFlags.enableDeferRootSchedulingToMicrotask, + enableInfiniteRenderLoopDetection = dynamicFlags.enableInfiniteRenderLoopDetection, + passChildrenWhenCloningPersistedNodes = dynamicFlags.passChildrenWhenCloningPersistedNodes; // The rest of the flags are static for better dead code elimination. +var enableAsyncActions = true; +var enableSchedulingProfiler = true; +var enableProfilerTimer = true; +var enableProfilerCommitHooks = true; +var enableProfilerNestedUpdatePhase = true; +var enableAsyncIterableChildren = false; +var syncLaneExpirationMs = 250; +var transitionLaneExpirationMs = 5000; +var enableLazyContextPropagation = false; +var enableLegacyHidden = false; +var disableLegacyMode = false; +var enableOwnerStacks = false; // Flow magic to verify the exports of this file match the original version. + var suppressWarning = false; function setSuppressWarning(newSuppressWarning) { { @@ -62,7 +86,7 @@ function error(format) { printWarning('error', format, args); } } -} +} // eslint-disable-next-line react-internal/no-production-logging function printWarning(level, format, args) { // When changing this logic, you might want to also @@ -71,6 +95,9 @@ function printWarning(level, format, args) { var isErrorLogger = format === '%s\n\n%s\n' || format === '%o\n\n%s\n\n%s\n'; if (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. var stack = ReactSharedInternals.getCurrentStack(); if (stack !== '') { @@ -1998,29 +2025,6 @@ injectEventPluginsByName({ ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin }); -// Re-export dynamic flags from the internal module. -var dynamicFlags = dynamicFlagsUntyped; // We destructure each value before re-exporting to avoid a dynamic look-up on -// the exports object every time a flag is read. - -var alwaysThrottleRetries = dynamicFlags.alwaysThrottleRetries, - consoleManagedByDevToolsDuringStrictMode = dynamicFlags.consoleManagedByDevToolsDuringStrictMode, - disableDefaultPropsExceptForClasses = dynamicFlags.disableDefaultPropsExceptForClasses, - enableAddPropertiesFastPath = dynamicFlags.enableAddPropertiesFastPath, - enableDeferRootSchedulingToMicrotask = dynamicFlags.enableDeferRootSchedulingToMicrotask, - enableInfiniteRenderLoopDetection = dynamicFlags.enableInfiniteRenderLoopDetection, - passChildrenWhenCloningPersistedNodes = dynamicFlags.passChildrenWhenCloningPersistedNodes; // The rest of the flags are static for better dead code elimination. -var enableAsyncActions = true; -var enableSchedulingProfiler = true; -var enableProfilerTimer = true; -var enableProfilerCommitHooks = true; -var enableProfilerNestedUpdatePhase = true; -var enableAsyncIterableChildren = false; -var syncLaneExpirationMs = 250; -var transitionLaneExpirationMs = 5000; -var enableLazyContextPropagation = false; -var enableLegacyHidden = false; -var disableLegacyMode = false; - // Modules provided by RN: var emptyObject$1 = {}; /** @@ -5185,6 +5189,8 @@ function runWithFiberInDEV(fiber, callback, arg0, arg1, arg2, arg3, arg4) { setCurrentFiber(fiber); try { + if (enableOwnerStacks) ; + return callback(arg0, arg1, arg2, arg3, arg4); } finally { current = previousFiber; @@ -26197,7 +26203,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition return root; } -var ReactVersion = '19.0.0-rc-c70662b2'; +var ReactVersion = '19.0.0-rc-571af8c1'; /* * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol diff --git a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js index 8374a672ab71f..89565fff5ee46 100644 --- a/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js +++ b/compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<3d4cf8990ac0b10f2ad4552e0a0fc75f>> + * @generated SignedSource<<3dbcb35ed104bc31d027dfdf6f5f8da0>> */ 'use strict'; @@ -30,6 +30,29 @@ var Scheduler = require('scheduler'); var ReactSharedInternals = React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE; +// Re-export dynamic flags from the internal module. +var dynamicFlags = dynamicFlagsUntyped; // We destructure each value before re-exporting to avoid a dynamic look-up on +// the exports object every time a flag is read. + +var alwaysThrottleRetries = dynamicFlags.alwaysThrottleRetries, + consoleManagedByDevToolsDuringStrictMode = dynamicFlags.consoleManagedByDevToolsDuringStrictMode, + disableDefaultPropsExceptForClasses = dynamicFlags.disableDefaultPropsExceptForClasses, + enableDeferRootSchedulingToMicrotask = dynamicFlags.enableDeferRootSchedulingToMicrotask, + enableInfiniteRenderLoopDetection = dynamicFlags.enableInfiniteRenderLoopDetection; + // The rest of the flags are static for better dead code elimination. +var enableAsyncActions = true; +var enableSchedulingProfiler = true; +var enableProfilerTimer = true; +var enableProfilerCommitHooks = true; +var enableProfilerNestedUpdatePhase = true; +var enableAsyncIterableChildren = false; +var syncLaneExpirationMs = 250; +var transitionLaneExpirationMs = 5000; +var enableLazyContextPropagation = false; +var enableLegacyHidden = false; +var disableLegacyMode = false; +var enableOwnerStacks = false; // Flow magic to verify the exports of this file match the original version. + var suppressWarning = false; function setSuppressWarning(newSuppressWarning) { { @@ -62,7 +85,7 @@ function error(format) { printWarning('error', format, args); } } -} +} // eslint-disable-next-line react-internal/no-production-logging function printWarning(level, format, args) { // When changing this logic, you might want to also @@ -71,6 +94,9 @@ function printWarning(level, format, args) { var isErrorLogger = format === '%s\n\n%s\n' || format === '%o\n\n%s\n\n%s\n'; if (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. var stack = ReactSharedInternals.getCurrentStack(); if (stack !== '') { @@ -2346,28 +2372,6 @@ function set(key, value) { key._reactInternals = value; } -// Re-export dynamic flags from the internal module. -var dynamicFlags = dynamicFlagsUntyped; // We destructure each value before re-exporting to avoid a dynamic look-up on -// the exports object every time a flag is read. - -var alwaysThrottleRetries = dynamicFlags.alwaysThrottleRetries, - consoleManagedByDevToolsDuringStrictMode = dynamicFlags.consoleManagedByDevToolsDuringStrictMode, - disableDefaultPropsExceptForClasses = dynamicFlags.disableDefaultPropsExceptForClasses, - enableDeferRootSchedulingToMicrotask = dynamicFlags.enableDeferRootSchedulingToMicrotask, - enableInfiniteRenderLoopDetection = dynamicFlags.enableInfiniteRenderLoopDetection; - // The rest of the flags are static for better dead code elimination. -var enableAsyncActions = true; -var enableSchedulingProfiler = true; -var enableProfilerTimer = true; -var enableProfilerCommitHooks = true; -var enableProfilerNestedUpdatePhase = true; -var enableAsyncIterableChildren = false; -var syncLaneExpirationMs = 250; -var transitionLaneExpirationMs = 5000; -var enableLazyContextPropagation = false; -var enableLegacyHidden = false; -var disableLegacyMode = false; - // When adding new symbols to this file, // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' // The Symbol used to tag the ReactElement-like types. @@ -3244,6 +3248,8 @@ function runWithFiberInDEV(fiber, callback, arg0, arg1, arg2, arg3, arg4) { setCurrentFiber(fiber); try { + if (enableOwnerStacks) ; + return callback(arg0, arg1, arg2, arg3, arg4); } finally { current = previousFiber; @@ -26547,7 +26553,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition return root; } -var ReactVersion = '19.0.0-rc-3589e53b'; +var ReactVersion = '19.0.0-rc-7e1b1d14'; /* * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol