Clean up context access profiling experiment (#31806)

We introduced the `unstable_useContextWithBailout` API to run compiler
based experiments. This API was designed to be an experiment proxy for
alternative approaches which would be heavier to implement. The
experiment turned out to be inconclusive. Since most of our performance
critical usage is already optimized, we weren't able to find a clear win
with this approach.

Since we don't have further plans for this API, let's clean it up.
This commit is contained in:
Jack Pope
2024-12-16 12:32:07 -05:00
committed by GitHub
parent 3eb371cc7b
commit ea2ac1e56b
15 changed files with 16 additions and 548 deletions
+1 -29
View File
@@ -20,7 +20,6 @@ import type {
Dependencies,
Fiber,
Dispatcher as DispatcherType,
ContextDependencyWithSelect,
} from 'react-reconciler/src/ReactInternalTypes';
import type {TransitionStatus} from 'react-reconciler/src/ReactFiberConfig';
@@ -76,13 +75,6 @@ function getPrimitiveStackCache(): Map<string, Array<any>> {
try {
// Use all hooks here to add them to the hook log.
Dispatcher.useContext(({_currentValue: null}: any));
if (typeof Dispatcher.unstable_useContextWithBailout === 'function') {
// This type check is for Flow only.
Dispatcher.unstable_useContextWithBailout(
({_currentValue: null}: any),
null,
);
}
Dispatcher.useState(null);
Dispatcher.useReducer((s: mixed, a: mixed) => s, null);
Dispatcher.useRef(null);
@@ -150,10 +142,7 @@ function getPrimitiveStackCache(): Map<string, Array<any>> {
let currentFiber: null | Fiber = null;
let currentHook: null | Hook = null;
let currentContextDependency:
| null
| ContextDependency<mixed>
| ContextDependencyWithSelect<mixed> = null;
let currentContextDependency: null | ContextDependency<mixed> = null;
function nextHook(): null | Hook {
const hook = currentHook;
@@ -274,22 +263,6 @@ function useContext<T>(context: ReactContext<T>): T {
return value;
}
function unstable_useContextWithBailout<T>(
context: ReactContext<T>,
select: (T => Array<mixed>) | null,
): T {
const value = readContext(context);
hookLog.push({
displayName: context.displayName || null,
primitive: 'ContextWithBailout',
stackError: new Error(),
value: value,
debugInfo: null,
dispatcherHookName: 'ContextWithBailout',
});
return value;
}
function useState<S>(
initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
@@ -764,7 +737,6 @@ const Dispatcher: DispatcherType = {
useCacheRefresh,
useCallback,
useContext,
unstable_useContextWithBailout,
useEffect,
useImperativeHandle,
useDebugValue,
+2 -113
View File
@@ -39,12 +39,11 @@ import {
enableLazyContextPropagation,
enableTransitionTracing,
enableUseEffectEventHook,
enableUseResourceEffectHook,
enableLegacyCache,
debugRenderPhaseSideEffectsForStrictMode,
disableLegacyMode,
enableNoCloningMemoCache,
enableContextProfiling,
enableUseResourceEffectHook,
} from 'shared/ReactFeatureFlags';
import {
REACT_CONTEXT_TYPE,
@@ -78,11 +77,7 @@ import {
ContinuousEventPriority,
higherEventPriority,
} from './ReactEventPriorities';
import {
readContext,
readContextAndCompare,
checkIfContextChanged,
} from './ReactFiberNewContext';
import {readContext, checkIfContextChanged} from './ReactFiberNewContext';
import {HostRoot, CacheComponent, HostComponent} from './ReactWorkTags';
import {
LayoutStatic as LayoutStaticEffect,
@@ -1111,16 +1106,6 @@ function updateWorkInProgressHook(): Hook {
return workInProgressHook;
}
function unstable_useContextWithBailout<T>(
context: ReactContext<T>,
select: (T => Array<mixed>) | null,
): T {
if (select === null) {
return readContext(context);
}
return readContextAndCompare(context, select);
}
function createFunctionComponentUpdateQueue(): FunctionComponentUpdateQueue {
return {
lastEffect: null,
@@ -3958,10 +3943,6 @@ if (enableUseEffectEventHook) {
if (enableUseResourceEffectHook) {
(ContextOnlyDispatcher: Dispatcher).useResourceEffect = throwInvalidHookError;
}
if (enableContextProfiling) {
(ContextOnlyDispatcher: Dispatcher).unstable_useContextWithBailout =
throwInvalidHookError;
}
const HooksDispatcherOnMount: Dispatcher = {
readContext,
@@ -3995,10 +3976,6 @@ if (enableUseEffectEventHook) {
if (enableUseResourceEffectHook) {
(HooksDispatcherOnMount: Dispatcher).useResourceEffect = mountResourceEffect;
}
if (enableContextProfiling) {
(HooksDispatcherOnMount: Dispatcher).unstable_useContextWithBailout =
unstable_useContextWithBailout;
}
const HooksDispatcherOnUpdate: Dispatcher = {
readContext,
@@ -4033,10 +4010,6 @@ if (enableUseResourceEffectHook) {
(HooksDispatcherOnUpdate: Dispatcher).useResourceEffect =
updateResourceEffect;
}
if (enableContextProfiling) {
(HooksDispatcherOnUpdate: Dispatcher).unstable_useContextWithBailout =
unstable_useContextWithBailout;
}
const HooksDispatcherOnRerender: Dispatcher = {
readContext,
@@ -4071,10 +4044,6 @@ if (enableUseResourceEffectHook) {
(HooksDispatcherOnRerender: Dispatcher).useResourceEffect =
updateResourceEffect;
}
if (enableContextProfiling) {
(HooksDispatcherOnRerender: Dispatcher).unstable_useContextWithBailout =
unstable_useContextWithBailout;
}
let HooksDispatcherOnMountInDEV: Dispatcher | null = null;
let HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher | null = null;
@@ -4296,17 +4265,6 @@ if (__DEV__) {
);
};
}
if (enableContextProfiling) {
(HooksDispatcherOnMountInDEV: Dispatcher).unstable_useContextWithBailout =
function <T>(
context: ReactContext<T>,
select: (T => Array<mixed>) | null,
): T {
currentHookNameInDev = 'useContext';
mountHookTypesDev();
return unstable_useContextWithBailout(context, select);
};
}
HooksDispatcherOnMountWithHookTypesInDEV = {
readContext<T>(context: ReactContext<T>): T {
@@ -4494,17 +4452,6 @@ if (__DEV__) {
);
};
}
if (enableContextProfiling) {
(HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher).unstable_useContextWithBailout =
function <T>(
context: ReactContext<T>,
select: (T => Array<mixed>) | null,
): T {
currentHookNameInDev = 'useContext';
updateHookTypesDev();
return unstable_useContextWithBailout(context, select);
};
}
HooksDispatcherOnUpdateInDEV = {
readContext<T>(context: ReactContext<T>): T {
@@ -4692,17 +4639,6 @@ if (__DEV__) {
);
};
}
if (enableContextProfiling) {
(HooksDispatcherOnUpdateInDEV: Dispatcher).unstable_useContextWithBailout =
function <T>(
context: ReactContext<T>,
select: (T => Array<mixed>) | null,
): T {
currentHookNameInDev = 'useContext';
updateHookTypesDev();
return unstable_useContextWithBailout(context, select);
};
}
HooksDispatcherOnRerenderInDEV = {
readContext<T>(context: ReactContext<T>): T {
@@ -4890,17 +4826,6 @@ if (__DEV__) {
);
};
}
if (enableContextProfiling) {
(HooksDispatcherOnRerenderInDEV: Dispatcher).unstable_useContextWithBailout =
function <T>(
context: ReactContext<T>,
select: (T => Array<mixed>) | null,
): T {
currentHookNameInDev = 'useContext';
updateHookTypesDev();
return unstable_useContextWithBailout(context, select);
};
}
InvalidNestedHooksDispatcherOnMountInDEV = {
readContext<T>(context: ReactContext<T>): T {
@@ -5114,18 +5039,6 @@ if (__DEV__) {
);
};
}
if (enableContextProfiling) {
(InvalidNestedHooksDispatcherOnMountInDEV: Dispatcher).unstable_useContextWithBailout =
function <T>(
context: ReactContext<T>,
select: (T => Array<mixed>) | null,
): T {
currentHookNameInDev = 'useContext';
warnInvalidHookAccess();
mountHookTypesDev();
return unstable_useContextWithBailout(context, select);
};
}
InvalidNestedHooksDispatcherOnUpdateInDEV = {
readContext<T>(context: ReactContext<T>): T {
@@ -5339,18 +5252,6 @@ if (__DEV__) {
);
};
}
if (enableContextProfiling) {
(InvalidNestedHooksDispatcherOnUpdateInDEV: Dispatcher).unstable_useContextWithBailout =
function <T>(
context: ReactContext<T>,
select: (T => Array<mixed>) | null,
): T {
currentHookNameInDev = 'useContext';
warnInvalidHookAccess();
updateHookTypesDev();
return unstable_useContextWithBailout(context, select);
};
}
InvalidNestedHooksDispatcherOnRerenderInDEV = {
readContext<T>(context: ReactContext<T>): T {
@@ -5564,16 +5465,4 @@ if (__DEV__) {
);
};
}
if (enableContextProfiling) {
(InvalidNestedHooksDispatcherOnRerenderInDEV: Dispatcher).unstable_useContextWithBailout =
function <T>(
context: ReactContext<T>,
select: (T => Array<mixed>) | null,
): T {
currentHookNameInDev = 'useContext';
warnInvalidHookAccess();
updateHookTypesDev();
return unstable_useContextWithBailout(context, select);
};
}
}
+6 -131
View File
@@ -12,7 +12,6 @@ import type {
Fiber,
ContextDependency,
Dependencies,
ContextDependencyWithSelect,
} from './ReactInternalTypes';
import type {StackCursor} from './ReactFiberStack';
import type {Lanes} from './ReactFiberLane';
@@ -48,8 +47,6 @@ import {
enableRenderableContext,
} from 'shared/ReactFeatureFlags';
import {getHostTransitionProvider} from './ReactFiberHostContext';
import isArray from '../../shared/isArray';
import {enableContextProfiling} from '../../shared/ReactFeatureFlags';
const valueCursor: StackCursor<mixed> = createCursor(null);
@@ -69,10 +66,7 @@ if (__DEV__) {
}
let currentlyRenderingFiber: Fiber | null = null;
let lastContextDependency:
| ContextDependency<mixed>
| ContextDependencyWithSelect<mixed>
| null = null;
let lastContextDependency: ContextDependency<mixed> | null = null;
let isDisallowedContextReadInDEV: boolean = false;
@@ -401,23 +395,6 @@ function propagateContextChanges<T>(
const context: ReactContext<T> = contexts[i];
// Check if the context matches.
if (dependency.context === context) {
if (enableContextProfiling) {
const select = dependency.select;
if (select != null && dependency.lastSelectedValue != null) {
const newValue = isPrimaryRenderer
? dependency.context._currentValue
: dependency.context._currentValue2;
if (
!checkIfSelectedContextValuesChanged(
dependency.lastSelectedValue,
select(newValue),
)
) {
// Compared value hasn't changed. Bail out early.
continue findContext;
}
}
}
// Match! Schedule an update on this fiber.
// In the lazy implementation, don't mark a dirty flag on the
@@ -657,29 +634,6 @@ function propagateParentContextChanges(
workInProgress.flags |= DidPropagateContext;
}
function checkIfSelectedContextValuesChanged(
oldComparedValue: Array<mixed>,
newComparedValue: Array<mixed>,
): boolean {
// We have an implicit contract that compare functions must return arrays.
// This allows us to compare multiple values in the same context access
// since compiling to additional hook calls regresses perf.
if (isArray(oldComparedValue) && isArray(newComparedValue)) {
if (oldComparedValue.length !== newComparedValue.length) {
return true;
}
for (let i = 0; i < oldComparedValue.length; i++) {
if (!is(newComparedValue[i], oldComparedValue[i])) {
return true;
}
}
} else {
throw new Error('Compared context values must be arrays');
}
return false;
}
export function checkIfContextChanged(
currentDependencies: Dependencies,
): boolean {
@@ -698,23 +652,8 @@ export function checkIfContextChanged(
? context._currentValue
: context._currentValue2;
const oldValue = dependency.memoizedValue;
if (
enableContextProfiling &&
dependency.select != null &&
dependency.lastSelectedValue != null
) {
if (
checkIfSelectedContextValuesChanged(
dependency.lastSelectedValue,
dependency.select(newValue),
)
) {
return true;
}
} else {
if (!is(newValue, oldValue)) {
return true;
}
if (!is(newValue, oldValue)) {
return true;
}
dependency = dependency.next;
}
@@ -747,21 +686,6 @@ export function prepareToReadContext(
}
}
export function readContextAndCompare<C>(
context: ReactContext<C>,
select: C => Array<mixed>,
): C {
if (!(enableLazyContextPropagation && enableContextProfiling)) {
throw new Error('Not implemented.');
}
return readContextForConsumer_withSelect(
currentlyRenderingFiber,
context,
select,
);
}
export function readContext<T>(context: ReactContext<T>): T {
if (__DEV__) {
// This warning would fire if you read context inside a Hook like useMemo.
@@ -789,59 +713,10 @@ export function readContextDuringReconciliation<T>(
return readContextForConsumer(consumer, context);
}
function readContextForConsumer_withSelect<C>(
function readContextForConsumer<T>(
consumer: Fiber | null,
context: ReactContext<C>,
select: C => Array<mixed>,
): C {
const value = isPrimaryRenderer
? context._currentValue
: context._currentValue2;
const contextItem = {
context: ((context: any): ReactContext<mixed>),
memoizedValue: value,
next: null,
select: ((select: any): (context: mixed) => Array<mixed>),
lastSelectedValue: select(value),
};
if (lastContextDependency === null) {
if (consumer === null) {
throw new Error(
'Context can only be read while React is rendering. ' +
'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
'In function components, you can read it directly in the function body, but not ' +
'inside Hooks like useReducer() or useMemo().',
);
}
// This is the first dependency for this component. Create a new list.
lastContextDependency = contextItem;
consumer.dependencies = __DEV__
? {
lanes: NoLanes,
firstContext: contextItem,
_debugThenableState: null,
}
: {
lanes: NoLanes,
firstContext: contextItem,
};
if (enableLazyContextPropagation) {
consumer.flags |= NeedsPropagation;
}
} else {
// Append a new context item.
lastContextDependency = lastContextDependency.next = contextItem;
}
return value;
}
function readContextForConsumer<C>(
consumer: Fiber | null,
context: ReactContext<C>,
): C {
context: ReactContext<T>,
): T {
const value = isPrimaryRenderer
? context._currentValue
: context._currentValue2;
+7 -20
View File
@@ -63,27 +63,18 @@ export type HookType =
| 'useFormState'
| 'useActionState';
export type ContextDependency<C> = {
context: ReactContext<C>,
next: ContextDependency<mixed> | ContextDependencyWithSelect<mixed> | null,
memoizedValue: C,
};
export type ContextDependencyWithSelect<C> = {
context: ReactContext<C>,
next: ContextDependency<mixed> | ContextDependencyWithSelect<mixed> | null,
memoizedValue: C,
select: C => Array<mixed>,
lastSelectedValue: ?Array<mixed>,
export type ContextDependency<T> = {
context: ReactContext<T>,
next: ContextDependency<mixed> | null,
memoizedValue: T,
...
};
export type Dependencies = {
lanes: Lanes,
firstContext:
| ContextDependency<mixed>
| ContextDependencyWithSelect<mixed>
| null,
firstContext: ContextDependency<mixed> | null,
_debugThenableState?: null | ThenableState, // DEV-only
...
};
export type MemoCache = {
@@ -401,10 +392,6 @@ export type Dispatcher = {
initialArg: I,
init?: (I) => S,
): [S, Dispatch<A>],
unstable_useContextWithBailout?: <T>(
context: ReactContext<T>,
select: (T => Array<mixed>) | null,
) => T,
useContext<T>(context: ReactContext<T>): T,
useRef<T>(initialValue: T): {current: T},
useEffect(
@@ -1,217 +0,0 @@
let React;
let ReactNoop;
let Scheduler;
let act;
let assertLog;
let useState;
let useContext;
let unstable_useContextWithBailout;
describe('ReactContextWithBailout', () => {
beforeEach(() => {
jest.resetModules();
React = require('react');
ReactNoop = require('react-noop-renderer');
Scheduler = require('scheduler');
const testUtils = require('internal-test-utils');
act = testUtils.act;
assertLog = testUtils.assertLog;
useState = React.useState;
useContext = React.useContext;
unstable_useContextWithBailout = React.unstable_useContextWithBailout;
});
function Text({text}) {
Scheduler.log(text);
return text;
}
// @gate enableLazyContextPropagation && enableContextProfiling
test('unstable_useContextWithBailout basic usage', async () => {
const Context = React.createContext();
let setContext;
function App() {
const [context, _setContext] = useState({a: 'A0', b: 'B0', c: 'C0'});
setContext = _setContext;
return (
<Context.Provider value={context}>
<Indirection />
</Context.Provider>
);
}
// Intermediate parent that bails out. Children will only re-render when the
// context changes.
const Indirection = React.memo(() => {
return (
<>
A: <A />, B: <B />, C: <C />, AB: <AB />
</>
);
});
function A() {
const {a} = unstable_useContextWithBailout(Context, context => [
context.a,
]);
return <Text text={a} />;
}
function B() {
const {b} = unstable_useContextWithBailout(Context, context => [
context.b,
]);
return <Text text={b} />;
}
function C() {
const {c} = unstable_useContextWithBailout(Context, context => [
context.c,
]);
return <Text text={c} />;
}
function AB() {
const {a, b} = unstable_useContextWithBailout(Context, context => [
context.a,
context.b,
]);
return <Text text={a + b} />;
}
const root = ReactNoop.createRoot();
await act(async () => {
root.render(<App />);
});
assertLog(['A0', 'B0', 'C0', 'A0B0']);
expect(root).toMatchRenderedOutput('A: A0, B: B0, C: C0, AB: A0B0');
// Update a. Only the A and AB consumer should re-render.
await act(async () => {
setContext({a: 'A1', c: 'C0', b: 'B0'});
});
assertLog(['A1', 'A1B0']);
expect(root).toMatchRenderedOutput('A: A1, B: B0, C: C0, AB: A1B0');
// Update b. Only the B and AB consumer should re-render.
await act(async () => {
setContext({a: 'A1', b: 'B1', c: 'C0'});
});
assertLog(['B1', 'A1B1']);
expect(root).toMatchRenderedOutput('A: A1, B: B1, C: C0, AB: A1B1');
// Update c. Only the C consumer should re-render.
await act(async () => {
setContext({a: 'A1', b: 'B1', c: 'C1'});
});
assertLog(['C1']);
expect(root).toMatchRenderedOutput('A: A1, B: B1, C: C1, AB: A1B1');
});
// @gate enableLazyContextPropagation && enableContextProfiling
test('unstable_useContextWithBailout and useContext subscribing to same context in same component', async () => {
const Context = React.createContext();
let setContext;
function App() {
const [context, _setContext] = useState({a: 0, b: 0, unrelated: 0});
setContext = _setContext;
return (
<Context.Provider value={context}>
<Indirection />
</Context.Provider>
);
}
// Intermediate parent that bails out. Children will only re-render when the
// context changes.
const Indirection = React.memo(() => {
return <Child />;
});
function Child() {
const {a} = unstable_useContextWithBailout(Context, context => [
context.a,
]);
const context = useContext(Context);
return <Text text={`A: ${a}, B: ${context.b}`} />;
}
const root = ReactNoop.createRoot();
await act(async () => {
root.render(<App />);
});
assertLog(['A: 0, B: 0']);
expect(root).toMatchRenderedOutput('A: 0, B: 0');
// Update an unrelated field that isn't used by the component. The context
// attempts to bail out, but the normal context forces an update.
await act(async () => {
setContext({a: 0, b: 0, unrelated: 1});
});
assertLog(['A: 0, B: 0']);
expect(root).toMatchRenderedOutput('A: 0, B: 0');
});
// @gate enableLazyContextPropagation && enableContextProfiling
test('unstable_useContextWithBailout and useContext subscribing to different contexts in same component', async () => {
const ContextA = React.createContext();
const ContextB = React.createContext();
let setContextA;
let setContextB;
function App() {
const [a, _setContextA] = useState({a: 0, unrelated: 0});
const [b, _setContextB] = useState(0);
setContextA = _setContextA;
setContextB = _setContextB;
return (
<ContextA.Provider value={a}>
<ContextB.Provider value={b}>
<Indirection />
</ContextB.Provider>
</ContextA.Provider>
);
}
// Intermediate parent that bails out. Children will only re-render when the
// context changes.
const Indirection = React.memo(() => {
return <Child />;
});
function Child() {
const {a} = unstable_useContextWithBailout(ContextA, context => [
context.a,
]);
const b = useContext(ContextB);
return <Text text={`A: ${a}, B: ${b}`} />;
}
const root = ReactNoop.createRoot();
await act(async () => {
root.render(<App />);
});
assertLog(['A: 0, B: 0']);
expect(root).toMatchRenderedOutput('A: 0, B: 0');
// Update a field in A that isn't part of the compared context. It should
// bail out.
await act(async () => {
setContextA({a: 0, unrelated: 1});
});
assertLog([]);
expect(root).toMatchRenderedOutput('A: 0, B: 0');
// Now update the same a field again, but this time, also update a different
// context in the same batch. The other context prevents a bail out.
await act(async () => {
setContextA({a: 0, unrelated: 1});
setContextB(1);
});
assertLog(['A: 0, B: 1']);
expect(root).toMatchRenderedOutput('A: 0, B: 1');
});
});
-1
View File
@@ -42,7 +42,6 @@ export {
use,
useActionState,
useCallback,
unstable_useContextWithBailout,
useContext,
useDebugValue,
useDeferredValue,
-2
View File
@@ -37,7 +37,6 @@ import {postpone} from './ReactPostpone';
import {
getCacheForType,
useCallback,
unstable_useContextWithBailout,
useContext,
useEffect,
useEffectEvent,
@@ -86,7 +85,6 @@ export {
cache,
postpone as unstable_postpone,
useCallback,
unstable_useContextWithBailout,
useContext,
useEffect,
useEffectEvent as experimental_useEffectEvent,
-25
View File
@@ -19,10 +19,6 @@ import {REACT_CONSUMER_TYPE} from 'shared/ReactSymbols';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import {enableUseResourceEffectHook} from 'shared/ReactFeatureFlags';
import {
enableContextProfiling,
enableLazyContextPropagation,
} from '../../shared/ReactFeatureFlags';
type BasicStateAction<S> = (S => S) | S;
type Dispatch<A> = A => void;
@@ -69,27 +65,6 @@ export function useContext<T>(Context: ReactContext<T>): T {
return dispatcher.useContext(Context);
}
export function unstable_useContextWithBailout<T>(
context: ReactContext<T>,
select: (T => Array<mixed>) | null,
): T {
if (!(enableLazyContextPropagation && enableContextProfiling)) {
throw new Error('Not implemented.');
}
const dispatcher = resolveDispatcher();
if (__DEV__) {
if (context.$$typeof === REACT_CONSUMER_TYPE) {
console.error(
'Calling useContext(Context.Consumer) is not supported and will cause bugs. ' +
'Did you mean to call useContext(Context) instead?',
);
}
}
// $FlowFixMe[not-a-function] This is unstable, thus optional
return dispatcher.unstable_useContextWithBailout(context, select);
}
export function useState<S>(
initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
-3
View File
@@ -101,9 +101,6 @@ export const enableTransitionTracing = false;
export const enableLazyContextPropagation = true;
// Expose unstable useContext for performance testing
export const enableContextProfiling = false;
// FB-only usage. The new API has different semantics.
export const enableLegacyHidden = false;
@@ -53,7 +53,6 @@ export const enableFizzExternalRuntime = true;
export const enableGetInspectorDataForInstanceInProduction = true;
export const enableHalt = false;
export const enableInfiniteRenderLoopDetection = false;
export const enableContextProfiling = false;
export const enableLazyContextPropagation = true;
export const enableLegacyCache = false;
export const enableLegacyFBSupport = false;
@@ -43,7 +43,6 @@ export const enableHalt = false;
export const enableHiddenSubtreeInsertionEffectCleanup = false;
export const enableInfiniteRenderLoopDetection = false;
export const enableLazyContextPropagation = true;
export const enableContextProfiling = false;
export const enableLegacyCache = false;
export const enableLegacyFBSupport = false;
export const enableLegacyHidden = false;
@@ -49,7 +49,6 @@ export const transitionLaneExpirationMs = 5000;
export const disableSchedulerTimeoutInWorkLoop = false;
export const enableLazyContextPropagation = true;
export const enableContextProfiling = false;
export const enableLegacyHidden = false;
export const enableTransitionTracing = false;
@@ -51,7 +51,6 @@ export const transitionLaneExpirationMs = 5000;
export const disableSchedulerTimeoutInWorkLoop = false;
export const enableLazyContextPropagation = true;
export const enableContextProfiling = false;
export const enableLegacyHidden = false;
export const enableTransitionTracing = false;
@@ -79,8 +79,6 @@ export const enablePostpone = false;
export const enableHalt = false;
export const enableContextProfiling = true;
// TODO: www currently relies on this feature. It's disabled in open source.
// Need to remove it.
export const disableCommentsAsDOMContainers = false;
-1
View File
@@ -530,4 +530,3 @@
"542": "Suspense Exception: This is not a real error! It's an implementation detail of `useActionState` to interrupt the current render. You must either rethrow it immediately, or move the `useActionState` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary.",
"543": "Expected a ResourceEffectUpdate to be pushed together with ResourceEffectIdentity. This is a bug in React."
}