|  | 
| 9 | 9 | 
 | 
| 10 | 10 | 'use strict'; | 
| 11 | 11 | 
 | 
|  | 12 | +function normalizeCodeLocInfo(str) { | 
|  | 13 | +  return ( | 
|  | 14 | +    typeof str === 'string' && | 
|  | 15 | +    str.replace(/\n +(?:at|in) ([\S]+)[^\n]*/g, function(m, name) { | 
|  | 16 | +      return '\n    in ' + name + ' (at **)'; | 
|  | 17 | +    }) | 
|  | 18 | +  ); | 
|  | 19 | +} | 
|  | 20 | + | 
| 12 | 21 | describe('Timeline profiler', () => { | 
| 13 | 22 |   let React; | 
| 14 | 23 |   let ReactDOMClient; | 
| @@ -1175,6 +1184,18 @@ describe('Timeline profiler', () => { | 
| 1175 | 1184 |         if (timelineData) { | 
| 1176 | 1185 |           expect(timelineData).toHaveLength(1); | 
| 1177 | 1186 | 
 | 
|  | 1187 | +          // normalize the location for component stack source | 
|  | 1188 | +          // for snapshot testing | 
|  | 1189 | +          timelineData.forEach(data => { | 
|  | 1190 | +            data.schedulingEvents.forEach(event => { | 
|  | 1191 | +              if (event.componentStack) { | 
|  | 1192 | +                event.componentStack = normalizeCodeLocInfo( | 
|  | 1193 | +                  event.componentStack, | 
|  | 1194 | +                ); | 
|  | 1195 | +              } | 
|  | 1196 | +            }); | 
|  | 1197 | +          }); | 
|  | 1198 | + | 
| 1178 | 1199 |           return timelineData[0]; | 
| 1179 | 1200 |         } else { | 
| 1180 | 1201 |           return null; | 
| @@ -1256,27 +1277,35 @@ describe('Timeline profiler', () => { | 
| 1256 | 1277 |           Array [ | 
| 1257 | 1278 |             Object { | 
| 1258 | 1279 |               "componentName": "Example", | 
|  | 1280 | +              "componentStack": " | 
|  | 1281 | +              in Example (at **)", | 
| 1259 | 1282 |               "lanes": "0b0000000000000000000000000000100", | 
| 1260 | 1283 |               "timestamp": 10, | 
| 1261 | 1284 |               "type": "schedule-state-update", | 
| 1262 | 1285 |               "warning": null, | 
| 1263 | 1286 |             }, | 
| 1264 | 1287 |             Object { | 
| 1265 | 1288 |               "componentName": "Example", | 
|  | 1289 | +              "componentStack": " | 
|  | 1290 | +              in Example (at **)", | 
| 1266 | 1291 |               "lanes": "0b0000000000000000000000001000000", | 
| 1267 | 1292 |               "timestamp": 10, | 
| 1268 | 1293 |               "type": "schedule-state-update", | 
| 1269 | 1294 |               "warning": null, | 
| 1270 | 1295 |             }, | 
| 1271 | 1296 |             Object { | 
| 1272 | 1297 |               "componentName": "Example", | 
|  | 1298 | +              "componentStack": " | 
|  | 1299 | +              in Example (at **)", | 
| 1273 | 1300 |               "lanes": "0b0000000000000000000000001000000", | 
| 1274 | 1301 |               "timestamp": 10, | 
| 1275 | 1302 |               "type": "schedule-state-update", | 
| 1276 | 1303 |               "warning": null, | 
| 1277 | 1304 |             }, | 
| 1278 | 1305 |             Object { | 
| 1279 | 1306 |               "componentName": "Example", | 
|  | 1307 | +              "componentStack": " | 
|  | 1308 | +              in Example (at **)", | 
| 1280 | 1309 |               "lanes": "0b0000000000000000000000000010000", | 
| 1281 | 1310 |               "timestamp": 10, | 
| 1282 | 1311 |               "type": "schedule-state-update", | 
| @@ -1614,6 +1643,8 @@ describe('Timeline profiler', () => { | 
| 1614 | 1643 |             }, | 
| 1615 | 1644 |             Object { | 
| 1616 | 1645 |               "componentName": "Example", | 
|  | 1646 | +              "componentStack": " | 
|  | 1647 | +              in Example (at **)", | 
| 1617 | 1648 |               "lanes": "0b0000000000000000000000000000001", | 
| 1618 | 1649 |               "timestamp": 20, | 
| 1619 | 1650 |               "type": "schedule-state-update", | 
| @@ -1741,6 +1772,8 @@ describe('Timeline profiler', () => { | 
| 1741 | 1772 |             }, | 
| 1742 | 1773 |             Object { | 
| 1743 | 1774 |               "componentName": "Example", | 
|  | 1775 | +              "componentStack": " | 
|  | 1776 | +              in Example (at **)", | 
| 1744 | 1777 |               "lanes": "0b0000000000000000000000000010000", | 
| 1745 | 1778 |               "timestamp": 10, | 
| 1746 | 1779 |               "type": "schedule-state-update", | 
| @@ -1872,6 +1905,8 @@ describe('Timeline profiler', () => { | 
| 1872 | 1905 |             }, | 
| 1873 | 1906 |             Object { | 
| 1874 | 1907 |               "componentName": "Example", | 
|  | 1908 | +              "componentStack": " | 
|  | 1909 | +              in Example (at **)", | 
| 1875 | 1910 |               "lanes": "0b0000000000000000000000000000001", | 
| 1876 | 1911 |               "timestamp": 21, | 
| 1877 | 1912 |               "type": "schedule-state-update", | 
| @@ -1934,6 +1969,8 @@ describe('Timeline profiler', () => { | 
| 1934 | 1969 |             }, | 
| 1935 | 1970 |             Object { | 
| 1936 | 1971 |               "componentName": "Example", | 
|  | 1972 | +              "componentStack": " | 
|  | 1973 | +              in Example (at **)", | 
| 1937 | 1974 |               "lanes": "0b0000000000000000000000000010000", | 
| 1938 | 1975 |               "timestamp": 21, | 
| 1939 | 1976 |               "type": "schedule-state-update", | 
| @@ -1982,6 +2019,8 @@ describe('Timeline profiler', () => { | 
| 1982 | 2019 |             }, | 
| 1983 | 2020 |             Object { | 
| 1984 | 2021 |               "componentName": "Example", | 
|  | 2022 | +              "componentStack": " | 
|  | 2023 | +              in Example (at **)", | 
| 1985 | 2024 |               "lanes": "0b0000000000000000000000000010000", | 
| 1986 | 2025 |               "timestamp": 20, | 
| 1987 | 2026 |               "type": "schedule-state-update", | 
| @@ -2065,6 +2104,8 @@ describe('Timeline profiler', () => { | 
| 2065 | 2104 |             }, | 
| 2066 | 2105 |             Object { | 
| 2067 | 2106 |               "componentName": "ErrorBoundary", | 
|  | 2107 | +              "componentStack": " | 
|  | 2108 | +              in ErrorBoundary (at **)", | 
| 2068 | 2109 |               "lanes": "0b0000000000000000000000000000001", | 
| 2069 | 2110 |               "timestamp": 20, | 
| 2070 | 2111 |               "type": "schedule-state-update", | 
| @@ -2177,6 +2218,8 @@ describe('Timeline profiler', () => { | 
| 2177 | 2218 |             }, | 
| 2178 | 2219 |             Object { | 
| 2179 | 2220 |               "componentName": "ErrorBoundary", | 
|  | 2221 | +              "componentStack": " | 
|  | 2222 | +              in ErrorBoundary (at **)", | 
| 2180 | 2223 |               "lanes": "0b0000000000000000000000000000001", | 
| 2181 | 2224 |               "timestamp": 30, | 
| 2182 | 2225 |               "type": "schedule-state-update", | 
| @@ -2441,6 +2484,52 @@ describe('Timeline profiler', () => { | 
| 2441 | 2484 |           } | 
| 2442 | 2485 |         `); | 
| 2443 | 2486 |       }); | 
|  | 2487 | + | 
|  | 2488 | +      it('should generate component stacks for state update', async () => { | 
|  | 2489 | +        function CommponentWithChildren({initialRender}) { | 
|  | 2490 | +          Scheduler.unstable_yieldValue('Render ComponentWithChildren'); | 
|  | 2491 | +          return <Child initialRender={initialRender} />; | 
|  | 2492 | +        } | 
|  | 2493 | + | 
|  | 2494 | +        function Child({initialRender}) { | 
|  | 2495 | +          const [didRender, setDidRender] = React.useState(initialRender); | 
|  | 2496 | +          if (!didRender) { | 
|  | 2497 | +            setDidRender(true); | 
|  | 2498 | +          } | 
|  | 2499 | +          Scheduler.unstable_yieldValue('Render Child'); | 
|  | 2500 | +          return null; | 
|  | 2501 | +        } | 
|  | 2502 | + | 
|  | 2503 | +        renderRootHelper(<CommponentWithChildren initialRender={false} />); | 
|  | 2504 | + | 
|  | 2505 | +        expect(Scheduler).toFlushAndYield([ | 
|  | 2506 | +          'Render ComponentWithChildren', | 
|  | 2507 | +          'Render Child', | 
|  | 2508 | +          'Render Child', | 
|  | 2509 | +        ]); | 
|  | 2510 | + | 
|  | 2511 | +        const timelineData = stopProfilingAndGetTimelineData(); | 
|  | 2512 | +        expect(timelineData.schedulingEvents).toMatchInlineSnapshot(` | 
|  | 2513 | +          Array [ | 
|  | 2514 | +            Object { | 
|  | 2515 | +              "lanes": "0b0000000000000000000000000010000", | 
|  | 2516 | +              "timestamp": 10, | 
|  | 2517 | +              "type": "schedule-render", | 
|  | 2518 | +              "warning": null, | 
|  | 2519 | +            }, | 
|  | 2520 | +            Object { | 
|  | 2521 | +              "componentName": "Child", | 
|  | 2522 | +              "componentStack": " | 
|  | 2523 | +              in Child (at **) | 
|  | 2524 | +              in CommponentWithChildren (at **)", | 
|  | 2525 | +              "lanes": "0b0000000000000000000000000010000", | 
|  | 2526 | +              "timestamp": 10, | 
|  | 2527 | +              "type": "schedule-state-update", | 
|  | 2528 | +              "warning": null, | 
|  | 2529 | +            }, | 
|  | 2530 | +          ] | 
|  | 2531 | +        `); | 
|  | 2532 | +      }); | 
| 2444 | 2533 |     }); | 
| 2445 | 2534 | 
 | 
| 2446 | 2535 |     describe('when not profiling', () => { | 
|  | 
0 commit comments