Skip to content

Commit abe70d3

Browse files
committed
[devtools] Fix can't expand prop value in some scenarios
1 parent 50393dc commit abe70d3

File tree

5 files changed

+170
-4
lines changed

5 files changed

+170
-4
lines changed

packages/react-devtools-shared/src/__tests__/__snapshots__/inspectedElementContext-test.js.snap

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`InspectedElementContext should allow component prop value and value\`s prototype has same name params.: 1: Inspected element 2 1`] = `
4+
{
5+
"id": 2,
6+
"owners": null,
7+
"context": null,
8+
"hooks": null,
9+
"props": {
10+
"data": {
11+
"b": null,
12+
"c": null,
13+
"d": "normal"
14+
}
15+
},
16+
"state": null
17+
}
18+
`;
19+
320
exports[`InspectedElementContext should dehydrate complex nested values when requested: 1: Initially inspect element 1`] = `
421
{
522
"id": 2,

packages/react-devtools-shared/src/__tests__/inspectedElementContext-test.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,82 @@ describe('InspectedElementContext', () => {
11071107
done();
11081108
});
11091109

1110+
it('should allow component prop value and value`s prototype has same name params.', async done => {
1111+
const testData = Object.create(
1112+
{
1113+
a: undefined,
1114+
b: Infinity,
1115+
c: NaN,
1116+
d: 'normal'
1117+
},
1118+
{
1119+
a: {
1120+
value: undefined,
1121+
writable: true,
1122+
enumerable: true,
1123+
configurable: true
1124+
},
1125+
b: {
1126+
value: Infinity,
1127+
writable: true,
1128+
enumerable: true,
1129+
configurable: true
1130+
},
1131+
c: {
1132+
value: NaN,
1133+
writable: true,
1134+
enumerable: true,
1135+
configurable: true
1136+
},
1137+
d: {
1138+
value: 'normal',
1139+
writable: true,
1140+
enumerable: true,
1141+
configurable: true
1142+
}
1143+
}
1144+
);
1145+
const Example = ({data}) => null;
1146+
const container = document.createElement('div');
1147+
await utils.actAsync(() =>
1148+
ReactDOM.render(<Example data={testData} />, container),
1149+
);
1150+
1151+
const id = ((store.getElementIDAtIndex(0): any): number);
1152+
1153+
let inspectedElement = null;
1154+
1155+
function Suspender({target}) {
1156+
const {getInspectedElement} = React.useContext(InspectedElementContext);
1157+
inspectedElement = getInspectedElement(id);
1158+
return null;
1159+
}
1160+
1161+
await utils.actAsync(
1162+
() =>
1163+
TestRenderer.create(
1164+
<Contexts
1165+
defaultSelectedElementID={id}
1166+
defaultSelectedElementIndex={0}>
1167+
<React.Suspense fallback={null}>
1168+
<Suspender target={id} />
1169+
</React.Suspense>
1170+
</Contexts>,
1171+
),
1172+
false,
1173+
);
1174+
expect(inspectedElement).not.toBeNull();
1175+
expect(inspectedElement).toMatchSnapshot(`1: Inspected element ${id}`);
1176+
expect(inspectedElement.props.data).toEqual({
1177+
a: undefined,
1178+
b: Infinity,
1179+
c: NaN,
1180+
d: 'normal'
1181+
});
1182+
1183+
done();
1184+
});
1185+
11101186
it('should not dehydrate nested values until explicitly requested', async done => {
11111187
const Example = () => {
11121188
const [state] = React.useState({

packages/react-devtools-shared/src/__tests__/legacy/__snapshots__/inspectElement-test.js.snap

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,26 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`InspectedElementContext should allow component prop value and value\`s prototype has same name params.: 1: Initially inspect element 1`] = `
4+
Object {
5+
"id": 2,
6+
"type": "full-data",
7+
"value": {
8+
"id": 2,
9+
"owners": null,
10+
"context": {},
11+
"hooks": null,
12+
"props": {
13+
"data": {
14+
"b": null,
15+
"c": null,
16+
"d": "normal"
17+
}
18+
},
19+
"state": null
20+
},
21+
}
22+
`;
23+
324
exports[`InspectedElementContext should inspect the currently selected element: 1: Initial inspection 1`] = `
425
Object {
526
"id": 2,

packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {InspectedElementPayload} from 'react-devtools-shared/src/backend/ty
1111
import type {DehydratedData} from 'react-devtools-shared/src/devtools/views/Components/types';
1212
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
1313
import type Store from 'react-devtools-shared/src/devtools/store';
14+
import { element } from 'prop-types';
1415

1516
describe('InspectedElementContext', () => {
1617
let React;
@@ -537,6 +538,57 @@ describe('InspectedElementContext', () => {
537538
done();
538539
});
539540

541+
542+
it('should allow component prop value and value`s prototype has same name params.', async done => {
543+
const testData = Object.create(
544+
{
545+
a: undefined,
546+
b: Infinity,
547+
c: NaN,
548+
d: 'normal'
549+
},
550+
{
551+
a: {
552+
value: undefined,
553+
writable: true,
554+
enumerable: true,
555+
configurable: true
556+
},
557+
b: {
558+
value: Infinity,
559+
writable: true,
560+
enumerable: true,
561+
configurable: true
562+
},
563+
c: {
564+
value: NaN,
565+
writable: true,
566+
enumerable: true,
567+
configurable: true
568+
},
569+
d: {
570+
value: 'normal',
571+
writable: true,
572+
enumerable: true,
573+
configurable: true
574+
}
575+
}
576+
);
577+
const Example = ({data}) => null;
578+
act(() =>
579+
ReactDOM.render(<Example data={testData} />, document.createElement('div')),
580+
);
581+
const id = ((store.getElementIDAtIndex(0): any): number);
582+
let inspectedElement = await read(id);
583+
expect(inspectedElement).toMatchSnapshot('1: Initially inspect element');
584+
const {props} = inspectedElement.value;
585+
expect(props.data.a).toBeUndefined();
586+
expect(Number.isFinite(props.data.b)).toBe(false);
587+
expect(props.data.c).toBeNaN();
588+
589+
done();
590+
});
591+
540592
it('should not dehydrate nested values until explicitly requested', async done => {
541593
const Example = () => null;
542594

packages/react-devtools-shared/src/utils.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ export function alphaSortKeys(
7070

7171
export function getAllEnumerableKeys(
7272
obj: Object,
73-
): Array<string | number | Symbol> {
74-
const keys = [];
73+
): Set<string | number | Symbol> {
74+
const keys = new Set();
7575
let current = obj;
7676
while (current != null) {
7777
const currentKeys = [
@@ -82,7 +82,7 @@ export function getAllEnumerableKeys(
8282
currentKeys.forEach(key => {
8383
// $FlowFixMe: key can be a Symbol https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor
8484
if (descriptors[key].enumerable) {
85-
keys.push(key);
85+
keys.add(key);
8686
}
8787
});
8888
current = Object.getPrototypeOf(current);
@@ -767,7 +767,7 @@ export function formatDataForPreview(
767767
return data.toString();
768768
case 'object':
769769
if (showFormattedValue) {
770-
const keys = getAllEnumerableKeys(data).sort(alphaSortKeys);
770+
const keys = Array.from(getAllEnumerableKeys(data)).sort(alphaSortKeys);
771771
772772
let formatted = '';
773773
for (let i = 0; i < keys.length; i++) {

0 commit comments

Comments
 (0)