Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions packages/react-devtools-core/src/standalone.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
import {localStorageSetItem} from 'react-devtools-shared/src/storage';

import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
import type {ReactFunctionLocation} from 'shared/ReactTypes';
import type {ReactFunctionLocation, ReactCallSite} from 'shared/ReactTypes';

export type StatusTypes = 'server-connected' | 'devtools-connected' | 'error';
export type StatusListener = (message: string, status: StatusTypes) => void;
Expand Down Expand Up @@ -144,8 +144,8 @@ async function fetchFileWithCaching(url: string) {
}

function canViewElementSourceFunction(
_source: ReactFunctionLocation,
symbolicatedSource: ReactFunctionLocation | null,
_source: ReactFunctionLocation | ReactCallSite,
symbolicatedSource: ReactFunctionLocation | ReactCallSite | null,
): boolean {
if (symbolicatedSource == null) {
return false;
Expand All @@ -156,8 +156,8 @@ function canViewElementSourceFunction(
}

function viewElementSourceFunction(
_source: ReactFunctionLocation,
symbolicatedSource: ReactFunctionLocation | null,
_source: ReactFunctionLocation | ReactCallSite,
symbolicatedSource: ReactFunctionLocation | ReactCallSite | null,
): void {
if (symbolicatedSource == null) {
return;
Expand Down
2 changes: 1 addition & 1 deletion packages/react-devtools-extensions/src/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ function createSourcesEditorPanel() {
editorPane = createdPane;

createdPane.setPage('panel.html');
createdPane.setHeight('42px');
createdPane.setHeight('75px');

createdPane.onShown.addListener(portal => {
editorPortalContainer = portal.container;
Expand Down
17 changes: 13 additions & 4 deletions packages/react-devtools-fusebox/src/frontend.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,26 @@ export type ReactFunctionLocation = [
number, // enclosing line number
number, // enclosing column number
];
export type ReactCallSite = [
string, // function name
string, // file name TODO: model nested eval locations as nested arrays
number, // line number
number, // column number
number, // enclosing line number
number, // enclosing column number
boolean, // async resume
];
export type ViewElementSource = (
source: ReactFunctionLocation,
symbolicatedSource: ReactFunctionLocation | null,
source: ReactFunctionLocation | ReactCallSite,
symbolicatedSource: ReactFunctionLocation | ReactCallSite | null,
) => void;
export type ViewAttributeSource = (
id: number,
path: Array<string | number>,
) => void;
export type CanViewElementSource = (
source: ReactFunctionLocation,
symbolicatedSource: ReactFunctionLocation | null,
source: ReactFunctionLocation | ReactCallSite,
symbolicatedSource: ReactFunctionLocation | ReactCallSite | null,
) => boolean;

export type InitializationOptions = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ export function test(maybeInspectedElement) {
hasOwnProperty('canEditFunctionProps') &&
hasOwnProperty('canEditHooks') &&
hasOwnProperty('canToggleSuspense') &&
hasOwnProperty('canToggleError') &&
hasOwnProperty('canViewSource')
hasOwnProperty('canToggleError')
);
}

Expand Down
5 changes: 0 additions & 5 deletions packages/react-devtools-shared/src/backend/fiber/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4374,8 +4374,6 @@ export function attach(
(fiber.alternate !== null &&
forceFallbackForFibers.has(fiber.alternate))),

// Can view component source location.
canViewSource,
source,

// Does the component have legacy context attached to it.
Expand Down Expand Up @@ -4416,7 +4414,6 @@ export function attach(
function inspectVirtualInstanceRaw(
virtualInstance: VirtualInstance,
): InspectedElement | null {
const canViewSource = true;
const source = getSourceForInstance(virtualInstance);

const componentInfo = virtualInstance.data;
Expand Down Expand Up @@ -4470,8 +4467,6 @@ export function attach(

canToggleSuspense: supportsTogglingSuspense && hasSuspenseBoundary,

// Can view component source location.
canViewSource,
source,

// Does the component have legacy context attached to it.
Expand Down
2 changes: 0 additions & 2 deletions packages/react-devtools-shared/src/backend/legacy/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -830,8 +830,6 @@ export function attach(
// Suspense did not exist in legacy versions
canToggleSuspense: false,

// Can view component source location.
canViewSource: type === ElementTypeClass || type === ElementTypeFunction,
source: null,

// Only legacy context exists in legacy versions.
Expand Down
3 changes: 0 additions & 3 deletions packages/react-devtools-shared/src/backend/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,6 @@ export type InspectedElement = {
// Is this Suspense, and can its value be overridden now?
canToggleSuspense: boolean,

// Can view component source location.
canViewSource: boolean,

// Does the component have legacy context attached to it.
hasLegacyContext: boolean,

Expand Down
2 changes: 0 additions & 2 deletions packages/react-devtools-shared/src/backendAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@ export function convertInspectedElementBackendToFrontend(
canToggleError,
isErrored,
canToggleSuspense,
canViewSource,
hasLegacyContext,
id,
type,
Expand Down Expand Up @@ -252,7 +251,6 @@ export function convertInspectedElementBackendToFrontend(
canToggleError,
isErrored,
canToggleSuspense,
canViewSource,
hasLegacyContext,
id,
key,
Expand Down
2 changes: 2 additions & 0 deletions packages/react-devtools-shared/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export const LOCAL_STORAGE_OPEN_IN_EDITOR_URL =
'React::DevTools::openInEditorUrl';
export const LOCAL_STORAGE_OPEN_IN_EDITOR_URL_PRESET =
'React::DevTools::openInEditorUrlPreset';
export const LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR =
'React::DevTools::alwaysOpenInEditor';
export const LOCAL_STORAGE_PARSE_HOOK_NAMES_KEY =
'React::DevTools::parseHookNames';
export const SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ import Toggle from '../Toggle';
import {ElementTypeSuspense} from 'react-devtools-shared/src/frontend/types';
import InspectedElementView from './InspectedElementView';
import {InspectedElementContext} from './InspectedElementContext';
import {getOpenInEditorURL} from '../../../utils';
import {LOCAL_STORAGE_OPEN_IN_EDITOR_URL} from '../../../constants';
import {getOpenInEditorURL, getAlwaysOpenInEditor} from '../../../utils';
import {
LOCAL_STORAGE_OPEN_IN_EDITOR_URL,
LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR,
} from '../../../constants';
import FetchFileWithCachingContext from './FetchFileWithCachingContext';
import {symbolicateSourceWithCache} from 'react-devtools-shared/src/symbolicateSource';
import OpenInEditorButton from './OpenInEditorButton';
Expand Down Expand Up @@ -118,18 +121,26 @@ export default function InspectedElementWrapper(_: Props): React.Node {
inspectedElement != null &&
inspectedElement.canToggleSuspense;

const editorURL = useSyncExternalStore(
function subscribe(callback) {
window.addEventListener(LOCAL_STORAGE_OPEN_IN_EDITOR_URL, callback);
const alwaysOpenInEditor = useSyncExternalStore(
useCallback(function subscribe(callback) {
window.addEventListener(LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR, callback);
return function unsubscribe() {
window.removeEventListener(LOCAL_STORAGE_OPEN_IN_EDITOR_URL, callback);
window.removeEventListener(
LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR,
callback,
);
};
},
function getState() {
return getOpenInEditorURL();
},
}, []),
getAlwaysOpenInEditor,
);

const editorURL = useSyncExternalStore(function subscribe(callback) {
window.addEventListener(LOCAL_STORAGE_OPEN_IN_EDITOR_URL, callback);
return function unsubscribe() {
window.removeEventListener(LOCAL_STORAGE_OPEN_IN_EDITOR_URL, callback);
};
}, getOpenInEditorURL);

const toggleErrored = useCallback(() => {
if (inspectedElement == null) {
return;
Expand Down Expand Up @@ -217,7 +228,8 @@ export default function InspectedElementWrapper(_: Props): React.Node {
</div>
</div>

{!!editorURL &&
{!alwaysOpenInEditor &&
!!editorURL &&
inspectedElement != null &&
inspectedElement.source != null &&
symbolicatedSourcePromise != null && (
Expand Down Expand Up @@ -271,8 +283,7 @@ export default function InspectedElementWrapper(_: Props): React.Node {

{!hideViewSourceAction && (
<InspectedElementViewSourceButton
canViewSource={inspectedElement?.canViewSource}
source={inspectedElement?.source}
source={inspectedElement ? inspectedElement.source : null}
symbolicatedSourcePromise={symbolicatedSourcePromise}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
*/

import * as React from 'react';
import {useCallback, useContext} from 'react';
import {copy} from 'clipboard-js';
import {toNormalUrl} from 'jsc-safe-url';

Expand All @@ -17,7 +16,7 @@ import ButtonIcon from '../ButtonIcon';
import Skeleton from './Skeleton';
import {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';

import ViewElementSourceContext from './ViewElementSourceContext';
import useOpenResource from '../useOpenResource';

import type {ReactFunctionLocation} from 'shared/ReactTypes';
import styles from './InspectedElementSourcePanel.css';
Expand Down Expand Up @@ -91,24 +90,11 @@ function CopySourceButton({source, symbolicatedSourcePromise}: Props) {
function FormattedSourceString({source, symbolicatedSourcePromise}: Props) {
const symbolicatedSource = React.use(symbolicatedSourcePromise);

const {canViewElementSourceFunction, viewElementSourceFunction} = useContext(
ViewElementSourceContext,
const [linkIsEnabled, viewSource] = useOpenResource(
source,
symbolicatedSource,
);

// 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 linkIsEnabled =
viewElementSourceFunction != null &&
source != null &&
(canViewElementSourceFunction == null ||
canViewElementSourceFunction(source, symbolicatedSource));

const viewSource = useCallback(() => {
if (viewElementSourceFunction != null && source != null) {
viewElementSourceFunction(source, symbolicatedSource);
}
}, [source, symbolicatedSource]);

const [, sourceURL, line] =
symbolicatedSource == null ? source : symbolicatedSource;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,79 +11,48 @@ import * as React from 'react';

import ButtonIcon from '../ButtonIcon';
import Button from '../Button';
import ViewElementSourceContext from './ViewElementSourceContext';
import Skeleton from './Skeleton';

import type {ReactFunctionLocation} from 'shared/ReactTypes';
import type {
CanViewElementSource,
ViewElementSource,
} from 'react-devtools-shared/src/devtools/views/DevTools';

const {useCallback, useContext} = React;
import useOpenResource from '../useOpenResource';

type Props = {
canViewSource: ?boolean,
source: ?ReactFunctionLocation,
source: null | ReactFunctionLocation,
symbolicatedSourcePromise: Promise<ReactFunctionLocation | 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: ?ReactFunctionLocation,
source: null | ReactFunctionLocation,
symbolicatedSourcePromise: Promise<ReactFunctionLocation | 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]);

const [buttonIsEnabled, viewSource] = useOpenResource(
source,
symbolicatedSource,
);
return (
<Button
disabled={!buttonIsEnabled}
Expand Down
10 changes: 5 additions & 5 deletions packages/react-devtools-shared/src/devtools/views/DevTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,22 @@ import type {FetchFileWithCaching} from './Components/FetchFileWithCachingContex
import type {HookNamesModuleLoaderFunction} from 'react-devtools-shared/src/devtools/views/Components/HookNamesModuleLoaderContext';
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
import type {BrowserTheme} from 'react-devtools-shared/src/frontend/types';
import type {ReactFunctionLocation} from 'shared/ReactTypes';
import type {ReactFunctionLocation, ReactCallSite} from 'shared/ReactTypes';
import type {SourceSelection} from './Editor/EditorPane';

export type TabID = 'components' | 'profiler';

export type ViewElementSource = (
source: ReactFunctionLocation,
symbolicatedSource: ReactFunctionLocation | null,
source: ReactFunctionLocation | ReactCallSite,
symbolicatedSource: ReactFunctionLocation | ReactCallSite | null,
) => void;
export type ViewAttributeSource = (
id: number,
path: Array<string | number>,
) => void;
export type CanViewElementSource = (
source: ReactFunctionLocation,
symbolicatedSource: ReactFunctionLocation | null,
source: ReactFunctionLocation | ReactCallSite,
symbolicatedSource: ReactFunctionLocation | ReactCallSite | null,
) => boolean;

export type Props = {
Expand Down
Loading
Loading