Update entry point exports (#21488)

The following APIs have been added to the `react` stable entry point:
* `SuspenseList`
* `startTransition`
* `unstable_createMutableSource`
* `unstable_useMutableSource`
* `useDeferredValue`
* `useTransition`

The following APIs have been added or removed from the `react-dom` stable entry point:
* `createRoot`
* `unstable_createPortal` (removed)

The following APIs have been added to the `react-is` stable entry point:
* `SuspenseList`
* `isSuspenseList`

The following feature flags have been changed from experimental to true:
* `enableLazyElements`
* `enableSelectiveHydration`
* `enableSuspenseServerRenderer`
This commit is contained in:
Brian Vaughn 2021-05-12 11:28:14 -04:00 committed by GitHub
parent b8fda6cabc
commit 2bf4805e4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
92 changed files with 575 additions and 969 deletions

View File

@ -268,7 +268,6 @@ describe('createSubscription', () => {
expect(Scheduler).toFlushAndYield(['b-1']); expect(Scheduler).toFlushAndYield(['b-1']);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('should ignore values emitted by a new subscribable until the commit phase', () => { it('should ignore values emitted by a new subscribable until the commit phase', () => {
const log = []; const log = [];
@ -327,7 +326,7 @@ describe('createSubscription', () => {
// Start React update, but don't finish // Start React update, but don't finish
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Parent observed={observableB} />); ReactNoop.render(<Parent observed={observableB} />);
}); });
} else { } else {
@ -362,7 +361,6 @@ describe('createSubscription', () => {
]); ]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('should not drop values emitted between updates', () => { it('should not drop values emitted between updates', () => {
const log = []; const log = [];
@ -421,7 +419,7 @@ describe('createSubscription', () => {
// Start React update, but don't finish // Start React update, but don't finish
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Parent observed={observableB} />); ReactNoop.render(<Parent observed={observableB} />);
}); });
} else { } else {

View File

@ -366,10 +366,9 @@ describe('ReactHooksInspectionIntegration', () => {
]); ]);
}); });
// @gate experimental
it('should support composite useTransition hook', () => { it('should support composite useTransition hook', () => {
function Foo(props) { function Foo(props) {
React.unstable_useTransition(); React.useTransition();
const memoizedValue = React.useMemo(() => 'hello', []); const memoizedValue = React.useMemo(() => 'hello', []);
return <div>{memoizedValue}</div>; return <div>{memoizedValue}</div>;
} }
@ -394,10 +393,9 @@ describe('ReactHooksInspectionIntegration', () => {
]); ]);
}); });
// @gate experimental
it('should support composite useDeferredValue hook', () => { it('should support composite useDeferredValue hook', () => {
function Foo(props) { function Foo(props) {
React.unstable_useDeferredValue('abc', { React.useDeferredValue('abc', {
timeoutMs: 500, timeoutMs: 500,
}); });
const [state] = React.useState(() => 'hello', []); const [state] = React.useState(() => 'hello', []);
@ -424,7 +422,6 @@ describe('ReactHooksInspectionIntegration', () => {
]); ]);
}); });
// @gate experimental
it('should support composite useOpaqueIdentifier hook', () => { it('should support composite useOpaqueIdentifier hook', () => {
function Foo(props) { function Foo(props) {
const id = React.unstable_useOpaqueIdentifier(); const id = React.unstable_useOpaqueIdentifier();
@ -452,7 +449,6 @@ describe('ReactHooksInspectionIntegration', () => {
}); });
}); });
// @gate experimental
it('should support composite useOpaqueIdentifier hook in concurrent mode', () => { it('should support composite useOpaqueIdentifier hook in concurrent mode', () => {
function Foo(props) { function Foo(props) {
const id = React.unstable_useOpaqueIdentifier(); const id = React.unstable_useOpaqueIdentifier();
@ -846,37 +842,40 @@ describe('ReactHooksInspectionIntegration', () => {
]); ]);
}); });
if (__EXPERIMENTAL__) { it('should support composite useMutableSource hook', () => {
it('should support composite useMutableSource hook', () => { const createMutableSource =
const mutableSource = React.unstable_createMutableSource({}, () => 1); React.createMutableSource || React.unstable_createMutableSource;
function Foo(props) { const useMutableSource =
React.unstable_useMutableSource( React.useMutableSource || React.unstable_useMutableSource;
mutableSource,
() => 'snapshot', const mutableSource = createMutableSource({}, () => 1);
() => {}, function Foo(props) {
); useMutableSource(
React.useMemo(() => 'memo', []); mutableSource,
return <div />; () => 'snapshot',
} () => {},
const renderer = ReactTestRenderer.create(<Foo />); );
const childFiber = renderer.root.findByType(Foo)._currentFiber(); React.useMemo(() => 'memo', []);
const tree = ReactDebugTools.inspectHooksOfFiber(childFiber); return <div />;
expect(tree).toEqual([ }
{ const renderer = ReactTestRenderer.create(<Foo />);
id: 0, const childFiber = renderer.root.findByType(Foo)._currentFiber();
isStateEditable: false, const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);
name: 'MutableSource', expect(tree).toEqual([
value: 'snapshot', {
subHooks: [], id: 0,
}, isStateEditable: false,
{ name: 'MutableSource',
id: 1, value: 'snapshot',
isStateEditable: false, subHooks: [],
name: 'Memo', },
value: 'memo', {
subHooks: [], id: 1,
}, isStateEditable: false,
]); name: 'Memo',
}); value: 'memo',
} subHooks: [],
},
]);
});
}); });

View File

@ -12,7 +12,7 @@ import {
// $FlowFixMe Flow does not yet know about flushSync() // $FlowFixMe Flow does not yet know about flushSync()
flushSync, flushSync,
// $FlowFixMe Flow does not yet know about createRoot() // $FlowFixMe Flow does not yet know about createRoot()
unstable_createRoot as createRoot, createRoot,
} from 'react-dom'; } from 'react-dom';
import Bridge from 'react-devtools-shared/src/bridge'; import Bridge from 'react-devtools-shared/src/bridge';
import Store from 'react-devtools-shared/src/devtools/store'; import Store from 'react-devtools-shared/src/devtools/store';

View File

@ -1,7 +1,7 @@
/* global chrome */ /* global chrome */
import {createElement} from 'react'; import {createElement} from 'react';
import {unstable_createRoot as createRoot, flushSync} from 'react-dom'; import {createRoot, flushSync} from 'react-dom';
import Bridge from 'react-devtools-shared/src/bridge'; import Bridge from 'react-devtools-shared/src/bridge';
import Store from 'react-devtools-shared/src/devtools/store'; import Store from 'react-devtools-shared/src/devtools/store';
import {getBrowserName, getBrowserTheme} from './utils'; import {getBrowserName, getBrowserTheme} from './utils';

View File

