@@ -84,7 +84,9 @@ function FormattedSourceString({source, symbolicatedSourcePromise}: Props) {
const {sourceURL, line} = source;
return (
-
+
{formatSourceForDisplay(sourceURL, line)}
);
@@ -93,7 +95,9 @@ function FormattedSourceString({source, symbolicatedSourcePromise}: Props) {
const {sourceURL, line} = symbolicatedSource;
return (
-
+
{formatSourceForDisplay(sourceURL, line)}
);
diff --git a/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/context.js b/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/context.js
index d037ca56add54..7170864ab35fe 100644
--- a/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/context.js
+++ b/packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/context.js
@@ -100,10 +100,10 @@ function NativeStyleContextController({children}: Props): React.Node {
[store],
);
- // It's very important that this context consumes selectedElementID and not NativeStyleID.
+ // It's very important that this context consumes inspectedElementID and not NativeStyleID.
// Otherwise the effect that sends the "inspect" message across the bridge-
// would itself be blocked by the same render that suspends (waiting for the data).
- const {selectedElementID} = useContext
(TreeStateContext);
+ const {inspectedElementID} = useContext(TreeStateContext);
const [currentStyleAndLayout, setCurrentStyleAndLayout] =
useState(null);
@@ -128,7 +128,7 @@ function NativeStyleContextController({children}: Props): React.Node {
resource.write(element, styleAndLayout);
// Schedule update with React if the currently-selected element has been invalidated.
- if (id === selectedElementID) {
+ if (id === inspectedElementID) {
setCurrentStyleAndLayout(styleAndLayout);
}
}
@@ -141,15 +141,15 @@ function NativeStyleContextController({children}: Props): React.Node {
'NativeStyleEditor_styleAndLayout',
onStyleAndLayout,
);
- }, [bridge, currentStyleAndLayout, selectedElementID, store]);
+ }, [bridge, currentStyleAndLayout, inspectedElementID, store]);
// This effect handler polls for updates on the currently selected element.
useEffect(() => {
- if (selectedElementID === null) {
+ if (inspectedElementID === null) {
return () => {};
}
- const rendererID = store.getRendererIDForElement(selectedElementID);
+ const rendererID = store.getRendererIDForElement(inspectedElementID);
let timeoutID: TimeoutID | null = null;
@@ -158,7 +158,7 @@ function NativeStyleContextController({children}: Props): React.Node {
if (rendererID !== null) {
bridge.send('NativeStyleEditor_measure', {
- id: selectedElementID,
+ id: inspectedElementID,
rendererID,
});
}
@@ -170,7 +170,7 @@ function NativeStyleContextController({children}: Props): React.Node {
const onStyleAndLayout = ({id}: StyleAndLayoutBackend) => {
// If this is the element we requested, wait a little bit and then ask for another update.
- if (id === selectedElementID) {
+ if (id === inspectedElementID) {
if (timeoutID !== null) {
clearTimeout(timeoutID);
}
@@ -190,7 +190,7 @@ function NativeStyleContextController({children}: Props): React.Node {
clearTimeout(timeoutID);
}
};
- }, [bridge, selectedElementID, store]);
+ }, [bridge, inspectedElementID, store]);
const value = useMemo(
() => ({getStyleAndLayout}),
diff --git a/packages/react-devtools-shared/src/devtools/views/Components/SelectedTreeHighlight.js b/packages/react-devtools-shared/src/devtools/views/Components/SelectedTreeHighlight.js
index 44183f6575234..16035a13d65f9 100644
--- a/packages/react-devtools-shared/src/devtools/views/Components/SelectedTreeHighlight.js
+++ b/packages/react-devtools-shared/src/devtools/views/Components/SelectedTreeHighlight.js
@@ -28,19 +28,19 @@ export default function SelectedTreeHighlight(_: {}): React.Node {
const {lineHeight} = useContext(SettingsContext);
const store = useContext(StoreContext);
const treeFocused = useContext(TreeFocusedContext);
- const {ownerID, selectedElementID} = useContext(TreeStateContext);
+ const {ownerID, inspectedElementID} = useContext(TreeStateContext);
const subscription = useMemo(
() => ({
getCurrentValue: () => {
if (
- selectedElementID === null ||
- store.isInsideCollapsedSubTree(selectedElementID)
+ inspectedElementID === null ||
+ store.isInsideCollapsedSubTree(inspectedElementID)
) {
return null;
}
- const element = store.getElementByID(selectedElementID);
+ const element = store.getElementByID(inspectedElementID);
if (
element === null ||
element.isCollapsed ||
@@ -83,7 +83,7 @@ export default function SelectedTreeHighlight(_: {}): React.Node {
};
},
}),
- [selectedElementID, store],
+ [inspectedElementID, store],
);
const data = useSubscription(subscription);
diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Tree.js b/packages/react-devtools-shared/src/devtools/views/Components/Tree.js
index db1bf9a98c135..2a1569bb52e1e 100644
--- a/packages/react-devtools-shared/src/devtools/views/Components/Tree.js
+++ b/packages/react-devtools-shared/src/devtools/views/Components/Tree.js
@@ -42,24 +42,36 @@ import {logEvent} from 'react-devtools-shared/src/Logger';
const DEFAULT_INDENTATION_SIZE = 12;
export type ItemData = {
- numElements: number,
isNavigatingWithKeyboard: boolean,
- lastScrolledIDRef: {current: number | null, ...},
onElementMouseEnter: (id: number) => void,
treeFocused: boolean,
};
-type Props = {};
+function calculateInitialScrollOffset(
+ inspectedElementIndex: number | null,
+ elementHeight: number,
+): number | void {
+ if (inspectedElementIndex === null) {
+ return undefined;
+ }
+
+ if (inspectedElementIndex < 3) {
+ return undefined;
+ }
+
+ // Make 3 elements on top of the inspected one visible
+ return (inspectedElementIndex - 3) * elementHeight;
+}
-export default function Tree(props: Props): React.Node {
+export default function Tree(): React.Node {
const dispatch = useContext(TreeDispatcherContext);
const {
numElements,
ownerID,
searchIndex,
searchResults,
- selectedElementID,
- selectedElementIndex,
+ inspectedElementID,
+ inspectedElementIndex,
} = useContext(TreeStateContext);
const bridge = useContext(BridgeContext);
const store = useContext(StoreContext);
@@ -88,15 +100,16 @@ export default function Tree(props: Props): React.Node {
// Using a callback ref accounts for this case...
const listCallbackRef = useCallback(
(list: $FlowFixMe) => {
- if (list != null && selectedElementIndex !== null) {
- list.scrollToItem(selectedElementIndex, 'smart');
+ if (list != null && inspectedElementIndex !== null) {
+ list.scrollToItem(inspectedElementIndex, 'smart');
}
},
- [selectedElementIndex],
+ [inspectedElementIndex],
);
// Picking an element in the inspector should put focus into the tree.
- // This ensures that keyboard navigation works right after picking a node.
+ // If possible, navigation works right after picking a node.
+ // NOTE: This is not guaranteed to work, because browser extension panels are hosted inside an iframe.
useEffect(() => {
function handleStopInspectingHost(didSelectNode: boolean) {
if (didSelectNode && focusTargetRef.current !== null) {
@@ -112,11 +125,6 @@ export default function Tree(props: Props): React.Node {
bridge.removeListener('stopInspectingHost', handleStopInspectingHost);
}, [bridge]);
- // This ref is passed down the context to elements.
- // It lets them avoid autoscrolling to the same item many times
- // when a selected virtual row goes in and out of the viewport.
- const lastScrolledIDRef = useRef(null);
-
// Navigate the tree with up/down arrow keys.
useEffect(() => {
if (treeRef.current === null) {
@@ -141,8 +149,8 @@ export default function Tree(props: Props): React.Node {
case 'ArrowLeft':
event.preventDefault();
element =
- selectedElementID !== null
- ? store.getElementByID(selectedElementID)
+ inspectedElementID !== null
+ ? store.getElementByID(inspectedElementID)
: null;
if (element !== null) {
if (event.altKey) {
@@ -161,8 +169,8 @@ export default function Tree(props: Props): React.Node {
case 'ArrowRight':
event.preventDefault();
element =
- selectedElementID !== null
- ? store.getElementByID(selectedElementID)
+ inspectedElementID !== null
+ ? store.getElementByID(inspectedElementID)
: null;
if (element !== null) {
if (event.altKey) {
@@ -210,35 +218,26 @@ export default function Tree(props: Props): React.Node {
return () => {
container.removeEventListener('keydown', handleKeyDown);
};
- }, [dispatch, selectedElementID, store]);
+ }, [dispatch, inspectedElementID, store]);
// Focus management.
const handleBlur = useCallback(() => setTreeFocused(false), []);
- const handleFocus = useCallback(() => {
- setTreeFocused(true);
-
- if (selectedElementIndex === null && numElements > 0) {
- dispatch({
- type: 'SELECT_ELEMENT_AT_INDEX',
- payload: 0,
- });
- }
- }, [dispatch, numElements, selectedElementIndex]);
+ const handleFocus = useCallback(() => setTreeFocused(true), []);
const handleKeyPress = useCallback(
(event: $FlowFixMe) => {
switch (event.key) {
case 'Enter':
case ' ':
- if (selectedElementID !== null) {
- dispatch({type: 'SELECT_OWNER', payload: selectedElementID});
+ if (inspectedElementID !== null) {
+ dispatch({type: 'SELECT_OWNER', payload: inspectedElementID});
}
break;
default:
break;
}
},
- [dispatch, selectedElementID],
+ [dispatch, inspectedElementID],
);
// If we switch the selected element while using the keyboard,
@@ -255,8 +254,8 @@ export default function Tree(props: Props): React.Node {
didSelectNewSearchResult = true;
}
if (isNavigatingWithKeyboard || didSelectNewSearchResult) {
- if (selectedElementID !== null) {
- highlightHostInstance(selectedElementID);
+ if (inspectedElementID !== null) {
+ highlightHostInstance(inspectedElementID);
} else {
clearHighlightHostInstance();
}
@@ -267,7 +266,7 @@ export default function Tree(props: Props): React.Node {
highlightHostInstance,
searchIndex,
searchResults,
- selectedElementID,
+ inspectedElementID,
]);
// Highlight last hovered element.
@@ -294,19 +293,11 @@ export default function Tree(props: Props): React.Node {
// This includes the owner context, since it controls a filtered view of the tree.
const itemData = useMemo(
() => ({
- numElements,
isNavigatingWithKeyboard,
onElementMouseEnter: handleElementMouseEnter,
- lastScrolledIDRef,
treeFocused,
}),
- [
- numElements,
- isNavigatingWithKeyboard,
- handleElementMouseEnter,
- lastScrolledIDRef,
- treeFocused,
- ],
+ [isNavigatingWithKeyboard, handleElementMouseEnter, treeFocused],
);
const itemKey = useCallback(
@@ -426,6 +417,10 @@ export default function Tree(props: Props): React.Node {
void;
@@ -162,8 +155,6 @@ type State = {
// Tree
numElements: number,
ownerSubtreeLeafElementID: number | null,
- selectedElementID: number | null,
- selectedElementIndex: number | null,
// Search
searchIndex: number | null,
@@ -176,14 +167,15 @@ type State = {
// Inspection element panel
inspectedElementID: number | null,
+ inspectedElementIndex: number | null,
};
function reduceTreeState(store: Store, state: State, action: Action): State {
let {
numElements,
ownerSubtreeLeafElementID,
- selectedElementIndex,
- selectedElementID,
+ inspectedElementID,
+ inspectedElementIndex,
} = state;
const ownerID = state.ownerID;
@@ -201,34 +193,33 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
// We deduce the parent-child mapping from removedIDs (id -> parentID)
// because by now it's too late to read them from the store.
while (
- selectedElementID !== null &&
- removedIDs.has(selectedElementID)
+ inspectedElementID !== null &&
+ removedIDs.has(inspectedElementID)
) {
- selectedElementID = ((removedIDs.get(
- selectedElementID,
- ): any): number);
+ // $FlowExpectedError[incompatible-type]
+ inspectedElementID = removedIDs.get(inspectedElementID);
}
- if (selectedElementID === 0) {
+ if (inspectedElementID === 0) {
// The whole root was removed.
- selectedElementIndex = null;
+ inspectedElementIndex = null;
}
break;
case 'SELECT_CHILD_ELEMENT_IN_TREE':
ownerSubtreeLeafElementID = null;
- if (selectedElementIndex !== null) {
- const selectedElement = store.getElementAtIndex(
- ((selectedElementIndex: any): number),
+ if (inspectedElementIndex !== null) {
+ const inspectedElement = store.getElementAtIndex(
+ inspectedElementIndex,
);
if (
- selectedElement !== null &&
- selectedElement.children.length > 0 &&
- !selectedElement.isCollapsed
+ inspectedElement !== null &&
+ inspectedElement.children.length > 0 &&
+ !inspectedElement.isCollapsed
) {
- const firstChildID = selectedElement.children[0];
+ const firstChildID = inspectedElement.children[0];
const firstChildIndex = store.getIndexOfElementID(firstChildID);
if (firstChildIndex !== null) {
- selectedElementIndex = firstChildIndex;
+ inspectedElementIndex = firstChildIndex;
}
}
}
@@ -236,7 +227,8 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
case 'SELECT_ELEMENT_AT_INDEX':
ownerSubtreeLeafElementID = null;
- selectedElementIndex = (action: ACTION_SELECT_ELEMENT_AT_INDEX).payload;
+ inspectedElementIndex = (action: ACTION_SELECT_ELEMENT_AT_INDEX)
+ .payload;
break;
case 'SELECT_ELEMENT_BY_ID':
ownerSubtreeLeafElementID = null;
@@ -245,30 +237,30 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
// It might also cause problems if the specified element was inside of a (not yet expanded) subtree.
lookupIDForIndex = false;
- selectedElementID = (action: ACTION_SELECT_ELEMENT_BY_ID).payload;
- selectedElementIndex =
- selectedElementID === null
+ inspectedElementID = (action: ACTION_SELECT_ELEMENT_BY_ID).payload;
+ inspectedElementIndex =
+ inspectedElementID === null
? null
- : store.getIndexOfElementID(selectedElementID);
+ : store.getIndexOfElementID(inspectedElementID);
break;
case 'SELECT_NEXT_ELEMENT_IN_TREE':
ownerSubtreeLeafElementID = null;
if (
- selectedElementIndex === null ||
- selectedElementIndex + 1 >= numElements
+ inspectedElementIndex === null ||
+ inspectedElementIndex + 1 >= numElements
) {
- selectedElementIndex = 0;
+ inspectedElementIndex = 0;
} else {
- selectedElementIndex++;
+ inspectedElementIndex++;
}
break;
case 'SELECT_NEXT_SIBLING_IN_TREE':
ownerSubtreeLeafElementID = null;
- if (selectedElementIndex !== null) {
+ if (inspectedElementIndex !== null) {
const selectedElement = store.getElementAtIndex(
- ((selectedElementIndex: any): number),
+ ((inspectedElementIndex: any): number),
);
if (selectedElement !== null && selectedElement.parentID !== 0) {
const parent = store.getElementByID(selectedElement.parentID);
@@ -279,23 +271,23 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
selectedChildIndex < children.length - 1
? children[selectedChildIndex + 1]
: children[0];
- selectedElementIndex = store.getIndexOfElementID(nextChildID);
+ inspectedElementIndex = store.getIndexOfElementID(nextChildID);
}
}
}
break;
case 'SELECT_OWNER_LIST_NEXT_ELEMENT_IN_TREE':
- if (selectedElementIndex !== null) {
+ if (inspectedElementIndex !== null) {
if (
ownerSubtreeLeafElementID !== null &&
- ownerSubtreeLeafElementID !== selectedElementID
+ ownerSubtreeLeafElementID !== inspectedElementID
) {
const leafElement = store.getElementByID(ownerSubtreeLeafElementID);
if (leafElement !== null) {
let currentElement: null | Element = leafElement;
while (currentElement !== null) {
- if (currentElement.ownerID === selectedElementID) {
- selectedElementIndex = store.getIndexOfElementID(
+ if (currentElement.ownerID === inspectedElementID) {
+ inspectedElementIndex = store.getIndexOfElementID(
currentElement.id,
);
break;
@@ -308,23 +300,23 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
}
break;
case 'SELECT_OWNER_LIST_PREVIOUS_ELEMENT_IN_TREE':
- if (selectedElementIndex !== null) {
+ if (inspectedElementIndex !== null) {
if (ownerSubtreeLeafElementID === null) {
// If this is the first time we're stepping through the owners tree,
// pin the current component as the owners list leaf.
// This will enable us to step back down to this component.
- ownerSubtreeLeafElementID = selectedElementID;
+ ownerSubtreeLeafElementID = inspectedElementID;
}
const selectedElement = store.getElementAtIndex(
- ((selectedElementIndex: any): number),
+ ((inspectedElementIndex: any): number),
);
if (selectedElement !== null && selectedElement.ownerID !== 0) {
const ownerIndex = store.getIndexOfElementID(
selectedElement.ownerID,
);
if (ownerIndex !== null) {
- selectedElementIndex = ownerIndex;
+ inspectedElementIndex = ownerIndex;
}
}
}
@@ -332,16 +324,16 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
case 'SELECT_PARENT_ELEMENT_IN_TREE':
ownerSubtreeLeafElementID = null;
- if (selectedElementIndex !== null) {
+ if (inspectedElementIndex !== null) {
const selectedElement = store.getElementAtIndex(
- ((selectedElementIndex: any): number),
+ ((inspectedElementIndex: any): number),
);
if (selectedElement !== null && selectedElement.parentID !== 0) {
const parentIndex = store.getIndexOfElementID(
selectedElement.parentID,
);
if (parentIndex !== null) {
- selectedElementIndex = parentIndex;
+ inspectedElementIndex = parentIndex;
}
}
}
@@ -349,18 +341,18 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
case 'SELECT_PREVIOUS_ELEMENT_IN_TREE':
ownerSubtreeLeafElementID = null;
- if (selectedElementIndex === null || selectedElementIndex === 0) {
- selectedElementIndex = numElements - 1;
+ if (inspectedElementIndex === null || inspectedElementIndex === 0) {
+ inspectedElementIndex = numElements - 1;
} else {
- selectedElementIndex--;
+ inspectedElementIndex--;
}
break;
case 'SELECT_PREVIOUS_SIBLING_IN_TREE':
ownerSubtreeLeafElementID = null;
- if (selectedElementIndex !== null) {
+ if (inspectedElementIndex !== null) {
const selectedElement = store.getElementAtIndex(
- ((selectedElementIndex: any): number),
+ ((inspectedElementIndex: any): number),
);
if (selectedElement !== null && selectedElement.parentID !== 0) {
const parent = store.getElementByID(selectedElement.parentID);
@@ -371,7 +363,7 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
selectedChildIndex > 0
? children[selectedChildIndex - 1]
: children[children.length - 1];
- selectedElementIndex = store.getIndexOfElementID(nextChildID);
+ inspectedElementIndex = store.getIndexOfElementID(nextChildID);
}
}
}
@@ -384,7 +376,7 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
}
let flatIndex = 0;
- if (selectedElementIndex !== null) {
+ if (inspectedElementIndex !== null) {
// Resume from the current position in the list.
// Otherwise step to the previous item, relative to the current selection.
for (
@@ -393,7 +385,7 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
i--
) {
const {index} = elementIndicesWithErrorsOrWarnings[i];
- if (index >= selectedElementIndex) {
+ if (index >= inspectedElementIndex) {
flatIndex = i;
} else {
break;
@@ -407,12 +399,12 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
elementIndicesWithErrorsOrWarnings[
elementIndicesWithErrorsOrWarnings.length - 1
];
- selectedElementID = prevEntry.id;
- selectedElementIndex = prevEntry.index;
+ inspectedElementID = prevEntry.id;
+ inspectedElementIndex = prevEntry.index;
} else {
prevEntry = elementIndicesWithErrorsOrWarnings[flatIndex - 1];
- selectedElementID = prevEntry.id;
- selectedElementIndex = prevEntry.index;
+ inspectedElementID = prevEntry.id;
+ inspectedElementIndex = prevEntry.index;
}
lookupIDForIndex = false;
@@ -426,12 +418,12 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
}
let flatIndex = -1;
- if (selectedElementIndex !== null) {
+ if (inspectedElementIndex !== null) {
// Resume from the current position in the list.
// Otherwise step to the next item, relative to the current selection.
for (let i = 0; i < elementIndicesWithErrorsOrWarnings.length; i++) {
const {index} = elementIndicesWithErrorsOrWarnings[i];
- if (index <= selectedElementIndex) {
+ if (index <= inspectedElementIndex) {
flatIndex = i;
} else {
break;
@@ -442,12 +434,12 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
let nextEntry;
if (flatIndex >= elementIndicesWithErrorsOrWarnings.length - 1) {
nextEntry = elementIndicesWithErrorsOrWarnings[0];
- selectedElementID = nextEntry.id;
- selectedElementIndex = nextEntry.index;
+ inspectedElementID = nextEntry.id;
+ inspectedElementIndex = nextEntry.index;
} else {
nextEntry = elementIndicesWithErrorsOrWarnings[flatIndex + 1];
- selectedElementID = nextEntry.id;
- selectedElementIndex = nextEntry.index;
+ inspectedElementID = nextEntry.id;
+ inspectedElementIndex = nextEntry.index;
}
lookupIDForIndex = false;
@@ -460,12 +452,15 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
}
// Keep selected item ID and index in sync.
- if (lookupIDForIndex && selectedElementIndex !== state.selectedElementIndex) {
- if (selectedElementIndex === null) {
- selectedElementID = null;
+ if (
+ lookupIDForIndex &&
+ inspectedElementIndex !== state.inspectedElementIndex
+ ) {
+ if (inspectedElementIndex === null) {
+ inspectedElementID = null;
} else {
- selectedElementID = store.getElementIDAtIndex(
- ((selectedElementIndex: any): number),
+ inspectedElementID = store.getElementIDAtIndex(
+ ((inspectedElementIndex: any): number),
);
}
}
@@ -475,8 +470,8 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
numElements,
ownerSubtreeLeafElementID,
- selectedElementIndex,
- selectedElementID,
+ inspectedElementIndex,
+ inspectedElementID,
};
}
@@ -485,8 +480,8 @@ function reduceSearchState(store: Store, state: State, action: Action): State {
searchIndex,
searchResults,
searchText,
- selectedElementID,
- selectedElementIndex,
+ inspectedElementID,
+ inspectedElementIndex,
} = state;
const ownerID = state.ownerID;
@@ -594,11 +589,11 @@ function reduceSearchState(store: Store, state: State, action: Action): State {
});
if (searchResults.length > 0) {
if (prevSearchIndex === null) {
- if (selectedElementIndex !== null) {
+ if (inspectedElementIndex !== null) {
searchIndex = getNearestResultIndex(
store,
searchResults,
- selectedElementIndex,
+ inspectedElementIndex,
);
} else {
searchIndex = 0;
@@ -619,7 +614,7 @@ function reduceSearchState(store: Store, state: State, action: Action): State {
}
if (searchText !== prevSearchText) {
- const newSearchIndex = searchResults.indexOf(selectedElementID);
+ const newSearchIndex = searchResults.indexOf(inspectedElementID);
if (newSearchIndex === -1) {
// Only move the selection if the new query
// doesn't match the current selection anymore.
@@ -631,17 +626,17 @@ function reduceSearchState(store: Store, state: State, action: Action): State {
}
}
if (didRequestSearch && searchIndex !== null) {
- selectedElementID = ((searchResults[searchIndex]: any): number);
- selectedElementIndex = store.getIndexOfElementID(
- ((selectedElementID: any): number),
+ inspectedElementID = ((searchResults[searchIndex]: any): number);
+ inspectedElementIndex = store.getIndexOfElementID(
+ ((inspectedElementID: any): number),
);
}
return {
...state,
- selectedElementID,
- selectedElementIndex,
+ inspectedElementID,
+ inspectedElementIndex,
searchIndex,
searchResults,
@@ -652,14 +647,14 @@ function reduceSearchState(store: Store, state: State, action: Action): State {
function reduceOwnersState(store: Store, state: State, action: Action): State {
let {
numElements,
- selectedElementID,
- selectedElementIndex,
ownerID,
ownerFlatTree,
+ inspectedElementID,
+ inspectedElementIndex,
} = state;
const {searchIndex, searchResults, searchText} = state;
- let prevSelectedElementIndex = selectedElementIndex;
+ let prevInspectedElementIndex = inspectedElementIndex;
switch (action.type) {
case 'HANDLE_STORE_MUTATION':
@@ -667,75 +662,76 @@ function reduceOwnersState(store: Store, state: State, action: Action): State {
if (!store.containsElement(ownerID)) {
ownerID = null;
ownerFlatTree = null;
- selectedElementID = null;
+ prevInspectedElementIndex = null;
} else {
ownerFlatTree = store.getOwnersListForElement(ownerID);
- if (selectedElementID !== null) {
+ if (inspectedElementID !== null) {
// Mutation might have caused the index of this ID to shift.
- selectedElementIndex = ownerFlatTree.findIndex(
- element => element.id === selectedElementID,
+ prevInspectedElementIndex = ownerFlatTree.findIndex(
+ element => element.id === inspectedElementID,
);
}
}
} else {
- if (selectedElementID !== null) {
+ if (inspectedElementID !== null) {
// Mutation might have caused the index of this ID to shift.
- selectedElementIndex = store.getIndexOfElementID(selectedElementID);
+ inspectedElementIndex = store.getIndexOfElementID(inspectedElementID);
}
}
- if (selectedElementIndex === -1) {
+ if (inspectedElementIndex === -1) {
// If we couldn't find this ID after mutation, unselect it.
- selectedElementIndex = null;
- selectedElementID = null;
+ inspectedElementIndex = null;
+ inspectedElementID = null;
}
break;
case 'RESET_OWNER_STACK':
ownerID = null;
ownerFlatTree = null;
- selectedElementIndex =
- selectedElementID !== null
- ? store.getIndexOfElementID(selectedElementID)
+ inspectedElementIndex =
+ inspectedElementID !== null
+ ? store.getIndexOfElementID(inspectedElementID)
: null;
break;
case 'SELECT_ELEMENT_AT_INDEX':
if (ownerFlatTree !== null) {
- selectedElementIndex = (action: ACTION_SELECT_ELEMENT_AT_INDEX).payload;
+ inspectedElementIndex = (action: ACTION_SELECT_ELEMENT_AT_INDEX)
+ .payload;
}
break;
case 'SELECT_ELEMENT_BY_ID':
if (ownerFlatTree !== null) {
const payload = (action: ACTION_SELECT_ELEMENT_BY_ID).payload;
if (payload === null) {
- selectedElementIndex = null;
+ inspectedElementIndex = null;
} else {
- selectedElementIndex = ownerFlatTree.findIndex(
+ inspectedElementIndex = ownerFlatTree.findIndex(
element => element.id === payload,
);
// If the selected element is outside of the current owners list,
// exit the list and select the element in the main tree.
// This supports features like toggling Suspense.
- if (selectedElementIndex !== null && selectedElementIndex < 0) {
+ if (inspectedElementIndex !== null && inspectedElementIndex < 0) {
ownerID = null;
ownerFlatTree = null;
- selectedElementIndex = store.getIndexOfElementID(payload);
+ inspectedElementIndex = store.getIndexOfElementID(payload);
}
}
}
break;
case 'SELECT_NEXT_ELEMENT_IN_TREE':
if (ownerFlatTree !== null && ownerFlatTree.length > 0) {
- if (selectedElementIndex === null) {
- selectedElementIndex = 0;
- } else if (selectedElementIndex + 1 < ownerFlatTree.length) {
- selectedElementIndex++;
+ if (inspectedElementIndex === null) {
+ inspectedElementIndex = 0;
+ } else if (inspectedElementIndex + 1 < ownerFlatTree.length) {
+ inspectedElementIndex++;
}
}
break;
case 'SELECT_PREVIOUS_ELEMENT_IN_TREE':
if (ownerFlatTree !== null && ownerFlatTree.length > 0) {
- if (selectedElementIndex !== null && selectedElementIndex > 0) {
- selectedElementIndex--;
+ if (inspectedElementIndex !== null && inspectedElementIndex > 0) {
+ inspectedElementIndex--;
}
}
break;
@@ -747,8 +743,8 @@ function reduceOwnersState(store: Store, state: State, action: Action): State {
ownerFlatTree = store.getOwnersListForElement(ownerID);
// Always force reset selection to be the top of the new owner tree.
- selectedElementIndex = 0;
- prevSelectedElementIndex = null;
+ inspectedElementIndex = 0;
+ prevInspectedElementIndex = null;
}
break;
default:
@@ -769,12 +765,12 @@ function reduceOwnersState(store: Store, state: State, action: Action): State {
}
// Keep selected item ID and index in sync.
- if (selectedElementIndex !== prevSelectedElementIndex) {
- if (selectedElementIndex === null) {
- selectedElementID = null;
+ if (inspectedElementIndex !== prevInspectedElementIndex) {
+ if (inspectedElementIndex === null) {
+ inspectedElementID = null;
} else {
if (ownerFlatTree !== null) {
- selectedElementID = ownerFlatTree[selectedElementIndex].id;
+ inspectedElementID = ownerFlatTree[inspectedElementIndex].id;
}
}
}
@@ -783,8 +779,6 @@ function reduceOwnersState(store: Store, state: State, action: Action): State {
...state,
numElements,
- selectedElementID,
- selectedElementIndex,
searchIndex,
searchResults,
@@ -792,51 +786,28 @@ function reduceOwnersState(store: Store, state: State, action: Action): State {
ownerID,
ownerFlatTree,
- };
-}
-function reduceSuspenseState(
- store: Store,
- state: State,
- action: Action,
-): State {
- const {type} = action;
- switch (type) {
- case 'UPDATE_INSPECTED_ELEMENT_ID':
- if (state.inspectedElementID !== state.selectedElementID) {
- return {
- ...state,
- inspectedElementID: state.selectedElementID,
- };
- }
- break;
- default:
- break;
- }
-
- // React can bailout of no-op updates.
- return state;
+ inspectedElementID,
+ inspectedElementIndex,
+ };
}
type Props = {
children: React$Node,
// Used for automated testing
- defaultInspectedElementID?: ?number,
defaultOwnerID?: ?number,
- defaultSelectedElementID?: ?number,
- defaultSelectedElementIndex?: ?number,
+ defaultInspectedElementID?: ?number,
+ defaultInspectedElementIndex?: ?number,
};
// TODO Remove TreeContextController wrapper element once global Context.write API exists.
function TreeContextController({
children,
- defaultInspectedElementID,
defaultOwnerID,
- defaultSelectedElementID,
- defaultSelectedElementIndex,
+ defaultInspectedElementID,
+ defaultInspectedElementIndex,
}: Props): React.Node {
- const bridge = useContext(BridgeContext);
const store = useContext(StoreContext);
const initialRevision = useMemo(() => store.revision, [store]);
@@ -866,23 +837,22 @@ function TreeContextController({
case 'SELECT_PREVIOUS_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE':
case 'SELECT_PREVIOUS_SIBLING_IN_TREE':
case 'SELECT_OWNER':
- case 'UPDATE_INSPECTED_ELEMENT_ID':
case 'SET_SEARCH_TEXT':
state = reduceTreeState(store, state, action);
state = reduceSearchState(store, state, action);
state = reduceOwnersState(store, state, action);
- state = reduceSuspenseState(store, state, action);
+ // TODO(hoxyq): review
// If the selected ID is in a collapsed subtree, reset the selected index to null.
// We'll know the correct index after the layout effect will toggle the tree,
// and the store tree is mutated to account for that.
if (
- state.selectedElementID !== null &&
- store.isInsideCollapsedSubTree(state.selectedElementID)
+ state.inspectedElementID !== null &&
+ store.isInsideCollapsedSubTree(state.inspectedElementID)
) {
return {
...state,
- selectedElementIndex: null,
+ inspectedElementIndex: null,
};
}
@@ -898,10 +868,6 @@ function TreeContextController({
// Tree
numElements: store.numElements,
ownerSubtreeLeafElementID: null,
- selectedElementID:
- defaultSelectedElementID == null ? null : defaultSelectedElementID,
- selectedElementIndex:
- defaultSelectedElementIndex == null ? null : defaultSelectedElementIndex,
// Search
searchIndex: null,
@@ -914,42 +880,41 @@ function TreeContextController({
// Inspection element panel
inspectedElementID:
- defaultInspectedElementID == null ? null : defaultInspectedElementID,
+ defaultInspectedElementID != null
+ ? defaultInspectedElementID
+ : store.lastSelectedHostInstanceElementId,
+ inspectedElementIndex:
+ defaultInspectedElementIndex != null
+ ? defaultInspectedElementIndex
+ : store.lastSelectedHostInstanceElementId
+ ? store.getIndexOfElementID(store.lastSelectedHostInstanceElementId)
+ : null,
});
- const dispatchWrapper = useCallback(
- (action: Action) => {
- dispatch(action);
- startTransition(() => {
- dispatch({type: 'UPDATE_INSPECTED_ELEMENT_ID'});
- });
- },
- [dispatch],
- );
-
// Listen for host element selections.
useEffect(() => {
- const handleSelectElement = (id: number) =>
- dispatchWrapper({type: 'SELECT_ELEMENT_BY_ID', payload: id});
- bridge.addListener('selectElement', handleSelectElement);
- return () => bridge.removeListener('selectElement', handleSelectElement);
- }, [bridge, dispatchWrapper]);
+ const handler = (id: Element['id']) =>
+ dispatch({type: 'SELECT_ELEMENT_BY_ID', payload: id});
+
+ store.addListener('hostInstanceSelected', handler);
+ return () => store.removeListener('hostInstanceSelected', handler);
+ }, [store, dispatch]);
// If a newly-selected search result or inspection selection is inside of a collapsed subtree, auto expand it.
// This needs to be a layout effect to avoid temporarily flashing an incorrect selection.
- const prevSelectedElementID = useRef(null);
+ const prevInspectedElementID = useRef(null);
useLayoutEffect(() => {
- if (state.selectedElementID !== prevSelectedElementID.current) {
- prevSelectedElementID.current = state.selectedElementID;
+ if (state.inspectedElementID !== prevInspectedElementID.current) {
+ prevInspectedElementID.current = state.inspectedElementID;
- if (state.selectedElementID !== null) {
- const element = store.getElementByID(state.selectedElementID);
+ if (state.inspectedElementID !== null) {
+ const element = store.getElementByID(state.inspectedElementID);
if (element !== null && element.parentID > 0) {
store.toggleIsCollapsed(element.parentID, false);
}
}
}
- }, [state.selectedElementID, store]);
+ }, [state.inspectedElementID, store]);
// Mutations to the underlying tree may impact this context (e.g. search results, selection state).
useEffect(() => {
@@ -957,7 +922,7 @@ function TreeContextController({
Array,
Map,
]) => {
- dispatchWrapper({
+ dispatch({
type: 'HANDLE_STORE_MUTATION',
payload: [addedElementIDs, removedElementIDs],
});
@@ -968,20 +933,19 @@ function TreeContextController({
// At the moment, we can treat this as a mutation.
// We don't know which Elements were newly added/removed, but that should be okay in this case.
// It would only impact the search state, which is unlikely to exist yet at this point.
- dispatchWrapper({
+ dispatch({
type: 'HANDLE_STORE_MUTATION',
payload: [[], new Map()],
});
}
store.addListener('mutated', handleStoreMutated);
-
return () => store.removeListener('mutated', handleStoreMutated);
- }, [dispatchWrapper, initialRevision, store]);
+ }, [dispatch, initialRevision, store]);
return (
-
+
{children}
@@ -1020,11 +984,11 @@ function recursivelySearchTree(
function getNearestResultIndex(
store: Store,
searchResults: Array,
- selectedElementIndex: number,
+ inspectedElementIndex: number,
): number {
const index = searchResults.findIndex(id => {
const innerIndex = store.getIndexOfElementID(id);
- return innerIndex !== null && innerIndex >= selectedElementIndex;
+ return innerIndex !== null && innerIndex >= inspectedElementIndex;
});
return index === -1 ? 0 : index;
diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/ProfilerContext.js b/packages/react-devtools-shared/src/devtools/views/Profiler/ProfilerContext.js
index 1ef7bb2b7e5c7..38203175136b0 100644
--- a/packages/react-devtools-shared/src/devtools/views/Profiler/ProfilerContext.js
+++ b/packages/react-devtools-shared/src/devtools/views/Profiler/ProfilerContext.js
@@ -88,7 +88,7 @@ type Props = {
function ProfilerContextController({children}: Props): React.Node {
const store = useContext(StoreContext);
- const {selectedElementID} = useContext(TreeStateContext);
+ const {inspectedElementID} = useContext(TreeStateContext);
const dispatch = useContext(TreeDispatcherContext);
const {profilerStore} = store;
@@ -176,9 +176,9 @@ function ProfilerContextController({children}: Props): React.Node {
if (rootID === null || !dataForRoots.has(rootID)) {
let selectedElementRootID = null;
- if (selectedElementID !== null) {
+ if (inspectedElementID !== null) {
selectedElementRootID =
- store.getRootIDForElement(selectedElementID);
+ store.getRootIDForElement(inspectedElementID);
}
if (
selectedElementRootID !== null &&
diff --git a/packages/react-devtools-shared/src/devtools/views/Settings/GeneralSettings.js b/packages/react-devtools-shared/src/devtools/views/Settings/GeneralSettings.js
index 69f4ec737581a..d56f32f81142c 100644
--- a/packages/react-devtools-shared/src/devtools/views/Settings/GeneralSettings.js
+++ b/packages/react-devtools-shared/src/devtools/views/Settings/GeneralSettings.js
@@ -34,10 +34,8 @@ export default function GeneralSettings(_: {}): React.Node {
setDisplayDensity,
setTheme,
setTraceUpdatesEnabled,
- setShowNamesWhenTracing,
theme,
traceUpdatesEnabled,
- showNamesWhenTracing,
} = useContext(SettingsContext);
const {backendVersion, supportsTraceUpdates} = useContext(StoreContext);
@@ -85,19 +83,6 @@ export default function GeneralSettings(_: {}): React.Node {
/>{' '}
Highlight updates when components render.
-
-
-
)}
diff --git a/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js b/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js
index ec7b3ba9c9da4..196ea806f6aac 100644
--- a/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js
+++ b/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js
@@ -21,7 +21,6 @@ import {
LOCAL_STORAGE_BROWSER_THEME,
LOCAL_STORAGE_PARSE_HOOK_NAMES_KEY,
LOCAL_STORAGE_TRACE_UPDATES_ENABLED_KEY,
- LOCAL_STORAGE_SHOW_NAMES_WHEN_TRACING_KEY,
} from 'react-devtools-shared/src/constants';
import {
COMFORTABLE_LINE_HEIGHT,
@@ -54,9 +53,6 @@ type Context = {
traceUpdatesEnabled: boolean,
setTraceUpdatesEnabled: (value: boolean) => void,
-
- showNamesWhenTracing: boolean,
- setShowNamesWhenTracing: (showNames: boolean) => void,
};
const SettingsContext: ReactContext
= createContext(
@@ -115,11 +111,6 @@ function SettingsContextController({
LOCAL_STORAGE_TRACE_UPDATES_ENABLED_KEY,
false,
);
- const [showNamesWhenTracing, setShowNamesWhenTracing] =
- useLocalStorageWithLog(
- LOCAL_STORAGE_SHOW_NAMES_WHEN_TRACING_KEY,
- true,
- );
const documentElements = useMemo(() => {
const array: Array = [
@@ -173,10 +164,6 @@ function SettingsContextController({
bridge.send('setTraceUpdatesEnabled', traceUpdatesEnabled);
}, [bridge, traceUpdatesEnabled]);
- useEffect(() => {
- bridge.send('setShowNamesWhenTracing', showNamesWhenTracing);
- }, [bridge, showNamesWhenTracing]);
-
const value: Context = useMemo(
() => ({
displayDensity,
@@ -192,8 +179,6 @@ function SettingsContextController({
theme,
browserTheme,
traceUpdatesEnabled,
- showNamesWhenTracing,
- setShowNamesWhenTracing,
}),
[
displayDensity,
@@ -205,7 +190,6 @@ function SettingsContextController({
theme,
browserTheme,
traceUpdatesEnabled,
- showNamesWhenTracing,
],
);
diff --git a/packages/react-devtools-shared/src/frontend/types.js b/packages/react-devtools-shared/src/frontend/types.js
index 6216283301bf5..302b168bd6eb0 100644
--- a/packages/react-devtools-shared/src/frontend/types.js
+++ b/packages/react-devtools-shared/src/frontend/types.js
@@ -49,6 +49,7 @@ export const ElementTypeSuspense = 12;
export const ElementTypeSuspenseList = 13;
export const ElementTypeTracingMarker = 14;
export const ElementTypeVirtual = 15;
+export const ElementTypeViewTransition = 16;
// Different types of elements displayed in the Elements tree.
// These types may be used to visually distinguish types,
@@ -66,7 +67,8 @@ export type ElementType =
| 12
| 13
| 14
- | 15;
+ | 15
+ | 16;
// WARNING
// The values below are referenced by ComponentFilters (which are saved via localStorage).
diff --git a/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js b/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
index 8b17db1dc38a1..c9dbcdb68c50f 100644
--- a/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
+++ b/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
@@ -1198,6 +1198,13 @@ export function hasInstanceAffectedParent(
return oldRect.height !== newRect.height || oldRect.width !== newRect.width;
}
+// How long to wait for new fonts to load before just committing anyway.
+// This freezes the screen. It needs to be short enough that it doesn't cause too much of
+// an issue when it's a new load and slow, yet long enough that you have a chance to load
+// it. Otherwise we wait for no reason. The assumption here is that you likely have
+// either cached the font or preloaded it earlier.
+const SUSPENSEY_FONT_TIMEOUT = 500;
+
export function startViewTransition(
rootContainer: Container,
mutationCallback: () => void,
@@ -1220,8 +1227,34 @@ export function startViewTransition(
const ownerWindow = ownerDocument.defaultView;
const pendingNavigation =
ownerWindow.navigation && ownerWindow.navigation.transition;
+ // $FlowFixMe[prop-missing]
+ const previousFontLoadingStatus = ownerDocument.fonts.status;
mutationCallback();
- // TODO: Wait for fonts.
+ if (previousFontLoadingStatus === 'loaded') {
+ // Force layout calculation to trigger font loading.
+ // eslint-disable-next-line ft-flow/no-unused-expressions
+ (ownerDocument.documentElement: any).clientHeight;
+ if (
+ // $FlowFixMe[prop-missing]
+ ownerDocument.fonts.status === 'loading'
+ ) {
+ // The mutation lead to new fonts being loaded. We should wait on them before continuing.
+ // This avoids waiting for potentially unrelated fonts that were already loading before.
+ // Either in an earlier transition or as part of a sync optimistic state. This doesn't
+ // include preloads that happened earlier.
+ const fontsReady = Promise.race([
+ // $FlowFixMe[prop-missing]
+ ownerDocument.fonts.ready,
+ new Promise(resolve =>
+ setTimeout(resolve, SUSPENSEY_FONT_TIMEOUT),
+ ),
+ ]).then(layoutCallback, layoutCallback);
+ const allReady = pendingNavigation
+ ? Promise.allSettled([pendingNavigation.finished, fontsReady])
+ : fontsReady;
+ return allReady.then(afterMutationCallback, afterMutationCallback);
+ }
+ }
layoutCallback();
if (pendingNavigation) {
return pendingNavigation.finished.then(
diff --git a/packages/react-native-renderer/src/ReactFabric.js b/packages/react-native-renderer/src/ReactFabric.js
index bd50d1a317896..67382f5f00d13 100644
--- a/packages/react-native-renderer/src/ReactFabric.js
+++ b/packages/react-native-renderer/src/ReactFabric.js
@@ -29,7 +29,6 @@ import {
import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';
import {setBatchingImplementation} from './legacy-events/ReactGenericBatching';
-import {getInspectorDataForInstance} from './ReactNativeFiberInspector';
import {LegacyRoot, ConcurrentRoot} from 'react-reconciler/src/ReactRootTags';
import {
findHostInstance_DEPRECATED,
@@ -188,9 +187,6 @@ export {
unmountComponentAtNode,
stopSurface,
createPortal,
- // This export is typically undefined in production builds.
- // See the "enableGetInspectorDataForInstanceInProduction" flag.
- getInspectorDataForInstance,
// The public instance has a reference to the internal instance handle.
// This method allows it to acess the most recent shadow node for
// the instance (it's only accessible through it).
diff --git a/packages/react-native-renderer/src/ReactNativeFiberInspector.js b/packages/react-native-renderer/src/ReactNativeFiberInspector.js
index d0423f1d48cfa..47d588d448a18 100644
--- a/packages/react-native-renderer/src/ReactNativeFiberInspector.js
+++ b/packages/react-native-renderer/src/ReactNativeFiberInspector.js
@@ -21,7 +21,6 @@ import {
UIManager,
getNodeFromPublicInstance,
} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
-import {enableGetInspectorDataForInstanceInProduction} from 'shared/ReactFeatureFlags';
import {getClosestInstanceFromNode} from './ReactNativeComponentTree';
import {
getNodeFromInternalInstanceHandle,
@@ -29,39 +28,40 @@ import {
} from './ReactNativePublicCompat';
import {getStackByFiberInDevAndProd} from 'react-reconciler/src/ReactFiberComponentStack';
-const emptyObject = {};
+let getInspectorDataForInstance: (
+ closestInstance: Fiber | null,
+) => InspectorData;
+
if (__DEV__) {
- Object.freeze(emptyObject);
-}
+ const emptyObject = Object.freeze({});
-// $FlowFixMe[missing-local-annot]
-function createHierarchy(fiberHierarchy) {
- return fiberHierarchy.map(fiber => ({
- name: getComponentNameFromType(fiber.type),
- getInspectorData: () => {
- return {
- props: getHostProps(fiber),
- measure: callback => {
- // If this is Fabric, we'll find a shadow node and use that to measure.
- const hostFiber = findCurrentHostFiber(fiber);
- const node =
- hostFiber != null &&
- hostFiber.stateNode !== null &&
- hostFiber.stateNode.node;
+ // $FlowFixMe[missing-local-annot]
+ const createHierarchy = function (fiberHierarchy) {
+ return fiberHierarchy.map(fiber => ({
+ name: getComponentNameFromType(fiber.type),
+ getInspectorData: () => {
+ return {
+ props: getHostProps(fiber),
+ measure: callback => {
+ // If this is Fabric, we'll find a shadow node and use that to measure.
+ const hostFiber = findCurrentHostFiber(fiber);
+ const node =
+ hostFiber != null &&
+ hostFiber.stateNode !== null &&
+ hostFiber.stateNode.node;
- if (node) {
- nativeFabricUIManager.measure(node, callback);
- } else {
- return UIManager.measure(getHostNode(fiber), callback);
- }
- },
- };
- },
- }));
-}
+ if (node) {
+ nativeFabricUIManager.measure(node, callback);
+ } else {
+ return UIManager.measure(getHostNode(fiber), callback);
+ }
+ },
+ };
+ },
+ }));
+ };
-function getHostNode(fiber: Fiber | null) {
- if (__DEV__ || enableGetInspectorDataForInstanceInProduction) {
+ const getHostNode = function (fiber: Fiber | null) {
let hostNode;
// look for children first for the hostNode
// as composite fibers do not have a hostNode
@@ -75,22 +75,19 @@ function getHostNode(fiber: Fiber | null) {
fiber = fiber.child;
}
return null;
- }
-}
+ };
-// $FlowFixMe[missing-local-annot]
-function getHostProps(fiber) {
- const host = findCurrentHostFiber(fiber);
- if (host) {
- return host.memoizedProps || emptyObject;
- }
- return emptyObject;
-}
+ const getHostProps = function (fiber: Fiber) {
+ const host = findCurrentHostFiber(fiber);
+ if (host) {
+ return host.memoizedProps || emptyObject;
+ }
+ return emptyObject;
+ };
-function getInspectorDataForInstance(
- closestInstance: Fiber | null,
-): InspectorData {
- if (__DEV__ || enableGetInspectorDataForInstanceInProduction) {
+ getInspectorDataForInstance = function (
+ closestInstance: Fiber | null,
+ ): InspectorData {
// Handle case where user clicks outside of ReactNative
if (!closestInstance) {
return {
@@ -125,36 +122,30 @@ function getInspectorDataForInstance(
selectedIndex,
componentStack,
};
- }
+ };
- throw new Error(
- 'getInspectorDataForInstance() is not available in production',
- );
-}
-
-function getOwnerHierarchy(instance: Fiber) {
- const hierarchy: Array<$FlowFixMe> = [];
- traverseOwnerTreeUp(hierarchy, instance);
- return hierarchy;
-}
+ const getOwnerHierarchy = function (instance: Fiber) {
+ const hierarchy: Array<$FlowFixMe> = [];
+ traverseOwnerTreeUp(hierarchy, instance);
+ return hierarchy;
+ };
-// $FlowFixMe[missing-local-annot]
-function lastNonHostInstance(hierarchy) {
- for (let i = hierarchy.length - 1; i > 1; i--) {
- const instance = hierarchy[i];
+ // $FlowFixMe[missing-local-annot]
+ const lastNonHostInstance = function (hierarchy) {
+ for (let i = hierarchy.length - 1; i > 1; i--) {
+ const instance = hierarchy[i];
- if (instance.tag !== HostComponent) {
- return instance;
+ if (instance.tag !== HostComponent) {
+ return instance;
+ }
}
- }
- return hierarchy[0];
-}
+ return hierarchy[0];
+ };
-function traverseOwnerTreeUp(
- hierarchy: Array<$FlowFixMe>,
- instance: Fiber,
-): void {
- if (__DEV__ || enableGetInspectorDataForInstanceInProduction) {
+ const traverseOwnerTreeUp = function (
+ hierarchy: Array<$FlowFixMe>,
+ instance: Fiber,
+ ): void {
hierarchy.unshift(instance);
const owner = instance._debugOwner;
if (owner != null && typeof owner.tag === 'number') {
@@ -162,13 +153,12 @@ function traverseOwnerTreeUp(
} else {
// TODO: Traverse Server Components owners.
}
- }
+ };
}
function getInspectorDataForViewTag(viewTag: number): InspectorData {
if (__DEV__) {
const closestInstance = getClosestInstanceFromNode(viewTag);
-
return getInspectorDataForInstance(closestInstance);
} else {
throw new Error(
diff --git a/packages/react-native-renderer/src/ReactNativeRenderer.js b/packages/react-native-renderer/src/ReactNativeRenderer.js
index 7f959184c95ef..a1a4825393dde 100644
--- a/packages/react-native-renderer/src/ReactNativeRenderer.js
+++ b/packages/react-native-renderer/src/ReactNativeRenderer.js
@@ -34,7 +34,6 @@ import {
// Modules provided by RN:
import {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
-import {getInspectorDataForInstance} from './ReactNativeFiberInspector';
import {LegacyRoot} from 'react-reconciler/src/ReactRootTags';
import {
findHostInstance_DEPRECATED,
@@ -206,9 +205,6 @@ export {
unmountComponentAtNodeAndRemoveContainer,
createPortal,
batchedUpdates as unstable_batchedUpdates,
- // This export is typically undefined in production builds.
- // See the "enableGetInspectorDataForInstanceInProduction" flag.
- getInspectorDataForInstance,
// DEV-only:
isChildPublicInstance,
};
diff --git a/packages/react-reconciler/src/ReactFiberComponentStack.js b/packages/react-reconciler/src/ReactFiberComponentStack.js
index ac2cdf20a4cd6..8385cbf63e74a 100644
--- a/packages/react-reconciler/src/ReactFiberComponentStack.js
+++ b/packages/react-reconciler/src/ReactFiberComponentStack.js
@@ -7,7 +7,10 @@
* @flow
*/
-import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
+import {
+ enableOwnerStacks,
+ enableViewTransition,
+} from 'shared/ReactFeatureFlags';
import type {Fiber} from './ReactInternalTypes';
import type {ReactComponentInfo} from 'shared/ReactTypes';
@@ -23,6 +26,7 @@ import {
SimpleMemoComponent,
ClassComponent,
HostText,
+ ViewTransitionComponent,
} from './ReactWorkTags';
import {
describeBuiltInComponentFrame,
@@ -52,6 +56,11 @@ function describeFiber(fiber: Fiber): string {
return describeFunctionComponentFrame(fiber.type.render);
case ClassComponent:
return describeClassComponentFrame(fiber.type);
+ case ViewTransitionComponent:
+ if (enableViewTransition) {
+ return describeBuiltInComponentFrame('ViewTransition');
+ }
+ // Fallthrough
default:
return '';
}
@@ -123,6 +132,12 @@ export function getOwnerStackByFiberInDev(workInProgress: Fiber): string {
case SuspenseListComponent:
info += describeBuiltInComponentFrame('SuspenseList');
break;
+ case ViewTransitionComponent:
+ if (enableViewTransition) {
+ info += describeBuiltInComponentFrame('SuspenseList');
+ break;
+ }
+ // Fallthrough
case FunctionComponent:
case SimpleMemoComponent:
case ClassComponent:
diff --git a/packages/react-reconciler/src/getComponentNameFromFiber.js b/packages/react-reconciler/src/getComponentNameFromFiber.js
index cac247f26912b..04ad072c2583f 100644
--- a/packages/react-reconciler/src/getComponentNameFromFiber.js
+++ b/packages/react-reconciler/src/getComponentNameFromFiber.js
@@ -14,6 +14,7 @@ import {
disableLegacyMode,
enableLegacyHidden,
enableRenderableContext,
+ enableViewTransition,
} from 'shared/ReactFeatureFlags';
import {
@@ -45,6 +46,7 @@ import {
CacheComponent,
TracingMarkerComponent,
Throw,
+ ViewTransitionComponent,
} from 'react-reconciler/src/ReactWorkTags';
import getComponentNameFromType from 'shared/getComponentNameFromType';
import {REACT_STRICT_MODE_TYPE} from 'shared/ReactSymbols';
@@ -139,7 +141,12 @@ export default function getComponentNameFromFiber(fiber: Fiber): string | null {
return 'SuspenseList';
case TracingMarkerComponent:
return 'TracingMarker';
+ case ViewTransitionComponent:
+ if (enableViewTransition) {
+ return 'ViewTransition';
+ }
// The display name for these tags come from the user-provided type:
+ // Fallthrough
case IncompleteClassComponent:
case IncompleteFunctionComponent:
if (disableLegacyMode) {
diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js
index bebb275e1ba62..bc1ae542fa6e1 100644
--- a/packages/shared/ReactFeatureFlags.js
+++ b/packages/shared/ReactFeatureFlags.js
@@ -260,6 +260,4 @@ export const enableAsyncDebugInfo = __EXPERIMENTAL__;
export const enableUpdaterTracking = __PROFILE__;
// Internal only.
-export const enableGetInspectorDataForInstanceInProduction = false;
-
export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js
index f3551ed658a44..7a01d9c9281db 100644
--- a/packages/shared/forks/ReactFeatureFlags.native-fb.js
+++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js
@@ -48,7 +48,6 @@ export const enableCreateEventHandleAPI = false;
export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
export const enableMoveBefore = true;
export const enableFizzExternalRuntime = true;
-export const enableGetInspectorDataForInstanceInProduction = true;
export const enableHalt = false;
export const enableInfiniteRenderLoopDetection = false;
export const enableLegacyCache = false;
diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js
index 11e20133950f3..26e05087c61db 100644
--- a/packages/shared/forks/ReactFeatureFlags.native-oss.js
+++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js
@@ -33,7 +33,6 @@ export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
export const enableFabricCompleteRootInCommitPhase = false;
export const enableMoveBefore = true;
export const enableFizzExternalRuntime = true;
-export const enableGetInspectorDataForInstanceInProduction = false;
export const enableHalt = false;
export const enableHiddenSubtreeInsertionEffectCleanup = false;
export const enableInfiniteRenderLoopDetection = false;
diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js
index f878cdc5601b6..7e11aceaf7806 100644
--- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js
+++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js
@@ -36,7 +36,6 @@ export const enableUseEffectEventHook = false;
export const favorSafetyOverHydrationPerf = true;
export const enableLegacyFBSupport = false;
export const enableMoveBefore = false;
-export const enableGetInspectorDataForInstanceInProduction = false;
export const enableFabricCompleteRootInCommitPhase = false;
export const enableHiddenSubtreeInsertionEffectCleanup = false;
export const enableHydrationLaneScheduling = true;
diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js
index a75174692c525..72731529b17a3 100644
--- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js
+++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js
@@ -27,7 +27,6 @@ export const enableCreateEventHandleAPI = false;
export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
export const enableMoveBefore = false;
export const enableFizzExternalRuntime = true;
-export const enableGetInspectorDataForInstanceInProduction = false;
export const enableHalt = false;
export const enableInfiniteRenderLoopDetection = false;
export const enableHiddenSubtreeInsertionEffectCleanup = true;
diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
index e25c011828603..bfd3316019bde 100644
--- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
+++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
@@ -38,7 +38,6 @@ export const enableUseEffectEventHook = false;
export const favorSafetyOverHydrationPerf = true;
export const enableLegacyFBSupport = false;
export const enableMoveBefore = false;
-export const enableGetInspectorDataForInstanceInProduction = false;
export const enableRenderableContext = false;
export const enableFabricCompleteRootInCommitPhase = false;
export const enableHiddenSubtreeInsertionEffectCleanup = true;
diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js
index a55cec676c37a..b317fca356c92 100644
--- a/packages/shared/forks/ReactFeatureFlags.www.js
+++ b/packages/shared/forks/ReactFeatureFlags.www.js
@@ -69,7 +69,6 @@ export const enableSchedulingProfiler: boolean =
__PROFILE__ && dynamicFeatureFlags.enableSchedulingProfiler;
export const disableLegacyContext = __EXPERIMENTAL__;
-export const enableGetInspectorDataForInstanceInProduction = false;
export const enableLegacyCache = true;