mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +01:00
[DevTools] Send Suspense rects to frontend (#34170)
This commit is contained in:
parent
ac7820a99e
commit
de06211dbe
|
|
@ -228,6 +228,8 @@ describe('commit tree', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <App>
|
▾ <App>
|
||||||
<Suspense>
|
<Suspense>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="App>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
utils.act(() => modernRender(<App renderChildren={true} />));
|
utils.act(() => modernRender(<App renderChildren={true} />));
|
||||||
expect(store).toMatchInlineSnapshot(`
|
expect(store).toMatchInlineSnapshot(`
|
||||||
|
|
@ -235,6 +237,8 @@ describe('commit tree', () => {
|
||||||
▾ <App>
|
▾ <App>
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<LazyInnerComponent>
|
<LazyInnerComponent>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="App>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
utils.act(() => modernRender(<App renderChildren={false} />));
|
utils.act(() => modernRender(<App renderChildren={false} />));
|
||||||
expect(store).toMatchInlineSnapshot(`
|
expect(store).toMatchInlineSnapshot(`
|
||||||
|
|
@ -299,6 +303,8 @@ describe('commit tree', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <App>
|
▾ <App>
|
||||||
<Suspense>
|
<Suspense>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="App>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
utils.act(() => modernRender(<App renderChildren={false} />));
|
utils.act(() => modernRender(<App renderChildren={false} />));
|
||||||
expect(store).toMatchInlineSnapshot(`
|
expect(store).toMatchInlineSnapshot(`
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,16 @@ describe('Store', () => {
|
||||||
let store;
|
let store;
|
||||||
let withErrorsOrWarningsIgnored;
|
let withErrorsOrWarningsIgnored;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
// JSDDOM doesn't implement getClientRects so we're just faking one for testing purposes
|
||||||
|
Element.prototype.getClientRects = function (this: Element) {
|
||||||
|
const textContent = this.textContent;
|
||||||
|
return [
|
||||||
|
new DOMRect(1, 2, textContent.length, textContent.split('\n').length),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
global.IS_REACT_ACT_ENVIRONMENT = true;
|
global.IS_REACT_ACT_ENVIRONMENT = true;
|
||||||
|
|
||||||
|
|
@ -123,6 +133,8 @@ describe('Store', () => {
|
||||||
<Suspense>
|
<Suspense>
|
||||||
▾ <Parent>
|
▾ <Parent>
|
||||||
<Child>
|
<Child>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Unknown" rects={null}>
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -480,6 +492,8 @@ describe('Store', () => {
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<Loading>
|
<Loading>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Wrapper>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
await act(() => {
|
await act(() => {
|
||||||
|
|
@ -491,6 +505,8 @@ describe('Store', () => {
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<Component key="Inside">
|
<Component key="Inside">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Wrapper>?" rects={[{x:1,y:2,width:5,height:1}]}>
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -513,23 +529,31 @@ describe('Store', () => {
|
||||||
}) => (
|
}) => (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Component key="Outside" />
|
<Component key="Outside" />
|
||||||
<React.Suspense fallback={<Loading key="Parent Fallback" />}>
|
<React.Suspense
|
||||||
|
name="parent"
|
||||||
|
fallback={<Loading key="Parent Fallback" />}>
|
||||||
<Component key="Unrelated at Start" />
|
<Component key="Unrelated at Start" />
|
||||||
<React.Suspense fallback={<Loading key="Suspense 1 Fallback" />}>
|
<React.Suspense
|
||||||
|
name="one"
|
||||||
|
fallback={<Loading key="Suspense 1 Fallback" />}>
|
||||||
{suspendFirst ? (
|
{suspendFirst ? (
|
||||||
<Never />
|
<Never />
|
||||||
) : (
|
) : (
|
||||||
<Component key="Suspense 1 Content" />
|
<Component key="Suspense 1 Content" />
|
||||||
)}
|
)}
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
<React.Suspense fallback={<Loading key="Suspense 2 Fallback" />}>
|
<React.Suspense
|
||||||
|
name="two"
|
||||||
|
fallback={<Loading key="Suspense 2 Fallback" />}>
|
||||||
{suspendSecond ? (
|
{suspendSecond ? (
|
||||||
<Never />
|
<Never />
|
||||||
) : (
|
) : (
|
||||||
<Component key="Suspense 2 Content" />
|
<Component key="Suspense 2 Content" />
|
||||||
)}
|
)}
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
<React.Suspense fallback={<Loading key="Suspense 3 Fallback" />}>
|
<React.Suspense
|
||||||
|
name="three"
|
||||||
|
fallback={<Loading key="Suspense 3 Fallback" />}>
|
||||||
<Never />
|
<Never />
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
{suspendParent && <Never />}
|
{suspendParent && <Never />}
|
||||||
|
|
@ -538,7 +562,7 @@ describe('Store', () => {
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
|
||||||
await act(() =>
|
await actAsync(() =>
|
||||||
render(
|
render(
|
||||||
<Wrapper
|
<Wrapper
|
||||||
suspendParent={false}
|
suspendParent={false}
|
||||||
|
|
@ -551,15 +575,20 @@ describe('Store', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <Wrapper>
|
▾ <Wrapper>
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="parent">
|
||||||
<Component key="Unrelated at Start">
|
<Component key="Unrelated at Start">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="one">
|
||||||
<Component key="Suspense 1 Content">
|
<Component key="Suspense 1 Content">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="two">
|
||||||
<Component key="Suspense 2 Content">
|
<Component key="Suspense 2 Content">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="three">
|
||||||
<Loading key="Suspense 3 Fallback">
|
<Loading key="Suspense 3 Fallback">
|
||||||
<Component key="Unrelated at End">
|
<Component key="Unrelated at End">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="parent" rects={[{x:1,y:2,width:10,height:1}]}>
|
||||||
|
<Suspense name="one" rects={null}>
|
||||||
|
<Suspense name="two" rects={null}>
|
||||||
|
<Suspense name="three" rects={null}>
|
||||||
`);
|
`);
|
||||||
await act(() =>
|
await act(() =>
|
||||||
render(
|
render(
|
||||||
|
|
@ -574,15 +603,20 @@ describe('Store', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <Wrapper>
|
▾ <Wrapper>
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="parent">
|
||||||
<Component key="Unrelated at Start">
|
<Component key="Unrelated at Start">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="one">
|
||||||
<Loading key="Suspense 1 Fallback">
|
<Loading key="Suspense 1 Fallback">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="two">
|
||||||
<Component key="Suspense 2 Content">
|
<Component key="Suspense 2 Content">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="three">
|
||||||
<Loading key="Suspense 3 Fallback">
|
<Loading key="Suspense 3 Fallback">
|
||||||
<Component key="Unrelated at End">
|
<Component key="Unrelated at End">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="parent" rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>
|
||||||
|
<Suspense name="one" rects={null}>
|
||||||
|
<Suspense name="two" rects={null}>
|
||||||
|
<Suspense name="three" rects={null}>
|
||||||
`);
|
`);
|
||||||
await act(() =>
|
await act(() =>
|
||||||
render(
|
render(
|
||||||
|
|
@ -597,15 +631,20 @@ describe('Store', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <Wrapper>
|
▾ <Wrapper>
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="parent">
|
||||||
<Component key="Unrelated at Start">
|
<Component key="Unrelated at Start">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="one">
|
||||||
<Component key="Suspense 1 Content">
|
<Component key="Suspense 1 Content">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="two">
|
||||||
<Loading key="Suspense 2 Fallback">
|
<Loading key="Suspense 2 Fallback">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="three">
|
||||||
<Loading key="Suspense 3 Fallback">
|
<Loading key="Suspense 3 Fallback">
|
||||||
<Component key="Unrelated at End">
|
<Component key="Unrelated at End">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="parent" rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>
|
||||||
|
<Suspense name="one" rects={null}>
|
||||||
|
<Suspense name="two" rects={null}>
|
||||||
|
<Suspense name="three" rects={null}>
|
||||||
`);
|
`);
|
||||||
await act(() =>
|
await act(() =>
|
||||||
render(
|
render(
|
||||||
|
|
@ -620,15 +659,20 @@ describe('Store', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <Wrapper>
|
▾ <Wrapper>
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="parent">
|
||||||
<Component key="Unrelated at Start">
|
<Component key="Unrelated at Start">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="one">
|
||||||
<Loading key="Suspense 1 Fallback">
|
<Loading key="Suspense 1 Fallback">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="two">
|
||||||
<Component key="Suspense 2 Content">
|
<Component key="Suspense 2 Content">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="three">
|
||||||
<Loading key="Suspense 3 Fallback">
|
<Loading key="Suspense 3 Fallback">
|
||||||
<Component key="Unrelated at End">
|
<Component key="Unrelated at End">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="parent" rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>
|
||||||
|
<Suspense name="one" rects={null}>
|
||||||
|
<Suspense name="two" rects={null}>
|
||||||
|
<Suspense name="three" rects={null}>
|
||||||
`);
|
`);
|
||||||
await act(() =>
|
await act(() =>
|
||||||
render(
|
render(
|
||||||
|
|
@ -643,8 +687,13 @@ describe('Store', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <Wrapper>
|
▾ <Wrapper>
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="parent">
|
||||||
<Loading key="Parent Fallback">
|
<Loading key="Parent Fallback">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="parent" rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>
|
||||||
|
<Suspense name="one" rects={null}>
|
||||||
|
<Suspense name="two" rects={null}>
|
||||||
|
<Suspense name="three" rects={null}>
|
||||||
`);
|
`);
|
||||||
await act(() =>
|
await act(() =>
|
||||||
render(
|
render(
|
||||||
|
|
@ -659,15 +708,20 @@ describe('Store', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <Wrapper>
|
▾ <Wrapper>
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="parent">
|
||||||
<Component key="Unrelated at Start">
|
<Component key="Unrelated at Start">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="one">
|
||||||
<Loading key="Suspense 1 Fallback">
|
<Loading key="Suspense 1 Fallback">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="two">
|
||||||
<Loading key="Suspense 2 Fallback">
|
<Loading key="Suspense 2 Fallback">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="three">
|
||||||
<Loading key="Suspense 3 Fallback">
|
<Loading key="Suspense 3 Fallback">
|
||||||
<Component key="Unrelated at End">
|
<Component key="Unrelated at End">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="parent" rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>
|
||||||
|
<Suspense name="one" rects={null}>
|
||||||
|
<Suspense name="two" rects={null}>
|
||||||
|
<Suspense name="three" rects={null}>
|
||||||
`);
|
`);
|
||||||
await act(() =>
|
await act(() =>
|
||||||
render(
|
render(
|
||||||
|
|
@ -682,15 +736,20 @@ describe('Store', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <Wrapper>
|
▾ <Wrapper>
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="parent">
|
||||||
<Component key="Unrelated at Start">
|
<Component key="Unrelated at Start">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="one">
|
||||||
<Component key="Suspense 1 Content">
|
<Component key="Suspense 1 Content">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="two">
|
||||||
<Component key="Suspense 2 Content">
|
<Component key="Suspense 2 Content">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="three">
|
||||||
<Loading key="Suspense 3 Fallback">
|
<Loading key="Suspense 3 Fallback">
|
||||||
<Component key="Unrelated at End">
|
<Component key="Unrelated at End">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="parent" rects={[{x:1,y:2,width:10,height:1}]}>
|
||||||
|
<Suspense name="one" rects={null}>
|
||||||
|
<Suspense name="two" rects={null}>
|
||||||
|
<Suspense name="three" rects={null}>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const rendererID = getRendererID();
|
const rendererID = getRendererID();
|
||||||
|
|
@ -705,15 +764,20 @@ describe('Store', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <Wrapper>
|
▾ <Wrapper>
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="parent">
|
||||||
<Component key="Unrelated at Start">
|
<Component key="Unrelated at Start">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="one">
|
||||||
<Loading key="Suspense 1 Fallback">
|
<Loading key="Suspense 1 Fallback">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="two">
|
||||||
<Component key="Suspense 2 Content">
|
<Component key="Suspense 2 Content">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="three">
|
||||||
<Loading key="Suspense 3 Fallback">
|
<Loading key="Suspense 3 Fallback">
|
||||||
<Component key="Unrelated at End">
|
<Component key="Unrelated at End">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="parent" rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>
|
||||||
|
<Suspense name="one" rects={null}>
|
||||||
|
<Suspense name="two" rects={null}>
|
||||||
|
<Suspense name="three" rects={null}>
|
||||||
`);
|
`);
|
||||||
await act(() =>
|
await act(() =>
|
||||||
agent.overrideSuspense({
|
agent.overrideSuspense({
|
||||||
|
|
@ -726,8 +790,13 @@ describe('Store', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <Wrapper>
|
▾ <Wrapper>
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="parent">
|
||||||
<Loading key="Parent Fallback">
|
<Loading key="Parent Fallback">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="parent" rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>
|
||||||
|
<Suspense name="one" rects={null}>
|
||||||
|
<Suspense name="two" rects={null}>
|
||||||
|
<Suspense name="three" rects={null}>
|
||||||
`);
|
`);
|
||||||
await act(() =>
|
await act(() =>
|
||||||
render(
|
render(
|
||||||
|
|
@ -742,8 +811,13 @@ describe('Store', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <Wrapper>
|
▾ <Wrapper>
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="parent">
|
||||||
<Loading key="Parent Fallback">
|
<Loading key="Parent Fallback">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="parent" rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>
|
||||||
|
<Suspense name="one" rects={null}>
|
||||||
|
<Suspense name="two" rects={null}>
|
||||||
|
<Suspense name="three" rects={null}>
|
||||||
`);
|
`);
|
||||||
await act(() =>
|
await act(() =>
|
||||||
agent.overrideSuspense({
|
agent.overrideSuspense({
|
||||||
|
|
@ -756,15 +830,20 @@ describe('Store', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <Wrapper>
|
▾ <Wrapper>
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="parent">
|
||||||
<Component key="Unrelated at Start">
|
<Component key="Unrelated at Start">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="one">
|
||||||
<Loading key="Suspense 1 Fallback">
|
<Loading key="Suspense 1 Fallback">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="two">
|
||||||
<Loading key="Suspense 2 Fallback">
|
<Loading key="Suspense 2 Fallback">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="three">
|
||||||
<Loading key="Suspense 3 Fallback">
|
<Loading key="Suspense 3 Fallback">
|
||||||
<Component key="Unrelated at End">
|
<Component key="Unrelated at End">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="parent" rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>
|
||||||
|
<Suspense name="one" rects={null}>
|
||||||
|
<Suspense name="two" rects={null}>
|
||||||
|
<Suspense name="three" rects={null}>
|
||||||
`);
|
`);
|
||||||
await act(() =>
|
await act(() =>
|
||||||
agent.overrideSuspense({
|
agent.overrideSuspense({
|
||||||
|
|
@ -777,15 +856,20 @@ describe('Store', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <Wrapper>
|
▾ <Wrapper>
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="parent">
|
||||||
<Component key="Unrelated at Start">
|
<Component key="Unrelated at Start">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="one">
|
||||||
<Loading key="Suspense 1 Fallback">
|
<Loading key="Suspense 1 Fallback">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="two">
|
||||||
<Loading key="Suspense 2 Fallback">
|
<Loading key="Suspense 2 Fallback">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="three">
|
||||||
<Loading key="Suspense 3 Fallback">
|
<Loading key="Suspense 3 Fallback">
|
||||||
<Component key="Unrelated at End">
|
<Component key="Unrelated at End">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="parent" rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>
|
||||||
|
<Suspense name="one" rects={null}>
|
||||||
|
<Suspense name="two" rects={null}>
|
||||||
|
<Suspense name="three" rects={null}>
|
||||||
`);
|
`);
|
||||||
await act(() =>
|
await act(() =>
|
||||||
render(
|
render(
|
||||||
|
|
@ -800,15 +884,20 @@ describe('Store', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <Wrapper>
|
▾ <Wrapper>
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="parent">
|
||||||
<Component key="Unrelated at Start">
|
<Component key="Unrelated at Start">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="one">
|
||||||
<Component key="Suspense 1 Content">
|
<Component key="Suspense 1 Content">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="two">
|
||||||
<Component key="Suspense 2 Content">
|
<Component key="Suspense 2 Content">
|
||||||
▾ <Suspense>
|
▾ <Suspense name="three">
|
||||||
<Loading key="Suspense 3 Fallback">
|
<Loading key="Suspense 3 Fallback">
|
||||||
<Component key="Unrelated at End">
|
<Component key="Unrelated at End">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="parent" rects={[{x:1,y:2,width:10,height:1}]}>
|
||||||
|
<Suspense name="one" rects={null}>
|
||||||
|
<Suspense name="two" rects={null}>
|
||||||
|
<Suspense name="three" rects={null}>
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -848,6 +937,8 @@ describe('Store', () => {
|
||||||
<Component key="A">
|
<Component key="A">
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<Loading>
|
<Loading>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Wrapper>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
await act(() => {
|
await act(() => {
|
||||||
|
|
@ -861,6 +952,8 @@ describe('Store', () => {
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<Component key="B">
|
<Component key="B">
|
||||||
<Component key="C">
|
<Component key="C">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Wrapper>?" rects={[{x:1,y:2,width:5,height:1}]}>
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1197,6 +1290,8 @@ describe('Store', () => {
|
||||||
expect(store).toMatchInlineSnapshot(`
|
expect(store).toMatchInlineSnapshot(`
|
||||||
[root]
|
[root]
|
||||||
▸ <Wrapper>
|
▸ <Wrapper>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Wrapper>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// This test isn't meaningful unless we expand the suspended tree
|
// This test isn't meaningful unless we expand the suspended tree
|
||||||
|
|
@ -1212,6 +1307,8 @@ describe('Store', () => {
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<Loading>
|
<Loading>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Wrapper>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
await act(() => {
|
await act(() => {
|
||||||
|
|
@ -1223,6 +1320,8 @@ describe('Store', () => {
|
||||||
<Component key="Outside">
|
<Component key="Outside">
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<Component key="Inside">
|
<Component key="Inside">
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Wrapper>?" rects={[{x:1,y:2,width:5,height:1}]}>
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1447,6 +1546,8 @@ describe('Store', () => {
|
||||||
expect(store).toMatchInlineSnapshot(`
|
expect(store).toMatchInlineSnapshot(`
|
||||||
[root]
|
[root]
|
||||||
▸ <SuspenseTree>
|
▸ <SuspenseTree>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="SuspenseTree>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
await act(() =>
|
await act(() =>
|
||||||
|
|
@ -1460,6 +1561,8 @@ describe('Store', () => {
|
||||||
▾ <SuspenseTree>
|
▾ <SuspenseTree>
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
▸ <Parent>
|
▸ <Parent>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="SuspenseTree>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const rendererID = getRendererID();
|
const rendererID = getRendererID();
|
||||||
|
|
@ -1477,6 +1580,8 @@ describe('Store', () => {
|
||||||
▾ <SuspenseTree>
|
▾ <SuspenseTree>
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<Fallback>
|
<Fallback>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="SuspenseTree>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
await act(() =>
|
await act(() =>
|
||||||
|
|
@ -1491,6 +1596,8 @@ describe('Store', () => {
|
||||||
▾ <SuspenseTree>
|
▾ <SuspenseTree>
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
▸ <Parent>
|
▸ <Parent>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="SuspenseTree>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -1794,6 +1901,8 @@ describe('Store', () => {
|
||||||
[root]
|
[root]
|
||||||
▾ <App>
|
▾ <App>
|
||||||
<Suspense>
|
<Suspense>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="App>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
|
|
@ -1806,6 +1915,8 @@ describe('Store', () => {
|
||||||
▾ <App>
|
▾ <App>
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<LazyInnerComponent>
|
<LazyInnerComponent>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="App>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// Render again to unmount it
|
// Render again to unmount it
|
||||||
|
|
@ -2291,20 +2402,24 @@ describe('Store', () => {
|
||||||
await actAsync(() => render(<App renderA={true} />));
|
await actAsync(() => render(<App renderA={true} />));
|
||||||
|
|
||||||
expect(store).toMatchInlineSnapshot(`
|
expect(store).toMatchInlineSnapshot(`
|
||||||
[root]
|
[root]
|
||||||
▾ <App>
|
▾ <App>
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<ChildA>
|
<ChildA>
|
||||||
`);
|
[shell]
|
||||||
|
<Suspense name="App>?" rects={null}>
|
||||||
|
`);
|
||||||
|
|
||||||
await actAsync(() => render(<App renderA={false} />));
|
await actAsync(() => render(<App renderA={false} />));
|
||||||
|
|
||||||
expect(store).toMatchInlineSnapshot(`
|
expect(store).toMatchInlineSnapshot(`
|
||||||
[root]
|
[root]
|
||||||
▾ <App>
|
▾ <App>
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<ChildB>
|
<ChildB>
|
||||||
`);
|
[shell]
|
||||||
|
<Suspense name="App>?" rects={null}>
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,9 @@ describe('Store component filters', () => {
|
||||||
<div>
|
<div>
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<div>
|
<div>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Unknown" rects={[]}>
|
||||||
|
<Suspense name="Unknown" rects={[]}>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
await actAsync(
|
await actAsync(
|
||||||
|
|
@ -171,6 +174,9 @@ describe('Store component filters', () => {
|
||||||
<div>
|
<div>
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<div>
|
<div>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Unknown" rects={[]}>
|
||||||
|
<Suspense name="Unknown" rects={[]}>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
await actAsync(
|
await actAsync(
|
||||||
|
|
@ -186,6 +192,9 @@ describe('Store component filters', () => {
|
||||||
<div>
|
<div>
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<div>
|
<div>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Unknown" rects={[]}>
|
||||||
|
<Suspense name="Unknown" rects={[]}>
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
// this helper with the real thing.
|
// this helper with the real thing.
|
||||||
actAsync = require('./utils').actAsync;
|
actAsync = require('./utils').actAsync;
|
||||||
|
|
||||||
print = require('./__serializers__/storeSerializer').print;
|
print = require('./__serializers__/storeSerializer').printStore;
|
||||||
});
|
});
|
||||||
|
|
||||||
// This is a stress test for the tree mount/update/unmount traversal.
|
// This is a stress test for the tree mount/update/unmount traversal.
|
||||||
|
|
@ -67,8 +67,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
let container = document.createElement('div');
|
let container = document.createElement('div');
|
||||||
let root = ReactDOMClient.createRoot(container);
|
let root = ReactDOMClient.createRoot(container);
|
||||||
act(() => root.render(<Parent>{[a, b, c, d, e]}</Parent>));
|
act(() => root.render(<Parent>{[a, b, c, d, e]}</Parent>));
|
||||||
expect(store).toMatchInlineSnapshot(
|
expect(store).toMatchInlineSnapshot(`
|
||||||
`
|
|
||||||
[root]
|
[root]
|
||||||
▾ <Parent>
|
▾ <Parent>
|
||||||
<A key="a">
|
<A key="a">
|
||||||
|
|
@ -76,8 +75,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
<C key="c">
|
<C key="c">
|
||||||
<D key="d">
|
<D key="d">
|
||||||
<E key="e">
|
<E key="e">
|
||||||
`,
|
`);
|
||||||
);
|
|
||||||
expect(container.textContent).toMatch('abcde');
|
expect(container.textContent).toMatch('abcde');
|
||||||
const snapshotForABCDE = print(store);
|
const snapshotForABCDE = print(store);
|
||||||
|
|
||||||
|
|
@ -86,8 +84,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
act(() => {
|
act(() => {
|
||||||
setShowX(true);
|
setShowX(true);
|
||||||
});
|
});
|
||||||
expect(store).toMatchInlineSnapshot(
|
expect(store).toMatchInlineSnapshot(`
|
||||||
`
|
|
||||||
[root]
|
[root]
|
||||||
▾ <Parent>
|
▾ <Parent>
|
||||||
<A key="a">
|
<A key="a">
|
||||||
|
|
@ -96,8 +93,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
<X>
|
<X>
|
||||||
<D key="d">
|
<D key="d">
|
||||||
<E key="e">
|
<E key="e">
|
||||||
`,
|
`);
|
||||||
);
|
|
||||||
expect(container.textContent).toMatch('abxde');
|
expect(container.textContent).toMatch('abxde');
|
||||||
const snapshotForABXDE = print(store);
|
const snapshotForABXDE = print(store);
|
||||||
|
|
||||||
|
|
@ -419,7 +415,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// We snapshot each step once so it doesn't regress.d
|
// We snapshot each step once so it doesn't regress.d
|
||||||
snapshots.push(print(store));
|
snapshots.push(print(store, false, null, false));
|
||||||
await act(() => root.unmount());
|
await act(() => root.unmount());
|
||||||
expect(print(store)).toBe('');
|
expect(print(store)).toBe('');
|
||||||
}
|
}
|
||||||
|
|
@ -524,7 +520,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
await act(() => root.unmount());
|
await act(() => root.unmount());
|
||||||
expect(print(store)).toBe('');
|
expect(print(store)).toBe('');
|
||||||
}
|
}
|
||||||
|
|
@ -544,7 +540,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
// Re-render with steps[j].
|
// Re-render with steps[j].
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -556,7 +552,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// Verify the successful transition to steps[j].
|
// Verify the successful transition to steps[j].
|
||||||
expect(print(store)).toEqual(snapshots[j]);
|
expect(print(store, false, null, false)).toEqual(snapshots[j]);
|
||||||
// Check that we can transition back again.
|
// Check that we can transition back again.
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -567,7 +563,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
// Clean up after every iteration.
|
// Clean up after every iteration.
|
||||||
await act(() => root.unmount());
|
await act(() => root.unmount());
|
||||||
expect(print(store)).toBe('');
|
expect(print(store)).toBe('');
|
||||||
|
|
@ -593,7 +589,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
// Re-render with steps[j].
|
// Re-render with steps[j].
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -609,7 +605,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// Verify the successful transition to steps[j].
|
// Verify the successful transition to steps[j].
|
||||||
expect(print(store)).toEqual(snapshots[j]);
|
expect(print(store, false, null, false)).toEqual(snapshots[j]);
|
||||||
// Check that we can transition back again.
|
// Check that we can transition back again.
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -624,7 +620,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
// Clean up after every iteration.
|
// Clean up after every iteration.
|
||||||
await act(() => root.unmount());
|
await act(() => root.unmount());
|
||||||
expect(print(store)).toBe('');
|
expect(print(store)).toBe('');
|
||||||
|
|
@ -646,7 +642,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
// Re-render with steps[j].
|
// Re-render with steps[j].
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -662,7 +658,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// Verify the successful transition to steps[j].
|
// Verify the successful transition to steps[j].
|
||||||
expect(print(store)).toEqual(snapshots[j]);
|
expect(print(store, false, null, false)).toEqual(snapshots[j]);
|
||||||
// Check that we can transition back again.
|
// Check that we can transition back again.
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -673,7 +669,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
// Clean up after every iteration.
|
// Clean up after every iteration.
|
||||||
await act(() => root.unmount());
|
await act(() => root.unmount());
|
||||||
expect(print(store)).toBe('');
|
expect(print(store)).toBe('');
|
||||||
|
|
@ -699,7 +695,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
// Re-render with steps[j].
|
// Re-render with steps[j].
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -711,7 +707,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// Verify the successful transition to steps[j].
|
// Verify the successful transition to steps[j].
|
||||||
expect(print(store)).toEqual(snapshots[j]);
|
expect(print(store, false, null, false)).toEqual(snapshots[j]);
|
||||||
// Check that we can transition back again.
|
// Check that we can transition back again.
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -726,7 +722,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
// Clean up after every iteration.
|
// Clean up after every iteration.
|
||||||
await act(() => root.unmount());
|
await act(() => root.unmount());
|
||||||
expect(print(store)).toBe('');
|
expect(print(store)).toBe('');
|
||||||
|
|
@ -755,7 +751,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
const suspenseID = store.getElementIDAtIndex(2);
|
const suspenseID = store.getElementIDAtIndex(2);
|
||||||
|
|
||||||
// Force fallback.
|
// Force fallback.
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
await actAsync(async () => {
|
await actAsync(async () => {
|
||||||
bridge.send('overrideSuspense', {
|
bridge.send('overrideSuspense', {
|
||||||
id: suspenseID,
|
id: suspenseID,
|
||||||
|
|
@ -763,7 +759,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
forceFallback: true,
|
forceFallback: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
expect(print(store)).toEqual(snapshots[j]);
|
expect(print(store, false, null, false)).toEqual(snapshots[j]);
|
||||||
|
|
||||||
// Stop forcing fallback.
|
// Stop forcing fallback.
|
||||||
await actAsync(async () => {
|
await actAsync(async () => {
|
||||||
|
|
@ -773,7 +769,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
forceFallback: false,
|
forceFallback: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
|
|
||||||
// Trigger actual fallback.
|
// Trigger actual fallback.
|
||||||
await act(() =>
|
await act(() =>
|
||||||
|
|
@ -789,7 +785,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(snapshots[j]);
|
expect(print(store, false, null, false)).toEqual(snapshots[j]);
|
||||||
|
|
||||||
// Force fallback while we're in fallback mode.
|
// Force fallback while we're in fallback mode.
|
||||||
await act(() => {
|
await act(() => {
|
||||||
|
|
@ -800,7 +796,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// Keep seeing fallback content.
|
// Keep seeing fallback content.
|
||||||
expect(print(store)).toEqual(snapshots[j]);
|
expect(print(store, false, null, false)).toEqual(snapshots[j]);
|
||||||
|
|
||||||
// Switch to primary mode.
|
// Switch to primary mode.
|
||||||
await act(() =>
|
await act(() =>
|
||||||
|
|
@ -813,7 +809,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// Fallback is still forced though.
|
// Fallback is still forced though.
|
||||||
expect(print(store)).toEqual(snapshots[j]);
|
expect(print(store, false, null, false)).toEqual(snapshots[j]);
|
||||||
|
|
||||||
// Stop forcing fallback. This reverts to primary content.
|
// Stop forcing fallback. This reverts to primary content.
|
||||||
await actAsync(async () => {
|
await actAsync(async () => {
|
||||||
|
|
@ -824,7 +820,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// Now we see primary content.
|
// Now we see primary content.
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
|
|
||||||
// Clean up after every iteration.
|
// Clean up after every iteration.
|
||||||
await actAsync(async () => root.unmount());
|
await actAsync(async () => root.unmount());
|
||||||
|
|
@ -910,7 +906,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// We snapshot each step once so it doesn't regress.
|
// We snapshot each step once so it doesn't regress.
|
||||||
snapshots.push(print(store));
|
snapshots.push(print(store, false, null, false));
|
||||||
await act(() => root.unmount());
|
await act(() => root.unmount());
|
||||||
expect(print(store)).toBe('');
|
expect(print(store)).toBe('');
|
||||||
}
|
}
|
||||||
|
|
@ -935,7 +931,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// We snapshot each step once so it doesn't regress.
|
// We snapshot each step once so it doesn't regress.
|
||||||
fallbackSnapshots.push(print(store));
|
fallbackSnapshots.push(print(store, false, null, false));
|
||||||
await act(() => root.unmount());
|
await act(() => root.unmount());
|
||||||
expect(print(store)).toBe('');
|
expect(print(store)).toBe('');
|
||||||
}
|
}
|
||||||
|
|
@ -1065,7 +1061,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
// Re-render with steps[j].
|
// Re-render with steps[j].
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -1079,7 +1075,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// Verify the successful transition to steps[j].
|
// Verify the successful transition to steps[j].
|
||||||
expect(print(store)).toEqual(snapshots[j]);
|
expect(print(store, false, null, false)).toEqual(snapshots[j]);
|
||||||
// Check that we can transition back again.
|
// Check that we can transition back again.
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -1092,7 +1088,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
// Clean up after every iteration.
|
// Clean up after every iteration.
|
||||||
await act(() => root.unmount());
|
await act(() => root.unmount());
|
||||||
expect(print(store)).toBe('');
|
expect(print(store)).toBe('');
|
||||||
|
|
@ -1121,7 +1117,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(fallbackSnapshots[i]);
|
expect(print(store, false, null, false)).toEqual(fallbackSnapshots[i]);
|
||||||
// Re-render with steps[j].
|
// Re-render with steps[j].
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -1140,7 +1136,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// Verify the successful transition to steps[j].
|
// Verify the successful transition to steps[j].
|
||||||
expect(print(store)).toEqual(fallbackSnapshots[j]);
|
expect(print(store, false, null, false)).toEqual(fallbackSnapshots[j]);
|
||||||
// Check that we can transition back again.
|
// Check that we can transition back again.
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -1158,7 +1154,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(fallbackSnapshots[i]);
|
expect(print(store, false, null, false)).toEqual(fallbackSnapshots[i]);
|
||||||
// Clean up after every iteration.
|
// Clean up after every iteration.
|
||||||
await act(() => root.unmount());
|
await act(() => root.unmount());
|
||||||
expect(print(store)).toBe('');
|
expect(print(store)).toBe('');
|
||||||
|
|
@ -1182,7 +1178,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
// Re-render with steps[j].
|
// Re-render with steps[j].
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -1196,7 +1192,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// Verify the successful transition to steps[j].
|
// Verify the successful transition to steps[j].
|
||||||
expect(print(store)).toEqual(fallbackSnapshots[j]);
|
expect(print(store, false, null, false)).toEqual(fallbackSnapshots[j]);
|
||||||
// Check that we can transition back again.
|
// Check that we can transition back again.
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -1209,7 +1205,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
// Clean up after every iteration.
|
// Clean up after every iteration.
|
||||||
await act(() => root.unmount());
|
await act(() => root.unmount());
|
||||||
expect(print(store)).toBe('');
|
expect(print(store)).toBe('');
|
||||||
|
|
@ -1233,7 +1229,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(fallbackSnapshots[i]);
|
expect(print(store, false, null, false)).toEqual(fallbackSnapshots[i]);
|
||||||
// Re-render with steps[j].
|
// Re-render with steps[j].
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -1247,7 +1243,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// Verify the successful transition to steps[j].
|
// Verify the successful transition to steps[j].
|
||||||
expect(print(store)).toEqual(snapshots[j]);
|
expect(print(store, false, null, false)).toEqual(snapshots[j]);
|
||||||
// Check that we can transition back again.
|
// Check that we can transition back again.
|
||||||
await act(() =>
|
await act(() =>
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -1260,7 +1256,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(fallbackSnapshots[i]);
|
expect(print(store, false, null, false)).toEqual(fallbackSnapshots[i]);
|
||||||
// Clean up after every iteration.
|
// Clean up after every iteration.
|
||||||
await act(() => root.unmount());
|
await act(() => root.unmount());
|
||||||
expect(print(store)).toBe('');
|
expect(print(store)).toBe('');
|
||||||
|
|
@ -1291,7 +1287,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
const suspenseID = store.getElementIDAtIndex(2);
|
const suspenseID = store.getElementIDAtIndex(2);
|
||||||
|
|
||||||
// Force fallback.
|
// Force fallback.
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
await actAsync(async () => {
|
await actAsync(async () => {
|
||||||
bridge.send('overrideSuspense', {
|
bridge.send('overrideSuspense', {
|
||||||
id: suspenseID,
|
id: suspenseID,
|
||||||
|
|
@ -1299,7 +1295,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
forceFallback: true,
|
forceFallback: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
expect(print(store)).toEqual(fallbackSnapshots[j]);
|
expect(print(store, false, null, false)).toEqual(fallbackSnapshots[j]);
|
||||||
|
|
||||||
// Stop forcing fallback.
|
// Stop forcing fallback.
|
||||||
await actAsync(async () => {
|
await actAsync(async () => {
|
||||||
|
|
@ -1309,7 +1305,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
forceFallback: false,
|
forceFallback: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
|
|
||||||
// Trigger actual fallback.
|
// Trigger actual fallback.
|
||||||
await act(() =>
|
await act(() =>
|
||||||
|
|
@ -1323,7 +1319,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
</Root>,
|
</Root>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(print(store)).toEqual(fallbackSnapshots[j]);
|
expect(print(store, false, null, false)).toEqual(fallbackSnapshots[j]);
|
||||||
|
|
||||||
// Force fallback while we're in fallback mode.
|
// Force fallback while we're in fallback mode.
|
||||||
await act(() => {
|
await act(() => {
|
||||||
|
|
@ -1334,7 +1330,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// Keep seeing fallback content.
|
// Keep seeing fallback content.
|
||||||
expect(print(store)).toEqual(fallbackSnapshots[j]);
|
expect(print(store, false, null, false)).toEqual(fallbackSnapshots[j]);
|
||||||
|
|
||||||
// Switch to primary mode.
|
// Switch to primary mode.
|
||||||
await act(() =>
|
await act(() =>
|
||||||
|
|
@ -1349,7 +1345,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// Fallback is still forced though.
|
// Fallback is still forced though.
|
||||||
expect(print(store)).toEqual(fallbackSnapshots[j]);
|
expect(print(store, false, null, false)).toEqual(fallbackSnapshots[j]);
|
||||||
|
|
||||||
// Stop forcing fallback. This reverts to primary content.
|
// Stop forcing fallback. This reverts to primary content.
|
||||||
await actAsync(async () => {
|
await actAsync(async () => {
|
||||||
|
|
@ -1360,7 +1356,7 @@ describe('StoreStressConcurrent', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// Now we see primary content.
|
// Now we see primary content.
|
||||||
expect(print(store)).toEqual(snapshots[i]);
|
expect(print(store, false, null, false)).toEqual(snapshots[i]);
|
||||||
|
|
||||||
// Clean up after every iteration.
|
// Clean up after every iteration.
|
||||||
await act(() => root.unmount());
|
await act(() => root.unmount());
|
||||||
|
|
|
||||||
|
|
@ -1368,6 +1368,9 @@ describe('TreeListContext', () => {
|
||||||
▾ <Child>
|
▾ <Child>
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<Grandchild>
|
<Grandchild>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Parent>?" rects={null}>
|
||||||
|
<Suspense name="Child>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const outerSuspenseID = ((store.getElementIDAtIndex(1): any): number);
|
const outerSuspenseID = ((store.getElementIDAtIndex(1): any): number);
|
||||||
|
|
@ -1407,6 +1410,9 @@ describe('TreeListContext', () => {
|
||||||
▾ <Child>
|
▾ <Child>
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<Grandchild>
|
<Grandchild>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Parent>?" rects={null}>
|
||||||
|
<Suspense name="Child>?" rects={null}>
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -2361,16 +2367,20 @@ describe('TreeListContext', () => {
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
|
|
||||||
expect(state).toMatchInlineSnapshot(`
|
expect(state).toMatchInlineSnapshot(`
|
||||||
[root]
|
[root]
|
||||||
<Suspense>
|
<Suspense>
|
||||||
`);
|
[shell]
|
||||||
|
<Suspense name="Unknown" rects={null}>
|
||||||
|
`);
|
||||||
|
|
||||||
selectNextErrorOrWarning();
|
selectNextErrorOrWarning();
|
||||||
|
|
||||||
expect(state).toMatchInlineSnapshot(`
|
expect(state).toMatchInlineSnapshot(`
|
||||||
[root]
|
[root]
|
||||||
<Suspense>
|
<Suspense>
|
||||||
`);
|
[shell]
|
||||||
|
<Suspense name="Unknown" rects={null}>
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should properly handle errors/warnings from components that dont mount because of Suspense', async () => {
|
it('should properly handle errors/warnings from components that dont mount because of Suspense', async () => {
|
||||||
|
|
@ -2392,9 +2402,11 @@ describe('TreeListContext', () => {
|
||||||
utils.act(() => TestRenderer.create(<Contexts />));
|
utils.act(() => TestRenderer.create(<Contexts />));
|
||||||
|
|
||||||
expect(state).toMatchInlineSnapshot(`
|
expect(state).toMatchInlineSnapshot(`
|
||||||
[root]
|
[root]
|
||||||
<Suspense>
|
<Suspense>
|
||||||
`);
|
[shell]
|
||||||
|
<Suspense name="Unknown" rects={null}>
|
||||||
|
`);
|
||||||
|
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
withErrorsOrWarningsIgnored(['test-only:'], () =>
|
withErrorsOrWarningsIgnored(['test-only:'], () =>
|
||||||
|
|
@ -2414,6 +2426,8 @@ describe('TreeListContext', () => {
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<Child> ⚠
|
<Child> ⚠
|
||||||
<Child>
|
<Child>
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Unknown" rects={null}>
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -2442,6 +2456,8 @@ describe('TreeListContext', () => {
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
▾ <Fallback>
|
▾ <Fallback>
|
||||||
<Child> ✕
|
<Child> ✕
|
||||||
|
[shell]
|
||||||
|
<Suspense name="Unknown" rects={null}>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
|
|
@ -2456,10 +2472,12 @@ describe('TreeListContext', () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(state).toMatchInlineSnapshot(`
|
expect(state).toMatchInlineSnapshot(`
|
||||||
[root]
|
[root]
|
||||||
▾ <Suspense>
|
▾ <Suspense>
|
||||||
<Child>
|
<Child>
|
||||||
`);
|
[shell]
|
||||||
|
<Suspense name="Unknown" rects={null}>
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ import {
|
||||||
SUSPENSE_TREE_OPERATION_ADD,
|
SUSPENSE_TREE_OPERATION_ADD,
|
||||||
SUSPENSE_TREE_OPERATION_REMOVE,
|
SUSPENSE_TREE_OPERATION_REMOVE,
|
||||||
SUSPENSE_TREE_OPERATION_REORDER_CHILDREN,
|
SUSPENSE_TREE_OPERATION_REORDER_CHILDREN,
|
||||||
|
SUSPENSE_TREE_OPERATION_RESIZE,
|
||||||
} from '../../constants';
|
} from '../../constants';
|
||||||
import {inspectHooksOfFiber} from 'react-debug-tools';
|
import {inspectHooksOfFiber} from 'react-debug-tools';
|
||||||
import {
|
import {
|
||||||
|
|
@ -2558,6 +2559,20 @@ export function attach(
|
||||||
pushOperation(fiberID);
|
pushOperation(fiberID);
|
||||||
pushOperation(parentID);
|
pushOperation(parentID);
|
||||||
pushOperation(nameStringID);
|
pushOperation(nameStringID);
|
||||||
|
|
||||||
|
const rects = suspenseInstance.rects;
|
||||||
|
if (rects === null) {
|
||||||
|
pushOperation(-1);
|
||||||
|
} else {
|
||||||
|
pushOperation(rects.length);
|
||||||
|
for (let i = 0; i < rects.length; ++i) {
|
||||||
|
const rect = rects[i];
|
||||||
|
pushOperation(Math.round(rect.x));
|
||||||
|
pushOperation(Math.round(rect.y));
|
||||||
|
pushOperation(Math.round(rect.width));
|
||||||
|
pushOperation(Math.round(rect.height));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function recordUnmount(fiberInstance: FiberInstance): void {
|
function recordUnmount(fiberInstance: FiberInstance): void {
|
||||||
|
|
@ -2606,7 +2621,30 @@ export function attach(
|
||||||
}
|
}
|
||||||
|
|
||||||
function recordSuspenseResize(suspenseNode: SuspenseNode): void {
|
function recordSuspenseResize(suspenseNode: SuspenseNode): void {
|
||||||
// TODO: Notify the front end of the change.
|
if (__DEBUG__) {
|
||||||
|
console.log('recordSuspenseResize()', suspenseNode);
|
||||||
|
}
|
||||||
|
const fiberInstance = suspenseNode.instance;
|
||||||
|
if (fiberInstance.kind !== FIBER_INSTANCE) {
|
||||||
|
// TODO: Resizes of filtered Suspense nodes are currently dropped.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pushOperation(SUSPENSE_TREE_OPERATION_RESIZE);
|
||||||
|
pushOperation(fiberInstance.id);
|
||||||
|
const rects = suspenseNode.rects;
|
||||||
|
if (rects === null) {
|
||||||
|
pushOperation(-1);
|
||||||
|
} else {
|
||||||
|
pushOperation(rects.length);
|
||||||
|
for (let i = 0; i < rects.length; ++i) {
|
||||||
|
const rect = rects[i];
|
||||||
|
pushOperation(Math.round(rect.x));
|
||||||
|
pushOperation(Math.round(rect.y));
|
||||||
|
pushOperation(Math.round(rect.width));
|
||||||
|
pushOperation(Math.round(rect.height));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function recordSuspenseUnmount(suspenseInstance: SuspenseNode): void {
|
function recordSuspenseUnmount(suspenseInstance: SuspenseNode): void {
|
||||||
|
|
@ -3442,7 +3480,25 @@ export function attach(
|
||||||
// Measure this Suspense node. In general we shouldn't do this until we have
|
// Measure this Suspense node. In general we shouldn't do this until we have
|
||||||
// inserted the new children but since we know this is a FiberInstance we'll
|
// inserted the new children but since we know this is a FiberInstance we'll
|
||||||
// just use the Fiber anyway.
|
// just use the Fiber anyway.
|
||||||
newSuspenseNode.rects = measureInstance(newInstance);
|
// Fallbacks get attributed to the parent so we only measure if we're
|
||||||
|
// showing primary content.
|
||||||
|
if (OffscreenComponent === -1) {
|
||||||
|
const isTimedOut = fiber.memoizedState !== null;
|
||||||
|
if (!isTimedOut) {
|
||||||
|
newSuspenseNode.rects = measureInstance(newInstance);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const contentFiber = fiber.child;
|
||||||
|
if (contentFiber === null) {
|
||||||
|
throw new Error(
|
||||||
|
'There should always be an Offscreen Fiber child in a Suspense boundary.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const isTimedOut = fiber.memoizedState !== null;
|
||||||
|
if (!isTimedOut) {
|
||||||
|
newSuspenseNode.rects = measureInstance(newInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
recordSuspenseMount(newSuspenseNode, reconcilingParentSuspenseNode);
|
recordSuspenseMount(newSuspenseNode, reconcilingParentSuspenseNode);
|
||||||
}
|
}
|
||||||
insertChild(newInstance);
|
insertChild(newInstance);
|
||||||
|
|
@ -3476,7 +3532,25 @@ export function attach(
|
||||||
// Measure this Suspense node. In general we shouldn't do this until we have
|
// Measure this Suspense node. In general we shouldn't do this until we have
|
||||||
// inserted the new children but since we know this is a FiberInstance we'll
|
// inserted the new children but since we know this is a FiberInstance we'll
|
||||||
// just use the Fiber anyway.
|
// just use the Fiber anyway.
|
||||||
newSuspenseNode.rects = measureInstance(newInstance);
|
// Fallbacks get attributed to the parent so we only measure if we're
|
||||||
|
// showing primary content.
|
||||||
|
if (OffscreenComponent === -1) {
|
||||||
|
const isTimedOut = fiber.memoizedState !== null;
|
||||||
|
if (!isTimedOut) {
|
||||||
|
newSuspenseNode.rects = measureInstance(newInstance);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const contentFiber = fiber.child;
|
||||||
|
if (contentFiber === null) {
|
||||||
|
throw new Error(
|
||||||
|
'There should always be an Offscreen Fiber child in a Suspense boundary.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const isTimedOut = fiber.memoizedState !== null;
|
||||||
|
if (!isTimedOut) {
|
||||||
|
newSuspenseNode.rects = measureInstance(newInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
insertChild(newInstance);
|
insertChild(newInstance);
|
||||||
if (__DEBUG__) {
|
if (__DEBUG__) {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ export const TREE_OPERATION_SET_SUBTREE_MODE = 7;
|
||||||
export const SUSPENSE_TREE_OPERATION_ADD = 8;
|
export const SUSPENSE_TREE_OPERATION_ADD = 8;
|
||||||
export const SUSPENSE_TREE_OPERATION_REMOVE = 9;
|
export const SUSPENSE_TREE_OPERATION_REMOVE = 9;
|
||||||
export const SUSPENSE_TREE_OPERATION_REORDER_CHILDREN = 10;
|
export const SUSPENSE_TREE_OPERATION_REORDER_CHILDREN = 10;
|
||||||
|
export const SUSPENSE_TREE_OPERATION_RESIZE = 11;
|
||||||
|
|
||||||
export const PROFILING_FLAG_BASIC_SUPPORT = 0b01;
|
export const PROFILING_FLAG_BASIC_SUPPORT = 0b01;
|
||||||
export const PROFILING_FLAG_TIMELINE_SUPPORT = 0b10;
|
export const PROFILING_FLAG_TIMELINE_SUPPORT = 0b10;
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import {
|
||||||
SUSPENSE_TREE_OPERATION_ADD,
|
SUSPENSE_TREE_OPERATION_ADD,
|
||||||
SUSPENSE_TREE_OPERATION_REMOVE,
|
SUSPENSE_TREE_OPERATION_REMOVE,
|
||||||
SUSPENSE_TREE_OPERATION_REORDER_CHILDREN,
|
SUSPENSE_TREE_OPERATION_REORDER_CHILDREN,
|
||||||
|
SUSPENSE_TREE_OPERATION_RESIZE,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import {ElementTypeRoot} from '../frontend/types';
|
import {ElementTypeRoot} from '../frontend/types';
|
||||||
import {
|
import {
|
||||||
|
|
@ -1418,6 +1419,7 @@ export default class Store extends EventEmitter<{
|
||||||
const id = operations[i + 1];
|
const id = operations[i + 1];
|
||||||
const parentID = operations[i + 2];
|
const parentID = operations[i + 2];
|
||||||
const nameStringID = operations[i + 3];
|
const nameStringID = operations[i + 3];
|
||||||
|
const numRects = ((operations[i + 4]: any): number);
|
||||||
let name = stringTable[nameStringID];
|
let name = stringTable[nameStringID];
|
||||||
|
|
||||||
if (this._idToSuspense.has(id)) {
|
if (this._idToSuspense.has(id)) {
|
||||||
|
|
@ -1448,6 +1450,22 @@ export default class Store extends EventEmitter<{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i += 5;
|
||||||
|
let rects: SuspenseNode['rects'];
|
||||||
|
if (numRects === -1) {
|
||||||
|
rects = null;
|
||||||
|
} else {
|
||||||
|
rects = [];
|
||||||
|
for (let rectIndex = 0; rectIndex < numRects; rectIndex++) {
|
||||||
|
const x = operations[i + 0];
|
||||||
|
const y = operations[i + 1];
|
||||||
|
const width = operations[i + 2];
|
||||||
|
const height = operations[i + 3];
|
||||||
|
rects.push({x, y, width, height});
|
||||||
|
i += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (__DEBUG__) {
|
if (__DEBUG__) {
|
||||||
debug('Suspense Add', `node ${id} as child of ${parentID}`);
|
debug('Suspense Add', `node ${id} as child of ${parentID}`);
|
||||||
}
|
}
|
||||||
|
|
@ -1476,10 +1494,9 @@ export default class Store extends EventEmitter<{
|
||||||
parentID,
|
parentID,
|
||||||
children: [],
|
children: [],
|
||||||
name,
|
name,
|
||||||
|
rects,
|
||||||
});
|
});
|
||||||
|
|
||||||
i += 4;
|
|
||||||
|
|
||||||
hasSuspenseTreeChanged = true;
|
hasSuspenseTreeChanged = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1591,6 +1608,61 @@ export default class Store extends EventEmitter<{
|
||||||
hasSuspenseTreeChanged = true;
|
hasSuspenseTreeChanged = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SUSPENSE_TREE_OPERATION_RESIZE: {
|
||||||
|
const id = ((operations[i + 1]: any): number);
|
||||||
|
const numRects = ((operations[i + 2]: any): number);
|
||||||
|
i += 3;
|
||||||
|
|
||||||
|
const suspense = this._idToSuspense.get(id);
|
||||||
|
if (suspense === undefined) {
|
||||||
|
this._throwAndEmitError(
|
||||||
|
Error(
|
||||||
|
`Cannot set rects for suspense node "${id}" because no matching node was found in the Store.`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let nextRects: SuspenseNode['rects'];
|
||||||
|
if (numRects === -1) {
|
||||||
|
nextRects = null;
|
||||||
|
} else {
|
||||||
|
nextRects = [];
|
||||||
|
for (let rectIndex = 0; rectIndex < numRects; rectIndex++) {
|
||||||
|
const x = operations[i + 0];
|
||||||
|
const y = operations[i + 1];
|
||||||
|
const width = operations[i + 2];
|
||||||
|
const height = operations[i + 3];
|
||||||
|
|
||||||
|
nextRects.push({x, y, width, height});
|
||||||
|
|
||||||
|
i += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspense.rects = nextRects;
|
||||||
|
|
||||||
|
if (__DEBUG__) {
|
||||||
|
debug(
|
||||||
|
'Resize',
|
||||||
|
`Suspense node ${id} resize to ${
|
||||||
|
nextRects === null
|
||||||
|
? 'null'
|
||||||
|
: nextRects
|
||||||
|
.map(
|
||||||
|
rect =>
|
||||||
|
`(${rect.x},${rect.y},${rect.width},${rect.height})`,
|
||||||
|
)
|
||||||
|
.join(',')
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasSuspenseTreeChanged = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
this._throwAndEmitError(
|
this._throwAndEmitError(
|
||||||
new UnsupportedBridgeOperationError(
|
new UnsupportedBridgeOperationError(
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,10 @@
|
||||||
import JSON5 from 'json5';
|
import JSON5 from 'json5';
|
||||||
|
|
||||||
import type {ReactFunctionLocation} from 'shared/ReactTypes';
|
import type {ReactFunctionLocation} from 'shared/ReactTypes';
|
||||||
import type {Element} from 'react-devtools-shared/src/frontend/types';
|
import type {
|
||||||
|
Element,
|
||||||
|
SuspenseNode,
|
||||||
|
} from 'react-devtools-shared/src/frontend/types';
|
||||||
import type {StateContext} from './views/Components/TreeContext';
|
import type {StateContext} from './views/Components/TreeContext';
|
||||||
import type Store from './store';
|
import type Store from './store';
|
||||||
|
|
||||||
|
|
@ -28,6 +31,11 @@ export function printElement(
|
||||||
key = ` key="${element.key}"`;
|
key = ` key="${element.key}"`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let name = '';
|
||||||
|
if (element.nameProp !== null) {
|
||||||
|
name = ` name="${element.nameProp}"`;
|
||||||
|
}
|
||||||
|
|
||||||
let hocDisplayNames = null;
|
let hocDisplayNames = null;
|
||||||
if (element.hocDisplayNames !== null) {
|
if (element.hocDisplayNames !== null) {
|
||||||
hocDisplayNames = [...element.hocDisplayNames];
|
hocDisplayNames = [...element.hocDisplayNames];
|
||||||
|
|
@ -43,7 +51,45 @@ export function printElement(
|
||||||
|
|
||||||
return `${' '.repeat(element.depth + 1)}${prefix} <${
|
return `${' '.repeat(element.depth + 1)}${prefix} <${
|
||||||
element.displayName || 'null'
|
element.displayName || 'null'
|
||||||
}${key}>${hocs}${suffix}`;
|
}${key}${name}>${hocs}${suffix}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function printSuspense(
|
||||||
|
suspense: SuspenseNode,
|
||||||
|
includeWeight: boolean = false,
|
||||||
|
): string {
|
||||||
|
let name = '';
|
||||||
|
if (suspense.name !== null) {
|
||||||
|
name = ` name="${suspense.name}"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let printedRects = '';
|
||||||
|
const rects = suspense.rects;
|
||||||
|
if (rects === null) {
|
||||||
|
printedRects = ' rects={null}';
|
||||||
|
} else {
|
||||||
|
printedRects = ` rects={[${rects.map(rect => `{x:${rect.x},y:${rect.y},width:${rect.width},height:${rect.height}}`).join(', ')}]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `<Suspense${name}${printedRects}>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function printSuspenseWithChildren(
|
||||||
|
store: Store,
|
||||||
|
suspense: SuspenseNode,
|
||||||
|
depth: number,
|
||||||
|
): Array<string> {
|
||||||
|
const lines = [' '.repeat(depth) + printSuspense(suspense)];
|
||||||
|
for (let i = 0; i < suspense.children.length; i++) {
|
||||||
|
const childID = suspense.children[i];
|
||||||
|
const child = store.getSuspenseByID(childID);
|
||||||
|
if (child === null) {
|
||||||
|
throw new Error(`Could not find Suspense node with ID "${childID}".`);
|
||||||
|
}
|
||||||
|
lines.push(...printSuspenseWithChildren(store, child, depth + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function printOwnersList(
|
export function printOwnersList(
|
||||||
|
|
@ -59,6 +105,7 @@ export function printStore(
|
||||||
store: Store,
|
store: Store,
|
||||||
includeWeight: boolean = false,
|
includeWeight: boolean = false,
|
||||||
state: StateContext | null = null,
|
state: StateContext | null = null,
|
||||||
|
includeSuspense: boolean = true,
|
||||||
): string {
|
): string {
|
||||||
const snapshotLines = [];
|
const snapshotLines = [];
|
||||||
|
|
||||||
|
|
@ -129,6 +176,26 @@ export function printStore(
|
||||||
}
|
}
|
||||||
|
|
||||||
rootWeight += weight;
|
rootWeight += weight;
|
||||||
|
|
||||||
|
if (includeSuspense) {
|
||||||
|
const shell = store.getSuspenseByID(rootID);
|
||||||
|
// Roots from legacy renderers don't have a separate Suspense tree
|
||||||
|
if (shell !== null) {
|
||||||
|
if (shell.children.length > 0) {
|
||||||
|
snapshotLines.push('[shell]');
|
||||||
|
for (let i = 0; i < shell.children.length; i++) {
|
||||||
|
const childID = shell.children[i];
|
||||||
|
const child = store.getSuspenseByID(childID);
|
||||||
|
if (child === null) {
|
||||||
|
throw new Error(
|
||||||
|
`Could not find Suspense node with ID "${childID}".`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
snapshotLines.push(...printSuspenseWithChildren(store, child, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Make sure the pretty-printed test align with the Store's reported number of total rows.
|
// Make sure the pretty-printed test align with the Store's reported number of total rows.
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import {
|
||||||
SUSPENSE_TREE_OPERATION_ADD,
|
SUSPENSE_TREE_OPERATION_ADD,
|
||||||
SUSPENSE_TREE_OPERATION_REMOVE,
|
SUSPENSE_TREE_OPERATION_REMOVE,
|
||||||
SUSPENSE_TREE_OPERATION_REORDER_CHILDREN,
|
SUSPENSE_TREE_OPERATION_REORDER_CHILDREN,
|
||||||
|
SUSPENSE_TREE_OPERATION_RESIZE,
|
||||||
} from 'react-devtools-shared/src/constants';
|
} from 'react-devtools-shared/src/constants';
|
||||||
import {
|
import {
|
||||||
parseElementDisplayNameFromBackend,
|
parseElementDisplayNameFromBackend,
|
||||||
|
|
@ -376,16 +377,26 @@ function updateTree(
|
||||||
const fiberID = operations[i + 1];
|
const fiberID = operations[i + 1];
|
||||||
const parentID = operations[i + 2];
|
const parentID = operations[i + 2];
|
||||||
const nameStringID = operations[i + 3];
|
const nameStringID = operations[i + 3];
|
||||||
|
const numRects = operations[i + 4];
|
||||||
const name = stringTable[nameStringID];
|
const name = stringTable[nameStringID];
|
||||||
|
|
||||||
i += 4;
|
|
||||||
|
|
||||||
if (__DEBUG__) {
|
if (__DEBUG__) {
|
||||||
|
let rects: string;
|
||||||
|
if (numRects === -1) {
|
||||||
|
rects = 'null';
|
||||||
|
} else {
|
||||||
|
rects =
|
||||||
|
'[' +
|
||||||
|
operations.slice(i + 5, i + 5 + numRects * 4).join(',') +
|
||||||
|
']';
|
||||||
|
}
|
||||||
debug(
|
debug(
|
||||||
'Add suspense',
|
'Add suspense',
|
||||||
`node ${fiberID} (${String(name)}) under ${parentID}`,
|
`node ${fiberID} (name=${JSON.stringify(name)}, rects={${rects}}) under ${parentID}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i += 5 + (numRects === -1 ? 0 : numRects * 4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -416,6 +427,30 @@ function updateTree(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SUSPENSE_TREE_OPERATION_RESIZE: {
|
||||||
|
const suspenseID = ((operations[i + 1]: any): number);
|
||||||
|
const numRects = ((operations[i + 2]: any): number);
|
||||||
|
|
||||||
|
if (__DEBUG__) {
|
||||||
|
if (numRects === -1) {
|
||||||
|
debug('Suspense resize', `suspense ${suspenseID} rects null`);
|
||||||
|
} else {
|
||||||
|
const rects = ((operations.slice(
|
||||||
|
i + 3,
|
||||||
|
i + 3 + numRects * 4,
|
||||||
|
): any): Array<number>);
|
||||||
|
debug(
|
||||||
|
'Suspense resize',
|
||||||
|
`suspense ${suspenseID} rects [${rects.join(',')}]`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 3 + (numRects === -1 ? 0 : numRects * 4);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw Error(`Unsupported Bridge operation "${operation}"`);
|
throw Error(`Unsupported Bridge operation "${operation}"`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -185,11 +185,19 @@ export type Element = {
|
||||||
compiledWithForget: boolean,
|
compiledWithForget: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type Rect = {
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
};
|
||||||
|
|
||||||
export type SuspenseNode = {
|
export type SuspenseNode = {
|
||||||
id: Element['id'],
|
id: Element['id'],
|
||||||
parentID: SuspenseNode['id'] | 0,
|
parentID: SuspenseNode['id'] | 0,
|
||||||
children: Array<SuspenseNode['id']>,
|
children: Array<SuspenseNode['id']>,
|
||||||
name: string | null,
|
name: string | null,
|
||||||
|
rects: null | Array<Rect>,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Serialized version of ReactIOInfo
|
// Serialized version of ReactIOInfo
|
||||||
|
|
|
||||||
55
packages/react-devtools-shared/src/utils.js
vendored
55
packages/react-devtools-shared/src/utils.js
vendored
|
|
@ -43,6 +43,7 @@ import {
|
||||||
SUSPENSE_TREE_OPERATION_ADD,
|
SUSPENSE_TREE_OPERATION_ADD,
|
||||||
SUSPENSE_TREE_OPERATION_REMOVE,
|
SUSPENSE_TREE_OPERATION_REMOVE,
|
||||||
SUSPENSE_TREE_OPERATION_REORDER_CHILDREN,
|
SUSPENSE_TREE_OPERATION_REORDER_CHILDREN,
|
||||||
|
SUSPENSE_TREE_OPERATION_RESIZE,
|
||||||
} from './constants';
|
} from './constants';
|
||||||
import {
|
import {
|
||||||
ComponentFilterElementType,
|
ComponentFilterElementType,
|
||||||
|
|
@ -339,11 +340,34 @@ export function printOperationsArray(operations: Array<number>) {
|
||||||
const parentID = operations[i + 2];
|
const parentID = operations[i + 2];
|
||||||
const nameStringID = operations[i + 3];
|
const nameStringID = operations[i + 3];
|
||||||
const name = stringTable[nameStringID];
|
const name = stringTable[nameStringID];
|
||||||
|
const numRects = operations[i + 4];
|
||||||
|
|
||||||
i += 4;
|
i += 5;
|
||||||
|
|
||||||
|
let rects: string;
|
||||||
|
if (numRects === -1) {
|
||||||
|
rects = 'null';
|
||||||
|
} else {
|
||||||
|
rects = '[';
|
||||||
|
for (let rectIndex = 0; rectIndex < numRects; rectIndex++) {
|
||||||
|
const offset = i + rectIndex * 4;
|
||||||
|
const x = operations[offset + 0];
|
||||||
|
const y = operations[offset + 1];
|
||||||
|
const width = operations[offset + 2];
|
||||||
|
const height = operations[offset + 3];
|
||||||
|
|
||||||
|
if (rectIndex > 0) {
|
||||||
|
rects += ', ';
|
||||||
|
}
|
||||||
|
rects += `(${x}, ${y}, ${width}, ${height})`;
|
||||||
|
|
||||||
|
i += 4;
|
||||||
|
}
|
||||||
|
rects += ']';
|
||||||
|
}
|
||||||
|
|
||||||
logs.push(
|
logs.push(
|
||||||
`Add suspense node ${fiberID} (${String(name)}) under ${parentID}`,
|
`Add suspense node ${fiberID} (${String(name)},rects={${rects}}) under ${parentID}`,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -372,6 +396,33 @@ export function printOperationsArray(operations: Array<number>) {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SUSPENSE_TREE_OPERATION_RESIZE: {
|
||||||
|
const id = ((operations[i + 1]: any): number);
|
||||||
|
const numRects = ((operations[i + 2]: any): number);
|
||||||
|
i += 3;
|
||||||
|
|
||||||
|
if (numRects === -1) {
|
||||||
|
logs.push(`Resize suspense node ${id} to null`);
|
||||||
|
} else {
|
||||||
|
let line = `Resize suspense node ${id} to [`;
|
||||||
|
for (let rectIndex = 0; rectIndex < numRects; rectIndex++) {
|
||||||
|
const x = operations[i + 0];
|
||||||
|
const y = operations[i + 1];
|
||||||
|
const width = operations[i + 2];
|
||||||
|
const height = operations[i + 3];
|
||||||
|
|
||||||
|
if (rectIndex > 0) {
|
||||||
|
line += ', ';
|
||||||
|
}
|
||||||
|
line += `(${x}, ${y}, ${width}, ${height})`;
|
||||||
|
|
||||||
|
i += 4;
|
||||||
|
}
|
||||||
|
logs.push(line + ']');
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw Error(`Unsupported Bridge operation "${operation}"`);
|
throw Error(`Unsupported Bridge operation "${operation}"`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user