@ -8,9 +8,11 @@
*/ */
import { import {
// $FlowFixMe
unstable_createMutableSource as createMutableSource, unstable_createMutableSource as createMutableSource,
unstable_useMutableSource as useMutableSource,
useLayoutEffect, useLayoutEffect,
// $FlowFixMe
unstable_useMutableSource as useMutableSource,
} from 'react'; } from 'react';
import { import {

View File

@ -382,7 +382,7 @@ describe(preprocessData, () => {
}); });
}); });
// @gate experimental && enableSchedulingProfiler // @gate enableSchedulingProfiler
it('should process a sample createRoot render sequence', () => { it('should process a sample createRoot render sequence', () => {
function App() { function App() {
const [didMount, setDidMount] = React.useState(false); const [didMount, setDidMount] = React.useState(false);

View File

@ -11,7 +11,7 @@ import 'regenerator-runtime/runtime';
import * as React from 'react'; import * as React from 'react';
// $FlowFixMe Flow does not yet know about createRoot() // $FlowFixMe Flow does not yet know about createRoot()
import {unstable_createRoot as createRoot} from 'react-dom'; import {createRoot} from 'react-dom';
import nullthrows from 'nullthrows'; import nullthrows from 'nullthrows';
import App from './App'; import App from './App';

View File

@ -149,7 +149,7 @@ describe('commit tree', () => {
it('should support Lazy components (createRoot)', async () => { it('should support Lazy components (createRoot)', async () => {
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
utils.act(() => store.profilerStore.startProfiling()); utils.act(() => store.profilerStore.startProfiling());
utils.act(() => root.render(<App renderChildren={true} />)); utils.act(() => root.render(<App renderChildren={true} />));
@ -226,7 +226,7 @@ describe('commit tree', () => {
it('should support Lazy components that are unmounted before resolving (createRoot)', async () => { it('should support Lazy components that are unmounted before resolving (createRoot)', async () => {
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
utils.act(() => store.profilerStore.startProfiling()); utils.act(() => store.profilerStore.startProfiling());
utils.act(() => root.render(<App renderChildren={true} />)); utils.act(() => root.render(<App renderChildren={true} />));

View File

@ -89,7 +89,7 @@ describe('profiling HostRoot', () => {
utils.act(() => store.profilerStore.startProfiling()); utils.act(() => store.profilerStore.startProfiling());
utils.act(() => { utils.act(() => {
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<App />); root.render(<App />);
}); });
utils.act(() => store.profilerStore.stopProfiling()); utils.act(() => store.profilerStore.stopProfiling());
@ -122,7 +122,7 @@ describe('profiling HostRoot', () => {
} }
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
utils.act(() => store.profilerStore.startProfiling()); utils.act(() => store.profilerStore.startProfiling());
utils.act(() => root.render(<App />)); utils.act(() => root.render(<App />));

View File

@ -356,18 +356,18 @@ describe('Store', () => {
}; };
const Wrapper = ({shouldSuspense}) => ( const Wrapper = ({shouldSuspense}) => (
<React.Fragment> <React.Fragment>
<React.unstable_SuspenseList revealOrder="forwards" tail="collapsed"> <React.SuspenseList revealOrder="forwards" tail="collapsed">
<Component key="A" /> <Component key="A" />
<React.Suspense fallback={<Loading />}> <React.Suspense fallback={<Loading />}>
{shouldSuspense ? <SuspendingComponent /> : <Component key="B" />} {shouldSuspense ? <SuspendingComponent /> : <Component key="B" />}
</React.Suspense> </React.Suspense>
<Component key="C" /> <Component key="C" />
</React.unstable_SuspenseList> </React.SuspenseList>
</React.Fragment> </React.Fragment>
); );
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
act(() => { act(() => {
root.render(<Wrapper shouldSuspense={true} />); root.render(<Wrapper shouldSuspense={true} />);
}); });
@ -984,7 +984,7 @@ describe('Store', () => {
it('should support Lazy components in (createRoot)', async () => { it('should support Lazy components in (createRoot)', async () => {
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
// Render once to start fetching the lazy component // Render once to start fetching the lazy component
act(() => root.render(<App renderChildren={true} />)); act(() => root.render(<App renderChildren={true} />));
@ -1020,7 +1020,7 @@ describe('Store', () => {
it('should support Lazy components that are unmounted before they finish loading in (createRoot)', async () => { it('should support Lazy components that are unmounted before they finish loading in (createRoot)', async () => {
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
// Render once to start fetching the lazy component // Render once to start fetching the lazy component
act(() => root.render(<App renderChildren={true} />)); act(() => root.render(<App renderChildren={true} />));

View File

@ -67,7 +67,7 @@ describe('StoreStressConcurrent', () => {
// 1. Render a normal version of [a, b, c, d, e]. // 1. Render a normal version of [a, b, c, d, e].
let container = document.createElement('div'); let container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
let root = ReactDOM.unstable_createRoot(container); let root = ReactDOM.createRoot(container);
act(() => root.render(<Parent>{[a, b, c, d, e]}</Parent>)); act(() => root.render(<Parent>{[a, b, c, d, e]}</Parent>));
expect(store).toMatchInlineSnapshot( expect(store).toMatchInlineSnapshot(
` `
@ -151,7 +151,7 @@ describe('StoreStressConcurrent', () => {
// Ensure fresh mount. // Ensure fresh mount.
container = document.createElement('div'); container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
root = ReactDOM.unstable_createRoot(container); root = ReactDOM.createRoot(container);
// Verify mounting 'abcde'. // Verify mounting 'abcde'.
act(() => root.render(<Parent>{cases[i]}</Parent>)); act(() => root.render(<Parent>{cases[i]}</Parent>));
@ -181,7 +181,7 @@ describe('StoreStressConcurrent', () => {
// There'll be no unmounting until the very end. // There'll be no unmounting until the very end.
container = document.createElement('div'); container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
root = ReactDOM.unstable_createRoot(container); root = ReactDOM.createRoot(container);
for (let i = 0; i < cases.length; i++) { for (let i = 0; i < cases.length; i++) {
// Verify mounting 'abcde'. // Verify mounting 'abcde'.
act(() => root.render(<Parent>{cases[i]}</Parent>)); act(() => root.render(<Parent>{cases[i]}</Parent>));
@ -247,7 +247,7 @@ describe('StoreStressConcurrent', () => {
const snapshots = []; const snapshots = [];
let container = document.createElement('div'); let container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
let root = ReactDOM.unstable_createRoot(container); let root = ReactDOM.createRoot(container);
for (let i = 0; i < steps.length; i++) { for (let i = 0; i < steps.length; i++) {
act(() => root.render(<Root>{steps[i]}</Root>)); act(() => root.render(<Root>{steps[i]}</Root>));
// We snapshot each step once so it doesn't regress. // We snapshot each step once so it doesn't regress.
@ -320,7 +320,7 @@ describe('StoreStressConcurrent', () => {
for (let j = 0; j < steps.length; j++) { for (let j = 0; j < steps.length; j++) {
container = document.createElement('div'); container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
root = ReactDOM.unstable_createRoot(container); root = ReactDOM.createRoot(container);
act(() => root.render(<Root>{steps[i]}</Root>)); act(() => root.render(<Root>{steps[i]}</Root>));
expect(print(store)).toMatch(snapshots[i]); expect(print(store)).toMatch(snapshots[i]);
act(() => root.render(<Root>{steps[j]}</Root>)); act(() => root.render(<Root>{steps[j]}</Root>));
@ -337,7 +337,7 @@ describe('StoreStressConcurrent', () => {
for (let j = 0; j < steps.length; j++) { for (let j = 0; j < steps.length; j++) {
container = document.createElement('div'); container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
root = ReactDOM.unstable_createRoot(container); root = ReactDOM.createRoot(container);
act(() => act(() =>
root.render( root.render(
<Root> <Root>
@ -409,7 +409,7 @@ describe('StoreStressConcurrent', () => {
const snapshots = []; const snapshots = [];
let container = document.createElement('div'); let container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
let root = ReactDOM.unstable_createRoot(container); let root = ReactDOM.createRoot(container);
for (let i = 0; i < steps.length; i++) { for (let i = 0; i < steps.length; i++) {
act(() => act(() =>
root.render( root.render(
@ -536,7 +536,7 @@ describe('StoreStressConcurrent', () => {
// Always start with a fresh container and steps[i]. // Always start with a fresh container and steps[i].
container = document.createElement('div'); container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
root = ReactDOM.unstable_createRoot(container); root = ReactDOM.createRoot(container);
act(() => act(() =>
root.render( root.render(
<Root> <Root>
@ -582,7 +582,7 @@ describe('StoreStressConcurrent', () => {
// Always start with a fresh container and steps[i]. // Always start with a fresh container and steps[i].
container = document.createElement('div'); container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
root = ReactDOM.unstable_createRoot(container); root = ReactDOM.createRoot(container);
act(() => act(() =>
root.render( root.render(
<Root> <Root>
@ -640,7 +640,7 @@ describe('StoreStressConcurrent', () => {
// Always start with a fresh container and steps[i]. // Always start with a fresh container and steps[i].
container = document.createElement('div'); container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
root = ReactDOM.unstable_createRoot(container); root = ReactDOM.createRoot(container);
act(() => act(() =>
root.render( root.render(
<Root> <Root>
@ -690,7 +690,7 @@ describe('StoreStressConcurrent', () => {
// Always start with a fresh container and steps[i]. // Always start with a fresh container and steps[i].
container = document.createElement('div'); container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
root = ReactDOM.unstable_createRoot(container); root = ReactDOM.createRoot(container);
act(() => act(() =>
root.render( root.render(
<Root> <Root>
@ -744,7 +744,7 @@ describe('StoreStressConcurrent', () => {
// Always start with a fresh container and steps[i]. // Always start with a fresh container and steps[i].
container = document.createElement('div'); container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
root = ReactDOM.unstable_createRoot(container); root = ReactDOM.createRoot(container);
act(() => act(() =>
root.render( root.render(
<Root> <Root>
@ -898,7 +898,7 @@ describe('StoreStressConcurrent', () => {
const snapshots = []; const snapshots = [];
let container = document.createElement('div'); let container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
let root = ReactDOM.unstable_createRoot(container); let root = ReactDOM.createRoot(container);
for (let i = 0; i < steps.length; i++) { for (let i = 0; i < steps.length; i++) {
act(() => act(() =>
root.render( root.render(
@ -1055,7 +1055,7 @@ describe('StoreStressConcurrent', () => {
// Always start with a fresh container and steps[i]. // Always start with a fresh container and steps[i].
container = document.createElement('div'); container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
root = ReactDOM.unstable_createRoot(container); root = ReactDOM.createRoot(container);
act(() => act(() =>
root.render( root.render(
<Root> <Root>
@ -1107,7 +1107,7 @@ describe('StoreStressConcurrent', () => {
// Always start with a fresh container and steps[i]. // Always start with a fresh container and steps[i].
container = document.createElement('div'); container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
root = ReactDOM.unstable_createRoot(container); root = ReactDOM.createRoot(container);
act(() => act(() =>
root.render( root.render(
<Root> <Root>
@ -1174,7 +1174,7 @@ describe('StoreStressConcurrent', () => {
// Always start with a fresh container and steps[i]. // Always start with a fresh container and steps[i].
container = document.createElement('div'); container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
root = ReactDOM.unstable_createRoot(container); root = ReactDOM.createRoot(container);
act(() => act(() =>
root.render( root.render(
<Root> <Root>
@ -1226,7 +1226,7 @@ describe('StoreStressConcurrent', () => {
// Always start with a fresh container and steps[i]. // Always start with a fresh container and steps[i].
container = document.createElement('div'); container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
root = ReactDOM.unstable_createRoot(container); root = ReactDOM.createRoot(container);
act(() => act(() =>
root.render( root.render(
<Root> <Root>
@ -1278,7 +1278,7 @@ describe('StoreStressConcurrent', () => {
// Always start with a fresh container and steps[i]. // Always start with a fresh container and steps[i].
container = document.createElement('div'); container = document.createElement('div');
// $FlowFixMe // $FlowFixMe
root = ReactDOM.unstable_createRoot(container); root = ReactDOM.createRoot(container);
act(() => act(() =>
root.render( root.render(
<Root> <Root>

View File

@ -10,7 +10,7 @@
import * as React from 'react'; import * as React from 'react';
import { import {
createContext, createContext,
unstable_startTransition as startTransition, startTransition,
unstable_useCacheRefresh as useCacheRefresh, unstable_useCacheRefresh as useCacheRefresh,
useCallback, useCallback,
useContext, useContext,

View File

@ -11,7 +11,7 @@ import * as React from 'react';
import { import {
useContext, useContext,
unstable_useCacheRefresh as useCacheRefresh, unstable_useCacheRefresh as useCacheRefresh,
unstable_useTransition as useTransition, useTransition,
} from 'react'; } from 'react';
import Button from '../Button'; import Button from '../Button';
import ButtonIcon from '../ButtonIcon'; import ButtonIcon from '../ButtonIcon';

View File

@ -8,12 +8,7 @@
*/ */
import * as React from 'react'; import * as React from 'react';
import { import {useTransition, useContext, useRef, useState} from 'react';
unstable_useTransition as useTransition,
useContext,
useRef,
useState,
} from 'react';
import EditableName from './EditableName'; import EditableName from './EditableName';
import EditableValue from './EditableValue'; import EditableValue from './EditableValue';
import NewArrayValue from './NewArrayValue'; import NewArrayValue from './NewArrayValue';

View File

@ -34,7 +34,7 @@ import {
useMemo, useMemo,
useReducer, useReducer,
useRef, useRef,
unstable_startTransition as startTransition, startTransition,
} from 'react'; } from 'react';
import {createRegExp} from '../utils'; import {createRegExp} from '../utils';
import {BridgeContext, StoreContext} from '../context'; import {BridgeContext, StoreContext} from '../context';

View File

@ -10,7 +10,7 @@
import type {Wakeable} from 'shared/ReactTypes'; import type {Wakeable} from 'shared/ReactTypes';
import type {GitHubIssue} from './githubAPI'; import type {GitHubIssue} from './githubAPI';
import {unstable_getCacheForType} from 'react'; import {unstable_getCacheForType as getCacheForType} from 'react';
import {searchGitHubIssues} from './githubAPI'; import {searchGitHubIssues} from './githubAPI';
const API_TIMEOUT = 3000; const API_TIMEOUT = 3000;
@ -55,7 +55,7 @@ function createMap(): GitHubIssueMap {
} }
function getRecordMap(): Map<string, Record<GitHubIssue>> { function getRecordMap(): Map<string, Record<GitHubIssue>> {
return unstable_getCacheForType(createMap); return getCacheForType(createMap);
} }
export function findGitHubIssue(errorMessage: string): GitHubIssue | null { export function findGitHubIssue(errorMessage: string): GitHubIssue | null {

View File

@ -8,8 +8,8 @@
*/ */
import { import {
unstable_getCacheForType, unstable_getCacheForType as getCacheForType,
unstable_startTransition as startTransition, startTransition,
} from 'react'; } from 'react';
import Store from './devtools/store'; import Store from './devtools/store';
import {inspectElement as inspectElementMutableSource} from './inspectedElementMutableSource'; import {inspectElement as inspectElementMutableSource} from './inspectedElementMutableSource';
@ -60,7 +60,7 @@ function createMap(): InspectedElementMap {
} }
function getRecordMap(): WeakMap<Element, Record<InspectedElementFrontend>> { function getRecordMap(): WeakMap<Element, Record<InspectedElementFrontend>> {
return unstable_getCacheForType(createMap); return getCacheForType(createMap);
} }
function createCacheSeed( function createCacheSeed(

View File

@ -8,12 +8,7 @@
*/ */
import * as React from 'react'; import * as React from 'react';
import { import {Fragment, Suspense, SuspenseList, useState} from 'react';
Fragment,
Suspense,
unstable_SuspenseList as SuspenseList,
useState,
} from 'react';
function SuspenseTree() { function SuspenseTree() {
return ( return (

View File

@ -5,7 +5,7 @@
import {createElement} from 'react'; import {createElement} from 'react';
import { import {
// $FlowFixMe Flow does not yet know about createRoot() // $FlowFixMe Flow does not yet know about createRoot()
unstable_createRoot as createRoot, createRoot,
} from 'react-dom'; } from 'react-dom';
import DeeplyNestedComponents from './DeeplyNestedComponents'; import DeeplyNestedComponents from './DeeplyNestedComponents';
import Iframe from './Iframe'; import Iframe from './Iframe';

View File

@ -2,7 +2,7 @@
import {createElement} from 'react'; import {createElement} from 'react';
// $FlowFixMe Flow does not yet know about createRoot() // $FlowFixMe Flow does not yet know about createRoot()
import {unstable_createRoot as createRoot} from 'react-dom'; import {createRoot} from 'react-dom';
import { import {
activate as activateBackend, activate as activateBackend,
initialize as initializeBackend, initialize as initializeBackend,

View File

@ -19,22 +19,21 @@ Object.assign((__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: any), {
}); });
export { export {
createPortal,
unstable_batchedUpdates,
flushSync,
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
version, createPortal,
createRoot,
createRoot as unstable_createRoot, // TODO Remove once callsites use createRoot
findDOMNode, findDOMNode,
flushSync,
hydrate, hydrate,
render, render,
unmountComponentAtNode, unmountComponentAtNode,
createRoot, unstable_batchedUpdates,
createRoot as unstable_createRoot,
unstable_flushControlled,
unstable_scheduleHydration,
unstable_runWithPriority,
unstable_renderSubtreeIntoContainer,
unstable_createPortal,
unstable_createEventHandle, unstable_createEventHandle,
unstable_flushControlled,
unstable_isNewReconciler, unstable_isNewReconciler,
unstable_renderSubtreeIntoContainer,
unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.
unstable_scheduleHydration,
version,
} from './src/client/ReactDOM'; } from './src/client/ReactDOM';

View File

@ -8,26 +8,18 @@
*/ */
export { export {
createPortal,
unstable_batchedUpdates,
flushSync,
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
version, createPortal,
// Disabled behind disableLegacyReactDOMAPIs createRoot,
findDOMNode, findDOMNode,
flushSync,
hydrate, hydrate,
render, render,
unmountComponentAtNode, unmountComponentAtNode,
// exposeConcurrentModeAPIs unstable_batchedUpdates,
createRoot as unstable_createRoot,
unstable_flushControlled, unstable_flushControlled,
unstable_scheduleHydration,
// DO NOT USE: Temporarily exposing this to migrate off of Scheduler.runWithPriority.
unstable_runWithPriority,
// Disabled behind disableUnstableRenderSubtreeIntoContainer
unstable_renderSubtreeIntoContainer, unstable_renderSubtreeIntoContainer,
// Disabled behind disableUnstableCreatePortal unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.
// Temporary alias since we already shipped React 16 RC with it. unstable_scheduleHydration,
// TODO: remove in React 18. version,
unstable_createPortal,
} from './src/client/ReactDOM'; } from './src/client/ReactDOM';

View File

@ -10,22 +10,21 @@
// Export all exports so that they're available in tests. // Export all exports so that they're available in tests.
// We can't use export * from in Flow for some reason. // We can't use export * from in Flow for some reason.
export { export {
createPortal,
unstable_batchedUpdates,
flushSync,
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
version, createPortal,
createRoot,
createRoot as unstable_createRoot,
findDOMNode, findDOMNode,
flushSync,
hydrate, hydrate,
render, render,
unmountComponentAtNode, unmountComponentAtNode,
createRoot, unstable_batchedUpdates,
createRoot as unstable_createRoot,
unstable_flushControlled,
unstable_scheduleHydration,
unstable_runWithPriority,
unstable_renderSubtreeIntoContainer,
unstable_createPortal,
unstable_createEventHandle, unstable_createEventHandle,
unstable_flushControlled,
unstable_isNewReconciler, unstable_isNewReconciler,
unstable_renderSubtreeIntoContainer,
unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.
unstable_scheduleHydration,
version,
} from './src/client/ReactDOM'; } from './src/client/ReactDOM';

View File

@ -8,16 +8,16 @@
*/ */
export { export {
createPortal,
unstable_batchedUpdates,
flushSync,
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
version, createPortal,
createRoot, createRoot,
createRoot as unstable_createRoot, createRoot as unstable_createRoot, // TODO Remove once callsites use createRoot
unstable_flushControlled, flushSync,
unstable_scheduleHydration, unstable_batchedUpdates,
unstable_runWithPriority,
unstable_createEventHandle, unstable_createEventHandle,
unstable_flushControlled,
unstable_isNewReconciler, unstable_isNewReconciler,
unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.
unstable_scheduleHydration,
version,
} from './src/client/ReactDOM'; } from './src/client/ReactDOM';

View File

@ -8,17 +8,15 @@
*/ */
export { export {
createPortal,
unstable_batchedUpdates,
flushSync,
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
version, createPortal,
createRoot,
findDOMNode, findDOMNode,
flushSync,
hydrate, hydrate,
render, render,
unmountComponentAtNode, unmountComponentAtNode,
unstable_batchedUpdates,
unstable_renderSubtreeIntoContainer, unstable_renderSubtreeIntoContainer,
// Temporary alias since we already shipped React 16 RC with it. version,
// TODO: remove in React 18.
unstable_createPortal,
} from './src/client/ReactDOM'; } from './src/client/ReactDOM';

View File

@ -246,34 +246,6 @@ describe('ReactDOMFiber', () => {
expect(container.innerHTML).toBe(''); expect(container.innerHTML).toBe('');
}); });
// TODO: remove in React 18
if (!__EXPERIMENTAL__) {
it('should support unstable_createPortal alias', () => {
const portalContainer = document.createElement('div');
expect(() =>
ReactDOM.render(
<div>
{ReactDOM.unstable_createPortal(<div>portal</div>, portalContainer)}
</div>,
container,
),
).toWarnDev(
'The ReactDOM.unstable_createPortal() alias has been deprecated, ' +
'and will be removed in React 18+. Update your code to use ' +
'ReactDOM.createPortal() instead. It has the exact same API, ' +
'but without the "unstable_" prefix.',
{withoutStack: true},
);
expect(portalContainer.innerHTML).toBe('<div>portal</div>');
expect(container.innerHTML).toBe('<div></div>');
ReactDOM.unmountComponentAtNode(container);
expect(portalContainer.innerHTML).toBe('');
expect(container.innerHTML).toBe('');
});
}
it('should render many portals', () => { it('should render many portals', () => {
const portalContainer1 = document.createElement('div'); const portalContainer1 = document.createElement('div');
const portalContainer2 = document.createElement('div'); const portalContainer2 = document.createElement('div');

View File

@ -148,7 +148,6 @@ describe('ReactDOMFiberAsync', () => {
}); });
describe('concurrent mode', () => { describe('concurrent mode', () => {
// @gate experimental
it('does not perform deferred updates synchronously', () => { it('does not perform deferred updates synchronously', () => {
const inputRef = React.createRef(); const inputRef = React.createRef();
const asyncValueRef = React.createRef(); const asyncValueRef = React.createRef();
@ -185,7 +184,7 @@ describe('ReactDOMFiberAsync', () => {
); );
} }
} }
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<Counter />); root.render(<Counter />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
expect(asyncValueRef.current.textContent).toBe(''); expect(asyncValueRef.current.textContent).toBe('');
@ -204,9 +203,8 @@ describe('ReactDOMFiberAsync', () => {
expect(syncValueRef.current.textContent).toBe('hello'); expect(syncValueRef.current.textContent).toBe('hello');
}); });
// @gate experimental
it('top-level updates are concurrent', () => { it('top-level updates are concurrent', () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<div>Hi</div>); root.render(<div>Hi</div>);
expect(container.textContent).toEqual(''); expect(container.textContent).toEqual('');
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
@ -218,7 +216,6 @@ describe('ReactDOMFiberAsync', () => {
expect(container.textContent).toEqual('Bye'); expect(container.textContent).toEqual('Bye');
}); });
// @gate experimental
it('deep updates (setState) are concurrent', () => { it('deep updates (setState) are concurrent', () => {
let instance; let instance;
class Component extends React.Component { class Component extends React.Component {
@ -229,7 +226,7 @@ describe('ReactDOMFiberAsync', () => {
} }
} }
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<Component />); root.render(<Component />);
expect(container.textContent).toEqual(''); expect(container.textContent).toEqual('');
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
@ -241,7 +238,6 @@ describe('ReactDOMFiberAsync', () => {
expect(container.textContent).toEqual('1'); expect(container.textContent).toEqual('1');
}); });
// @gate experimental
it('flushSync flushes updates before end of the tick', () => { it('flushSync flushes updates before end of the tick', () => {
const ops = []; const ops = [];
let instance; let instance;
@ -260,7 +256,7 @@ describe('ReactDOMFiberAsync', () => {
} }
} }
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<Component />); root.render(<Component />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
@ -302,7 +298,7 @@ describe('ReactDOMFiberAsync', () => {
return this.state.counter; return this.state.counter;
} }
} }
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<Counter />); root.render(<Counter />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
expect(container.textContent).toEqual('0'); expect(container.textContent).toEqual('0');
@ -385,7 +381,6 @@ describe('ReactDOMFiberAsync', () => {
expect(returnValue).toBe(undefined); expect(returnValue).toBe(undefined);
}); });
// @gate experimental
it('ignores discrete events on a pending removed element', async () => { it('ignores discrete events on a pending removed element', async () => {
const disableButtonRef = React.createRef(); const disableButtonRef = React.createRef();
const submitButtonRef = React.createRef(); const submitButtonRef = React.createRef();
@ -406,7 +401,7 @@ describe('ReactDOMFiberAsync', () => {
); );
} }
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
await act(async () => { await act(async () => {
root.render(<Form />); root.render(<Form />);
}); });
@ -426,7 +421,6 @@ describe('ReactDOMFiberAsync', () => {
expect(submitButton.current).toBe(undefined); expect(submitButton.current).toBe(undefined);
}); });
// @gate experimental
it('ignores discrete events on a pending removed event listener', async () => { it('ignores discrete events on a pending removed event listener', async () => {
const disableButtonRef = React.createRef(); const disableButtonRef = React.createRef();
const submitButtonRef = React.createRef(); const submitButtonRef = React.createRef();
@ -458,7 +452,7 @@ describe('ReactDOMFiberAsync', () => {
); );
} }
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
await act(async () => { await act(async () => {
root.render(<Form />); root.render(<Form />);
}); });
@ -491,7 +485,6 @@ describe('ReactDOMFiberAsync', () => {
expect(formSubmitted).toBe(false); expect(formSubmitted).toBe(false);
}); });
// @gate experimental
it('uses the newest discrete events on a pending changed event listener', async () => { it('uses the newest discrete events on a pending changed event listener', async () => {
const enableButtonRef = React.createRef(); const enableButtonRef = React.createRef();
const submitButtonRef = React.createRef(); const submitButtonRef = React.createRef();
@ -518,7 +511,7 @@ describe('ReactDOMFiberAsync', () => {
); );
} }
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
await act(async () => { await act(async () => {
root.render(<Form />); root.render(<Form />);
}); });
@ -582,9 +575,8 @@ describe('ReactDOMFiberAsync', () => {
expect(containerC.textContent).toEqual('Finished'); expect(containerC.textContent).toEqual('Finished');
}); });
// @gate experimental
it('updates flush without yielding in the next event', () => { it('updates flush without yielding in the next event', () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
function Text(props) { function Text(props) {
Scheduler.unstable_yieldValue(props.text); Scheduler.unstable_yieldValue(props.text);
@ -607,7 +599,6 @@ describe('ReactDOMFiberAsync', () => {
expect(container.textContent).toEqual('ABC'); expect(container.textContent).toEqual('ABC');
}); });
// @gate experimental
it('unmounted roots should never clear newer root content from a container', () => { it('unmounted roots should never clear newer root content from a container', () => {
const ref = React.createRef(); const ref = React.createRef();
@ -630,7 +621,7 @@ describe('ReactDOMFiberAsync', () => {
return <button ref={ref}>new</button>; return <button ref={ref}>new</button>;
} }
const oldRoot = ReactDOM.unstable_createRoot(container); const oldRoot = ReactDOM.createRoot(container);
act(() => { act(() => {
oldRoot.render(<OldApp />); oldRoot.render(<OldApp />);
}); });
@ -642,7 +633,7 @@ describe('ReactDOMFiberAsync', () => {
expect(container.textContent).toBe(''); expect(container.textContent).toBe('');
// We can now render a new one. // We can now render a new one.
const newRoot = ReactDOM.unstable_createRoot(container); const newRoot = ReactDOM.createRoot(container);
ReactDOM.flushSync(() => { ReactDOM.flushSync(() => {
newRoot.render(<NewApp />); newRoot.render(<NewApp />);
}); });

View File

@ -38,7 +38,7 @@ describe('ReactDOMFizzServer', () => {
} }
Stream = require('stream'); Stream = require('stream');
Suspense = React.Suspense; Suspense = React.Suspense;
SuspenseList = React.unstable_SuspenseList; SuspenseList = React.SuspenseList;
PropTypes = require('prop-types'); PropTypes = require('prop-types');
textCache = new Map(); textCache = new Map();
@ -313,7 +313,7 @@ describe('ReactDOMFizzServer', () => {
expect(loggedErrors).toEqual([]); expect(loggedErrors).toEqual([]);
// Attempt to hydrate the content. // Attempt to hydrate the content.
const root = ReactDOM.unstable_createRoot(container, {hydrate: true}); const root = ReactDOM.createRoot(container, {hydrate: true});
root.render(<App isClient={true} />); root.render(<App isClient={true} />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
@ -405,7 +405,7 @@ describe('ReactDOMFizzServer', () => {
expect(loggedErrors).toEqual([]); expect(loggedErrors).toEqual([]);
// Attempt to hydrate the content. // Attempt to hydrate the content.
const root = ReactDOM.unstable_createRoot(container, {hydrate: true}); const root = ReactDOM.createRoot(container, {hydrate: true});
root.render(<App isClient={true} />); root.render(<App isClient={true} />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
@ -481,7 +481,7 @@ describe('ReactDOMFizzServer', () => {
expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>); expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);
// Attempt to hydrate the content. // Attempt to hydrate the content.
const root = ReactDOM.unstable_createRoot(container, {hydrate: true}); const root = ReactDOM.createRoot(container, {hydrate: true});
root.render(<App />); root.render(<App />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
@ -563,7 +563,7 @@ describe('ReactDOMFizzServer', () => {
expect(loggedErrors).toEqual([]); expect(loggedErrors).toEqual([]);
// Attempt to hydrate the content. // Attempt to hydrate the content.
const root = ReactDOM.unstable_createRoot(container, {hydrate: true}); const root = ReactDOM.createRoot(container, {hydrate: true});
root.render(<App />); root.render(<App />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
@ -635,7 +635,7 @@ describe('ReactDOMFizzServer', () => {
startWriting(); startWriting();
}); });
const root = ReactDOM.unstable_createRoot(container, {hydrate: true}); const root = ReactDOM.createRoot(container, {hydrate: true});
root.render(<App showMore={false} />); root.render(<App showMore={false} />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
@ -703,7 +703,7 @@ describe('ReactDOMFizzServer', () => {
// We're still showing a fallback. // We're still showing a fallback.
// Attempt to hydrate the content. // Attempt to hydrate the content.
const root = ReactDOM.unstable_createRoot(container, {hydrate: true}); const root = ReactDOM.createRoot(container, {hydrate: true});
root.render(<App />); root.render(<App />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
@ -1294,7 +1294,7 @@ describe('ReactDOMFizzServer', () => {
// We're still showing a fallback. // We're still showing a fallback.
// Attempt to hydrate the content. // Attempt to hydrate the content.
const root = ReactDOM.unstable_createRoot(container, {hydrate: true}); const root = ReactDOM.createRoot(container, {hydrate: true});
root.render(<App isClient={true} />); root.render(<App isClient={true} />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();

View File

@ -107,7 +107,6 @@ describe('ReactDOMHooks', () => {
expect(labelRef.current.innerHTML).toBe('abc'); expect(labelRef.current.innerHTML).toBe('abc');
}); });
// @gate experimental
it('should not bail out when an update is scheduled from within an event handler in Concurrent Mode', async () => { it('should not bail out when an update is scheduled from within an event handler in Concurrent Mode', async () => {
const {createRef, useCallback, useState} = React; const {createRef, useCallback, useState} = React;
@ -128,7 +127,7 @@ describe('ReactDOMHooks', () => {
const inputRef = createRef(); const inputRef = createRef();
const labelRef = createRef(); const labelRef = createRef();
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<Example inputRef={inputRef} labelRef={labelRef} />); root.render(<Example inputRef={inputRef} labelRef={labelRef} />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();

View File

@ -42,7 +42,6 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
} }
} }
// @gate experimental
it('ignores discrete events on a pending removed element', async () => { it('ignores discrete events on a pending removed element', async () => {
const disableButtonRef = React.createRef(); const disableButtonRef = React.createRef();
const submitButtonRef = React.createRef(); const submitButtonRef = React.createRef();
@ -66,7 +65,7 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
); );
} }
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
await act(() => { await act(() => {
root.render(<Form />); root.render(<Form />);
}); });
@ -88,7 +87,6 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
// We'll assume that the browser won't let the user click it. // We'll assume that the browser won't let the user click it.
}); });
// @gate experimental
it('ignores discrete events on a pending removed event listener', async () => { it('ignores discrete events on a pending removed event listener', async () => {
const disableButtonRef = React.createRef(); const disableButtonRef = React.createRef();
const submitButtonRef = React.createRef(); const submitButtonRef = React.createRef();
@ -125,7 +123,7 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
); );
} }
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<Form />); root.render(<Form />);
// Flush // Flush
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
@ -157,7 +155,6 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
expect(formSubmitted).toBe(false); expect(formSubmitted).toBe(false);
}); });
// @gate experimental
it('uses the newest discrete events on a pending changed event listener', async () => { it('uses the newest discrete events on a pending changed event listener', async () => {
const enableButtonRef = React.createRef(); const enableButtonRef = React.createRef();
const submitButtonRef = React.createRef(); const submitButtonRef = React.createRef();
@ -188,7 +185,7 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
); );
} }
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<Form />); root.render(<Form />);
// Flush // Flush
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
@ -220,9 +217,8 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
expect(formSubmitted).toBe(true); expect(formSubmitted).toBe(true);
}); });
// @gate experimental
it('mouse over should be user-blocking but not discrete', async () => { it('mouse over should be user-blocking but not discrete', async () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
const target = React.createRef(null); const target = React.createRef(null);
function Foo() { function Foo() {
@ -251,9 +247,8 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
expect(container.textContent).toEqual('hovered'); expect(container.textContent).toEqual('hovered');
}); });
// @gate experimental
it('mouse enter should be user-blocking but not discrete', async () => { it('mouse enter should be user-blocking but not discrete', async () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
const target = React.createRef(null); const target = React.createRef(null);
function Foo() { function Foo() {
@ -284,9 +279,8 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
expect(container.textContent).toEqual('hovered'); expect(container.textContent).toEqual('hovered');
}); });
// @gate experimental
it('continuous native events flush as expected', async () => { it('continuous native events flush as expected', async () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
const target = React.createRef(null); const target = React.createRef(null);
function Foo({hovered}) { function Foo({hovered}) {
@ -324,9 +318,8 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
expect(container.textContent).toEqual('hovered'); expect(container.textContent).toEqual('hovered');
}); });
// @gate experimental
it('should batch inside native events', async () => { it('should batch inside native events', async () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
const target = React.createRef(null); const target = React.createRef(null);
function Foo() { function Foo() {
@ -375,9 +368,8 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
} }
}); });
// @gate experimental
it('should not flush discrete events at the end of outermost batchedUpdates', async () => { it('should not flush discrete events at the end of outermost batchedUpdates', async () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
let target; let target;
function Foo() { function Foo() {

View File

@ -27,7 +27,6 @@ describe('ReactDOMNestedEvents', () => {
useState = React.useState; useState = React.useState;
}); });
// @gate experimental
test('nested event dispatches should not cause updates to flush', async () => { test('nested event dispatches should not cause updates to flush', async () => {
const buttonRef = React.createRef(null); const buttonRef = React.createRef(null);
function App() { function App() {
@ -58,7 +57,7 @@ describe('ReactDOMNestedEvents', () => {
const container = document.createElement('div'); const container = document.createElement('div');
document.body.appendChild(container); document.body.appendChild(container);
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
await act(async () => { await act(async () => {
root.render(<App />); root.render(<App />);

View File

@ -28,15 +28,8 @@ describe('ReactDOMRoot', () => {
act = require('react-dom/test-utils').unstable_concurrentAct; act = require('react-dom/test-utils').unstable_concurrentAct;
}); });
if (!__EXPERIMENTAL__) {
it('createRoot is not exposed in stable build', () => {
expect(ReactDOM.unstable_createRoot).toBe(undefined);
});
return;
}
it('renders children', () => { it('renders children', () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<div>Hi</div>); root.render(<div>Hi</div>);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
expect(container.textContent).toEqual('Hi'); expect(container.textContent).toEqual('Hi');
@ -44,7 +37,7 @@ describe('ReactDOMRoot', () => {
it('warns if a callback parameter is provided to render', () => { it('warns if a callback parameter is provided to render', () => {
const callback = jest.fn(); const callback = jest.fn();
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
expect(() => expect(() =>
root.render(<div>Hi</div>, callback), root.render(<div>Hi</div>, callback),
).toErrorDev( ).toErrorDev(
@ -58,7 +51,7 @@ describe('ReactDOMRoot', () => {
it('warns if a callback parameter is provided to unmount', () => { it('warns if a callback parameter is provided to unmount', () => {
const callback = jest.fn(); const callback = jest.fn();
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<div>Hi</div>); root.render(<div>Hi</div>);
expect(() => expect(() =>
root.unmount(callback), root.unmount(callback),
@ -72,7 +65,7 @@ describe('ReactDOMRoot', () => {
}); });
it('unmounts children', () => { it('unmounts children', () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<div>Hi</div>); root.render(<div>Hi</div>);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
expect(container.textContent).toEqual('Hi'); expect(container.textContent).toEqual('Hi');
@ -95,7 +88,7 @@ describe('ReactDOMRoot', () => {
// Does not hydrate by default // Does not hydrate by default
const container1 = document.createElement('div'); const container1 = document.createElement('div');
container1.innerHTML = markup; container1.innerHTML = markup;
const root1 = ReactDOM.unstable_createRoot(container1); const root1 = ReactDOM.createRoot(container1);
root1.render( root1.render(
<div> <div>
<span /> <span />
@ -106,7 +99,7 @@ describe('ReactDOMRoot', () => {
// Accepts `hydrate` option // Accepts `hydrate` option
const container2 = document.createElement('div'); const container2 = document.createElement('div');
container2.innerHTML = markup; container2.innerHTML = markup;
const root2 = ReactDOM.unstable_createRoot(container2, {hydrate: true}); const root2 = ReactDOM.createRoot(container2, {hydrate: true});
root2.render( root2.render(
<div> <div>
<span /> <span />
@ -138,7 +131,7 @@ describe('ReactDOMRoot', () => {
it('clears existing children', async () => { it('clears existing children', async () => {
container.innerHTML = '<div>a</div><div>b</div>'; container.innerHTML = '<div>a</div><div>b</div>';
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render( root.render(
<div> <div>
<span>c</span> <span>c</span>
@ -159,12 +152,12 @@ describe('ReactDOMRoot', () => {
it('throws a good message on invalid containers', () => { it('throws a good message on invalid containers', () => {
expect(() => { expect(() => {
ReactDOM.unstable_createRoot(<div>Hi</div>); ReactDOM.createRoot(<div>Hi</div>);
}).toThrow('createRoot(...): Target container is not a DOM element.'); }).toThrow('createRoot(...): Target container is not a DOM element.');
}); });
it('warns when rendering with legacy API into createRoot() container', () => { it('warns when rendering with legacy API into createRoot() container', () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<div>Hi</div>); root.render(<div>Hi</div>);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
expect(container.textContent).toEqual('Hi'); expect(container.textContent).toEqual('Hi');
@ -187,7 +180,7 @@ describe('ReactDOMRoot', () => {
}); });
it('warns when hydrating with legacy API into createRoot() container', () => { it('warns when hydrating with legacy API into createRoot() container', () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<div>Hi</div>); root.render(<div>Hi</div>);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
expect(container.textContent).toEqual('Hi'); expect(container.textContent).toEqual('Hi');
@ -207,7 +200,7 @@ describe('ReactDOMRoot', () => {
}); });
it('warns when unmounting with legacy API (no previous content)', () => { it('warns when unmounting with legacy API (no previous content)', () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<div>Hi</div>); root.render(<div>Hi</div>);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
expect(container.textContent).toEqual('Hi'); expect(container.textContent).toEqual('Hi');
@ -236,7 +229,7 @@ describe('ReactDOMRoot', () => {
// Currently createRoot().render() doesn't clear this. // Currently createRoot().render() doesn't clear this.
container.appendChild(document.createElement('div')); container.appendChild(document.createElement('div'));
// The rest is the same as test above. // The rest is the same as test above.
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<div>Hi</div>); root.render(<div>Hi</div>);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
expect(container.textContent).toEqual('Hi'); expect(container.textContent).toEqual('Hi');
@ -262,7 +255,7 @@ describe('ReactDOMRoot', () => {
it('warns when passing legacy container to createRoot()', () => { it('warns when passing legacy container to createRoot()', () => {
ReactDOM.render(<div>Hi</div>, container); ReactDOM.render(<div>Hi</div>, container);
expect(() => { expect(() => {
ReactDOM.unstable_createRoot(container); ReactDOM.createRoot(container);
}).toErrorDev( }).toErrorDev(
'You are calling ReactDOM.createRoot() on a container that was previously ' + 'You are calling ReactDOM.createRoot() on a container that was previously ' +
'passed to ReactDOM.render(). This is not supported.', 'passed to ReactDOM.render(). This is not supported.',
@ -271,9 +264,9 @@ describe('ReactDOMRoot', () => {
}); });
it('warns when creating two roots managing the same container', () => { it('warns when creating two roots managing the same container', () => {
ReactDOM.unstable_createRoot(container); ReactDOM.createRoot(container);
expect(() => { expect(() => {
ReactDOM.unstable_createRoot(container); ReactDOM.createRoot(container);
}).toErrorDev( }).toErrorDev(
'You are calling ReactDOM.createRoot() on a container that ' + 'You are calling ReactDOM.createRoot() on a container that ' +
'has already been passed to createRoot() before. Instead, call ' + 'has already been passed to createRoot() before. Instead, call ' +
@ -283,15 +276,15 @@ describe('ReactDOMRoot', () => {
}); });
it('does not warn when creating second root after first one is unmounted', () => { it('does not warn when creating second root after first one is unmounted', () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.unmount(); root.unmount();
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
ReactDOM.unstable_createRoot(container); // No warning ReactDOM.createRoot(container); // No warning
}); });
it('warns if creating a root on the document.body', async () => { it('warns if creating a root on the document.body', async () => {
expect(() => { expect(() => {
ReactDOM.unstable_createRoot(document.body); ReactDOM.createRoot(document.body);
}).toErrorDev( }).toErrorDev(
'createRoot(): Creating roots directly with document.body is ' + 'createRoot(): Creating roots directly with document.body is ' +
'discouraged, since its children are often manipulated by third-party ' + 'discouraged, since its children are often manipulated by third-party ' +
@ -303,7 +296,7 @@ describe('ReactDOMRoot', () => {
}); });
it('warns if updating a root that has had its contents removed', async () => { it('warns if updating a root that has had its contents removed', async () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<div>Hi</div>); root.render(<div>Hi</div>);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
container.innerHTML = ''; container.innerHTML = '';
@ -319,9 +312,8 @@ describe('ReactDOMRoot', () => {
); );
}); });
// @gate experimental
it('opts-in to concurrent default updates', async () => { it('opts-in to concurrent default updates', async () => {
const root = ReactDOM.unstable_createRoot(container, { const root = ReactDOM.createRoot(container, {
unstable_concurrentUpdatesByDefault: true, unstable_concurrentUpdatesByDefault: true,
}); });

View File

@ -895,7 +895,6 @@ describe('ReactDOMServerHooks', () => {
}); });
describe('useOpaqueIdentifier', () => { describe('useOpaqueIdentifier', () => {
// @gate experimental
it('generates unique ids for server string render', async () => { it('generates unique ids for server string render', async () => {
function App(props) { function App(props) {
const idOne = useOpaqueIdentifier(); const idOne = useOpaqueIdentifier();
@ -929,7 +928,6 @@ describe('ReactDOMServerHooks', () => {
).not.toBeNull(); ).not.toBeNull();
}); });
// @gate experimental
it('generates unique ids for server stream render', async () => { it('generates unique ids for server stream render', async () => {
function App(props) { function App(props) {
const idOne = useOpaqueIdentifier(); const idOne = useOpaqueIdentifier();
@ -963,7 +961,6 @@ describe('ReactDOMServerHooks', () => {
).not.toBeNull(); ).not.toBeNull();
}); });
// @gate experimental
it('generates unique ids for client render', async () => { it('generates unique ids for client render', async () => {
function App(props) { function App(props) {
const idOne = useOpaqueIdentifier(); const idOne = useOpaqueIdentifier();
@ -997,7 +994,6 @@ describe('ReactDOMServerHooks', () => {
).not.toBeNull(); ).not.toBeNull();
}); });
// @gate experimental
it('generates unique ids for client render on good server markup', async () => { it('generates unique ids for client render on good server markup', async () => {
function App(props) { function App(props) {
const idOne = useOpaqueIdentifier(); const idOne = useOpaqueIdentifier();
@ -1031,7 +1027,6 @@ describe('ReactDOMServerHooks', () => {
).not.toBeNull(); ).not.toBeNull();
}); });
// @gate experimental
it('useOpaqueIdentifier does not change id even if the component updates during client render', async () => { it('useOpaqueIdentifier does not change id even if the component updates during client render', async () => {
let _setShowId; let _setShowId;
function App() { function App() {
@ -1063,7 +1058,6 @@ describe('ReactDOMServerHooks', () => {
); );
}); });
// @gate experimental
it('useOpaqueIdentifier identifierPrefix works for server renderer and does not clash', async () => { it('useOpaqueIdentifier identifierPrefix works for server renderer and does not clash', async () => {
function ChildTwo({id}) { function ChildTwo({id}) {
return <div id={id}>Child Three</div>; return <div id={id}>Child Three</div>;
@ -1149,7 +1143,6 @@ describe('ReactDOMServerHooks', () => {
).toBe(true); ).toBe(true);
}); });
// @gate experimental
it('useOpaqueIdentifier identifierPrefix works for multiple reads on a streaming server renderer', async () => { it('useOpaqueIdentifier identifierPrefix works for multiple reads on a streaming server renderer', async () => {
function ChildTwo() { function ChildTwo() {
const id = useOpaqueIdentifier(); const id = useOpaqueIdentifier();
@ -1241,7 +1234,6 @@ describe('ReactDOMServerHooks', () => {
await Promise.all([streamOneIsDone, streamTwoIsDone]); await Promise.all([streamOneIsDone, streamTwoIsDone]);
}); });
// @gate experimental
it('useOpaqueIdentifier: IDs match when, after hydration, a new component that uses the ID is rendered', async () => { it('useOpaqueIdentifier: IDs match when, after hydration, a new component that uses the ID is rendered', async () => {
let _setShowDiv; let _setShowDiv;
function App() { function App() {
@ -1261,7 +1253,7 @@ describe('ReactDOMServerHooks', () => {
document.body.append(container); document.body.append(container);
container.innerHTML = ReactDOMServer.renderToString(<App />); container.innerHTML = ReactDOMServer.renderToString(<App />);
const root = ReactDOM.unstable_createRoot(container, {hydrate: true}); const root = ReactDOM.createRoot(container, {hydrate: true});
root.render(<App />); root.render(<App />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
jest.runAllTimers(); jest.runAllTimers();
@ -1285,7 +1277,6 @@ describe('ReactDOMServerHooks', () => {
).not.toBeNull(); ).not.toBeNull();
}); });
// @gate experimental
it('useOpaqueIdentifier: IDs match when, after hydration, a new component that uses the ID is rendered for legacy', async () => { it('useOpaqueIdentifier: IDs match when, after hydration, a new component that uses the ID is rendered for legacy', async () => {
let _setShowDiv; let _setShowDiv;
function App() { function App() {
@ -1326,7 +1317,6 @@ describe('ReactDOMServerHooks', () => {
).not.toBeNull(); ).not.toBeNull();
}); });
// @gate experimental
it('useOpaqueIdentifier: ID is not used during hydration but is used in an update', async () => { it('useOpaqueIdentifier: ID is not used during hydration but is used in an update', async () => {
let _setShow; let _setShow;
function App({unused}) { function App({unused}) {
@ -1344,7 +1334,7 @@ describe('ReactDOMServerHooks', () => {
const container = document.createElement('div'); const container = document.createElement('div');
document.body.append(container); document.body.append(container);
container.innerHTML = ReactDOMServer.renderToString(<App />); container.innerHTML = ReactDOMServer.renderToString(<App />);
const root = ReactDOM.unstable_createRoot(container, {hydrate: true}); const root = ReactDOM.createRoot(container, {hydrate: true});
act(() => { act(() => {
root.render(<App />); root.render(<App />);
}); });
@ -1359,7 +1349,6 @@ describe('ReactDOMServerHooks', () => {
).not.toBeNull(); ).not.toBeNull();
}); });
// @gate experimental
it('useOpaqueIdentifier: ID is not used during hydration but is used in an update in legacy', async () => { it('useOpaqueIdentifier: ID is not used during hydration but is used in an update in legacy', async () => {
let _setShow; let _setShow;
function App({unused}) { function App({unused}) {
@ -1389,7 +1378,6 @@ describe('ReactDOMServerHooks', () => {
).not.toBeNull(); ).not.toBeNull();
}); });
// @gate experimental
it('useOpaqueIdentifier: flushSync', async () => { it('useOpaqueIdentifier: flushSync', async () => {
let _setShow; let _setShow;
function App() { function App() {
@ -1406,7 +1394,7 @@ describe('ReactDOMServerHooks', () => {
const container = document.createElement('div'); const container = document.createElement('div');
document.body.append(container); document.body.append(container);
container.innerHTML = ReactDOMServer.renderToString(<App />); container.innerHTML = ReactDOMServer.renderToString(<App />);
const root = ReactDOM.unstable_createRoot(container, {hydrate: true}); const root = ReactDOM.createRoot(container, {hydrate: true});
act(() => { act(() => {
root.render(<App />); root.render(<App />);
}); });
@ -1422,7 +1410,6 @@ describe('ReactDOMServerHooks', () => {
).not.toBeNull(); ).not.toBeNull();
}); });
// @gate experimental
it('useOpaqueIdentifier: children with id hydrates before other children if ID updates', async () => { it('useOpaqueIdentifier: children with id hydrates before other children if ID updates', async () => {
let _setShow; let _setShow;
@ -1498,7 +1485,7 @@ describe('ReactDOMServerHooks', () => {
.getAttribute('id'); .getAttribute('id');
expect(serverId).not.toBeNull(); expect(serverId).not.toBeNull();
const root = ReactDOM.unstable_createRoot(container, {hydrate: true}); const root = ReactDOM.createRoot(container, {hydrate: true});
root.render(<App show={false} />); root.render(<App show={false} />);
expect(Scheduler).toHaveYielded([]); expect(Scheduler).toHaveYielded([]);
@ -1546,7 +1533,6 @@ describe('ReactDOMServerHooks', () => {
expect(Scheduler).toHaveYielded([]); expect(Scheduler).toHaveYielded([]);
}); });
// @gate experimental
it('useOpaqueIdentifier: IDs match when part of the DOM tree is server rendered and part is client rendered', async () => { it('useOpaqueIdentifier: IDs match when part of the DOM tree is server rendered and part is client rendered', async () => {
let suspend = true; let suspend = true;
let resolve; let resolve;
@ -1591,7 +1577,7 @@ describe('ReactDOMServerHooks', () => {
container.innerHTML = ReactDOMServer.renderToString(<App />); container.innerHTML = ReactDOMServer.renderToString(<App />);
suspend = true; suspend = true;
const root = ReactDOM.unstable_createRoot(container, {hydrate: true}); const root = ReactDOM.createRoot(container, {hydrate: true});
await act(async () => { await act(async () => {
root.render(<App />); root.render(<App />);
}); });
@ -1627,7 +1613,6 @@ describe('ReactDOMServerHooks', () => {
).not.toBeNull(); ).not.toBeNull();
}); });
// @gate experimental
it('useOpaqueIdentifier warn when there is a hydration error', async () => { it('useOpaqueIdentifier warn when there is a hydration error', async () => {
function Child({appId}) { function Child({appId}) {
return <div aria-labelledby={appId} />; return <div aria-labelledby={appId} />;
@ -1642,7 +1627,7 @@ describe('ReactDOMServerHooks', () => {
// This is the wrong HTML string // This is the wrong HTML string
container.innerHTML = '<span></span>'; container.innerHTML = '<span></span>';
ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />); ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
expect(() => Scheduler.unstable_flushAll()).toErrorDev( expect(() => Scheduler.unstable_flushAll()).toErrorDev(
[ [
'Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.', 'Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.',
@ -1652,7 +1637,6 @@ describe('ReactDOMServerHooks', () => {
); );
}); });
// @gate experimental
it('useOpaqueIdentifier: IDs match when part of the DOM tree is server rendered and part is client rendered', async () => { it('useOpaqueIdentifier: IDs match when part of the DOM tree is server rendered and part is client rendered', async () => {
let suspend = true; let suspend = true;
@ -1695,7 +1679,7 @@ describe('ReactDOMServerHooks', () => {
container.innerHTML = ReactDOMServer.renderToString(<App />); container.innerHTML = ReactDOMServer.renderToString(<App />);
suspend = false; suspend = false;
const root = ReactDOM.unstable_createRoot(container, {hydrate: true}); const root = ReactDOM.createRoot(container, {hydrate: true});
await act(async () => { await act(async () => {
root.render(<App />); root.render(<App />);
}); });
@ -1717,7 +1701,6 @@ describe('ReactDOMServerHooks', () => {
).not.toBeNull(); ).not.toBeNull();
}); });
// @gate experimental
it('useOpaqueIdentifier warn when there is a hydration error', async () => { it('useOpaqueIdentifier warn when there is a hydration error', async () => {
function Child({appId}) { function Child({appId}) {
return <div aria-labelledby={appId} />; return <div aria-labelledby={appId} />;
@ -1732,7 +1715,7 @@ describe('ReactDOMServerHooks', () => {
// This is the wrong HTML string // This is the wrong HTML string
container.innerHTML = '<span></span>'; container.innerHTML = '<span></span>';
ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />); ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
expect(() => Scheduler.unstable_flushAll()).toErrorDev( expect(() => Scheduler.unstable_flushAll()).toErrorDev(
[ [
'Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.', 'Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.',
@ -1742,7 +1725,6 @@ describe('ReactDOMServerHooks', () => {
); );
}); });
// @gate experimental
it('useOpaqueIdentifier warns when there is a hydration error and we are using ID as a string', async () => { it('useOpaqueIdentifier warns when there is a hydration error and we are using ID as a string', async () => {
function Child({appId}) { function Child({appId}) {
return <div aria-labelledby={appId + ''} />; return <div aria-labelledby={appId + ''} />;
@ -1757,7 +1739,7 @@ describe('ReactDOMServerHooks', () => {
// This is the wrong HTML string // This is the wrong HTML string
container.innerHTML = '<span></span>'; container.innerHTML = '<span></span>';
ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />); ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
expect(() => Scheduler.unstable_flushAll()).toErrorDev( expect(() => Scheduler.unstable_flushAll()).toErrorDev(
[ [
'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.', 'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.',
@ -1767,7 +1749,6 @@ describe('ReactDOMServerHooks', () => {
); );
}); });
// @gate experimental
it('useOpaqueIdentifier warns when there is a hydration error and we are using ID as a string', async () => { it('useOpaqueIdentifier warns when there is a hydration error and we are using ID as a string', async () => {
function Child({appId}) { function Child({appId}) {
return <div aria-labelledby={appId + ''} />; return <div aria-labelledby={appId + ''} />;
@ -1782,7 +1763,7 @@ describe('ReactDOMServerHooks', () => {
// This is the wrong HTML string // This is the wrong HTML string
container.innerHTML = '<span></span>'; container.innerHTML = '<span></span>';
ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />); ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
expect(() => Scheduler.unstable_flushAll()).toErrorDev( expect(() => Scheduler.unstable_flushAll()).toErrorDev(
[ [
'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.', 'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.',
@ -1792,7 +1773,6 @@ describe('ReactDOMServerHooks', () => {
); );
}); });
// @gate experimental
it('useOpaqueIdentifier warns if you try to use the result as a string in a child component', async () => { it('useOpaqueIdentifier warns if you try to use the result as a string in a child component', async () => {
function Child({appId}) { function Child({appId}) {
return <div aria-labelledby={appId + ''} />; return <div aria-labelledby={appId + ''} />;
@ -1806,7 +1786,7 @@ describe('ReactDOMServerHooks', () => {
document.body.appendChild(container); document.body.appendChild(container);
container.innerHTML = ReactDOMServer.renderToString(<App />); container.innerHTML = ReactDOMServer.renderToString(<App />);
ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />); ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
expect(() => Scheduler.unstable_flushAll()).toErrorDev( expect(() => Scheduler.unstable_flushAll()).toErrorDev(
[ [
'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.', 'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.',
@ -1816,7 +1796,6 @@ describe('ReactDOMServerHooks', () => {
); );
}); });
// @gate experimental
it('useOpaqueIdentifier warns if you try to use the result as a string', async () => { it('useOpaqueIdentifier warns if you try to use the result as a string', async () => {
function App() { function App() {
const id = useOpaqueIdentifier(); const id = useOpaqueIdentifier();
@ -1827,7 +1806,7 @@ describe('ReactDOMServerHooks', () => {
document.body.appendChild(container); document.body.appendChild(container);
container.innerHTML = ReactDOMServer.renderToString(<App />); container.innerHTML = ReactDOMServer.renderToString(<App />);
ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />); ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
expect(() => Scheduler.unstable_flushAll()).toErrorDev( expect(() => Scheduler.unstable_flushAll()).toErrorDev(
[ [
'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.', 'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.',
@ -1837,7 +1816,6 @@ describe('ReactDOMServerHooks', () => {
); );
}); });
// @gate experimental
it('useOpaqueIdentifier warns if you try to use the result as a string in a child component wrapped in a Suspense', async () => { it('useOpaqueIdentifier warns if you try to use the result as a string in a child component wrapped in a Suspense', async () => {
function Child({appId}) { function Child({appId}) {
return <div aria-labelledby={appId + ''} />; return <div aria-labelledby={appId + ''} />;
@ -1856,7 +1834,7 @@ describe('ReactDOMServerHooks', () => {
container.innerHTML = ReactDOMServer.renderToString(<App />); container.innerHTML = ReactDOMServer.renderToString(<App />);
ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />); ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
if (gate(flags => flags.deferRenderPhaseUpdateToNextBatch)) { if (gate(flags => flags.deferRenderPhaseUpdateToNextBatch)) {
expect(() => Scheduler.unstable_flushAll()).toErrorDev([ expect(() => Scheduler.unstable_flushAll()).toErrorDev([
@ -1878,7 +1856,6 @@ describe('ReactDOMServerHooks', () => {
} }
}); });
// @gate experimental
it('useOpaqueIdentifier warns if you try to add the result as a number in a child component wrapped in a Suspense', async () => { it('useOpaqueIdentifier warns if you try to add the result as a number in a child component wrapped in a Suspense', async () => {
function Child({appId}) { function Child({appId}) {
return <div aria-labelledby={+appId} />; return <div aria-labelledby={+appId} />;
@ -1899,7 +1876,7 @@ describe('ReactDOMServerHooks', () => {
container.innerHTML = ReactDOMServer.renderToString(<App />); container.innerHTML = ReactDOMServer.renderToString(<App />);
ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />); ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
if (gate(flags => flags.deferRenderPhaseUpdateToNextBatch)) { if (gate(flags => flags.deferRenderPhaseUpdateToNextBatch)) {
expect(() => Scheduler.unstable_flushAll()).toErrorDev([ expect(() => Scheduler.unstable_flushAll()).toErrorDev([
@ -1921,7 +1898,6 @@ describe('ReactDOMServerHooks', () => {
} }
}); });
// @gate experimental
it('useOpaqueIdentifier with two opaque identifiers on the same page', () => { it('useOpaqueIdentifier with two opaque identifiers on the same page', () => {
let _setShow; let _setShow;
@ -1960,7 +1936,7 @@ describe('ReactDOMServerHooks', () => {
.getAttribute('aria-labelledby'), .getAttribute('aria-labelledby'),
).toEqual(serverID); ).toEqual(serverID);
ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />); ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
jest.runAllTimers(); jest.runAllTimers();
expect(Scheduler).toHaveYielded([]); expect(Scheduler).toHaveYielded([]);
expect(Scheduler).toFlushAndYield([]); expect(Scheduler).toFlushAndYield([]);

View File

@ -102,7 +102,6 @@ describe('ReactDOMServerPartialHydration', () => {
); );
} }
// @gate experimental
it('hydrates a parent even if a child Suspense boundary is blocked', async () => { it('hydrates a parent even if a child Suspense boundary is blocked', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -161,7 +160,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(ref.current).toBe(span); expect(ref.current).toBe(span);
}); });
// @gate experimental
it('calls the hydration callbacks after hydration or deletion', async () => { it('calls the hydration callbacks after hydration or deletion', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -252,7 +250,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(deleted.length).toBe(1); expect(deleted.length).toBe(1);
}); });
// @gate experimental
it('calls the onDeleted hydration callback if the parent gets deleted', async () => { it('calls the onDeleted hydration callback if the parent gets deleted', async () => {
let suspend = false; let suspend = false;
const promise = new Promise(() => {}); const promise = new Promise(() => {});
@ -310,7 +307,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(deleted.length).toBe(1); expect(deleted.length).toBe(1);
}); });
// @gate experimental || www
it('warns and replaces the boundary content in legacy mode', async () => { it('warns and replaces the boundary content in legacy mode', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -390,7 +386,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(container.textContent).toBe('Hello'); expect(container.textContent).toBe('Hello');
}); });
// @gate experimental
it('can insert siblings before the dehydrated boundary', () => { it('can insert siblings before the dehydrated boundary', () => {
let suspend = false; let suspend = false;
const promise = new Promise(() => {}); const promise = new Promise(() => {});
@ -449,7 +444,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(container.firstChild.firstChild.textContent).toBe('First'); expect(container.firstChild.firstChild.textContent).toBe('First');
}); });
// @gate experimental
it('can delete the dehydrated boundary before it is hydrated', () => { it('can delete the dehydrated boundary before it is hydrated', () => {
let suspend = false; let suspend = false;
const promise = new Promise(() => {}); const promise = new Promise(() => {});
@ -506,7 +500,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(container.firstChild.children[1].textContent).toBe('After'); expect(container.firstChild.children[1].textContent).toBe('After');
}); });
// @gate experimental
it('blocks updates to hydrate the content first if props have changed', async () => { it('blocks updates to hydrate the content first if props have changed', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -652,7 +645,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(span.className).toBe('hi'); expect(span.className).toBe('hi');
}); });
// @gate experimental
it('shows the fallback if props have changed before hydration completes and is still suspended', async () => { it('shows the fallback if props have changed before hydration completes and is still suspended', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -722,7 +714,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(container.textContent).toBe('Hi'); expect(container.textContent).toBe('Hi');
}); });
// @gate experimental
it('shows the fallback of the outer if fallback is missing', async () => { it('shows the fallback of the outer if fallback is missing', async () => {
// This is the same exact test as above but with a nested Suspense without a fallback. // This is the same exact test as above but with a nested Suspense without a fallback.
// This should be a noop. // This should be a noop.
@ -796,7 +787,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(container.textContent).toBe('Hi'); expect(container.textContent).toBe('Hi');
}); });
// @gate experimental
it('clears nested suspense boundaries if they did not hydrate yet', async () => { it('clears nested suspense boundaries if they did not hydrate yet', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -869,7 +859,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(container.textContent).toBe('Hi Hi'); expect(container.textContent).toBe('Hi Hi');
}); });
// @gate experimental
it('hydrates first if props changed but we are able to resolve within a timeout', async () => { it('hydrates first if props changed but we are able to resolve within a timeout', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -917,9 +906,7 @@ describe('ReactDOMServerPartialHydration', () => {
expect(container.textContent).toBe('Hello'); expect(container.textContent).toBe('Hello');
// Render an update with a long timeout. // Render an update with a long timeout.
React.unstable_startTransition(() => React.startTransition(() => root.render(<App text="Hi" className="hi" />));
root.render(<App text="Hi" className="hi" />),
);
// This shouldn't force the fallback yet. // This shouldn't force the fallback yet.
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
@ -949,7 +936,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(span.className).toBe('hi'); expect(span.className).toBe('hi');
}); });
// @gate experimental
it('warns but works if setState is called before commit in a dehydrated component', async () => { it('warns but works if setState is called before commit in a dehydrated component', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -1018,7 +1004,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(container.textContent).toBe('Hello'); expect(container.textContent).toBe('Hello');
}); });
// @gate experimental
it('blocks the update to hydrate first if context has changed', async () => { it('blocks the update to hydrate first if context has changed', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -1103,7 +1088,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(span.className).toBe('hi'); expect(span.className).toBe('hi');
}); });
// @gate experimental
it('shows the fallback if context has changed before hydration completes and is still suspended', async () => { it('shows the fallback if context has changed before hydration completes and is still suspended', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -1187,7 +1171,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(container.textContent).toBe('Hi'); expect(container.textContent).toBe('Hi');
}); });
// @gate experimental
it('replaces the fallback with client content if it is not rendered by the server', async () => { it('replaces the fallback with client content if it is not rendered by the server', async () => {
let suspend = false; let suspend = false;
const promise = new Promise(resolvePromise => {}); const promise = new Promise(resolvePromise => {});
@ -1236,7 +1219,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(ref.current).toBe(span); expect(ref.current).toBe(span);
}); });
// @gate experimental
it('replaces the fallback within the suspended time if there is a nested suspense', async () => { it('replaces the fallback within the suspended time if there is a nested suspense', async () => {
let suspend = false; let suspend = false;
const promise = new Promise(resolvePromise => {}); const promise = new Promise(resolvePromise => {});
@ -1296,7 +1278,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(ref.current).toBe(span); expect(ref.current).toBe(span);
}); });
// @gate experimental
it('replaces the fallback within the suspended time if there is a nested suspense in a nested suspense', async () => { it('replaces the fallback within the suspended time if there is a nested suspense in a nested suspense', async () => {
let suspend = false; let suspend = false;
const promise = new Promise(resolvePromise => {}); const promise = new Promise(resolvePromise => {});
@ -1358,7 +1339,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(ref.current).toBe(span); expect(ref.current).toBe(span);
}); });
// @gate experimental
it('shows inserted items in a SuspenseList before content is hydrated', async () => { it('shows inserted items in a SuspenseList before content is hydrated', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -1444,7 +1424,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(ref.current).toBe(spanB); expect(ref.current).toBe(spanB);
}); });
// @gate experimental
it('shows is able to hydrate boundaries even if others in a list are pending', async () => { it('shows is able to hydrate boundaries even if others in a list are pending', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -1591,7 +1570,7 @@ describe('ReactDOMServerPartialHydration', () => {
await act(async () => { await act(async () => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<App />); root.render(<App />);
}); });
@ -1622,7 +1601,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(ref.current).toBe(b); expect(ref.current).toBe(b);
}); });
// @gate experimental
it('clears server boundaries when SuspenseList suspends last row hydrating', async () => { it('clears server boundaries when SuspenseList suspends last row hydrating', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -1679,7 +1657,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(container.textContent).toBe('AB'); expect(container.textContent).toBe('AB');
}); });
// @gate experimental
it('can client render nested boundaries', async () => { it('can client render nested boundaries', async () => {
let suspend = false; let suspend = false;
const promise = new Promise(() => {}); const promise = new Promise(() => {});
@ -1734,7 +1711,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(container.lastChild.data).toBe('unrelated comment'); expect(container.lastChild.data).toBe('unrelated comment');
}); });
// @gate experimental
it('can hydrate TWO suspense boundaries', async () => { it('can hydrate TWO suspense boundaries', async () => {
const ref1 = React.createRef(); const ref1 = React.createRef();
const ref2 = React.createRef(); const ref2 = React.createRef();
@ -1774,7 +1750,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(ref2.current).toBe(span2); expect(ref2.current).toBe(span2);
}); });
// @gate experimental
it('regenerates if it cannot hydrate before changes to props/context expire', async () => { it('regenerates if it cannot hydrate before changes to props/context expire', async () => {
let suspend = false; let suspend = false;
const promise = new Promise(resolvePromise => {}); const promise = new Promise(resolvePromise => {});
@ -1856,7 +1831,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(newSpan.className).toBe('hi'); expect(newSpan.className).toBe('hi');
}); });
// @gate experimental
it('does not invoke an event on a hydrated node until it commits', async () => { it('does not invoke an event on a hydrated node until it commits', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -2022,7 +1996,6 @@ describe('ReactDOMServerPartialHydration', () => {
document.body.removeChild(container); document.body.removeChild(container);
}); });
// @gate experimental
it('invokes discrete events on nested suspense boundaries in a root (legacy system)', async () => { it('invokes discrete events on nested suspense boundaries in a root (legacy system)', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -2190,7 +2163,6 @@ describe('ReactDOMServerPartialHydration', () => {
document.body.removeChild(container); document.body.removeChild(container);
}); });
// @gate experimental
it('does not invoke the parent of dehydrated boundary event', async () => { it('does not invoke the parent of dehydrated boundary event', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -2266,7 +2238,6 @@ describe('ReactDOMServerPartialHydration', () => {
document.body.removeChild(container); document.body.removeChild(container);
}); });
// @gate experimental
it('does not invoke an event on a parent tree when a subtree is dehydrated', async () => { it('does not invoke an event on a parent tree when a subtree is dehydrated', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -2345,7 +2316,6 @@ describe('ReactDOMServerPartialHydration', () => {
document.body.removeChild(parentContainer); document.body.removeChild(parentContainer);
}); });
// @gate experimental
it('blocks only on the last continuous event (legacy system)', async () => { it('blocks only on the last continuous event (legacy system)', async () => {
let suspend1 = false; let suspend1 = false;
let resolve1; let resolve1;
@ -2450,7 +2420,6 @@ describe('ReactDOMServerPartialHydration', () => {
document.body.removeChild(container); document.body.removeChild(container);
}); });
// @gate experimental
it('finishes normal pri work before continuing to hydrate a retry', async () => { it('finishes normal pri work before continuing to hydrate a retry', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -2532,7 +2501,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(ref.current).not.toBe(null); expect(ref.current).not.toBe(null);
}); });
// @gate experimental
it('regression test: does not overfire non-bubbling browser events', async () => { it('regression test: does not overfire non-bubbling browser events', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -2623,7 +2591,6 @@ describe('ReactDOMServerPartialHydration', () => {
// follow up. // follow up.
// //
// @gate FIXME // @gate FIXME
// @gate experimental
it('hydrates a hidden subtree outside of a Suspense boundary', async () => { it('hydrates a hidden subtree outside of a Suspense boundary', async () => {
const ref = React.createRef(); const ref = React.createRef();

View File

@ -126,7 +126,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
IdleEventPriority = require('react-reconciler/constants').IdleEventPriority; IdleEventPriority = require('react-reconciler/constants').IdleEventPriority;
}); });
// @gate experimental
it('hydrates the target boundary synchronously during a click', async () => { it('hydrates the target boundary synchronously during a click', async () => {
function Child({text}) { function Child({text}) {
Scheduler.unstable_yieldValue(text); Scheduler.unstable_yieldValue(text);
@ -189,7 +188,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
document.body.removeChild(container); document.body.removeChild(container);
}); });
// @gate experimental
it('hydrates at higher pri if sync did not work first time', async () => { it('hydrates at higher pri if sync did not work first time', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -277,7 +275,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
document.body.removeChild(container); document.body.removeChild(container);
}); });
// @gate experimental
it('hydrates at higher pri for secondary discrete events', async () => { it('hydrates at higher pri for secondary discrete events', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -628,7 +625,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
document.body.removeChild(container); document.body.removeChild(container);
}); });
// @gate experimental
it('hydrates the hovered targets as higher priority for continuous events', async () => { it('hydrates the hovered targets as higher priority for continuous events', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -731,7 +727,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
document.body.removeChild(container); document.body.removeChild(container);
}); });
// @gate experimental
it('hydrates the last target path first for continuous events', async () => { it('hydrates the last target path first for continuous events', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;

View File

@ -93,7 +93,6 @@ describe('ReactDOMServerSuspense', () => {
: children; : children;
} }
// @gate experimental || www
it('should render the children when no promise is thrown', async () => { it('should render the children when no promise is thrown', async () => {
const c = await serverRender( const c = await serverRender(
<div> <div>
@ -105,7 +104,6 @@ describe('ReactDOMServerSuspense', () => {
expect(getVisibleChildren(c)).toEqual(<div>Children</div>); expect(getVisibleChildren(c)).toEqual(<div>Children</div>);
}); });
// @gate experimental || www
it('should render the fallback when a promise thrown', async () => { it('should render the fallback when a promise thrown', async () => {
const c = await serverRender( const c = await serverRender(
<div> <div>
@ -117,7 +115,6 @@ describe('ReactDOMServerSuspense', () => {
expect(getVisibleChildren(c)).toEqual(<div>Fallback</div>); expect(getVisibleChildren(c)).toEqual(<div>Fallback</div>);
}); });
// @gate experimental || www
it('should work with nested suspense components', async () => { it('should work with nested suspense components', async () => {
const c = await serverRender( const c = await serverRender(
<div> <div>
@ -140,7 +137,6 @@ describe('ReactDOMServerSuspense', () => {
); );
}); });
// @gate experimental
it('server renders a SuspenseList component and its children', async () => { it('server renders a SuspenseList component and its children', async () => {
const example = ( const example = (
<React.SuspenseList> <React.SuspenseList>

View File

@ -492,12 +492,11 @@ describe('ReactDOMServerHydration', () => {
expect(element.textContent).toBe('Hello world'); expect(element.textContent).toBe('Hello world');
}); });
// @gate experimental
it('does not re-enter hydration after committing the first one', () => { it('does not re-enter hydration after committing the first one', () => {
const finalHTML = ReactDOMServer.renderToString(<div />); const finalHTML = ReactDOMServer.renderToString(<div />);
const container = document.createElement('div'); const container = document.createElement('div');
container.innerHTML = finalHTML; container.innerHTML = finalHTML;
const root = ReactDOM.unstable_createRoot(container, {hydrate: true}); const root = ReactDOM.createRoot(container, {hydrate: true});
root.render(<div />); root.render(<div />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
root.render(null); root.render(null);

View File

@ -29,7 +29,7 @@ describe('ReactTestUtils.act()', () => {
if (__EXPERIMENTAL__) { if (__EXPERIMENTAL__) {
let concurrentRoot = null; let concurrentRoot = null;
const renderConcurrent = (el, dom) => { const renderConcurrent = (el, dom) => {
concurrentRoot = ReactDOM.unstable_createRoot(dom); concurrentRoot = ReactDOM.createRoot(dom);
concurrentRoot.render(el); concurrentRoot.render(el);
}; };
@ -96,20 +96,17 @@ describe('ReactTestUtils.act()', () => {
]); ]);
}); });
// @gate experimental
it('does not warn in concurrent mode', () => { it('does not warn in concurrent mode', () => {
const root = ReactDOM.unstable_createRoot(document.createElement('div')); const root = ReactDOM.createRoot(document.createElement('div'));
root.render(<App />); root.render(<App />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
}); });
// @gate experimental
it('warns in concurrent mode if root is strict', () => { it('warns in concurrent mode if root is strict', () => {
expect(() => { expect(() => {
const root = ReactDOM.unstable_createRoot( const root = ReactDOM.createRoot(document.createElement('div'), {
document.createElement('div'), unstable_strictMode: true,
{unstable_strictMode: true}, });
);
root.render(<App />); root.render(<App />);
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
}).toErrorDev([ }).toErrorDev([
@ -665,7 +662,7 @@ function runActTests(label, render, unmount, rerender) {
expect(document.querySelector('[data-test-id=spinner]')).toBeNull(); expect(document.querySelector('[data-test-id=spinner]')).toBeNull();
// trigger a suspendy update with a delay // trigger a suspendy update with a delay
React.unstable_startTransition(() => { React.startTransition(() => {
act(() => { act(() => {
rerender(<App suspend={true} />); rerender(<App suspend={true} />);
}); });

View File

@ -29,10 +29,9 @@ it('does not warn when rendering in legacy mode', () => {
}).toErrorDev([]); }).toErrorDev([]);
}); });
// @gate experimental
it('should warn when rendering in concurrent mode', () => { it('should warn when rendering in concurrent mode', () => {
expect(() => { expect(() => {
ReactDOM.unstable_createRoot(document.createElement('div')).render(<App />); ReactDOM.createRoot(document.createElement('div')).render(<App />);
}).toErrorDev( }).toErrorDev(
'In Concurrent or Sync modes, the "scheduler" module needs to be mocked ' + 'In Concurrent or Sync modes, the "scheduler" module needs to be mocked ' +
'to guarantee consistent behaviour across tests and browsers.', 'to guarantee consistent behaviour across tests and browsers.',
@ -40,6 +39,6 @@ it('should warn when rendering in concurrent mode', () => {
); );
// does not warn twice // does not warn twice
expect(() => { expect(() => {
ReactDOM.unstable_createRoot(document.createElement('div')).render(<App />); ReactDOM.createRoot(document.createElement('div')).render(<App />);
}).toErrorDev([]); }).toErrorDev([]);
}); });

View File

@ -1332,7 +1332,7 @@ describe('ReactUpdates', () => {
); );
} }
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
let hiddenDiv; let hiddenDiv;
act(() => { act(() => {
root.render(<Foo />); root.render(<Foo />);

View File

@ -22,7 +22,7 @@ beforeEach(() => {
Scheduler = require('scheduler'); Scheduler = require('scheduler');
Suspense = React.Suspense; Suspense = React.Suspense;
SuspenseList = React.unstable_SuspenseList; SuspenseList = React.SuspenseList;
getCacheForType = React.unstable_getCacheForType; getCacheForType = React.unstable_getCacheForType;

View File

@ -78,7 +78,6 @@ setAttemptHydrationAtCurrentPriority(attemptHydrationAtCurrentPriority);
setGetCurrentUpdatePriority(getCurrentUpdatePriority); setGetCurrentUpdatePriority(getCurrentUpdatePriority);
setAttemptHydrationAtPriority(runWithPriority); setAttemptHydrationAtPriority(runWithPriority);
let didWarnAboutUnstableCreatePortal = false;
let didWarnAboutUnstableRenderSubtreeIntoContainer = false; let didWarnAboutUnstableRenderSubtreeIntoContainer = false;
if (__DEV__) { if (__DEV__) {
@ -155,25 +154,6 @@ function renderSubtreeIntoContainer(
); );
} }
function unstable_createPortal(
children: ReactNodeList,
container: Container,
key: ?string = null,
) {
if (__DEV__) {
if (!didWarnAboutUnstableCreatePortal) {
didWarnAboutUnstableCreatePortal = true;
console.warn(
'The ReactDOM.unstable_createPortal() alias has been deprecated, ' +
'and will be removed in React 18+. Update your code to use ' +
'ReactDOM.createPortal() instead. It has the exact same API, ' +
'but without the "unstable_" prefix.',
);
}
}
return createPortal(children, container, key);
}
const Internals = { const Internals = {
// Keep in sync with ReactTestUtils.js, and ReactTestUtilsAct.js. // Keep in sync with ReactTestUtils.js, and ReactTestUtilsAct.js.
// This is an array for better minification. // This is an array for better minification.
@ -206,10 +186,6 @@ export {
scheduleHydration as unstable_scheduleHydration, scheduleHydration as unstable_scheduleHydration,
// Disabled behind disableUnstableRenderSubtreeIntoContainer // Disabled behind disableUnstableRenderSubtreeIntoContainer
renderSubtreeIntoContainer as unstable_renderSubtreeIntoContainer, renderSubtreeIntoContainer as unstable_renderSubtreeIntoContainer,
// Disabled behind disableUnstableCreatePortal
// Temporary alias since we already shipped React 16 RC with it.
// TODO: remove in React 18.
unstable_createPortal,
// enableCreateEventHandleAPI // enableCreateEventHandleAPI
createEventHandle as unstable_createEventHandle, createEventHandle as unstable_createEventHandle,
// TODO: Remove this once callers migrate to alternatives. // TODO: Remove this once callers migrate to alternatives.

View File

@ -575,7 +575,6 @@ describe('DOMPluginEventSystem', () => {
expect(log).toEqual(['second', 'first']); expect(log).toEqual(['second', 'first']);
}); });
// @gate experimental
it('does not invoke an event on a parent tree when a subtree is dehydrated', async () => { it('does not invoke an event on a parent tree when a subtree is dehydrated', async () => {
let suspend = false; let suspend = false;
let resolve; let resolve;
@ -1951,7 +1950,7 @@ describe('DOMPluginEventSystem', () => {
// Increase counter // Increase counter
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<Test counter={1} />); root.render(<Test counter={1} />);
}); });
} else { } else {

View File

@ -495,9 +495,8 @@ describe('ChangeEventPlugin', () => {
}); });
describe('concurrent mode', () => { describe('concurrent mode', () => {
// @gate experimental
it('text input', () => { it('text input', () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
let input; let input;
class ControlledInput extends React.Component { class ControlledInput extends React.Component {
@ -538,9 +537,8 @@ describe('ChangeEventPlugin', () => {
expect(input.value).toBe('changed [!]'); expect(input.value).toBe('changed [!]');
}); });
// @gate experimental
it('checkbox input', () => { it('checkbox input', () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
let input; let input;
class ControlledInput extends React.Component { class ControlledInput extends React.Component {
@ -594,9 +592,8 @@ describe('ChangeEventPlugin', () => {
expect(input.checked).toBe(false); expect(input.checked).toBe(false);
}); });
// @gate experimental
it('textarea', () => { it('textarea', () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
let textarea; let textarea;
class ControlledTextarea extends React.Component { class ControlledTextarea extends React.Component {
@ -637,9 +634,8 @@ describe('ChangeEventPlugin', () => {
expect(textarea.value).toBe('changed [!]'); expect(textarea.value).toBe('changed [!]');
}); });
// @gate experimental
it('parent of input', () => { it('parent of input', () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
let input; let input;
class ControlledInput extends React.Component { class ControlledInput extends React.Component {
@ -684,9 +680,8 @@ describe('ChangeEventPlugin', () => {
expect(input.value).toBe('changed [!]'); expect(input.value).toBe('changed [!]');
}); });
// @gate experimental
it('is sync for non-input events', async () => { it('is sync for non-input events', async () => {
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
let input; let input;
class ControlledInput extends React.Component { class ControlledInput extends React.Component {
@ -731,12 +726,11 @@ describe('ChangeEventPlugin', () => {
expect(input.value).toBe(''); expect(input.value).toBe('');
}); });
// @gate experimental
it('mouse enter/leave should be user-blocking but not discrete', async () => { it('mouse enter/leave should be user-blocking but not discrete', async () => {
const {unstable_concurrentAct: act} = TestUtils; const {unstable_concurrentAct: act} = TestUtils;
const {useState} = React; const {useState} = React;
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
const target = React.createRef(null); const target = React.createRef(null);
function Foo() { function Foo() {

View File

@ -240,10 +240,9 @@ describe('SimpleEventPlugin', function() {
act = require('react-dom/test-utils').unstable_concurrentAct; act = require('react-dom/test-utils').unstable_concurrentAct;
}); });
// @gate experimental
it('flushes pending interactive work before exiting event handler', async () => { it('flushes pending interactive work before exiting event handler', async () => {
container = document.createElement('div'); container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
document.body.appendChild(container); document.body.appendChild(container);
let button; let button;
@ -316,10 +315,9 @@ describe('SimpleEventPlugin', function() {
// NOTE: This test was written for the old behavior of discrete updates, // NOTE: This test was written for the old behavior of discrete updates,
// where they would be async, but flushed early if another discrete update // where they would be async, but flushed early if another discrete update
// was dispatched. // was dispatched.
// @gate experimental
it('end result of many interactive updates is deterministic', async () => { it('end result of many interactive updates is deterministic', async () => {
container = document.createElement('div'); container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
document.body.appendChild(container); document.body.appendChild(container);
let button; let button;

View File

@ -23,7 +23,7 @@ export {
Profiler, Profiler,
StrictMode, StrictMode,
Suspense, Suspense,
unstable_SuspenseList, SuspenseList,
isAsyncMode, isAsyncMode,
isConcurrentMode, isConcurrentMode,
isContextConsumer, isContextConsumer,
@ -37,5 +37,5 @@ export {
isProfiler, isProfiler,
isStrictMode, isStrictMode,
isSuspense, isSuspense,
unstable_isSuspenseList, isSuspenseList,
} from './src/ReactIs'; } from './src/ReactIs';

View File

@ -23,6 +23,7 @@ export {
Profiler, Profiler,
StrictMode, StrictMode,
Suspense, Suspense,
SuspenseList,
isAsyncMode, isAsyncMode,
isConcurrentMode, isConcurrentMode,
isContextConsumer, isContextConsumer,
@ -36,4 +37,5 @@ export {
isProfiler, isProfiler,
isStrictMode, isStrictMode,
isSuspense, isSuspense,
isSuspenseList,
} from './src/ReactIs'; } from './src/ReactIs';

View File

@ -72,7 +72,7 @@ export const Portal = REACT_PORTAL_TYPE;
export const Profiler = REACT_PROFILER_TYPE; export const Profiler = REACT_PROFILER_TYPE;
export const StrictMode = REACT_STRICT_MODE_TYPE; export const StrictMode = REACT_STRICT_MODE_TYPE;
export const Suspense = REACT_SUSPENSE_TYPE; export const Suspense = REACT_SUSPENSE_TYPE;
export const unstable_SuspenseList = REACT_SUSPENSE_LIST_TYPE; export const SuspenseList = REACT_SUSPENSE_LIST_TYPE;
export {isValidElementType}; export {isValidElementType};
@ -143,6 +143,6 @@ export function isStrictMode(object: any) {
export function isSuspense(object: any) { export function isSuspense(object: any) {
return typeOf(object) === REACT_SUSPENSE_TYPE; return typeOf(object) === REACT_SUSPENSE_TYPE;
} }
export function unstable_isSuspenseList(object: any) { export function isSuspenseList(object: any) {
return typeOf(object) === REACT_SUSPENSE_LIST_TYPE; return typeOf(object) === REACT_SUSPENSE_LIST_TYPE;
} }

View File

@ -186,22 +186,13 @@ describe('ReactIs', () => {
expect(ReactIs.isSuspense(<div />)).toBe(false); expect(ReactIs.isSuspense(<div />)).toBe(false);
}); });
// @gate experimental
it('should identify suspense list', () => { it('should identify suspense list', () => {
expect(ReactIs.isValidElementType(React.unstable_SuspenseList)).toBe(true); expect(ReactIs.isValidElementType(React.SuspenseList)).toBe(true);
expect(ReactIs.typeOf(<React.unstable_SuspenseList />)).toBe( expect(ReactIs.typeOf(<React.SuspenseList />)).toBe(ReactIs.SuspenseList);
ReactIs.unstable_SuspenseList, expect(ReactIs.isSuspenseList(<React.SuspenseList />)).toBe(true);
); expect(ReactIs.isSuspenseList({type: ReactIs.SuspenseList})).toBe(false);
expect( expect(ReactIs.isSuspenseList('React.SuspenseList')).toBe(false);
ReactIs.unstable_isSuspenseList(<React.unstable_SuspenseList />), expect(ReactIs.isSuspenseList(<div />)).toBe(false);
).toBe(true);
expect(
ReactIs.unstable_isSuspenseList({type: ReactIs.unstable_SuspenseList}),
).toBe(false);
expect(ReactIs.unstable_isSuspenseList('React.unstable_SuspenseList')).toBe(
false,
);
expect(ReactIs.unstable_isSuspenseList(<div />)).toBe(false);
}); });
it('should identify profile root', () => { it('should identify profile root', () => {

View File

@ -22,7 +22,7 @@ describe('ReactCache', () => {
Suspense = React.Suspense; Suspense = React.Suspense;
getCacheForType = React.unstable_getCacheForType; getCacheForType = React.unstable_getCacheForType;
useCacheRefresh = React.unstable_useCacheRefresh; useCacheRefresh = React.unstable_useCacheRefresh;
startTransition = React.unstable_startTransition; startTransition = React.startTransition;
useState = React.useState; useState = React.useState;
caches = []; caches = [];

View File

@ -19,7 +19,7 @@ describe('ReactLazyContextPropagation', () => {
useState = React.useState; useState = React.useState;
useContext = React.useContext; useContext = React.useContext;
Suspense = React.Suspense; Suspense = React.Suspense;
SuspenseList = React.unstable_SuspenseList; SuspenseList = React.SuspenseList;
getCacheForType = React.unstable_getCacheForType; getCacheForType = React.unstable_getCacheForType;
@ -649,8 +649,6 @@ describe('ReactLazyContextPropagation', () => {
expect(root).toMatchRenderedOutput('BBB'); expect(root).toMatchRenderedOutput('BBB');
}); });
// @gate enableCache
// @gate experimental
test('contexts are propagated through SuspenseList', async () => { test('contexts are propagated through SuspenseList', async () => {
// This kinda tests an implementation detail. SuspenseList has an early // This kinda tests an implementation detail. SuspenseList has an early
// bailout that doesn't use `bailoutOnAlreadyFinishedWork`. It probably // bailout that doesn't use `bailoutOnAlreadyFinishedWork`. It probably

View File

@ -45,7 +45,6 @@ describe('ReactSuspenseList', () => {
return Component; return Component;
} }
// @gate experimental || !enableSyncDefaultUpdates
it('appends rendering tasks to the end of the priority queue', async () => { it('appends rendering tasks to the end of the priority queue', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -65,7 +64,7 @@ describe('ReactSuspenseList', () => {
expect(Scheduler).toFlushAndYield([]); expect(Scheduler).toFlushAndYield([]);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<App show={true} />); root.render(<App show={true} />);
}); });
} else { } else {

View File

@ -25,7 +25,7 @@ describe('ReactExpiration', () => {
React = require('react'); React = require('react');
ReactNoop = require('react-noop-renderer'); ReactNoop = require('react-noop-renderer');
Scheduler = require('scheduler'); Scheduler = require('scheduler');
startTransition = React.unstable_startTransition; startTransition = React.startTransition;
useState = React.useState; useState = React.useState;
useEffect = React.useEffect; useEffect = React.useEffect;
@ -115,10 +115,10 @@ describe('ReactExpiration', () => {
// Flush the sync task. // Flush the sync task.
ReactNoop.flushSync(); ReactNoop.flushSync();
} }
// @gate experimental || !enableSyncDefaultUpdates
it('increases priority of updates as time progresses', () => { it('increases priority of updates as time progresses', () => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<span prop="done" />); ReactNoop.render(<span prop="done" />);
}); });
} else { } else {
@ -142,7 +142,6 @@ describe('ReactExpiration', () => {
expect(ReactNoop.getChildren()).toEqual([span('done')]); expect(ReactNoop.getChildren()).toEqual([span('done')]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('two updates of like priority in the same event always flush within the same batch', () => { it('two updates of like priority in the same event always flush within the same batch', () => {
class TextClass extends React.Component { class TextClass extends React.Component {
componentDidMount() { componentDidMount() {
@ -166,7 +165,7 @@ describe('ReactExpiration', () => {
// First, show what happens for updates in two separate events. // First, show what happens for updates in two separate events.
// Schedule an update. // Schedule an update.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<TextClass text="A" />); ReactNoop.render(<TextClass text="A" />);
}); });
} else { } else {
@ -201,7 +200,6 @@ describe('ReactExpiration', () => {
expect(Scheduler).toFlushAndYield(['B [render]', 'B [commit]']); expect(Scheduler).toFlushAndYield(['B [render]', 'B [commit]']);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it( it(
'two updates of like priority in the same event always flush within the ' + 'two updates of like priority in the same event always flush within the ' +
"same batch, even if there's a sync update in between", "same batch, even if there's a sync update in between",
@ -228,7 +226,7 @@ describe('ReactExpiration', () => {
// First, show what happens for updates in two separate events. // First, show what happens for updates in two separate events.
// Schedule an update. // Schedule an update.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<TextClass text="A" />); ReactNoop.render(<TextClass text="A" />);
}); });
} else { } else {
@ -269,7 +267,6 @@ describe('ReactExpiration', () => {
}, },
); );
// @gate experimental || !enableSyncDefaultUpdates
it('cannot update at the same expiration time that is already rendering', () => { it('cannot update at the same expiration time that is already rendering', () => {
const store = {text: 'initial'}; const store = {text: 'initial'};
const subscribers = []; const subscribers = [];
@ -307,7 +304,7 @@ describe('ReactExpiration', () => {
// Initial mount // Initial mount
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<App />); ReactNoop.render(<App />);
}); });
} else { } else {
@ -326,7 +323,7 @@ describe('ReactExpiration', () => {
// Partial update // Partial update
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
subscribers.forEach(s => s.setState({text: '1'})); subscribers.forEach(s => s.setState({text: '1'}));
}); });
} else { } else {
@ -347,7 +344,6 @@ describe('ReactExpiration', () => {
]); ]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('stops yielding if CPU-bound update takes too long to finish', () => { it('stops yielding if CPU-bound update takes too long to finish', () => {
const root = ReactNoop.createRoot(); const root = ReactNoop.createRoot();
function App() { function App() {
@ -363,7 +359,7 @@ describe('ReactExpiration', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<App />); root.render(<App />);
}); });
} else { } else {
@ -381,7 +377,6 @@ describe('ReactExpiration', () => {
expect(root).toMatchRenderedOutput('ABCDE'); expect(root).toMatchRenderedOutput('ABCDE');
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('root expiration is measured from the time of the first update', () => { it('root expiration is measured from the time of the first update', () => {
Scheduler.unstable_advanceTime(10000); Scheduler.unstable_advanceTime(10000);
@ -398,7 +393,7 @@ describe('ReactExpiration', () => {
); );
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<App />); root.render(<App />);
}); });
} else { } else {
@ -416,7 +411,6 @@ describe('ReactExpiration', () => {
expect(root).toMatchRenderedOutput('ABCDE'); expect(root).toMatchRenderedOutput('ABCDE');
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('should measure expiration times relative to module initialization', () => { it('should measure expiration times relative to module initialization', () => {
// Tests an implementation detail where expiration times are computed using // Tests an implementation detail where expiration times are computed using
// bitwise operations. // bitwise operations.
@ -433,7 +427,7 @@ describe('ReactExpiration', () => {
ReactNoop = require('react-noop-renderer'); ReactNoop = require('react-noop-renderer');
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render('Hi'); ReactNoop.render('Hi');
}); });
} else { } else {
@ -453,7 +447,6 @@ describe('ReactExpiration', () => {
expect(ReactNoop).toMatchRenderedOutput('Hi'); expect(ReactNoop).toMatchRenderedOutput('Hi');
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('should measure callback timeout relative to current time, not start-up time', () => { it('should measure callback timeout relative to current time, not start-up time', () => {
// Corresponds to a bugfix: https://github.com/facebook/react/pull/15479 // Corresponds to a bugfix: https://github.com/facebook/react/pull/15479
// The bug wasn't caught by other tests because we use virtual times that // The bug wasn't caught by other tests because we use virtual times that
@ -463,7 +456,7 @@ describe('ReactExpiration', () => {
Scheduler.unstable_advanceTime(10000); Scheduler.unstable_advanceTime(10000);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render('Hi'); ReactNoop.render('Hi');
}); });
} else { } else {
@ -481,7 +474,6 @@ describe('ReactExpiration', () => {
expect(ReactNoop).toMatchRenderedOutput('Hi'); expect(ReactNoop).toMatchRenderedOutput('Hi');
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('prevents starvation by sync updates by disabling time slicing if too much time has elapsed', async () => { it('prevents starvation by sync updates by disabling time slicing if too much time has elapsed', async () => {
let updateSyncPri; let updateSyncPri;
let updateNormalPri; let updateNormalPri;
@ -513,7 +505,7 @@ describe('ReactExpiration', () => {
// First demonstrate what happens when there's no starvation // First demonstrate what happens when there's no starvation
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
updateNormalPri(); updateNormalPri();
}); });
} else { } else {
@ -537,7 +529,7 @@ describe('ReactExpiration', () => {
// Do the same thing, but starve the first update // Do the same thing, but starve the first update
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
updateNormalPri(); updateNormalPri();
}); });
} else { } else {
@ -628,7 +620,6 @@ describe('ReactExpiration', () => {
expect(root).toMatchRenderedOutput('Sync pri: 2, Idle pri: 2'); expect(root).toMatchRenderedOutput('Sync pri: 2, Idle pri: 2');
}); });
// @gate experimental
it('when multiple lanes expire, we can finish the in-progress one without including the others', async () => { it('when multiple lanes expire, we can finish the in-progress one without including the others', async () => {
let setA; let setA;
let setB; let setB;
@ -677,7 +668,6 @@ describe('ReactExpiration', () => {
}); });
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('updates do not expire while they are IO-bound', async () => { it('updates do not expire while they are IO-bound', async () => {
const {Suspense} = React; const {Suspense} = React;
@ -701,7 +691,7 @@ describe('ReactExpiration', () => {
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<App step={1} />); root.render(<App step={1} />);
}); });
} else { } else {
@ -734,7 +724,6 @@ describe('ReactExpiration', () => {
}); });
}); });
// @gate experimental
it('flushSync should not affect expired work', async () => { it('flushSync should not affect expired work', async () => {
let setA; let setA;
let setB; let setB;
@ -778,7 +767,6 @@ describe('ReactExpiration', () => {
}); });
}); });
// @gate experimental
it('passive effects of expired update flush after paint', async () => { it('passive effects of expired update flush after paint', async () => {
function App({step}) { function App({step}) {
useEffect(() => { useEffect(() => {

View File

@ -14,7 +14,7 @@ describe('ReactFlushSync', () => {
Scheduler = require('scheduler'); Scheduler = require('scheduler');
useState = React.useState; useState = React.useState;
useEffect = React.useEffect; useEffect = React.useEffect;
startTransition = React.unstable_startTransition; startTransition = React.startTransition;
}); });
function Text({text}) { function Text({text}) {
@ -22,7 +22,6 @@ describe('ReactFlushSync', () => {
return text; return text;
} }
// @gate experimental || !enableSyncDefaultUpdates
test('changes priority of updates in useEffect', async () => { test('changes priority of updates in useEffect', async () => {
function App() { function App() {
const [syncState, setSyncState] = useState(0); const [syncState, setSyncState] = useState(0);
@ -39,7 +38,7 @@ describe('ReactFlushSync', () => {
const root = ReactNoop.createRoot(); const root = ReactNoop.createRoot();
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<App />); root.render(<App />);
}); });
} else { } else {
@ -64,7 +63,6 @@ describe('ReactFlushSync', () => {
expect(root).toMatchRenderedOutput('1, 1'); expect(root).toMatchRenderedOutput('1, 1');
}); });
// @gate experimental
test('nested with startTransition', async () => { test('nested with startTransition', async () => {
let setSyncState; let setSyncState;
let setState; let setState;

View File

@ -52,8 +52,8 @@ describe('ReactHooksWithNoopRenderer', () => {
useImperativeHandle = React.useImperativeHandle; useImperativeHandle = React.useImperativeHandle;
forwardRef = React.forwardRef; forwardRef = React.forwardRef;
memo = React.memo; memo = React.memo;
useTransition = React.unstable_useTransition; useTransition = React.useTransition;
useDeferredValue = React.unstable_useDeferredValue; useDeferredValue = React.useDeferredValue;
Suspense = React.Suspense; Suspense = React.Suspense;
act = ReactNoop.act; act = ReactNoop.act;
ContinuousEventPriority = require('react-reconciler/constants') ContinuousEventPriority = require('react-reconciler/constants')
@ -149,7 +149,6 @@ describe('ReactHooksWithNoopRenderer', () => {
return Promise.resolve().then(() => {}); return Promise.resolve().then(() => {});
} }
// @gate experimental || !enableSyncDefaultUpdates
it('resumes after an interruption', () => { it('resumes after an interruption', () => {
function Counter(props, ref) { function Counter(props, ref) {
const [count, updateCount] = useState(0); const [count, updateCount] = useState(0);
@ -166,7 +165,7 @@ describe('ReactHooksWithNoopRenderer', () => {
// Schedule some updates // Schedule some updates
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
// TODO: Batched updates need to be inside startTransition? // TODO: Batched updates need to be inside startTransition?
ReactNoop.batchedUpdates(() => { ReactNoop.batchedUpdates(() => {
counter.current.updateCount(1); counter.current.updateCount(1);
@ -691,7 +690,6 @@ describe('ReactHooksWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span(22)]); expect(ReactNoop.getChildren()).toEqual([span(22)]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('discards render phase updates if something suspends', async () => { it('discards render phase updates if something suspends', async () => {
const thenable = {then() {}}; const thenable = {then() {}};
function Foo({signal}) { function Foo({signal}) {
@ -728,7 +726,7 @@ describe('ReactHooksWithNoopRenderer', () => {
expect(root).toMatchRenderedOutput(<span prop={0} />); expect(root).toMatchRenderedOutput(<span prop={0} />);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<Foo signal={false} />); root.render(<Foo signal={false} />);
}); });
} else { } else {
@ -739,7 +737,7 @@ describe('ReactHooksWithNoopRenderer', () => {
// Rendering again should suspend again. // Rendering again should suspend again.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<Foo signal={false} />); root.render(<Foo signal={false} />);
}); });
} else { } else {
@ -748,7 +746,6 @@ describe('ReactHooksWithNoopRenderer', () => {
expect(Scheduler).toFlushAndYield(['Suspend!']); expect(Scheduler).toFlushAndYield(['Suspend!']);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('discards render phase updates if something suspends, but not other updates in the same component', async () => { it('discards render phase updates if something suspends, but not other updates in the same component', async () => {
const thenable = {then() {}}; const thenable = {then() {}};
function Foo({signal}) { function Foo({signal}) {
@ -792,7 +789,7 @@ describe('ReactHooksWithNoopRenderer', () => {
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<Foo signal={false} />); root.render(<Foo signal={false} />);
setLabel('B'); setLabel('B');
}); });
@ -806,7 +803,7 @@ describe('ReactHooksWithNoopRenderer', () => {
// Rendering again should suspend again. // Rendering again should suspend again.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<Foo signal={false} />); root.render(<Foo signal={false} />);
}); });
} else { } else {
@ -817,7 +814,7 @@ describe('ReactHooksWithNoopRenderer', () => {
// Flip the signal back to "cancel" the update. However, the update to // Flip the signal back to "cancel" the update. However, the update to
// label should still proceed. It shouldn't have been dropped. // label should still proceed. It shouldn't have been dropped.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<Foo signal={true} />); root.render(<Foo signal={true} />);
}); });
} else { } else {
@ -864,13 +861,12 @@ describe('ReactHooksWithNoopRenderer', () => {
}); });
// TODO: This should probably warn // TODO: This should probably warn
// @gate experimental
it('calling startTransition inside render phase', async () => { it('calling startTransition inside render phase', async () => {
function App() { function App() {
const [counter, setCounter] = useState(0); const [counter, setCounter] = useState(0);
if (counter === 0) { if (counter === 0) {
React.unstable_startTransition(() => { React.startTransition(() => {
setCounter(c => c + 1); setCounter(c => c + 1);
}); });
} }
@ -1315,7 +1311,6 @@ describe('ReactHooksWithNoopRenderer', () => {
}); });
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('does not warn about state updates for unmounted components with pending passive unmounts for alternates', () => { it('does not warn about state updates for unmounted components with pending passive unmounts for alternates', () => {
let setParentState = null; let setParentState = null;
const setChildStates = []; const setChildStates = [];
@ -1383,7 +1378,7 @@ describe('ReactHooksWithNoopRenderer', () => {
// Schedule another update for children, and partially process it. // Schedule another update for children, and partially process it.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
setChildStates.forEach(setChildState => setChildState(2)); setChildStates.forEach(setChildState => setChildState(2));
}); });
} else { } else {
@ -1685,7 +1680,6 @@ describe('ReactHooksWithNoopRenderer', () => {
}); });
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('updates have async priority even if effects are flushed early', () => { it('updates have async priority even if effects are flushed early', () => {
function Counter(props) { function Counter(props) {
const [count, updateCount] = useState('(empty)'); const [count, updateCount] = useState('(empty)');
@ -1707,7 +1701,7 @@ describe('ReactHooksWithNoopRenderer', () => {
// Rendering again should flush the previous commit's effects // Rendering again should flush the previous commit's effects
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Counter count={1} />, () => ReactNoop.render(<Counter count={1} />, () =>
Scheduler.unstable_yieldValue('Sync effect'), Scheduler.unstable_yieldValue('Sync effect'),
); );
@ -3127,8 +3121,8 @@ describe('ReactHooksWithNoopRenderer', () => {
expect(totalRefUpdates).toBe(2); // Should not increase since last time expect(totalRefUpdates).toBe(2); // Should not increase since last time
}); });
}); });
describe('useTransition', () => { describe('useTransition', () => {
// @gate experimental
it('delays showing loading state until after timeout', async () => { it('delays showing loading state until after timeout', async () => {
let transition; let transition;
function App() { function App() {
@ -3190,7 +3184,6 @@ describe('ReactHooksWithNoopRenderer', () => {
}); });
describe('useDeferredValue', () => { describe('useDeferredValue', () => {
// @gate experimental
it('defers text value', async () => { it('defers text value', async () => {
function TextBox({text}) { function TextBox({text}) {
return <AsyncText text={text} />; return <AsyncText text={text} />;
@ -3694,9 +3687,8 @@ describe('ReactHooksWithNoopRenderer', () => {
]); ]);
}); });
// @gate experimental
it('regression: SuspenseList causes unmounts to be dropped on deletion', async () => { it('regression: SuspenseList causes unmounts to be dropped on deletion', async () => {
const SuspenseList = React.unstable_SuspenseList; const SuspenseList = React.SuspenseList;
function Row({label}) { function Row({label}) {
useEffect(() => { useEffect(() => {

View File

@ -50,7 +50,6 @@ describe('ReactIncremental', () => {
expect(Scheduler).toFlushWithoutYielding(); expect(Scheduler).toFlushWithoutYielding();
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('should render a simple component, in steps if needed', () => { it('should render a simple component, in steps if needed', () => {
function Bar() { function Bar() {
Scheduler.unstable_yieldValue('Bar'); Scheduler.unstable_yieldValue('Bar');
@ -67,7 +66,7 @@ describe('ReactIncremental', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo />, () => ReactNoop.render(<Foo />, () =>
Scheduler.unstable_yieldValue('callback'), Scheduler.unstable_yieldValue('callback'),
); );
@ -143,7 +142,6 @@ describe('ReactIncremental', () => {
]); ]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('can cancel partially rendered work and restart', () => { it('can cancel partially rendered work and restart', () => {
function Bar(props) { function Bar(props) {
Scheduler.unstable_yieldValue('Bar'); Scheduler.unstable_yieldValue('Bar');
@ -165,7 +163,7 @@ describe('ReactIncremental', () => {
expect(Scheduler).toFlushAndYield(['Foo', 'Bar', 'Bar']); expect(Scheduler).toFlushAndYield(['Foo', 'Bar', 'Bar']);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo text="bar" />); ReactNoop.render(<Foo text="bar" />);
}); });
} else { } else {
@ -178,7 +176,7 @@ describe('ReactIncremental', () => {
ReactNoop.flushSync(() => ReactNoop.render(null)); ReactNoop.flushSync(() => ReactNoop.render(null));
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo text="baz" />); ReactNoop.render(<Foo text="baz" />);
}); });
} else { } else {
@ -192,7 +190,6 @@ describe('ReactIncremental', () => {
expect(Scheduler).toFlushAndYield(['Bar']); expect(Scheduler).toFlushAndYield(['Bar']);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('should call callbacks even if updates are aborted', () => { it('should call callbacks even if updates are aborted', () => {
let inst; let inst;
@ -219,7 +216,7 @@ describe('ReactIncremental', () => {
expect(Scheduler).toFlushWithoutYielding(); expect(Scheduler).toFlushWithoutYielding();
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
inst.setState( inst.setState(
() => { () => {
Scheduler.unstable_yieldValue('setState1'); Scheduler.unstable_yieldValue('setState1');
@ -244,7 +241,7 @@ describe('ReactIncremental', () => {
// This will abort the previous work and restart // This will abort the previous work and restart
ReactNoop.flushSync(() => ReactNoop.render(<Foo />)); ReactNoop.flushSync(() => ReactNoop.render(<Foo />));
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
inst.setState( inst.setState(
() => { () => {
Scheduler.unstable_yieldValue('setState2'); Scheduler.unstable_yieldValue('setState2');
@ -1764,7 +1761,6 @@ describe('ReactIncremental', () => {
expect(instance.state.n).toEqual(3); expect(instance.state.n).toEqual(3);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('merges and masks context', () => { it('merges and masks context', () => {
class Intl extends React.Component { class Intl extends React.Component {
static childContextTypes = { static childContextTypes = {
@ -1883,7 +1879,7 @@ describe('ReactIncremental', () => {
'ShowBoth {"locale":"de"}', 'ShowBoth {"locale":"de"}',
]); ]);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<Intl locale="sv"> <Intl locale="sv">
<ShowLocale /> <ShowLocale />
@ -2033,7 +2029,7 @@ describe('ReactIncremental', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<Intl locale="fr"> <Intl locale="fr">
<ShowLocale /> <ShowLocale />
@ -2739,7 +2735,6 @@ describe('ReactIncremental', () => {
expect(Scheduler).toFlushAndYield(['count:1, name:not brian']); expect(Scheduler).toFlushAndYield(['count:1, name:not brian']);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('does not interrupt for update at same priority', () => { it('does not interrupt for update at same priority', () => {
function Parent(props) { function Parent(props) {
Scheduler.unstable_yieldValue('Parent: ' + props.step); Scheduler.unstable_yieldValue('Parent: ' + props.step);
@ -2752,7 +2747,7 @@ describe('ReactIncremental', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Parent step={1} />); ReactNoop.render(<Parent step={1} />);
}); });
} else { } else {
@ -2766,7 +2761,6 @@ describe('ReactIncremental', () => {
expect(Scheduler).toFlushAndYield(['Child: 1', 'Parent: 2', 'Child: 2']); expect(Scheduler).toFlushAndYield(['Child: 1', 'Parent: 2', 'Child: 2']);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('does not interrupt for update at lower priority', () => { it('does not interrupt for update at lower priority', () => {
function Parent(props) { function Parent(props) {
Scheduler.unstable_yieldValue('Parent: ' + props.step); Scheduler.unstable_yieldValue('Parent: ' + props.step);
@ -2779,7 +2773,7 @@ describe('ReactIncremental', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Parent step={1} />); ReactNoop.render(<Parent step={1} />);
}); });
} else { } else {
@ -2794,7 +2788,6 @@ describe('ReactIncremental', () => {
expect(Scheduler).toFlushAndYield(['Child: 1', 'Parent: 2', 'Child: 2']); expect(Scheduler).toFlushAndYield(['Child: 1', 'Parent: 2', 'Child: 2']);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('does interrupt for update at higher priority', () => { it('does interrupt for update at higher priority', () => {
function Parent(props) { function Parent(props) {
Scheduler.unstable_yieldValue('Parent: ' + props.step); Scheduler.unstable_yieldValue('Parent: ' + props.step);
@ -2807,7 +2800,7 @@ describe('ReactIncremental', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Parent step={1} />); ReactNoop.render(<Parent step={1} />);
}); });
} else { } else {

View File

@ -58,7 +58,6 @@ describe('ReactIncrementalErrorHandling', () => {
); );
} }
// @gate experimental || !enableSyncDefaultUpdates
it('recovers from errors asynchronously', () => { it('recovers from errors asynchronously', () => {
class ErrorBoundary extends React.Component { class ErrorBoundary extends React.Component {
state = {error: null}; state = {error: null};
@ -92,7 +91,7 @@ describe('ReactIncrementalErrorHandling', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<ErrorBoundary> <ErrorBoundary>
<Indirection> <Indirection>
@ -171,7 +170,6 @@ describe('ReactIncrementalErrorHandling', () => {
expect(ReactNoop.getChildren()).toEqual([span('Caught an error: oops!')]); expect(ReactNoop.getChildren()).toEqual([span('Caught an error: oops!')]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('recovers from errors asynchronously (legacy, no getDerivedStateFromError)', () => { it('recovers from errors asynchronously (legacy, no getDerivedStateFromError)', () => {
class ErrorBoundary extends React.Component { class ErrorBoundary extends React.Component {
state = {error: null}; state = {error: null};
@ -205,7 +203,7 @@ describe('ReactIncrementalErrorHandling', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<ErrorBoundary> <ErrorBoundary>
<Indirection> <Indirection>
@ -270,7 +268,6 @@ describe('ReactIncrementalErrorHandling', () => {
expect(ReactNoop.getChildren()).toEqual([span('Caught an error: oops!')]); expect(ReactNoop.getChildren()).toEqual([span('Caught an error: oops!')]);
}); });
// @gate experimental
it("retries at a lower priority if there's additional pending work", async () => { it("retries at a lower priority if there's additional pending work", async () => {
function App(props) { function App(props) {
if (props.isBroken) { if (props.isBroken) {
@ -285,12 +282,12 @@ describe('ReactIncrementalErrorHandling', () => {
Scheduler.unstable_yieldValue('commit'); Scheduler.unstable_yieldValue('commit');
} }
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<App isBroken={true} />, onCommit); ReactNoop.render(<App isBroken={true} />, onCommit);
}); });
expect(Scheduler).toFlushAndYieldThrough(['error']); expect(Scheduler).toFlushAndYieldThrough(['error']);
React.unstable_startTransition(() => { React.startTransition(() => {
// This update is in a separate batch // This update is in a separate batch
ReactNoop.render(<App isBroken={false} />, onCommit); ReactNoop.render(<App isBroken={false} />, onCommit);
}); });
@ -333,14 +330,14 @@ describe('ReactIncrementalErrorHandling', () => {
Scheduler.unstable_yieldValue('commit'); Scheduler.unstable_yieldValue('commit');
} }
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<App isBroken={true} />, onCommit); ReactNoop.render(<App isBroken={true} />, onCommit);
}); });
expect(Scheduler).toFlushAndYieldThrough(['error']); expect(Scheduler).toFlushAndYieldThrough(['error']);
expect(ReactNoop).toMatchRenderedOutput(null); expect(ReactNoop).toMatchRenderedOutput(null);
React.unstable_startTransition(() => { React.startTransition(() => {
// This update is in a separate batch // This update is in a separate batch
ReactNoop.render(<App isBroken={false} />, onCommit); ReactNoop.render(<App isBroken={false} />, onCommit);
}); });
@ -378,7 +375,6 @@ describe('ReactIncrementalErrorHandling', () => {
); );
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('retries one more time before handling error', () => { it('retries one more time before handling error', () => {
function BadRender({unused}) { function BadRender({unused}) {
Scheduler.unstable_yieldValue('BadRender'); Scheduler.unstable_yieldValue('BadRender');
@ -401,7 +397,7 @@ describe('ReactIncrementalErrorHandling', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Parent />, () => ReactNoop.render(<Parent />, () =>
Scheduler.unstable_yieldValue('commit'), Scheduler.unstable_yieldValue('commit'),
); );
@ -429,7 +425,6 @@ describe('ReactIncrementalErrorHandling', () => {
expect(ReactNoop.getChildren()).toEqual([]); expect(ReactNoop.getChildren()).toEqual([]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('retries one more time if an error occurs during a render that expires midway through the tree', async () => { it('retries one more time if an error occurs during a render that expires midway through the tree', async () => {
function Oops({unused}) { function Oops({unused}) {
Scheduler.unstable_yieldValue('Oops'); Scheduler.unstable_yieldValue('Oops');
@ -454,7 +449,7 @@ describe('ReactIncrementalErrorHandling', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<App />); ReactNoop.render(<App />);
}); });
} else { } else {
@ -566,7 +561,6 @@ describe('ReactIncrementalErrorHandling', () => {
expect(ReactNoop.getChildren()).toEqual([span('Caught an error: Hello.')]); expect(ReactNoop.getChildren()).toEqual([span('Caught an error: Hello.')]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('catches render error in a boundary during partial deferred mounting', () => { it('catches render error in a boundary during partial deferred mounting', () => {
class ErrorBoundary extends React.Component { class ErrorBoundary extends React.Component {
state = {error: null}; state = {error: null};
@ -592,7 +586,7 @@ describe('ReactIncrementalErrorHandling', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<ErrorBoundary> <ErrorBoundary>
<BrokenRender /> <BrokenRender />
@ -757,7 +751,6 @@ describe('ReactIncrementalErrorHandling', () => {
expect(ReactNoop.getChildren()).toEqual([]); expect(ReactNoop.getChildren()).toEqual([]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('propagates an error from a noop error boundary during partial deferred mounting', () => { it('propagates an error from a noop error boundary during partial deferred mounting', () => {
class RethrowErrorBoundary extends React.Component { class RethrowErrorBoundary extends React.Component {
componentDidCatch(error) { componentDidCatch(error) {
@ -776,7 +769,7 @@ describe('ReactIncrementalErrorHandling', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<RethrowErrorBoundary> <RethrowErrorBoundary>
<BrokenRender /> <BrokenRender />
@ -1842,7 +1835,6 @@ describe('ReactIncrementalErrorHandling', () => {
}); });
} }
// @gate experimental
it('uncaught errors should be discarded if the render is aborted', async () => { it('uncaught errors should be discarded if the render is aborted', async () => {
const root = ReactNoop.createRoot(); const root = ReactNoop.createRoot();
@ -1853,7 +1845,7 @@ describe('ReactIncrementalErrorHandling', () => {
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<Oops />); root.render(<Oops />);
}); });
} else { } else {
@ -1866,7 +1858,7 @@ describe('ReactIncrementalErrorHandling', () => {
// Interleaved update. When the root completes, instead of throwing the // Interleaved update. When the root completes, instead of throwing the
// error, it should try rendering again. This update will cause it to // error, it should try rendering again. This update will cause it to
// recover gracefully. // recover gracefully.
React.unstable_startTransition(() => { React.startTransition(() => {
root.render('Everything is fine.'); root.render('Everything is fine.');
}); });
}); });
@ -1875,7 +1867,6 @@ describe('ReactIncrementalErrorHandling', () => {
expect(root).toMatchRenderedOutput('Everything is fine.'); expect(root).toMatchRenderedOutput('Everything is fine.');
}); });
// @gate experimental
it('uncaught errors are discarded if the render is aborted, case 2', async () => { it('uncaught errors are discarded if the render is aborted, case 2', async () => {
const {useState} = React; const {useState} = React;
const root = ReactNoop.createRoot(); const root = ReactNoop.createRoot();
@ -1902,7 +1893,7 @@ describe('ReactIncrementalErrorHandling', () => {
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
// Schedule a default pri and a low pri update on the root. // Schedule a default pri and a low pri update on the root.
root.render(<Oops />); root.render(<Oops />);
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<AllGood />); root.render(<AllGood />);
}); });

View File

@ -34,7 +34,6 @@ describe('ReactIncrementalReflection', () => {
return {type: 'span', children: [], prop, hidden: false}; return {type: 'span', children: [], prop, hidden: false};
} }
// @gate experimental || !enableSyncDefaultUpdates
it('handles isMounted even when the initial render is deferred', () => { it('handles isMounted even when the initial render is deferred', () => {
const instances = []; const instances = [];
@ -65,7 +64,7 @@ describe('ReactIncrementalReflection', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo />); ReactNoop.render(<Foo />);
}); });
} else { } else {
@ -83,7 +82,6 @@ describe('ReactIncrementalReflection', () => {
expect(instances[0]._isMounted()).toBe(true); expect(instances[0]._isMounted()).toBe(true);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('handles isMounted when an unmount is deferred', () => { it('handles isMounted when an unmount is deferred', () => {
const instances = []; const instances = [];
@ -120,7 +118,7 @@ describe('ReactIncrementalReflection', () => {
expect(instances[0]._isMounted()).toBe(true); expect(instances[0]._isMounted()).toBe(true);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo mount={false} />); ReactNoop.render(<Foo mount={false} />);
}); });
} else { } else {
@ -138,7 +136,6 @@ describe('ReactIncrementalReflection', () => {
expect(instances[0]._isMounted()).toBe(false); expect(instances[0]._isMounted()).toBe(false);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('finds no node before insertion and correct node before deletion', () => { it('finds no node before insertion and correct node before deletion', () => {
let classInstance = null; let classInstance = null;
@ -210,7 +207,7 @@ describe('ReactIncrementalReflection', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo step={0} />); ReactNoop.render(<Foo step={0} />);
}); });
} else { } else {
@ -250,7 +247,7 @@ describe('ReactIncrementalReflection', () => {
// The next step will render a new host node but won't get committed yet. // The next step will render a new host node but won't get committed yet.
// We expect this to mutate the original Fiber. // We expect this to mutate the original Fiber.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo step={2} />); ReactNoop.render(<Foo step={2} />);
}); });
} else { } else {
@ -277,7 +274,7 @@ describe('ReactIncrementalReflection', () => {
// Render to null but don't commit it yet. // Render to null but don't commit it yet.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo step={3} />); ReactNoop.render(<Foo step={3} />);
}); });
} else { } else {

View File

@ -85,7 +85,6 @@ describe('ReactIncrementalScheduling', () => {
expect(ReactNoop).toMatchRenderedOutput(<span prop={5} />); expect(ReactNoop).toMatchRenderedOutput(<span prop={5} />);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('works on deferred roots in the order they were scheduled', () => { it('works on deferred roots in the order they were scheduled', () => {
const {useEffect} = React; const {useEffect} = React;
function Text({text}) { function Text({text}) {
@ -109,7 +108,7 @@ describe('ReactIncrementalScheduling', () => {
// Schedule deferred work in the reverse order // Schedule deferred work in the reverse order
ReactNoop.act(() => { ReactNoop.act(() => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.renderToRootWithID(<Text text="c:2" />, 'c'); ReactNoop.renderToRootWithID(<Text text="c:2" />, 'c');
ReactNoop.renderToRootWithID(<Text text="b:2" />, 'b'); ReactNoop.renderToRootWithID(<Text text="b:2" />, 'b');
}); });
@ -126,7 +125,7 @@ describe('ReactIncrementalScheduling', () => {
// Schedule last bit of work, it will get processed the last // Schedule last bit of work, it will get processed the last
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.renderToRootWithID(<Text text="a:2" />, 'a'); ReactNoop.renderToRootWithID(<Text text="a:2" />, 'a');
}); });
} else { } else {
@ -146,7 +145,6 @@ describe('ReactIncrementalScheduling', () => {
}); });
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('schedules sync updates when inside componentDidMount/Update', () => { it('schedules sync updates when inside componentDidMount/Update', () => {
let instance; let instance;
@ -186,7 +184,7 @@ describe('ReactIncrementalScheduling', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo />); ReactNoop.render(<Foo />);
}); });
} else { } else {
@ -206,7 +204,7 @@ describe('ReactIncrementalScheduling', () => {
]); ]);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
instance.setState({tick: 2}); instance.setState({tick: 2});
}); });
} else { } else {
@ -224,7 +222,6 @@ describe('ReactIncrementalScheduling', () => {
]); ]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('can opt-in to async scheduling inside componentDidMount/Update', () => { it('can opt-in to async scheduling inside componentDidMount/Update', () => {
let instance; let instance;
class Foo extends React.Component { class Foo extends React.Component {
@ -284,7 +281,7 @@ describe('ReactIncrementalScheduling', () => {
// Increment the tick to 2. This will trigger an update inside cDU. Flush // Increment the tick to 2. This will trigger an update inside cDU. Flush
// the first update without flushing the second one. // the first update without flushing the second one.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
instance.setState({tick: 2}); instance.setState({tick: 2});
}); });
@ -315,7 +312,6 @@ describe('ReactIncrementalScheduling', () => {
} }
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('performs Task work even after time runs out', () => { it('performs Task work even after time runs out', () => {
class Foo extends React.Component { class Foo extends React.Component {
state = {step: 1}; state = {step: 1};
@ -334,7 +330,7 @@ describe('ReactIncrementalScheduling', () => {
} }
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo />); ReactNoop.render(<Foo />);
}); });
} else { } else {

View File

@ -384,7 +384,6 @@ describe('ReactIncrementalSideEffects', () => {
expect(ReactNoop.getChildren('portalContainer')).toEqual([]); expect(ReactNoop.getChildren('portalContainer')).toEqual([]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('does not update child nodes if a flush is aborted', () => { it('does not update child nodes if a flush is aborted', () => {
function Bar(props) { function Bar(props) {
Scheduler.unstable_yieldValue('Bar'); Scheduler.unstable_yieldValue('Bar');
@ -411,7 +410,7 @@ describe('ReactIncrementalSideEffects', () => {
]); ]);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo text="World" />); ReactNoop.render(<Foo text="World" />);
}); });
} else { } else {
@ -640,14 +639,13 @@ describe('ReactIncrementalSideEffects', () => {
); );
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('can update a completed tree before it has a chance to commit', () => { it('can update a completed tree before it has a chance to commit', () => {
function Foo(props) { function Foo(props) {
Scheduler.unstable_yieldValue('Foo'); Scheduler.unstable_yieldValue('Foo');
return <span prop={props.step} />; return <span prop={props.step} />;
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo step={1} />); ReactNoop.render(<Foo step={1} />);
}); });
} else { } else {
@ -662,7 +660,7 @@ describe('ReactIncrementalSideEffects', () => {
expect(ReactNoop.getChildrenAsJSX()).toEqual(<span prop={1} />); expect(ReactNoop.getChildrenAsJSX()).toEqual(<span prop={1} />);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo step={2} />); ReactNoop.render(<Foo step={2} />);
}); });
} else { } else {
@ -675,7 +673,7 @@ describe('ReactIncrementalSideEffects', () => {
// new props // new props
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo step={3} />); ReactNoop.render(<Foo step={3} />);
}); });
} else { } else {

View File

@ -131,7 +131,6 @@ describe('ReactIncrementalUpdates', () => {
expect(instance.state).toEqual({c: 'c', d: 'd'}); expect(instance.state).toEqual({c: 'c', d: 'd'});
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('can abort an update, schedule additional updates, and resume', () => { it('can abort an update, schedule additional updates, and resume', () => {
let instance; let instance;
class Foo extends React.Component { class Foo extends React.Component {
@ -162,7 +161,7 @@ describe('ReactIncrementalUpdates', () => {
// Schedule some async updates // Schedule some async updates
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
instance.setState(createUpdate('a')); instance.setState(createUpdate('a'));
instance.setState(createUpdate('b')); instance.setState(createUpdate('b'));
instance.setState(createUpdate('c')); instance.setState(createUpdate('c'));
@ -184,7 +183,7 @@ describe('ReactIncrementalUpdates', () => {
instance.setState(createUpdate('e')); instance.setState(createUpdate('e'));
instance.setState(createUpdate('f')); instance.setState(createUpdate('f'));
}); });
React.unstable_startTransition(() => { React.startTransition(() => {
instance.setState(createUpdate('g')); instance.setState(createUpdate('g'));
}); });
@ -229,7 +228,6 @@ describe('ReactIncrementalUpdates', () => {
} }
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('can abort an update, schedule a replaceState, and resume', () => { it('can abort an update, schedule a replaceState, and resume', () => {
let instance; let instance;
class Foo extends React.Component { class Foo extends React.Component {
@ -260,7 +258,7 @@ describe('ReactIncrementalUpdates', () => {
// Schedule some async updates // Schedule some async updates
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
instance.setState(createUpdate('a')); instance.setState(createUpdate('a'));
instance.setState(createUpdate('b')); instance.setState(createUpdate('b'));
instance.setState(createUpdate('c')); instance.setState(createUpdate('c'));
@ -285,7 +283,7 @@ describe('ReactIncrementalUpdates', () => {
// reaching into the updater. // reaching into the updater.
instance.updater.enqueueReplaceState(instance, createUpdate('f')); instance.updater.enqueueReplaceState(instance, createUpdate('f'));
}); });
React.unstable_startTransition(() => { React.startTransition(() => {
instance.setState(createUpdate('g')); instance.setState(createUpdate('g'));
}); });
@ -543,7 +541,6 @@ describe('ReactIncrementalUpdates', () => {
expect(ReactNoop.getChildren()).toEqual([span('derived state')]); expect(ReactNoop.getChildren()).toEqual([span('derived state')]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('regression: does not expire soon due to layout effects in the last batch', () => { it('regression: does not expire soon due to layout effects in the last batch', () => {
const {useState, useLayoutEffect} = React; const {useState, useLayoutEffect} = React;
@ -561,7 +558,7 @@ describe('ReactIncrementalUpdates', () => {
ReactNoop.act(() => { ReactNoop.act(() => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<App />); ReactNoop.render(<App />);
}); });
} else { } else {
@ -577,7 +574,7 @@ describe('ReactIncrementalUpdates', () => {
Scheduler.unstable_advanceTime(10000); Scheduler.unstable_advanceTime(10000);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
setCount(2); setCount(2);
}); });
} else { } else {
@ -588,7 +585,6 @@ describe('ReactIncrementalUpdates', () => {
}); });
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('regression: does not expire soon due to previous flushSync', () => { it('regression: does not expire soon due to previous flushSync', () => {
function Text({text}) { function Text({text}) {
Scheduler.unstable_yieldValue(text); Scheduler.unstable_yieldValue(text);
@ -603,7 +599,7 @@ describe('ReactIncrementalUpdates', () => {
Scheduler.unstable_advanceTime(10000); Scheduler.unstable_advanceTime(10000);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Text text="B" />); ReactNoop.render(<Text text="B" />);
}); });
} else { } else {
@ -613,7 +609,6 @@ describe('ReactIncrementalUpdates', () => {
expect(Scheduler).toHaveYielded([]); expect(Scheduler).toHaveYielded([]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('regression: does not expire soon due to previous expired work', () => { it('regression: does not expire soon due to previous expired work', () => {
function Text({text}) { function Text({text}) {
Scheduler.unstable_yieldValue(text); Scheduler.unstable_yieldValue(text);
@ -621,7 +616,7 @@ describe('ReactIncrementalUpdates', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Text text="A" />); ReactNoop.render(<Text text="A" />);
}); });
} else { } else {
@ -634,7 +629,7 @@ describe('ReactIncrementalUpdates', () => {
Scheduler.unstable_advanceTime(10000); Scheduler.unstable_advanceTime(10000);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Text text="B" />); ReactNoop.render(<Text text="B" />);
}); });
} else { } else {
@ -644,7 +639,6 @@ describe('ReactIncrementalUpdates', () => {
expect(Scheduler).toHaveYielded([]); expect(Scheduler).toHaveYielded([]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('when rebasing, does not exclude updates that were already committed, regardless of priority', async () => { it('when rebasing, does not exclude updates that were already committed, regardless of priority', async () => {
const {useState, useLayoutEffect} = React; const {useState, useLayoutEffect} = React;
@ -678,7 +672,7 @@ describe('ReactIncrementalUpdates', () => {
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
pushToLog('A'); pushToLog('A');
}); });
} else { } else {
@ -707,7 +701,6 @@ describe('ReactIncrementalUpdates', () => {
expect(root).toMatchRenderedOutput('ABCD'); expect(root).toMatchRenderedOutput('ABCD');
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('when rebasing, does not exclude updates that were already committed, regardless of priority (classes)', async () => { it('when rebasing, does not exclude updates that were already committed, regardless of priority (classes)', async () => {
let pushToLog; let pushToLog;
class App extends React.Component { class App extends React.Component {
@ -740,7 +733,7 @@ describe('ReactIncrementalUpdates', () => {
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
pushToLog('A'); pushToLog('A');
}); });
} else { } else {

View File

@ -12,7 +12,7 @@ describe('ReactInterleavedUpdates', () => {
React = require('react'); React = require('react');
ReactNoop = require('react-noop-renderer'); ReactNoop = require('react-noop-renderer');
Scheduler = require('scheduler'); Scheduler = require('scheduler');
startTransition = React.unstable_startTransition; startTransition = React.startTransition;
useState = React.useState; useState = React.useState;
useEffect = React.useEffect; useEffect = React.useEffect;
}); });
@ -22,7 +22,6 @@ describe('ReactInterleavedUpdates', () => {
return text; return text;
} }
// @gate experimental || !enableSyncDefaultUpdates
test('update during an interleaved event is not processed during the current render', async () => { test('update during an interleaved event is not processed during the current render', async () => {
const updaters = []; const updaters = [];
@ -57,7 +56,7 @@ describe('ReactInterleavedUpdates', () => {
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
updateChildren(1); updateChildren(1);
}); });
} else { } else {
@ -69,7 +68,7 @@ describe('ReactInterleavedUpdates', () => {
// In an interleaved event, schedule an update on each of the children. // In an interleaved event, schedule an update on each of the children.
// Including the two that haven't rendered yet. // Including the two that haven't rendered yet.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
updateChildren(2); updateChildren(2);
}); });
} else { } else {
@ -85,7 +84,6 @@ describe('ReactInterleavedUpdates', () => {
expect(root).toMatchRenderedOutput('222'); expect(root).toMatchRenderedOutput('222');
}); });
// @gate experimental
// @gate !enableSyncDefaultUpdates // @gate !enableSyncDefaultUpdates
test('low priority update during an interleaved event is not processed during the current render', async () => { test('low priority update during an interleaved event is not processed during the current render', async () => {
// Same as previous test, but the interleaved update is lower priority than // Same as previous test, but the interleaved update is lower priority than

View File

@ -1475,7 +1475,6 @@ describe('ReactLazy', () => {
}); });
// @gate enableLazyElements // @gate enableLazyElements
// @gate experimental || !enableSyncDefaultUpdates
it('mount and reorder lazy elements', async () => { it('mount and reorder lazy elements', async () => {
class Child extends React.Component { class Child extends React.Component {
componentDidMount() { componentDidMount() {
@ -1536,7 +1535,7 @@ describe('ReactLazy', () => {
// Swap the position of A and B // Swap the position of A and B
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.update(<Parent swap={true} />); root.update(<Parent swap={true} />);
}); });
} else { } else {

View File

@ -828,7 +828,6 @@ describe('ReactNewContext', () => {
); );
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('warns if multiple renderers concurrently render the same context', () => { it('warns if multiple renderers concurrently render the same context', () => {
spyOnDev(console, 'error'); spyOnDev(console, 'error');
const Context = React.createContext(0); const Context = React.createContext(0);
@ -848,7 +847,7 @@ describe('ReactNewContext', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<App value={1} />); ReactNoop.render(<App value={1} />);
}); });
} else { } else {

View File

@ -28,7 +28,7 @@ describe('ReactSchedulerIntegration', () => {
NormalPriority = Scheduler.unstable_NormalPriority; NormalPriority = Scheduler.unstable_NormalPriority;
IdlePriority = Scheduler.unstable_IdlePriority; IdlePriority = Scheduler.unstable_IdlePriority;
runWithPriority = Scheduler.unstable_runWithPriority; runWithPriority = Scheduler.unstable_runWithPriority;
startTransition = React.unstable_startTransition; startTransition = React.startTransition;
}); });
// Note: This is based on a similar component we use in www. We can delete // Note: This is based on a similar component we use in www. We can delete
@ -88,7 +88,6 @@ describe('ReactSchedulerIntegration', () => {
]); ]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('requests a paint after committing', () => { it('requests a paint after committing', () => {
const scheduleCallback = Scheduler.unstable_scheduleCallback; const scheduleCallback = Scheduler.unstable_scheduleCallback;
@ -102,7 +101,7 @@ describe('ReactSchedulerIntegration', () => {
// Schedule a React render. React will request a paint after committing it. // Schedule a React render. React will request a paint after committing it.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render('Update'); root.render('Update');
}); });
} else { } else {
@ -203,7 +202,7 @@ describe(
React = require('react'); React = require('react');
ReactNoop = require('react-noop-renderer'); ReactNoop = require('react-noop-renderer');
Scheduler = require('scheduler'); Scheduler = require('scheduler');
startTransition = React.unstable_startTransition; startTransition = React.startTransition;
}); });
afterEach(() => { afterEach(() => {
@ -252,7 +251,6 @@ describe(
}); });
}); });
// @gate experimental
it('mock Scheduler module to check if `shouldYield` is called', async () => { it('mock Scheduler module to check if `shouldYield` is called', async () => {
// This test reproduces a bug where React's Scheduler task timed out but // This test reproduces a bug where React's Scheduler task timed out but
// the `shouldYield` method returned true. Usually we try not to mock // the `shouldYield` method returned true. Usually we try not to mock

View File

@ -96,7 +96,6 @@ describe('ReactSuspense', () => {
} }
} }
// @gate experimental || !enableSyncDefaultUpdates
it('suspends rendering and continues later', () => { it('suspends rendering and continues later', () => {
function Bar(props) { function Bar(props) {
Scheduler.unstable_yieldValue('Bar'); Scheduler.unstable_yieldValue('Bar');
@ -128,7 +127,7 @@ describe('ReactSuspense', () => {
// Navigate the shell to now render the child content. // Navigate the shell to now render the child content.
// This should suspend. // This should suspend.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.update(<Foo renderBar={true} />); root.update(<Foo renderBar={true} />);
}); });
} else { } else {
@ -201,7 +200,6 @@ describe('ReactSuspense', () => {
expect(root).toMatchRenderedOutput('AB'); expect(root).toMatchRenderedOutput('AB');
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('interrupts current render if promise resolves before current render phase', () => { it('interrupts current render if promise resolves before current render phase', () => {
let didResolve = false; let didResolve = false;
const listeners = []; const listeners = [];
@ -244,7 +242,7 @@ describe('ReactSuspense', () => {
// The update will suspend. // The update will suspend.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.update( root.update(
<> <>
<Suspense fallback={<Text text="Loading..." />}> <Suspense fallback={<Text text="Loading..." />}>
@ -289,7 +287,6 @@ describe('ReactSuspense', () => {
expect(root).toMatchRenderedOutput('AsyncAfter SuspenseSibling'); expect(root).toMatchRenderedOutput('AsyncAfter SuspenseSibling');
}); });
// @gate experimental
// @gate !enableSyncDefaultUpdates // @gate !enableSyncDefaultUpdates
it( it(
'interrupts current render when something suspends with a ' + 'interrupts current render when something suspends with a ' +
@ -331,7 +328,7 @@ describe('ReactSuspense', () => {
// Schedule another update. This will have lower priority because it's // Schedule another update. This will have lower priority because it's
// a transition. // a transition.
React.unstable_startTransition(() => { React.startTransition(() => {
root.update(<App shouldSuspend={false} step={2} />); root.update(<App shouldSuspend={false} step={2} />);
}); });

View File

@ -14,7 +14,7 @@ describe('ReactSuspenseList', () => {
Scheduler = require('scheduler'); Scheduler = require('scheduler');
Profiler = React.Profiler; Profiler = React.Profiler;
Suspense = React.Suspense; Suspense = React.Suspense;
SuspenseList = React.unstable_SuspenseList; SuspenseList = React.SuspenseList;
}); });
function Text(props) { function Text(props) {
@ -40,7 +40,6 @@ describe('ReactSuspenseList', () => {
return Component; return Component;
} }
// @gate experimental
it('warns if an unsupported revealOrder option is used', () => { it('warns if an unsupported revealOrder option is used', () => {
function Foo() { function Foo() {
return ( return (
@ -60,7 +59,6 @@ describe('ReactSuspenseList', () => {
]); ]);
}); });
// @gate experimental
it('warns if a upper case revealOrder option is used', () => { it('warns if a upper case revealOrder option is used', () => {
function Foo() { function Foo() {
return ( return (
@ -80,7 +78,6 @@ describe('ReactSuspenseList', () => {
]); ]);
}); });
// @gate experimental
it('warns if a misspelled revealOrder option is used', () => { it('warns if a misspelled revealOrder option is used', () => {
function Foo() { function Foo() {
return ( return (
@ -101,7 +98,6 @@ describe('ReactSuspenseList', () => {
]); ]);
}); });
// @gate experimental
it('warns if a single element is passed to a "forwards" list', () => { it('warns if a single element is passed to a "forwards" list', () => {
function Foo({children}) { function Foo({children}) {
return <SuspenseList revealOrder="forwards">{children}</SuspenseList>; return <SuspenseList revealOrder="forwards">{children}</SuspenseList>;
@ -134,7 +130,6 @@ describe('ReactSuspenseList', () => {
]); ]);
}); });
// @gate experimental
it('warns if a single fragment is passed to a "backwards" list', () => { it('warns if a single fragment is passed to a "backwards" list', () => {
function Foo() { function Foo() {
return ( return (
@ -155,7 +150,6 @@ describe('ReactSuspenseList', () => {
]); ]);
}); });
// @gate experimental
it('warns if a nested array is passed to a "forwards" list', () => { it('warns if a nested array is passed to a "forwards" list', () => {
function Foo({items}) { function Foo({items}) {
return ( return (
@ -183,7 +177,6 @@ describe('ReactSuspenseList', () => {
]); ]);
}); });
// @gate experimental
it('shows content independently by default', async () => { it('shows content independently by default', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -250,7 +243,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('shows content independently in legacy mode regardless of option', async () => { it('shows content independently in legacy mode regardless of option', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -321,7 +313,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('displays all "together"', async () => { it('displays all "together"', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -391,7 +382,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('displays all "together" even when nested as siblings', async () => { it('displays all "together" even when nested as siblings', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -477,7 +467,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('displays all "together" in nested SuspenseLists', async () => { it('displays all "together" in nested SuspenseLists', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -539,7 +528,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('displays all "together" in nested SuspenseLists where the inner is default', async () => { it('displays all "together" in nested SuspenseLists where the inner is default', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -599,7 +587,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('displays all "together" during an update', async () => { it('displays all "together" during an update', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -684,7 +671,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('avoided boundaries can be coordinate with SuspenseList', async () => { it('avoided boundaries can be coordinate with SuspenseList', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -783,7 +769,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('displays each items in "forwards" order', async () => { it('displays each items in "forwards" order', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -849,7 +834,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('displays each items in "backwards" order', async () => { it('displays each items in "backwards" order', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -915,7 +899,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('displays added row at the top "together" and the bottom in "forwards" order', async () => { it('displays added row at the top "together" and the bottom in "forwards" order', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -1070,7 +1053,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('displays added row at the top "together" and the bottom in "backwards" order', async () => { it('displays added row at the top "together" and the bottom in "backwards" order', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -1255,7 +1237,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('switches to rendering fallbacks if the tail takes long CPU time', async () => { it('switches to rendering fallbacks if the tail takes long CPU time', async () => {
function Foo() { function Foo() {
return ( return (
@ -1275,7 +1256,7 @@ describe('ReactSuspenseList', () => {
// This render is only CPU bound. Nothing suspends. // This render is only CPU bound. Nothing suspends.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo />); ReactNoop.render(<Foo />);
}); });
} else { } else {
@ -1324,7 +1305,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('only shows one loading state at a time for "collapsed" tail insertions', async () => { it('only shows one loading state at a time for "collapsed" tail insertions', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -1394,7 +1374,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('warns if an unsupported tail option is used', () => { it('warns if an unsupported tail option is used', () => {
function Foo() { function Foo() {
return ( return (
@ -1415,7 +1394,6 @@ describe('ReactSuspenseList', () => {
]); ]);
}); });
// @gate experimental
it('warns if a tail option is used with "together"', () => { it('warns if a tail option is used with "together"', () => {
function Foo() { function Foo() {
return ( return (
@ -1436,7 +1414,6 @@ describe('ReactSuspenseList', () => {
]); ]);
}); });
// @gate experimental
it('renders one "collapsed" fallback even if CPU time elapsed', async () => { it('renders one "collapsed" fallback even if CPU time elapsed', async () => {
function Foo() { function Foo() {
return ( return (
@ -1459,7 +1436,7 @@ describe('ReactSuspenseList', () => {
// This render is only CPU bound. Nothing suspends. // This render is only CPU bound. Nothing suspends.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo />); ReactNoop.render(<Foo />);
}); });
} else { } else {
@ -1509,7 +1486,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('adding to the middle does not collapse insertions (forwards)', async () => { it('adding to the middle does not collapse insertions (forwards)', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -1652,7 +1628,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('adding to the middle does not collapse insertions (backwards)', async () => { it('adding to the middle does not collapse insertions (backwards)', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -1800,7 +1775,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('adding to the middle of committed tail does not collapse insertions', async () => { it('adding to the middle of committed tail does not collapse insertions', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -1958,7 +1932,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('only shows no initial loading state "hidden" tail insertions', async () => { it('only shows no initial loading state "hidden" tail insertions', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -2022,7 +1995,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('eventually resolves a nested forwards suspense list', async () => { it('eventually resolves a nested forwards suspense list', async () => {
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -2085,7 +2057,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('eventually resolves a nested forwards suspense list with a hidden tail', async () => { it('eventually resolves a nested forwards suspense list with a hidden tail', async () => {
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -2132,7 +2103,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('eventually resolves two nested forwards suspense lists with a hidden tail', async () => { it('eventually resolves two nested forwards suspense lists with a hidden tail', async () => {
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -2200,7 +2170,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('can do unrelated adjacent updates', async () => { it('can do unrelated adjacent updates', async () => {
let updateAdjacent; let updateAdjacent;
function Adjacent() { function Adjacent() {
@ -2247,7 +2216,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('is able to re-suspend the last rows during an update with hidden', async () => { it('is able to re-suspend the last rows during an update with hidden', async () => {
const AsyncB = createAsyncText('B'); const AsyncB = createAsyncText('B');
@ -2336,7 +2304,6 @@ describe('ReactSuspenseList', () => {
expect(previousInst).toBe(setAsyncB); expect(previousInst).toBe(setAsyncB);
}); });
// @gate experimental
it('is able to re-suspend the last rows during an update with hidden', async () => { it('is able to re-suspend the last rows during an update with hidden', async () => {
const AsyncB = createAsyncText('B'); const AsyncB = createAsyncText('B');
@ -2425,7 +2392,6 @@ describe('ReactSuspenseList', () => {
expect(previousInst).toBe(setAsyncB); expect(previousInst).toBe(setAsyncB);
}); });
// @gate experimental
it('is able to interrupt a partially rendered tree and continue later', async () => { it('is able to interrupt a partially rendered tree and continue later', async () => {
const AsyncA = createAsyncText('A'); const AsyncA = createAsyncText('A');
@ -2462,7 +2428,7 @@ describe('ReactSuspenseList', () => {
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
// Add a few items at the end. // Add a few items at the end.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
updateLowPri(true); updateLowPri(true);
}); });
} else { } else {
@ -2504,7 +2470,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('can resume class components when revealed together', async () => { it('can resume class components when revealed together', async () => {
const A = createAsyncText('A'); const A = createAsyncText('A');
const B = createAsyncText('B'); const B = createAsyncText('B');
@ -2567,7 +2532,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('should be able to progressively show CPU expensive rows with two pass rendering', async () => { it('should be able to progressively show CPU expensive rows with two pass rendering', async () => {
function TwoPass({text}) { function TwoPass({text}) {
const [pass, setPass] = React.useState(0); const [pass, setPass] = React.useState(0);
@ -2605,7 +2569,7 @@ describe('ReactSuspenseList', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<App />); ReactNoop.render(<App />);
}); });
} else { } else {
@ -2638,7 +2602,6 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental
it('should be able to progressively show rows with two pass rendering and visible', async () => { it('should be able to progressively show rows with two pass rendering and visible', async () => {
function TwoPass({text}) { function TwoPass({text}) {
const [pass, setPass] = React.useState(0); const [pass, setPass] = React.useState(0);
@ -2678,7 +2641,7 @@ describe('ReactSuspenseList', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<App />); ReactNoop.render(<App />);
}); });
} else { } else {
@ -2720,7 +2683,7 @@ describe('ReactSuspenseList', () => {
); );
}); });
// @gate experimental && enableProfilerTimer // @gate enableProfilerTimer
it('counts the actual duration when profiling a SuspenseList', async () => { it('counts the actual duration when profiling a SuspenseList', async () => {
// Order of parameters: id, phase, actualDuration, treeBaseDuration // Order of parameters: id, phase, actualDuration, treeBaseDuration
const onRender = jest.fn(); const onRender = jest.fn();

View File

@ -212,7 +212,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo />); ReactNoop.render(<Foo />);
}); });
} else { } else {
@ -284,7 +284,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// The update will suspend. // The update will suspend.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo renderBar={true} />); ReactNoop.render(<Foo renderBar={true} />);
}); });
} else { } else {
@ -354,7 +354,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(Scheduler).toFlushAndYield([]); expect(Scheduler).toFlushAndYield([]);
// B suspends. Continue rendering the remaining siblings. // B suspends. Continue rendering the remaining siblings.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<Suspense fallback={<Text text="Loading..." />}> <Suspense fallback={<Text text="Loading..." />}>
<Text text="A" /> <Text text="A" />
@ -401,7 +401,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// TODO: Delete this feature flag. // TODO: Delete this feature flag.
// @gate !replayFailedUnitOfWorkWithInvokeGuardedCallback || !__DEV__ // @gate !replayFailedUnitOfWorkWithInvokeGuardedCallback || !__DEV__
// @gate enableCache // @gate enableCache
// @gate experimental || !enableSyncDefaultUpdates
it('retries on error', async () => { it('retries on error', async () => {
class ErrorBoundary extends React.Component { class ErrorBoundary extends React.Component {
state = {error: null}; state = {error: null};
@ -437,7 +436,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([]); expect(ReactNoop.getChildren()).toEqual([]);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<App renderContent={true} />); ReactNoop.render(<App renderContent={true} />);
}); });
} else { } else {
@ -567,7 +566,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}); });
// @gate enableCache // @gate enableCache
// @gate experimental || !enableSyncDefaultUpdates
it('keeps working on lower priority work after being pinged', async () => { it('keeps working on lower priority work after being pinged', async () => {
// Advance the virtual time so that we're close to the edge of a bucket. // Advance the virtual time so that we're close to the edge of a bucket.
ReactNoop.expire(149); ReactNoop.expire(149);
@ -586,7 +584,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([]); expect(ReactNoop.getChildren()).toEqual([]);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<App showA={true} showB={false} />); ReactNoop.render(<App showA={true} showB={false} />);
}); });
} else { } else {
@ -599,7 +597,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// but not enough to expire the suspense timeout. // but not enough to expire the suspense timeout.
ReactNoop.expire(120); ReactNoop.expire(120);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<App showA={true} showB={true} />); ReactNoop.render(<App showA={true} showB={true} />);
}); });
} else { } else {
@ -630,7 +628,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Default pri // Default pri
ReactNoop.render(<App />); ReactNoop.render(<App />);
// Low pri // Low pri
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<App hide={true} />); ReactNoop.render(<App hide={true} />);
}); });
@ -647,7 +645,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// times model. Might not make sense in the new model. // times model. Might not make sense in the new model.
// TODO: This test doesn't over what it was originally designed to test. // TODO: This test doesn't over what it was originally designed to test.
// Either rewrite or delete. // Either rewrite or delete.
// @gate experimental || !enableSyncDefaultUpdates
it('tries each subsequent level after suspending', async () => { it('tries each subsequent level after suspending', async () => {
const root = ReactNoop.createRoot(); const root = ReactNoop.createRoot();
@ -683,7 +680,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Schedule an update at several distinct expiration times // Schedule an update at several distinct expiration times
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<App step={1} shouldSuspend={true} />); root.render(<App step={1} shouldSuspend={true} />);
}); });
} else { } else {
@ -694,7 +691,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
interrupt(); interrupt();
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<App step={2} shouldSuspend={true} />); root.render(<App step={2} shouldSuspend={true} />);
}); });
} else { } else {
@ -705,7 +702,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
interrupt(); interrupt();
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<App step={3} shouldSuspend={true} />); root.render(<App step={3} shouldSuspend={true} />);
}); });
} else { } else {
@ -928,7 +925,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span('Async'), span('Sync')]); expect(ReactNoop.getChildren()).toEqual([span('Async'), span('Sync')]);
}); });
// @gate experimental // @gate enableCache
it('does not expire for transitions', async () => { it('does not expire for transitions', async () => {
ReactNoop.render( ReactNoop.render(
<Fragment> <Fragment>
@ -937,7 +934,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
); );
expect(Scheduler).toFlushAndYield([]); expect(Scheduler).toFlushAndYield([]);
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<Fragment> <Fragment>
<Suspense fallback={<Text text="Loading..." />}> <Suspense fallback={<Text text="Loading..." />}>
@ -984,7 +981,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(Scheduler).toFlushAndYield([]); expect(Scheduler).toFlushAndYield([]);
expect(ReactNoop.getChildren()).toEqual([]); expect(ReactNoop.getChildren()).toEqual([]);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<> <>
<Suspense fallback={<Text text="Loading..." />}> <Suspense fallback={<Text text="Loading..." />}>
@ -1051,7 +1048,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(Scheduler).toFlushAndYield([]); expect(Scheduler).toFlushAndYield([]);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<Suspense fallback={<Text text="Loading..." />}> <Suspense fallback={<Text text="Loading..." />}>
<AsyncText text="Async" /> <AsyncText text="Async" />
@ -1075,7 +1072,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span('Async')]); expect(ReactNoop.getChildren()).toEqual([span('Async')]);
}); });
// @gate experimental
// @gate enableCache // @gate enableCache
it('starts working on an update even if its priority falls between two suspended levels', async () => { it('starts working on an update even if its priority falls between two suspended levels', async () => {
function App(props) { function App(props) {
@ -1096,7 +1092,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(Scheduler).toFlushAndYield(['S']); expect(Scheduler).toFlushAndYield(['S']);
// Schedule an update, and suspend for up to 5 seconds. // Schedule an update, and suspend for up to 5 seconds.
React.unstable_startTransition(() => ReactNoop.render(<App text="A" />)); React.startTransition(() => ReactNoop.render(<App text="A" />));
// The update should suspend. // The update should suspend.
expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
expect(ReactNoop.getChildren()).toEqual([span('S')]); expect(ReactNoop.getChildren()).toEqual([span('S')]);
@ -1108,7 +1104,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span('S')]); expect(ReactNoop.getChildren()).toEqual([span('S')]);
// Schedule another low priority update. // Schedule another low priority update.
React.unstable_startTransition(() => ReactNoop.render(<App text="B" />)); React.startTransition(() => ReactNoop.render(<App text="B" />));
// This update should also suspend. // This update should also suspend.
expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
expect(ReactNoop.getChildren()).toEqual([span('S')]); expect(ReactNoop.getChildren()).toEqual([span('S')]);
@ -1857,7 +1853,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}); });
// @gate enableCache // @gate enableCache
// @gate experimental || !enableSyncDefaultUpdates
it('suspends for longer if something took a long (CPU bound) time to render', async () => { it('suspends for longer if something took a long (CPU bound) time to render', async () => {
function Foo({renderContent}) { function Foo({renderContent}) {
Scheduler.unstable_yieldValue('Foo'); Scheduler.unstable_yieldValue('Foo');
@ -1872,7 +1867,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(Scheduler).toFlushAndYield(['Foo']); expect(Scheduler).toFlushAndYield(['Foo']);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo renderContent={true} />); ReactNoop.render(<Foo renderContent={true} />);
}); });
} else { } else {
@ -2044,7 +2039,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(Scheduler).toFlushAndYield(['Foo']); expect(Scheduler).toFlushAndYield(['Foo']);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo renderContent={true} />); ReactNoop.render(<Foo renderContent={true} />);
}); });
} else { } else {
@ -2365,7 +2360,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span('A')]); expect(ReactNoop.getChildren()).toEqual([span('A')]);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo showB={true} />); ReactNoop.render(<Foo showB={true} />);
}); });
} else { } else {
@ -2445,7 +2440,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}); });
describe('startTransition', () => { describe('startTransition', () => {
// @gate experimental
// @gate enableCache // @gate enableCache
it('top level render', async () => { it('top level render', async () => {
function App({page}) { function App({page}) {
@ -2457,7 +2451,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
} }
// Initial render. // Initial render.
React.unstable_startTransition(() => ReactNoop.render(<App page="A" />)); React.startTransition(() => ReactNoop.render(<App page="A" />));
expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
// Only a short time is needed to unsuspend the initial loading state. // Only a short time is needed to unsuspend the initial loading state.
@ -2471,7 +2465,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span('A')]); expect(ReactNoop.getChildren()).toEqual([span('A')]);
// Start transition. // Start transition.
React.unstable_startTransition(() => ReactNoop.render(<App page="B" />)); React.startTransition(() => ReactNoop.render(<App page="B" />));
expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
Scheduler.unstable_advanceTime(100000); Scheduler.unstable_advanceTime(100000);
@ -2485,7 +2479,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span('B')]); expect(ReactNoop.getChildren()).toEqual([span('B')]);
}); });
// @gate experimental
// @gate enableCache // @gate enableCache
it('hooks', async () => { it('hooks', async () => {
let transitionToPage; let transitionToPage;
@ -2507,7 +2500,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Initial render. // Initial render.
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
React.unstable_startTransition(() => transitionToPage('A')); React.startTransition(() => transitionToPage('A'));
expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
// Only a short time is needed to unsuspend the initial loading state. // Only a short time is needed to unsuspend the initial loading state.
@ -2523,7 +2516,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Start transition. // Start transition.
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
React.unstable_startTransition(() => transitionToPage('B')); React.startTransition(() => transitionToPage('B'));
expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
Scheduler.unstable_advanceTime(100000); Scheduler.unstable_advanceTime(100000);
@ -2538,7 +2531,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span('B')]); expect(ReactNoop.getChildren()).toEqual([span('B')]);
}); });
// @gate experimental
// @gate enableCache // @gate enableCache
it('classes', async () => { it('classes', async () => {
let transitionToPage; let transitionToPage;
@ -2563,7 +2555,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Initial render. // Initial render.
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
React.unstable_startTransition(() => transitionToPage('A')); React.startTransition(() => transitionToPage('A'));
expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
// Only a short time is needed to unsuspend the initial loading state. // Only a short time is needed to unsuspend the initial loading state.
@ -2579,7 +2571,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Start transition. // Start transition.
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
React.unstable_startTransition(() => transitionToPage('B')); React.startTransition(() => transitionToPage('B'));
expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
Scheduler.unstable_advanceTime(100000); Scheduler.unstable_advanceTime(100000);
@ -2596,7 +2588,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}); });
describe('delays transitions when using React.startTranistion', () => { describe('delays transitions when using React.startTranistion', () => {
// @gate experimental
// @gate enableCache // @gate enableCache
it('top level render', async () => { it('top level render', async () => {
function App({page}) { function App({page}) {
@ -2608,7 +2599,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
} }
// Initial render. // Initial render.
React.unstable_startTransition(() => ReactNoop.render(<App page="A" />)); React.startTransition(() => ReactNoop.render(<App page="A" />));
expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
// Only a short time is needed to unsuspend the initial loading state. // Only a short time is needed to unsuspend the initial loading state.
@ -2622,7 +2613,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span('A')]); expect(ReactNoop.getChildren()).toEqual([span('A')]);
// Start transition. // Start transition.
React.unstable_startTransition(() => ReactNoop.render(<App page="B" />)); React.startTransition(() => ReactNoop.render(<App page="B" />));
expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
Scheduler.unstable_advanceTime(2999); Scheduler.unstable_advanceTime(2999);
@ -2637,7 +2628,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span('B')]); expect(ReactNoop.getChildren()).toEqual([span('B')]);
// Start a long (infinite) transition. // Start a long (infinite) transition.
React.unstable_startTransition(() => ReactNoop.render(<App page="C" />)); React.startTransition(() => ReactNoop.render(<App page="C" />));
expect(Scheduler).toFlushAndYield(['Suspend! [C]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [C]', 'Loading...']);
// Even after lots of time has passed, we have still not yet flushed the // Even after lots of time has passed, we have still not yet flushed the
@ -2647,7 +2638,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span('B')]); expect(ReactNoop.getChildren()).toEqual([span('B')]);
}); });
// @gate experimental
// @gate enableCache // @gate enableCache
it('hooks', async () => { it('hooks', async () => {
let transitionToPage; let transitionToPage;
@ -2669,7 +2659,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Initial render. // Initial render.
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
React.unstable_startTransition(() => transitionToPage('A')); React.startTransition(() => transitionToPage('A'));
expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
// Only a short time is needed to unsuspend the initial loading state. // Only a short time is needed to unsuspend the initial loading state.
@ -2685,7 +2675,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Start transition. // Start transition.
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
React.unstable_startTransition(() => transitionToPage('B')); React.startTransition(() => transitionToPage('B'));
expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
@ -2703,7 +2693,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Start a long (infinite) transition. // Start a long (infinite) transition.
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
React.unstable_startTransition(() => transitionToPage('C')); React.startTransition(() => transitionToPage('C'));
expect(Scheduler).toFlushAndYield(['Suspend! [C]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [C]', 'Loading...']);
@ -2715,7 +2705,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}); });
}); });
// @gate experimental
// @gate enableCache // @gate enableCache
it('classes', async () => { it('classes', async () => {
let transitionToPage; let transitionToPage;
@ -2740,7 +2729,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Initial render. // Initial render.
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
React.unstable_startTransition(() => transitionToPage('A')); React.startTransition(() => transitionToPage('A'));
expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
// Only a short time is needed to unsuspend the initial loading state. // Only a short time is needed to unsuspend the initial loading state.
@ -2756,7 +2745,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Start transition. // Start transition.
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
React.unstable_startTransition(() => transitionToPage('B')); React.startTransition(() => transitionToPage('B'));
expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
Scheduler.unstable_advanceTime(2999); Scheduler.unstable_advanceTime(2999);
@ -2773,7 +2762,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Start a long (infinite) transition. // Start a long (infinite) transition.
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
React.unstable_startTransition(() => transitionToPage('C')); React.startTransition(() => transitionToPage('C'));
expect(Scheduler).toFlushAndYield(['Suspend! [C]', 'Loading...']); expect(Scheduler).toFlushAndYield(['Suspend! [C]', 'Loading...']);
@ -2786,7 +2775,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}); });
}); });
// @gate experimental
// @gate enableCache // @gate enableCache
it('do not show placeholder when updating an avoided boundary with startTransition', async () => { it('do not show placeholder when updating an avoided boundary with startTransition', async () => {
function App({page}) { function App({page}) {
@ -2810,7 +2798,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span('Hi!'), span('A')]); expect(ReactNoop.getChildren()).toEqual([span('Hi!'), span('A')]);
// Start transition. // Start transition.
React.unstable_startTransition(() => ReactNoop.render(<App page="B" />)); React.startTransition(() => ReactNoop.render(<App page="B" />));
expect(Scheduler).toFlushAndYield(['Hi!', 'Suspend! [B]', 'Loading B...']); expect(Scheduler).toFlushAndYield(['Hi!', 'Suspend! [B]', 'Loading B...']);
@ -2831,7 +2819,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
); );
}); });
// @gate experimental
// @gate enableCache // @gate enableCache
it('do not show placeholder when mounting an avoided boundary with startTransition', async () => { it('do not show placeholder when mounting an avoided boundary with startTransition', async () => {
function App({page}) { function App({page}) {
@ -2857,7 +2844,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop.getChildren()).toEqual([span('Hi!'), span('A')]); expect(ReactNoop.getChildren()).toEqual([span('Hi!'), span('A')]);
// Start transition. // Start transition.
React.unstable_startTransition(() => ReactNoop.render(<App page="B" />)); React.startTransition(() => ReactNoop.render(<App page="B" />));
expect(Scheduler).toFlushAndYield(['Hi!', 'Suspend! [B]', 'Loading B...']); expect(Scheduler).toFlushAndYield(['Hi!', 'Suspend! [B]', 'Loading B...']);
@ -2913,7 +2900,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Update. Since showing a fallback would hide content that's already // Update. Since showing a fallback would hide content that's already
// visible, it should suspend for a JND without committing. // visible, it should suspend for a JND without committing.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<App text="First update" />); root.render(<App text="First update" />);
}); });
} else { } else {
@ -2926,7 +2913,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Update again. This should also suspend for a JND. // Update again. This should also suspend for a JND.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<App text="Second update" />); root.render(<App text="Second update" />);
}); });
} else { } else {
@ -2992,7 +2979,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(root).toMatchRenderedOutput(<span prop="Foo" />); expect(root).toMatchRenderedOutput(<span prop="Foo" />);
}); });
// @gate experimental
// @gate enableCache // @gate enableCache
it('should not render hidden content while suspended on higher pri', async () => { it('should not render hidden content while suspended on higher pri', async () => {
function Offscreen() { function Offscreen() {
@ -3021,7 +3007,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop).toMatchRenderedOutput(<div hidden={true} />); expect(ReactNoop).toMatchRenderedOutput(<div hidden={true} />);
// Start transition. // Start transition.
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<App showContent={true} />); ReactNoop.render(<App showContent={true} />);
}); });
@ -3043,7 +3029,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
); );
}); });
// @gate experimental
// @gate enableCache // @gate enableCache
it('should be able to unblock higher pri content before suspended hidden', async () => { it('should be able to unblock higher pri content before suspended hidden', async () => {
function Offscreen() { function Offscreen() {
@ -3074,7 +3059,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(Scheduler).toFlushAndYieldThrough(['Suspend! [A]']); expect(Scheduler).toFlushAndYieldThrough(['Suspend! [A]']);
// Start transition. // Start transition.
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<App showContent={true} />); ReactNoop.render(<App showContent={true} />);
}); });
@ -3272,7 +3257,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// update even though the primary tree is suspended. // update even though the primary tree is suspended.
await ReactNoop.act(async () => { await ReactNoop.act(async () => {
setAppText('C'); setAppText('C');
React.unstable_startTransition(() => { React.startTransition(() => {
setFallbackText('Still loading...'); setFallbackText('Still loading...');
}); });
}); });
@ -3705,11 +3690,10 @@ describe('ReactSuspenseWithNoopRenderer', () => {
); );
}); });
// @gate experimental
// @gate enableCache // @gate enableCache
// @gate !enableSyncDefaultUpdates // @gate !enableSyncDefaultUpdates
it('regression: ping at high priority causes update to be dropped', async () => { it('regression: ping at high priority causes update to be dropped', async () => {
const {useState, unstable_useTransition: useTransition} = React; const {useState, useTransition} = React;
let setTextA; let setTextA;
function A() { function A() {
@ -3818,15 +3802,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}); });
// Regression: https://github.com/facebook/react/issues/18486 // Regression: https://github.com/facebook/react/issues/18486
// @gate experimental
// @gate enableCache // @gate enableCache
it('does not get stuck in pending state with render phase updates', async () => { it('does not get stuck in pending state with render phase updates', async () => {
let setTextWithShortTransition; let setTextWithShortTransition;
let setTextWithLongTransition; let setTextWithLongTransition;
function App() { function App() {
const [isPending1, startShortTransition] = React.unstable_useTransition(); const [isPending1, startShortTransition] = React.useTransition();
const [isPending2, startLongTransition] = React.unstable_useTransition(); const [isPending2, startLongTransition] = React.useTransition();
const isPending = isPending1 || isPending2; const isPending = isPending1 || isPending2;
const [text, setText] = React.useState(''); const [text, setText] = React.useState('');
const [mirror, setMirror] = React.useState(''); const [mirror, setMirror] = React.useState('');

View File

@ -32,9 +32,9 @@ describe('ReactTransition', () => {
Scheduler = require('scheduler'); Scheduler = require('scheduler');
useState = React.useState; useState = React.useState;
useLayoutEffect = React.useLayoutEffect; useLayoutEffect = React.useLayoutEffect;
useTransition = React.unstable_useTransition; useTransition = React.useTransition;
Suspense = React.Suspense; Suspense = React.Suspense;
startTransition = React.unstable_startTransition; startTransition = React.startTransition;
getCacheForType = React.unstable_getCacheForType; getCacheForType = React.unstable_getCacheForType;
act = ReactNoop.act; act = ReactNoop.act;
@ -158,7 +158,6 @@ describe('ReactTransition', () => {
} }
} }
// @gate experimental
// @gate enableCache // @gate enableCache
test('isPending works even if called from outside an input event', async () => { test('isPending works even if called from outside an input event', async () => {
let start; let start;
@ -200,7 +199,6 @@ describe('ReactTransition', () => {
expect(root).toMatchRenderedOutput('Async'); expect(root).toMatchRenderedOutput('Async');
}); });
// @gate experimental
// @gate enableCache // @gate enableCache
test( test(
'when multiple transitions update the same queue, only the most recent ' + 'when multiple transitions update the same queue, only the most recent ' +
@ -320,7 +318,6 @@ describe('ReactTransition', () => {
); );
// Same as previous test, but for class update queue. // Same as previous test, but for class update queue.
// @gate experimental
// @gate enableCache // @gate enableCache
test( test(
'when multiple transitions update the same queue, only the most recent ' + 'when multiple transitions update the same queue, only the most recent ' +
@ -445,7 +442,6 @@ describe('ReactTransition', () => {
}, },
); );
// @gate experimental
// @gate enableCache // @gate enableCache
test( test(
'when multiple transitions update overlapping queues, all the transitions ' + 'when multiple transitions update overlapping queues, all the transitions ' +
@ -551,7 +547,6 @@ describe('ReactTransition', () => {
}, },
); );
// @gate experimental
// @gate enableCache // @gate enableCache
test('interrupt a refresh transition if a new transition is scheduled', async () => { test('interrupt a refresh transition if a new transition is scheduled', async () => {
const root = ReactNoop.createRoot(); const root = ReactNoop.createRoot();
@ -607,7 +602,6 @@ describe('ReactTransition', () => {
expect(root).toMatchRenderedOutput('Updated'); expect(root).toMatchRenderedOutput('Updated');
}); });
// @gate experimental
// @gate enableCache // @gate enableCache
test( test(
"interrupt a refresh transition when something suspends and we've " + "interrupt a refresh transition when something suspends and we've " +
@ -669,7 +663,7 @@ describe('ReactTransition', () => {
expect(Scheduler).toFlushAndYieldThrough(['A']); expect(Scheduler).toFlushAndYieldThrough(['A']);
// Now schedule a second transition. We won't interrupt the first one. // Now schedule a second transition. We won't interrupt the first one.
React.unstable_startTransition(() => { React.startTransition(() => {
setShouldHideInParent(true); setShouldHideInParent(true);
}); });
// Continue rendering the first transition. // Continue rendering the first transition.
@ -710,7 +704,6 @@ describe('ReactTransition', () => {
}, },
); );
// @gate experimental
// @gate enableCache // @gate enableCache
test( test(
'interrupt a refresh transition when something suspends and a parent ' + 'interrupt a refresh transition when something suspends and a parent ' +
@ -776,8 +769,6 @@ describe('ReactTransition', () => {
}, },
); );
// @gate experimental
// @gate enableCache
it('should render normal pri updates scheduled after transitions before transitions', async () => { it('should render normal pri updates scheduled after transitions before transitions', async () => {
let updateTransitionPri; let updateTransitionPri;
let updateNormalPri; let updateNormalPri;
@ -833,7 +824,6 @@ describe('ReactTransition', () => {
expect(root).toMatchRenderedOutput('Transition pri: 1, Normal pri: 1'); expect(root).toMatchRenderedOutput('Transition pri: 1, Normal pri: 1');
}); });
// @gate experimental
// @gate enableCache // @gate enableCache
it('should render normal pri updates before transition suspense retries', async () => { it('should render normal pri updates before transition suspense retries', async () => {
let updateTransitionPri; let updateTransitionPri;
@ -898,8 +888,6 @@ describe('ReactTransition', () => {
expect(root).toMatchRenderedOutput('Async, Normal pri: 1'); expect(root).toMatchRenderedOutput('Async, Normal pri: 1');
}); });
// @gate experimental
// @gate enableCache
it('should not interrupt transitions with normal pri updates', async () => { it('should not interrupt transitions with normal pri updates', async () => {
let updateNormalPri; let updateNormalPri;
let updateTransitionPri; let updateTransitionPri;

View File

@ -15,7 +15,7 @@ describe('ReactUpdatePriority', () => {
Scheduler = require('scheduler'); Scheduler = require('scheduler');
ContinuousEventPriority = require('react-reconciler/constants') ContinuousEventPriority = require('react-reconciler/constants')
.ContinuousEventPriority; .ContinuousEventPriority;
startTransition = React.unstable_startTransition; startTransition = React.startTransition;
useState = React.useState; useState = React.useState;
useEffect = React.useEffect; useEffect = React.useEffect;
}); });
@ -84,7 +84,6 @@ describe('ReactUpdatePriority', () => {
expect(Scheduler).toHaveYielded(['Idle: 2, Default: 2']); expect(Scheduler).toHaveYielded(['Idle: 2, Default: 2']);
}); });
// @gate experimental
test('continuous updates should interrupt transisions', async () => { test('continuous updates should interrupt transisions', async () => {
const root = ReactNoop.createRoot(); const root = ReactNoop.createRoot();

View File

@ -153,7 +153,6 @@ describe('updaters', () => {
expect(allSchedulerTypes).toEqual([[null], [SchedulingComponent]]); expect(allSchedulerTypes).toEqual([[null], [SchedulingComponent]]);
}); });
// @gate experimental
it('should cover cascading updates', async () => { it('should cover cascading updates', async () => {
let triggerActiveCascade = null; let triggerActiveCascade = null;
let triggerPassiveCascade = null; let triggerPassiveCascade = null;
@ -183,7 +182,7 @@ describe('updaters', () => {
return count; return count;
}; };
const root = ReactDOM.unstable_createRoot(document.createElement('div')); const root = ReactDOM.createRoot(document.createElement('div'));
await ReactTestUtils.act(async () => { await ReactTestUtils.act(async () => {
root.render(<Parent />); root.render(<Parent />);
expect(Scheduler).toFlushAndYieldThrough([ expect(Scheduler).toFlushAndYieldThrough([
@ -292,7 +291,6 @@ describe('updaters', () => {
done(); done();
}); });
// @gate experimental
it('should cover error handling', async () => { it('should cover error handling', async () => {
let triggerError = null; let triggerError = null;
@ -329,7 +327,7 @@ describe('updaters', () => {
throw new Error('Hello'); throw new Error('Hello');
}; };
const root = ReactDOM.unstable_createRoot(document.createElement('div')); const root = ReactDOM.createRoot(document.createElement('div'));
await ReactTestUtils.act(async () => { await ReactTestUtils.act(async () => {
root.render(<Parent shouldError={false} />); root.render(<Parent shouldError={false} />);
}); });
@ -349,7 +347,6 @@ describe('updaters', () => {
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
}); });
// @gate experimental
it('should distinguish between updaters in the case of interleaved work', async () => { it('should distinguish between updaters in the case of interleaved work', async () => {
const { const {
FunctionComponent, FunctionComponent,
@ -368,7 +365,7 @@ describe('updaters', () => {
const LowPriorityUpdater = () => { const LowPriorityUpdater = () => {
const [count, setCount] = React.useState(0); const [count, setCount] = React.useState(0);
triggerLowPriorityUpdate = () => { triggerLowPriorityUpdate = () => {
React.unstable_startTransition(() => { React.startTransition(() => {
setCount(prevCount => prevCount + 1); setCount(prevCount => prevCount + 1);
}); });
}; };
@ -380,7 +377,7 @@ describe('updaters', () => {
return null; return null;
}; };
const root = ReactDOM.unstable_createRoot(document.createElement('div')); const root = ReactDOM.createRoot(document.createElement('div'));
root.render( root.render(
<React.Fragment> <React.Fragment>
<SyncPriorityUpdater /> <SyncPriorityUpdater />

View File

@ -149,7 +149,6 @@ describe('SchedulingProfiler', () => {
}); });
// @gate enableSchedulingProfiler // @gate enableSchedulingProfiler
// @gate experimental || !enableSyncDefaultUpdates
it('should mark render yields', async () => { it('should mark render yields', async () => {
function Bar() { function Bar() {
Scheduler.unstable_yieldValue('Bar'); Scheduler.unstable_yieldValue('Bar');
@ -162,7 +161,7 @@ describe('SchedulingProfiler', () => {
} }
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render(<Foo />); ReactNoop.render(<Foo />);
}); });

View File

@ -100,7 +100,6 @@ describe('SchedulingProfiler labels', () => {
); );
}); });
// @gate experimental
// @gate enableSchedulingProfiler // @gate enableSchedulingProfiler
it('regression test DefaultLane', () => { it('regression test DefaultLane', () => {
const container = document.createElement('div'); const container = document.createElement('div');
@ -114,7 +113,6 @@ describe('SchedulingProfiler labels', () => {
}); });
}); });
// @gate experimental
// @gate enableSchedulingProfiler // @gate enableSchedulingProfiler
// @gate !enableLegacyFBSupport // @gate !enableLegacyFBSupport
it('regression test InputDiscreteLane', () => { it('regression test InputDiscreteLane', () => {
@ -144,7 +142,6 @@ describe('SchedulingProfiler labels', () => {
); );
}); });
// @gate experimental
// @gate enableSchedulingProfiler // @gate enableSchedulingProfiler
it('regression test InputContinuousLane', () => { it('regression test InputContinuousLane', () => {
const container = document.createElement('div'); const container = document.createElement('div');

View File

@ -31,8 +31,11 @@ function loadModules() {
ReactNoop = require('react-noop-renderer'); ReactNoop = require('react-noop-renderer');
Scheduler = require('scheduler'); Scheduler = require('scheduler');
act = ReactNoop.act; act = ReactNoop.act;
createMutableSource = React.unstable_createMutableSource;
useMutableSource = React.unstable_useMutableSource; // Stable entrypoints export with "unstable_" prefix.
createMutableSource =
React.createMutableSource || React.unstable_createMutableSource;
useMutableSource = React.useMutableSource || React.unstable_useMutableSource;
} }
describe('useMutableSource', () => { describe('useMutableSource', () => {
@ -138,7 +141,6 @@ describe('useMutableSource', () => {
beforeEach(loadModules); beforeEach(loadModules);
// @gate experimental
it('should subscribe to a source and schedule updates when it changes', () => { it('should subscribe to a source and schedule updates when it changes', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -206,14 +208,13 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should restart work if a new source is mutated during render', () => { it('should restart work if a new source is mutated during render', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
act(() => { act(() => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<> <>
<Component <Component
@ -262,7 +263,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should schedule an update if a new source is mutated between render and commit (subscription)', () => { it('should schedule an update if a new source is mutated between render and commit (subscription)', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -302,7 +302,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should unsubscribe and resubscribe if a new source is used', () => { it('should unsubscribe and resubscribe if a new source is used', () => {
const sourceA = createSource('a-one'); const sourceA = createSource('a-one');
const mutableSourceA = createMutableSource( const mutableSourceA = createMutableSource(
@ -359,7 +358,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should unsubscribe and resubscribe if a new subscribe function is provided', () => { it('should unsubscribe and resubscribe if a new subscribe function is provided', () => {
const source = createSource('a-one'); const source = createSource('a-one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -424,7 +422,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should re-use previously read snapshot value when reading is unsafe', () => { it('should re-use previously read snapshot value when reading is unsafe', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -452,7 +449,7 @@ describe('useMutableSource', () => {
// Changing values should schedule an update with React. // Changing values should schedule an update with React.
// Start working on this update but don't finish it. // Start working on this update but don't finish it.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
source.value = 'two'; source.value = 'two';
}); });
} else { } else {
@ -487,7 +484,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should read from source on newly mounted subtree if no pending updates are scheduled for source', () => { it('should read from source on newly mounted subtree if no pending updates are scheduled for source', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -527,7 +523,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should throw and restart render if source and snapshot are unavailable during an update', () => { it('should throw and restart render if source and snapshot are unavailable during an update', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -591,7 +586,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should throw and restart render if source and snapshot are unavailable during a sync update', () => { it('should throw and restart render if source and snapshot are unavailable during a sync update', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -655,7 +649,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should only update components whose subscriptions fire', () => { it('should only update components whose subscriptions fire', () => {
const source = createComplexSource('a:one', 'b:one'); const source = createComplexSource('a:one', 'b:one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -694,7 +687,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should detect tearing in part of the store not yet subscribed to', () => { it('should detect tearing in part of the store not yet subscribed to', () => {
const source = createComplexSource('a:one', 'b:one'); const source = createComplexSource('a:one', 'b:one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -722,7 +714,7 @@ describe('useMutableSource', () => {
// Because the store has not changed yet, there are no pending updates, // Because the store has not changed yet, there are no pending updates,
// so it is considered safe to read from when we start this render. // so it is considered safe to read from when we start this render.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<> <>
<Component <Component
@ -787,7 +779,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('does not schedule an update for subscriptions that fire with an unchanged snapshot', () => { it('does not schedule an update for subscriptions that fire with an unchanged snapshot', () => {
const MockComponent = jest.fn(Component); const MockComponent = jest.fn(Component);
@ -814,7 +805,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should throw and restart if getSnapshot changes between scheduled update and re-render', () => { it('should throw and restart if getSnapshot changes between scheduled update and re-render', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -855,7 +845,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should recover from a mutation during yield when other work is scheduled', () => { it('should recover from a mutation during yield when other work is scheduled', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -863,7 +852,7 @@ describe('useMutableSource', () => {
act(() => { act(() => {
// Start a render that uses the mutable source. // Start a render that uses the mutable source.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<> <>
<Component <Component
@ -910,7 +899,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should not throw if the new getSnapshot returns the same snapshot value', () => { it('should not throw if the new getSnapshot returns the same snapshot value', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -965,7 +953,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should not throw if getSnapshot changes but the source can be safely read from anyway', () => { it('should not throw if getSnapshot changes but the source can be safely read from anyway', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -1005,7 +992,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should still schedule an update if an eager selector throws after a mutation', () => { it('should still schedule an update if an eager selector throws after a mutation', () => {
const source = createSource({ const source = createSource({
friends: [ friends: [
@ -1072,7 +1058,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should not warn about updates that fire between unmount and passive unsubscribe', () => { it('should not warn about updates that fire between unmount and passive unsubscribe', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -1109,7 +1094,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should support inline selectors and updates that are processed after selector change', async () => { it('should support inline selectors and updates that are processed after selector change', async () => {
const source = createSource({ const source = createSource({
a: 'initial', a: 'initial',
@ -1154,7 +1138,6 @@ describe('useMutableSource', () => {
expect(root).toMatchRenderedOutput('Another update'); expect(root).toMatchRenderedOutput('Another update');
}); });
// @gate experimental
it('should clear the update queue when getSnapshot changes with pending lower priority updates', async () => { it('should clear the update queue when getSnapshot changes with pending lower priority updates', async () => {
const source = createSource({ const source = createSource({
a: 'initial', a: 'initial',
@ -1211,7 +1194,6 @@ describe('useMutableSource', () => {
expect(root).toMatchRenderedOutput('B: Update'); expect(root).toMatchRenderedOutput('B: Update');
}); });
// @gate experimental
it('should clear the update queue when source changes with pending lower priority updates', async () => { it('should clear the update queue when source changes with pending lower priority updates', async () => {
const sourceA = createSource('initial'); const sourceA = createSource('initial');
const sourceB = createSource('initial'); const sourceB = createSource('initial');
@ -1256,7 +1238,6 @@ describe('useMutableSource', () => {
expect(root).toMatchRenderedOutput('B: Update'); expect(root).toMatchRenderedOutput('B: Update');
}); });
// @gate experimental
it('should always treat reading as potentially unsafe when getSnapshot changes between renders', async () => { it('should always treat reading as potentially unsafe when getSnapshot changes between renders', async () => {
const source = createSource({ const source = createSource({
a: 'foo', a: 'foo',
@ -1346,7 +1327,6 @@ describe('useMutableSource', () => {
expect(Scheduler).toHaveYielded(['x: bar, y: bar']); expect(Scheduler).toHaveYielded(['x: bar, y: bar']);
}); });
// @gate experimental
it('getSnapshot changes and then source is mutated in between paint and passive effect phase', async () => { it('getSnapshot changes and then source is mutated in between paint and passive effect phase', async () => {
const source = createSource({ const source = createSource({
a: 'foo', a: 'foo',
@ -1405,7 +1385,6 @@ describe('useMutableSource', () => {
expect(root).toMatchRenderedOutput('baz'); expect(root).toMatchRenderedOutput('baz');
}); });
// @gate experimental
it('getSnapshot changes and then source is mutated in between paint and passive effect phase, case 2', async () => { it('getSnapshot changes and then source is mutated in between paint and passive effect phase, case 2', async () => {
const source = createSource({ const source = createSource({
a: 'a0', a: 'a0',
@ -1476,7 +1455,6 @@ describe('useMutableSource', () => {
expect(root.getChildrenAsJSX()).toEqual('first: a1, second: a1'); expect(root.getChildrenAsJSX()).toEqual('first: a1, second: a1');
}); });
// @gate experimental
it( it(
'if source is mutated after initial read but before subscription is set ' + 'if source is mutated after initial read but before subscription is set ' +
'up, should still entangle all pending mutations even if snapshot of ' + 'up, should still entangle all pending mutations even if snapshot of ' +
@ -1533,7 +1511,7 @@ describe('useMutableSource', () => {
await act(async () => { await act(async () => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render( root.render(
<> <>
<Read getSnapshot={getSnapshotA} /> <Read getSnapshot={getSnapshotA} />
@ -1563,7 +1541,7 @@ describe('useMutableSource', () => {
// read during render will happen to match the latest value. But it should // read during render will happen to match the latest value. But it should
// still entangle the updates to prevent the previous update (a1) from // still entangle the updates to prevent the previous update (a1) from
// rendering by itself. // rendering by itself.
React.unstable_startTransition(() => { React.startTransition(() => {
mutateA('a0'); mutateA('a0');
mutateB('b0'); mutateB('b0');
}); });
@ -1581,7 +1559,6 @@ describe('useMutableSource', () => {
}, },
); );
// @gate experimental
it('warns about functions being used as snapshot values', async () => { it('warns about functions being used as snapshot values', async () => {
const source = createSource(() => 'a'); const source = createSource(() => 'a');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -1609,7 +1586,6 @@ describe('useMutableSource', () => {
expect(root).toMatchRenderedOutput('a'); expect(root).toMatchRenderedOutput('a');
}); });
// @gate experimental
it('getSnapshot changes and then source is mutated during interleaved event', async () => { it('getSnapshot changes and then source is mutated during interleaved event', async () => {
const {useEffect} = React; const {useEffect} = React;
@ -1680,7 +1656,7 @@ describe('useMutableSource', () => {
await act(async () => { await act(async () => {
// Switch the parent and the child to read using the same config // Switch the parent and the child to read using the same config
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<App parentConfig={configB} childConfig={configB} />); root.render(<App parentConfig={configB} childConfig={configB} />);
}); });
} else { } else {
@ -1692,7 +1668,7 @@ describe('useMutableSource', () => {
// Mutate the config. This is at lower priority so that 1) to make sure // Mutate the config. This is at lower priority so that 1) to make sure
// it doesn't happen to get batched with the in-progress render, and 2) // it doesn't happen to get batched with the in-progress render, and 2)
// so it doesn't interrupt the in-progress render. // so it doesn't interrupt the in-progress render.
React.unstable_startTransition(() => { React.startTransition(() => {
source.valueB = '3'; source.valueB = '3';
}); });
@ -1734,7 +1710,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should not tear with newly mounted component when updates were scheduled at a lower priority', async () => { it('should not tear with newly mounted component when updates were scheduled at a lower priority', async () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -1802,7 +1777,7 @@ describe('useMutableSource', () => {
expect(source.listenerCount).toBe(1); expect(source.listenerCount).toBe(1);
// Mutate -> schedule update for ComponentA // Mutate -> schedule update for ComponentA
React.unstable_startTransition(() => { React.startTransition(() => {
source.value = 'two'; source.value = 'two';
}); });
@ -1815,7 +1790,6 @@ describe('useMutableSource', () => {
if (__DEV__) { if (__DEV__) {
// See https://github.com/facebook/react/issues/19948 // See https://github.com/facebook/react/issues/19948
describe('side effecte detection', () => { describe('side effecte detection', () => {
// @gate experimental
it('should throw if a mutable source is mutated during render', () => { it('should throw if a mutable source is mutated during render', () => {
const source = createSource(0); const source = createSource(0);
const mutableSource = createMutableSource( const mutableSource = createMutableSource(
@ -1860,7 +1834,6 @@ describe('useMutableSource', () => {
]); ]);
}); });
// @gate experimental
it('should throw if a mutable source is mutated during render (legacy mode)', () => { it('should throw if a mutable source is mutated during render (legacy mode)', () => {
const source = createSource('initial'); const source = createSource('initial');
const mutableSource = createMutableSource( const mutableSource = createMutableSource(
@ -1899,7 +1872,6 @@ describe('useMutableSource', () => {
expect(Scheduler).toHaveYielded(['MutateDuringRead:initial']); expect(Scheduler).toHaveYielded(['MutateDuringRead:initial']);
}); });
// @gate experimental
it('should not misidentify mutations after render as side effects', async () => { it('should not misidentify mutations after render as side effects', async () => {
const source = createSource('initial'); const source = createSource('initial');
const mutableSource = createMutableSource( const mutableSource = createMutableSource(
@ -1934,7 +1906,6 @@ describe('useMutableSource', () => {
}); });
describe('dev warnings', () => { describe('dev warnings', () => {
// @gate experimental
it('should warn if the subscribe function does not return an unsubscribe function', () => { it('should warn if the subscribe function does not return an unsubscribe function', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource( const mutableSource = createMutableSource(
@ -1960,7 +1931,6 @@ describe('useMutableSource', () => {
); );
}); });
// @gate experimental
it('should error if multiple renderers of the same type use a mutable source at the same time', () => { it('should error if multiple renderers of the same type use a mutable source at the same time', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource( const mutableSource = createMutableSource(
@ -1971,7 +1941,7 @@ describe('useMutableSource', () => {
act(() => { act(() => {
// Start a render that uses the mutable source. // Start a render that uses the mutable source.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<> <>
<Component <Component
@ -2041,7 +2011,6 @@ describe('useMutableSource', () => {
}); });
}); });
// @gate experimental
it('should error if multiple renderers of the same type use a mutable source at the same time with mutation between', () => { it('should error if multiple renderers of the same type use a mutable source at the same time with mutation between', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource( const mutableSource = createMutableSource(
@ -2052,7 +2021,7 @@ describe('useMutableSource', () => {
act(() => { act(() => {
// Start a render that uses the mutable source. // Start a render that uses the mutable source.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactNoop.render( ReactNoop.render(
<> <>
<Component <Component

View File

@ -27,8 +27,12 @@ describe('useMutableSourceHydration', () => {
Scheduler = require('scheduler'); Scheduler = require('scheduler');
act = require('react-dom/test-utils').unstable_concurrentAct; act = require('react-dom/test-utils').unstable_concurrentAct;
createMutableSource = React.unstable_createMutableSource;
useMutableSource = React.unstable_useMutableSource; // Stable entrypoints export with "unstable_" prefix.
createMutableSource =
React.createMutableSource || React.unstable_createMutableSource;
useMutableSource =
React.useMutableSource || React.unstable_useMutableSource;
}); });
function dispatchAndSetCurrentEvent(el, event) { function dispatchAndSetCurrentEvent(el, event) {
@ -140,7 +144,6 @@ describe('useMutableSourceHydration', () => {
return <div>{`${label}:${snapshot}`}</div>; return <div>{`${label}:${snapshot}`}</div>;
} }
// @gate experimental
it('should render and hydrate', () => { it('should render and hydrate', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -164,7 +167,7 @@ describe('useMutableSourceHydration', () => {
expect(Scheduler).toHaveYielded(['only:one']); expect(Scheduler).toHaveYielded(['only:one']);
expect(source.listenerCount).toBe(0); expect(source.listenerCount).toBe(0);
const root = ReactDOM.unstable_createRoot(container, { const root = ReactDOM.createRoot(container, {
hydrate: true, hydrate: true,
hydrationOptions: { hydrationOptions: {
mutableSources: [mutableSource], mutableSources: [mutableSource],
@ -177,7 +180,6 @@ describe('useMutableSourceHydration', () => {
expect(source.listenerCount).toBe(1); expect(source.listenerCount).toBe(1);
}); });
// @gate experimental
it('should detect a tear before hydrating a component', () => { it('should detect a tear before hydrating a component', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -201,7 +203,7 @@ describe('useMutableSourceHydration', () => {
expect(Scheduler).toHaveYielded(['only:one']); expect(Scheduler).toHaveYielded(['only:one']);
expect(source.listenerCount).toBe(0); expect(source.listenerCount).toBe(0);
const root = ReactDOM.unstable_createRoot(container, { const root = ReactDOM.createRoot(container, {
hydrate: true, hydrate: true,
hydrationOptions: { hydrationOptions: {
mutableSources: [mutableSource], mutableSources: [mutableSource],
@ -222,7 +224,6 @@ describe('useMutableSourceHydration', () => {
expect(source.listenerCount).toBe(1); expect(source.listenerCount).toBe(1);
}); });
// @gate experimental
it('should detect a tear between hydrating components', () => { it('should detect a tear between hydrating components', () => {
const source = createSource('one'); const source = createSource('one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -254,7 +255,7 @@ describe('useMutableSourceHydration', () => {
expect(Scheduler).toHaveYielded(['a:one', 'b:one']); expect(Scheduler).toHaveYielded(['a:one', 'b:one']);
expect(source.listenerCount).toBe(0); expect(source.listenerCount).toBe(0);
const root = ReactDOM.unstable_createRoot(container, { const root = ReactDOM.createRoot(container, {
hydrate: true, hydrate: true,
hydrationOptions: { hydrationOptions: {
mutableSources: [mutableSource], mutableSources: [mutableSource],
@ -263,7 +264,7 @@ describe('useMutableSourceHydration', () => {
expect(() => { expect(() => {
act(() => { act(() => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<TestComponent />); root.render(<TestComponent />);
}); });
} else { } else {
@ -281,7 +282,6 @@ describe('useMutableSourceHydration', () => {
expect(source.listenerCount).toBe(2); expect(source.listenerCount).toBe(2);
}); });
// @gate experimental
it('should detect a tear between hydrating components reading from different parts of a source', () => { it('should detect a tear between hydrating components reading from different parts of a source', () => {
const source = createComplexSource('a:one', 'b:one'); const source = createComplexSource('a:one', 'b:one');
const mutableSource = createMutableSource(source, param => param.version); const mutableSource = createMutableSource(source, param => param.version);
@ -314,7 +314,7 @@ describe('useMutableSourceHydration', () => {
container.innerHTML = htmlString; container.innerHTML = htmlString;
expect(Scheduler).toHaveYielded(['0:a:one', '1:b:one']); expect(Scheduler).toHaveYielded(['0:a:one', '1:b:one']);
const root = ReactDOM.unstable_createRoot(container, { const root = ReactDOM.createRoot(container, {
hydrate: true, hydrate: true,
hydrationOptions: { hydrationOptions: {
mutableSources: [mutableSource], mutableSources: [mutableSource],
@ -323,7 +323,7 @@ describe('useMutableSourceHydration', () => {
expect(() => { expect(() => {
act(() => { act(() => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render( root.render(
<> <>
<Component <Component
@ -370,7 +370,6 @@ describe('useMutableSourceHydration', () => {
expect(Scheduler).toHaveYielded(['0:a:one', '1:b:two']); expect(Scheduler).toHaveYielded(['0:a:one', '1:b:two']);
}); });
// @gate experimental
// @gate !enableSyncDefaultUpdates // @gate !enableSyncDefaultUpdates
it('should detect a tear during a higher priority interruption', () => { it('should detect a tear during a higher priority interruption', () => {
const source = createSource('one'); const source = createSource('one');
@ -405,7 +404,7 @@ describe('useMutableSourceHydration', () => {
expect(Scheduler).toHaveYielded([1, 'a:one']); expect(Scheduler).toHaveYielded([1, 'a:one']);
expect(source.listenerCount).toBe(0); expect(source.listenerCount).toBe(0);
const root = ReactDOM.unstable_createRoot(container, { const root = ReactDOM.createRoot(container, {
hydrate: true, hydrate: true,
hydrationOptions: { hydrationOptions: {
mutableSources: [mutableSource], mutableSources: [mutableSource],
@ -415,7 +414,7 @@ describe('useMutableSourceHydration', () => {
expect(() => { expect(() => {
act(() => { act(() => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.render(<TestComponent flag={1} />); root.render(<TestComponent flag={1} />);
}); });
} else { } else {

View File

@ -2437,7 +2437,7 @@ describe('ReactFresh', () => {
}; };
}); });
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<AppV1 offscreen={true} />); root.render(<AppV1 offscreen={true} />);
expect(Scheduler).toFlushAndYieldThrough(['App#layout']); expect(Scheduler).toFlushAndYieldThrough(['App#layout']);
const el = container.firstChild; const el = container.firstChild;

View File

@ -72,7 +72,6 @@ describe('ReactFlightDOMRelay', () => {
}); });
}); });
// @gate experimental
it('can render a client component using a module reference and render there', () => { it('can render a client component using a module reference and render there', () => {
function UserClient(props) { function UserClient(props) {
return ( return (
@ -105,7 +104,6 @@ describe('ReactFlightDOMRelay', () => {
expect(container.innerHTML).toEqual('<span>Hello, Seb Smith</span>'); expect(container.innerHTML).toEqual('<span>Hello, Seb Smith</span>');
}); });
// @gate experimental
it('can reasonably handle different element types', () => { it('can reasonably handle different element types', () => {
const { const {
forwardRef, forwardRef,

View File

@ -128,7 +128,6 @@ describe('ReactFlightDOM', () => {
}); });
}); });
// @gate experimental
it('should resolve the root', async () => { it('should resolve the root', async () => {
const {Suspense} = React; const {Suspense} = React;
@ -171,7 +170,7 @@ describe('ReactFlightDOM', () => {
const response = ReactServerDOMReader.createFromReadableStream(readable); const response = ReactServerDOMReader.createFromReadableStream(readable);
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
await act(async () => { await act(async () => {
root.render(<App response={response} />); root.render(<App response={response} />);
}); });
@ -180,7 +179,6 @@ describe('ReactFlightDOM', () => {
); );
}); });
// @gate experimental
it('should not get confused by $', async () => { it('should not get confused by $', async () => {
const {Suspense} = React; const {Suspense} = React;
@ -210,14 +208,13 @@ describe('ReactFlightDOM', () => {
const response = ReactServerDOMReader.createFromReadableStream(readable); const response = ReactServerDOMReader.createFromReadableStream(readable);
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
await act(async () => { await act(async () => {
root.render(<App response={response} />); root.render(<App response={response} />);
}); });
expect(container.innerHTML).toBe('<p>$1</p>'); expect(container.innerHTML).toBe('<p>$1</p>');
}); });
// @gate experimental
it('should not get confused by @', async () => { it('should not get confused by @', async () => {
const {Suspense} = React; const {Suspense} = React;
@ -247,14 +244,13 @@ describe('ReactFlightDOM', () => {
const response = ReactServerDOMReader.createFromReadableStream(readable); const response = ReactServerDOMReader.createFromReadableStream(readable);
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
await act(async () => { await act(async () => {
root.render(<App response={response} />); root.render(<App response={response} />);
}); });
expect(container.innerHTML).toBe('<p>@div</p>'); expect(container.innerHTML).toBe('<p>@div</p>');
}); });
// @gate experimental
it('should progressively reveal server components', async () => { it('should progressively reveal server components', async () => {
let reportedErrors = []; let reportedErrors = [];
const {Suspense} = React; const {Suspense} = React;
@ -383,7 +379,7 @@ describe('ReactFlightDOM', () => {
const response = ReactServerDOMReader.createFromReadableStream(readable); const response = ReactServerDOMReader.createFromReadableStream(readable);
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
await act(async () => { await act(async () => {
root.render( root.render(
<Suspense fallback={<p>(loading)</p>}> <Suspense fallback={<p>(loading)</p>}>
@ -454,7 +450,6 @@ describe('ReactFlightDOM', () => {
expect(reportedErrors).toEqual([]); expect(reportedErrors).toEqual([]);
}); });
// @gate experimental
it('should preserve state of client components on refetch', async () => { it('should preserve state of client components on refetch', async () => {
const {Suspense} = React; const {Suspense} = React;
@ -483,7 +478,7 @@ describe('ReactFlightDOM', () => {
} }
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
const stream1 = getTestStream(); const stream1 = getTestStream();
ReactServerDOMWriter.pipeToNodeWritable( ReactServerDOMWriter.pipeToNodeWritable(

View File

@ -73,7 +73,6 @@ describe('ReactTestRendererAsync', () => {
expect(renderer.toJSON()).toEqual(['A:2', 'B:2', 'C:2']); expect(renderer.toJSON()).toEqual(['A:2', 'B:2', 'C:2']);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('flushThrough flushes until the expected values is yielded', () => { it('flushThrough flushes until the expected values is yielded', () => {
function Child(props) { function Child(props) {
Scheduler.unstable_yieldValue(props.children); Scheduler.unstable_yieldValue(props.children);
@ -91,7 +90,7 @@ describe('ReactTestRendererAsync', () => {
let renderer; let renderer;
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
renderer = ReactTestRenderer.create(<Parent step={1} />, { renderer = ReactTestRenderer.create(<Parent step={1} />, {
unstable_isConcurrent: true, unstable_isConcurrent: true,
}); });
@ -112,7 +111,6 @@ describe('ReactTestRendererAsync', () => {
expect(renderer.toJSON()).toEqual(['A:1', 'B:1', 'C:1']); expect(renderer.toJSON()).toEqual(['A:1', 'B:1', 'C:1']);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('supports high priority interruptions', () => { it('supports high priority interruptions', () => {
function Child(props) { function Child(props) {
Scheduler.unstable_yieldValue(props.children); Scheduler.unstable_yieldValue(props.children);
@ -138,7 +136,7 @@ describe('ReactTestRendererAsync', () => {
let renderer; let renderer;
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
renderer = ReactTestRenderer.create(<Example step={1} />, { renderer = ReactTestRenderer.create(<Example step={1} />, {
unstable_isConcurrent: true, unstable_isConcurrent: true,
}); });

View File

@ -8,55 +8,52 @@
*/ */
export { export {
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
Children, Children,
createRef,
Component, Component,
Fragment,
Profiler,
PureComponent, PureComponent,
StrictMode,
Suspense,
SuspenseList,
SuspenseList as unstable_SuspenseList, // TODO: Remove once call sights updated to SuspenseList
cloneElement,
createContext, createContext,
createElement,
createFactory,
createMutableSource,
createMutableSource as unstable_createMutableSource,
createRef,
forwardRef, forwardRef,
isValidElement,
lazy, lazy,
memo, memo,
startTransition,
startTransition as unstable_startTransition, // TODO: Remove once call sights updated to startTransition
unstable_Cache,
unstable_DebugTracingMode,
unstable_LegacyHidden,
unstable_Scope,
unstable_getCacheForType,
unstable_useCacheRefresh,
unstable_useOpaqueIdentifier,
useCallback, useCallback,
useContext, useContext,
useDebugValue,
useDeferredValue,
useDeferredValue as unstable_useDeferredValue, // TODO: Remove once call sights updated to useDeferredValue
useEffect, useEffect,
useImperativeHandle, useImperativeHandle,
useDebugValue,
useLayoutEffect, useLayoutEffect,
useMemo, useMemo,
useMutableSource,
useMutableSource as unstable_useMutableSource,
useReducer, useReducer,
useRef, useRef,
useState, useState,
useMutableSource,
useMutableSource as unstable_useMutableSource,
createMutableSource,
createMutableSource as unstable_createMutableSource,
Fragment,
Profiler,
StrictMode,
Suspense,
unstable_LegacyHidden,
createElement,
cloneElement,
isValidElement,
version,
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
createFactory,
// exposeConcurrentModeAPIs
useTransition, useTransition,
useTransition as unstable_useTransition, useTransition as unstable_useTransition, // TODO: Remove once call sights updated to useTransition
useDeferredValue, version,
useDeferredValue as unstable_useDeferredValue,
startTransition,
startTransition as unstable_startTransition,
SuspenseList,
SuspenseList as unstable_SuspenseList,
unstable_getCacheForType,
unstable_Cache,
unstable_useCacheRefresh,
// enableScopeAPI
unstable_Scope,
unstable_useOpaqueIdentifier,
// enableDebugTracing
unstable_DebugTracingMode,
} from './src/React'; } from './src/React';
export {jsx, jsxs, jsxDEV} from './src/jsx/ReactJSX'; export {jsx, jsxs, jsxDEV} from './src/jsx/ReactJSX';

View File

@ -8,46 +8,44 @@
*/ */
export { export {
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
Children, Children,
createRef,
Component, Component,
Fragment,
Profiler,
PureComponent, PureComponent,
StrictMode,
Suspense,
SuspenseList,
cloneElement,
createContext, createContext,
createElement,
createFactory,
createMutableSource as unstable_createMutableSource,
createRef,
forwardRef, forwardRef,
isValidElement,
lazy, lazy,
memo, memo,
startTransition,
unstable_Cache,
unstable_DebugTracingMode,
unstable_LegacyHidden,
unstable_getCacheForType,
unstable_useCacheRefresh,
unstable_useOpaqueIdentifier,
useCallback, useCallback,
useContext, useContext,
useDebugValue,
useDeferredValue,
useEffect, useEffect,
useImperativeHandle, useImperativeHandle,
useDebugValue,
useLayoutEffect, useLayoutEffect,
useMemo, useMemo,
useMutableSource as unstable_useMutableSource,
useReducer, useReducer,
useRef, useRef,
useState, useState,
useMutableSource as unstable_useMutableSource, useTransition,
createMutableSource as unstable_createMutableSource,
Fragment,
Profiler,
StrictMode,
Suspense,
unstable_LegacyHidden,
createElement,
cloneElement,
isValidElement,
version, version,
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
createFactory,
// exposeConcurrentModeAPIs
useTransition as unstable_useTransition,
useDeferredValue as unstable_useDeferredValue,
startTransition as unstable_startTransition,
SuspenseList as unstable_SuspenseList,
unstable_useOpaqueIdentifier,
unstable_getCacheForType,
unstable_Cache,
unstable_useCacheRefresh,
// enableDebugTracing
unstable_DebugTracingMode,
} from './src/React'; } from './src/React';

View File

@ -32,51 +32,45 @@ export type ChildrenArray<+T> = $ReadOnlyArray<ChildrenArray<T>> | T;
// Export all exports so that they're available in tests. // Export all exports so that they're available in tests.
// We can't use export * from in Flow for some reason. // We can't use export * from in Flow for some reason.
export { export {
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
Children, Children,
createRef,
Component, Component,
Fragment,
Profiler,
PureComponent, PureComponent,
StrictMode,
Suspense,
SuspenseList,
cloneElement,
createContext, createContext,
createElement,
createFactory,
createMutableSource,
createRef,
forwardRef, forwardRef,
isValidElement,
lazy, lazy,
memo, memo,
startTransition,
unstable_Cache,
unstable_DebugTracingMode,
unstable_LegacyHidden,
unstable_Scope,
unstable_getCacheForType,
unstable_useCacheRefresh,
unstable_useOpaqueIdentifier,
useCallback, useCallback,
useContext, useContext,
useDebugValue,
useDeferredValue,
useEffect, useEffect,
useImperativeHandle, useImperativeHandle,
useDebugValue,
useLayoutEffect, useLayoutEffect,
useMemo, useMemo,
useMutableSource,
useReducer, useReducer,
useRef, useRef,
useState, useState,
useMutableSource,
useMutableSource as unstable_useMutableSource,
createMutableSource,
createMutableSource as unstable_createMutableSource,
Fragment,
Profiler,
unstable_DebugTracingMode,
StrictMode,
Suspense,
createElement,
cloneElement,
isValidElement,
version,
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
createFactory,
useTransition, useTransition,
useTransition as unstable_useTransition, version,
startTransition,
startTransition as unstable_startTransition,
useDeferredValue,
useDeferredValue as unstable_useDeferredValue,
SuspenseList,
SuspenseList as unstable_SuspenseList,
unstable_LegacyHidden,
unstable_Scope,
unstable_useOpaqueIdentifier,
unstable_getCacheForType,
unstable_Cache,
unstable_useCacheRefresh,
} from './src/React'; } from './src/React';

View File

@ -8,54 +8,51 @@
*/ */
export { export {
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
Children, Children,
createRef,
Component, Component,
Fragment,
Profiler,
PureComponent, PureComponent,
StrictMode,
Suspense,
SuspenseList,
SuspenseList as unstable_SuspenseList, // TODO: Remove once call sights updated to SuspenseList
cloneElement,
createContext, createContext,
createElement,
createMutableSource,
createMutableSource as unstable_createMutableSource,
createRef,
forwardRef, forwardRef,
isValidElement,
lazy, lazy,
memo, memo,
startTransition,
startTransition as unstable_startTransition, // TODO: Remove once call sights updated to startTransition
unstable_Cache,
unstable_DebugTracingMode,
unstable_LegacyHidden,
unstable_Scope,
unstable_getCacheForType,
unstable_useCacheRefresh,
unstable_useOpaqueIdentifier,
useCallback, useCallback,
useContext, useContext,
useDebugValue,
useDeferredValue,
useDeferredValue as unstable_useDeferredValue, // TODO: Remove once call sights updated to useDeferredValue
useEffect, useEffect,
useImperativeHandle, useImperativeHandle,
useDebugValue,
useLayoutEffect, useLayoutEffect,
useMemo, useMemo,
useMutableSource, useMutableSource,
useMutableSource as unstable_useMutableSource, useMutableSource as unstable_useMutableSource,
createMutableSource,
createMutableSource as unstable_createMutableSource,
useReducer, useReducer,
useRef, useRef,
useState, useState,
Fragment,
Profiler,
StrictMode,
Suspense,
unstable_LegacyHidden,
createElement,
cloneElement,
isValidElement,
version,
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
// exposeConcurrentModeAPIs
useTransition, useTransition,
useTransition as unstable_useTransition, useTransition as unstable_useTransition, // TODO: Remove once call sights updated to useTransition
useDeferredValue, version,
useDeferredValue as unstable_useDeferredValue,
startTransition,
startTransition as unstable_startTransition,
SuspenseList,
SuspenseList as unstable_SuspenseList,
unstable_getCacheForType,
unstable_Cache,
unstable_useCacheRefresh,
// enableScopeAPI
unstable_Scope,
unstable_useOpaqueIdentifier,
// enableDebugTracing
unstable_DebugTracingMode,
} from './src/React'; } from './src/React';
export {jsx, jsxs, jsxDEV} from './src/jsx/ReactJSX'; export {jsx, jsxs, jsxDEV} from './src/jsx/ReactJSX';

View File

@ -8,32 +8,39 @@
*/ */
export { export {
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
Children, Children,
createRef,
Component, Component,
Fragment,
Profiler,
PureComponent, PureComponent,
StrictMode,
Suspense,
SuspenseList,
cloneElement,
createContext, createContext,
createElement,
createFactory,
createMutableSource as unstable_createMutableSource,
createRef,
forwardRef, forwardRef,
isValidElement,
lazy, lazy,
memo, memo,
startTransition,
unstable_useOpaqueIdentifier,
useCallback, useCallback,
useContext, useContext,
useDebugValue,
useDeferredValue,
useEffect, useEffect,
useImperativeHandle, useImperativeHandle,
useDebugValue,
useLayoutEffect, useLayoutEffect,
useMemo, useMemo,
useMutableSource as unstable_useMutableSource,
useReducer, useReducer,
useRef, useRef,
useState, useState,
Fragment, useTransition,
Profiler,
StrictMode,
Suspense,
createElement,
cloneElement,
isValidElement,
version, version,
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
createFactory,
} from './src/React'; } from './src/React';

View File

@ -186,7 +186,6 @@ describe(`onRender`, () => {
expect(callback).toHaveBeenCalledTimes(2); expect(callback).toHaveBeenCalledTimes(2);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('is not invoked until the commit phase', () => { it('is not invoked until the commit phase', () => {
const callback = jest.fn(); const callback = jest.fn();
@ -196,7 +195,7 @@ describe(`onRender`, () => {
}; };
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactTestRenderer.create( ReactTestRenderer.create(
<React.Profiler id="test" onRender={callback}> <React.Profiler id="test" onRender={callback}>
<Yield value="first" /> <Yield value="first" />
@ -690,7 +689,6 @@ describe(`onRender`, () => {
expect(onRender.mock.calls[2][1]).toBe('update'); expect(onRender.mock.calls[2][1]).toBe('update');
}); });
// @gate experimental
it('is properly distinguish updates and nested-updates when there is more than sync remaining work', () => { it('is properly distinguish updates and nested-updates when there is more than sync remaining work', () => {
loadModules({ loadModules({
useNoopRenderer: true, useNoopRenderer: true,
@ -709,7 +707,7 @@ describe(`onRender`, () => {
const onRender = jest.fn(); const onRender = jest.fn();
// Schedule low-priority work. // Schedule low-priority work.
React.unstable_startTransition(() => React.startTransition(() =>
ReactNoop.render( ReactNoop.render(
<React.Profiler id="root" onRender={onRender}> <React.Profiler id="root" onRender={onRender}>
<Component /> <Component />
@ -734,7 +732,6 @@ describe(`onRender`, () => {
}); });
describe('with regard to interruptions', () => { describe('with regard to interruptions', () => {
// @gate experimental || !enableSyncDefaultUpdates
it('should accumulate actual time after a scheduling interruptions', () => { it('should accumulate actual time after a scheduling interruptions', () => {
const callback = jest.fn(); const callback = jest.fn();
@ -748,7 +745,7 @@ describe(`onRender`, () => {
// Render partially, but run out of time before completing. // Render partially, but run out of time before completing.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactTestRenderer.create( ReactTestRenderer.create(
<React.Profiler id="test" onRender={callback}> <React.Profiler id="test" onRender={callback}>
<Yield renderTime={2} /> <Yield renderTime={2} />
@ -781,7 +778,6 @@ describe(`onRender`, () => {
expect(call[5]).toBe(10); // commit time expect(call[5]).toBe(10); // commit time
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('should not include time between frames', () => { it('should not include time between frames', () => {
const callback = jest.fn(); const callback = jest.fn();
@ -796,7 +792,7 @@ describe(`onRender`, () => {
// Render partially, but don't finish. // Render partially, but don't finish.
// This partial render should take 5ms of simulated time. // This partial render should take 5ms of simulated time.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
ReactTestRenderer.create( ReactTestRenderer.create(
<React.Profiler id="outer" onRender={callback}> <React.Profiler id="outer" onRender={callback}>
<Yield renderTime={5} /> <Yield renderTime={5} />
@ -847,7 +843,6 @@ describe(`onRender`, () => {
expect(outerCall[5]).toBe(87); // commit time expect(outerCall[5]).toBe(87); // commit time
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('should report the expected times when a high-pri update replaces a mount in-progress', () => { it('should report the expected times when a high-pri update replaces a mount in-progress', () => {
const callback = jest.fn(); const callback = jest.fn();
@ -863,7 +858,7 @@ describe(`onRender`, () => {
// This partial render should take 10ms of simulated time. // This partial render should take 10ms of simulated time.
let renderer; let renderer;
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
renderer = ReactTestRenderer.create( renderer = ReactTestRenderer.create(
<React.Profiler id="test" onRender={callback}> <React.Profiler id="test" onRender={callback}>
<Yield renderTime={10} /> <Yield renderTime={10} />
@ -914,7 +909,6 @@ describe(`onRender`, () => {
expect(callback).toHaveBeenCalledTimes(0); expect(callback).toHaveBeenCalledTimes(0);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('should report the expected times when a high-priority update replaces a low-priority update', () => { it('should report the expected times when a high-priority update replaces a low-priority update', () => {
const callback = jest.fn(); const callback = jest.fn();
@ -951,7 +945,7 @@ describe(`onRender`, () => {
// Render a partially update, but don't finish. // Render a partially update, but don't finish.
// This partial render should take 3ms of simulated time. // This partial render should take 3ms of simulated time.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
renderer.update( renderer.update(
<React.Profiler id="test" onRender={callback}> <React.Profiler id="test" onRender={callback}>
<Yield renderTime={3} /> <Yield renderTime={3} />
@ -1008,7 +1002,6 @@ describe(`onRender`, () => {
expect(callback).toHaveBeenCalledTimes(1); expect(callback).toHaveBeenCalledTimes(1);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('should report the expected times when a high-priority update interrupts a low-priority update', () => { it('should report the expected times when a high-priority update interrupts a low-priority update', () => {
const callback = jest.fn(); const callback = jest.fn();
@ -1076,7 +1069,7 @@ describe(`onRender`, () => {
// Render a partially update, but don't finish. // Render a partially update, but don't finish.
// This partial render will take 10ms of actual render time. // This partial render will take 10ms of actual render time.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
first.setState({renderTime: 10}); first.setState({renderTime: 10});
}); });
} else { } else {

View File

@ -138,7 +138,6 @@ describe('ReactProfiler DevTools integration', () => {
).toBe(7); ).toBe(7);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('regression test: #17159', () => { it('regression test: #17159', () => {
function Text({text}) { function Text({text}) {
Scheduler.unstable_yieldValue(text); Scheduler.unstable_yieldValue(text);
@ -157,7 +156,7 @@ describe('ReactProfiler DevTools integration', () => {
Scheduler.unstable_advanceTime(10000); Scheduler.unstable_advanceTime(10000);
// Schedule an update. // Schedule an update.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
root.update(<Text text="B" />); root.update(<Text text="B" />);
}); });
} else { } else {

View File

@ -49,7 +49,6 @@ describe('ReactStrictMode', () => {
return null; return null;
} }
// @gate experimental
it('should default to not strict', () => { it('should default to not strict', () => {
act(() => { act(() => {
const container = document.createElement('div'); const container = document.createElement('div');
@ -65,7 +64,6 @@ describe('ReactStrictMode', () => {
}); });
if (__DEV__) { if (__DEV__) {
// @gate experimental
it('should support enabling strict mode via createRoot option', () => { it('should support enabling strict mode via createRoot option', () => {
act(() => { act(() => {
const container = document.createElement('div'); const container = document.createElement('div');
@ -87,7 +85,6 @@ describe('ReactStrictMode', () => {
]); ]);
}); });
// @gate experimental
it('should include legacy + strict effects mode', () => { it('should include legacy + strict effects mode', () => {
act(() => { act(() => {
const container = document.createElement('div'); const container = document.createElement('div');
@ -111,7 +108,6 @@ describe('ReactStrictMode', () => {
]); ]);
}); });
// @gate experimental
it('should allow level to be increased with nesting', () => { it('should allow level to be increased with nesting', () => {
act(() => { act(() => {
const container = document.createElement('div'); const container = document.createElement('div');

View File

@ -362,7 +362,6 @@ describe('Concurrent Mode', () => {
Scheduler = require('scheduler'); Scheduler = require('scheduler');
}); });
// @gate experimental
it('should warn about unsafe legacy lifecycle methods anywhere in a StrictMode tree', () => { it('should warn about unsafe legacy lifecycle methods anywhere in a StrictMode tree', () => {
function StrictRoot() { function StrictRoot() {
return ( return (
@ -405,7 +404,7 @@ describe('Concurrent Mode', () => {
} }
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<StrictRoot />); root.render(<StrictRoot />);
expect(() => Scheduler.unstable_flushAll()).toErrorDev( expect(() => Scheduler.unstable_flushAll()).toErrorDev(
[ [
@ -436,7 +435,6 @@ Please update the following components: App`,
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
}); });
// @gate experimental
it('should coalesce warnings by lifecycle name', () => { it('should coalesce warnings by lifecycle name', () => {
function StrictRoot() { function StrictRoot() {
return ( return (
@ -468,7 +466,7 @@ Please update the following components: App`,
} }
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<StrictRoot />); root.render(<StrictRoot />);
expect(() => { expect(() => {
@ -526,7 +524,6 @@ Please update the following components: Parent`,
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
}); });
// @gate experimental
it('should warn about components not present during the initial render', () => { it('should warn about components not present during the initial render', () => {
function StrictRoot({foo}) { function StrictRoot({foo}) {
return <React.StrictMode>{foo ? <Foo /> : <Bar />}</React.StrictMode>; return <React.StrictMode>{foo ? <Foo /> : <Bar />}</React.StrictMode>;
@ -545,7 +542,7 @@ Please update the following components: Parent`,
} }
const container = document.createElement('div'); const container = document.createElement('div');
const root = ReactDOM.unstable_createRoot(container); const root = ReactDOM.createRoot(container);
root.render(<StrictRoot foo={true} />); root.render(<StrictRoot foo={true} />);
expect(() => expect(() =>
Scheduler.unstable_flushAll(), Scheduler.unstable_flushAll(),

View File

@ -8,31 +8,32 @@
*/ */
export { export {
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
Children, Children,
createRef,
forwardRef,
lazy,
memo,
useCallback,
useContext,
useDebugValue,
useMemo,
useMutableSource as unstable_useMutableSource,
createMutableSource as unstable_createMutableSource,
Fragment, Fragment,
Profiler, Profiler,
StrictMode, StrictMode,
Suspense, Suspense,
createElement, SuspenseList,
cloneElement, cloneElement,
createElement,
createMutableSource as unstable_createMutableSource,
createRef,
forwardRef,
isValidElement, isValidElement,
version, lazy,
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, memo,
// exposeConcurrentModeAPIs startTransition,
useDeferredValue as unstable_useDeferredValue,
SuspenseList as unstable_SuspenseList,
unstable_useOpaqueIdentifier,
unstable_getCacheForType,
// enableDebugTracing
unstable_DebugTracingMode, unstable_DebugTracingMode,
unstable_getCacheForType,
unstable_useOpaqueIdentifier,
useCallback,
useContext,
useDebugValue,
useDeferredValue,
useDeferredValue as unstable_useDeferredValue,
useMemo,
useMutableSource as unstable_useMutableSource,
useTransition,
version,
} from './src/React'; } from './src/React';

View File

@ -55,11 +55,11 @@ export const enableProfilerNestedUpdateScheduledHook = false;
export const enableUpdaterTracking = __PROFILE__; export const enableUpdaterTracking = __PROFILE__;
// SSR experiments // SSR experiments
export const enableSuspenseServerRenderer = __EXPERIMENTAL__; export const enableSuspenseServerRenderer = true;
export const enableSelectiveHydration = __EXPERIMENTAL__; export const enableSelectiveHydration = true;
// Flight experiments // Flight experiments
export const enableLazyElements = __EXPERIMENTAL__; export const enableLazyElements = true;
export const enableCache = __EXPERIMENTAL__; export const enableCache = __EXPERIMENTAL__;
// Only used in www builds. // Only used in www builds.

View File

@ -23,7 +23,7 @@ export const enableSuspenseLayoutEffectSemantics = __VARIANT__;
// Enable this flag to help with concurrent mode debugging. // Enable this flag to help with concurrent mode debugging.
// It logs information to the console about React scheduling, rendering, and commit phases. // It logs information to the console about React scheduling, rendering, and commit phases.
// //
// NOTE: This feature will only work in DEV mode; all callsights are wrapped with __DEV__. // NOTE: This feature will only work in DEV mode; all callsites are wrapped with __DEV__.
export const enableDebugTracing = __EXPERIMENTAL__; export const enableDebugTracing = __EXPERIMENTAL__;
export const enableUpdaterTracking = false; export const enableUpdaterTracking = false;

View File

@ -262,7 +262,6 @@ describe('useSubscription', () => {
expect(subscriptions).toHaveLength(2); expect(subscriptions).toHaveLength(2);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('should ignore values emitted by a new subscribable until the commit phase', () => { it('should ignore values emitted by a new subscribable until the commit phase', () => {
const log = []; const log = [];
@ -333,7 +332,7 @@ describe('useSubscription', () => {
// Start React update, but don't finish // Start React update, but don't finish
act(() => { act(() => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
renderer.update(<Parent observed={observableB} />); renderer.update(<Parent observed={observableB} />);
}); });
} else { } else {
@ -370,7 +369,6 @@ describe('useSubscription', () => {
]); ]);
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('should not drop values emitted between updates', () => { it('should not drop values emitted between updates', () => {
const log = []; const log = [];
@ -442,7 +440,7 @@ describe('useSubscription', () => {
// Start React update, but don't finish // Start React update, but don't finish
act(() => { act(() => {
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
renderer.update(<Parent observed={observableB} />); renderer.update(<Parent observed={observableB} />);
}); });
} else { } else {
@ -576,7 +574,6 @@ describe('useSubscription', () => {
Scheduler.unstable_flushAll(); Scheduler.unstable_flushAll();
}); });
// @gate experimental || !enableSyncDefaultUpdates
it('should not tear if a mutation occurs during a concurrent update', () => { it('should not tear if a mutation occurs during a concurrent update', () => {
const input = document.createElement('input'); const input = document.createElement('input');
@ -625,7 +622,7 @@ describe('useSubscription', () => {
// This update will not be eagerly evaluated, // This update will not be eagerly evaluated,
// but useSubscription() should eagerly close over the updated value to avoid tearing. // but useSubscription() should eagerly close over the updated value to avoid tearing.
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
mutate('C'); mutate('C');
}); });
} else { } else {
@ -633,7 +630,7 @@ describe('useSubscription', () => {
} }
expect(Scheduler).toFlushAndYieldThrough(['render:first:C']); expect(Scheduler).toFlushAndYieldThrough(['render:first:C']);
if (gate(flags => flags.enableSyncDefaultUpdates)) { if (gate(flags => flags.enableSyncDefaultUpdates)) {
React.unstable_startTransition(() => { React.startTransition(() => {
mutate('D'); mutate('D');
}); });
} else { } else {