[DevTools] Reorder moved filtered Fibers with backing DevToolsInstance (#34104)

Instead, we just continue to collect the unfiltered children.

---------

Co-authored-by: Sebastian Sebbie Silbermann <sebastian.silbermann@vercel.com>
This commit is contained in:
Sebastian Markbåge 2025-08-05 12:39:45 -04:00 committed by GitHub
parent 7deda941f7
commit 99fd4f2ac1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 80 additions and 0 deletions

View File

@ -17,8 +17,10 @@ describe('Store', () => {
let act;
let actAsync;
let bridge;
let createDisplayNameFilter;
let getRendererID;
let legacyRender;
let previousComponentFilters;
let store;
let withErrorsOrWarningsIgnored;
@ -29,6 +31,8 @@ describe('Store', () => {
bridge = global.bridge;
store = global.store;
previousComponentFilters = store.componentFilters;
React = require('react');
ReactDOM = require('react-dom');
ReactDOMClient = require('react-dom/client');
@ -38,9 +42,14 @@ describe('Store', () => {
actAsync = utils.actAsync;
getRendererID = utils.getRendererID;
legacyRender = utils.legacyRender;
createDisplayNameFilter = utils.createDisplayNameFilter;
withErrorsOrWarningsIgnored = utils.withErrorsOrWarningsIgnored;
});
afterEach(() => {
store.componentFilters = previousComponentFilters;
});
const {render, unmount, createContainer} = getVersionedRenderImplementation();
// @reactVersion >= 18.0
@ -129,6 +138,72 @@ describe('Store', () => {
`);
});
it('should handle reorder of filtered elements', async () => {
function IgnoreMePassthrough({children}) {
return children;
}
function PassThrough({children}) {
return children;
}
await actAsync(
async () =>
(store.componentFilters = [createDisplayNameFilter('^IgnoreMe', true)]),
);
await act(() => {
render(
<PassThrough key="e" name="e">
<IgnoreMePassthrough key="e1">
<PassThrough name="e-child-one">
<p>e1</p>
</PassThrough>
</IgnoreMePassthrough>
<IgnoreMePassthrough key="e2">
<PassThrough name="e-child-two">
<div>e2</div>
</PassThrough>
</IgnoreMePassthrough>
</PassThrough>,
);
});
expect(store).toMatchInlineSnapshot(`
[root]
<PassThrough key="e">
<PassThrough>
<p>
<PassThrough>
<div>
`);
await act(() => {
render(
<PassThrough key="e" name="e">
<IgnoreMePassthrough key="e2">
<PassThrough name="e-child-two">
<div>e2</div>
</PassThrough>
</IgnoreMePassthrough>
<IgnoreMePassthrough key="e1">
<PassThrough name="e-child-one">
<p>e1</p>
</PassThrough>
</IgnoreMePassthrough>
</PassThrough>,
);
});
expect(store).toMatchInlineSnapshot(`
[root]
<PassThrough key="e">
<PassThrough>
<div>
<PassThrough>
<p>
`);
});
describe('StrictMode compliance', () => {
it('should mark strict root elements as strict', async () => {
const App = () => <Component />;

View File

@ -3612,6 +3612,11 @@ export function attach(
shouldResetChildren = true;
}
} else if (prevChild !== null && shouldFilterFiber(nextChild)) {
// The filtered instance could've reordered.
if (prevChild !== prevChildAtSameIndex) {
shouldResetChildren = true;
}
// If this Fiber should be filtered, we need to still update its children.
// This relies on an alternate since we don't have an Instance with the previous
// child on it. Ideally, the reconciliation wouldn't need previous Fibers that