Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: use versioned render in profilingCommitTreeBuilder test and gate some for legacy rendering #28236

Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,35 @@

import type Store from 'react-devtools-shared/src/devtools/store';

import {
getLegacyRenderImplementation,
getModernRenderImplementation,
} from './utils';

describe('commit tree', () => {
let React;
let ReactDOMClient;
let Scheduler;
let legacyRender;
let store: Store;
let utils;

beforeEach(() => {
utils = require('./utils');
utils.beforeEachProfiling();

legacyRender = utils.legacyRender;

store = global.store;
store.collapseNodesByDefault = false;
store.recordChangeDescriptions = true;

React = require('react');
ReactDOMClient = require('react-dom/client');
Scheduler = require('scheduler');
});

const {render: legacyRender} = getLegacyRenderImplementation();
const {render: modernRender} = getModernRenderImplementation();

// @reactVersion >= 16.9
it('should be able to rebuild the store tree for each commit', () => {
// @reactVersion <= 18.2
it('should be able to rebuild the store tree for each commit (legacy render)', () => {
const Parent = ({count}) => {
Scheduler.unstable_advanceTime(10);
return new Array(count)
Expand All @@ -45,31 +49,88 @@ describe('commit tree', () => {
return null;
});

const container = document.createElement('div');
utils.act(() => store.profilerStore.startProfiling());
utils.act(() => legacyRender(<Parent count={1} />));
expect(store).toMatchInlineSnapshot(`
[root]
▾ <Parent>
<Child key="0"> [Memo]
`);
utils.act(() => legacyRender(<Parent count={3} />));
expect(store).toMatchInlineSnapshot(`
[root]
▾ <Parent>
<Child key="0"> [Memo]
<Child key="1"> [Memo]
<Child key="2"> [Memo]
`);
utils.act(() => legacyRender(<Parent count={2} />));
expect(store).toMatchInlineSnapshot(`
[root]
▾ <Parent>
<Child key="0"> [Memo]
<Child key="1"> [Memo]
`);
utils.act(() => legacyRender(<Parent count={0} />));
expect(store).toMatchInlineSnapshot(`
[root]
<Parent>
`);
utils.act(() => store.profilerStore.stopProfiling());

const rootID = store.roots[0];
const commitTrees = [];
for (let commitIndex = 0; commitIndex < 4; commitIndex++) {
commitTrees.push(
store.profilerStore.profilingCache.getCommitTree({
commitIndex,
rootID,
}),
);
}

expect(commitTrees[0].nodes.size).toBe(3); // <Root> + <Parent> + <Child>
expect(commitTrees[1].nodes.size).toBe(5); // <Root> + <Parent> + <Child> x 3
expect(commitTrees[2].nodes.size).toBe(4); // <Root> + <Parent> + <Child> x 2
expect(commitTrees[3].nodes.size).toBe(2); // <Root> + <Parent>
});

// @reactVersion >= 18
it('should be able to rebuild the store tree for each commit (createRoot)', () => {
const Parent = ({count}) => {
Scheduler.unstable_advanceTime(10);
return new Array(count)
.fill(true)
.map((_, index) => <Child key={index} />);
};
const Child = React.memo(function Child() {
Scheduler.unstable_advanceTime(2);
return null;
});

utils.act(() => store.profilerStore.startProfiling());
utils.act(() => legacyRender(<Parent count={1} />, container));
utils.act(() => modernRender(<Parent count={1} />));
expect(store).toMatchInlineSnapshot(`
[root]
▾ <Parent>
<Child key="0"> [Memo]
`);
utils.act(() => legacyRender(<Parent count={3} />, container));
utils.act(() => modernRender(<Parent count={3} />));
expect(store).toMatchInlineSnapshot(`
[root]
▾ <Parent>
<Child key="0"> [Memo]
<Child key="1"> [Memo]
<Child key="2"> [Memo]
`);
utils.act(() => legacyRender(<Parent count={2} />, container));
utils.act(() => modernRender(<Parent count={2} />));
expect(store).toMatchInlineSnapshot(`
[root]
▾ <Parent>
<Child key="0"> [Memo]
<Child key="1"> [Memo]
`);
utils.act(() => legacyRender(<Parent count={0} />, container));
utils.act(() => modernRender(<Parent count={0} />));
expect(store).toMatchInlineSnapshot(`
[root]
<Parent>
Expand Down Expand Up @@ -118,25 +179,24 @@ describe('commit tree', () => {
});

// @reactVersion >= 16.9
// @reactVersion <= 18.2
it('should support Lazy components (legacy render)', async () => {
const container = document.createElement('div');

utils.act(() => store.profilerStore.startProfiling());
utils.act(() => legacyRender(<App renderChildren={true} />, container));
utils.act(() => legacyRender(<App renderChildren={true} />));
await Promise.resolve();
expect(store).toMatchInlineSnapshot(`
[root]
▾ <App>
<Suspense>
`);
utils.act(() => legacyRender(<App renderChildren={true} />, container));
utils.act(() => legacyRender(<App renderChildren={true} />));
expect(store).toMatchInlineSnapshot(`
[root]
▾ <App>
▾ <Suspense>
<LazyInnerComponent>
`);
utils.act(() => legacyRender(<App renderChildren={false} />, container));
utils.act(() => legacyRender(<App renderChildren={false} />));
expect(store).toMatchInlineSnapshot(`
[root]
<App>
Expand All @@ -161,25 +221,22 @@ describe('commit tree', () => {

// @reactVersion >= 18.0
it('should support Lazy components (createRoot)', async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);

utils.act(() => store.profilerStore.startProfiling());
utils.act(() => root.render(<App renderChildren={true} />));
utils.act(() => modernRender(<App renderChildren={true} />));
await Promise.resolve();
expect(store).toMatchInlineSnapshot(`
[root]
▾ <App>
<Suspense>
`);
utils.act(() => root.render(<App renderChildren={true} />));
utils.act(() => modernRender(<App renderChildren={true} />));
expect(store).toMatchInlineSnapshot(`
[root]
▾ <App>
▾ <Suspense>
<LazyInnerComponent>
`);
utils.act(() => root.render(<App renderChildren={false} />));
utils.act(() => modernRender(<App renderChildren={false} />));
expect(store).toMatchInlineSnapshot(`
[root]
<App>
Expand All @@ -203,17 +260,16 @@ describe('commit tree', () => {
});

// @reactVersion >= 16.9
// @reactVersion <= 18.2
it('should support Lazy components that are unmounted before resolving (legacy render)', async () => {
const container = document.createElement('div');

utils.act(() => store.profilerStore.startProfiling());
utils.act(() => legacyRender(<App renderChildren={true} />, container));
utils.act(() => legacyRender(<App renderChildren={true} />));
expect(store).toMatchInlineSnapshot(`
[root]
▾ <App>
<Suspense>
`);
utils.act(() => legacyRender(<App renderChildren={false} />, container));
utils.act(() => legacyRender(<App renderChildren={false} />));
expect(store).toMatchInlineSnapshot(`
[root]
<App>
Expand All @@ -237,17 +293,14 @@ describe('commit tree', () => {

// @reactVersion >= 18.0
it('should support Lazy components that are unmounted before resolving (createRoot)', async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);

utils.act(() => store.profilerStore.startProfiling());
utils.act(() => root.render(<App renderChildren={true} />));
utils.act(() => modernRender(<App renderChildren={true} />));
expect(store).toMatchInlineSnapshot(`
[root]
▾ <App>
<Suspense>
`);
utils.act(() => root.render(<App renderChildren={false} />));
utils.act(() => modernRender(<App renderChildren={false} />));
expect(store).toMatchInlineSnapshot(`
[root]
<App>
Expand Down
5 changes: 4 additions & 1 deletion packages/react-devtools-shared/src/__tests__/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ export function getModernRenderImplementation(): RenderImplementation {
});

function render(elements) {
if (root == null) {
root = ReactDOMClient.createRoot(container);
}
root.render(elements);

return unmount;
Expand All @@ -195,7 +198,7 @@ export function getModernRenderImplementation(): RenderImplementation {
container = document.createElement('div');
document.body.appendChild(container);

root = ReactDOMClient.createRoot(container);
root = null;

containersToRemove.push(container);
}
Expand Down