Skip to content

Commit b15bf2b

Browse files
author
Brian Vaughn
authored
DevTools bugfix for useState() with hasOwnProperty key (#21524)
1 parent 343776f commit b15bf2b

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,36 @@ describe('ProfilerStore', () => {
135135
});
136136
}).toThrow('Cannot modify filter preferences while profiling');
137137
});
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+
});
138170
});

packages/react-devtools-shared/src/backend/renderer.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,15 +1221,18 @@ export function attach(
12211221
}
12221222

12231223
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);
12241229
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))
12331236
);
12341237
}
12351238

0 commit comments

Comments
 (0)