From cb151849e13f46ec64570519cb93d5939fb60cab Mon Sep 17 00:00:00 2001 From: Josh Story Date: Wed, 24 Apr 2024 08:50:32 -0700 Subject: [PATCH] [react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether --- .../src/__tests__/TimelineProfiler-test.js | 2368 +++++++++-------- .../src/__tests__/preprocessData-test.js | 70 +- .../src/e2e-regression/app.js | 7 +- .../src/e2e-regression/devtools.js | 7 +- packages/react-devtools-shell/src/e2e/app.js | 7 +- .../react-devtools-shell/src/e2e/devtools.js | 7 +- .../react-devtools-shell/webpack-server.js | 12 +- .../src/client/ReactDOMContainer.js | 42 + packages/react-dom/client.js | 48 +- packages/react-dom/index.experimental.js | 28 - packages/react-dom/index.js | 16 +- packages/react-dom/index.stable.js | 27 - packages/react-dom/npm/client.js | 53 +- packages/react-dom/npm/profiling.js | 4 +- .../react-dom/npm/server-rendering-stub.js | 7 - packages/react-dom/package.json | 2 - packages/react-dom/profiling.js | 12 + packages/react-dom/server-rendering-stub.js | 61 - .../ReactDOMFB.js} | 10 +- .../ReactDOMFB.modern.js} | 7 +- ...actDOMServer.js => ReactDOMReactServer.js} | 0 .../react-dom/src/ReactDOMSharedInternals.js | 6 - .../ReactDOMTestingFB.js} | 19 +- .../react-dom/src/ReactDOMTestingFB.modern.js | 23 + .../react-dom/src/__tests__/ReactDOM-test.js | 4 +- .../src/__tests__/ReactDOMRoot-test.js | 22 - ...DOMServerPartialHydration-test.internal.js | 2 +- ...MServerSelectiveHydration-test.internal.js | 6 +- .../ReactDOMSuspensePlaceholder-test.js | 2 +- .../src/__tests__/ReactEmptyComponent-test.js | 2 +- .../ReactLegacyCompositeComponent-test.js | 2 +- .../src/__tests__/ReactUpdates-test.js | 2 +- .../react-dom-server-rendering-stub-test.js | 99 - packages/react-dom/src/client/ReactDOM.js | 204 -- .../react-dom/src/client/ReactDOMClient.js | 84 + .../{ReactDOMFB.js => ReactDOMClientFB.js} | 2 +- packages/react-dom/src/client/ReactDOMRoot.js | 34 +- .../react-dom/src/client/ReactDOMRootFB.js | 2 +- .../src/server/ReactDOMServerRenderingStub.js | 48 - packages/react-dom/src/shared/ReactDOM.js | 84 + .../react-dom/unstable_testing.classic.fb.js | 45 - .../unstable_testing.experimental.js | 18 +- packages/react-dom/unstable_testing.js | 32 +- packages/react-dom/unstable_testing.stable.js | 25 - .../__tests__/ReactFlightDOMBrowser-test.js | 29 +- scripts/jest/setupHostConfigs.js | 37 +- scripts/rollup/bundles.js | 71 +- scripts/rollup/forks.js | 6 +- scripts/rollup/modules.js | 1 - scripts/shared/inlinedHostConfigs.js | 59 +- scripts/shared/pathsByLanguageVersion.js | 2 - 51 files changed, 1715 insertions(+), 2052 deletions(-) create mode 100644 packages/react-dom-bindings/src/client/ReactDOMContainer.js delete mode 100644 packages/react-dom/index.experimental.js delete mode 100644 packages/react-dom/index.stable.js delete mode 100644 packages/react-dom/npm/server-rendering-stub.js create mode 100644 packages/react-dom/profiling.js delete mode 100644 packages/react-dom/server-rendering-stub.js rename packages/react-dom/{index.classic.fb.js => src/ReactDOMFB.js} (88%) rename packages/react-dom/{index.modern.fb.js => src/ReactDOMFB.modern.js} (79%) rename packages/react-dom/src/{ReactDOMServer.js => ReactDOMReactServer.js} (100%) rename packages/react-dom/{unstable_testing.modern.fb.js => src/ReactDOMTestingFB.js} (57%) create mode 100644 packages/react-dom/src/ReactDOMTestingFB.modern.js delete mode 100644 packages/react-dom/src/__tests__/react-dom-server-rendering-stub-test.js delete mode 100644 packages/react-dom/src/client/ReactDOM.js create mode 100644 packages/react-dom/src/client/ReactDOMClient.js rename packages/react-dom/src/client/{ReactDOMFB.js => ReactDOMClientFB.js} (98%) delete mode 100644 packages/react-dom/src/server/ReactDOMServerRenderingStub.js create mode 100644 packages/react-dom/src/shared/ReactDOM.js delete mode 100644 packages/react-dom/unstable_testing.classic.fb.js delete mode 100644 packages/react-dom/unstable_testing.stable.js diff --git a/packages/react-devtools-shared/src/__tests__/TimelineProfiler-test.js b/packages/react-devtools-shared/src/__tests__/TimelineProfiler-test.js index a09b4e54de4ca..acffea6a42c45 100644 --- a/packages/react-devtools-shared/src/__tests__/TimelineProfiler-test.js +++ b/packages/react-devtools-shared/src/__tests__/TimelineProfiler-test.js @@ -121,21 +121,21 @@ describe('Timeline profiler', () => { legacyRender(
); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-1", - "--render-start-1", - "--render-stop", - "--commit-start-1", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen", - "--layout-effects-start-1", - "--layout-effects-stop", - "--commit-stop", - ] - `); + [ + "--schedule-render-1", + "--render-start-1", + "--render-stop", + "--commit-start-1", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen", + "--layout-effects-start-1", + "--layout-effects-stop", + "--commit-stop", + ] + `); }); // TODO(hoxyq): investigate why running this test with React 18 fails @@ -154,24 +154,24 @@ describe('Timeline profiler', () => { ); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-2", - "--render-start-2", - "--component-render-start-Example", - "--component-render-stop", - "--suspense-suspend-0-Example-mount-2-", - "--render-stop", - "--commit-start-2", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-2", - "--layout-effects-stop", - "--commit-stop", - ] - `); + [ + "--schedule-render-2", + "--render-start-2", + "--component-render-start-Example", + "--component-render-stop", + "--suspense-suspend-0-Example-mount-2-", + "--render-stop", + "--commit-start-2", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-2", + "--layout-effects-stop", + "--commit-stop", + ] + `); clearPendingMarks(); @@ -199,24 +199,24 @@ describe('Timeline profiler', () => { ); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-2", - "--render-start-2", - "--component-render-start-Example", - "--component-render-stop", - "--suspense-suspend-0-Example-mount-2-", - "--render-stop", - "--commit-start-2", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-2", - "--layout-effects-stop", - "--commit-stop", - ] - `); + [ + "--schedule-render-2", + "--render-start-2", + "--component-render-start-Example", + "--component-render-stop", + "--suspense-suspend-0-Example-mount-2-", + "--render-stop", + "--commit-start-2", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-2", + "--layout-effects-stop", + "--commit-stop", + ] + `); clearPendingMarks(); @@ -253,39 +253,39 @@ describe('Timeline profiler', () => { ); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-1", - "--render-start-1", - "--component-render-start-ErrorBoundary", - "--component-render-stop", - "--component-render-start-ExampleThatThrows", - "--component-render-start-ExampleThatThrows", - "--component-render-stop", - "--error-ExampleThatThrows-mount-Expected error", - "--render-stop", - "--commit-start-1", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen", - "--layout-effects-start-1", - "--schedule-state-update-1-ErrorBoundary", - "--layout-effects-stop", - "--commit-stop", - "--render-start-1", - "--component-render-start-ErrorBoundary", - "--component-render-stop", - "--render-stop", - "--commit-start-1", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen", - "--commit-stop", - ] - `); + [ + "--schedule-render-1", + "--render-start-1", + "--component-render-start-ErrorBoundary", + "--component-render-stop", + "--component-render-start-ExampleThatThrows", + "--component-render-start-ExampleThatThrows", + "--component-render-stop", + "--error-ExampleThatThrows-mount-Expected error", + "--render-stop", + "--commit-start-1", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen", + "--layout-effects-start-1", + "--schedule-state-update-1-ErrorBoundary", + "--layout-effects-stop", + "--commit-stop", + "--render-start-1", + "--component-render-start-ErrorBoundary", + "--component-render-stop", + "--render-stop", + "--commit-start-1", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen", + "--commit-stop", + ] + `); }); }); @@ -309,30 +309,32 @@ describe('Timeline profiler', () => { modernRender(
); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-32", - ] - `); + [ + "--schedule-render-32", + ] + `); clearPendingMarks(); await waitForPaint([]); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--render-start-32", - "--render-stop", - "--commit-start-32", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-32", - "--layout-effects-stop", - "--commit-stop", - ] - `); + [ + "--render-start-32", + "--render-stop", + "--commit-start-32", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-32", + "--layout-effects-stop", + "--commit-stop", + ] + `); }); it('should mark render yields', async () => { @@ -353,14 +355,14 @@ describe('Timeline profiler', () => { await waitFor(['Foo']); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-128", - "--render-start-128", - "--component-render-start-Foo", - "--component-render-stop", - "--render-yield", - ] - `); + [ + "--schedule-render-128", + "--render-start-128", + "--component-render-start-Foo", + "--component-render-stop", + "--render-yield", + ] + `); }); it('should mark concurrent render with suspense that resolves', async () => { @@ -380,33 +382,35 @@ describe('Timeline profiler', () => { ); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-32", - ] - `); + [ + "--schedule-render-32", + ] + `); clearPendingMarks(); await waitForPaint([]); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--render-start-32", - "--component-render-start-Example", - "--component-render-stop", - "--suspense-suspend-0-Example-mount-32-", - "--render-stop", - "--commit-start-32", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-32", - "--layout-effects-stop", - "--commit-stop", - ] - `); + [ + "--render-start-32", + "--component-render-start-Example", + "--component-render-stop", + "--suspense-suspend-0-Example-mount-32-", + "--render-stop", + "--commit-start-32", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-32", + "--layout-effects-stop", + "--commit-stop", + ] + `); clearPendingMarks(); @@ -435,33 +439,35 @@ describe('Timeline profiler', () => { ); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-32", - ] - `); + [ + "--schedule-render-32", + ] + `); clearPendingMarks(); await waitForPaint([]); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--render-start-32", - "--component-render-start-Example", - "--component-render-stop", - "--suspense-suspend-0-Example-mount-32-", - "--render-stop", - "--commit-start-32", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-32", - "--layout-effects-stop", - "--commit-stop", - ] - `); + [ + "--render-start-32", + "--component-render-start-Example", + "--component-render-stop", + "--suspense-suspend-0-Example-mount-32-", + "--render-stop", + "--commit-start-32", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-32", + "--layout-effects-stop", + "--commit-stop", + ] + `); clearPendingMarks(); @@ -490,44 +496,48 @@ describe('Timeline profiler', () => { modernRender(); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-32", - ] - `); + [ + "--schedule-render-32", + ] + `); clearPendingMarks(); await waitForPaint([]); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--render-start-32", - "--component-render-start-Example", - "--component-render-stop", - "--render-stop", - "--commit-start-32", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-32", - "--schedule-state-update-2-Example", - "--layout-effects-stop", - "--render-start-2", - "--component-render-start-Example", - "--component-render-stop", - "--render-stop", - "--commit-start-2", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--commit-stop", - "--commit-stop", - ] - `); + [ + "--render-start-32", + "--component-render-start-Example", + "--component-render-stop", + "--render-stop", + "--commit-start-32", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-32", + "--schedule-state-update-2-Example", + "--layout-effects-stop", + "--render-start-2", + "--component-render-start-Example", + "--component-render-stop", + "--render-stop", + "--commit-start-2", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--commit-stop", + "--commit-stop", + ] + `); }); it('should mark cascading class component force updates', async () => { @@ -543,44 +553,48 @@ describe('Timeline profiler', () => { modernRender(); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-32", - ] - `); + [ + "--schedule-render-32", + ] + `); clearPendingMarks(); await waitForPaint([]); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--render-start-32", - "--component-render-start-Example", - "--component-render-stop", - "--render-stop", - "--commit-start-32", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-32", - "--schedule-forced-update-2-Example", - "--layout-effects-stop", - "--render-start-2", - "--component-render-start-Example", - "--component-render-stop", - "--render-stop", - "--commit-start-2", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--commit-stop", - "--commit-stop", - ] - `); + [ + "--render-start-32", + "--component-render-start-Example", + "--component-render-stop", + "--render-stop", + "--commit-start-32", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-32", + "--schedule-forced-update-2-Example", + "--layout-effects-stop", + "--render-start-2", + "--component-render-start-Example", + "--component-render-stop", + "--render-stop", + "--commit-start-2", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--commit-stop", + "--commit-stop", + ] + `); }); it('should mark render phase state updates for class component', async () => { @@ -597,10 +611,10 @@ describe('Timeline profiler', () => { modernRender(); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-32", - ] - `); + [ + "--schedule-render-32", + ] + `); clearPendingMarks(); @@ -617,23 +631,25 @@ describe('Timeline profiler', () => { ); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--render-start-32", - "--component-render-start-Example", - "--schedule-state-update-32-Example", - "--component-render-stop", - "--render-stop", - "--commit-start-32", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-32", - "--layout-effects-stop", - "--commit-stop", - ] - `); + [ + "--render-start-32", + "--component-render-start-Example", + "--schedule-state-update-32-Example", + "--component-render-stop", + "--render-stop", + "--commit-start-32", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-32", + "--layout-effects-stop", + "--commit-stop", + ] + `); }); it('should mark render phase force updates for class component', async () => { @@ -651,10 +667,10 @@ describe('Timeline profiler', () => { modernRender(); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-32", - ] - `); + [ + "--schedule-render-32", + ] + `); clearPendingMarks(); @@ -671,23 +687,25 @@ describe('Timeline profiler', () => { ); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--render-start-32", - "--component-render-start-Example", - "--schedule-forced-update-32-Example", - "--component-render-stop", - "--render-stop", - "--commit-start-32", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-32", - "--layout-effects-stop", - "--commit-stop", - ] - `); + [ + "--render-start-32", + "--component-render-start-Example", + "--schedule-forced-update-32-Example", + "--component-render-stop", + "--render-stop", + "--commit-start-32", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-32", + "--layout-effects-stop", + "--commit-stop", + ] + `); }); it('should mark cascading layout updates', async () => { @@ -702,46 +720,50 @@ describe('Timeline profiler', () => { modernRender(); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-32", - ] - `); + [ + "--schedule-render-32", + ] + `); clearPendingMarks(); await waitForPaint([]); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--render-start-32", - "--component-render-start-Example", - "--component-render-stop", - "--render-stop", - "--commit-start-32", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-32", - "--component-layout-effect-mount-start-Example", - "--schedule-state-update-2-Example", - "--component-layout-effect-mount-stop", - "--layout-effects-stop", - "--render-start-2", - "--component-render-start-Example", - "--component-render-stop", - "--render-stop", - "--commit-start-2", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--commit-stop", - "--commit-stop", - ] - `); + [ + "--render-start-32", + "--component-render-start-Example", + "--component-render-stop", + "--render-stop", + "--commit-start-32", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-32", + "--component-layout-effect-mount-start-Example", + "--schedule-state-update-2-Example", + "--component-layout-effect-mount-stop", + "--layout-effects-stop", + "--render-start-2", + "--component-render-start-Example", + "--component-render-stop", + "--render-stop", + "--commit-start-2", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--commit-stop", + "--commit-stop", + ] + `); }); it('should mark cascading passive updates', async () => { @@ -758,39 +780,43 @@ describe('Timeline profiler', () => { await waitForAll([]); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-32", - "--render-start-32", - "--component-render-start-Example", - "--component-render-stop", - "--render-stop", - "--commit-start-32", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-32", - "--layout-effects-stop", - "--commit-stop", - "--passive-effects-start-32", - "--component-passive-effect-mount-start-Example", - "--schedule-state-update-32-Example", - "--component-passive-effect-mount-stop", - "--passive-effects-stop", - "--render-start-32", - "--component-render-start-Example", - "--component-render-stop", - "--render-stop", - "--commit-start-32", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--commit-stop", - ] - `); + [ + "--schedule-render-32", + "--render-start-32", + "--component-render-start-Example", + "--component-render-stop", + "--render-stop", + "--commit-start-32", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-32", + "--layout-effects-stop", + "--commit-stop", + "--passive-effects-start-32", + "--component-passive-effect-mount-start-Example", + "--schedule-state-update-32-Example", + "--component-passive-effect-mount-stop", + "--passive-effects-stop", + "--render-start-32", + "--component-render-start-Example", + "--component-render-stop", + "--render-stop", + "--commit-start-32", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--commit-stop", + ] + `); }); it('should mark render phase updates', async () => { @@ -807,24 +833,26 @@ describe('Timeline profiler', () => { await waitForAll([]); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-32", - "--render-start-32", - "--component-render-start-Example", - "--schedule-state-update-32-Example", - "--component-render-stop", - "--render-stop", - "--commit-start-32", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-32", - "--layout-effects-stop", - "--commit-stop", - ] - `); + [ + "--schedule-render-32", + "--render-start-32", + "--component-render-start-Example", + "--schedule-state-update-32-Example", + "--component-render-stop", + "--render-stop", + "--commit-start-32", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-32", + "--layout-effects-stop", + "--commit-stop", + ] + `); }); it('should mark concurrent render that throws', async () => { @@ -855,54 +883,58 @@ describe('Timeline profiler', () => { ); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-32", - ] - `); + [ + "--schedule-render-32", + ] + `); clearPendingMarks(); await waitForPaint([]); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--render-start-32", - "--component-render-start-ErrorBoundary", - "--component-render-stop", - "--component-render-start-ExampleThatThrows", - "--component-render-stop", - "--error-ExampleThatThrows-mount-Expected error", - "--render-stop", - "--render-start-32", - "--component-render-start-ErrorBoundary", - "--component-render-stop", - "--component-render-start-ExampleThatThrows", - "--component-render-stop", - "--error-ExampleThatThrows-mount-Expected error", - "--render-stop", - "--commit-start-32", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-32", - "--schedule-state-update-2-ErrorBoundary", - "--layout-effects-stop", - "--render-start-2", - "--component-render-start-ErrorBoundary", - "--component-render-stop", - "--render-stop", - "--commit-start-2", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--commit-stop", - "--commit-stop", - ] - `); + [ + "--render-start-32", + "--component-render-start-ErrorBoundary", + "--component-render-stop", + "--component-render-start-ExampleThatThrows", + "--component-render-stop", + "--error-ExampleThatThrows-mount-Expected error", + "--render-stop", + "--render-start-32", + "--component-render-start-ErrorBoundary", + "--component-render-stop", + "--component-render-start-ExampleThatThrows", + "--component-render-stop", + "--error-ExampleThatThrows-mount-Expected error", + "--render-stop", + "--commit-start-32", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-32", + "--schedule-state-update-2-ErrorBoundary", + "--layout-effects-stop", + "--render-start-2", + "--component-render-start-ErrorBoundary", + "--component-render-stop", + "--render-stop", + "--commit-start-2", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--commit-stop", + "--commit-stop", + ] + `); }); it('should mark passive and layout effects', async () => { @@ -950,27 +982,29 @@ describe('Timeline profiler', () => { await waitForPaint(['layout 1 mount', 'layout 2 mount']); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-32", - "--render-start-32", - "--component-render-start-ComponentWithEffects", - "--component-render-stop", - "--render-stop", - "--commit-start-32", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-32", - "--component-layout-effect-mount-start-ComponentWithEffects", - "--component-layout-effect-mount-stop", - "--component-layout-effect-mount-start-ComponentWithEffects", - "--component-layout-effect-mount-stop", - "--layout-effects-stop", - "--commit-stop", - ] - `); + [ + "--schedule-render-32", + "--render-start-32", + "--component-render-start-ComponentWithEffects", + "--component-render-stop", + "--render-stop", + "--commit-start-32", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-32", + "--component-layout-effect-mount-start-ComponentWithEffects", + "--component-layout-effect-mount-stop", + "--component-layout-effect-mount-start-ComponentWithEffects", + "--component-layout-effect-mount-stop", + "--layout-effects-stop", + "--commit-stop", + ] + `); clearPendingMarks(); @@ -981,17 +1015,17 @@ describe('Timeline profiler', () => { ]); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--passive-effects-start-32", - "--component-passive-effect-mount-start-ComponentWithEffects", - "--component-passive-effect-mount-stop", - "--component-passive-effect-mount-start-ComponentWithEffects", - "--component-passive-effect-mount-stop", - "--component-passive-effect-mount-start-ComponentWithEffects", - "--component-passive-effect-mount-stop", - "--passive-effects-stop", - ] - `); + [ + "--passive-effects-start-32", + "--component-passive-effect-mount-start-ComponentWithEffects", + "--component-passive-effect-mount-stop", + "--component-passive-effect-mount-start-ComponentWithEffects", + "--component-passive-effect-mount-stop", + "--component-passive-effect-mount-start-ComponentWithEffects", + "--component-passive-effect-mount-stop", + "--passive-effects-stop", + ] + `); clearPendingMarks(); @@ -1008,33 +1042,35 @@ describe('Timeline profiler', () => { ]); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-2", - "--render-start-2", - "--render-stop", - "--commit-start-2", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--component-layout-effect-unmount-start-ComponentWithEffects", - "--component-layout-effect-unmount-stop", - "--component-layout-effect-unmount-start-ComponentWithEffects", - "--component-layout-effect-unmount-stop", - "--layout-effects-start-2", - "--layout-effects-stop", - "--passive-effects-start-2", - "--component-passive-effect-unmount-start-ComponentWithEffects", - "--component-passive-effect-unmount-stop", - "--component-passive-effect-unmount-start-ComponentWithEffects", - "--component-passive-effect-unmount-stop", - "--component-passive-effect-unmount-start-ComponentWithEffects", - "--component-passive-effect-unmount-stop", - "--passive-effects-stop", - "--commit-stop", - ] - `); + [ + "--schedule-render-2", + "--render-start-2", + "--render-stop", + "--commit-start-2", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--component-layout-effect-unmount-start-ComponentWithEffects", + "--component-layout-effect-unmount-stop", + "--component-layout-effect-unmount-start-ComponentWithEffects", + "--component-layout-effect-unmount-stop", + "--layout-effects-start-2", + "--layout-effects-stop", + "--passive-effects-start-2", + "--component-passive-effect-unmount-start-ComponentWithEffects", + "--component-passive-effect-unmount-stop", + "--component-passive-effect-unmount-start-ComponentWithEffects", + "--component-passive-effect-unmount-stop", + "--component-passive-effect-unmount-start-ComponentWithEffects", + "--component-passive-effect-unmount-stop", + "--passive-effects-stop", + "--commit-stop", + ] + `); }); }); @@ -1048,21 +1084,21 @@ describe('Timeline profiler', () => { legacyRender(
); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-1", - "--render-start-1", - "--render-stop", - "--commit-start-1", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen", - "--layout-effects-start-1", - "--layout-effects-stop", - "--commit-stop", - ] - `); + [ + "--schedule-render-1", + "--render-start-1", + "--render-stop", + "--commit-start-1", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen", + "--layout-effects-start-1", + "--layout-effects-stop", + "--commit-stop", + ] + `); }); }); @@ -1079,10 +1115,10 @@ describe('Timeline profiler', () => { it('regression test DefaultLane', () => { modernRender(
); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-render-32", - ] - `); + [ + "--schedule-render-32", + ] + `); }); it('regression test InputDiscreteLane', async () => { @@ -1107,23 +1143,25 @@ describe('Timeline profiler', () => { await Promise.resolve(); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-state-update-2-App", - "--render-start-2", - "--component-render-start-App", - "--component-render-stop", - "--render-stop", - "--commit-start-2", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-2", - "--layout-effects-stop", - "--commit-stop", - ] - `); + [ + "--schedule-state-update-2-App", + "--render-start-2", + "--component-render-start-App", + "--component-render-stop", + "--render-stop", + "--commit-start-2", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-2", + "--layout-effects-stop", + "--commit-stop", + ] + `); }); it('regression test InputContinuousLane', async () => { @@ -1147,23 +1185,25 @@ describe('Timeline profiler', () => { await waitForAll([]); expect(clearedMarks).toMatchInlineSnapshot(` - [ - "--schedule-state-update-8-App", - "--render-start-8", - "--component-render-start-App", - "--component-render-stop", - "--render-stop", - "--commit-start-8", - "--react-version-", - "--profiler-version-1", - "--react-internal-module-start- at filtered (:0:0)", - "--react-internal-module-stop- at filtered (:1:1)", - "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", - "--layout-effects-start-8", - "--layout-effects-stop", - "--commit-stop", - ] - `); + [ + "--schedule-state-update-8-App", + "--render-start-8", + "--component-render-start-App", + "--component-render-stop", + "--render-stop", + "--commit-start-8", + "--react-version-", + "--profiler-version-1", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-internal-module-start- at filtered (:0:0)", + "--react-internal-module-stop- at filtered (:1:1)", + "--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred", + "--layout-effects-start-8", + "--layout-effects-stop", + "--commit-stop", + ] + `); }); }); }); @@ -1229,15 +1269,15 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); expect(timelineData.schedulingEvents).toMatchInlineSnapshot(` - [ - { - "lanes": "0b0000000000000000000000000000001", - "timestamp": 10, - "type": "schedule-render", - "warning": null, - }, - ] - `); + [ + { + "lanes": "0b0000000000000000000000000000001", + "timestamp": 10, + "type": "schedule-render", + "warning": null, + }, + ] + `); }); // @reactVersion <= 18.2 @@ -1281,60 +1321,60 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); expect(timelineData.componentMeasures).toMatchInlineSnapshot(` - [ - { - "componentName": "ErrorBoundary", - "duration": 10, - "timestamp": 10, - "type": "render", - "warning": null, - }, - { - "componentName": "ExampleThatThrows", - "duration": 0, - "timestamp": 20, - "type": "render", - "warning": null, - }, - { - "componentName": "ErrorBoundary", - "duration": 10, - "timestamp": 20, - "type": "render", - "warning": null, - }, - ] - `); + [ + { + "componentName": "ErrorBoundary", + "duration": 10, + "timestamp": 10, + "type": "render", + "warning": null, + }, + { + "componentName": "ExampleThatThrows", + "duration": 0, + "timestamp": 20, + "type": "render", + "warning": null, + }, + { + "componentName": "ErrorBoundary", + "duration": 10, + "timestamp": 20, + "type": "render", + "warning": null, + }, + ] + `); expect(timelineData.schedulingEvents).toMatchInlineSnapshot(` - [ - { - "lanes": "0b0000000000000000000000000000001", - "timestamp": 10, - "type": "schedule-render", - "warning": null, - }, - { - "componentName": "ErrorBoundary", - "componentStack": " - in ErrorBoundary (at **)", - "lanes": "0b0000000000000000000000000000001", - "timestamp": 20, - "type": "schedule-state-update", - "warning": null, - }, - ] - `); + [ + { + "lanes": "0b0000000000000000000000000000001", + "timestamp": 10, + "type": "schedule-render", + "warning": null, + }, + { + "componentName": "ErrorBoundary", + "componentStack": " + in ErrorBoundary (at **)", + "lanes": "0b0000000000000000000000000000001", + "timestamp": 20, + "type": "schedule-state-update", + "warning": null, + }, + ] + `); expect(timelineData.thrownErrors).toMatchInlineSnapshot(` - [ - { - "componentName": "ExampleThatThrows", - "message": "Expected error", - "phase": "mount", - "timestamp": 20, - "type": "thrown-error", - }, - ] - `); + [ + { + "componentName": "ExampleThatThrows", + "message": "Expected error", + "phase": "mount", + "timestamp": 20, + "type": "thrown-error", + }, + ] + `); }); // @reactVersion <= 18.2 @@ -1378,19 +1418,19 @@ describe('Timeline profiler', () => { expect(timelineData.suspenseEvents).toHaveLength(1); const suspenseEvent = timelineData.suspenseEvents[0]; expect(suspenseEvent).toMatchInlineSnapshot(` - { - "componentName": "Example", - "depth": 0, - "duration": 10, - "id": "0", - "phase": "mount", - "promiseName": "", - "resolution": "resolved", - "timestamp": 10, - "type": "suspense", - "warning": null, - } - `); + { + "componentName": "Example", + "depth": 0, + "duration": 10, + "id": "0", + "phase": "mount", + "promiseName": "", + "resolution": "resolved", + "timestamp": 10, + "type": "suspense", + "warning": null, + } + `); // There should be two batches of renders: Suspeneded and resolved. expect(timelineData.batchUIDToMeasuresMap.size).toBe(2); @@ -1436,19 +1476,19 @@ describe('Timeline profiler', () => { expect(timelineData.suspenseEvents).toHaveLength(1); const suspenseEvent = timelineData.suspenseEvents[0]; expect(suspenseEvent).toMatchInlineSnapshot(` - { - "componentName": "Example", - "depth": 0, - "duration": 10, - "id": "0", - "phase": "mount", - "promiseName": "", - "resolution": "rejected", - "timestamp": 10, - "type": "suspense", - "warning": null, - } - `); + { + "componentName": "Example", + "depth": 0, + "duration": 10, + "id": "0", + "phase": "mount", + "promiseName": "", + "resolution": "rejected", + "timestamp": 10, + "type": "suspense", + "warning": null, + } + `); // There should be two batches of renders: Suspeneded and resolved. expect(timelineData.batchUIDToMeasuresMap.size).toBe(2); @@ -1477,15 +1517,15 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); expect(timelineData.schedulingEvents).toMatchInlineSnapshot(` - [ - { - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "schedule-render", - "warning": null, - }, - ] - `); + [ + { + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "schedule-render", + "warning": null, + }, + ] + `); }); it('should mark concurrent render without suspends or state updates', () => { @@ -1514,45 +1554,45 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); expect(timelineData.schedulingEvents).toMatchInlineSnapshot(` - [ - { - "componentName": "Example", - "componentStack": " - in Example (at **)", - "lanes": "0b0000000000000000000000010000000", - "timestamp": 10, - "type": "schedule-state-update", - "warning": null, - }, - { - "componentName": "Example", - "componentStack": " - in Example (at **)", - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "schedule-state-update", - "warning": null, - }, - ] - `); + [ + { + "componentName": "Example", + "componentStack": " + in Example (at **)", + "lanes": "0b0000000000000000000000010000000", + "timestamp": 10, + "type": "schedule-state-update", + "warning": null, + }, + { + "componentName": "Example", + "componentStack": " + in Example (at **)", + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "schedule-state-update", + "warning": null, + }, + ] + `); expect(timelineData.componentMeasures).toMatchInlineSnapshot(` - [ - { - "componentName": "Example", - "duration": 0, - "timestamp": 10, - "type": "render", - "warning": null, - }, - { - "componentName": "Example", - "duration": 10, - "timestamp": 10, - "type": "render", - "warning": null, - }, - ] - `); + [ + { + "componentName": "Example", + "duration": 0, + "timestamp": 10, + "type": "render", + "warning": null, + }, + { + "componentName": "Example", + "duration": 10, + "timestamp": 10, + "type": "render", + "warning": null, + }, + ] + `); expect(timelineData.batchUIDToMeasuresMap.size).toBe(2); }); @@ -1621,19 +1661,19 @@ describe('Timeline profiler', () => { expect(timelineData.suspenseEvents).toHaveLength(1); const suspenseEvent = timelineData.suspenseEvents[0]; expect(suspenseEvent).toMatchInlineSnapshot(` - { - "componentName": "Example", - "depth": 0, - "duration": 10, - "id": "0", - "phase": "mount", - "promiseName": "", - "resolution": "resolved", - "timestamp": 10, - "type": "suspense", - "warning": null, - } - `); + { + "componentName": "Example", + "depth": 0, + "duration": 10, + "id": "0", + "phase": "mount", + "promiseName": "", + "resolution": "resolved", + "timestamp": 10, + "type": "suspense", + "warning": null, + } + `); // There should be two batches of renders: Suspeneded and resolved. expect(timelineData.batchUIDToMeasuresMap.size).toBe(2); @@ -1678,19 +1718,19 @@ describe('Timeline profiler', () => { expect(timelineData.suspenseEvents).toHaveLength(1); const suspenseEvent = timelineData.suspenseEvents[0]; expect(suspenseEvent).toMatchInlineSnapshot(` - { - "componentName": "Example", - "depth": 0, - "duration": 10, - "id": "0", - "phase": "mount", - "promiseName": "", - "resolution": "rejected", - "timestamp": 10, - "type": "suspense", - "warning": null, - } - `); + { + "componentName": "Example", + "depth": 0, + "duration": 10, + "id": "0", + "phase": "mount", + "promiseName": "", + "resolution": "rejected", + "timestamp": 10, + "type": "suspense", + "warning": null, + } + `); // There should be two batches of renders: Suspeneded and resolved. expect(timelineData.batchUIDToMeasuresMap.size).toBe(2); @@ -1717,42 +1757,42 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); expect(timelineData.batchUIDToMeasuresMap.size).toBe(2); expect(timelineData.componentMeasures).toMatchInlineSnapshot(` - [ - { - "componentName": "Example", - "duration": 10, - "timestamp": 10, - "type": "render", - "warning": null, - }, - { - "componentName": "Example", - "duration": 10, - "timestamp": 20, - "type": "render", - "warning": null, - }, - ] - `); + [ + { + "componentName": "Example", + "duration": 10, + "timestamp": 10, + "type": "render", + "warning": null, + }, + { + "componentName": "Example", + "duration": 10, + "timestamp": 20, + "type": "render", + "warning": null, + }, + ] + `); expect(timelineData.schedulingEvents).toMatchInlineSnapshot(` - [ - { - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "schedule-render", - "warning": null, - }, - { - "componentName": "Example", - "componentStack": " - in Example (at **)", - "lanes": "0b0000000000000000000000000000010", - "timestamp": 20, - "type": "schedule-state-update", - "warning": null, - }, - ] - `); + [ + { + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "schedule-render", + "warning": null, + }, + { + "componentName": "Example", + "componentStack": " + in Example (at **)", + "lanes": "0b0000000000000000000000000000010", + "timestamp": 20, + "type": "schedule-state-update", + "warning": null, + }, + ] + `); }); it('should mark cascading class component force updates', async () => { @@ -1776,40 +1816,40 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); expect(timelineData.batchUIDToMeasuresMap.size).toBe(2); expect(timelineData.componentMeasures).toMatchInlineSnapshot(` - [ - { - "componentName": "Example", - "duration": 10, - "timestamp": 10, - "type": "render", - "warning": null, - }, - { - "componentName": "Example", - "duration": 10, - "timestamp": 20, - "type": "render", - "warning": null, - }, - ] - `); + [ + { + "componentName": "Example", + "duration": 10, + "timestamp": 10, + "type": "render", + "warning": null, + }, + { + "componentName": "Example", + "duration": 10, + "timestamp": 20, + "type": "render", + "warning": null, + }, + ] + `); expect(timelineData.schedulingEvents).toMatchInlineSnapshot(` - [ - { - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "schedule-render", - "warning": null, - }, - { - "componentName": "Example", - "lanes": "0b0000000000000000000000000000010", - "timestamp": 20, - "type": "schedule-force-update", - "warning": null, - }, - ] - `); + [ + { + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "schedule-render", + "warning": null, + }, + { + "componentName": "Example", + "lanes": "0b0000000000000000000000000000010", + "timestamp": 20, + "type": "schedule-force-update", + "warning": null, + }, + ] + `); }); it('should mark render phase state updates for class component', async () => { @@ -1844,42 +1884,42 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); expect(timelineData.batchUIDToMeasuresMap.size).toBe(2); expect(timelineData.componentMeasures).toMatchInlineSnapshot(` - [ - { - "componentName": "Example", - "duration": 10, - "timestamp": 10, - "type": "render", - "warning": null, - }, - { - "componentName": "Example", - "duration": 10, - "timestamp": 20, - "type": "render", - "warning": null, - }, - ] - `); + [ + { + "componentName": "Example", + "duration": 10, + "timestamp": 10, + "type": "render", + "warning": null, + }, + { + "componentName": "Example", + "duration": 10, + "timestamp": 20, + "type": "render", + "warning": null, + }, + ] + `); expect(timelineData.schedulingEvents).toMatchInlineSnapshot(` - [ - { - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "schedule-render", - "warning": null, - }, - { - "componentName": "Example", - "componentStack": " - in Example (at **)", - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "schedule-state-update", - "warning": null, - }, - ] - `); + [ + { + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "schedule-render", + "warning": null, + }, + { + "componentName": "Example", + "componentStack": " + in Example (at **)", + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "schedule-state-update", + "warning": null, + }, + ] + `); }); it('should mark render phase force updates for class component', async () => { @@ -1913,40 +1953,40 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); expect(timelineData.batchUIDToMeasuresMap.size).toBe(2); expect(timelineData.componentMeasures).toMatchInlineSnapshot(` - [ - { - "componentName": "Example", - "duration": 10, - "timestamp": 10, - "type": "render", - "warning": null, - }, - { - "componentName": "Example", - "duration": 10, - "timestamp": 20, - "type": "render", - "warning": null, - }, - ] - `); + [ + { + "componentName": "Example", + "duration": 10, + "timestamp": 10, + "type": "render", + "warning": null, + }, + { + "componentName": "Example", + "duration": 10, + "timestamp": 20, + "type": "render", + "warning": null, + }, + ] + `); expect(timelineData.schedulingEvents).toMatchInlineSnapshot(` - [ - { - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "schedule-render", - "warning": null, - }, - { - "componentName": "Example", - "lanes": "0b0000000000000000000000000100000", - "timestamp": 20, - "type": "schedule-force-update", - "warning": null, - }, - ] - `); + [ + { + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "schedule-render", + "warning": null, + }, + { + "componentName": "Example", + "lanes": "0b0000000000000000000000000100000", + "timestamp": 20, + "type": "schedule-force-update", + "warning": null, + }, + ] + `); }); it('should mark cascading layout updates', async () => { @@ -1968,49 +2008,49 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); expect(timelineData.batchUIDToMeasuresMap.size).toBe(2); expect(timelineData.componentMeasures).toMatchInlineSnapshot(` - [ - { - "componentName": "Example", - "duration": 10, - "timestamp": 10, - "type": "render", - "warning": null, - }, - { - "componentName": "Example", - "duration": 1, - "timestamp": 20, - "type": "layout-effect-mount", - "warning": null, - }, - { - "componentName": "Example", - "duration": 10, - "timestamp": 21, - "type": "render", - "warning": null, - }, - ] - `); + [ + { + "componentName": "Example", + "duration": 10, + "timestamp": 10, + "type": "render", + "warning": null, + }, + { + "componentName": "Example", + "duration": 1, + "timestamp": 20, + "type": "layout-effect-mount", + "warning": null, + }, + { + "componentName": "Example", + "duration": 10, + "timestamp": 21, + "type": "render", + "warning": null, + }, + ] + `); expect(timelineData.schedulingEvents).toMatchInlineSnapshot(` - [ - { - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "schedule-render", - "warning": null, - }, - { - "componentName": "Example", - "componentStack": " - in Example (at **)", - "lanes": "0b0000000000000000000000000000010", - "timestamp": 21, - "type": "schedule-state-update", - "warning": null, - }, - ] - `); + [ + { + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "schedule-render", + "warning": null, + }, + { + "componentName": "Example", + "componentStack": " + in Example (at **)", + "lanes": "0b0000000000000000000000000000010", + "timestamp": 21, + "type": "schedule-state-update", + "warning": null, + }, + ] + `); }); it('should mark cascading passive updates', async () => { @@ -2031,49 +2071,49 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); expect(timelineData.batchUIDToMeasuresMap.size).toBe(2); expect(timelineData.componentMeasures).toMatchInlineSnapshot(` - [ - { - "componentName": "Example", - "duration": 10, - "timestamp": 10, - "type": "render", - "warning": null, - }, - { - "componentName": "Example", - "duration": 1, - "timestamp": 20, - "type": "passive-effect-mount", - "warning": null, - }, - { - "componentName": "Example", - "duration": 10, - "timestamp": 21, - "type": "render", - "warning": null, - }, - ] - `); + [ + { + "componentName": "Example", + "duration": 10, + "timestamp": 10, + "type": "render", + "warning": null, + }, + { + "componentName": "Example", + "duration": 1, + "timestamp": 20, + "type": "passive-effect-mount", + "warning": null, + }, + { + "componentName": "Example", + "duration": 10, + "timestamp": 21, + "type": "render", + "warning": null, + }, + ] + `); expect(timelineData.schedulingEvents).toMatchInlineSnapshot(` - [ - { - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "schedule-render", - "warning": null, - }, - { - "componentName": "Example", - "componentStack": " - in Example (at **)", - "lanes": "0b0000000000000000000000000100000", - "timestamp": 21, - "type": "schedule-state-update", - "warning": null, - }, - ] - `); + [ + { + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "schedule-render", + "warning": null, + }, + { + "componentName": "Example", + "componentStack": " + in Example (at **)", + "lanes": "0b0000000000000000000000000100000", + "timestamp": 21, + "type": "schedule-state-update", + "warning": null, + }, + ] + `); }); it('should mark render phase updates', async () => { @@ -2094,35 +2134,35 @@ describe('Timeline profiler', () => { // Render phase updates should be retried as part of the same batch. expect(timelineData.batchUIDToMeasuresMap.size).toBe(1); expect(timelineData.componentMeasures).toMatchInlineSnapshot(` - [ - { - "componentName": "Example", - "duration": 20, - "timestamp": 10, - "type": "render", - "warning": null, - }, - ] - `); + [ + { + "componentName": "Example", + "duration": 20, + "timestamp": 10, + "type": "render", + "warning": null, + }, + ] + `); expect(timelineData.schedulingEvents).toMatchInlineSnapshot(` - [ - { - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "schedule-render", - "warning": null, - }, - { - "componentName": "Example", - "componentStack": " - in Example (at **)", - "lanes": "0b0000000000000000000000000100000", - "timestamp": 20, - "type": "schedule-state-update", - "warning": null, - }, - ] - `); + [ + { + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "schedule-render", + "warning": null, + }, + { + "componentName": "Example", + "componentStack": " + in Example (at **)", + "lanes": "0b0000000000000000000000000100000", + "timestamp": 20, + "type": "schedule-state-update", + "warning": null, + }, + ] + `); }); it('should mark concurrent render that throws', async () => { @@ -2166,81 +2206,81 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); expect(timelineData.componentMeasures).toMatchInlineSnapshot(` - [ - { - "componentName": "ErrorBoundary", - "duration": 10, - "timestamp": 10, - "type": "render", - "warning": null, - }, - { - "componentName": "ExampleThatThrows", - "duration": 0, - "timestamp": 20, - "type": "render", - "warning": null, - }, - { - "componentName": "ErrorBoundary", - "duration": 10, - "timestamp": 20, - "type": "render", - "warning": null, - }, - { - "componentName": "ExampleThatThrows", - "duration": 0, - "timestamp": 30, - "type": "render", - "warning": null, - }, - { - "componentName": "ErrorBoundary", - "duration": 10, - "timestamp": 30, - "type": "render", - "warning": null, - }, - ] - `); + [ + { + "componentName": "ErrorBoundary", + "duration": 10, + "timestamp": 10, + "type": "render", + "warning": null, + }, + { + "componentName": "ExampleThatThrows", + "duration": 0, + "timestamp": 20, + "type": "render", + "warning": null, + }, + { + "componentName": "ErrorBoundary", + "duration": 10, + "timestamp": 20, + "type": "render", + "warning": null, + }, + { + "componentName": "ExampleThatThrows", + "duration": 0, + "timestamp": 30, + "type": "render", + "warning": null, + }, + { + "componentName": "ErrorBoundary", + "duration": 10, + "timestamp": 30, + "type": "render", + "warning": null, + }, + ] + `); expect(timelineData.schedulingEvents).toMatchInlineSnapshot(` - [ - { - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "schedule-render", - "warning": null, - }, - { - "componentName": "ErrorBoundary", - "componentStack": " - in ErrorBoundary (at **)", - "lanes": "0b0000000000000000000000000000010", - "timestamp": 30, - "type": "schedule-state-update", - "warning": null, - }, - ] - `); + [ + { + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "schedule-render", + "warning": null, + }, + { + "componentName": "ErrorBoundary", + "componentStack": " + in ErrorBoundary (at **)", + "lanes": "0b0000000000000000000000000000010", + "timestamp": 30, + "type": "schedule-state-update", + "warning": null, + }, + ] + `); expect(timelineData.thrownErrors).toMatchInlineSnapshot(` - [ - { - "componentName": "ExampleThatThrows", - "message": "Expected error", - "phase": "mount", - "timestamp": 20, - "type": "thrown-error", - }, - { - "componentName": "ExampleThatThrows", - "message": "Expected error", - "phase": "mount", - "timestamp": 30, - "type": "thrown-error", - }, - ] - `); + [ + { + "componentName": "ExampleThatThrows", + "message": "Expected error", + "phase": "mount", + "timestamp": 20, + "type": "thrown-error", + }, + { + "componentName": "ExampleThatThrows", + "message": "Expected error", + "phase": "mount", + "timestamp": 30, + "type": "thrown-error", + }, + ] + `); }); it('should mark passive and layout effects', async () => { @@ -2307,174 +2347,174 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); expect(timelineData.componentMeasures).toMatchInlineSnapshot(` - [ - { - "componentName": "ComponentWithEffects", - "duration": 0, - "timestamp": 10, - "type": "render", - "warning": null, - }, - { - "componentName": "ComponentWithEffects", - "duration": 0, - "timestamp": 10, - "type": "layout-effect-mount", - "warning": null, - }, - { - "componentName": "ComponentWithEffects", - "duration": 0, - "timestamp": 10, - "type": "layout-effect-mount", - "warning": null, - }, - { - "componentName": "ComponentWithEffects", - "duration": 0, - "timestamp": 10, - "type": "passive-effect-mount", - "warning": null, - }, - { - "componentName": "ComponentWithEffects", - "duration": 0, - "timestamp": 10, - "type": "passive-effect-mount", - "warning": null, - }, - { - "componentName": "ComponentWithEffects", - "duration": 0, - "timestamp": 10, - "type": "passive-effect-mount", - "warning": null, - }, - { - "componentName": "ComponentWithEffects", - "duration": 0, - "timestamp": 10, - "type": "layout-effect-unmount", - "warning": null, - }, - { - "componentName": "ComponentWithEffects", - "duration": 0, - "timestamp": 10, - "type": "layout-effect-unmount", - "warning": null, - }, - { - "componentName": "ComponentWithEffects", - "duration": 0, - "timestamp": 10, - "type": "passive-effect-unmount", - "warning": null, - }, - { - "componentName": "ComponentWithEffects", - "duration": 0, - "timestamp": 10, - "type": "passive-effect-unmount", - "warning": null, - }, - { - "componentName": "ComponentWithEffects", - "duration": 0, - "timestamp": 10, - "type": "passive-effect-unmount", - "warning": null, - }, - ] - `); + [ + { + "componentName": "ComponentWithEffects", + "duration": 0, + "timestamp": 10, + "type": "render", + "warning": null, + }, + { + "componentName": "ComponentWithEffects", + "duration": 0, + "timestamp": 10, + "type": "layout-effect-mount", + "warning": null, + }, + { + "componentName": "ComponentWithEffects", + "duration": 0, + "timestamp": 10, + "type": "layout-effect-mount", + "warning": null, + }, + { + "componentName": "ComponentWithEffects", + "duration": 0, + "timestamp": 10, + "type": "passive-effect-mount", + "warning": null, + }, + { + "componentName": "ComponentWithEffects", + "duration": 0, + "timestamp": 10, + "type": "passive-effect-mount", + "warning": null, + }, + { + "componentName": "ComponentWithEffects", + "duration": 0, + "timestamp": 10, + "type": "passive-effect-mount", + "warning": null, + }, + { + "componentName": "ComponentWithEffects", + "duration": 0, + "timestamp": 10, + "type": "layout-effect-unmount", + "warning": null, + }, + { + "componentName": "ComponentWithEffects", + "duration": 0, + "timestamp": 10, + "type": "layout-effect-unmount", + "warning": null, + }, + { + "componentName": "ComponentWithEffects", + "duration": 0, + "timestamp": 10, + "type": "passive-effect-unmount", + "warning": null, + }, + { + "componentName": "ComponentWithEffects", + "duration": 0, + "timestamp": 10, + "type": "passive-effect-unmount", + "warning": null, + }, + { + "componentName": "ComponentWithEffects", + "duration": 0, + "timestamp": 10, + "type": "passive-effect-unmount", + "warning": null, + }, + ] + `); expect(timelineData.batchUIDToMeasuresMap).toMatchInlineSnapshot(` - Map { - 1 => [ - { - "batchUID": 1, - "depth": 0, - "duration": 0, - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "render-idle", - }, - { - "batchUID": 1, - "depth": 0, - "duration": 0, - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "render", - }, - { - "batchUID": 1, - "depth": 0, - "duration": 0, - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "commit", - }, - { - "batchUID": 1, - "depth": 1, - "duration": 0, - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "layout-effects", - }, - { - "batchUID": 1, - "depth": 0, - "duration": 0, - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "passive-effects", - }, - ], - 2 => [ - { - "batchUID": 2, - "depth": 0, - "duration": 0, - "lanes": "0b0000000000000000000000000000010", - "timestamp": 10, - "type": "render-idle", - }, - { - "batchUID": 2, - "depth": 0, - "duration": 0, - "lanes": "0b0000000000000000000000000000010", - "timestamp": 10, - "type": "render", - }, - { - "batchUID": 2, - "depth": 0, - "duration": 0, - "lanes": "0b0000000000000000000000000000010", - "timestamp": 10, - "type": "commit", - }, - { - "batchUID": 2, - "depth": 1, - "duration": 0, - "lanes": "0b0000000000000000000000000000010", - "timestamp": 10, - "type": "layout-effects", - }, - { - "batchUID": 2, - "depth": 1, - "duration": 0, - "lanes": "0b0000000000000000000000000000010", - "timestamp": 10, - "type": "passive-effects", - }, - ], - } - `); + Map { + 1 => [ + { + "batchUID": 1, + "depth": 0, + "duration": 0, + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "render-idle", + }, + { + "batchUID": 1, + "depth": 0, + "duration": 0, + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "render", + }, + { + "batchUID": 1, + "depth": 0, + "duration": 0, + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "commit", + }, + { + "batchUID": 1, + "depth": 1, + "duration": 0, + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "layout-effects", + }, + { + "batchUID": 1, + "depth": 0, + "duration": 0, + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "passive-effects", + }, + ], + 2 => [ + { + "batchUID": 2, + "depth": 0, + "duration": 0, + "lanes": "0b0000000000000000000000000000010", + "timestamp": 10, + "type": "render-idle", + }, + { + "batchUID": 2, + "depth": 0, + "duration": 0, + "lanes": "0b0000000000000000000000000000010", + "timestamp": 10, + "type": "render", + }, + { + "batchUID": 2, + "depth": 0, + "duration": 0, + "lanes": "0b0000000000000000000000000000010", + "timestamp": 10, + "type": "commit", + }, + { + "batchUID": 2, + "depth": 1, + "duration": 0, + "lanes": "0b0000000000000000000000000000010", + "timestamp": 10, + "type": "layout-effects", + }, + { + "batchUID": 2, + "depth": 1, + "duration": 0, + "lanes": "0b0000000000000000000000000000010", + "timestamp": 10, + "type": "passive-effects", + }, + ], + } + `); }); it('should generate component stacks for state update', async () => { @@ -2502,25 +2542,25 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); expect(timelineData.schedulingEvents).toMatchInlineSnapshot(` - [ - { - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "schedule-render", - "warning": null, - }, - { - "componentName": "Child", - "componentStack": " - in Child (at **) - in CommponentWithChildren (at **)", - "lanes": "0b0000000000000000000000000100000", - "timestamp": 10, - "type": "schedule-state-update", - "warning": null, - }, - ] - `); + [ + { + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "schedule-render", + "warning": null, + }, + { + "componentName": "Child", + "componentStack": " + in Child (at **) + in CommponentWithChildren (at **)", + "lanes": "0b0000000000000000000000000100000", + "timestamp": 10, + "type": "schedule-state-update", + "warning": null, + }, + ] + `); }); }); }); diff --git a/packages/react-devtools-shared/src/__tests__/preprocessData-test.js b/packages/react-devtools-shared/src/__tests__/preprocessData-test.js index c7edb766a24b6..f3e29a23cffd8 100644 --- a/packages/react-devtools-shared/src/__tests__/preprocessData-test.js +++ b/packages/react-devtools-shared/src/__tests__/preprocessData-test.js @@ -841,9 +841,9 @@ describe('Timeline profiler', () => { { "batchUID": 0, "depth": 0, - "duration": 0.012, + "duration": 0.014, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.006, + "timestamp": 0.008, "type": "render-idle", }, { @@ -851,15 +851,15 @@ describe('Timeline profiler', () => { "depth": 0, "duration": 0.003, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.006, + "timestamp": 0.008, "type": "render", }, { "batchUID": 0, "depth": 0, - "duration": 0.008, + "duration": 0.010, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.01, + "timestamp": 0.012, "type": "commit", }, { @@ -867,7 +867,7 @@ describe('Timeline profiler', () => { "depth": 1, "duration": 0.001, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.016, + "timestamp": 0.02, "type": "layout-effects", }, { @@ -875,7 +875,7 @@ describe('Timeline profiler', () => { "depth": 0, "duration": 0.004, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.019, + "timestamp": 0.023, "type": "passive-effects", }, ], @@ -883,9 +883,9 @@ describe('Timeline profiler', () => { { "batchUID": 1, "depth": 0, - "duration": 0.012, + "duration": 0.014, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.024, + "timestamp": 0.028, "type": "render-idle", }, { @@ -893,15 +893,15 @@ describe('Timeline profiler', () => { "depth": 0, "duration": 0.003, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.024, + "timestamp": 0.028, "type": "render", }, { "batchUID": 1, "depth": 0, - "duration": 0.008, + "duration": 0.010, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.028, + "timestamp": 0.032, "type": "commit", }, { @@ -909,7 +909,7 @@ describe('Timeline profiler', () => { "depth": 1, "duration": 0.001, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.034, + "timestamp": 0.04, "type": "layout-effects", }, { @@ -917,7 +917,7 @@ describe('Timeline profiler', () => { "depth": 0, "duration": 0.003, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.037, + "timestamp": 0.043, "type": "passive-effects", }, ], @@ -926,33 +926,33 @@ describe('Timeline profiler', () => { { "componentName": "App", "duration": 0.001, - "timestamp": 0.007, + "timestamp": 0.009, "type": "render", "warning": null, }, { "componentName": "App", "duration": 0.002, - "timestamp": 0.02, + "timestamp": 0.024, "type": "passive-effect-mount", "warning": null, }, { "componentName": "App", "duration": 0.001, - "timestamp": 0.025, + "timestamp": 0.029, "type": "render", "warning": null, }, { "componentName": "App", "duration": 0.001, - "timestamp": 0.038, + "timestamp": 0.044, "type": "passive-effect-mount", "warning": null, }, ], - "duration": 0.04, + "duration": 0.046, "flamechart": [], "internalModuleSourceToRanges": Map { undefined => [ @@ -1015,9 +1015,9 @@ describe('Timeline profiler', () => { { "batchUID": 0, "depth": 0, - "duration": 0.012, + "duration": 0.014, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.006, + "timestamp": 0.008, "type": "render-idle", }, { @@ -1025,15 +1025,15 @@ describe('Timeline profiler', () => { "depth": 0, "duration": 0.003, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.006, + "timestamp": 0.008, "type": "render", }, { "batchUID": 0, "depth": 0, - "duration": 0.008, + "duration": 0.010, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.01, + "timestamp": 0.012, "type": "commit", }, { @@ -1041,7 +1041,7 @@ describe('Timeline profiler', () => { "depth": 1, "duration": 0.001, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.016, + "timestamp": 0.02, "type": "layout-effects", }, { @@ -1049,15 +1049,15 @@ describe('Timeline profiler', () => { "depth": 0, "duration": 0.004, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.019, + "timestamp": 0.023, "type": "passive-effects", }, { "batchUID": 1, "depth": 0, - "duration": 0.012, + "duration": 0.014, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.024, + "timestamp": 0.028, "type": "render-idle", }, { @@ -1065,15 +1065,15 @@ describe('Timeline profiler', () => { "depth": 0, "duration": 0.003, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.024, + "timestamp": 0.028, "type": "render", }, { "batchUID": 1, "depth": 0, - "duration": 0.008, + "duration": 0.010, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.028, + "timestamp": 0.032, "type": "commit", }, { @@ -1081,7 +1081,7 @@ describe('Timeline profiler', () => { "depth": 1, "duration": 0.001, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.034, + "timestamp": 0.04, "type": "layout-effects", }, { @@ -1089,7 +1089,7 @@ describe('Timeline profiler', () => { "depth": 0, "duration": 0.003, "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.037, + "timestamp": 0.043, "type": "passive-effects", }, ], @@ -1126,14 +1126,14 @@ describe('Timeline profiler', () => { "schedulingEvents": [ { "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.005, + "timestamp": 0.007, "type": "schedule-render", "warning": null, }, { "componentName": "App", "lanes": "0b0000000000000000000000000000101", - "timestamp": 0.021, + "timestamp": 0.025, "type": "schedule-state-update", "warning": null, }, diff --git a/packages/react-devtools-shell/src/e2e-regression/app.js b/packages/react-devtools-shell/src/e2e-regression/app.js index a2b4eb735cced..d0210d323570d 100644 --- a/packages/react-devtools-shell/src/e2e-regression/app.js +++ b/packages/react-devtools-shell/src/e2e-regression/app.js @@ -3,8 +3,7 @@ // This test harness mounts each test app as a separate root to test multi-root applications. import * as React from 'react'; -import * as ReactDOM from 'react-dom'; -import {createRoot} from 'react-dom/client'; +import * as ReactDOMClient from 'react-dom/client'; import ListApp from '../e2e-apps/ListApp'; function mountApp(App: () => React$Node) { @@ -12,7 +11,7 @@ function mountApp(App: () => React$Node) { ((document.body: any): HTMLBodyElement).appendChild(container); - const root = createRoot(container); + const root = ReactDOMClient.createRoot(container); root.render(); } function mountTestApp() { @@ -27,5 +26,5 @@ window.parent.REACT_DOM_APP = { createTestNameSelector: name => `[data-testname="${name}"]`, findAllNodes: (container, nodes) => container.querySelectorAll(nodes.join(' ')), - ...ReactDOM, + ...ReactDOMClient, }; diff --git a/packages/react-devtools-shell/src/e2e-regression/devtools.js b/packages/react-devtools-shell/src/e2e-regression/devtools.js index 4e560b584e657..6e9ada823ca47 100644 --- a/packages/react-devtools-shell/src/e2e-regression/devtools.js +++ b/packages/react-devtools-shell/src/e2e-regression/devtools.js @@ -1,6 +1,6 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom'; -import {createRoot} from 'react-dom/client'; +import * as ReactDOMClient from 'react-dom/client'; import { activate as activateBackend, initialize as initializeBackend, @@ -32,7 +32,7 @@ function init(appIframe, devtoolsContainer, appSource) { const DevTools = createDevTools(contentWindow); inject(contentDocument, appSource, () => { - createRoot(devtoolsContainer).render( + ReactDOMClient.createRoot(devtoolsContainer).render( ); // ReactDOM Test Selector APIs used by Playwright e2e tests -window.parent.REACT_DOM_APP = ReactDOM; +window.parent.REACT_DOM_APP = ReactDOMClient; diff --git a/packages/react-devtools-shell/src/e2e/devtools.js b/packages/react-devtools-shell/src/e2e/devtools.js index 542443855d89c..89bc2b57f99c8 100644 --- a/packages/react-devtools-shell/src/e2e/devtools.js +++ b/packages/react-devtools-shell/src/e2e/devtools.js @@ -8,8 +8,7 @@ */ import * as React from 'react'; -import * as ReactDOM from 'react-dom'; -import {createRoot} from 'react-dom/client'; +import * as ReactDOMClient from 'react-dom/client'; import { activate as activateBackend, initialize as initializeBackend, @@ -41,7 +40,7 @@ function init(appIframe, devtoolsContainer, appSource) { const DevTools = createDevTools(contentWindow); inject(contentDocument, appSource, () => { - createRoot(devtoolsContainer).render( + ReactDOMClient.createRoot(devtoolsContainer).render( ({ }, }); +const clientAsSeparateBuild = semver.gte(REACT_VERSION, '19.0.0'); + const app = makeConfig( { 'app-index': './src/app/index.js', @@ -142,8 +144,14 @@ const app = makeConfig( react: resolve(builtModulesDir, 'react'), 'react-debug-tools': resolve(builtModulesDir, 'react-debug-tools'), 'react-devtools-feature-flags': resolveFeatureFlags('shell'), - 'react-dom/client': resolve(builtModulesDir, 'react-dom/client'), - 'react-dom': resolve(builtModulesDir, 'react-dom/unstable_testing'), + 'react-dom/client': resolve( + builtModulesDir, + clientAsSeparateBuild ? 'react-dom/unstable_testing' : 'react-dom/client', + ), + 'react-dom': resolve( + builtModulesDir, + clientAsSeparateBuild ? 'react-dom' : 'react-dom/unstable_testing', + ), 'react-is': resolve(builtModulesDir, 'react-is'), scheduler: resolve(builtModulesDir, 'scheduler'), }, diff --git a/packages/react-dom-bindings/src/client/ReactDOMContainer.js b/packages/react-dom-bindings/src/client/ReactDOMContainer.js new file mode 100644 index 0000000000000..0af0f13a790a8 --- /dev/null +++ b/packages/react-dom-bindings/src/client/ReactDOMContainer.js @@ -0,0 +1,42 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +import {disableCommentsAsDOMContainers} from 'shared/ReactFeatureFlags'; + +import { + ELEMENT_NODE, + COMMENT_NODE, + DOCUMENT_NODE, + DOCUMENT_FRAGMENT_NODE, +} from './HTMLNodeType'; + +export function isValidContainer(node: any): boolean { + return !!( + node && + (node.nodeType === ELEMENT_NODE || + node.nodeType === DOCUMENT_NODE || + node.nodeType === DOCUMENT_FRAGMENT_NODE || + (!disableCommentsAsDOMContainers && + node.nodeType === COMMENT_NODE && + (node: any).nodeValue === ' react-mount-point-unstable ')) + ); +} + +// TODO: Remove this function which also includes comment nodes. +// We only use it in places that are currently more relaxed. +export function isValidContainerLegacy(node: any): boolean { + return !!( + node && + (node.nodeType === ELEMENT_NODE || + node.nodeType === DOCUMENT_NODE || + node.nodeType === DOCUMENT_FRAGMENT_NODE || + (node.nodeType === COMMENT_NODE && + (node: any).nodeValue === ' react-mount-point-unstable ')) + ); +} diff --git a/packages/react-dom/client.js b/packages/react-dom/client.js index 5011372e2faec..4d57f56da05f9 100644 --- a/packages/react-dom/client.js +++ b/packages/react-dom/client.js @@ -7,50 +7,4 @@ * @flow */ -'use strict'; - -import type {ReactNodeList} from 'shared/ReactTypes'; -import type { - RootType, - HydrateRootOptions, - CreateRootOptions, -} from './src/client/ReactDOMRoot'; - -import { - createRoot as createRootImpl, - hydrateRoot as hydrateRootImpl, - __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE as Internals, -} from './'; - -export function createRoot( - container: Element | Document | DocumentFragment, - options?: CreateRootOptions, -): RootType { - if (__DEV__) { - Internals.usingClientEntryPoint = true; - } - try { - return createRootImpl(container, options); - } finally { - if (__DEV__) { - Internals.usingClientEntryPoint = false; - } - } -} - -export function hydrateRoot( - container: Document | Element, - children: ReactNodeList, - options?: HydrateRootOptions, -): RootType { - if (__DEV__) { - Internals.usingClientEntryPoint = true; - } - try { - return hydrateRootImpl(container, children, options); - } finally { - if (__DEV__) { - Internals.usingClientEntryPoint = false; - } - } -} +export {createRoot, hydrateRoot, version} from './src/client/ReactDOMClient'; diff --git a/packages/react-dom/index.experimental.js b/packages/react-dom/index.experimental.js deleted file mode 100644 index 0cc5ef13e3698..0000000000000 --- a/packages/react-dom/index.experimental.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export {default as __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './src/ReactDOMSharedInternals'; -export { - createPortal, - createRoot, - hydrateRoot, - flushSync, - unstable_batchedUpdates, - unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority. - useFormStatus, - useFormState, - requestFormReset, - prefetchDNS, - preconnect, - preload, - preloadModule, - preinit, - preinitModule, - version, -} from './src/client/ReactDOM'; diff --git a/packages/react-dom/index.js b/packages/react-dom/index.js index b6f85ce628c57..ca91fdcea1cbe 100644 --- a/packages/react-dom/index.js +++ b/packages/react-dom/index.js @@ -7,25 +7,19 @@ * @flow */ -// Export all exports so that they're available in tests. -// We can't use export * from in Flow for some reason. export {default as __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './src/ReactDOMSharedInternals'; export { createPortal, - createRoot, - hydrateRoot, flushSync, - unstable_batchedUpdates, - unstable_createEventHandle, - unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority. - useFormStatus, - useFormState, - requestFormReset, prefetchDNS, preconnect, preload, preloadModule, preinit, preinitModule, + requestFormReset, + unstable_batchedUpdates, + useFormState, + useFormStatus, version, -} from './src/client/ReactDOM'; +} from './src/shared/ReactDOM'; diff --git a/packages/react-dom/index.stable.js b/packages/react-dom/index.stable.js deleted file mode 100644 index f5ed138d67ab6..0000000000000 --- a/packages/react-dom/index.stable.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export {default as __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './src/ReactDOMSharedInternals'; -export { - createPortal, - createRoot, - hydrateRoot, - flushSync, - unstable_batchedUpdates, - useFormStatus, - useFormState, - requestFormReset, - prefetchDNS, - preconnect, - preload, - preloadModule, - preinit, - preinitModule, - version, -} from './src/client/ReactDOM'; diff --git a/packages/react-dom/npm/client.js b/packages/react-dom/npm/client.js index af04d9eb2ad9f..02e6e22500db1 100644 --- a/packages/react-dom/npm/client.js +++ b/packages/react-dom/npm/client.js @@ -1,25 +1,38 @@ 'use strict'; -var m = require('react-dom'); +function checkDCE() { + /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ + if ( + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined' || + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== 'function' + ) { + return; + } + if (process.env.NODE_ENV !== 'production') { + // This branch is unreachable because this function is only called + // in production, but the condition is true only in development. + // Therefore if the branch is still here, dead code elimination wasn't + // properly applied. + // Don't change the message. React DevTools relies on it. Also make sure + // this message doesn't occur elsewhere in this function, or it will cause + // a false positive. + throw new Error('^_^'); + } + try { + // Verify that the code above has been dead code eliminated (DCE'd). + __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE); + } catch (err) { + // DevTools shouldn't crash React, no matter what. + // We should still report in case we break this code. + console.error(err); + } +} + if (process.env.NODE_ENV === 'production') { - exports.createRoot = m.createRoot; - exports.hydrateRoot = m.hydrateRoot; + // DCE check should happen before ReactDOM bundle executes so that + // DevTools can report bad minification during injection. + checkDCE(); + module.exports = require('./cjs/react-dom-client.production.js'); } else { - var i = m.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE; - exports.createRoot = function (c, o) { - i.usingClientEntryPoint = true; - try { - return m.createRoot(c, o); - } finally { - i.usingClientEntryPoint = false; - } - }; - exports.hydrateRoot = function (c, h, o) { - i.usingClientEntryPoint = true; - try { - return m.hydrateRoot(c, h, o); - } finally { - i.usingClientEntryPoint = false; - } - }; + module.exports = require('./cjs/react-dom-client.development.js'); } diff --git a/packages/react-dom/npm/profiling.js b/packages/react-dom/npm/profiling.js index ad62952364dcf..29e4965c66381 100644 --- a/packages/react-dom/npm/profiling.js +++ b/packages/react-dom/npm/profiling.js @@ -32,7 +32,7 @@ if (process.env.NODE_ENV === 'production') { // DCE check should happen before ReactDOM bundle executes so that // DevTools can report bad minification during injection. checkDCE(); - module.exports = require('./cjs/react-dom.profiling.js'); + module.exports = require('./cjs/react-dom-profiling.profiling.js'); } else { - module.exports = require('./cjs/react-dom.development.js'); + module.exports = require('./cjs/react-dom-profiling.development.js'); } diff --git a/packages/react-dom/npm/server-rendering-stub.js b/packages/react-dom/npm/server-rendering-stub.js deleted file mode 100644 index c402d242d6362..0000000000000 --- a/packages/react-dom/npm/server-rendering-stub.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -if (process.env.NODE_ENV === 'production') { - module.exports = require('./cjs/react-dom-server-rendering-stub.production.js'); -} else { - module.exports = require('./cjs/react-dom-server-rendering-stub.development.js'); -} diff --git a/packages/react-dom/package.json b/packages/react-dom/package.json index 3c4b8bd50a2bd..170471ad8ac1a 100644 --- a/packages/react-dom/package.json +++ b/packages/react-dom/package.json @@ -31,7 +31,6 @@ "profiling.js", "profiling.react-server.js", "react-dom.react-server.js", - "server-rendering-stub.js", "server.browser.js", "server.bun.js", "server.edge.js", @@ -107,7 +106,6 @@ "react-server": "./static.react-server.js", "default": "./static.node.js" }, - "./server-rendering-stub": "./server-rendering-stub.js", "./profiling": { "react-server": "./profiling.react-server.js", "default": "./profiling.js" diff --git a/packages/react-dom/profiling.js b/packages/react-dom/profiling.js new file mode 100644 index 0000000000000..cdd2502fc007a --- /dev/null +++ b/packages/react-dom/profiling.js @@ -0,0 +1,12 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +// This entrypoint should track the /client entrypoint +export * from './client'; +export * from './index'; diff --git a/packages/react-dom/server-rendering-stub.js b/packages/react-dom/server-rendering-stub.js deleted file mode 100644 index 30f4f80e38903..0000000000000 --- a/packages/react-dom/server-rendering-stub.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -// Export all exports so that they're available in tests. -// We can't use export * from in Flow for some reason. - -import ReactVersion from 'shared/ReactVersion'; -export {ReactVersion as version}; - -export {default as __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './src/ReactDOMSharedInternals'; - -export { - createPortal, - flushSync, - prefetchDNS, - preconnect, - preload, - preloadModule, - preinit, - preinitModule, - useFormStatus, - useFormState, - unstable_batchedUpdates, -} from './src/server/ReactDOMServerRenderingStub'; - -import type {FormStatus} from 'react-dom-bindings/src/shared/ReactDOMFormActions'; -import { - useFormStatus, - useFormState, -} from './src/server/ReactDOMServerRenderingStub'; -import type {Awaited} from 'shared/ReactTypes'; - -export function experimental_useFormStatus(): FormStatus { - if (__DEV__) { - console.error( - 'useFormStatus is now in canary. Remove the experimental_ prefix. ' + - 'The prefixed alias will be removed in an upcoming release.', - ); - } - return useFormStatus(); -} - -export function experimental_useFormState( - action: (Awaited, P) => S, - initialState: Awaited, - permalink?: string, -): [Awaited, (P) => void, boolean] { - if (__DEV__) { - console.error( - 'useFormState is now in canary. Remove the experimental_ prefix. ' + - 'The prefixed alias will be removed in an upcoming release.', - ); - } - return useFormState(action, initialState, permalink); -} diff --git a/packages/react-dom/index.classic.fb.js b/packages/react-dom/src/ReactDOMFB.js similarity index 88% rename from packages/react-dom/index.classic.fb.js rename to packages/react-dom/src/ReactDOMFB.js index 63c20f7e51bfe..409aa376d5c1c 100644 --- a/packages/react-dom/index.classic.fb.js +++ b/packages/react-dom/src/ReactDOMFB.js @@ -9,7 +9,7 @@ import {isEnabled} from 'react-dom-bindings/src/events/ReactDOMEventListener'; -import Internals from './src/ReactDOMSharedInternalsFB'; +import Internals from './ReactDOMSharedInternalsFB'; // For classic WWW builds, include a few internals that are already in use. Object.assign((Internals: any), { @@ -18,6 +18,8 @@ Object.assign((Internals: any), { }, }); +export {Internals as __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE}; + export { createPortal, flushSync, @@ -33,7 +35,7 @@ export { preinit, preinitModule, version, -} from './src/client/ReactDOMFB'; +} from './client/ReactDOMClientFB'; export { createRoot, @@ -43,6 +45,4 @@ export { findDOMNode, unstable_renderSubtreeIntoContainer, unmountComponentAtNode, -} from './src/client/ReactDOMRootFB'; - -export {Internals as __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE}; +} from './client/ReactDOMRootFB'; diff --git a/packages/react-dom/index.modern.fb.js b/packages/react-dom/src/ReactDOMFB.modern.js similarity index 79% rename from packages/react-dom/index.modern.fb.js rename to packages/react-dom/src/ReactDOMFB.modern.js index 861febfa5e37b..0dd47906019ff 100644 --- a/packages/react-dom/index.modern.fb.js +++ b/packages/react-dom/src/ReactDOMFB.modern.js @@ -7,7 +7,8 @@ * @flow */ -export {default as __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './src/ReactDOMSharedInternalsFB'; +export {default as __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './ReactDOMSharedInternalsFB'; + export { createPortal, flushSync, @@ -24,6 +25,6 @@ export { preinit, preinitModule, version, -} from './src/client/ReactDOMFB'; +} from './client/ReactDOMClientFB'; -export {createRoot, hydrateRoot} from './src/client/ReactDOMRootFB'; +export {createRoot, hydrateRoot} from './client/ReactDOMRootFB'; diff --git a/packages/react-dom/src/ReactDOMServer.js b/packages/react-dom/src/ReactDOMReactServer.js similarity index 100% rename from packages/react-dom/src/ReactDOMServer.js rename to packages/react-dom/src/ReactDOMReactServer.js diff --git a/packages/react-dom/src/ReactDOMSharedInternals.js b/packages/react-dom/src/ReactDOMSharedInternals.js index 0a0f97866738a..0d11b81718917 100644 --- a/packages/react-dom/src/ReactDOMSharedInternals.js +++ b/packages/react-dom/src/ReactDOMSharedInternals.js @@ -20,11 +20,6 @@ type ReactDOMInternals = { | (( componentOrElement: React$Component, ) => null | Element | Text), - usingClientEntryPoint: boolean, -}; - -export type ReactDOMInternalsDev = ReactDOMInternals & { - usingClientEntryPoint: boolean, }; function noop() {} @@ -52,7 +47,6 @@ const Internals: ReactDOMInternals = { d /* ReactDOMCurrentDispatcher */: DefaultDispatcher, p /* currentUpdatePriority */: NoEventPriority, findDOMNode: null, - usingClientEntryPoint: false, }; export default Internals; diff --git a/packages/react-dom/unstable_testing.modern.fb.js b/packages/react-dom/src/ReactDOMTestingFB.js similarity index 57% rename from packages/react-dom/unstable_testing.modern.fb.js rename to packages/react-dom/src/ReactDOMTestingFB.js index 244d82025105f..1d7a4c8fb13bc 100644 --- a/packages/react-dom/unstable_testing.modern.fb.js +++ b/packages/react-dom/src/ReactDOMTestingFB.js @@ -7,23 +7,8 @@ * @flow */ -export { - createPortal, - flushSync, - unstable_batchedUpdates, - unstable_createEventHandle, - useFormStatus, - useFormState, - prefetchDNS, - preconnect, - preload, - preloadModule, - preinit, - preinitModule, - version, - __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, -} from './index.modern.fb.js'; -export {createRoot, hydrateRoot} from './client.js'; +export * from './ReactDOMFB'; + export { createComponentSelector, createHasPseudoClassSelector, diff --git a/packages/react-dom/src/ReactDOMTestingFB.modern.js b/packages/react-dom/src/ReactDOMTestingFB.modern.js new file mode 100644 index 0000000000000..7d60bf6d4e0b8 --- /dev/null +++ b/packages/react-dom/src/ReactDOMTestingFB.modern.js @@ -0,0 +1,23 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +export * from './ReactDOMFB.modern'; + +export { + createComponentSelector, + createHasPseudoClassSelector, + createRoleSelector, + createTestNameSelector, + createTextSelector, + getFindAllNodesFailureDescription, + findAllNodes, + findBoundingRects, + focusWithin, + observeVisibleRects, +} from 'react-reconciler/src/ReactFiberReconciler'; diff --git a/packages/react-dom/src/__tests__/ReactDOM-test.js b/packages/react-dom/src/__tests__/ReactDOM-test.js index e4d7b0ddec658..72fa57fb1fd5e 100644 --- a/packages/react-dom/src/__tests__/ReactDOM-test.js +++ b/packages/react-dom/src/__tests__/ReactDOM-test.js @@ -22,11 +22,11 @@ describe('ReactDOM', () => { jest.resetModules(); React = require('react'); ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); + ReactDOMServer = require('react-dom/server'); findDOMNode = ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE .findDOMNode; - ReactDOMClient = require('react-dom/client'); - ReactDOMServer = require('react-dom/server'); act = require('internal-test-utils').act; }); diff --git a/packages/react-dom/src/__tests__/ReactDOMRoot-test.js b/packages/react-dom/src/__tests__/ReactDOMRoot-test.js index f36f45a1e28fd..993e6e5a641fa 100644 --- a/packages/react-dom/src/__tests__/ReactDOMRoot-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMRoot-test.js @@ -47,28 +47,6 @@ describe('ReactDOMRoot', () => { expect(container.textContent).toEqual('Hi'); }); - // @gate !www || !__DEV__ - it('warns if you import createRoot from react-dom', async () => { - expect(() => ReactDOM.createRoot(container)).toErrorDev( - 'You are importing createRoot from "react-dom" which is not supported. ' + - 'You should instead import it from "react-dom/client".', - { - withoutStack: true, - }, - ); - }); - - // @gate !www || !__DEV__ - it('warns if you import hydrateRoot from react-dom', async () => { - expect(() => ReactDOM.hydrateRoot(container, null)).toErrorDev( - 'You are importing hydrateRoot from "react-dom" which is not supported. ' + - 'You should instead import it from "react-dom/client".', - { - withoutStack: true, - }, - ); - }); - it('warns if a callback parameter is provided to render', async () => { const callback = jest.fn(); const root = ReactDOMClient.createRoot(container); diff --git a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js index cd0c360b41c37..36f7c95ba6531 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js @@ -1479,7 +1479,7 @@ describe('ReactDOMServerPartialHydration', () => { expect(span.className).toBe('hi'); }); - // @gate experimental || www + // @gate www it('blocks updates to hydrate the content first if props changed at idle priority', async () => { let suspend = false; let resolve; diff --git a/packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js index 6a5aff96b3c1f..cbc4b5256c185 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js @@ -1333,7 +1333,7 @@ describe('ReactDOMServerSelectiveHydration', () => { await waitForAll(['App', 'C', 'B', 'A']); }); - // @gate experimental || www + // @gate www it('hydrates before an update even if hydration moves away from it', async () => { function Child({text}) { Scheduler.log(text); @@ -1677,7 +1677,7 @@ describe('ReactDOMServerSelectiveHydration', () => { expect(initialSpan).toBe(spanRef); }); - // @gate experimental || www + // @gate www it('can force hydration in response to continuous update', async () => { function Child({text}) { Scheduler.log(`Child ${text}`); @@ -1746,7 +1746,7 @@ describe('ReactDOMServerSelectiveHydration', () => { expect(initialSpan).toBe(spanRef); }); - // @gate experimental || www + // @gate www it('regression test: can unwind context on selective hydration interruption', async () => { const Context = React.createContext('DefaultContext'); diff --git a/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js b/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js index 5cb46b93b5f8c..50ba64a478888 100644 --- a/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js @@ -26,10 +26,10 @@ describe('ReactDOMSuspensePlaceholder', () => { jest.resetModules(); React = require('react'); ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); findDOMNode = ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE .findDOMNode; - ReactDOMClient = require('react-dom/client'); Scheduler = require('scheduler'); act = require('internal-test-utils').act; assertLog = require('internal-test-utils').assertLog; diff --git a/packages/react-dom/src/__tests__/ReactEmptyComponent-test.js b/packages/react-dom/src/__tests__/ReactEmptyComponent-test.js index de22540c5432f..c985d0e048dd1 100644 --- a/packages/react-dom/src/__tests__/ReactEmptyComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactEmptyComponent-test.js @@ -26,10 +26,10 @@ describe('ReactEmptyComponent', () => { React = require('react'); ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); findDOMNode = ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE .findDOMNode; - ReactDOMClient = require('react-dom/client'); Scheduler = require('scheduler'); const InternalTestUtils = require('internal-test-utils'); act = InternalTestUtils.act; diff --git a/packages/react-dom/src/__tests__/ReactLegacyCompositeComponent-test.js b/packages/react-dom/src/__tests__/ReactLegacyCompositeComponent-test.js index a39fbb0540881..eaf49b7527e38 100644 --- a/packages/react-dom/src/__tests__/ReactLegacyCompositeComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactLegacyCompositeComponent-test.js @@ -21,10 +21,10 @@ describe('ReactLegacyCompositeComponent', () => { jest.resetModules(); React = require('react'); ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); findDOMNode = ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE .findDOMNode; - ReactDOMClient = require('react-dom/client'); PropTypes = require('prop-types'); act = require('internal-test-utils').act; }); diff --git a/packages/react-dom/src/__tests__/ReactUpdates-test.js b/packages/react-dom/src/__tests__/ReactUpdates-test.js index 322907635d798..9a10a8d061b5f 100644 --- a/packages/react-dom/src/__tests__/ReactUpdates-test.js +++ b/packages/react-dom/src/__tests__/ReactUpdates-test.js @@ -24,10 +24,10 @@ describe('ReactUpdates', () => { jest.resetModules(); React = require('react'); ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); findDOMNode = ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE .findDOMNode; - ReactDOMClient = require('react-dom/client'); act = require('internal-test-utils').act; Scheduler = require('scheduler'); diff --git a/packages/react-dom/src/__tests__/react-dom-server-rendering-stub-test.js b/packages/react-dom/src/__tests__/react-dom-server-rendering-stub-test.js deleted file mode 100644 index 9425ca1dd1f15..0000000000000 --- a/packages/react-dom/src/__tests__/react-dom-server-rendering-stub-test.js +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @emails react-core - */ - -'use strict'; - -let React; -let ReactDOM; -let ReactDOMFizzServer; - -describe('react-dom-server-rendering-stub', () => { - beforeEach(() => { - jest.mock('react-dom', () => require('react-dom/server-rendering-stub')); - - React = require('react'); - ReactDOM = require('react-dom'); - ReactDOMFizzServer = require('react-dom/server'); - }); - - it('exports a version', () => { - expect(ReactDOM.version).toBeTruthy(); - }); - - it('exports that are expected to be client only in the future are not exported', () => { - expect(ReactDOM.createRoot).toBe(undefined); - expect(ReactDOM.hydrateRoot).toBe(undefined); - expect(ReactDOM.findDOMNode).toBe(undefined); - expect( - ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE - .findDOMNode, - ).toBe(null); - expect(ReactDOM.hydrate).toBe(undefined); - expect(ReactDOM.render).toBe(undefined); - expect(ReactDOM.unmountComponentAtNode).toBe(undefined); - expect(ReactDOM.unstable_createEventHandle).toBe(undefined); - expect(ReactDOM.unstable_renderSubtreeIntoContainer).toBe(undefined); - expect(ReactDOM.unstable_runWithPriority).toBe(undefined); - }); - - it('provides preload, preloadModule, preinit, and preinitModule exports', async () => { - function App() { - ReactDOM.preload('foo', {as: 'style'}); - ReactDOM.preloadModule('foomodule'); - ReactDOM.preinit('bar', {as: 'style'}); - ReactDOM.preinitModule('barmodule'); - return
foo
; - } - const html = ReactDOMFizzServer.renderToString(); - expect(html).toEqual( - '
foo
', - ); - }); - - it('provides preconnect and prefetchDNS exports', async () => { - function App() { - ReactDOM.preconnect('foo', {crossOrigin: 'use-credentials'}); - ReactDOM.prefetchDNS('bar'); - return
foo
; - } - const html = ReactDOMFizzServer.renderToString(); - expect(html).toEqual( - '
foo
', - ); - }); - - it('provides a stub for createPortal', async () => { - expect(() => { - ReactDOM.createPortal(); - }).toThrow( - 'createPortal was called on the server. Portals are not currently supported on the server. Update your program to conditionally call createPortal on the client only.', - ); - }); - - it('provides a stub for flushSync', async () => { - let x = false; - expect(() => { - ReactDOM.flushSync(() => (x = true)); - }).toThrow( - 'flushSync was called on the server. This is likely caused by a function being called during render or in module scope that was intended to be called from an effect or event handler. Update your to not call flushSync no the server.', - ); - expect(x).toBe(false); - }); - - // @gate enableAsyncActions - it('exports useFormStatus', async () => { - function App() { - const {pending} = ReactDOM.useFormStatus(); - return 'Pending: ' + pending; - } - - const result = await ReactDOMFizzServer.renderToStaticMarkup(); - expect(result).toEqual('Pending: false'); - }); -}); diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js deleted file mode 100644 index 913b9359037dc..0000000000000 --- a/packages/react-dom/src/client/ReactDOM.js +++ /dev/null @@ -1,204 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import type {ReactNodeList} from 'shared/ReactTypes'; -import type { - RootType, - HydrateRootOptions, - CreateRootOptions, -} from './ReactDOMRoot'; - -import {disableLegacyMode} from 'shared/ReactFeatureFlags'; -import { - createRoot as createRootImpl, - hydrateRoot as hydrateRootImpl, - isValidContainer, -} from './ReactDOMRoot'; -import {createEventHandle} from 'react-dom-bindings/src/client/ReactDOMEventHandle'; -import {runWithPriority} from 'react-dom-bindings/src/client/ReactDOMUpdatePriority'; -import {flushSync as flushSyncIsomorphic} from '../shared/ReactDOMFlushSync'; - -import { - flushSyncFromReconciler as flushSyncWithoutWarningIfAlreadyRendering, - isAlreadyRendering, - injectIntoDevTools, - findHostInstance, -} from 'react-reconciler/src/ReactFiberReconciler'; -import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal'; -import {canUseDOM} from 'shared/ExecutionEnvironment'; -import ReactVersion from 'shared/ReactVersion'; - -import {getClosestInstanceFromNode} from 'react-dom-bindings/src/client/ReactDOMComponentTree'; -import Internals from '../ReactDOMSharedInternals'; - -export { - prefetchDNS, - preconnect, - preload, - preloadModule, - preinit, - preinitModule, -} from '../shared/ReactDOMFloat'; -export { - useFormStatus, - useFormState, - requestFormReset, -} from 'react-dom-bindings/src/shared/ReactDOMFormActions'; - -if (__DEV__) { - if ( - typeof Map !== 'function' || - // $FlowFixMe[prop-missing] Flow incorrectly thinks Map has no prototype - Map.prototype == null || - typeof Map.prototype.forEach !== 'function' || - typeof Set !== 'function' || - // $FlowFixMe[prop-missing] Flow incorrectly thinks Set has no prototype - Set.prototype == null || - typeof Set.prototype.clear !== 'function' || - typeof Set.prototype.forEach !== 'function' - ) { - console.error( - 'React depends on Map and Set built-in types. Make sure that you load a ' + - 'polyfill in older browsers. https://react.dev/link/react-polyfills', - ); - } -} - -function createPortal( - children: ReactNodeList, - container: Element | DocumentFragment, - key: ?string = null, -): React$Portal { - if (!isValidContainer(container)) { - throw new Error('Target container is not a DOM element.'); - } - - // TODO: pass ReactDOM portal implementation as third argument - // $FlowFixMe[incompatible-return] The Flow type is opaque but there's no way to actually create it. - return createPortalImpl(children, container, null, key); -} - -function createRoot( - container: Element | Document | DocumentFragment, - options?: CreateRootOptions, -): RootType { - if (__DEV__) { - if (!Internals.usingClientEntryPoint) { - console.error( - 'You are importing createRoot from "react-dom" which is not supported. ' + - 'You should instead import it from "react-dom/client".', - ); - } - } - return createRootImpl(container, options); -} - -function hydrateRoot( - container: Document | Element, - initialChildren: ReactNodeList, - options?: HydrateRootOptions, -): RootType { - if (__DEV__) { - if (!Internals.usingClientEntryPoint) { - console.error( - 'You are importing hydrateRoot from "react-dom" which is not supported. ' + - 'You should instead import it from "react-dom/client".', - ); - } - } - return hydrateRootImpl(container, initialChildren, options); -} - -// Overload the definition to the two valid signatures. -// Warning, this opts-out of checking the function body. -declare function flushSyncFromReconciler(fn: () => R): R; -// eslint-disable-next-line no-redeclare -declare function flushSyncFromReconciler(): void; -// eslint-disable-next-line no-redeclare -function flushSyncFromReconciler(fn: (() => R) | void): R | void { - if (__DEV__) { - if (isAlreadyRendering()) { - console.error( - 'flushSync was called from inside a lifecycle method. React cannot ' + - 'flush when React is already rendering. Consider moving this call to ' + - 'a scheduler task or micro task.', - ); - } - } - return flushSyncWithoutWarningIfAlreadyRendering(fn); -} - -const flushSync: typeof flushSyncIsomorphic = disableLegacyMode - ? flushSyncIsomorphic - : flushSyncFromReconciler; - -function findDOMNode( - componentOrElement: React$Component, -): null | Element | Text { - return findHostInstance(componentOrElement); -} - -// Expose findDOMNode on internals -Internals.findDOMNode = findDOMNode; - -function unstable_batchedUpdates(fn: (a: A) => R, a: A): R { - // batchedUpdates was a legacy mode feature that is a no-op outside of - // legacy mode. In 19, we made it an actual no-op, but we're keeping it - // for now since there may be libraries that still include it. - return fn(a); -} - -export { - createPortal, - unstable_batchedUpdates, - flushSync, - ReactVersion as version, - // exposeConcurrentModeAPIs - createRoot, - hydrateRoot, - // enableCreateEventHandleAPI - createEventHandle as unstable_createEventHandle, - // TODO: Remove this once callers migrate to alternatives. - // This should only be used by React internals. - runWithPriority as unstable_runWithPriority, -}; - -const foundDevTools = injectIntoDevTools({ - findFiberByHostInstance: getClosestInstanceFromNode, - bundleType: __DEV__ ? 1 : 0, - version: ReactVersion, - rendererPackageName: 'react-dom', -}); - -if (__DEV__) { - if (!foundDevTools && canUseDOM && window.top === window.self) { - // If we're in Chrome or Firefox, provide a download link if not installed. - if ( - (navigator.userAgent.indexOf('Chrome') > -1 && - navigator.userAgent.indexOf('Edge') === -1) || - navigator.userAgent.indexOf('Firefox') > -1 - ) { - const protocol = window.location.protocol; - // Don't warn in exotic cases like chrome-extension://. - if (/^(https?|file):$/.test(protocol)) { - // eslint-disable-next-line react-internal/no-production-logging - console.info( - '%cDownload the React DevTools ' + - 'for a better development experience: ' + - 'https://react.dev/link/react-devtools' + - (protocol === 'file:' - ? '\nYou might need to use a local HTTP server (instead of file://): ' + - 'https://react.dev/link/react-devtools-faq' - : ''), - 'font-weight:bold', - ); - } - } - } -} diff --git a/packages/react-dom/src/client/ReactDOMClient.js b/packages/react-dom/src/client/ReactDOMClient.js new file mode 100644 index 0000000000000..036fd846a47ba --- /dev/null +++ b/packages/react-dom/src/client/ReactDOMClient.js @@ -0,0 +1,84 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +import {createRoot, hydrateRoot} from './ReactDOMRoot'; + +import { + injectIntoDevTools, + findHostInstance, +} from 'react-reconciler/src/ReactFiberReconciler'; +import {canUseDOM} from 'shared/ExecutionEnvironment'; +import ReactVersion from 'shared/ReactVersion'; + +import {getClosestInstanceFromNode} from 'react-dom-bindings/src/client/ReactDOMComponentTree'; +import Internals from 'shared/ReactDOMSharedInternals'; + +if (__DEV__) { + if ( + typeof Map !== 'function' || + // $FlowFixMe[prop-missing] Flow incorrectly thinks Map has no prototype + Map.prototype == null || + typeof Map.prototype.forEach !== 'function' || + typeof Set !== 'function' || + // $FlowFixMe[prop-missing] Flow incorrectly thinks Set has no prototype + Set.prototype == null || + typeof Set.prototype.clear !== 'function' || + typeof Set.prototype.forEach !== 'function' + ) { + console.error( + 'React depends on Map and Set built-in types. Make sure that you load a ' + + 'polyfill in older browsers. https://react.dev/link/react-polyfills', + ); + } +} + +function findDOMNode( + componentOrElement: React$Component, +): null | Element | Text { + return findHostInstance(componentOrElement); +} + +// Expose findDOMNode on internals +Internals.findDOMNode = findDOMNode; + +export {ReactVersion as version, createRoot, hydrateRoot}; + +const foundDevTools = injectIntoDevTools({ + findFiberByHostInstance: getClosestInstanceFromNode, + bundleType: __DEV__ ? 1 : 0, + version: ReactVersion, + rendererPackageName: 'react-dom', +}); + +if (__DEV__) { + if (!foundDevTools && canUseDOM && window.top === window.self) { + // If we're in Chrome or Firefox, provide a download link if not installed. + if ( + (navigator.userAgent.indexOf('Chrome') > -1 && + navigator.userAgent.indexOf('Edge') === -1) || + navigator.userAgent.indexOf('Firefox') > -1 + ) { + const protocol = window.location.protocol; + // Don't warn in exotic cases like chrome-extension://. + if (/^(https?|file):$/.test(protocol)) { + // eslint-disable-next-line react-internal/no-production-logging + console.info( + '%cDownload the React DevTools ' + + 'for a better development experience: ' + + 'https://react.dev/link/react-devtools' + + (protocol === 'file:' + ? '\nYou might need to use a local HTTP server (instead of file://): ' + + 'https://react.dev/link/react-devtools-faq' + : ''), + 'font-weight:bold', + ); + } + } + } +} diff --git a/packages/react-dom/src/client/ReactDOMFB.js b/packages/react-dom/src/client/ReactDOMClientFB.js similarity index 98% rename from packages/react-dom/src/client/ReactDOMFB.js rename to packages/react-dom/src/client/ReactDOMClientFB.js index 9b016b04d8dfd..1f918e3cf68c0 100644 --- a/packages/react-dom/src/client/ReactDOMFB.js +++ b/packages/react-dom/src/client/ReactDOMClientFB.js @@ -10,7 +10,7 @@ import type {ReactNodeList} from 'shared/ReactTypes'; import {disableLegacyMode} from 'shared/ReactFeatureFlags'; -import {isValidContainer} from './ReactDOMRoot'; +import {isValidContainer} from 'react-dom-bindings/src/client/ReactDOMContainer'; import {createEventHandle} from 'react-dom-bindings/src/client/ReactDOMEventHandle'; import {runWithPriority} from 'react-dom-bindings/src/client/ReactDOMUpdatePriority'; import {flushSync as flushSyncIsomorphic} from '../shared/ReactDOMFlushSync'; diff --git a/packages/react-dom/src/client/ReactDOMRoot.js b/packages/react-dom/src/client/ReactDOMRoot.js index ef573f5f790cd..aef8775de5a16 100644 --- a/packages/react-dom/src/client/ReactDOMRoot.js +++ b/packages/react-dom/src/client/ReactDOMRoot.js @@ -13,11 +13,11 @@ import type { TransitionTracingCallbacks, } from 'react-reconciler/src/ReactInternalTypes'; +import {isValidContainer} from 'react-dom-bindings/src/client/ReactDOMContainer'; import {queueExplicitHydrationTarget} from 'react-dom-bindings/src/events/ReactDOMEventReplaying'; import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols'; import { allowConcurrentByDefault, - disableCommentsAsDOMContainers, enableAsyncActions, } from 'shared/ReactFeatureFlags'; @@ -82,12 +82,7 @@ import { unmarkContainerAsRoot, } from 'react-dom-bindings/src/client/ReactDOMComponentTree'; import {listenToAllSupportedEvents} from 'react-dom-bindings/src/events/DOMPluginEventSystem'; -import { - ELEMENT_NODE, - COMMENT_NODE, - DOCUMENT_NODE, - DOCUMENT_FRAGMENT_NODE, -} from 'react-dom-bindings/src/client/HTMLNodeType'; +import {COMMENT_NODE} from 'react-dom-bindings/src/client/HTMLNodeType'; import { createContainer, @@ -357,31 +352,6 @@ export function hydrateRoot( return new ReactDOMHydrationRoot(root); } -export function isValidContainer(node: any): boolean { - return !!( - node && - (node.nodeType === ELEMENT_NODE || - node.nodeType === DOCUMENT_NODE || - node.nodeType === DOCUMENT_FRAGMENT_NODE || - (!disableCommentsAsDOMContainers && - node.nodeType === COMMENT_NODE && - (node: any).nodeValue === ' react-mount-point-unstable ')) - ); -} - -// TODO: Remove this function which also includes comment nodes. -// We only use it in places that are currently more relaxed. -export function isValidContainerLegacy(node: any): boolean { - return !!( - node && - (node.nodeType === ELEMENT_NODE || - node.nodeType === DOCUMENT_NODE || - node.nodeType === DOCUMENT_FRAGMENT_NODE || - (node.nodeType === COMMENT_NODE && - (node: any).nodeValue === ' react-mount-point-unstable ')) - ); -} - function warnIfReactDOMContainerInDEV(container: any) { if (__DEV__) { if (isContainerMarkedAsRoot(container)) { diff --git a/packages/react-dom/src/client/ReactDOMRootFB.js b/packages/react-dom/src/client/ReactDOMRootFB.js index 38fe67c0a5b26..f41d8868279c7 100644 --- a/packages/react-dom/src/client/ReactDOMRootFB.js +++ b/packages/react-dom/src/client/ReactDOMRootFB.js @@ -36,7 +36,7 @@ import { unmarkContainerAsRoot, } from 'react-dom-bindings/src/client/ReactDOMComponentTree'; import {listenToAllSupportedEvents} from 'react-dom-bindings/src/events/DOMPluginEventSystem'; -import {isValidContainerLegacy} from './ReactDOMRoot'; +import {isValidContainerLegacy} from 'react-dom-bindings/src/client/ReactDOMContainer'; import { DOCUMENT_NODE, ELEMENT_NODE, diff --git a/packages/react-dom/src/server/ReactDOMServerRenderingStub.js b/packages/react-dom/src/server/ReactDOMServerRenderingStub.js deleted file mode 100644 index d3a7f33095fd6..0000000000000 --- a/packages/react-dom/src/server/ReactDOMServerRenderingStub.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export { - preinit, - preinitModule, - preload, - preloadModule, - preconnect, - prefetchDNS, -} from '../shared/ReactDOMFloat'; -export { - useFormStatus, - useFormState, -} from 'react-dom-bindings/src/shared/ReactDOMFormActions'; - -export function createPortal() { - throw new Error( - 'createPortal was called on the server. Portals are not currently' + - ' supported on the server. Update your program to conditionally call' + - ' createPortal on the client only.', - ); -} - -export function flushSync() { - throw new Error( - 'flushSync was called on the server. This is likely caused by a' + - ' function being called during render or in module scope that was' + - ' intended to be called from an effect or event handler. Update your' + - ' to not call flushSync no the server.', - ); -} - -// on the server we just call the callback because there is -// not update mechanism. Really this should not be called on the -// server but since the semantics are generally clear enough we -// can provide this trivial implementation. -function batchedUpdates(fn: A => R, a: A): R { - return fn(a); -} - -export {batchedUpdates as unstable_batchedUpdates}; diff --git a/packages/react-dom/src/shared/ReactDOM.js b/packages/react-dom/src/shared/ReactDOM.js new file mode 100644 index 0000000000000..f1d48bfacd4de --- /dev/null +++ b/packages/react-dom/src/shared/ReactDOM.js @@ -0,0 +1,84 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +import type {ReactNodeList} from 'shared/ReactTypes'; + +import ReactVersion from 'shared/ReactVersion'; + +import {isValidContainer} from 'react-dom-bindings/src/client/ReactDOMContainer'; +import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal'; +import {flushSync} from './ReactDOMFlushSync'; + +import { + prefetchDNS, + preconnect, + preload, + preloadModule, + preinit, + preinitModule, +} from './ReactDOMFloat'; +import { + requestFormReset, + useFormStatus, + useFormState, +} from 'react-dom-bindings/src/shared/ReactDOMFormActions'; + +if (__DEV__) { + if ( + typeof Map !== 'function' || + // $FlowFixMe[prop-missing] Flow incorrectly thinks Map has no prototype + Map.prototype == null || + typeof Map.prototype.forEach !== 'function' || + typeof Set !== 'function' || + // $FlowFixMe[prop-missing] Flow incorrectly thinks Set has no prototype + Set.prototype == null || + typeof Set.prototype.clear !== 'function' || + typeof Set.prototype.forEach !== 'function' + ) { + console.error( + 'React depends on Map and Set built-in types. Make sure that you load a ' + + 'polyfill in older browsers. https://reactjs.org/link/react-polyfills', + ); + } +} + +function batchedUpdates(fn: (a: A) => R, a: A): R { + // batchedUpdates is now just a passthrough noop + return fn(a); +} + +function createPortal( + children: ReactNodeList, + container: Element | DocumentFragment, + key: ?string = null, +): React$Portal { + if (!isValidContainer(container)) { + throw new Error('Target container is not a DOM element.'); + } + + // TODO: pass ReactDOM portal implementation as third argument + // $FlowFixMe[incompatible-return] The Flow type is opaque but there's no way to actually create it. + return createPortalImpl(children, container, null, key); +} + +export { + ReactVersion as version, + createPortal, + flushSync, + batchedUpdates as unstable_batchedUpdates, + prefetchDNS, + preconnect, + preload, + preloadModule, + preinit, + preinitModule, + requestFormReset, + useFormStatus, + useFormState, +}; diff --git a/packages/react-dom/unstable_testing.classic.fb.js b/packages/react-dom/unstable_testing.classic.fb.js deleted file mode 100644 index db9a26388fb93..0000000000000 --- a/packages/react-dom/unstable_testing.classic.fb.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export { - createPortal, - findDOMNode, - flushSync, - render, - unmountComponentAtNode, - unstable_batchedUpdates, - unstable_createEventHandle, - unstable_renderSubtreeIntoContainer, - unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority. - useFormStatus, - useFormState, - prefetchDNS, - preconnect, - preload, - preloadModule, - preinit, - preinitModule, - version, - __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, -} from './index.classic.fb.js'; - -export {createRoot, hydrateRoot} from './client.js'; - -export { - createComponentSelector, - createHasPseudoClassSelector, - createRoleSelector, - createTestNameSelector, - createTextSelector, - getFindAllNodesFailureDescription, - findAllNodes, - findBoundingRects, - focusWithin, - observeVisibleRects, -} from 'react-reconciler/src/ReactFiberReconciler'; diff --git a/packages/react-dom/unstable_testing.experimental.js b/packages/react-dom/unstable_testing.experimental.js index da7aeb1fb1a92..499635551ed58 100644 --- a/packages/react-dom/unstable_testing.experimental.js +++ b/packages/react-dom/unstable_testing.experimental.js @@ -7,23 +7,7 @@ * @flow */ -export { - createPortal, - flushSync, - unstable_batchedUpdates, - useFormStatus, - useFormState, - prefetchDNS, - preconnect, - preload, - preloadModule, - preinit, - preinitModule, - version, - __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, -} from './index.experimental.js'; - -export {createRoot, hydrateRoot} from './client.js'; +export * from './client.js'; export { createComponentSelector, diff --git a/packages/react-dom/unstable_testing.js b/packages/react-dom/unstable_testing.js index 19cc1515cdffe..bc330f3537ef3 100644 --- a/packages/react-dom/unstable_testing.js +++ b/packages/react-dom/unstable_testing.js @@ -7,34 +7,4 @@ * @flow */ -export { - createPortal, - flushSync, - unstable_batchedUpdates, - unstable_createEventHandle, - unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority. - useFormStatus, - useFormState, - prefetchDNS, - preconnect, - preload, - preloadModule, - preinit, - preinitModule, - version, -} from './index.js'; - -export {createRoot, hydrateRoot} from './client.js'; - -export { - createComponentSelector, - createHasPseudoClassSelector, - createRoleSelector, - createTestNameSelector, - createTextSelector, - getFindAllNodesFailureDescription, - findAllNodes, - findBoundingRects, - focusWithin, - observeVisibleRects, -} from 'react-reconciler/src/ReactFiberReconciler'; +export * from './client.js'; diff --git a/packages/react-dom/unstable_testing.stable.js b/packages/react-dom/unstable_testing.stable.js deleted file mode 100644 index 59b667fa15a7d..0000000000000 --- a/packages/react-dom/unstable_testing.stable.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export { - createPortal, - flushSync, - unstable_batchedUpdates, - useFormStatus, - useFormState, - prefetchDNS, - preconnect, - preload, - preloadModule, - preinit, - preinitModule, - version, - __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, -} from './index.stable.js'; -export {createRoot, hydrateRoot} from './client.js'; diff --git a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js index c92f7799bb6e8..58833f3654a5d 100644 --- a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js +++ b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js @@ -1172,19 +1172,22 @@ describe('ReactFlightDOMBrowser', () => { root.render(); }); expect(document.head.innerHTML).toBe( - // Currently the react-dom entrypoint loads the fiber implementation - // even if you never pull in the the client APIs. this causes the fiber - // dispatcher to be present even for Flight ReactDOM calls. This is not what - // you would have in a real application but given we're runnign flight and - // fiber the in the same scope it's unavoidable until we make the entrypoint - // not automatically pull in the fiber implementation. This test currently - // asserts this be demonstrating that the preload call after the await point - // is written to the document before the call before it. We still demonstrate that - // flight handled the sync call because if the fiber implementation did it would appear - // before the after call. In the future we will change this assertion once the fiber - // implementation no long automatically gets pulled in - '', - // '', + gate(f => f.www) + ? // The www entrypoints for ReactDOM and ReactDOMClient are unified so even + // when you pull in just the top level the dispatcher for the Document is + // loaded alongside it. In a normal environment there would be nothing to dispatch to + // in a server environment so the preload calls would still only be dispatched to fizz + // or the browser but not both. However in this contrived test environment the preloads + // are being dispatched simultaneously causing an extraneous preload to show up. This test currently + // asserts this be demonstrating that the preload call after the await point + // is written to the document before the call before it. We still demonstrate that + // flight handled the sync call because if the fiber implementation did it would appear + // before the after call. In the future we will change this assertion once the fiber + // implementation no long automatically gets pulled in + '' + : // For other release channels the client and isomorphic entrypoints are separate and thus we only + // observe the expected preload from before the first await + '', ); expect(container.innerHTML).toBe('

hello world

'); }); diff --git a/scripts/jest/setupHostConfigs.js b/scripts/jest/setupHostConfigs.js index 8f2d508856e6f..0339f144693e2 100644 --- a/scripts/jest/setupHostConfigs.js +++ b/scripts/jest/setupHostConfigs.js @@ -12,8 +12,43 @@ function resolveEntryFork(resolvedEntry, isFBBundle) { // .stable.js // .experimental.js // .js - if (isFBBundle) { + // FB builds for react-dom need to alias both react-dom and react-dom/client to the same + // entrypoint since there is only a single build for them. + if ( + resolvedEntry.endsWith('react-dom/index.js') || + resolvedEntry.endsWith('react-dom/client.js') || + resolvedEntry.endsWith('react-dom/unstable_testing.js') + ) { + let specifier; + let entrypoint; + if (resolvedEntry.endsWith('index.js')) { + specifier = 'react-dom'; + entrypoint = __EXPERIMENTAL__ + ? 'src/ReactDOMFB.modern.js' + : 'src/ReactDOMFB.js'; + } else if (resolvedEntry.endsWith('client.js')) { + specifier = 'react-dom/client'; + entrypoint = __EXPERIMENTAL__ + ? 'src/ReactDOMFB.modern.js' + : 'src/ReactDOMFB.js'; + } else { + // must be unstable_testing + specifier = 'react-dom/unstable_testing'; + entrypoint = __EXPERIMENTAL__ + ? 'src/ReactDOMTestingFB.modern.js' + : 'src/ReactDOMTestingFB.js'; + } + + resolvedEntry = nodePath.join(resolvedEntry, '..', entrypoint); + if (fs.existsSync(resolvedEntry)) { + return resolvedEntry; + } + const fbReleaseChannel = __EXPERIMENTAL__ ? 'www-modern' : 'www-classic'; + throw new Error( + `${fbReleaseChannel} tests are expected to alias ${specifier} to ${entrypoint} but this file was not found` + ); + } const resolvedFBEntry = resolvedEntry.replace( '.js', __EXPERIMENTAL__ ? '.modern.fb.js' : '.classic.fb.js' diff --git a/scripts/rollup/bundles.js b/scripts/rollup/bundles.js index f5b5b3a23e5ff..f84f556d17550 100644 --- a/scripts/rollup/bundles.js +++ b/scripts/rollup/bundles.js @@ -151,14 +151,7 @@ const bundles = [ /******* React DOM *******/ { - bundleTypes: [ - NODE_DEV, - NODE_PROD, - NODE_PROFILING, - FB_WWW_DEV, - FB_WWW_PROD, - FB_WWW_PROFILING, - ], + bundleTypes: [NODE_DEV, NODE_PROD], moduleType: RENDERER, entry: 'react-dom', global: 'ReactDOM', @@ -166,12 +159,43 @@ const bundles = [ wrapWithModuleBoundaries: true, externals: ['react'], }, + /******* React DOM Client *******/ + { + bundleTypes: [NODE_DEV, NODE_PROD], + moduleType: RENDERER, + entry: 'react-dom/client', + global: 'ReactDOM', + minifyWithProdErrorCodes: true, + wrapWithModuleBoundaries: true, + externals: ['react', 'react-dom'], + }, + + /******* React DOM Profiling (Client) *******/ + { + bundleTypes: [NODE_DEV, NODE_PROFILING], + moduleType: RENDERER, + entry: 'react-dom/profiling', + global: 'ReactDOM', + minifyWithProdErrorCodes: true, + wrapWithModuleBoundaries: true, + externals: ['react', 'react-dom'], + }, + /******* React DOM FB *******/ + { + bundleTypes: [FB_WWW_DEV, FB_WWW_PROD, FB_WWW_PROFILING], + moduleType: RENDERER, + entry: 'react-dom/src/ReactDOMFB.js', + global: 'ReactDOM', + minifyWithProdErrorCodes: true, + wrapWithModuleBoundaries: true, + externals: ['react'], + }, /******* React DOM React Server *******/ { bundleTypes: [NODE_DEV, NODE_PROD], moduleType: RENDERER, - entry: 'react-dom/src/ReactDOMServer.js', + entry: 'react-dom/src/ReactDOMReactServer.js', name: 'react-dom.react-server', condition: 'react-server', global: 'ReactDOM', @@ -191,16 +215,25 @@ const bundles = [ externals: ['react', 'react-dom'], }, - /******* React DOM - www - Testing *******/ + /******* React DOM - Testing *******/ { moduleType: RENDERER, - bundleTypes: __EXPERIMENTAL__ - ? [FB_WWW_DEV, FB_WWW_PROD, NODE_DEV, NODE_PROD] - : [FB_WWW_DEV, FB_WWW_PROD], + bundleTypes: __EXPERIMENTAL__ ? [NODE_DEV, NODE_PROD] : [], entry: 'react-dom/unstable_testing', global: 'ReactDOMTesting', minifyWithProdErrorCodes: true, wrapWithModuleBoundaries: false, + externals: ['react', 'react-dom'], + }, + + /******* React DOM - www - Testing *******/ + { + moduleType: RENDERER, + bundleTypes: [FB_WWW_DEV, FB_WWW_PROD], + entry: 'react-dom/src/ReactDOMTestingFB.js', + global: 'ReactDOMTesting', + minifyWithProdErrorCodes: true, + wrapWithModuleBoundaries: false, externals: ['react'], }, @@ -306,18 +339,6 @@ const bundles = [ externals: [], }, - /******* React DOM Server Render Stub *******/ - { - bundleTypes: [NODE_DEV, NODE_PROD], - moduleType: RENDERER, - entry: 'react-dom/server-rendering-stub', - name: 'react-dom-server-rendering-stub', - global: 'ReactDOMServerRenderingStub', - minifyWithProdErrorCodes: true, - wrapWithModuleBoundaries: false, - externals: ['react'], - }, - /******* React Server DOM Webpack Server *******/ { bundleTypes: [NODE_DEV, NODE_PROD], diff --git a/scripts/rollup/forks.js b/scripts/rollup/forks.js index 35b9a5421cf86..a83b8b1b1a969 100644 --- a/scripts/rollup/forks.js +++ b/scripts/rollup/forks.js @@ -91,9 +91,9 @@ const forks = Object.freeze({ ) => { if ( entry === 'react-dom' || - entry === 'react-dom/server-rendering-stub' || - entry === 'react-dom/src/ReactDOMServer.js' || - entry === 'react-dom/unstable_testing' + entry === 'react-dom/src/ReactDOMFB.js' || + entry === 'react-dom/src/ReactDOMTestingFB.js' || + entry === 'react-dom/src/ReactDOMServer.js' ) { if ( bundleType === FB_WWW_DEV || diff --git a/scripts/rollup/modules.js b/scripts/rollup/modules.js index 6e8a0c9f0b439..e1ebc1c945a0d 100644 --- a/scripts/rollup/modules.js +++ b/scripts/rollup/modules.js @@ -29,7 +29,6 @@ const knownGlobals = Object.freeze({ react: 'React', 'react-dom': 'ReactDOM', 'react-dom/server': 'ReactDOMServer', - 'react-interactions/events/tap': 'ReactEventsTap', scheduler: 'Scheduler', 'scheduler/unstable_mock': 'SchedulerMock', ReactNativeInternalFeatureFlags: 'ReactNativeInternalFeatureFlags', diff --git a/scripts/shared/inlinedHostConfigs.js b/scripts/shared/inlinedHostConfigs.js index 8995d4a79a6da..74f72140c6062 100644 --- a/scripts/shared/inlinedHostConfigs.js +++ b/scripts/shared/inlinedHostConfigs.js @@ -11,21 +11,23 @@ module.exports = [ shortName: 'dom-node', entryPoints: [ 'react-dom', - 'react-dom/src/ReactDOMServer.js', + 'react-dom/client', + 'react-dom/profiling', 'react-dom/unstable_testing', + 'react-dom/src/ReactDOMReactServer.js', 'react-dom/src/server/react-dom-server.node.js', 'react-dom/static.node', 'react-dom/test-utils', - 'react-dom/server-rendering-stub', 'react-dom/unstable_server-external-runtime', 'react-server-dom-webpack/server.node.unbundled', 'react-server-dom-webpack/client.node.unbundled', ], paths: [ 'react-dom', - 'react-dom/src/ReactDOMServer.js', + 'react-dom/src/ReactDOMReactServer.js', 'react-dom-bindings', 'react-dom/client', + 'react-dom/profiling', 'react-dom/server', 'react-dom/server.node', 'react-dom/static', @@ -45,7 +47,6 @@ module.exports = [ 'react-devtools-core', 'react-devtools-shell', 'react-devtools-shared', - 'react-interactions', 'shared/ReactDOMSharedInternals', 'react-server/src/ReactFlightServerConfigDebugNode.js', ], @@ -62,6 +63,7 @@ module.exports = [ 'react-dom', 'react-dom-bindings', 'react-dom/client', + 'react-dom/profiling', 'react-dom/server', 'react-dom/server.node', 'react-dom/static', @@ -82,7 +84,6 @@ module.exports = [ 'react-devtools-core', 'react-devtools-shell', 'react-devtools-shared', - 'react-interactions', 'shared/ReactDOMSharedInternals', 'react-server/src/ReactFlightServerConfigDebugNode.js', ], @@ -99,6 +100,7 @@ module.exports = [ 'react-dom', 'react-dom-bindings', 'react-dom/client', + 'react-dom/profiling', 'react-dom/server', 'react-dom/server.node', 'react-dom/static', @@ -119,7 +121,6 @@ module.exports = [ 'react-devtools-core', 'react-devtools-shell', 'react-devtools-shared', - 'react-interactions', 'shared/ReactDOMSharedInternals', 'react-server/src/ReactFlightServerConfigDebugNode.js', ], @@ -136,6 +137,7 @@ module.exports = [ 'react-dom', 'react-dom-bindings', 'react-dom/client', + 'react-dom/profiling', 'react-dom/server', 'react-dom/server.node', 'react-dom/static', @@ -157,7 +159,6 @@ module.exports = [ 'react-devtools-core', 'react-devtools-shell', 'react-devtools-shared', - 'react-interactions', 'shared/ReactDOMSharedInternals', 'react-server/src/ReactFlightServerConfigDebugNode.js', ], @@ -166,9 +167,17 @@ module.exports = [ }, { shortName: 'dom-bun', - entryPoints: ['react-dom', 'react-dom/src/server/react-dom-server.bun.js'], + entryPoints: [ + 'react-dom', + 'react-dom/client', + 'react-dom/profiling', + 'react-dom/unstable_testing', + 'react-dom/src/server/react-dom-server.bun.js', + ], paths: [ 'react-dom', + 'react-dom/client', + 'react-dom/profiling', 'react-dom/server.bun', 'react-dom/src/server/react-dom-server.bun', 'react-dom/src/server/ReactDOMFizzServerBun.js', @@ -182,19 +191,21 @@ module.exports = [ shortName: 'dom-browser', entryPoints: [ 'react-dom', + 'react-dom/client', + 'react-dom/profiling', 'react-dom/unstable_testing', 'react-dom/src/server/react-dom-server.browser.js', 'react-dom/static.browser', - 'react-dom/server-rendering-stub', 'react-dom/unstable_server-external-runtime', 'react-server-dom-webpack/server.browser', 'react-server-dom-webpack/client.browser', ], paths: [ 'react-dom', - 'react-dom/src/ReactDOMServer.js', + 'react-dom/src/ReactDOMReactServer.js', 'react-dom-bindings', 'react-dom/client', + 'react-dom/profiling', 'react-dom/server.browser', 'react-dom/static.browser', 'react-dom/unstable_testing', @@ -223,8 +234,9 @@ module.exports = [ entryPoints: ['react-server-dom-esm/client.browser'], paths: [ 'react-dom', - 'react-dom/src/ReactDOMServer.js', + 'react-dom/src/ReactDOMReactServer.js', 'react-dom/client', + 'react-dom/profiling', 'react-dom/server', 'react-dom/server.node', 'react-dom-bindings', @@ -236,7 +248,6 @@ module.exports = [ 'react-devtools-core', 'react-devtools-shell', 'react-devtools-shared', - 'react-interactions', 'shared/ReactDOMSharedInternals', ], isFlowTyped: true, @@ -251,6 +262,7 @@ module.exports = [ paths: [ 'react-dom', 'react-dom/client', + 'react-dom/profiling', 'react-dom/server', 'react-dom/server.node', 'react-dom-bindings', @@ -266,7 +278,6 @@ module.exports = [ 'react-devtools-core', 'react-devtools-shell', 'react-devtools-shared', - 'react-interactions', 'shared/ReactDOMSharedInternals', ], isFlowTyped: true, @@ -282,9 +293,10 @@ module.exports = [ ], paths: [ 'react-dom', - 'react-dom/src/ReactDOMServer.js', + 'react-dom/src/ReactDOMReactServer.js', 'react-dom-bindings', 'react-dom/client', + 'react-dom/profiling', 'react-dom/server.edge', 'react-dom/static.edge', 'react-dom/unstable_testing', @@ -316,9 +328,10 @@ module.exports = [ ], paths: [ 'react-dom', - 'react-dom/src/ReactDOMServer.js', + 'react-dom/src/ReactDOMReactServer.js', 'react-dom-bindings', 'react-dom/client', + 'react-dom/profiling', 'react-dom/server.edge', 'react-dom/static.edge', 'react-dom/unstable_testing', @@ -350,9 +363,10 @@ module.exports = [ ], paths: [ 'react-dom', - 'react-dom/src/ReactDOMServer.js', + 'react-dom/src/ReactDOMReactServer.js', 'react-dom-bindings', 'react-dom/client', + 'react-dom/profiling', 'react-dom/server', 'react-dom/server.node', 'react-dom/static', @@ -370,7 +384,6 @@ module.exports = [ 'react-devtools-core', 'react-devtools-shell', 'react-devtools-shared', - 'react-interactions', 'shared/ReactDOMSharedInternals', 'react-server/src/ReactFlightServerConfigDebugNode.js', ], @@ -385,7 +398,7 @@ module.exports = [ ], paths: [ 'react-dom', - 'react-dom/src/ReactDOMServer.js', + 'react-dom/src/ReactDOMReactServer.js', 'react-dom-bindings', 'react-server-dom-webpack', 'react-dom/src/server/ReactDOMLegacyServerImpl.js', // not an entrypoint, but only usable in *Browser and *Node files @@ -400,10 +413,16 @@ module.exports = [ }, { shortName: 'dom-fb', - entryPoints: ['react-server-dom-fb/src/ReactDOMServerFB.js'], + entryPoints: [ + 'react-dom/src/ReactDOMFB.js', + 'react-dom/src/ReactDOMTestingFB.js', + 'react-server-dom-fb/src/ReactDOMServerFB.js', + ], paths: [ 'react-dom', - 'react-dom/src/ReactDOMServer.js', + 'react-dom/src/ReactDOMFB.js', + 'react-dom/src/ReactDOMTestingFB.js', + 'react-dom/src/ReactDOMReactServer.js', 'react-dom-bindings', 'react-server-dom-fb', 'shared/ReactDOMSharedInternals', diff --git a/scripts/shared/pathsByLanguageVersion.js b/scripts/shared/pathsByLanguageVersion.js index 10c49821af5e9..4a754f3cd491e 100644 --- a/scripts/shared/pathsByLanguageVersion.js +++ b/scripts/shared/pathsByLanguageVersion.js @@ -16,8 +16,6 @@ const esNextPaths = [ // Source files 'packages/*/src/**/*.js', 'packages/dom-event-testing-library/**/*.js', - 'packages/react-interactions/**/*.js', - 'packages/react-interactions/**/*.js', 'packages/shared/**/*.js', // Shims and Flow environment 'scripts/flow/*.js',