From 860f673a7a6bf826010d41de2f66de62171ab676 Mon Sep 17 00:00:00 2001 From: Ricky Date: Wed, 10 Mar 2021 18:34:35 -0500 Subject: [PATCH] Remove Blocking Mode (again) (#20974) * Remove Blocking Mode (again) * Rename batchingmode file and comment --- packages/react-dom/index.classic.fb.js | 2 - packages/react-dom/index.experimental.js | 1 - packages/react-dom/index.js | 2 - packages/react-dom/index.modern.fb.js | 2 - .../src/__tests__/ReactDOMFiberAsync-test.js | 40 ++++++------- ...DOMServerPartialHydration-test.internal.js | 2 +- .../ReactDOMServerSuspense-test.internal.js | 2 +- .../src/__tests__/ReactTestUtilsAct-test.js | 58 ++----------------- .../ReactUnmockedSchedulerWarning-test.js | 19 ------ packages/react-dom/src/client/ReactDOM.js | 3 +- packages/react-dom/src/client/ReactDOMRoot.js | 32 ++-------- packages/react-noop-renderer/src/ReactNoop.js | 1 - .../src/ReactNoopPersistent.js | 1 - .../src/createReactNoop.js | 33 +---------- .../react-reconciler/src/ReactFiber.new.js | 23 +------- .../react-reconciler/src/ReactFiber.old.js | 23 +------- .../src/ReactFiberBeginWork.new.js | 21 +++---- .../src/ReactFiberBeginWork.old.js | 21 +++---- .../src/ReactFiberCompleteWork.new.js | 11 +--- .../src/ReactFiberCompleteWork.old.js | 11 +--- .../src/ReactFiberHooks.new.js | 4 +- .../src/ReactFiberHooks.old.js | 4 +- .../src/ReactFiberRoot.new.js | 5 +- .../src/ReactFiberRoot.old.js | 5 +- .../src/ReactFiberThrow.new.js | 10 ++-- .../src/ReactFiberThrow.old.js | 10 ++-- .../src/ReactFiberWorkLoop.new.js | 11 ++-- .../src/ReactFiberWorkLoop.old.js | 11 ++-- .../react-reconciler/src/ReactRootTags.js | 5 +- .../react-reconciler/src/ReactTypeOfMode.js | 13 ++--- ...rnal.js => ReactBatching-test.internal.js} | 25 ++++---- ...tIncrementalErrorHandling-test.internal.js | 4 -- .../src/__tests__/ReactOffscreen-test.js | 12 ++-- .../ReactSuspenseFuzz-test.internal.js | 7 --- .../ReactStrictMode-test.internal.js | 17 ------ packages/shared/ReactFeatureFlags.js | 2 +- 36 files changed, 121 insertions(+), 332 deletions(-) rename packages/react-reconciler/src/__tests__/{ReactBatchedMode-test.internal.js => ReactBatching-test.internal.js} (86%) diff --git a/packages/react-dom/index.classic.fb.js b/packages/react-dom/index.classic.fb.js index ea9dd9aba257e..0b16c0808368b 100644 --- a/packages/react-dom/index.classic.fb.js +++ b/packages/react-dom/index.classic.fb.js @@ -30,8 +30,6 @@ export { unmountComponentAtNode, createRoot, createRoot as unstable_createRoot, - createBlockingRoot, - createBlockingRoot as unstable_createBlockingRoot, unstable_flushControlled, unstable_scheduleHydration, unstable_runWithPriority, diff --git a/packages/react-dom/index.experimental.js b/packages/react-dom/index.experimental.js index 9ed70f3959ec9..e685ec6e8a1f8 100644 --- a/packages/react-dom/index.experimental.js +++ b/packages/react-dom/index.experimental.js @@ -20,7 +20,6 @@ export { unmountComponentAtNode, // exposeConcurrentModeAPIs createRoot as unstable_createRoot, - createBlockingRoot as unstable_createBlockingRoot, unstable_flushControlled, unstable_scheduleHydration, // DO NOT USE: Temporarily exposing this to migrate off of Scheduler.runWithPriority. diff --git a/packages/react-dom/index.js b/packages/react-dom/index.js index 59825272c3a89..7adfaa4ad2185 100644 --- a/packages/react-dom/index.js +++ b/packages/react-dom/index.js @@ -21,8 +21,6 @@ export { unmountComponentAtNode, createRoot, createRoot as unstable_createRoot, - createBlockingRoot, - createBlockingRoot as unstable_createBlockingRoot, unstable_flushControlled, unstable_scheduleHydration, unstable_runWithPriority, diff --git a/packages/react-dom/index.modern.fb.js b/packages/react-dom/index.modern.fb.js index addcce97749c9..f91cc3cb89553 100644 --- a/packages/react-dom/index.modern.fb.js +++ b/packages/react-dom/index.modern.fb.js @@ -15,8 +15,6 @@ export { version, createRoot, createRoot as unstable_createRoot, - createBlockingRoot, - createBlockingRoot as unstable_createBlockingRoot, unstable_flushControlled, unstable_scheduleHydration, unstable_runWithPriority, diff --git a/packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.js b/packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.js index 7fde6e5ddeb6b..ff4e1b5aeeb5f 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.js @@ -574,31 +574,29 @@ describe('ReactDOMFiberAsync', () => { expect(containerC.textContent).toEqual('Finished'); }); - describe('createBlockingRoot', () => { - // @gate experimental - it('updates flush without yielding in the next event', () => { - const root = ReactDOM.unstable_createBlockingRoot(container); + // @gate experimental + it('updates flush without yielding in the next event', () => { + const root = ReactDOM.unstable_createRoot(container); - function Text(props) { - Scheduler.unstable_yieldValue(props.text); - return props.text; - } + function Text(props) { + Scheduler.unstable_yieldValue(props.text); + return props.text; + } - root.render( - <> - - - - , - ); + root.render( + <> + + + + , + ); - // Nothing should have rendered yet - expect(container.textContent).toEqual(''); + // Nothing should have rendered yet + expect(container.textContent).toEqual(''); - // Everything should render immediately in the next event - expect(Scheduler).toFlushExpired(['A', 'B', 'C']); - expect(container.textContent).toEqual('ABC'); - }); + // Everything should render immediately in the next event + expect(Scheduler).toFlushAndYield(['A', 'B', 'C']); + expect(container.textContent).toEqual('ABC'); }); // @gate experimental diff --git a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js index 91f6e8f022727..00ed4050d6a99 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js @@ -357,7 +357,7 @@ describe('ReactDOMServerPartialHydration', () => { }).toErrorDev( 'Warning: Cannot hydrate Suspense in legacy mode. Switch from ' + 'ReactDOM.hydrate(element, container) to ' + - 'ReactDOM.createBlockingRoot(container, { hydrate: true })' + + 'ReactDOM.createRoot(container, { hydrate: true })' + '.render(element) or remove the Suspense components from the server ' + 'rendered components.' + '\n in Suspense (at **)' + diff --git a/packages/react-dom/src/__tests__/ReactDOMServerSuspense-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMServerSuspense-test.internal.js index 6c48b36bd107d..7b28d572ccceb 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerSuspense-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerSuspense-test.internal.js @@ -127,7 +127,7 @@ describe('ReactDOMServerSuspense', () => { expect(divB.textContent).toBe('B'); act(() => { - const root = ReactDOM.createBlockingRoot(parent, {hydrate: true}); + const root = ReactDOM.createRoot(parent, {hydrate: true}); root.render(example); }); diff --git a/packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js b/packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js index 57807679e8eb2..242743d2f3732 100644 --- a/packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js +++ b/packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js @@ -72,33 +72,6 @@ describe('ReactTestUtils.act()', () => { runActTests('legacy mode', renderLegacy, unmountLegacy, rerenderLegacy); - // and then in blocking mode - if (__EXPERIMENTAL__) { - let blockingRoot = null; - const renderBatched = (el, dom) => { - blockingRoot = ReactDOM.unstable_createBlockingRoot(dom); - blockingRoot.render(el); - }; - - const unmountBatched = dom => { - if (blockingRoot !== null) { - blockingRoot.unmount(); - blockingRoot = null; - } - }; - - const rerenderBatched = el => { - blockingRoot.render(el); - }; - - runActTests( - 'blocking mode', - renderBatched, - unmountBatched, - rerenderBatched, - ); - } - describe('unacted effects', () => { function App() { React.useEffect(() => {}, []); @@ -124,19 +97,6 @@ describe('ReactTestUtils.act()', () => { ]); }); - // @gate experimental - it('warns in blocking mode', () => { - expect(() => { - const root = ReactDOM.unstable_createBlockingRoot( - document.createElement('div'), - ); - root.render(); - Scheduler.unstable_flushAll(); - }).toErrorDev([ - 'An update to App ran an effect, but was not wrapped in act(...)', - ]); - }); - // @gate experimental it('warns in concurrent mode', () => { expect(() => { @@ -731,14 +691,10 @@ function runActTests(label, render, unmount, rerender) { it('triggers fallbacks if available', async () => { if (label !== 'legacy mode') { - // FIXME: Support for Blocking* and Concurrent Mode were - // intentionally removed from the public version of `act`. It will - // be added back in a future major version, before Blocking and and - // Concurrent Mode are officially released. Consider disabling all - // non-Legacy tests in this suite until then. - // - // *Blocking Mode actually does happen to work, though - // not "officially" since it's an unreleased feature. + // FIXME: Support for Concurrent Root intentionally removed + // from the public version of `act`. It will be added back in + // a future major version, before the Concurrent Root is released. + // Consider skipping all non-Legacy tests in this suite until then. return; } @@ -794,10 +750,8 @@ function runActTests(label, render, unmount, rerender) { // In Concurrent Mode, refresh transitions delay indefinitely. expect(document.querySelector('[data-test-id=spinner]')).toBeNull(); } else { - // In Legacy Mode and Blocking Mode, all fallbacks are forced to - // display, even during a refresh transition. - // TODO: Consider delaying indefinitely in Blocking Mode, to match - // Concurrent Mode semantics. + // In Legacy Mode, all fallbacks are forced to display, + // even during a refresh transition. expect( document.querySelector('[data-test-id=spinner]'), ).not.toBeNull(); diff --git a/packages/react-dom/src/__tests__/ReactUnmockedSchedulerWarning-test.js b/packages/react-dom/src/__tests__/ReactUnmockedSchedulerWarning-test.js index 435b4989c1157..79437e7f5c760 100644 --- a/packages/react-dom/src/__tests__/ReactUnmockedSchedulerWarning-test.js +++ b/packages/react-dom/src/__tests__/ReactUnmockedSchedulerWarning-test.js @@ -43,22 +43,3 @@ it('should warn when rendering in concurrent mode', () => { ReactDOM.unstable_createRoot(document.createElement('div')).render(); }).toErrorDev([]); }); - -// @gate experimental -it('should warn when rendering in blocking mode', () => { - expect(() => { - ReactDOM.unstable_createBlockingRoot(document.createElement('div')).render( - , - ); - }).toErrorDev( - 'In Concurrent or Sync modes, the "scheduler" module needs to be mocked ' + - 'to guarantee consistent behaviour across tests and browsers.', - {withoutStack: true}, - ); - // does not warn twice - expect(() => { - ReactDOM.unstable_createBlockingRoot(document.createElement('div')).render( - , - ); - }).toErrorDev([]); -}); diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js index 66ae001c3b27d..7cff285a938d0 100644 --- a/packages/react-dom/src/client/ReactDOM.js +++ b/packages/react-dom/src/client/ReactDOM.js @@ -18,7 +18,7 @@ import { unstable_renderSubtreeIntoContainer, unmountComponentAtNode, } from './ReactDOMLegacy'; -import {createRoot, createBlockingRoot, isValidContainer} from './ReactDOMRoot'; +import {createRoot, isValidContainer} from './ReactDOMRoot'; import {createEventHandle} from './ReactDOMEventHandle'; import { @@ -201,7 +201,6 @@ export { unmountComponentAtNode, // exposeConcurrentModeAPIs createRoot, - createBlockingRoot, flushControlled as unstable_flushControlled, scheduleHydration as unstable_scheduleHydration, // Disabled behind disableUnstableRenderSubtreeIntoContainer diff --git a/packages/react-dom/src/client/ReactDOMRoot.js b/packages/react-dom/src/client/ReactDOMRoot.js index 62a72dc229618..56532d5d67488 100644 --- a/packages/react-dom/src/client/ReactDOMRoot.js +++ b/packages/react-dom/src/client/ReactDOMRoot.js @@ -51,25 +51,17 @@ import { registerMutableSourceForHydration, } from 'react-reconciler/src/ReactFiberReconciler'; import invariant from 'shared/invariant'; -import { - BlockingRoot, - ConcurrentRoot, - LegacyRoot, -} from 'react-reconciler/src/ReactRootTags'; +import {ConcurrentRoot, LegacyRoot} from 'react-reconciler/src/ReactRootTags'; function ReactDOMRoot(container: Container, options: void | RootOptions) { this._internalRoot = createRootImpl(container, ConcurrentRoot, options); } -function ReactDOMBlockingRoot( - container: Container, - tag: RootTag, - options: void | RootOptions, -) { - this._internalRoot = createRootImpl(container, tag, options); +function ReactDOMLegacyRoot(container: Container, options: void | RootOptions) { + this._internalRoot = createRootImpl(container, LegacyRoot, options); } -ReactDOMRoot.prototype.render = ReactDOMBlockingRoot.prototype.render = function( +ReactDOMRoot.prototype.render = ReactDOMLegacyRoot.prototype.render = function( children: ReactNodeList, ): void { const root = this._internalRoot; @@ -99,7 +91,7 @@ ReactDOMRoot.prototype.render = ReactDOMBlockingRoot.prototype.render = function updateContainer(children, root, null, null); }; -ReactDOMRoot.prototype.unmount = ReactDOMBlockingRoot.prototype.unmount = function(): void { +ReactDOMRoot.prototype.unmount = ReactDOMLegacyRoot.prototype.unmount = function(): void { if (__DEV__) { if (typeof arguments[0] === 'function') { console.error( @@ -169,23 +161,11 @@ export function createRoot( return new ReactDOMRoot(container, options); } -export function createBlockingRoot( - container: Container, - options?: RootOptions, -): RootType { - invariant( - isValidContainer(container), - 'createRoot(...): Target container is not a DOM element.', - ); - warnIfReactDOMContainerInDEV(container); - return new ReactDOMBlockingRoot(container, BlockingRoot, options); -} - export function createLegacyRoot( container: Container, options?: RootOptions, ): RootType { - return new ReactDOMBlockingRoot(container, LegacyRoot, options); + return new ReactDOMLegacyRoot(container, options); } export function isValidContainer(node: mixed): boolean { diff --git a/packages/react-noop-renderer/src/ReactNoop.js b/packages/react-noop-renderer/src/ReactNoop.js index 8305dd6d8641f..c09fa2d8000f5 100644 --- a/packages/react-noop-renderer/src/ReactNoop.js +++ b/packages/react-noop-renderer/src/ReactNoop.js @@ -23,7 +23,6 @@ export const { getPendingChildren, getOrCreateRootContainer, createRoot, - createBlockingRoot, createLegacyRoot, getChildrenAsJSX, getPendingChildrenAsJSX, diff --git a/packages/react-noop-renderer/src/ReactNoopPersistent.js b/packages/react-noop-renderer/src/ReactNoopPersistent.js index c4a73cdfb81b4..97876990a9b57 100644 --- a/packages/react-noop-renderer/src/ReactNoopPersistent.js +++ b/packages/react-noop-renderer/src/ReactNoopPersistent.js @@ -23,7 +23,6 @@ export const { getPendingChildren, getOrCreateRootContainer, createRoot, - createBlockingRoot, createLegacyRoot, getChildrenAsJSX, getPendingChildrenAsJSX, diff --git a/packages/react-noop-renderer/src/createReactNoop.js b/packages/react-noop-renderer/src/createReactNoop.js index f7663b0593583..80c888a88e53d 100644 --- a/packages/react-noop-renderer/src/createReactNoop.js +++ b/packages/react-noop-renderer/src/createReactNoop.js @@ -21,11 +21,7 @@ import type {RootTag} from 'react-reconciler/src/ReactRootTags'; import * as Scheduler from 'scheduler/unstable_mock'; import {REACT_FRAGMENT_TYPE, REACT_ELEMENT_TYPE} from 'shared/ReactSymbols'; -import { - ConcurrentRoot, - BlockingRoot, - LegacyRoot, -} from 'react-reconciler/src/ReactRootTags'; +import {ConcurrentRoot, LegacyRoot} from 'react-reconciler/src/ReactRootTags'; import ReactSharedInternals from 'shared/ReactSharedInternals'; import enqueueTask from 'shared/enqueueTask'; @@ -752,33 +748,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { }; }, - createBlockingRoot() { - const container = { - rootID: '' + idCounter++, - pendingChildren: [], - children: [], - }; - const fiberRoot = NoopRenderer.createContainer( - container, - BlockingRoot, - false, - null, - null, - ); - return { - _Scheduler: Scheduler, - render(children: ReactNodeList) { - NoopRenderer.updateContainer(children, fiberRoot, null, null); - }, - getChildren() { - return getChildren(container); - }, - getChildrenAsJSX() { - return getChildrenAsJSX(container); - }, - }; - }, - createLegacyRoot() { const container = { rootID: '' + idCounter++, diff --git a/packages/react-reconciler/src/ReactFiber.new.js b/packages/react-reconciler/src/ReactFiber.new.js index 3c49e56431c39..de9c83e3a35dd 100644 --- a/packages/react-reconciler/src/ReactFiber.new.js +++ b/packages/react-reconciler/src/ReactFiber.new.js @@ -26,7 +26,7 @@ import { enableScopeAPI, } from 'shared/ReactFeatureFlags'; import {NoFlags, Placement, StaticMask} from './ReactFiberFlags'; -import {ConcurrentRoot, BlockingRoot} from './ReactRootTags'; +import {ConcurrentRoot} from './ReactRootTags'; import { IndeterminateComponent, ClassComponent, @@ -68,7 +68,6 @@ import { ProfileMode, StrictLegacyMode, StrictEffectsMode, - BlockingMode, } from './ReactTypeOfMode'; import { REACT_FORWARD_REF_TYPE, @@ -424,25 +423,7 @@ export function createHostRootFiber( ): Fiber { let mode; if (tag === ConcurrentRoot) { - mode = ConcurrentMode | BlockingMode; - if (strictModeLevelOverride !== null) { - if (strictModeLevelOverride >= 1) { - mode |= StrictLegacyMode; - } - if (enableStrictEffects) { - if (strictModeLevelOverride >= 2) { - mode |= StrictEffectsMode; - } - } - } else { - if (enableStrictEffects && createRootStrictEffectsByDefault) { - mode |= StrictLegacyMode | StrictEffectsMode; - } else { - mode |= StrictLegacyMode; - } - } - } else if (tag === BlockingRoot) { - mode = BlockingMode; + mode = ConcurrentMode; if (strictModeLevelOverride !== null) { if (strictModeLevelOverride >= 1) { mode |= StrictLegacyMode; diff --git a/packages/react-reconciler/src/ReactFiber.old.js b/packages/react-reconciler/src/ReactFiber.old.js index e98634b37cfd6..f399ab3593146 100644 --- a/packages/react-reconciler/src/ReactFiber.old.js +++ b/packages/react-reconciler/src/ReactFiber.old.js @@ -26,7 +26,7 @@ import { enableScopeAPI, } from 'shared/ReactFeatureFlags'; import {NoFlags, Placement, StaticMask} from './ReactFiberFlags'; -import {ConcurrentRoot, BlockingRoot} from './ReactRootTags'; +import {ConcurrentRoot} from './ReactRootTags'; import { IndeterminateComponent, ClassComponent, @@ -68,7 +68,6 @@ import { ProfileMode, StrictLegacyMode, StrictEffectsMode, - BlockingMode, } from './ReactTypeOfMode'; import { REACT_FORWARD_REF_TYPE, @@ -424,25 +423,7 @@ export function createHostRootFiber( ): Fiber { let mode; if (tag === ConcurrentRoot) { - mode = ConcurrentMode | BlockingMode; - if (strictModeLevelOverride !== null) { - if (strictModeLevelOverride >= 1) { - mode |= StrictLegacyMode; - } - if (enableStrictEffects) { - if (strictModeLevelOverride >= 2) { - mode |= StrictEffectsMode; - } - } - } else { - if (enableStrictEffects && createRootStrictEffectsByDefault) { - mode |= StrictLegacyMode | StrictEffectsMode; - } else { - mode |= StrictLegacyMode; - } - } - } else if (tag === BlockingRoot) { - mode = BlockingMode; + mode = ConcurrentMode; if (strictModeLevelOverride !== null) { if (strictModeLevelOverride >= 1) { mode |= StrictLegacyMode; diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js index 345f668fc62e8..a014ef5747895 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js @@ -128,7 +128,6 @@ import { NoMode, ProfileMode, StrictLegacyMode, - BlockingMode, } from './ReactTypeOfMode'; import { shouldSetTextContent, @@ -609,7 +608,6 @@ function updateOffscreenComponent( // Rendering a hidden tree. if ((workInProgress.mode & ConcurrentMode) === NoMode) { // In legacy sync mode, don't defer the subtree. Render it now. - // TODO: Figure out what we should do in Blocking mode. const nextState: OffscreenState = { baseLanes: NoLanes, cachePool: null, @@ -2134,7 +2132,10 @@ function mountSuspenseFallbackChildren( let primaryChildFragment; let fallbackChildFragment; - if ((mode & BlockingMode) === NoMode && progressedPrimaryFragment !== null) { + if ( + (mode & ConcurrentMode) === NoMode && + progressedPrimaryFragment !== null + ) { // In legacy mode, we commit the primary tree as if it successfully // completed, even though it's in an inconsistent state. primaryChildFragment = progressedPrimaryFragment; @@ -2206,7 +2207,7 @@ function updateSuspensePrimaryChildren( children: primaryChildren, }, ); - if ((workInProgress.mode & BlockingMode) === NoMode) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { primaryChildFragment.lanes = renderLanes; } primaryChildFragment.return = workInProgress; @@ -2247,7 +2248,7 @@ function updateSuspenseFallbackChildren( if ( // In legacy mode, we commit the primary tree as if it successfully // completed, even though it's in an inconsistent state. - (mode & BlockingMode) === NoMode && + (mode & ConcurrentMode) === NoMode && // Make sure we're on the second pass, i.e. the primary child fragment was // already cloned. In legacy mode, the only case where this isn't true is // when DevTools forces us to display a fallback; we skip the first render @@ -2369,7 +2370,7 @@ function mountSuspenseFallbackAfterRetryWithoutHydrating( primaryChildFragment.sibling = fallbackChildFragment; workInProgress.child = primaryChildFragment; - if ((workInProgress.mode & BlockingMode) !== NoMode) { + if ((workInProgress.mode & ConcurrentMode) !== NoMode) { // We will have dropped the effect list which contains the // deletion. We need to reconcile to delete the current child. reconcileChildFibers(workInProgress, current.child, null, renderLanes); @@ -2385,12 +2386,12 @@ function mountDehydratedSuspenseComponent( ): null | Fiber { // During the first pass, we'll bail out and not drill into the children. // Instead, we'll leave the content in place and try to hydrate it later. - if ((workInProgress.mode & BlockingMode) === NoMode) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { if (__DEV__) { console.error( 'Cannot hydrate Suspense in legacy mode. Switch from ' + 'ReactDOM.hydrate(element, container) to ' + - 'ReactDOM.createBlockingRoot(container, { hydrate: true })' + + 'ReactDOM.createRoot(container, { hydrate: true })' + '.render(element) or remove the Suspense components from ' + 'the server rendered components.', ); @@ -2443,7 +2444,7 @@ function updateDehydratedSuspenseComponent( ); } - if ((workInProgress.mode & BlockingMode) === NoMode) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { return retrySuspenseComponentWithoutHydrating( current, workInProgress, @@ -2861,7 +2862,7 @@ function updateSuspenseListComponent( } pushSuspenseContext(workInProgress, suspenseContext); - if ((workInProgress.mode & BlockingMode) === NoMode) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { // In legacy mode, SuspenseList doesn't work so we just // use make it a noop by treating it as the default revealOrder. workInProgress.memoizedState = null; diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js index 72b4e33431b00..2c355abdf95b2 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js @@ -128,7 +128,6 @@ import { NoMode, ProfileMode, StrictLegacyMode, - BlockingMode, } from './ReactTypeOfMode'; import { shouldSetTextContent, @@ -609,7 +608,6 @@ function updateOffscreenComponent( // Rendering a hidden tree. if ((workInProgress.mode & ConcurrentMode) === NoMode) { // In legacy sync mode, don't defer the subtree. Render it now. - // TODO: Figure out what we should do in Blocking mode. const nextState: OffscreenState = { baseLanes: NoLanes, cachePool: null, @@ -2134,7 +2132,10 @@ function mountSuspenseFallbackChildren( let primaryChildFragment; let fallbackChildFragment; - if ((mode & BlockingMode) === NoMode && progressedPrimaryFragment !== null) { + if ( + (mode & ConcurrentMode) === NoMode && + progressedPrimaryFragment !== null + ) { // In legacy mode, we commit the primary tree as if it successfully // completed, even though it's in an inconsistent state. primaryChildFragment = progressedPrimaryFragment; @@ -2206,7 +2207,7 @@ function updateSuspensePrimaryChildren( children: primaryChildren, }, ); - if ((workInProgress.mode & BlockingMode) === NoMode) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { primaryChildFragment.lanes = renderLanes; } primaryChildFragment.return = workInProgress; @@ -2247,7 +2248,7 @@ function updateSuspenseFallbackChildren( if ( // In legacy mode, we commit the primary tree as if it successfully // completed, even though it's in an inconsistent state. - (mode & BlockingMode) === NoMode && + (mode & ConcurrentMode) === NoMode && // Make sure we're on the second pass, i.e. the primary child fragment was // already cloned. In legacy mode, the only case where this isn't true is // when DevTools forces us to display a fallback; we skip the first render @@ -2369,7 +2370,7 @@ function mountSuspenseFallbackAfterRetryWithoutHydrating( primaryChildFragment.sibling = fallbackChildFragment; workInProgress.child = primaryChildFragment; - if ((workInProgress.mode & BlockingMode) !== NoMode) { + if ((workInProgress.mode & ConcurrentMode) !== NoMode) { // We will have dropped the effect list which contains the // deletion. We need to reconcile to delete the current child. reconcileChildFibers(workInProgress, current.child, null, renderLanes); @@ -2385,12 +2386,12 @@ function mountDehydratedSuspenseComponent( ): null | Fiber { // During the first pass, we'll bail out and not drill into the children. // Instead, we'll leave the content in place and try to hydrate it later. - if ((workInProgress.mode & BlockingMode) === NoMode) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { if (__DEV__) { console.error( 'Cannot hydrate Suspense in legacy mode. Switch from ' + 'ReactDOM.hydrate(element, container) to ' + - 'ReactDOM.createBlockingRoot(container, { hydrate: true })' + + 'ReactDOM.createRoot(container, { hydrate: true })' + '.render(element) or remove the Suspense components from ' + 'the server rendered components.', ); @@ -2443,7 +2444,7 @@ function updateDehydratedSuspenseComponent( ); } - if ((workInProgress.mode & BlockingMode) === NoMode) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { return retrySuspenseComponentWithoutHydrating( current, workInProgress, @@ -2861,7 +2862,7 @@ function updateSuspenseListComponent( } pushSuspenseContext(workInProgress, suspenseContext); - if ((workInProgress.mode & BlockingMode) === NoMode) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { // In legacy mode, SuspenseList doesn't work so we just // use make it a noop by treating it as the default revealOrder. workInProgress.memoizedState = null; diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js index 47f65d2da6efc..1dcc0ec9c87d1 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js @@ -55,12 +55,7 @@ import { LegacyHiddenComponent, CacheComponent, } from './ReactWorkTags'; -import { - NoMode, - BlockingMode, - ConcurrentMode, - ProfileMode, -} from './ReactTypeOfMode'; +import {NoMode, ConcurrentMode, ProfileMode} from './ReactTypeOfMode'; import { Ref, Update, @@ -1059,12 +1054,10 @@ function completeWork( } if (nextDidTimeout && !prevDidTimeout) { - // If this subtree is running in blocking mode we can suspend, - // otherwise we won't suspend. // TODO: This will still suspend a synchronous tree if anything // in the concurrent tree already suspended during this render. // This is a known bug. - if ((workInProgress.mode & BlockingMode) !== NoMode) { + if ((workInProgress.mode & ConcurrentMode) !== NoMode) { // TODO: Move this back to throwException because this is too late // if this is a large tree which is common for initial loads. We // don't know if we should restart a render or not until we get diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js index df878d24e76a5..dc1112d3b88f6 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js @@ -55,12 +55,7 @@ import { LegacyHiddenComponent, CacheComponent, } from './ReactWorkTags'; -import { - NoMode, - BlockingMode, - ConcurrentMode, - ProfileMode, -} from './ReactTypeOfMode'; +import {NoMode, ConcurrentMode, ProfileMode} from './ReactTypeOfMode'; import { Ref, Update, @@ -1059,12 +1054,10 @@ function completeWork( } if (nextDidTimeout && !prevDidTimeout) { - // If this subtree is running in blocking mode we can suspend, - // otherwise we won't suspend. // TODO: This will still suspend a synchronous tree if anything // in the concurrent tree already suspended during this render. // This is a known bug. - if ((workInProgress.mode & BlockingMode) !== NoMode) { + if ((workInProgress.mode & ConcurrentMode) !== NoMode) { // TODO: Move this back to throwException because this is too late // if this is a large tree which is common for initial loads. We // don't know if we should restart a render or not until we get diff --git a/packages/react-reconciler/src/ReactFiberHooks.new.js b/packages/react-reconciler/src/ReactFiberHooks.new.js index 9eb089d07d7a5..00afb7daefdd7 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.new.js +++ b/packages/react-reconciler/src/ReactFiberHooks.new.js @@ -34,7 +34,7 @@ import { import { NoMode, - BlockingMode, + ConcurrentMode, DebugTracingMode, StrictEffectsMode, } from './ReactTypeOfMode'; @@ -1809,7 +1809,7 @@ function mountOpaqueIdentifier(): OpaqueIDType | void { const setId = mountState(id)[1]; - if ((currentlyRenderingFiber.mode & BlockingMode) === NoMode) { + if ((currentlyRenderingFiber.mode & ConcurrentMode) === NoMode) { if ( __DEV__ && enableStrictEffects && diff --git a/packages/react-reconciler/src/ReactFiberHooks.old.js b/packages/react-reconciler/src/ReactFiberHooks.old.js index b51d2020a8fad..3f60972dcd519 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.old.js +++ b/packages/react-reconciler/src/ReactFiberHooks.old.js @@ -34,7 +34,7 @@ import { import { NoMode, - BlockingMode, + ConcurrentMode, DebugTracingMode, StrictEffectsMode, } from './ReactTypeOfMode'; @@ -1809,7 +1809,7 @@ function mountOpaqueIdentifier(): OpaqueIDType | void { const setId = mountState(id)[1]; - if ((currentlyRenderingFiber.mode & BlockingMode) === NoMode) { + if ((currentlyRenderingFiber.mode & ConcurrentMode) === NoMode) { if ( __DEV__ && enableStrictEffects && diff --git a/packages/react-reconciler/src/ReactFiberRoot.new.js b/packages/react-reconciler/src/ReactFiberRoot.new.js index ae6a5bdb596f6..f06925e10fbe9 100644 --- a/packages/react-reconciler/src/ReactFiberRoot.new.js +++ b/packages/react-reconciler/src/ReactFiberRoot.new.js @@ -25,7 +25,7 @@ import { } from 'shared/ReactFeatureFlags'; import {unstable_getThreadID} from 'scheduler/tracing'; import {initializeUpdateQueue} from './ReactUpdateQueue.new'; -import {LegacyRoot, BlockingRoot, ConcurrentRoot} from './ReactRootTags'; +import {LegacyRoot, ConcurrentRoot} from './ReactRootTags'; function FiberRootNode(containerInfo, tag, hydrate) { this.tag = tag; @@ -73,9 +73,6 @@ function FiberRootNode(containerInfo, tag, hydrate) { if (__DEV__) { switch (tag) { - case BlockingRoot: - this._debugRootType = 'createBlockingRoot()'; - break; case ConcurrentRoot: this._debugRootType = 'createRoot()'; break; diff --git a/packages/react-reconciler/src/ReactFiberRoot.old.js b/packages/react-reconciler/src/ReactFiberRoot.old.js index 0c0d45c098720..712803920ebb2 100644 --- a/packages/react-reconciler/src/ReactFiberRoot.old.js +++ b/packages/react-reconciler/src/ReactFiberRoot.old.js @@ -25,7 +25,7 @@ import { } from 'shared/ReactFeatureFlags'; import {unstable_getThreadID} from 'scheduler/tracing'; import {initializeUpdateQueue} from './ReactUpdateQueue.old'; -import {LegacyRoot, BlockingRoot, ConcurrentRoot} from './ReactRootTags'; +import {LegacyRoot, ConcurrentRoot} from './ReactRootTags'; function FiberRootNode(containerInfo, tag, hydrate) { this.tag = tag; @@ -73,9 +73,6 @@ function FiberRootNode(containerInfo, tag, hydrate) { if (__DEV__) { switch (tag) { - case BlockingRoot: - this._debugRootType = 'createBlockingRoot()'; - break; case ConcurrentRoot: this._debugRootType = 'createRoot()'; break; diff --git a/packages/react-reconciler/src/ReactFiberThrow.new.js b/packages/react-reconciler/src/ReactFiberThrow.new.js index ba5a81ecccbf2..2641bdd3b345e 100644 --- a/packages/react-reconciler/src/ReactFiberThrow.new.js +++ b/packages/react-reconciler/src/ReactFiberThrow.new.js @@ -34,7 +34,7 @@ import { ForceUpdateForLegacySuspense, } from './ReactFiberFlags'; import {shouldCaptureSuspense} from './ReactFiberSuspenseComponent.new'; -import {NoMode, BlockingMode, DebugTracingMode} from './ReactTypeOfMode'; +import {NoMode, ConcurrentMode, DebugTracingMode} from './ReactTypeOfMode'; import { enableDebugTracing, enableSchedulingProfiler, @@ -233,7 +233,7 @@ function throwException( // A legacy mode Suspense quirk, only relevant to hook components. const tag = sourceFiber.tag; if ( - (sourceFiber.mode & BlockingMode) === NoMode && + (sourceFiber.mode & ConcurrentMode) === NoMode && (tag === FunctionComponent || tag === ForwardRef || tag === SimpleMemoComponent) @@ -274,13 +274,13 @@ function throwException( wakeables.add(wakeable); } - // If the boundary is outside of blocking mode, we should *not* + // If the boundary is in legacy mode, we should *not* // suspend the commit. Pretend as if the suspended component rendered // null and keep rendering. In the commit phase, we'll schedule a // subsequent synchronous update to re-render the Suspense. // // Note: It doesn't matter whether the component that suspended was - // inside a blocking mode tree. If the Suspense is outside of it, we + // inside a concurrent mode tree. If the Suspense is outside of it, we // should *not* suspend the commit. // // If the suspense boundary suspended itself suspended, we don't have to @@ -288,7 +288,7 @@ function throwException( // directly do a second pass over the fallback in this render and // pretend we meant to render that directly. if ( - (workInProgress.mode & BlockingMode) === NoMode && + (workInProgress.mode & ConcurrentMode) === NoMode && workInProgress !== returnFiber ) { workInProgress.flags |= DidCapture; diff --git a/packages/react-reconciler/src/ReactFiberThrow.old.js b/packages/react-reconciler/src/ReactFiberThrow.old.js index baa807e180dd0..294b807ebcb1b 100644 --- a/packages/react-reconciler/src/ReactFiberThrow.old.js +++ b/packages/react-reconciler/src/ReactFiberThrow.old.js @@ -34,7 +34,7 @@ import { ForceUpdateForLegacySuspense, } from './ReactFiberFlags'; import {shouldCaptureSuspense} from './ReactFiberSuspenseComponent.old'; -import {NoMode, BlockingMode, DebugTracingMode} from './ReactTypeOfMode'; +import {NoMode, ConcurrentMode, DebugTracingMode} from './ReactTypeOfMode'; import { enableDebugTracing, enableSchedulingProfiler, @@ -233,7 +233,7 @@ function throwException( // A legacy mode Suspense quirk, only relevant to hook components. const tag = sourceFiber.tag; if ( - (sourceFiber.mode & BlockingMode) === NoMode && + (sourceFiber.mode & ConcurrentMode) === NoMode && (tag === FunctionComponent || tag === ForwardRef || tag === SimpleMemoComponent) @@ -274,13 +274,13 @@ function throwException( wakeables.add(wakeable); } - // If the boundary is outside of blocking mode, we should *not* + // If the boundary is in legacy mode, we should *not* // suspend the commit. Pretend as if the suspended component rendered // null and keep rendering. In the commit phase, we'll schedule a // subsequent synchronous update to re-render the Suspense. // // Note: It doesn't matter whether the component that suspended was - // inside a blocking mode tree. If the Suspense is outside of it, we + // inside a concurrent mode tree. If the Suspense is outside of it, we // should *not* suspend the commit. // // If the suspense boundary suspended itself suspended, we don't have to @@ -288,7 +288,7 @@ function throwException( // directly do a second pass over the fallback in this render and // pretend we meant to render that directly. if ( - (workInProgress.mode & BlockingMode) === NoMode && + (workInProgress.mode & ConcurrentMode) === NoMode && workInProgress !== returnFiber ) { workInProgress.flags |= DidCapture; diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js index 8f83cf88fea9b..5bd865cc4d159 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js @@ -100,7 +100,6 @@ import { NoMode, StrictLegacyMode, ProfileMode, - BlockingMode, ConcurrentMode, } from './ReactTypeOfMode'; import { @@ -386,7 +385,7 @@ export function getCurrentTime() { export function requestUpdateLane(fiber: Fiber): Lane { // Special cases const mode = fiber.mode; - if ((mode & BlockingMode) === NoMode) { + if ((mode & ConcurrentMode) === NoMode) { return (SyncLane: Lane); } else if ((mode & ConcurrentMode) === NoMode) { return getCurrentUpdateLanePriority() === SyncLanePriority @@ -467,7 +466,7 @@ function requestRetryLane(fiber: Fiber) { // Special cases const mode = fiber.mode; - if ((mode & BlockingMode) === NoMode) { + if ((mode & ConcurrentMode) === NoMode) { return (SyncLane: Lane); } else if ((mode & ConcurrentMode) === NoMode) { return getCurrentUpdateLanePriority() === SyncLanePriority @@ -658,7 +657,7 @@ export function isInterleavedUpdate(fiber: Fiber, lane: Lane) { // Requires some refactoring. Not a big deal though since it's rare for // concurrent apps to have more than a single root. workInProgressRoot !== null && - (fiber.mode & BlockingMode) !== NoMode && + (fiber.mode & ConcurrentMode) !== NoMode && // If this is a render phase update (i.e. UNSAFE_componentWillReceiveProps), // then don't treat this as an interleaved update. This pattern is // accompanied by a warning but we haven't fully deprecated it yet. We can @@ -2545,7 +2544,7 @@ function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { return; } - if (!(fiber.mode & (BlockingMode | ConcurrentMode))) { + if (!(fiber.mode & ConcurrentMode)) { return; } @@ -2924,7 +2923,7 @@ export function warnIfUnmockedScheduler(fiber: Fiber) { didWarnAboutUnmockedScheduler === false && Scheduler.unstable_flushAllWithoutAsserting === undefined ) { - if (fiber.mode & BlockingMode || fiber.mode & ConcurrentMode) { + if (fiber.mode & ConcurrentMode) { didWarnAboutUnmockedScheduler = true; console.error( 'In Concurrent or Sync modes, the "scheduler" module needs to be mocked ' + diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js index 4b59de6b0d5d6..fef8f4e56d697 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js @@ -100,7 +100,6 @@ import { NoMode, StrictLegacyMode, ProfileMode, - BlockingMode, ConcurrentMode, } from './ReactTypeOfMode'; import { @@ -386,7 +385,7 @@ export function getCurrentTime() { export function requestUpdateLane(fiber: Fiber): Lane { // Special cases const mode = fiber.mode; - if ((mode & BlockingMode) === NoMode) { + if ((mode & ConcurrentMode) === NoMode) { return (SyncLane: Lane); } else if ((mode & ConcurrentMode) === NoMode) { return getCurrentUpdateLanePriority() === SyncLanePriority @@ -467,7 +466,7 @@ function requestRetryLane(fiber: Fiber) { // Special cases const mode = fiber.mode; - if ((mode & BlockingMode) === NoMode) { + if ((mode & ConcurrentMode) === NoMode) { return (SyncLane: Lane); } else if ((mode & ConcurrentMode) === NoMode) { return getCurrentUpdateLanePriority() === SyncLanePriority @@ -658,7 +657,7 @@ export function isInterleavedUpdate(fiber: Fiber, lane: Lane) { // Requires some refactoring. Not a big deal though since it's rare for // concurrent apps to have more than a single root. workInProgressRoot !== null && - (fiber.mode & BlockingMode) !== NoMode && + (fiber.mode & ConcurrentMode) !== NoMode && // If this is a render phase update (i.e. UNSAFE_componentWillReceiveProps), // then don't treat this as an interleaved update. This pattern is // accompanied by a warning but we haven't fully deprecated it yet. We can @@ -2545,7 +2544,7 @@ function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { return; } - if (!(fiber.mode & (BlockingMode | ConcurrentMode))) { + if (!(fiber.mode & ConcurrentMode)) { return; } @@ -2924,7 +2923,7 @@ export function warnIfUnmockedScheduler(fiber: Fiber) { didWarnAboutUnmockedScheduler === false && Scheduler.unstable_flushAllWithoutAsserting === undefined ) { - if (fiber.mode & BlockingMode || fiber.mode & ConcurrentMode) { + if (fiber.mode & ConcurrentMode) { didWarnAboutUnmockedScheduler = true; console.error( 'In Concurrent or Sync modes, the "scheduler" module needs to be mocked ' + diff --git a/packages/react-reconciler/src/ReactRootTags.js b/packages/react-reconciler/src/ReactRootTags.js index 409f4bd931a76..cda44d6e1ed51 100644 --- a/packages/react-reconciler/src/ReactRootTags.js +++ b/packages/react-reconciler/src/ReactRootTags.js @@ -7,8 +7,7 @@ * @flow */ -export type RootTag = 0 | 1 | 2; +export type RootTag = 0 | 1; export const LegacyRoot = 0; -export const BlockingRoot = 1; -export const ConcurrentRoot = 2; +export const ConcurrentRoot = 1; diff --git a/packages/react-reconciler/src/ReactTypeOfMode.js b/packages/react-reconciler/src/ReactTypeOfMode.js index a6499be7aca11..466363fabd4e8 100644 --- a/packages/react-reconciler/src/ReactTypeOfMode.js +++ b/packages/react-reconciler/src/ReactTypeOfMode.js @@ -10,10 +10,9 @@ export type TypeOfMode = number; export const NoMode = /* */ 0b000000; -// TODO: Remove BlockingMode and ConcurrentMode by reading from the root tag instead -export const BlockingMode = /* */ 0b000001; -export const ConcurrentMode = /* */ 0b000010; -export const ProfileMode = /* */ 0b000100; -export const DebugTracingMode = /* */ 0b001000; -export const StrictLegacyMode = /* */ 0b010000; -export const StrictEffectsMode = /* */ 0b100000; +// TODO: Remove ConcurrentMode by reading from the root tag instead +export const ConcurrentMode = /* */ 0b000001; +export const ProfileMode = /* */ 0b000010; +export const DebugTracingMode = /* */ 0b000100; +export const StrictLegacyMode = /* */ 0b001000; +export const StrictEffectsMode = /* */ 0b010000; diff --git a/packages/react-reconciler/src/__tests__/ReactBatchedMode-test.internal.js b/packages/react-reconciler/src/__tests__/ReactBatching-test.internal.js similarity index 86% rename from packages/react-reconciler/src/__tests__/ReactBatchedMode-test.internal.js rename to packages/react-reconciler/src/__tests__/ReactBatching-test.internal.js index c6af59fbd915c..7998d2a23177e 100644 --- a/packages/react-reconciler/src/__tests__/ReactBatchedMode-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactBatching-test.internal.js @@ -53,7 +53,7 @@ describe('ReactBlockingMode', () => { } it('updates flush without yielding in the next event', () => { - const root = ReactNoop.createBlockingRoot(); + const root = ReactNoop.createRoot(); root.render( <> @@ -67,7 +67,7 @@ describe('ReactBlockingMode', () => { expect(root).toMatchRenderedOutput(null); // Everything should render immediately in the next event - expect(Scheduler).toFlushExpired(['A', 'B', 'C']); + expect(Scheduler).toFlushAndYield(['A', 'B', 'C']); expect(root).toMatchRenderedOutput('ABC'); }); @@ -81,16 +81,17 @@ describe('ReactBlockingMode', () => { return ; } - const root = ReactNoop.createBlockingRoot(); + const root = ReactNoop.createRoot(); root.render(); expect(root).toMatchRenderedOutput(null); + expect(Scheduler).toHaveYielded([]); - expect(Scheduler).toFlushExpired(['Hi', 'Layout effect']); + expect(Scheduler).toFlushAndYield(['Hi', 'Layout effect']); expect(root).toMatchRenderedOutput('Hi'); }); it('uses proper Suspense semantics, not legacy ones', async () => { - const root = ReactNoop.createBlockingRoot(); + const root = ReactNoop.createRoot(); root.render( }> @@ -105,15 +106,15 @@ describe('ReactBlockingMode', () => { , ); - expect(Scheduler).toFlushExpired(['A', 'Suspend! [B]', 'C', 'Loading...']); - // In Legacy Mode, A and B would mount in a hidden primary tree. In Batched - // and Concurrent Mode, nothing in the primary tree should mount. But the + expect(Scheduler).toFlushAndYield(['A', 'Suspend! [B]', 'C', 'Loading...']); + // In Legacy Mode, A and B would mount in a hidden primary tree. In + // Concurrent Mode, nothing in the primary tree should mount. But the // fallback should mount immediately. expect(root).toMatchRenderedOutput('Loading...'); await jest.advanceTimersByTime(1000); expect(Scheduler).toHaveYielded(['Promise resolved [B]']); - expect(Scheduler).toFlushExpired(['A', 'B', 'C']); + expect(Scheduler).toFlushAndYield(['A', 'B', 'C']); expect(root).toMatchRenderedOutput( <> A @@ -125,7 +126,7 @@ describe('ReactBlockingMode', () => { it('flushSync does not flush batched work', () => { const {useState, forwardRef, useImperativeHandle} = React; - const root = ReactNoop.createBlockingRoot(); + const root = ReactNoop.createRoot(); const Foo = forwardRef(({label}, ref) => { const [step, setStep] = useState(0); @@ -143,7 +144,7 @@ describe('ReactBlockingMode', () => { ); // Mount - expect(Scheduler).toFlushExpired(['A0', 'B0']); + expect(Scheduler).toFlushAndYield(['A0', 'B0']); expect(root).toMatchRenderedOutput('A0B0'); // Schedule a batched update to the first sibling @@ -161,7 +162,7 @@ describe('ReactBlockingMode', () => { expect(root).toMatchRenderedOutput('A0B1'); // Now flush the first update - expect(Scheduler).toFlushExpired(['A1']); + expect(Scheduler).toFlushAndYield(['A1']); expect(root).toMatchRenderedOutput('A1B1'); }); }); diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js index 613fe89d63279..a14c36bfce2bb 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js @@ -1870,10 +1870,6 @@ describe('ReactIncrementalErrorHandling', () => { const root = ReactNoop.createRoot(); root.render('Error when completing root'); expect(Scheduler).toFlushAndThrow('Error when completing root'); - - const blockingRoot = ReactNoop.createBlockingRoot(); - blockingRoot.render('Error when completing root'); - expect(Scheduler).toFlushAndThrow('Error when completing root'); }); } }); diff --git a/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js b/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js index b3f14e6ad1efc..d04203089c22b 100644 --- a/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js +++ b/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js @@ -125,7 +125,7 @@ describe('ReactOffscreen', () => { }); // @gate experimental - it('does not defer in blocking mode', async () => { + it('does defer in concurrent mode', async () => { let setState; function Foo() { const [state, _setState] = useState('A'); @@ -133,7 +133,7 @@ describe('ReactOffscreen', () => { return ; } - const root = ReactNoop.createBlockingRoot(); + const root = ReactNoop.createRoot(); await ReactNoop.act(async () => { root.render( <> @@ -143,9 +143,13 @@ describe('ReactOffscreen', () => { , ); - // Should not defer the hidden tree - expect(Scheduler).toFlushUntilNextPaint(['A', 'Outside']); + // Should defer the hidden tree. + expect(Scheduler).toFlushUntilNextPaint(['Outside']); }); + + // The hidden tree was rendered at lower priority. + expect(Scheduler).toHaveYielded(['A']); + expect(root).toMatchRenderedOutput( <> diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseFuzz-test.internal.js b/packages/react-reconciler/src/__tests__/ReactSuspenseFuzz-test.internal.js index eabcb41be0e6d..c67edf8a15632 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseFuzz-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseFuzz-test.internal.js @@ -170,13 +170,6 @@ describe('ReactSuspenseFuzz', () => { expect(legacyOutput).toEqual(expectedOutput); ReactNoop.renderLegacySyncRoot(null); - resetCache(); - const batchedBlockingRoot = ReactNoop.createBlockingRoot(); - batchedBlockingRoot.render(children); - resolveAllTasks(); - const batchedSyncOutput = batchedBlockingRoot.getChildrenAsJSX(); - expect(batchedSyncOutput).toEqual(expectedOutput); - resetCache(); const concurrentRoot = ReactNoop.createRoot(); concurrentRoot.render(children); diff --git a/packages/react/src/__tests__/ReactStrictMode-test.internal.js b/packages/react/src/__tests__/ReactStrictMode-test.internal.js index cb567340d3983..20c83a46dfaac 100644 --- a/packages/react/src/__tests__/ReactStrictMode-test.internal.js +++ b/packages/react/src/__tests__/ReactStrictMode-test.internal.js @@ -66,23 +66,6 @@ describe('ReactStrictMode', () => { ]); }); - // @gate experimental - it('should support overriding default via createBlockingRoot option', () => { - act(() => { - const container = document.createElement('div'); - const root = ReactDOM.createBlockingRoot(container, { - unstable_strictModeLevel: 0, - }); - root.render(); - }); - - expect(log).toEqual([ - 'A: render', - 'A: useLayoutEffect mount', - 'A: useEffect mount', - ]); - }); - // @gate experimental it('should disable strict mode if level 0 is specified', () => { act(() => { diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index 5029a6f4900bf..75ab4b6842d90 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -27,7 +27,7 @@ export const debugRenderPhaseSideEffectsForStrictMode = __DEV__; // this feature flag only impacts StrictEffectsMode. export const enableStrictEffects = false; -// If TRUE, trees rendered with createRoot (and createBlockingRoot) APIs will be StrictEffectsMode. +// If TRUE, trees rendered with createRoot will be StrictEffectsMode. // If FALSE, these trees will be StrictLegacyMode. export const createRootStrictEffectsByDefault = false;