[DevTools] Display RegExp values in props/state (#17690)
Previously, when props/state contained a regexp, it was shown as an empty object. This commit adds regexps as values in need of special rehydration (like Symbols or TypedArrays), and display them as a user might expect. Co-authored-by: Zirak <zirakertan@gmail.com>
Brian Vaughn committed
Dec 22, 2019 at 11:49 UTC
f887d1aa27336baa0bc292158793a5a244c712b6
7 files changed
+34
packages/react-devtools-shared/src/__tests__/__snapshots__/inspectedElementContext-test.js.snap
+1
@@ -511,6 +511,7 @@ exports[`InspectedElementContext should support complex data types: 1: Inspected
511
"inner": {}
512
},
513
"react_element": {},
514
+ "regexp": {},
515
"set": {
516
"0": "abc",
517
"1": 123
packages/react-devtools-shared/src/__tests__/inspectedElementContext-test.js
+8
@@ -555,6 +555,7 @@ describe('InspectedElementContext', () => {
555
map_of_maps={mapOfMaps}
556
object_of_objects={objectOfObjects}
557
react_element={<span />}
558
+ regexp={/abc/giu}
559
set={setShallow}
560
set_of_sets={setOfSets}
561
symbol={Symbol('symbol')}
@@ -604,6 +605,7 @@ describe('InspectedElementContext', () => {
605
map_of_maps,
606
object_of_objects,
607
react_element,
608
+ regexp,
609
set,
610
set_of_sets,
611
symbol,
@@ -699,6 +701,12 @@ describe('InspectedElementContext', () => {
701
expect(react_element[meta.preview_long]).toBe('<span />');
702
expect(react_element[meta.preview_short]).toBe('<span />');
703
704
+ expect(regexp[meta.inspectable]).toBe(false);
705
+ expect(regexp[meta.name]).toBe('/abc/giu');
706
+ expect(regexp[meta.preview_long]).toBe('/abc/giu');
707
+ expect(regexp[meta.preview_short]).toBe('/abc/giu');
708
+ expect(regexp[meta.type]).toBe('regexp');
709
+
710
expect(set[meta.inspectable]).toBeUndefined(); // Complex type
711
expect(set[meta.name]).toBe('Set');
712
expect(set[meta.type]).toBe('iterator');
packages/react-devtools-shared/src/__tests__/legacy/__snapshots__/inspectElement-test.js.snap
+1
@@ -152,6 +152,7 @@ Object {
152
"inner": {}
153
},
154
"react_element": {},
155
+ "regexp": {},
156
"set": {
157
"0": "abc",
158
"1": 123
packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js
+8
@@ -185,6 +185,7 @@ describe('InspectedElementContext', () => {
185
map_of_maps={mapOfMaps}
186
object_of_objects={objectOfObjects}
187
react_element={<span />}
188
+ regexp={/abc/giu}
189
set={setShallow}
190
set_of_sets={setOfSets}
191
symbol={Symbol('symbol')}
@@ -212,6 +213,7 @@ describe('InspectedElementContext', () => {
213
map_of_maps,
214
object_of_objects,
215
react_element,
216
+ regexp,
217
set,
218
set_of_sets,
219
symbol,
@@ -279,6 +281,12 @@ describe('InspectedElementContext', () => {
281
expect(react_element[meta.name]).toBe('span');
282
expect(react_element[meta.type]).toBe('react_element');
283
284
+ expect(regexp[meta.inspectable]).toBe(false);
285
+ expect(regexp[meta.name]).toBe('/abc/giu');
286
+ expect(regexp[meta.preview_long]).toBe('/abc/giu');
287
+ expect(regexp[meta.preview_short]).toBe('/abc/giu');
288
+ expect(regexp[meta.type]).toBe('regexp');
289
+
290
expect(set[meta.inspectable]).toBeUndefined(); // Complex type
291
expect(set[meta.name]).toBe('Set');
292
expect(set[meta.type]).toBe('iterator');
packages/react-devtools-shared/src/hydration.js
+10
@@ -271,6 +271,16 @@ export function dehydrate(
271
type,
272
};
273
274
+ case 'regexp':
275
+ cleaned.push(path);
276
+ return {
277
+ inspectable: false,
278
+ preview_short: formatDataForPreview(data, false),
279
+ preview_long: formatDataForPreview(data, true),
280
+ name: data.toString(),
281
+ type,
282
+ };
283
+
284
case 'object':
285
isPathWhitelistedCheck = isPathWhitelisted(path);
286
if (level >= LEVEL_THRESHOLD && !isPathWhitelistedCheck) {
packages/react-devtools-shared/src/utils.js
+5
@@ -340,6 +340,7 @@ export type DataType =
340
| 'number'
341
| 'object'
342
| 'react_element'
343
+ | 'regexp'
344
| 'string'
345
| 'symbol'
346
| 'typed_array'
@@ -395,6 +396,8 @@ export function getDataType(data: Object): DataType {
396
return 'array_buffer';
397
} else if (typeof data[Symbol.iterator] === 'function') {
398
return 'iterator';
399
+ } else if (data.constructor.name === 'RegExp') {
400
+ return 'regexp';
401
} else if (Object.prototype.toString.call(data) === '[object Date]') {
402
return 'date';
403
}
@@ -504,6 +507,8 @@ export function formatDataForPreview(
507
return `"${data}"`;
508
case 'bigint':
509
return truncateForDisplay(data.toString() + 'n');
510
+ case 'regexp':
511
+ return truncateForDisplay(data.toString());
512
case 'symbol':
513
return truncateForDisplay(data.toString());
514
case 'react_element':
packages/react-devtools-shell/src/app/InspectableElements/SimpleValues.js
+1
@@ -24,6 +24,7 @@ export default function SimpleValues() {
24
true={true}
25
false={false}
26
function={noop}
27
+ regex={/abc[123]+/i}
28
/>
29
);
30
}