mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
0825d019be
Stacked on #34094. This shows the I/O stack if available. If it's not available or if it has a different owner (like if it was passed in) then we show the `"awaited at:"` stack below it so you can see where it started and where it was awaited. If it's the same owner this tends to be unnecessary noise. We could maybe be smarter if the stacks are very different then you might want to show both even with the same owner. <img width="517" height="478" alt="Screenshot 2025-08-04 at 11 57 28 AM" src="https://github.com/user-attachments/assets/2dbfbed4-4671-4a5f-8e6e-ebec6fe8a1b7" /> Additionally, this adds an inferred await if there's no owner and no stack for the await. The inferred await of a function/class component is just the owner. No stack. Because the stack trace would be the return value. This will also be the case if you use throw-a-Promise. The inferred await in the child position of a built-in is the JSX location of that await like if you pass a promise to a child. This inference already happens when you pass a Promise from RSC so in this case it already has an await - so this is mainly for client promises.
84 lines
2.1 KiB
JavaScript
84 lines
2.1 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow
|
|
*/
|
|
|
|
import * as React from 'react';
|
|
import {use, useContext} from 'react';
|
|
|
|
import useOpenResource from '../useOpenResource';
|
|
|
|
import styles from './StackTraceView.css';
|
|
|
|
import type {
|
|
ReactStackTrace,
|
|
ReactCallSite,
|
|
ReactFunctionLocation,
|
|
} from 'shared/ReactTypes';
|
|
|
|
import FetchFileWithCachingContext from './FetchFileWithCachingContext';
|
|
|
|
import {symbolicateSourceWithCache} from 'react-devtools-shared/src/symbolicateSource';
|
|
|
|
import formatLocationForDisplay from './formatLocationForDisplay';
|
|
|
|
type CallSiteViewProps = {
|
|
callSite: ReactCallSite,
|
|
};
|
|
|
|
export function CallSiteView({callSite}: CallSiteViewProps): React.Node {
|
|
const fetchFileWithCaching = useContext(FetchFileWithCachingContext);
|
|
|
|
const [virtualFunctionName, virtualURL, virtualLine, virtualColumn] =
|
|
callSite;
|
|
|
|
const symbolicatedCallSite: null | ReactFunctionLocation =
|
|
fetchFileWithCaching !== null
|
|
? use(
|
|
symbolicateSourceWithCache(
|
|
fetchFileWithCaching,
|
|
virtualURL,
|
|
virtualLine,
|
|
virtualColumn,
|
|
),
|
|
)
|
|
: null;
|
|
|
|
const [linkIsEnabled, viewSource] = useOpenResource(
|
|
callSite,
|
|
symbolicatedCallSite,
|
|
);
|
|
const [functionName, url, line, column] =
|
|
symbolicatedCallSite !== null ? symbolicatedCallSite : callSite;
|
|
return (
|
|
<div className={styles.CallSite}>
|
|
{functionName || virtualFunctionName}
|
|
{' @ '}
|
|
<span
|
|
className={linkIsEnabled ? styles.Link : null}
|
|
onClick={viewSource}
|
|
title={url + ':' + line}>
|
|
{formatLocationForDisplay(url, line, column)}
|
|
</span>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
type Props = {
|
|
stack: ReactStackTrace,
|
|
};
|
|
|
|
export default function StackTraceView({stack}: Props): React.Node {
|
|
return (
|
|
<div className={styles.StackTraceView}>
|
|
{stack.map((callSite, index) => (
|
|
<CallSiteView key={index} callSite={callSite} />
|
|
))}
|
|
</div>
|
|
);
|
|
}
|