diff --git a/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js b/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js
index 6a596a8b4a624..70a59b135e85e 100644
--- a/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js
+++ b/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js
@@ -1168,6 +1168,83 @@ describe('InspectedElement', () => {
done();
});
+ it('should allow component prop value and value`s prototype has same name params.', async done => {
+ const testData = Object.create(
+ {
+ a: undefined,
+ b: Infinity,
+ c: NaN,
+ d: 'normal',
+ },
+ {
+ a: {
+ value: undefined,
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ },
+ b: {
+ value: Infinity,
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ },
+ c: {
+ value: NaN,
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ },
+ d: {
+ value: 'normal',
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ },
+ },
+ );
+ const Example = ({data}) => null;
+ const container = document.createElement('div');
+ await utils.actAsync(() =>
+ ReactDOM.render(, container),
+ );
+
+ const id = ((store.getElementIDAtIndex(0): any): number);
+
+ let inspectedElement = null;
+
+ function Suspender({target}) {
+ inspectedElement = useInspectedElement(target);
+ return null;
+ }
+
+ await utils.actAsync(
+ () =>
+ TestRenderer.create(
+
+
+
+
+ ,
+ ),
+ false,
+ );
+ expect(inspectedElement.props).toMatchInlineSnapshot(`
+ Object {
+ "data": Object {
+ "a": undefined,
+ "b": Infinity,
+ "c": NaN,
+ "d": "normal",
+ },
+ }
+ `);
+
+ done();
+ });
+
it('should not dehydrate nested values until explicitly requested', async done => {
const Example = () => {
const [state] = React.useState({
diff --git a/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js b/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js
index 05d2bdcbeb6eb..6d446ca481de9 100644
--- a/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js
+++ b/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js
@@ -588,6 +588,66 @@ describe('InspectedElementContext', () => {
done();
});
+ it('should allow component prop value and value`s prototype has same name params.', async done => {
+ const testData = Object.create(
+ {
+ a: undefined,
+ b: Infinity,
+ c: NaN,
+ d: 'normal',
+ },
+ {
+ a: {
+ value: undefined,
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ },
+ b: {
+ value: Infinity,
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ },
+ c: {
+ value: NaN,
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ },
+ d: {
+ value: 'normal',
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ },
+ },
+ );
+
+ const Example = ({data}) => null;
+ act(() =>
+ ReactDOM.render(
+ ,
+ document.createElement('div'),
+ ),
+ );
+
+ const id = ((store.getElementIDAtIndex(0): any): number);
+ const inspectedElement = await read(id);
+
+ expect(inspectedElement.props).toMatchInlineSnapshot(`
+ Object {
+ "data": Object {
+ "a": undefined,
+ "b": Infinity,
+ "c": NaN,
+ "d": "normal",
+ },
+ }
+ `);
+ done();
+ });
+
it('should not dehydrate nested values until explicitly requested', async done => {
const Example = () => null;
diff --git a/packages/react-devtools-shared/src/hydration.js b/packages/react-devtools-shared/src/hydration.js
index 24379d675c4a9..69909cb2f658e 100644
--- a/packages/react-devtools-shared/src/hydration.js
+++ b/packages/react-devtools-shared/src/hydration.js
@@ -383,7 +383,9 @@ export function hydrate(
const value = parent[last];
- if (value.type === 'infinity') {
+ if (!value) {
+ return;
+ } else if (value.type === 'infinity') {
parent[last] = Infinity;
} else if (value.type === 'nan') {
parent[last] = NaN;
diff --git a/packages/react-devtools-shared/src/utils.js b/packages/react-devtools-shared/src/utils.js
index d84d5e67e98b6..be31af5c85ac8 100644
--- a/packages/react-devtools-shared/src/utils.js
+++ b/packages/react-devtools-shared/src/utils.js
@@ -70,8 +70,8 @@ export function alphaSortKeys(
export function getAllEnumerableKeys(
obj: Object,
-): Array {
- const keys = [];
+): Set {
+ const keys = new Set();
let current = obj;
while (current != null) {
const currentKeys = [
@@ -82,7 +82,7 @@ export function getAllEnumerableKeys(
currentKeys.forEach(key => {
// $FlowFixMe: key can be a Symbol https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor
if (descriptors[key].enumerable) {
- keys.push(key);
+ keys.add(key);
}
});
current = Object.getPrototypeOf(current);
@@ -767,7 +767,7 @@ export function formatDataForPreview(
return data.toString();
case 'object':
if (showFormattedValue) {
- const keys = getAllEnumerableKeys(data).sort(alphaSortKeys);
+ const keys = Array.from(getAllEnumerableKeys(data)).sort(alphaSortKeys);
let formatted = '';
for (let i = 0; i < keys.length; i++) {