@@ -1530,16 +1530,6 @@ export function attach(
15301530 // When a mount or update is in progress, this value tracks the root that is being operated on.
15311531 let currentRootID : number = - 1 ;
15321532
1533- function getFiberIDThrows ( fiber : Fiber ) : number {
1534- const fiberInstance = getFiberInstanceUnsafe ( fiber ) ;
1535- if ( fiberInstance !== null ) {
1536- return fiberInstance . id ;
1537- }
1538- throw Error (
1539- `Could not find ID for Fiber "${ getDisplayNameForFiber ( fiber ) || '' } "` ,
1540- ) ;
1541- }
1542-
15431533 // Returns a FiberInstance if one has already been generated for the Fiber or null if one has not been generated.
15441534 // Use this method while e.g. logging to avoid over-retaining Fibers.
15451535 function getFiberInstanceUnsafe ( fiber : Fiber ) : FiberInstance | null {
@@ -1625,7 +1615,7 @@ export function attach(
16251615 } ;
16261616 } else {
16271617 const data : ChangeDescription = {
1628- context : getContextChangedKeys ( nextFiber ) ,
1618+ context : getContextChanged ( prevFiber , nextFiber ) ,
16291619 didHooksChange : false ,
16301620 isFirstMount : false ,
16311621 props : getChangedKeys (
@@ -1659,7 +1649,7 @@ export function attach(
16591649 nextFiber . memoizedState ,
16601650 ) ;
16611651 const data : ChangeDescription = {
1662- context : getContextChangedKeys ( nextFiber ) ,
1652+ context : getContextChanged ( prevFiber , nextFiber ) ,
16631653 didHooksChange : indices !== null && indices . length > 0 ,
16641654 isFirstMount : false ,
16651655 props : getChangedKeys (
@@ -1677,147 +1667,33 @@ export function attach(
16771667 }
16781668 }
16791669
1680- function updateContextsForFiber ( fiber : Fiber ) {
1681- switch ( getElementTypeForFiber ( fiber ) ) {
1682- case ElementTypeClass :
1683- case ElementTypeForwardRef :
1684- case ElementTypeFunction :
1685- case ElementTypeMemo :
1686- if ( idToContextsMap !== null ) {
1687- const id = getFiberIDThrows ( fiber ) ;
1688- const contexts = getContextsForFiber ( fiber ) ;
1689- if ( contexts !== null ) {
1690- // $FlowFixMe[incompatible-use] found when upgrading Flow
1691- idToContextsMap . set ( id , contexts ) ;
1692- }
1693- }
1694- break ;
1695- default :
1696- break ;
1697- }
1698- }
1699-
1700- // Differentiates between a null context value and no context.
1701- const NO_CONTEXT = { } ;
1702-
1703- function getContextsForFiber ( fiber : Fiber ) : [ Object , any ] | null {
1704- let legacyContext = NO_CONTEXT ;
1705- let modernContext = NO_CONTEXT ;
1706-
1707- switch ( getElementTypeForFiber ( fiber ) ) {
1708- case ElementTypeClass :
1709- const instance = fiber . stateNode ;
1710- if ( instance != null ) {
1711- if (
1712- instance . constructor &&
1713- instance . constructor . contextType != null
1714- ) {
1715- modernContext = instance . context ;
1716- } else {
1717- legacyContext = instance . context ;
1718- if ( legacyContext && Object . keys ( legacyContext ) . length === 0 ) {
1719- legacyContext = NO_CONTEXT ;
1720- }
1721- }
1722- }
1723- return [ legacyContext , modernContext ] ;
1724- case ElementTypeForwardRef :
1725- case ElementTypeFunction :
1726- case ElementTypeMemo :
1727- const dependencies = fiber . dependencies ;
1728- if ( dependencies && dependencies . firstContext ) {
1729- modernContext = dependencies . firstContext ;
1730- }
1731-
1732- return [ legacyContext , modernContext ] ;
1733- default :
1734- return null ;
1735- }
1736- }
1737-
1738- // Record all contexts at the time profiling is started.
1739- // Fibers only store the current context value,
1740- // so we need to track them separately in order to determine changed keys.
1741- function crawlToInitializeContextsMap ( fiber : Fiber ) {
1742- const id = getFiberIDUnsafe ( fiber ) ;
1743-
1744- // Not all Fibers in the subtree have mounted yet.
1745- // For example, Offscreen (hidden) or Suspense (suspended) subtrees won't yet be tracked.
1746- // We can safely skip these subtrees.
1747- if ( id !== null ) {
1748- updateContextsForFiber ( fiber ) ;
1749-
1750- let current = fiber . child ;
1751- while ( current !== null ) {
1752- crawlToInitializeContextsMap ( current ) ;
1753- current = current . sibling ;
1670+ function getContextChanged ( prevFiber : Fiber , nextFiber : Fiber ) : boolean {
1671+ let prevContext =
1672+ prevFiber . dependencies && prevFiber . dependencies . firstContext ;
1673+ let nextContext =
1674+ nextFiber . dependencies && nextFiber . dependencies . firstContext ;
1675+
1676+ while ( prevContext && nextContext ) {
1677+ // Note this only works for versions of React that support this key (e.v. 18+)
1678+ // For older versions, there's no good way to read the current context value after render has completed.
1679+ // This is because React maintains a stack of context values during render,
1680+ // but by the time DevTools is called, render has finished and the stack is empty.
1681+ if ( prevContext . context !== nextContext . context ) {
1682+ // If the order of context has changed, then the later context values might have
1683+ // changed too but the main reason it rerendered was earlier. Either an earlier
1684+ // context changed value but then we would have exited already. If we end up here
1685+ // it's because a state or props change caused the order of contexts used to change.
1686+ // So the main cause is not the contexts themselves.
1687+ return false ;
17541688 }
1755- }
1756- }
1757-
1758- function getContextChangedKeys ( fiber : Fiber ) : null | boolean | Array < string > {
1759- if ( idToContextsMap !== null ) {
1760- const id = getFiberIDThrows ( fiber ) ;
1761- // $FlowFixMe[incompatible-use] found when upgrading Flow
1762- const prevContexts = idToContextsMap . has ( id )
1763- ? // $FlowFixMe[incompatible-use] found when upgrading Flow
1764- idToContextsMap . get ( id )
1765- : null ;
1766- const nextContexts = getContextsForFiber ( fiber ) ;
1767-
1768- if ( prevContexts == null || nextContexts == null ) {
1769- return null ;
1689+ if ( ! is ( prevContext . memoizedValue , nextContext . memoizedValue ) ) {
1690+ return true ;
17701691 }
17711692
1772- const [ prevLegacyContext , prevModernContext ] = prevContexts ;
1773- const [ nextLegacyContext , nextModernContext ] = nextContexts ;
1774-
1775- switch ( getElementTypeForFiber ( fiber ) ) {
1776- case ElementTypeClass :
1777- if ( prevContexts && nextContexts ) {
1778- if ( nextLegacyContext !== NO_CONTEXT ) {
1779- return getChangedKeys ( prevLegacyContext , nextLegacyContext ) ;
1780- } else if ( nextModernContext !== NO_CONTEXT ) {
1781- return prevModernContext !== nextModernContext ;
1782- }
1783- }
1784- break ;
1785- case ElementTypeForwardRef :
1786- case ElementTypeFunction :
1787- case ElementTypeMemo :
1788- if ( nextModernContext !== NO_CONTEXT ) {
1789- let prevContext = prevModernContext ;
1790- let nextContext = nextModernContext ;
1791-
1792- while ( prevContext && nextContext ) {
1793- // Note this only works for versions of React that support this key (e.v. 18+)
1794- // For older versions, there's no good way to read the current context value after render has completed.
1795- // This is because React maintains a stack of context values during render,
1796- // but by the time DevTools is called, render has finished and the stack is empty.
1797- if ( prevContext . context !== nextContext . context ) {
1798- // If the order of context has changed, then the later context values might have
1799- // changed too but the main reason it rerendered was earlier. Either an earlier
1800- // context changed value but then we would have exited already. If we end up here
1801- // it's because a state or props change caused the order of contexts used to change.
1802- // So the main cause is not the contexts themselves.
1803- return false ;
1804- }
1805- if ( ! is ( prevContext . memoizedValue , nextContext . memoizedValue ) ) {
1806- return true ;
1807- }
1808-
1809- prevContext = prevContext . next ;
1810- nextContext = nextContext . next ;
1811- }
1812-
1813- return false ;
1814- }
1815- break ;
1816- default :
1817- break ;
1818- }
1693+ prevContext = prevContext . next ;
1694+ nextContext = nextContext . next ;
18191695 }
1820- return null ;
1696+ return false ;
18211697 }
18221698
18231699 function isHookThatCanScheduleUpdate ( hookObject : any ) {
@@ -3002,8 +2878,6 @@ export function attach(
30022878 metadata . changeDescriptions . set ( id , changeDescription ) ;
30032879 }
30042880 }
3005-
3006- updateContextsForFiber ( fiber ) ;
30072881 }
30082882 }
30092883 }
@@ -5209,7 +5083,6 @@ export function attach(
52095083
52105084 let currentCommitProfilingMetadata: CommitProfilingData | null = null;
52115085 let displayNamesByRootID: DisplayNamesByRootID | null = null;
5212- let idToContextsMap: Map< number , any > | null = null;
52135086 let initialTreeBaseDurationsMap: Map< number , Array < [ number , number ] >> | null =
52145087 null ;
52155088 let isProfiling : boolean = false ;
@@ -5356,7 +5229,6 @@ export function attach(
53565229 // (e.g. when a fiber is re-rendered or when a fiber gets removed).
53575230 displayNamesByRootID = new Map();
53585231 initialTreeBaseDurationsMap = new Map();
5359- idToContextsMap = new Map();
53605232
53615233 hook.getFiberRoots(rendererID).forEach(root => {
53625234 const rootInstance = rootToFiberInstanceMap . get ( root ) ;
@@ -5373,13 +5245,6 @@ export function attach(
53735245 const initialTreeBaseDurations : Array < [ number , number ] > = [ ] ;
53745246 snapshotTreeBaseDurations ( rootInstance , initialTreeBaseDurations ) ;
53755247 ( initialTreeBaseDurationsMap : any ) . set ( rootID , initialTreeBaseDurations ) ;
5376-
5377- if ( shouldRecordChangeDescriptions ) {
5378- // Record all contexts at the time profiling is started.
5379- // Fibers only store the current context value,
5380- // so we need to track them separately in order to determine changed keys.
5381- crawlToInitializeContextsMap ( root . current ) ;
5382- }
53835248 } );
53845249
53855250 isProfiling = true;
0 commit comments