DevTools bug fix: Proxied methods should be safely dehydrated for display
Pascal Fong Kye committed
Aug 12, 2020 at 18:15 UTC
b6e1d086043a801682ff01b00c7a623d529b46c0
5 files changed
+25
-3
packages/react-devtools-extensions/src/backend.js
+1
-1
@@ -72,7 +72,7 @@ function setup(hook) {
72
initBackend(hook, agent, window);
73
74
// Let the frontend know that the backend has attached listeners and is ready for messages.
75
- // This covers the case of of syncing saved values after reloading/navigating while DevTools remain open.
75
+ // This covers the case of syncing saved values after reloading/navigating while DevTools remain open.
76
bridge.send('extensionBackendInitialized');
77
78
// Setup React Native style editor if a renderer like react-native-web has injected it.
packages/react-devtools-shared/src/__tests__/__snapshots__/inspectedElementContext-test.js.snap
+1
@@ -541,6 +541,7 @@ exports[`InspectedElementContext should support complex data types: 1: Inspected
541
"object_of_objects": {
542
"inner": {}
543
},
544
+ "proxy": {},
545
"react_element": {},
546
"regexp": {},
547
"set": {
packages/react-devtools-shared/src/__tests__/inspectedElementContext-test.js
+16
@@ -549,6 +549,14 @@ describe('InspectedElementContext', () => {
549
}
550
const instance = new Class();
551
552
+ const proxyInstance = new Proxy(() => {}, {
553
+ get: function(_, name) {
554
+ return function() {
555
+ return null;
556
+ };
557
+ },
558
+ });
559
+
560
const container = document.createElement('div');
561
await utils.actAsync(() =>
562
ReactDOM.render(
@@ -567,6 +575,7 @@ describe('InspectedElementContext', () => {
575
map={mapShallow}
576
map_of_maps={mapOfMaps}
577
object_of_objects={objectOfObjects}
578
+ proxy={proxyInstance}
579
react_element={<span />}
580
regexp={/abc/giu}
581
set={setShallow}
@@ -619,6 +628,7 @@ describe('InspectedElementContext', () => {
628
map,
629
map_of_maps,
630
object_of_objects,
631
+ proxy,
632
react_element,
633
regexp,
634
set,
@@ -722,6 +732,12 @@ describe('InspectedElementContext', () => {
732
);
733
expect(object_of_objects.inner[meta.preview_short]).toBe('{…}');
734
735
+ expect(proxy[meta.inspectable]).toBe(false);
736
+ expect(proxy[meta.name]).toBe('function');
737
+ expect(proxy[meta.type]).toBe('function');
738
+ expect(proxy[meta.preview_long]).toBe('ƒ () {}');
739
+ expect(proxy[meta.preview_short]).toBe('ƒ () {}');
740
+
741
expect(react_element[meta.inspectable]).toBe(false);
742
expect(react_element[meta.name]).toBe('span');
743
expect(react_element[meta.type]).toBe('react_element');
packages/react-devtools-shared/src/hydration.js
+4
-1
@@ -151,7 +151,10 @@ export function dehydrate(
151
inspectable: false,
152
preview_short: formatDataForPreview(data, false),
153
preview_long: formatDataForPreview(data, true),
154
- name: data.name || 'function',
154
+ name:
155
+ typeof data.name === 'function' || !data.name
156
+ ? 'function'
157
+ : data.name,
158
type,
159
};
160
packages/react-devtools-shared/src/utils.js
+3
-1
@@ -539,7 +539,9 @@ export function formatDataForPreview(
539
case 'html_element':
540
return `<${truncateForDisplay(data.tagName.toLowerCase())} />`;
541
case 'function':
542
- return truncateForDisplay(`ƒ ${data.name}() {}`);
542
+ return truncateForDisplay(
543
+ `ƒ ${typeof data.name === 'function' ? '' : data.name}() {}`,
544
+ );
545
case 'string':
546
return `"${data}"`;
547
case 'bigint':