Repository: facebook/react
Pull request: [Perf Tracks] Handle arrays with bigints in deep objects

Fixes https://github.com/facebook/react/issues/35004
Closes https://github.com/facebook/react/pull/35013

We show arrays with primitive values `JSON.stringify`ed in the performance tracks. However, `bigint` is not accepted by `JSON.stringify` so we have to treat arrays with these values as complex.

We could implement a replacer that stringifies `bigint`. [A replacer would be considerably slower in latest versions of v8](https://v8.dev/blog/json-stringify)

Changed files:
filename: packages/react-reconciler/src/__tests__/ReactPerformanceTrack-test.js
patch: @@ -440,4 +440,87 @@ describe('ReactPerformanceTracks', () => {
     ]);
     performanceMeasureCalls.length = 0;
   });
+
+  // @gate __DEV__ && enableComponentPerformanceTrack
+  it('can handle bigint in arrays', async () => {
+    const App = function App({numbers}) {
+      Scheduler.unstable_advanceTime(10);
+      React.useEffect(() => {}, [numbers]);
+    };
+
+    Scheduler.unstable_advanceTime(1);
+    await act(() => {
+      ReactNoop.render(
+        <App
+          data={{
+            deeply: {
+              nested: {
+                numbers: [1n],
+              },
+            },
+          }}
+        />,
+      );
+    });
+
+    expect(performanceMeasureCalls).toEqual([
+      [
+        'Mount',
+        {
+          detail: {
+            devtools: {
+              color: 'warning',
+              properties: null,
+              tooltipText: 'Mount',
+              track: 'Components ⚛',
+            },
+          },
+          end: 11,
+          start: 1,
+        },
+      ],
+    ]);
+    performanceMeasureCalls.length = 0;
+
+    Scheduler.unstable_advanceTime(10);
+
+    await act(() => {
+      ReactNoop.render(
+        <App
+          data={{
+            deeply: {
+              nested: {
+                numbers: [2n],
+              },
+            },
+          }}
+        />,
+      );
+    });
+
+    expect(performanceMeasureCalls).toEqual([
+      [
+        '​App',
+        {
+          detail: {
+            devtools: {
+              color: 'primary-dark',
+              properties: [
+                ['Changed Props', ''],
+                ['  data', ''],
+                ['    deeply', ''],
+                ['      nested', ''],
+                ['–       numbers', 'Array'],
+                ['+       numbers', 'Array'],
+              ],
+              tooltipText: 'App',
+              track: 'Components ⚛',
+            },
+          },
+          end: 31,
+          start: 21,
+        },
+      ],
+    ]);
+  });
 });

filename: packages/shared/ReactPerformanceTrackProperties.js
patch: @@ -16,7 +16,7 @@ import getComponentNameFromType from './getComponentNameFromType';
 
 const EMPTY_ARRAY = 0;
 const COMPLEX_ARRAY = 1;
-const PRIMITIVE_ARRAY = 2; // Primitive values only
+const PRIMITIVE_ARRAY = 2; // Primitive values only that are accepted by JSON.stringify
 const ENTRIES_ARRAY = 3; // Tuple arrays of string and value (like Headers, Map, etc)
 
 // Showing wider objects in the devtools is not useful.
@@ -46,6 +46,8 @@ function getArrayKind(array: Object): 0 | 1 | 2 | 3 {
       return COMPLEX_ARRAY;
     } else if (kind !== EMPTY_ARRAY && kind !== PRIMITIVE_ARRAY) {
       return COMPLEX_ARRAY;
+    } else if (typeof value === 'bigint') {
+      return COMPLEX_ARRAY;
     } else {
       kind = PRIMITIVE_ARRAY;
     }