DevTools can inspect Proxies that return broken iterator functions (#21660)
Brian Vaughn committed
Jun 11, 2021 at 10:15 UTC
01be61c12f4361dc9e4c4f4157bffbeb0e57b064
2 files changed
+47
-3
packages/react-devtools-shared/src/__tests__/inspectedElement-test.js
+40
@@ -1813,6 +1813,46 @@ describe('InspectedElement', () => {
1813
`);
1814
});
1815
1816
+ // See github.com/facebook/react/issues/21654
1817
+ it('should support Proxies that dont return an iterator', async () => {
1818
+ const Example = () => null;
1819
+ const proxy = new Proxy(
1820
+ {},
1821
+ {
1822
+ get: (target, prop, receiver) => {
1823
+ target[prop] = value => {};
1824
+ return target[prop];
1825
+ },
1826
+ },
1827
+ );
1828
+
1829
+ const container = document.createElement('div');
1830
+ await utils.actAsync(() =>
1831
+ ReactDOM.render(<Example proxy={proxy} />, container),
1832
+ );
1833
+
1834
+ const inspectedElement = await inspectElementAtIndex(0);
1835
+
1836
+ expect(inspectedElement.props).toMatchInlineSnapshot(`
1837
+ Object {
1838
+ "proxy": Object {
1839
+ "$$typeof": Dehydrated {
1840
+ "preview_short": ƒ () {},
1841
+ "preview_long": ƒ () {},
1842
+ },
1843
+ "Symbol(Symbol.iterator)": Dehydrated {
1844
+ "preview_short": ƒ () {},
1845
+ "preview_long": ƒ () {},
1846
+ },
1847
+ "constructor": Dehydrated {
1848
+ "preview_short": ƒ () {},
1849
+ "preview_long": ƒ () {},
1850
+ },
1851
+ },
1852
+ }
1853
+ `);
1854
+ });
1855
+
1856
describe('$r', () => {
1857
it('should support function components', async () => {
1858
const Example = () => {
packages/react-devtools-shared/src/utils.js
+7
-3
@@ -540,9 +540,13 @@ export function getDataType(data: Object): DataType {
540
// but this seems kind of awkward and expensive.
541
return 'array_buffer';
542
} else if (typeof data[Symbol.iterator] === 'function') {
543
- return data[Symbol.iterator]() === data
544
- ? 'opaque_iterator'
545
- : 'iterator';
543
+ const iterator = data[Symbol.iterator]();
544
+ if (!iterator) {
545
+ // Proxies might break assumptoins about iterators.
546
+ // See github.com/facebook/react/issues/21654
547
+ } else {
548
+ return iterator === data ? 'opaque_iterator' : 'iterator';
549
+ }
550
} else if (data.constructor && data.constructor.name === 'RegExp') {
551
return 'regexp';
552
} else {