@samitouri / QOS-React / commits / 9635257c1b

[DevTools] Preserve -Infinity in inspected values (#36347)

## Summary `getDataType` collapsed both `Infinity` and `-Infinity` to the `'infinity'` data type, so a `-Infinity` value coming from inspected props/state/hooks was rehydrated on the frontend as `Infinity`. This adds a `'-infinity'` `DataType`, routes it through `dehydrate`/`hydrate` alongside the existing `'infinity'` arm, and makes `smartParse`/`smartStringify` (used for editable hook values) symmetric. ## Files - `packages/react-devtools-shared/src/utils.js` — extend `DataType`, split sign in `getDataType`, route `'-infinity'` through `formatDataForPreview`. - `packages/react-devtools-shared/src/hydration.js` — `dehydrate` and `hydrate` cases for `'-infinity'`. - `packages/react-devtools-shared/src/devtools/utils.js` — `smartParse` accepts `'-Infinity'`; `smartStringify` returns `'-Infinity'` for negative infinite values. - `packages/react-devtools-shared/src/__tests__/inspectedElement-test.js` and `legacy/inspectElement-test.js` — added `minus_infinity={-Infinity}` to the simple-data-types tests + snapshots. - `packages/react-devtools-shell/src/app/InspectableElements/SimpleValues.js` — added `minusInfinity` to the dev shell so the path is exercised manually. ## Test plan - [x] `yarn prettier` / `yarn linc` - [x] `yarn flow dom-node` — no errors - [x] `yarn test --silent --no-watchman -t "should support simple data types"` (source channel) - [x] `yarn test-www --silent --no-watchman -t "should support simple data types"` (www-modern) - [ ] `yarn test-build-devtools` — relies on a built bundle; left to CI per repo policy. Fixes #32552

zxuhan7 committed May 2, 2026 at 10:50 UTC 9635257c1b557acc81f95b1e974a54c752e703a2
6 files changed +14 -2
packages/react-devtools-shared/src/__tests__/inspectedElement-test.js
+2
@@ -582,6 +582,7 @@ describe('InspectedElement', () => {
582 boolean_false={false}
583 boolean_true={true}
584 infinity={Infinity}
585 + minus_infinity={-Infinity}
586 integer_zero={0}
587 integer_one={1}
588 float={1.23}
@@ -604,6 +605,7 @@ describe('InspectedElement', () => {
605 "infinity": Infinity,
606 "integer_one": 1,
607 "integer_zero": 0,
608 + "minus_infinity": -Infinity,
609 "nan": NaN,
610 "string": "abc",
611 "string_empty": "",
packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js
+2
@@ -98,6 +98,7 @@ describe('InspectedElementContext', () => {
98 boolean_false: false,
99 boolean_true: true,
100 infinity: Infinity,
101 + minus_infinity: -Infinity,
102 integer_zero: 0,
103 integer_one: 1,
104 float: 1.23,
@@ -128,6 +129,7 @@ describe('InspectedElementContext', () => {
129 "infinity": Infinity,
130 "integer_one": 1,
131 "integer_zero": 0,
132 + "minus_infinity": -Infinity,
133 "nan": NaN,
134 "string": "abc",
135 "string_empty": "",
packages/react-devtools-shared/src/devtools/utils.js
+3 -1
@@ -235,6 +235,8 @@ export function smartParse(value: any): any | void | number {
235 switch (value) {
236 case 'Infinity':
237 return Infinity;
238 + case '-Infinity':
239 + return -Infinity;
240 case 'NaN':
241 return NaN;
242 case 'undefined':
@@ -249,7 +251,7 @@ export function smartStringify(value: any): string {
251 if (Number.isNaN(value)) {
252 return 'NaN';
253 } else if (!Number.isFinite(value)) {
252 - return 'Infinity';
254 + return value > 0 ? 'Infinity' : '-Infinity';
255 }
256 } else if (value === undefined) {
257 return 'undefined';
packages/react-devtools-shared/src/hydration.js
+3
@@ -596,6 +596,7 @@ export function dehydrate(
596 return value;
597 }
598 case 'infinity':
599 + case '-infinity':
600 case 'nan':
601 case 'undefined':
602 // Some values are lossy when sent through a WebSocket.
@@ -704,6 +705,8 @@ export function hydrate(
705 return;
706 } else if (value.type === 'infinity') {
707 parent[last] = Infinity;
708 + } else if (value.type === '-infinity') {
709 + parent[last] = -Infinity;
710 } else if (value.type === 'nan') {
711 parent[last] = NaN;
712 } else if (value.type === 'undefined') {
packages/react-devtools-shared/src/utils.js
+3 -1
@@ -708,6 +708,7 @@ export type DataType =
708 | 'html_all_collection'
709 | 'html_element'
710 | 'infinity'
711 + | '-infinity'
712 | 'iterator'
713 | 'opaque_iterator'
714 | 'nan'
@@ -765,7 +766,7 @@ export function getDataType(data: Object): DataType {
766 if (Number.isNaN(data)) {
767 return 'nan';
768 } else if (!Number.isFinite(data)) {
768 - return 'infinity';
769 + return data > 0 ? 'infinity' : '-infinity';
770 } else {
771 return 'number';
772 }
@@ -1219,6 +1220,7 @@ export function formatDataForPreview(
1220 case 'boolean':
1221 case 'number':
1222 case 'infinity':
1223 + case '-infinity':
1224 case 'nan':
1225 case 'null':
1226 case 'undefined':
packages/react-devtools-shell/src/app/InspectableElements/SimpleValues.js
+1
@@ -25,6 +25,7 @@ export default class SimpleValues extends Component {
25 null={null}
26 nan={NaN}
27 infinity={Infinity}
28 + minusInfinity={-Infinity}
29 true={true}
30 false={false}
31 function={noop}