From 72a933d2892dac9e5327678b6bd37af8d589bb22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= Date: Wed, 9 Mar 2022 11:48:03 -0500 Subject: [PATCH] Gate legacy hidden (#24047) * Gate legacy hidden * Gate tests * Remove export from experimental --- ...DOMServerPartialHydration-test.internal.js | 4 +- .../src/__tests__/ReactUpdates-test.js | 2 +- .../react-reconciler/src/ReactFiber.new.js | 6 +- .../react-reconciler/src/ReactFiber.old.js | 6 +- .../src/ReactFiberBeginWork.new.js | 14 +- .../src/ReactFiberBeginWork.old.js | 14 +- .../src/ReactFiberCompleteWork.new.js | 10 +- .../src/ReactFiberCompleteWork.old.js | 10 +- .../__tests__/ReactContextPropagation-test.js | 6 +- .../src/__tests__/ReactIncremental-test.js | 6 +- ...tIncrementalErrorHandling-test.internal.js | 2 +- .../ReactIncrementalSideEffects-test.js | 10 +- .../src/__tests__/ReactNewContext-test.js | 2 +- .../src/__tests__/ReactOffscreen-test.js | 8 +- .../ReactSchedulerIntegration-test.js | 2 +- .../ReactSuspenseWithNoopRenderer-test.js | 4 +- .../src/getComponentNameFromFiber.js | 8 +- .../src/__tests__/ReactFresh-test.js | 181 +++++++++--------- packages/react/index.experimental.js | 1 - packages/shared/ReactFeatureFlags.js | 3 + .../forks/ReactFeatureFlags.native-fb.js | 1 + .../forks/ReactFeatureFlags.native-oss.js | 1 + .../forks/ReactFeatureFlags.test-renderer.js | 1 + .../ReactFeatureFlags.test-renderer.native.js | 1 + .../ReactFeatureFlags.test-renderer.www.js | 1 + .../shared/forks/ReactFeatureFlags.testing.js | 1 + .../forks/ReactFeatureFlags.testing.www.js | 1 + .../shared/forks/ReactFeatureFlags.www.js | 2 + packages/shared/isValidElementType.js | 3 +- 29 files changed, 175 insertions(+), 136 deletions(-) diff --git a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js index 7e25788c9232d..6d02211edffd0 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js @@ -3197,7 +3197,7 @@ describe('ReactDOMServerPartialHydration', () => { expect(span.innerHTML).toBe('Hidden child'); }); - // @gate experimental || www + // @gate www it('renders a hidden LegacyHidden component inside a Suspense boundary', async () => { const ref = React.createRef(); @@ -3225,7 +3225,7 @@ describe('ReactDOMServerPartialHydration', () => { expect(span.innerHTML).toBe('Hidden child'); }); - // @gate experimental || www + // @gate www it('renders a visible LegacyHidden component', async () => { const ref = React.createRef(); diff --git a/packages/react-dom/src/__tests__/ReactUpdates-test.js b/packages/react-dom/src/__tests__/ReactUpdates-test.js index 9e81a3b20ff1c..4fe596b9b7fb7 100644 --- a/packages/react-dom/src/__tests__/ReactUpdates-test.js +++ b/packages/react-dom/src/__tests__/ReactUpdates-test.js @@ -1302,7 +1302,7 @@ describe('ReactUpdates', () => { expect(ops).toEqual(['Foo', 'Bar', 'Baz']); }); - // @gate experimental || www + // @gate www it('delays sync updates inside hidden subtrees in Concurrent Mode', () => { const container = document.createElement('div'); diff --git a/packages/react-reconciler/src/ReactFiber.new.js b/packages/react-reconciler/src/ReactFiber.new.js index 977a3f67e03d2..1509d2201117d 100644 --- a/packages/react-reconciler/src/ReactFiber.new.js +++ b/packages/react-reconciler/src/ReactFiber.new.js @@ -23,6 +23,7 @@ import { enableStrictEffects, enableProfilerTimer, enableScopeAPI, + enableLegacyHidden, enableSyncDefaultUpdates, allowConcurrentByDefault, enableTransitionTracing, @@ -510,7 +511,10 @@ export function createFiberFromTypeAndProps( case REACT_OFFSCREEN_TYPE: return createFiberFromOffscreen(pendingProps, mode, lanes, key); case REACT_LEGACY_HIDDEN_TYPE: - return createFiberFromLegacyHidden(pendingProps, mode, lanes, key); + if (enableLegacyHidden) { + return createFiberFromLegacyHidden(pendingProps, mode, lanes, key); + } + // eslint-disable-next-line no-fallthrough case REACT_SCOPE_TYPE: if (enableScopeAPI) { return createFiberFromScope(type, pendingProps, mode, lanes, key); diff --git a/packages/react-reconciler/src/ReactFiber.old.js b/packages/react-reconciler/src/ReactFiber.old.js index 8999226fc22ef..ba9f5132b45ca 100644 --- a/packages/react-reconciler/src/ReactFiber.old.js +++ b/packages/react-reconciler/src/ReactFiber.old.js @@ -23,6 +23,7 @@ import { enableStrictEffects, enableProfilerTimer, enableScopeAPI, + enableLegacyHidden, enableSyncDefaultUpdates, allowConcurrentByDefault, enableTransitionTracing, @@ -510,7 +511,10 @@ export function createFiberFromTypeAndProps( case REACT_OFFSCREEN_TYPE: return createFiberFromOffscreen(pendingProps, mode, lanes, key); case REACT_LEGACY_HIDDEN_TYPE: - return createFiberFromLegacyHidden(pendingProps, mode, lanes, key); + if (enableLegacyHidden) { + return createFiberFromLegacyHidden(pendingProps, mode, lanes, key); + } + // eslint-disable-next-line no-fallthrough case REACT_SCOPE_TYPE: if (enableScopeAPI) { return createFiberFromScope(type, pendingProps, mode, lanes, key); diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js index 181d32febf917..4bae5d0b7b982 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js @@ -98,6 +98,7 @@ import { enableSchedulingProfiler, enablePersistentOffscreenHostContainer, enableTransitionTracing, + enableLegacyHidden, } from 'shared/ReactFeatureFlags'; import isArray from 'shared/isArray'; import shallowEqual from 'shared/shallowEqual'; @@ -640,7 +641,7 @@ function updateOffscreenComponent( if ( nextProps.mode === 'hidden' || - nextProps.mode === 'unstable-defer-without-hiding' + (enableLegacyHidden && nextProps.mode === 'unstable-defer-without-hiding') ) { // Rendering a hidden tree. if ((workInProgress.mode & ConcurrentMode) === NoMode) { @@ -774,7 +775,7 @@ function updateOffscreenComponent( // or some other infra that expects a HostComponent. const isHidden = nextProps.mode === 'hidden' && - workInProgress.tag !== LegacyHiddenComponent; + (!enableLegacyHidden || workInProgress.tag !== LegacyHiddenComponent); const offscreenContainer = reconcileOffscreenHostContainer( current, workInProgress, @@ -3948,7 +3949,14 @@ function beginWork( return updateOffscreenComponent(current, workInProgress, renderLanes); } case LegacyHiddenComponent: { - return updateLegacyHiddenComponent(current, workInProgress, renderLanes); + if (enableLegacyHidden) { + return updateLegacyHiddenComponent( + current, + workInProgress, + renderLanes, + ); + } + break; } case CacheComponent: { if (enableCache) { diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js index 57a8f9c48fb1f..583539dd08b52 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js @@ -98,6 +98,7 @@ import { enableSchedulingProfiler, enablePersistentOffscreenHostContainer, enableTransitionTracing, + enableLegacyHidden, } from 'shared/ReactFeatureFlags'; import isArray from 'shared/isArray'; import shallowEqual from 'shared/shallowEqual'; @@ -640,7 +641,7 @@ function updateOffscreenComponent( if ( nextProps.mode === 'hidden' || - nextProps.mode === 'unstable-defer-without-hiding' + (enableLegacyHidden && nextProps.mode === 'unstable-defer-without-hiding') ) { // Rendering a hidden tree. if ((workInProgress.mode & ConcurrentMode) === NoMode) { @@ -774,7 +775,7 @@ function updateOffscreenComponent( // or some other infra that expects a HostComponent. const isHidden = nextProps.mode === 'hidden' && - workInProgress.tag !== LegacyHiddenComponent; + (!enableLegacyHidden || workInProgress.tag !== LegacyHiddenComponent); const offscreenContainer = reconcileOffscreenHostContainer( current, workInProgress, @@ -3948,7 +3949,14 @@ function beginWork( return updateOffscreenComponent(current, workInProgress, renderLanes); } case LegacyHiddenComponent: { - return updateLegacyHiddenComponent(current, workInProgress, renderLanes); + if (enableLegacyHidden) { + return updateLegacyHiddenComponent( + current, + workInProgress, + renderLanes, + ); + } + break; } case CacheComponent: { if (enableCache) { diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js index 3ca22e58263e7..2a44cf94a14aa 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js @@ -32,6 +32,7 @@ import type {Cache} from './ReactFiberCacheComponent.new'; import { enableClientRenderFallbackOnHydrationMismatch, enableSuspenseAvoidThisFallback, + enableLegacyHidden, } from 'shared/ReactFeatureFlags'; import {resetWorkInProgressVersions as resetMutableSourceWorkInProgressVersions} from './ReactMutableSource.new'; @@ -1499,9 +1500,8 @@ function completeWork( const prevIsHidden = prevState !== null; if ( prevIsHidden !== nextIsHidden && - newProps.mode !== 'unstable-defer-without-hiding' && // LegacyHidden doesn't do any hiding — it only pre-renders. - workInProgress.tag !== LegacyHiddenComponent + (!enableLegacyHidden || workInProgress.tag !== LegacyHiddenComponent) ) { workInProgress.flags |= Visibility; } @@ -1519,9 +1519,9 @@ function completeWork( // If so, we need to hide those nodes in the commit phase, so // schedule a visibility effect. if ( - workInProgress.tag !== LegacyHiddenComponent && - workInProgress.subtreeFlags & (Placement | Update) && - newProps.mode !== 'unstable-defer-without-hiding' + (!enableLegacyHidden || + workInProgress.tag !== LegacyHiddenComponent) && + workInProgress.subtreeFlags & (Placement | Update) ) { workInProgress.flags |= Visibility; } diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js index bea755f7b4b6d..f02a20222d0fe 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js @@ -32,6 +32,7 @@ import type {Cache} from './ReactFiberCacheComponent.old'; import { enableClientRenderFallbackOnHydrationMismatch, enableSuspenseAvoidThisFallback, + enableLegacyHidden, } from 'shared/ReactFeatureFlags'; import {resetWorkInProgressVersions as resetMutableSourceWorkInProgressVersions} from './ReactMutableSource.old'; @@ -1499,9 +1500,8 @@ function completeWork( const prevIsHidden = prevState !== null; if ( prevIsHidden !== nextIsHidden && - newProps.mode !== 'unstable-defer-without-hiding' && // LegacyHidden doesn't do any hiding — it only pre-renders. - workInProgress.tag !== LegacyHiddenComponent + (!enableLegacyHidden || workInProgress.tag !== LegacyHiddenComponent) ) { workInProgress.flags |= Visibility; } @@ -1519,9 +1519,9 @@ function completeWork( // If so, we need to hide those nodes in the commit phase, so // schedule a visibility effect. if ( - workInProgress.tag !== LegacyHiddenComponent && - workInProgress.subtreeFlags & (Placement | Update) && - newProps.mode !== 'unstable-defer-without-hiding' + (!enableLegacyHidden || + workInProgress.tag !== LegacyHiddenComponent) && + workInProgress.subtreeFlags & (Placement | Update) ) { workInProgress.flags |= Visibility; } diff --git a/packages/react-reconciler/src/__tests__/ReactContextPropagation-test.js b/packages/react-reconciler/src/__tests__/ReactContextPropagation-test.js index 24e57002ef303..9b87ab65686e8 100644 --- a/packages/react-reconciler/src/__tests__/ReactContextPropagation-test.js +++ b/packages/react-reconciler/src/__tests__/ReactContextPropagation-test.js @@ -546,7 +546,7 @@ describe('ReactLazyContextPropagation', () => { expect(root).toMatchRenderedOutput('BB'); }); - // @gate experimental || www + // @gate www test('context is propagated through offscreen trees', async () => { const LegacyHidden = React.unstable_LegacyHidden; @@ -592,7 +592,7 @@ describe('ReactLazyContextPropagation', () => { expect(root).toMatchRenderedOutput('BB'); }); - // @gate experimental || www + // @gate www test('multiple contexts are propagated across through offscreen trees', async () => { // Same as previous test, but with multiple context providers const LegacyHidden = React.unstable_LegacyHidden; @@ -818,7 +818,7 @@ describe('ReactLazyContextPropagation', () => { expect(root).toMatchRenderedOutput('BB'); }); - // @gate experimental || www + // @gate www test('nested bailouts through offscreen trees', async () => { // Lazy context propagation will stop propagating when it hits the first // match. If we bail out again inside that tree, we must resume propagating. diff --git a/packages/react-reconciler/src/__tests__/ReactIncremental-test.js b/packages/react-reconciler/src/__tests__/ReactIncremental-test.js index 20496019984f2..8998ce6162eaa 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncremental-test.js +++ b/packages/react-reconciler/src/__tests__/ReactIncremental-test.js @@ -270,7 +270,7 @@ describe('ReactIncremental', () => { expect(inst.state).toEqual({text: 'bar', text2: 'baz'}); }); - // @gate experimental || www + // @gate www it('can deprioritize unfinished work and resume it later', () => { function Bar(props) { Scheduler.unstable_yieldValue('Bar'); @@ -316,7 +316,7 @@ describe('ReactIncremental', () => { expect(Scheduler).toFlushAndYield(['Middle', 'Middle']); }); - // @gate experimental || www + // @gate www it('can deprioritize a tree from without dropping work', () => { function Bar(props) { Scheduler.unstable_yieldValue('Bar'); @@ -1999,7 +1999,7 @@ describe('ReactIncremental', () => { }); } - // @gate experimental || www + // @gate www it('provides context when reusing work', () => { class Intl extends React.Component { static childContextTypes = { diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js index 55ce08b45450b..aafc918469c43 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js @@ -310,7 +310,7 @@ describe('ReactIncrementalErrorHandling', () => { expect(ReactNoop.getChildren()).toEqual([span('Everything is fine.')]); }); - // @gate experimental || www + // @gate www it('does not include offscreen work when retrying after an error', () => { function App(props) { if (props.isBroken) { diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.js b/packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.js index f0c6bad86319a..e09c866d6d67d 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.js @@ -424,7 +424,7 @@ describe('ReactIncrementalSideEffects', () => { ]); }); - // @gate experimental || www + // @gate www it('preserves a previously rendered node when deprioritized', () => { function Middle(props) { Scheduler.unstable_yieldValue('Middle'); @@ -475,7 +475,7 @@ describe('ReactIncrementalSideEffects', () => { ); }); - // @gate experimental || www + // @gate www it('can reuse side-effects after being preempted', () => { function Bar(props) { Scheduler.unstable_yieldValue('Bar'); @@ -555,7 +555,7 @@ describe('ReactIncrementalSideEffects', () => { ); }); - // @gate experimental || www + // @gate www it('can reuse side-effects after being preempted, if shouldComponentUpdate is false', () => { class Bar extends React.Component { shouldComponentUpdate(nextProps) { @@ -690,7 +690,7 @@ describe('ReactIncrementalSideEffects', () => { expect(ReactNoop.getChildrenAsJSX()).toEqual(); }); - // @gate experimental || www + // @gate www it('updates a child even though the old props is empty', () => { function Foo(props) { return ( @@ -930,7 +930,7 @@ describe('ReactIncrementalSideEffects', () => { expect(ops).toEqual(['Bar', 'Baz', 'Bar', 'Bar']); }); - // @gate experimental || www + // @gate www it('deprioritizes setStates that happens within a deprioritized tree', () => { const barInstances = []; diff --git a/packages/react-reconciler/src/__tests__/ReactNewContext-test.js b/packages/react-reconciler/src/__tests__/ReactNewContext-test.js index eb90d61dad6a1..3c3fddf204d5c 100644 --- a/packages/react-reconciler/src/__tests__/ReactNewContext-test.js +++ b/packages/react-reconciler/src/__tests__/ReactNewContext-test.js @@ -667,7 +667,7 @@ describe('ReactNewContext', () => { expect(ReactNoop.getChildren()).toEqual([span(2), span(2)]); }); - // @gate experimental || www + // @gate www it("context consumer doesn't bail out inside hidden subtree", () => { const Context = React.createContext('dark'); const Consumer = getConsumer(Context); diff --git a/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js b/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js index 4dfd6459a33a3..3125fcc29e5f9 100644 --- a/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js +++ b/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js @@ -26,7 +26,7 @@ describe('ReactOffscreen', () => { return ; } - // @gate experimental || www + // @gate www it('unstable-defer-without-hiding should never toggle the visibility of its children', async () => { function App({mode}) { return ( @@ -85,7 +85,7 @@ describe('ReactOffscreen', () => { ); }); - // @gate experimental || www + // @gate www it('does not defer in legacy mode', async () => { let setState; function Foo() { @@ -130,7 +130,7 @@ describe('ReactOffscreen', () => { ); }); - // @gate experimental || www + // @gate www it('does defer in concurrent mode', async () => { let setState; function Foo() { @@ -310,7 +310,7 @@ describe('ReactOffscreen', () => { expect(root).toMatchRenderedOutput(