DevTools bugfix for useState() with hasOwnProperty key (#21524)
Brian Vaughn committed
May 18, 2021 at 13:43 UTC
b15bf2b2f1effb6f760effac9f48c5901622f27b
2 files changed
+43
-8
packages/react-devtools-shared/src/__tests__/profilerStore-test.js
+32
@@ -135,4 +135,36 @@ describe('ProfilerStore', () => {
135
});
136
}).toThrow('Cannot modify filter preferences while profiling');
137
});
138
+
139
+ it('should not throw if state contains a property hasOwnProperty ', () => {
140
+ let setStateCallback;
141
+ const ControlledInput = () => {
142
+ const [state, setState] = React.useState({hasOwnProperty: true});
143
+ setStateCallback = setState;
144
+ return state.hasOwnProperty;
145
+ };
146
+
147
+ const container = document.createElement('div');
148
+
149
+ // This element has to be in the <body> for the event system to work.
150
+ document.body.appendChild(container);
151
+
152
+ // It's important that this test uses legacy sync mode.
153
+ // The root API does not trigger this particular failing case.
154
+ ReactDOM.render(<ControlledInput />, container);
155
+
156
+ utils.act(() => store.profilerStore.startProfiling());
157
+ utils.act(() =>
158
+ setStateCallback({
159
+ hasOwnProperty: false,
160
+ }),
161
+ );
162
+ utils.act(() => store.profilerStore.stopProfiling());
163
+
164
+ // Only one commit should have been recorded (in response to the "change" event).
165
+ const root = store.roots[0];
166
+ const data = store.profilerStore.getDataForRoot(root);
167
+ expect(data.commitData).toHaveLength(1);
168
+ expect(data.operations).toHaveLength(1);
169
+ });
170
});
packages/react-devtools-shared/src/backend/renderer.js
+11
-8
@@ -1221,15 +1221,18 @@ export function attach(
1221
}
1222
1223
function isEffect(memoizedState) {
1224
+ if (memoizedState === null || typeof memoizedState !== 'object') {
1225
+ return false;
1226
+ }
1227
+ const {deps} = memoizedState;
1228
+ const hasOwnProperty = Object.prototype.hasOwnProperty.bind(memoizedState);
1229
return (
1225
- memoizedState !== null &&
1226
- typeof memoizedState === 'object' &&
1227
- memoizedState.hasOwnProperty('tag') &&
1228
- memoizedState.hasOwnProperty('create') &&
1229
- memoizedState.hasOwnProperty('destroy') &&
1230
- memoizedState.hasOwnProperty('deps') &&
1231
- (memoizedState.deps === null || isArray(memoizedState.deps)) &&
1232
- memoizedState.hasOwnProperty('next')
1230
+ hasOwnProperty('create') &&
1231
+ hasOwnProperty('destroy') &&
1232
+ hasOwnProperty('deps') &&
1233
+ hasOwnProperty('next') &&
1234
+ hasOwnProperty('tag') &&
1235
+ (deps === null || isArray(deps))
1236
);
1237
}
1238