Skip to content

Commit

Permalink
Added missing guard to DevTools for Objects with null proto (#17757)
Browse files Browse the repository at this point in the history
This prevents a runtime error from occurring when these objects are inspected.
  • Loading branch information
Brian Vaughn authored Jan 2, 2020
1 parent 2c1e5d2 commit 195b3db
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,11 @@ exports[`InspectedElementContext should support complex data types: 1: Inspected
"object_of_objects": {
"inner": {}
},
"object_with_null_proto": {
"string": "abc",
"number": 123,
"boolean": true
},
"react_element": {},
"regexp": {},
"set": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ describe('InspectedElementContext', () => {
const setOfSets = new Set([new Set(['a', 'b', 'c']), new Set([1, 2, 3])]);
const mapOfMaps = new Map([['first', mapShallow], ['second', mapShallow]]);
const objectOfObjects = {
inner: {string: 'abc', number: 213, boolean: true},
inner: {string: 'abc', number: 123, boolean: true},
};
const typedArray = Int8Array.from([100, -100, 0]);
const arrayBuffer = typedArray.buffer;
Expand All @@ -537,6 +537,10 @@ describe('InspectedElementContext', () => {
xyz: 1,
},
});
const objectWithNullProto = Object.create(null);
objectWithNullProto.string = 'abc';
objectWithNullProto.number = 123;
objectWithNullProto.boolean = true;

const container = document.createElement('div');
await utils.actAsync(() =>
Expand All @@ -554,6 +558,7 @@ describe('InspectedElementContext', () => {
map={mapShallow}
map_of_maps={mapOfMaps}
object_of_objects={objectOfObjects}
object_with_null_proto={objectWithNullProto}
react_element={<span />}
regexp={/abc/giu}
set={setShallow}
Expand Down Expand Up @@ -604,6 +609,7 @@ describe('InspectedElementContext', () => {
map,
map_of_maps,
object_of_objects,
object_with_null_proto,
react_element,
regexp,
set,
Expand Down Expand Up @@ -691,10 +697,16 @@ describe('InspectedElementContext', () => {
expect(object_of_objects.inner[meta.name]).toBe('');
expect(object_of_objects.inner[meta.type]).toBe('object');
expect(object_of_objects.inner[meta.preview_long]).toBe(
'{boolean: true, number: 213, string: "abc"}',
'{boolean: true, number: 123, string: "abc"}',
);
expect(object_of_objects.inner[meta.preview_short]).toBe('{…}');

expect(object_with_null_proto).toEqual({
boolean: true,
number: 123,
string: 'abc',
});

expect(react_element[meta.inspectable]).toBe(false);
expect(react_element[meta.name]).toBe('span');
expect(react_element[meta.type]).toBe('react_element');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ Object {
"object_of_objects": {
"inner": {}
},
"object_with_null_proto": {
"string": "abc",
"number": 123,
"boolean": true
},
"react_element": {},
"regexp": {},
"set": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ describe('InspectedElementContext', () => {
const setOfSets = new Set([new Set(['a', 'b', 'c']), new Set([1, 2, 3])]);
const mapOfMaps = new Map([['first', mapShallow], ['second', mapShallow]]);
const objectOfObjects = {
inner: {string: 'abc', number: 213, boolean: true},
inner: {string: 'abc', number: 123, boolean: true},
};
const typedArray = Int8Array.from([100, -100, 0]);
const arrayBuffer = typedArray.buffer;
Expand All @@ -168,6 +168,10 @@ describe('InspectedElementContext', () => {
xyz: 1,
},
});
const objectWithNullProto = Object.create(null);
objectWithNullProto.string = 'abc';
objectWithNullProto.number = 123;
objectWithNullProto.boolean = true;

act(() =>
ReactDOM.render(
Expand All @@ -184,6 +188,7 @@ describe('InspectedElementContext', () => {
map={mapShallow}
map_of_maps={mapOfMaps}
object_of_objects={objectOfObjects}
object_with_null_proto={objectWithNullProto}
react_element={<span />}
regexp={/abc/giu}
set={setShallow}
Expand Down Expand Up @@ -212,6 +217,7 @@ describe('InspectedElementContext', () => {
map,
map_of_maps,
object_of_objects,
object_with_null_proto,
react_element,
regexp,
set,
Expand Down Expand Up @@ -273,10 +279,16 @@ describe('InspectedElementContext', () => {
expect(object_of_objects.inner[meta.name]).toBe('');
expect(object_of_objects.inner[meta.type]).toBe('object');
expect(object_of_objects.inner[meta.preview_long]).toBe(
'{boolean: true, number: 213, string: "abc"}',
'{boolean: true, number: 123, string: "abc"}',
);
expect(object_of_objects.inner[meta.preview_short]).toBe('{…}');

expect(object_with_null_proto).toEqual({
boolean: true,
number: 123,
string: 'abc',
});

expect(react_element[meta.inspectable]).toBe(false);
expect(react_element[meta.name]).toBe('span');
expect(react_element[meta.type]).toBe('react_element');
Expand Down
4 changes: 2 additions & 2 deletions packages/react-devtools-shared/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,15 +388,15 @@ export function getDataType(data: Object): DataType {
return data.constructor.hasOwnProperty('BYTES_PER_ELEMENT')
? 'typed_array'
: 'data_view';
} else if (data.constructor.name === 'ArrayBuffer') {
} else if (data.constructor && data.constructor.name === 'ArrayBuffer') {
// HACK This ArrayBuffer check is gross; is there a better way?
// We could try to create a new DataView with the value.
// If it doesn't error, we know it's an ArrayBuffer,
// but this seems kind of awkward and expensive.
return 'array_buffer';
} else if (typeof data[Symbol.iterator] === 'function') {
return 'iterator';
} else if (data.constructor.name === 'RegExp') {
} else if (data.constructor && data.constructor.name === 'RegExp') {
return 'regexp';
} else if (Object.prototype.toString.call(data) === '[object Date]') {
return 'date';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ const immutable = Immutable.fromJS({
xyz: 1,
},
});
const objectWithNullProto = Object.create(null);
objectWithNullProto.foo = 'abc';
objectWithNullProto.bar = 123;

export default function UnserializableProps() {
return (
Expand All @@ -37,6 +40,7 @@ export default function UnserializableProps() {
setOfSets={setOfSets}
typedArray={typedArray}
immutable={immutable}
objectWithNullProto={objectWithNullProto}
/>
);
}
Expand Down

0 comments on commit 195b3db

Please sign in to comment.