Skip to content

Commit

Permalink
[Fiber] Enable Native console.createTask Stacks When Available (#29223)
Browse files Browse the repository at this point in the history
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.

<img width="673" alt="Screenshot 2024-05-22 at 4 00 27 PM"
src="https://github.com/facebook/react/assets/63648/5313ed53-b298-4386-8f76-8eb85bdfbbc7">

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
`<Counter> (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 ea6e059.
  • Loading branch information
sebmarkbage committed May 26, 2024
1 parent 15d1dee commit 50be937
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<1b15d797a9023201acc95022ba001e0f>>
* @generated SignedSource<<5d2de112982cec5eac69c9d1f8e71fe5>>
*/

'use strict';
Expand All @@ -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),
Expand All @@ -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
Expand All @@ -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 !== '') {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<498b38ab8fbbf44800642c8dc0009e44>>
* @generated SignedSource<<d10d18b906d5290962ea3f530139aefd>>
*/

'use strict';
Expand Down Expand Up @@ -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
Expand All @@ -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 !== '') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<0a367e8c426be018f37ef2a753bebe30>>
* @generated SignedSource<<92915fe99444450e2d1431f2c1ba40f2>>
*/

'use strict';
Expand Down Expand Up @@ -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
Expand All @@ -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 !== '') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<43472d2aa5457c3ff87b82ad5ff89a40>>
* @generated SignedSource<<a504442f74a5c97d4fa7e8c91e8156f4>>
*/

'use strict';
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 !== '') {
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
b078c810c787cf13d9bd1958f083b4e3a162a720
ea6e05912aa43a0bbfbee381752caa1817a41a86
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<66f3250cfa263c3a4528924d68e4197c>>
* @generated SignedSource<<d66dfe0f482a855f5a25c6611f697b38>>
*/

'use strict';
Expand All @@ -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) {
{
Expand Down Expand Up @@ -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
Expand All @@ -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 !== '') {
Expand Down Expand Up @@ -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 = {};
/**
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<3d4cf8990ac0b10f2ad4552e0a0fc75f>>
* @generated SignedSource<<3dbcb35ed104bc31d027dfdf6f5f8da0>>
*/

'use strict';
Expand All @@ -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) {
{
Expand Down Expand Up @@ -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
Expand All @@ -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 !== '') {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 50be937

Please sign in to comment.