diff --git a/packages/react/index.fb.js b/packages/react/index.fb.js
index 7892f31dd4757..4764281481dbb 100644
--- a/packages/react/index.fb.js
+++ b/packages/react/index.fb.js
@@ -7,6 +7,8 @@
* @flow
*/
+import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
+import {captureOwnerStack as captureOwnerStackImpl} from './src/ReactClient';
export {
__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
__COMPILER_RUNTIME,
@@ -68,3 +70,11 @@ export {useMemoCache as unstable_useMemoCache} from './src/ReactHooks';
// export to match the name of the OSS function typically exported from
// react/compiler-runtime
export {useMemoCache as c} from './src/ReactHooks';
+
+// Only export captureOwnerStack in development.
+let captureOwnerStack: ?() => null | string;
+if (__DEV__ && enableOwnerStacks) {
+ captureOwnerStack = captureOwnerStackImpl;
+}
+
+export {captureOwnerStack};
diff --git a/packages/react/src/ReactServer.fb.js b/packages/react/src/ReactServer.fb.js
index d6702023e4741..fe6260a799a2c 100644
--- a/packages/react/src/ReactServer.fb.js
+++ b/packages/react/src/ReactServer.fb.js
@@ -10,6 +10,8 @@
export {default as __SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './ReactSharedInternalsServer';
import {forEach, map, count, toArray, only} from './ReactChildren';
+import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
+import {captureOwnerStack as captureOwnerStackImpl} from './ReactOwnerStack';
import {
REACT_FRAGMENT_TYPE,
REACT_PROFILER_TYPE,
@@ -37,6 +39,12 @@ const Children = {
only,
};
+// Only export captureOwnerStack if the flag is on, to support feature detection.
+let captureOwnerStack: ?() => null | string;
+if (__DEV__ && enableOwnerStacks) {
+ captureOwnerStack = captureOwnerStackImpl;
+}
+
export {
Children,
REACT_FRAGMENT_TYPE as Fragment,
@@ -57,4 +65,5 @@ export {
useDebugValue,
useMemo,
version,
+ captureOwnerStack, // DEV-only
};
diff --git a/packages/react/src/__tests__/ReactStrictMode-test.js b/packages/react/src/__tests__/ReactStrictMode-test.js
index 97fcc1ec8c4ce..db60674ba64bf 100644
--- a/packages/react/src/__tests__/ReactStrictMode-test.js
+++ b/packages/react/src/__tests__/ReactStrictMode-test.js
@@ -1028,40 +1028,67 @@ describe('context legacy', () => {
root.render();
});
- assertConsoleErrorDev([
- 'LegacyContextProvider uses the legacy childContextTypes API ' +
- 'which will soon be removed. Use React.createContext() instead. ' +
- '(https://react.dev/link/legacy-context)' +
- '\n in LegacyContextProvider (at **)' +
- '\n in div (at **)' +
- '\n in Root (at **)',
- 'LegacyContextConsumer uses the legacy contextTypes API which ' +
- 'will soon be removed. Use React.createContext() with static ' +
- 'contextType instead. (https://react.dev/link/legacy-context)' +
- '\n in LegacyContextConsumer (at **)' +
- '\n in div (at **)' +
- '\n in LegacyContextProvider (at **)' +
- '\n in div (at **)' +
- '\n in Root (at **)',
- 'FunctionalLegacyContextConsumer uses the legacy contextTypes ' +
- 'API which will be removed soon. Use React.createContext() ' +
- 'with React.useContext() instead. (https://react.dev/link/legacy-context)' +
- '\n in FunctionalLegacyContextConsumer (at **)' +
- '\n in div (at **)' +
- '\n in LegacyContextProvider (at **)' +
- '\n in div (at **)' +
- '\n in Root (at **)',
- 'Legacy context API has been detected within a strict-mode tree.' +
- '\n\nThe old API will be supported in all 16.x releases, but applications ' +
- 'using it should migrate to the new version.' +
- '\n\nPlease update the following components: ' +
- 'FunctionalLegacyContextConsumer, LegacyContextConsumer, LegacyContextProvider' +
- '\n\nLearn more about this warning here: ' +
- 'https://react.dev/link/legacy-context' +
- '\n in LegacyContextProvider (at **)' +
- '\n in div (at **)' +
- '\n in Root (at **)',
- ]);
+ if (gate(flags => flags.enableOwnerStacks)) {
+ assertConsoleErrorDev([
+ 'LegacyContextProvider uses the legacy childContextTypes API ' +
+ 'which will soon be removed. Use React.createContext() instead. ' +
+ '(https://react.dev/link/legacy-context)' +
+ '\n in Root (at **)',
+ 'LegacyContextConsumer uses the legacy contextTypes API which ' +
+ 'will soon be removed. Use React.createContext() with static ' +
+ 'contextType instead. (https://react.dev/link/legacy-context)' +
+ '\n in LegacyContextProvider (at **)' +
+ '\n in Root (at **)',
+ 'FunctionalLegacyContextConsumer uses the legacy contextTypes ' +
+ 'API which will be removed soon. Use React.createContext() ' +
+ 'with React.useContext() instead. (https://react.dev/link/legacy-context)' +
+ '\n in LegacyContextProvider (at **)' +
+ '\n in Root (at **)',
+ 'Legacy context API has been detected within a strict-mode tree.' +
+ '\n\nThe old API will be supported in all 16.x releases, but applications ' +
+ 'using it should migrate to the new version.' +
+ '\n\nPlease update the following components: ' +
+ 'FunctionalLegacyContextConsumer, LegacyContextConsumer, LegacyContextProvider' +
+ '\n\nLearn more about this warning here: ' +
+ 'https://react.dev/link/legacy-context' +
+ '\n in Root (at **)',
+ ]);
+ } else {
+ assertConsoleErrorDev([
+ 'LegacyContextProvider uses the legacy childContextTypes API ' +
+ 'which will soon be removed. Use React.createContext() instead. ' +
+ '(https://react.dev/link/legacy-context)' +
+ '\n in LegacyContextProvider (at **)' +
+ '\n in div (at **)' +
+ '\n in Root (at **)',
+ 'LegacyContextConsumer uses the legacy contextTypes API which ' +
+ 'will soon be removed. Use React.createContext() with static ' +
+ 'contextType instead. (https://react.dev/link/legacy-context)' +
+ '\n in LegacyContextConsumer (at **)' +
+ '\n in div (at **)' +
+ '\n in LegacyContextProvider (at **)' +
+ '\n in div (at **)' +
+ '\n in Root (at **)',
+ 'FunctionalLegacyContextConsumer uses the legacy contextTypes ' +
+ 'API which will be removed soon. Use React.createContext() ' +
+ 'with React.useContext() instead. (https://react.dev/link/legacy-context)' +
+ '\n in FunctionalLegacyContextConsumer (at **)' +
+ '\n in div (at **)' +
+ '\n in LegacyContextProvider (at **)' +
+ '\n in div (at **)' +
+ '\n in Root (at **)',
+ 'Legacy context API has been detected within a strict-mode tree.' +
+ '\n\nThe old API will be supported in all 16.x releases, but applications ' +
+ 'using it should migrate to the new version.' +
+ '\n\nPlease update the following components: ' +
+ 'FunctionalLegacyContextConsumer, LegacyContextConsumer, LegacyContextProvider' +
+ '\n\nLearn more about this warning here: ' +
+ 'https://react.dev/link/legacy-context' +
+ '\n in LegacyContextProvider (at **)' +
+ '\n in div (at **)' +
+ '\n in Root (at **)',
+ ]);
+ }
// Dedupe
await act(() => {
diff --git a/packages/react/src/__tests__/createReactClassIntegration-test.js b/packages/react/src/__tests__/createReactClassIntegration-test.js
index 811d897e859e7..4aabc11b52e8d 100644
--- a/packages/react/src/__tests__/createReactClassIntegration-test.js
+++ b/packages/react/src/__tests__/createReactClassIntegration-test.js
@@ -338,7 +338,14 @@ describe('create-react-class-integration', () => {
root.render();
});
assertConsoleErrorDev([
- 'Component uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',
+ gate(flags =>
+ flags.enableOwnerStacks
+ ? [
+ 'Component uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',
+ {withoutStack: true},
+ ]
+ : 'Component uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',
+ ),
'Component uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.',
]);
expect(container.firstChild.className).toBe('foo');
diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js b/packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js
index 832838313095c..fc9bed7cc056f 100644
--- a/packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js
+++ b/packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js
@@ -26,3 +26,4 @@ export const passChildrenWhenCloningPersistedNodes = __VARIANT__;
export const enableFabricCompleteRootInCommitPhase = __VARIANT__;
export const enableSiblingPrerendering = __VARIANT__;
export const enableUseResourceEffectHook = __VARIANT__;
+export const enableOwnerStacks = __VARIANT__;
diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js
index defa7cd330d7f..58ae9c4fffe41 100644
--- a/packages/shared/forks/ReactFeatureFlags.native-fb.js
+++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js
@@ -28,6 +28,7 @@ export const {
enableUseResourceEffectHook,
passChildrenWhenCloningPersistedNodes,
enableSiblingPrerendering,
+ enableOwnerStacks,
} = dynamicFlags;
// The rest of the flags are static for better dead code elimination.
@@ -67,7 +68,6 @@ export const enableLegacyCache = false;
export const enableLegacyFBSupport = false;
export const enableLegacyHidden = false;
export const enableNoCloningMemoCache = false;
-export const enableOwnerStacks = false;
export const enablePostpone = false;
export const enableProfilerCommitHooks = __PROFILE__;
export const enableProfilerNestedUpdatePhase = __PROFILE__;
diff --git a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js
index db38e0e1fdcba..7c28c76fb1392 100644
--- a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js
+++ b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js
@@ -27,6 +27,7 @@ export const enableRetryLaneExpiration = __VARIANT__;
export const enableTransitionTracing = __VARIANT__;
export const favorSafetyOverHydrationPerf = __VARIANT__;
export const renameElementSymbol = __VARIANT__;
+export const enableOwnerStacks = __VARIANT__;
export const retryLaneExpirationMs = 5000;
export const syncLaneExpirationMs = 250;
export const transitionLaneExpirationMs = 5000;
diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js
index 8ddbf3dd7c519..da97bbc212876 100644
--- a/packages/shared/forks/ReactFeatureFlags.www.js
+++ b/packages/shared/forks/ReactFeatureFlags.www.js
@@ -37,6 +37,7 @@ export const {
retryLaneExpirationMs,
syncLaneExpirationMs,
transitionLaneExpirationMs,
+ enableOwnerStacks,
} = dynamicFeatureFlags;
// On WWW, __EXPERIMENTAL__ is used for a new modern build.
@@ -121,7 +122,6 @@ export const useModernStrictMode = true;
export const disableLegacyMode = true;
-export const enableOwnerStacks = false;
export const enableShallowPropDiffing = false;
// Flow magic to verify the exports of this file match the original version.