From 6bb9cb4bc11e90f989c42dbf9e653694bd2b9f44 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 6 Feb 2024 20:21:27 -0500 Subject: [PATCH 1/2] Remove __self and __source location from elements Along with all the places using it like the _debugSource on Fiber. This removes source location info from React DevTools and React Native Inspector. --- .../react-client/src/ReactFlightClient.js | 12 ---- .../__tests__/__e2e__/components.test.js | 5 +- .../__tests__/storeComponentFilters-test.js | 8 ++- .../src/backend/legacy/renderer.js | 5 -- .../src/backend/renderer.js | 27 ++++----- .../src/backend/types.js | 4 -- .../react-devtools-shared/src/backendAPI.js | 3 +- .../src/frontend/types.js | 3 +- .../ReactDeprecationWarnings-test.js | 12 +++- .../__tests__/ReactFunctionComponent-test.js | 4 -- .../src/ReactNativeFiberInspector.js | 4 -- .../src/ReactNativeTypes.js | 7 --- .../react-reconciler/src/ReactChildFiber.js | 11 ---- packages/react-reconciler/src/ReactFiber.js | 11 +--- .../src/ReactFiberBeginWork.js | 9 +-- .../src/ReactFiberCommitWork.js | 1 - .../src/ReactFiberComponentStack.js | 15 +++-- .../src/ReactInternalTypes.js | 2 - .../src/ReactFizzComponentStack.js | 6 +- packages/react/src/ReactElementProd.js | 41 +------------- packages/react/src/ReactElementValidator.js | 1 - packages/react/src/jsx/ReactJSXElement.js | 15 ----- .../react/src/jsx/ReactJSXElementValidator.js | 1 - packages/shared/ReactComponentStackFrame.js | 55 ++++--------------- packages/shared/ReactElementType.js | 8 --- packages/shared/checkPropTypes.js | 1 - 26 files changed, 60 insertions(+), 211 deletions(-) diff --git a/packages/react-client/src/ReactFlightClient.js b/packages/react-client/src/ReactFlightClient.js index 8ed9762bb7666..20ff8abe4a08f 100644 --- a/packages/react-client/src/ReactFlightClient.js +++ b/packages/react-client/src/ReactFlightClient.js @@ -475,18 +475,6 @@ function createElement( writable: true, value: true, // This element has already been validated on the server. }); - Object.defineProperty(element, '_self', { - configurable: false, - enumerable: false, - writable: false, - value: null, - }); - Object.defineProperty(element, '_source', { - configurable: false, - enumerable: false, - writable: false, - value: null, - }); } return element; } diff --git a/packages/react-devtools-inline/__tests__/__e2e__/components.test.js b/packages/react-devtools-inline/__tests__/__e2e__/components.test.js index dfa6775da6bab..39467d3a9c932 100644 --- a/packages/react-devtools-inline/__tests__/__e2e__/components.test.js +++ b/packages/react-devtools-inline/__tests__/__e2e__/components.test.js @@ -92,14 +92,15 @@ test.describe('Components', () => { ? valueElement.value : valueElement.innerText; - return [name, value, source.innerText]; + return [name, value, source ? source.innerText : null]; }, {name: isEditableName, value: isEditableValue} ); expect(propName).toBe('label'); expect(propValue).toBe('"one"'); - expect(sourceText).toMatch(/ListApp[a-zA-Z]*\.js/); + expect(sourceText).toBe(null); + // TODO: expect(sourceText).toMatch(/ListApp[a-zA-Z]*\.js/); }); test('should allow props to be edited', async () => { diff --git a/packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js b/packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js index 573ca40cba6b0..571302961dc51 100644 --- a/packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js +++ b/packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js @@ -242,7 +242,13 @@ describe('Store component filters', () => { ]), ); - expect(store).toMatchInlineSnapshot(`[root]`); + // TODO: Filtering should work on component location. + // expect(store).toMatchInlineSnapshot(`[root]`); + expect(store).toMatchInlineSnapshot(` + [root] + ▾ +
+ `); await actAsync( async () => diff --git a/packages/react-devtools-shared/src/backend/legacy/renderer.js b/packages/react-devtools-shared/src/backend/legacy/renderer.js index 9b1a860a40ed2..8f8af5594f8d4 100644 --- a/packages/react-devtools-shared/src/backend/legacy/renderer.js +++ b/packages/react-devtools-shared/src/backend/legacy/renderer.js @@ -773,12 +773,10 @@ export function attach( let owners = null; let props = null; let state = null; - let source = null; const element = internalInstance._currentElement; if (element !== null) { props = element.props; - source = element._source != null ? element._source : null; let owner = element._owner; if (owner) { @@ -851,9 +849,6 @@ export function attach( // List of owners owners, - // Location of component in source code. - source, - rootType: null, rendererPackageName: null, rendererVersion: null, diff --git a/packages/react-devtools-shared/src/backend/renderer.js b/packages/react-devtools-shared/src/backend/renderer.js index a097f850072dd..069cde215a1ca 100644 --- a/packages/react-devtools-shared/src/backend/renderer.js +++ b/packages/react-devtools-shared/src/backend/renderer.js @@ -958,7 +958,7 @@ export function attach( // NOTICE Keep in sync with get*ForFiber methods function shouldFilterFiber(fiber: Fiber): boolean { - const {_debugSource, tag, type, key} = fiber; + const {tag, type, key} = fiber; switch (tag) { case DehydratedSuspenseComponent: @@ -1010,15 +1010,15 @@ export function attach( } } - if (_debugSource != null && hideElementsWithPaths.size > 0) { - const {fileName} = _debugSource; - // eslint-disable-next-line no-for-of-loops/no-for-of-loops - for (const pathRegExp of hideElementsWithPaths) { - if (pathRegExp.test(fileName)) { - return true; - } - } - } + // TODO: Figure out a way to filter by path in the new model which has no debug info. + // if (hideElementsWithPaths.size > 0) { + // const {fileName} = ...; + // for (const pathRegExp of hideElementsWithPaths) { + // if (pathRegExp.test(fileName)) { + // return true; + // } + // } + // } return false; } @@ -3132,7 +3132,6 @@ export function attach( const { _debugOwner, - _debugSource, stateNode, key, memoizedProps, @@ -3362,9 +3361,6 @@ export function attach( // List of owners owners, - // Location of component in source code. - source: _debugSource || null, - rootType, rendererPackageName: renderer.rendererPackageName, rendererVersion: renderer.version, @@ -3725,9 +3721,6 @@ export function attach( if (nativeNodes !== null) { console.log('Nodes:', nativeNodes); } - if (result.source !== null) { - console.log('Location:', result.source); - } if (window.chrome || /firefox/i.test(navigator.userAgent)) { console.log( 'Right-click any value to save it as a global variable for further inspection.', diff --git a/packages/react-devtools-shared/src/backend/types.js b/packages/react-devtools-shared/src/backend/types.js index 14a26140b2d3f..6b0cd5ee6c2b0 100644 --- a/packages/react-devtools-shared/src/backend/types.js +++ b/packages/react-devtools-shared/src/backend/types.js @@ -15,7 +15,6 @@ */ import type {ReactContext, Wakeable} from 'shared/ReactTypes'; -import type {Source} from 'shared/ReactElementType'; import type {Fiber} from 'react-reconciler/src/ReactInternalTypes'; import type { ComponentFilter, @@ -280,9 +279,6 @@ export type InspectedElement = { // List of owners owners: Array | null, - // Location of component in source code. - source: Source | null, - type: ElementType, // Meta information about the root this element belongs to. diff --git a/packages/react-devtools-shared/src/backendAPI.js b/packages/react-devtools-shared/src/backendAPI.js index 397019bb373c6..21ae444a1ef8c 100644 --- a/packages/react-devtools-shared/src/backendAPI.js +++ b/packages/react-devtools-shared/src/backendAPI.js @@ -226,7 +226,6 @@ export function convertInspectedElementBackendToFrontend( canViewSource, hasLegacyContext, id, - source, type, owners, context, @@ -261,7 +260,7 @@ export function convertInspectedElementBackendToFrontend( rendererPackageName, rendererVersion, rootType, - source, + source: null, // TODO: Load source location lazily. type, owners: owners === null diff --git a/packages/react-devtools-shared/src/frontend/types.js b/packages/react-devtools-shared/src/frontend/types.js index 76a6a741b7975..9623efd3dd230 100644 --- a/packages/react-devtools-shared/src/frontend/types.js +++ b/packages/react-devtools-shared/src/frontend/types.js @@ -14,7 +14,6 @@ * Be mindful of backwards compatibility when making changes. */ -import type {Source} from 'shared/ReactElementType'; import type { Dehydrated, Unserializable, @@ -220,7 +219,7 @@ export type InspectedElement = { owners: Array | null, // Location of component in source code. - source: Source | null, + source: null, // TODO: Reinstate a way to load this lazily. type: ElementType, diff --git a/packages/react-dom/src/__tests__/ReactDeprecationWarnings-test.js b/packages/react-dom/src/__tests__/ReactDeprecationWarnings-test.js index ba503d093f24d..efb66e7a4fbfc 100644 --- a/packages/react-dom/src/__tests__/ReactDeprecationWarnings-test.js +++ b/packages/react-dom/src/__tests__/ReactDeprecationWarnings-test.js @@ -131,6 +131,10 @@ describe('ReactDeprecationWarnings', () => { 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', + 'Warning: Component "Component" contains the string ref "refComponent". ' + + 'Support for string refs will be removed in a future major release. We recommend ' + + 'using useRef() or createRef() instead. Learn more about using refs safely here: ' + + 'https://reactjs.org/link/strict-mode-string-ref', ]); }); @@ -155,14 +159,18 @@ describe('ReactDeprecationWarnings', () => { } ReactNoop.render(); - await expect(async () => await waitForAll([])).toErrorDev( + await expect(async () => await waitForAll([])).toErrorDev([ 'Warning: Component "Component" contains the string ref "refComponent". ' + 'Support for string refs will be removed in a future major release. ' + 'This case cannot be automatically converted to an arrow function. ' + 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', - ); + 'Warning: Component "Component" contains the string ref "refComponent". ' + + 'Support for string refs will be removed in a future major release. We recommend ' + + 'using useRef() or createRef() instead. Learn more about using refs safely here: ' + + 'https://reactjs.org/link/strict-mode-string-ref', + ]); }); } }); diff --git a/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js b/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js index b28ece61e1e2e..fffca3675a711 100644 --- a/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactFunctionComponent-test.js @@ -270,7 +270,6 @@ describe('ReactFunctionComponent', () => { return {}} />; } } - Object.defineProperty(AnonymousParentUsingJSX, 'name', {value: undefined}); let instance1; @@ -293,9 +292,6 @@ describe('ReactFunctionComponent', () => { }); } } - Object.defineProperty(AnonymousParentNotUsingJSX, 'name', { - value: undefined, - }); let instance2; expect(() => { diff --git a/packages/react-native-renderer/src/ReactNativeFiberInspector.js b/packages/react-native-renderer/src/ReactNativeFiberInspector.js index 17b2c5e5608aa..3e6d222ee8d87 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberInspector.js +++ b/packages/react-native-renderer/src/ReactNativeFiberInspector.js @@ -37,7 +37,6 @@ function createHierarchy(fiberHierarchy) { getInspectorData: findNodeHandle => { return { props: getHostProps(fiber), - source: fiber._debugSource, measure: callback => { // If this is Fabric, we'll find a shadow node and use that to measure. const hostFiber = findCurrentHostFiber(fiber); @@ -98,7 +97,6 @@ function getInspectorDataForInstance( hierarchy: [], props: emptyObject, selectedIndex: null, - source: null, }; } @@ -107,7 +105,6 @@ function getInspectorDataForInstance( const instance = lastNonHostInstance(fiberHierarchy); const hierarchy = createHierarchy(fiberHierarchy); const props = getHostProps(instance); - const source = instance._debugSource; const selectedIndex = fiberHierarchy.indexOf(instance); return { @@ -115,7 +112,6 @@ function getInspectorDataForInstance( hierarchy, props, selectedIndex, - source, }; } diff --git a/packages/react-native-renderer/src/ReactNativeTypes.js b/packages/react-native-renderer/src/ReactNativeTypes.js index c61ee86be4f86..92c8c4de83bd5 100644 --- a/packages/react-native-renderer/src/ReactNativeTypes.js +++ b/packages/react-native-renderer/src/ReactNativeTypes.js @@ -142,11 +142,6 @@ type InspectorDataProps = $ReadOnly<{ ... }>; -type InspectorDataSource = $ReadOnly<{ - fileName?: string, - lineNumber?: number, -}>; - type InspectorDataGetter = ( ( componentOrHandle: ElementRef | number, @@ -154,7 +149,6 @@ type InspectorDataGetter = ( ) => $ReadOnly<{ measure: (callback: MeasureOnSuccessCallback) => void, props: InspectorDataProps, - source: InspectorDataSource, }>; export type InspectorData = $ReadOnly<{ @@ -165,7 +159,6 @@ export type InspectorData = $ReadOnly<{ }>, selectedIndex: ?number, props: InspectorDataProps, - source: ?InspectorDataSource, }>; export type TouchedViewDataAtPoint = $ReadOnly<{ diff --git a/packages/react-reconciler/src/ReactChildFiber.js b/packages/react-reconciler/src/ReactChildFiber.js index 236ef7f37136f..5f6013d14b49f 100644 --- a/packages/react-reconciler/src/ReactChildFiber.js +++ b/packages/react-reconciler/src/ReactChildFiber.js @@ -129,14 +129,6 @@ function coerceRef( ) { if (__DEV__) { if ( - // We warn in ReactElement.js if owner and self are equal for string refs - // because these cannot be automatically converted to an arrow function - // using a codemod. Therefore, we don't have to warn about string refs again. - !( - element._owner && - element._self && - element._owner.stateNode !== element._self - ) && // Will already throw with "Function components cannot have string refs" !( element._owner && @@ -446,7 +438,6 @@ function createChildReconciler( existing.ref = coerceRef(returnFiber, current, element); existing.return = returnFiber; if (__DEV__) { - existing._debugSource = element._source; existing._debugOwner = element._owner; } return existing; @@ -1234,7 +1225,6 @@ function createChildReconciler( const existing = useFiber(child, element.props.children); existing.return = returnFiber; if (__DEV__) { - existing._debugSource = element._source; existing._debugOwner = element._owner; } return existing; @@ -1260,7 +1250,6 @@ function createChildReconciler( existing.ref = coerceRef(returnFiber, child, element); existing.return = returnFiber; if (__DEV__) { - existing._debugSource = element._source; existing._debugOwner = element._owner; } return existing; diff --git a/packages/react-reconciler/src/ReactFiber.js b/packages/react-reconciler/src/ReactFiber.js index 573e497454028..8a01d87b8ff7c 100644 --- a/packages/react-reconciler/src/ReactFiber.js +++ b/packages/react-reconciler/src/ReactFiber.js @@ -7,7 +7,7 @@ * @flow */ -import type {ReactElement, Source} from 'shared/ReactElementType'; +import type {ReactElement} from 'shared/ReactElementType'; import type {ReactFragment, ReactPortal, ReactScope} from 'shared/ReactTypes'; import type {Fiber} from './ReactInternalTypes'; import type {RootTag} from './ReactRootTags'; @@ -202,7 +202,6 @@ function FiberNode( if (__DEV__) { // This isn't directly used but is handy for debugging internals: - this._debugSource = null; this._debugOwner = null; this._debugNeedsRemount = false; this._debugHookTypes = null; @@ -285,7 +284,6 @@ export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber { if (__DEV__) { // DEV-only fields - workInProgress._debugSource = current._debugSource; workInProgress._debugOwner = current._debugOwner; workInProgress._debugHookTypes = current._debugHookTypes; } @@ -488,7 +486,6 @@ export function createFiberFromTypeAndProps( type: any, // React$ElementType key: null | string, pendingProps: any, - source: null | Source, owner: null | Fiber, mode: TypeOfMode, lanes: Lanes, @@ -637,7 +634,6 @@ export function createFiberFromTypeAndProps( fiber.lanes = lanes; if (__DEV__) { - fiber._debugSource = source; fiber._debugOwner = owner; } @@ -649,10 +645,8 @@ export function createFiberFromElement( mode: TypeOfMode, lanes: Lanes, ): Fiber { - let source = null; let owner = null; if (__DEV__) { - source = element._source; owner = element._owner; } const type = element.type; @@ -662,13 +656,11 @@ export function createFiberFromElement( type, key, pendingProps, - source, owner, mode, lanes, ); if (__DEV__) { - fiber._debugSource = element._source; fiber._debugOwner = element._owner; } return fiber; @@ -919,7 +911,6 @@ export function assignFiberPropertiesInDEV( target.treeBaseDuration = source.treeBaseDuration; } - target._debugSource = source._debugSource; target._debugOwner = source._debugOwner; target._debugNeedsRemount = source._debugNeedsRemount; target._debugHookTypes = source._debugHookTypes; diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 5c555b1812d43..4a333ad782f1b 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -533,7 +533,6 @@ function updateMemoComponent( Component.type, null, nextProps, - null, workInProgress, workInProgress.mode, renderLanes, @@ -2097,16 +2096,13 @@ function validateFunctionComponentInDev(workInProgress: Fiber, Component: any) { } if (workInProgress.ref !== null) { let info = ''; + const componentName = getComponentNameFromType(Component) || 'Unknown'; const ownerName = getCurrentFiberOwnerNameInDevOrNull(); if (ownerName) { info += '\n\nCheck the render method of `' + ownerName + '`.'; } - let warningKey = ownerName || ''; - const debugSource = workInProgress._debugSource; - if (debugSource) { - warningKey = debugSource.fileName + ':' + debugSource.lineNumber; - } + const warningKey = componentName + '|' + (ownerName || ''); if (!didWarnAboutFunctionRefs[warningKey]) { didWarnAboutFunctionRefs[warningKey] = true; console.error( @@ -4058,7 +4054,6 @@ function beginWork( workInProgress.type, workInProgress.key, workInProgress.pendingProps, - workInProgress._debugSource || null, workInProgress._debugOwner || null, workInProgress.mode, workInProgress.lanes, diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.js b/packages/react-reconciler/src/ReactFiberCommitWork.js index 13cece7ed9368..8b44a80e00eaa 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.js @@ -1693,7 +1693,6 @@ function detachFiberAfterEffects(fiber: Fiber) { fiber.stateNode = null; if (__DEV__) { - fiber._debugSource = null; fiber._debugOwner = null; } diff --git a/packages/react-reconciler/src/ReactFiberComponentStack.js b/packages/react-reconciler/src/ReactFiberComponentStack.js index b532840b8a364..3300dec292c9a 100644 --- a/packages/react-reconciler/src/ReactFiberComponentStack.js +++ b/packages/react-reconciler/src/ReactFiberComponentStack.js @@ -34,26 +34,25 @@ function describeFiber(fiber: Fiber): string { ? fiber._debugOwner.type : null : null; - const source = __DEV__ ? fiber._debugSource : null; switch (fiber.tag) { case HostHoistable: case HostSingleton: case HostComponent: - return describeBuiltInComponentFrame(fiber.type, source, owner); + return describeBuiltInComponentFrame(fiber.type, owner); case LazyComponent: - return describeBuiltInComponentFrame('Lazy', source, owner); + return describeBuiltInComponentFrame('Lazy', owner); case SuspenseComponent: - return describeBuiltInComponentFrame('Suspense', source, owner); + return describeBuiltInComponentFrame('Suspense', owner); case SuspenseListComponent: - return describeBuiltInComponentFrame('SuspenseList', source, owner); + return describeBuiltInComponentFrame('SuspenseList', owner); case FunctionComponent: case IndeterminateComponent: case SimpleMemoComponent: - return describeFunctionComponentFrame(fiber.type, source, owner); + return describeFunctionComponentFrame(fiber.type, owner); case ForwardRef: - return describeFunctionComponentFrame(fiber.type.render, source, owner); + return describeFunctionComponentFrame(fiber.type.render, owner); case ClassComponent: - return describeClassComponentFrame(fiber.type, source, owner); + return describeClassComponentFrame(fiber.type, owner); default: return ''; } diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index e03ac26a0103c..f4ec8ab186a05 100644 --- a/packages/react-reconciler/src/ReactInternalTypes.js +++ b/packages/react-reconciler/src/ReactInternalTypes.js @@ -7,7 +7,6 @@ * @flow */ -import type {Source} from 'shared/ReactElementType'; import type { RefObject, ReactContext, @@ -200,7 +199,6 @@ export type Fiber = { // to be the same as work in progress. // __DEV__ only - _debugSource?: Source | null, _debugOwner?: Fiber | null, _debugIsCurrentlyTiming?: boolean, _debugNeedsRemount?: boolean, diff --git a/packages/react-server/src/ReactFizzComponentStack.js b/packages/react-server/src/ReactFizzComponentStack.js index 207d1bd331c90..7aeb6b0802c92 100644 --- a/packages/react-server/src/ReactFizzComponentStack.js +++ b/packages/react-server/src/ReactFizzComponentStack.js @@ -43,13 +43,13 @@ export function getStackByComponentStackNode( do { switch (node.tag) { case 0: - info += describeBuiltInComponentFrame(node.type, null, null); + info += describeBuiltInComponentFrame(node.type, null); break; case 1: - info += describeFunctionComponentFrame(node.type, null, null); + info += describeFunctionComponentFrame(node.type, null); break; case 2: - info += describeClassComponentFrame(node.type, null, null); + info += describeClassComponentFrame(node.type, null); break; } // $FlowFixMe[incompatible-type] we bail out when we get a null diff --git a/packages/react/src/ReactElementProd.js b/packages/react/src/ReactElementProd.js index b4f1519c79786..b81b84730431d 100644 --- a/packages/react/src/ReactElementProd.js +++ b/packages/react/src/ReactElementProd.js @@ -138,7 +138,7 @@ function warnIfStringRefCannotBeAutoConverted(config) { * indicating filename, line number, and/or other information. * @internal */ -function ReactElement(type, key, ref, self, source, owner, props) { +function ReactElement(type, key, ref, owner, props) { const element = { // This tag allows us to uniquely identify this as a React Element $$typeof: REACT_ELEMENT_TYPE, @@ -170,21 +170,6 @@ function ReactElement(type, key, ref, self, source, owner, props) { writable: true, value: false, }); - // self and source are DEV only properties. - Object.defineProperty(element, '_self', { - configurable: false, - enumerable: false, - writable: false, - value: self, - }); - // Two elements created in two different places should be considered - // equal for testing purposes and therefore we hide it from enumeration. - Object.defineProperty(element, '_source', { - configurable: false, - enumerable: false, - writable: false, - value: source, - }); if (Object.freeze) { Object.freeze(element.props); Object.freeze(element); @@ -206,8 +191,6 @@ export function createElement(type, config, children) { let key = null; let ref = null; - let self = null; - let source = null; if (config != null) { if (hasValidRef(config)) { @@ -224,8 +207,6 @@ export function createElement(type, config, children) { key = '' + config.key; } - self = config.__self === undefined ? null : config.__self; - source = config.__source === undefined ? null : config.__source; // Remaining properties are added to a new props object for (propName in config) { if ( @@ -289,15 +270,7 @@ export function createElement(type, config, children) { } } } - return ReactElement( - type, - key, - ref, - self, - source, - ReactCurrentOwner.current, - props, - ); + return ReactElement(type, key, ref, ReactCurrentOwner.current, props); } /** @@ -320,8 +293,6 @@ export function cloneAndReplaceKey(oldElement, newKey) { oldElement.type, newKey, oldElement.ref, - oldElement._self, - oldElement._source, oldElement._owner, oldElement.props, ); @@ -348,12 +319,6 @@ export function cloneElement(element, config, children) { // Reserved names are extracted let key = element.key; let ref = element.ref; - // Self is preserved since the owner is preserved. - const self = element._self; - // Source is preserved since cloneElement is unlikely to be targeted by a - // transpiler, and the original source is probably a better indicator of the - // true owner. - const source = element._source; // Owner will be preserved, unless ref is overridden let owner = element._owner; @@ -415,7 +380,7 @@ export function cloneElement(element, config, children) { props.children = childArray; } - return ReactElement(element.type, key, ref, self, source, owner, props); + return ReactElement(element.type, key, ref, owner, props); } /** diff --git a/packages/react/src/ReactElementValidator.js b/packages/react/src/ReactElementValidator.js index b67466f92b607..7162a1e22a0c5 100644 --- a/packages/react/src/ReactElementValidator.js +++ b/packages/react/src/ReactElementValidator.js @@ -39,7 +39,6 @@ function setCurrentlyValidatingElement(element) { const owner = element._owner; const stack = describeUnknownElementTypeFrameInDEV( element.type, - element._source, owner ? owner.type : null, ); setExtraStackFrame(stack); diff --git a/packages/react/src/jsx/ReactJSXElement.js b/packages/react/src/jsx/ReactJSXElement.js index bc3691e4a9d1b..e2ad636e035f3 100644 --- a/packages/react/src/jsx/ReactJSXElement.js +++ b/packages/react/src/jsx/ReactJSXElement.js @@ -170,21 +170,6 @@ function ReactElement(type, key, ref, self, source, owner, props) { writable: true, value: false, }); - // self and source are DEV only properties. - Object.defineProperty(element, '_self', { - configurable: false, - enumerable: false, - writable: false, - value: self, - }); - // Two elements created in two different places should be considered - // equal for testing purposes and therefore we hide it from enumeration. - Object.defineProperty(element, '_source', { - configurable: false, - enumerable: false, - writable: false, - value: source, - }); if (Object.freeze) { Object.freeze(element.props); Object.freeze(element); diff --git a/packages/react/src/jsx/ReactJSXElementValidator.js b/packages/react/src/jsx/ReactJSXElementValidator.js index 45d25e6ff11aa..3fbbc1cdf2883 100644 --- a/packages/react/src/jsx/ReactJSXElementValidator.js +++ b/packages/react/src/jsx/ReactJSXElementValidator.js @@ -40,7 +40,6 @@ function setCurrentlyValidatingElement(element) { const owner = element._owner; const stack = describeUnknownElementTypeFrameInDEV( element.type, - element._source, owner ? owner.type : null, ); ReactDebugCurrentFrame.setExtraStackFrame(stack); diff --git a/packages/shared/ReactComponentStackFrame.js b/packages/shared/ReactComponentStackFrame.js index 9738fcaa2d946..94a6c517d914a 100644 --- a/packages/shared/ReactComponentStackFrame.js +++ b/packages/shared/ReactComponentStackFrame.js @@ -7,7 +7,6 @@ * @flow */ -import type {Source} from 'shared/ReactElementType'; import type {LazyComponent} from 'react/src/ReactLazy'; import {enableComponentStackLocations} from 'shared/ReactFeatureFlags'; @@ -29,7 +28,6 @@ const {ReactCurrentDispatcher} = ReactSharedInternals; let prefix; export function describeBuiltInComponentFrame( name: string, - source: void | null | Source, ownerFn: void | null | Function, ): string { if (enableComponentStackLocations) { @@ -49,7 +47,7 @@ export function describeBuiltInComponentFrame( if (__DEV__ && ownerFn) { ownerName = ownerFn.displayName || ownerFn.name || null; } - return describeComponentFrame(name, source, ownerName); + return describeComponentFrame(name, ownerName); } } @@ -293,31 +291,9 @@ export function describeNativeComponentFrame( return syntheticFrame; } -const BEFORE_SLASH_RE = /^(.*)[\\\/]/; - -function describeComponentFrame( - name: null | string, - source: void | null | Source, - ownerName: null | string, -) { +function describeComponentFrame(name: null | string, ownerName: null | string) { let sourceInfo = ''; - if (__DEV__ && source) { - const path = source.fileName; - let fileName = path.replace(BEFORE_SLASH_RE, ''); - // In DEV, include code for a common special case: - // prefer "folder/index.js" instead of just "index.js". - if (/^index\./.test(fileName)) { - const match = path.match(BEFORE_SLASH_RE); - if (match) { - const pathBeforeSlash = match[1]; - if (pathBeforeSlash) { - const folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, ''); - fileName = folderName + '/' + fileName; - } - } - } - sourceInfo = ' (at ' + fileName + ':' + source.lineNumber + ')'; - } else if (ownerName) { + if (ownerName) { sourceInfo = ' (created by ' + ownerName + ')'; } return '\n in ' + (name || 'Unknown') + sourceInfo; @@ -325,19 +301,17 @@ function describeComponentFrame( export function describeClassComponentFrame( ctor: Function, - source: void | null | Source, ownerFn: void | null | Function, ): string { if (enableComponentStackLocations) { return describeNativeComponentFrame(ctor, true); } else { - return describeFunctionComponentFrame(ctor, source, ownerFn); + return describeFunctionComponentFrame(ctor, ownerFn); } } export function describeFunctionComponentFrame( fn: Function, - source: void | null | Source, ownerFn: void | null | Function, ): string { if (enableComponentStackLocations) { @@ -351,7 +325,7 @@ export function describeFunctionComponentFrame( if (__DEV__ && ownerFn) { ownerName = ownerFn.displayName || ownerFn.name || null; } - return describeComponentFrame(name, source, ownerName); + return describeComponentFrame(name, ownerName); } } @@ -362,7 +336,6 @@ function shouldConstruct(Component: Function) { export function describeUnknownElementTypeFrameInDEV( type: any, - source: void | null | Source, ownerFn: void | null | Function, ): string { if (!__DEV__) { @@ -375,36 +348,32 @@ export function describeUnknownElementTypeFrameInDEV( if (enableComponentStackLocations) { return describeNativeComponentFrame(type, shouldConstruct(type)); } else { - return describeFunctionComponentFrame(type, source, ownerFn); + return describeFunctionComponentFrame(type, ownerFn); } } if (typeof type === 'string') { - return describeBuiltInComponentFrame(type, source, ownerFn); + return describeBuiltInComponentFrame(type, ownerFn); } switch (type) { case REACT_SUSPENSE_TYPE: - return describeBuiltInComponentFrame('Suspense', source, ownerFn); + return describeBuiltInComponentFrame('Suspense', ownerFn); case REACT_SUSPENSE_LIST_TYPE: - return describeBuiltInComponentFrame('SuspenseList', source, ownerFn); + return describeBuiltInComponentFrame('SuspenseList', ownerFn); } if (typeof type === 'object') { switch (type.$$typeof) { case REACT_FORWARD_REF_TYPE: - return describeFunctionComponentFrame(type.render, source, ownerFn); + return describeFunctionComponentFrame(type.render, ownerFn); case REACT_MEMO_TYPE: // Memo may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); + return describeUnknownElementTypeFrameInDEV(type.type, ownerFn); case REACT_LAZY_TYPE: { const lazyComponent: LazyComponent = (type: any); const payload = lazyComponent._payload; const init = lazyComponent._init; try { // Lazy may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV( - init(payload), - source, - ownerFn, - ); + return describeUnknownElementTypeFrameInDEV(init(payload), ownerFn); } catch (x) {} } } diff --git a/packages/shared/ReactElementType.js b/packages/shared/ReactElementType.js index 7507eb9e1c6e5..c6024752a3be6 100644 --- a/packages/shared/ReactElementType.js +++ b/packages/shared/ReactElementType.js @@ -7,11 +7,6 @@ * @flow */ -export type Source = { - fileName: string, - lineNumber: number, -}; - export type ReactElement = { $$typeof: any, type: any, @@ -23,7 +18,4 @@ export type ReactElement = { // __DEV__ _store: {validated: boolean, ...}, - _self: React$Element, - _shadowChildren: any, - _source: Source, }; diff --git a/packages/shared/checkPropTypes.js b/packages/shared/checkPropTypes.js index dab145468a5bc..0b9582b236284 100644 --- a/packages/shared/checkPropTypes.js +++ b/packages/shared/checkPropTypes.js @@ -22,7 +22,6 @@ function setCurrentlyValidatingElement(element: any) { const owner = element._owner; const stack = describeUnknownElementTypeFrameInDEV( element.type, - element._source, owner ? owner.type : null, ); ReactDebugCurrentFrame.setExtraStackFrame(stack); From ee1b0bcc0a335b27187bf42131ec1daedf3bd5e4 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Wed, 7 Feb 2024 14:27:42 -0500 Subject: [PATCH 2/2] Add componentStack to ReactNativeInspector data This is fairly lazy in that only the selected instance calls this so the slow component stack call is ok. --- .../react-native-renderer/src/ReactNativeFiberInspector.js | 5 +++++ packages/react-native-renderer/src/ReactNativeTypes.js | 1 + 2 files changed, 6 insertions(+) diff --git a/packages/react-native-renderer/src/ReactNativeFiberInspector.js b/packages/react-native-renderer/src/ReactNativeFiberInspector.js index 3e6d222ee8d87..f30012b2cf917 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberInspector.js +++ b/packages/react-native-renderer/src/ReactNativeFiberInspector.js @@ -24,6 +24,7 @@ import { import {enableGetInspectorDataForInstanceInProduction} from 'shared/ReactFeatureFlags'; import {getClosestInstanceFromNode} from './ReactNativeComponentTree'; import {getNodeFromInternalInstanceHandle} from './ReactNativePublicCompat'; +import {getStackByFiberInDevAndProd} from 'react-reconciler/src/ReactFiberComponentStack'; const emptyObject = {}; if (__DEV__) { @@ -97,6 +98,7 @@ function getInspectorDataForInstance( hierarchy: [], props: emptyObject, selectedIndex: null, + componentStack: '', }; } @@ -106,12 +108,15 @@ function getInspectorDataForInstance( const hierarchy = createHierarchy(fiberHierarchy); const props = getHostProps(instance); const selectedIndex = fiberHierarchy.indexOf(instance); + const componentStack = + fiber !== null ? getStackByFiberInDevAndProd(fiber) : ''; return { closestInstance: instance, hierarchy, props, selectedIndex, + componentStack, }; } diff --git a/packages/react-native-renderer/src/ReactNativeTypes.js b/packages/react-native-renderer/src/ReactNativeTypes.js index 92c8c4de83bd5..f02b921b6ce7a 100644 --- a/packages/react-native-renderer/src/ReactNativeTypes.js +++ b/packages/react-native-renderer/src/ReactNativeTypes.js @@ -159,6 +159,7 @@ export type InspectorData = $ReadOnly<{ }>, selectedIndex: ?number, props: InspectorDataProps, + componentStack: string, }>; export type TouchedViewDataAtPoint = $ReadOnly<{