mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
e5287287aa
Stacked on https://github.com/facebook/react/pull/28351, please review only the last commit. Top-level description of the approach: 1. Once user selects an element from the tree, frontend asks backend to return the inspected element, this is where we simulate an error happening in `render` function of the component and then we parse the error stack. As an improvement, we should probably migrate from custom implementation of error stack parser to `error-stack-parser` from npm. 2. When frontend receives the inspected element and this object is being propagated, we create a Promise for symbolicated source, which is then passed down to all components, which are using `source`. 3. These components use `use` hook for this promise and are wrapped in Suspense. Caching: 1. For browser extension, we cache Promises based on requested resource + key + column, also added use of `chrome.devtools.inspectedWindow.getResource` API. 2. For standalone case (RN), we cache based on requested resource url, we cache the content of it.
98 lines
2.9 KiB
JavaScript
98 lines
2.9 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 ButtonIcon from '../ButtonIcon';
|
|
import Button from '../Button';
|
|
import ViewElementSourceContext from './ViewElementSourceContext';
|
|
import Skeleton from './Skeleton';
|
|
|
|
import type {Source as InspectedElementSource} from 'react-devtools-shared/src/shared/types';
|
|
import type {
|
|
CanViewElementSource,
|
|
ViewElementSource,
|
|
} from 'react-devtools-shared/src/devtools/views/DevTools';
|
|
|
|
const {useCallback, useContext} = React;
|
|
|
|
type Props = {
|
|
canViewSource: ?boolean,
|
|
source: ?InspectedElementSource,
|
|
symbolicatedSourcePromise: Promise<InspectedElementSource | null> | null,
|
|
};
|
|
|
|
function InspectedElementViewSourceButton({
|
|
canViewSource,
|
|
source,
|
|
symbolicatedSourcePromise,
|
|
}: Props): React.Node {
|
|
const {canViewElementSourceFunction, viewElementSourceFunction} = useContext(
|
|
ViewElementSourceContext,
|
|
);
|
|
|
|
return (
|
|
<React.Suspense fallback={<Skeleton height={16} width={24} />}>
|
|
<ActualSourceButton
|
|
canViewSource={canViewSource}
|
|
source={source}
|
|
symbolicatedSourcePromise={symbolicatedSourcePromise}
|
|
canViewElementSourceFunction={canViewElementSourceFunction}
|
|
viewElementSourceFunction={viewElementSourceFunction}
|
|
/>
|
|
</React.Suspense>
|
|
);
|
|
}
|
|
|
|
type ActualSourceButtonProps = {
|
|
canViewSource: ?boolean,
|
|
source: ?InspectedElementSource,
|
|
symbolicatedSourcePromise: Promise<InspectedElementSource | null> | null,
|
|
canViewElementSourceFunction: CanViewElementSource | null,
|
|
viewElementSourceFunction: ViewElementSource | null,
|
|
};
|
|
function ActualSourceButton({
|
|
canViewSource,
|
|
source,
|
|
symbolicatedSourcePromise,
|
|
canViewElementSourceFunction,
|
|
viewElementSourceFunction,
|
|
}: ActualSourceButtonProps): React.Node {
|
|
const symbolicatedSource =
|
|
symbolicatedSourcePromise == null
|
|
? null
|
|
: React.use(symbolicatedSourcePromise);
|
|
|
|
// In some cases (e.g. FB internal usage) the standalone shell might not be able to view the source.
|
|
// To detect this case, we defer to an injected helper function (if present).
|
|
const buttonIsEnabled =
|
|
!!canViewSource &&
|
|
viewElementSourceFunction != null &&
|
|
source != null &&
|
|
(canViewElementSourceFunction == null ||
|
|
canViewElementSourceFunction(source, symbolicatedSource));
|
|
|
|
const viewSource = useCallback(() => {
|
|
if (viewElementSourceFunction != null && source != null) {
|
|
viewElementSourceFunction(source, symbolicatedSource);
|
|
}
|
|
}, [source, symbolicatedSource]);
|
|
|
|
return (
|
|
<Button
|
|
disabled={!buttonIsEnabled}
|
|
onClick={viewSource}
|
|
title="View source for this element">
|
|
<ButtonIcon type="view-source" />
|
|
</Button>
|
|
);
|
|
}
|
|
|
|
export default InspectedElementViewSourceButton;
|