@samitouri / QOS-React-2 / commits / f887d1aa27

[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 }