-
Notifications
You must be signed in to change notification settings - Fork 46.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Flight] Prefix owner stacks added to the console.log with the current stack #30427
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -232,15 +232,15 @@ describe('console', () => { | |
expect(mockWarn.mock.calls[0][0]).toBe('warn'); | ||
expect(normalizeCodeLocInfo(mockWarn.mock.calls[0][1])).toEqual( | ||
supportsOwnerStacks | ||
? '\n in Parent (at **)' | ||
? '\n in Child (at **)\n in Parent (at **)' | ||
: '\n in Child (at **)\n in Intermediate (at **)\n in Parent (at **)', | ||
); | ||
expect(mockError).toHaveBeenCalledTimes(1); | ||
expect(mockError.mock.calls[0]).toHaveLength(2); | ||
expect(mockError.mock.calls[0][0]).toBe('error'); | ||
expect(normalizeCodeLocInfo(mockError.mock.calls[0][1])).toBe( | ||
supportsOwnerStacks | ||
? '\n in Parent (at **)' | ||
? '\n in Child (at **)\n in Parent (at **)' | ||
: '\n in Child (at **)\n in Intermediate (at **)\n in Parent (at **)', | ||
); | ||
}); | ||
|
@@ -279,7 +279,8 @@ describe('console', () => { | |
expect(mockWarn.mock.calls[0][0]).toBe('active warn'); | ||
expect(normalizeCodeLocInfo(mockWarn.mock.calls[0][1])).toEqual( | ||
supportsOwnerStacks | ||
? '\n in Parent (at **)' | ||
? // TODO: It would be nice to have a Child stack frame here since it's just the effect function. | ||
'\n in Parent (at **)' | ||
: '\n in Child (at **)\n in Intermediate (at **)\n in Parent (at **)', | ||
); | ||
expect(mockWarn.mock.calls[1]).toHaveLength(2); | ||
|
@@ -497,15 +498,15 @@ describe('console', () => { | |
expect(mockWarn.mock.calls[0][0]).toBe('warn'); | ||
expect(normalizeCodeLocInfo(mockWarn.mock.calls[0][1])).toEqual( | ||
supportsOwnerStacks | ||
? '\n in Parent (at **)' | ||
? '\n in Child (at **)\n in Parent (at **)' | ||
: '\n in Child (at **)\n in Intermediate (at **)\n in Parent (at **)', | ||
); | ||
expect(mockError).toHaveBeenCalledTimes(1); | ||
expect(mockError.mock.calls[0]).toHaveLength(2); | ||
expect(mockError.mock.calls[0][0]).toBe('error'); | ||
expect(normalizeCodeLocInfo(mockError.mock.calls[0][1])).toBe( | ||
supportsOwnerStacks | ||
? '\n in Parent (at **)' | ||
? '\n in Child (at **)\n in Parent (at **)' | ||
: '\n in Child (at **)\n in Intermediate (at **)\n in Parent (at **)', | ||
); | ||
}); | ||
|
@@ -1032,7 +1033,7 @@ describe('console', () => { | |
expect(mockWarn.mock.calls[0]).toHaveLength(2); | ||
expect(normalizeCodeLocInfo(mockWarn.mock.calls[0][1])).toEqual( | ||
supportsOwnerStacks | ||
? '\n in Parent (at **)' | ||
? '\n in Child (at **)\n in Parent (at **)' | ||
: '\n in Child (at **)\n in Intermediate (at **)\n in Parent (at **)', | ||
); | ||
expect(mockWarn.mock.calls[1]).toHaveLength(3); | ||
|
@@ -1042,15 +1043,16 @@ describe('console', () => { | |
expect(mockWarn.mock.calls[1][1]).toMatch('warn'); | ||
expect(normalizeCodeLocInfo(mockWarn.mock.calls[1][2]).trim()).toEqual( | ||
supportsOwnerStacks | ||
? 'in Parent (at **)' | ||
? 'in Object.overrideMethod (at **)' + // TODO: This leading frame is due to our extra wrapper that shouldn't exist. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This happens because the We should really just get rid of that extra patching because it runs late and is therefore running after potential user space patching. We should instead reuse the early patching that we already do for the purpose of strict mode printing. That way whatever user spaces wrappers do will be before the dimming and we don't add an extra stack frame here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yup. I am planning to work on it this week. |
||
'\n in Child (at **)\n in Parent (at **)' | ||
: 'in Child (at **)\n in Intermediate (at **)\n in Parent (at **)', | ||
); | ||
|
||
expect(mockError).toHaveBeenCalledTimes(2); | ||
expect(mockError.mock.calls[0]).toHaveLength(2); | ||
expect(normalizeCodeLocInfo(mockError.mock.calls[0][1])).toEqual( | ||
supportsOwnerStacks | ||
? '\n in Parent (at **)' | ||
? '\n in Child (at **)\n in Parent (at **)' | ||
: '\n in Child (at **)\n in Intermediate (at **)\n in Parent (at **)', | ||
); | ||
expect(mockError.mock.calls[1]).toHaveLength(3); | ||
|
@@ -1060,7 +1062,8 @@ describe('console', () => { | |
expect(mockError.mock.calls[1][1]).toEqual('error'); | ||
expect(normalizeCodeLocInfo(mockError.mock.calls[1][2]).trim()).toEqual( | ||
supportsOwnerStacks | ||
? 'in Parent (at **)' | ||
? 'in Object.overrideMethod (at **)' + // TODO: This leading frame is due to our extra wrapper that shouldn't exist. | ||
'\n in Child (at **)\n in Parent (at **)' | ||
: 'in Child (at **)\n in Intermediate (at **)\n in Parent (at **)', | ||
); | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -121,13 +121,6 @@ export function supportsOwnerStacks(fiber: Fiber): boolean { | |
return fiber._debugStack !== undefined; | ||
} | ||
|
||
function describeFunctionComponentFrameWithoutLineNumber(fn: Function): string { | ||
// We use this because we don't actually want to describe the line of the component | ||
// but just the component name. | ||
const name = fn ? fn.displayName || fn.name : ''; | ||
return name ? describeBuiltInComponentFrame(name) : ''; | ||
} | ||
|
||
export function getOwnerStackByFiberInDev( | ||
workTagMap: WorkTagMap, | ||
workInProgress: Fiber, | ||
|
@@ -140,10 +133,6 @@ export function getOwnerStackByFiberInDev( | |
HostComponent, | ||
SuspenseComponent, | ||
SuspenseListComponent, | ||
FunctionComponent, | ||
SimpleMemoComponent, | ||
ForwardRef, | ||
ClassComponent, | ||
} = workTagMap; | ||
try { | ||
let info = ''; | ||
|
@@ -159,8 +148,6 @@ export function getOwnerStackByFiberInDev( | |
// on the regular stack that's currently executing. However, for built-ins there is no such | ||
// named stack frame and it would be ignored as being internal anyway. Therefore we add | ||
// add one extra frame just to describe the "current" built-in component by name. | ||
// Similarly, if there is no owner at all, then there's no stack frame so we add the name | ||
// of the root component to the stack to know which component is currently executing. | ||
switch (workInProgress.tag) { | ||
case HostHoistable: | ||
case HostSingleton: | ||
|
@@ -173,24 +160,6 @@ export function getOwnerStackByFiberInDev( | |
case SuspenseListComponent: | ||
info += describeBuiltInComponentFrame('SuspenseList'); | ||
break; | ||
case FunctionComponent: | ||
case SimpleMemoComponent: | ||
case ClassComponent: | ||
if (!workInProgress._debugOwner && info === '') { | ||
// Only if we have no other data about the callsite do we add | ||
// the component name as the single stack frame. | ||
info += describeFunctionComponentFrameWithoutLineNumber( | ||
workInProgress.type, | ||
); | ||
} | ||
break; | ||
case ForwardRef: | ||
if (!workInProgress._debugOwner && info === '') { | ||
info += describeFunctionComponentFrameWithoutLineNumber( | ||
workInProgress.type.render, | ||
); | ||
} | ||
break; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the actual stack usually has a frame inside the current component, we don't have to add it even if there's no owner since otherwise it'll end up show up twice. I'll do a separate PR to align this with captureOwnerStack() which should also exclude these. |
||
} | ||
|
||
let owner: void | null | Fiber | ReactComponentInfo = workInProgress; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only has the
useEffect(() =>
inner function on the stack trace which don't currently have thereact-bottom-stack-frame
which means they're filtered out since we don't know which frames to include.Even if we did it wouldn't have a name. It might be nice to automatically name the effect functions based on the component/hook that they're part of. Similar to how class methods are named based on both the class instance and the method.