Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export captureOwnerStacks() only in DEV "react" builds #29923

Merged
merged 1 commit into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/react-reconciler/src/ReactCurrentFiber.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export function getCurrentParentStackInDev(): string {
return '';
}

function getCurrentFiberStackInDev(stack: Error): string {
function getCurrentFiberStackInDev(stack: null | Error): string {
if (__DEV__) {
if (current === null) {
return '';
Expand Down
65 changes: 65 additions & 0 deletions packages/react-reconciler/src/__tests__/ReactOwnerStacks-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @emails react-core
* @jest-environment node
*/
'use strict';

let React;
let ReactNoop;
let act;

describe('ReactOwnerStacks', () => {
beforeEach(function () {
jest.resetModules();

React = require('react');
ReactNoop = require('react-noop-renderer');
act = require('internal-test-utils').act;
});

function normalizeCodeLocInfo(str) {
return (
str &&
str.replace(/\n +(?:at|in) ([\S]+)[^\n]*/g, function (m, name) {
return '\n in ' + name + ' (at **)';
})
);
}

// @gate __DEV__ && enableOwnerStacks
it('can get the component owner stacks during rendering in dev', async () => {
let stack;

function Foo() {
return <Bar />;
}
function Bar() {
return (
<div>
<Baz />
</div>
);
}
function Baz() {
stack = React.captureOwnerStack();
return <span>hi</span>;
}

await act(() => {
ReactNoop.render(
<div>
<Foo />
</div>,
);
});

expect(normalizeCodeLocInfo(stack)).toBe(
'\n in Bar (at **)' + '\n in Foo (at **)',
);
});
});
1 change: 1 addition & 0 deletions packages/react-test-renderer/src/ReactTestRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import {
disableLegacyMode,
} from 'shared/ReactFeatureFlags';

// $FlowFixMe[prop-missing]: This is only in the development export.
const act = React.act;

// TODO: Remove from public bundle
Expand Down
80 changes: 80 additions & 0 deletions packages/react/index.development.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

// Keep in sync with https://github.com/facebook/flow/blob/main/lib/react.js
export type ComponentType<-P> = React$ComponentType<P>;
export type AbstractComponent<
-Config,
+Instance = mixed,
> = React$AbstractComponent<Config, Instance>;
export type ElementType = React$ElementType;
export type Element<+C> = React$Element<C>;
export type Key = React$Key;
export type Ref<C> = React$Ref<C>;
export type Node = React$Node;
export type Context<T> = React$Context<T>;
export type Portal = React$Portal;
export type ElementProps<C> = React$ElementProps<C>;
export type ElementConfig<C> = React$ElementConfig<C>;
export type ElementRef<C> = React$ElementRef<C>;
export type Config<Props, DefaultProps> = React$Config<Props, DefaultProps>;
export type ChildrenArray<+T> = $ReadOnlyArray<ChildrenArray<T>> | T;

// Export all exports so that they're available in tests.
// We can't use export * from in Flow for some reason.
export {
__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
Children,
Component,
Fragment,
Profiler,
PureComponent,
StrictMode,
Suspense,
cloneElement,
createContext,
createElement,
createRef,
use,
forwardRef,
isValidElement,
lazy,
memo,
cache,
startTransition,
unstable_DebugTracingMode,
unstable_LegacyHidden,
unstable_Activity,
unstable_Scope,
unstable_SuspenseList,
unstable_TracingMarker,
unstable_getCacheForType,
unstable_useCacheRefresh,
useId,
useCallback,
useContext,
useDebugValue,
useDeferredValue,
useEffect,
experimental_useEffectEvent,
useImperativeHandle,
useInsertionEffect,
useLayoutEffect,
useMemo,
useOptimistic,
useSyncExternalStore,
useReducer,
useRef,
useState,
useTransition,
useActionState,
version,
act, // DEV-only
captureOwnerStack, // DEV-only
} from './src/ReactClient';
72 changes: 72 additions & 0 deletions packages/react/index.experimental.development.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

export {
__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
Children,
Component,
Fragment,
Profiler,
PureComponent,
StrictMode,
Suspense,
cloneElement,
createContext,
createElement,
createRef,
use,
forwardRef,
isValidElement,
lazy,
memo,
cache,
startTransition,
unstable_DebugTracingMode,
unstable_Activity,
unstable_postpone,
unstable_getCacheForType,
unstable_SuspenseList,
unstable_useCacheRefresh,
useId,
useCallback,
useContext,
useDebugValue,
useDeferredValue,
useEffect,
experimental_useEffectEvent,
useImperativeHandle,
useInsertionEffect,
useLayoutEffect,
useMemo,
useOptimistic,
useReducer,
useRef,
useState,
useSyncExternalStore,
useTransition,
useActionState,
version,
act, // DEV-only
captureOwnerStack, // DEV-only
} from './src/ReactClient';

import {useOptimistic} from './src/ReactClient';

export function experimental_useOptimistic<S, A>(
passthrough: S,
reducer: ?(S, A) => S,
): [S, (A) => void] {
if (__DEV__) {
console.error(
'useOptimistic is now in canary. Remove the experimental_ prefix. ' +
'The prefixed alias will be removed in an upcoming release.',
);
}
return useOptimistic(passthrough, reducer);
}
1 change: 0 additions & 1 deletion packages/react/index.experimental.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

export {
__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
act,
Children,
Component,
Fragment,
Expand Down
1 change: 0 additions & 1 deletion packages/react/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export type ChildrenArray<+T> = $ReadOnlyArray<ChildrenArray<T>> | T;
// We can't use export * from in Flow for some reason.
export {
__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
act,
Children,
Component,
Fragment,
Expand Down
4 changes: 3 additions & 1 deletion packages/react/src/ReactClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import {
import ReactSharedInternals from './ReactSharedInternalsClient';
import {startTransition} from './ReactStartTransition';
import {act} from './ReactAct';
import {captureOwnerStack} from './ReactOwnerStack';

const Children = {
map,
Expand Down Expand Up @@ -121,5 +122,6 @@ export {
// enableTransitionTracing
REACT_TRACING_MARKER_TYPE as unstable_TracingMarker,
useId,
act,
act, // DEV-only
captureOwnerStack, // DEV-only
};
24 changes: 24 additions & 0 deletions packages/react/src/ReactOwnerStack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright (c) Meta Platforms, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
import ReactSharedInternals from 'shared/ReactSharedInternals';

export function captureOwnerStack(): null | string {
if (!enableOwnerStacks || !__DEV__) {
return null;
}
const getCurrentStack = ReactSharedInternals.getCurrentStack;
if (getCurrentStack === null) {
return null;
}
// The current stack will be the owner stack if enableOwnerStacks is true
// which it is always here. Otherwise it's the parent stack.
return getCurrentStack(null);
}
85 changes: 85 additions & 0 deletions packages/react/src/ReactServer.experimental.development.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

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 {
REACT_FRAGMENT_TYPE,
REACT_PROFILER_TYPE,
REACT_STRICT_MODE_TYPE,
REACT_SUSPENSE_TYPE,
REACT_DEBUG_TRACING_MODE_TYPE,
} from 'shared/ReactSymbols';
import {
cloneElement,
createElement,
isValidElement,
} from './jsx/ReactJSXElement';
import {createRef} from './ReactCreateRef';
import {
use,
useId,
useCallback,
useDebugValue,
useMemo,
useActionState,
getCacheForType,
} from './ReactHooks';
import {forwardRef} from './ReactForwardRef';
import {lazy} from './ReactLazy';
import {memo} from './ReactMemo';
import {cache} from './ReactCacheServer';
import {startTransition} from './ReactStartTransition';
import {postpone} from './ReactPostpone';
import {captureOwnerStack} from './ReactOwnerStack';
import version from 'shared/ReactVersion';

const Children = {
map,
forEach,
count,
toArray,
only,
};

// These are server-only
export {
taintUniqueValue as experimental_taintUniqueValue,
taintObjectReference as experimental_taintObjectReference,
} from './ReactTaint';

export {
Children,
REACT_FRAGMENT_TYPE as Fragment,
REACT_PROFILER_TYPE as Profiler,
REACT_STRICT_MODE_TYPE as StrictMode,
REACT_SUSPENSE_TYPE as Suspense,
cloneElement,
createElement,
createRef,
use,
forwardRef,
isValidElement,
lazy,
memo,
cache,
startTransition,
REACT_DEBUG_TRACING_MODE_TYPE as unstable_DebugTracingMode,
REACT_SUSPENSE_TYPE as unstable_SuspenseList,
getCacheForType as unstable_getCacheForType,
postpone as unstable_postpone,
useId,
useCallback,
useDebugValue,
useMemo,
useActionState,
version,
captureOwnerStack, // DEV-only
};
4 changes: 2 additions & 2 deletions packages/react/src/ReactSharedInternalsClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export type SharedStateClient = {
thrownErrors: Array<mixed>,

// ReactDebugCurrentFrame
getCurrentStack: null | ((stack: Error) => string),
getCurrentStack: null | ((stack: null | Error) => string),
};

export type RendererTask = boolean => RendererTask | null;
Expand All @@ -56,7 +56,7 @@ if (__DEV__) {
// Stack implementation injected by the current renderer.
ReactSharedInternals.getCurrentStack = (null:
| null
| ((stack: Error) => string));
| ((stack: null | Error) => string));
}

export default ReactSharedInternals;
Loading