Skip to content

Commit 053a13e

Browse files
committed
Fix memory leak hotspots (#5116)
- render: clear the root Fragment's props.children after commit so replaced vnode generations are not retained - unmount: clear component._globalContext with the other component references (cherry picked from commit bd0302d)
1 parent c427a83 commit 053a13e

3 files changed

Lines changed: 28 additions & 1 deletion

File tree

src/diff/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ export function unmount(vnode, parentVNode, skipRemove) {
717717
}
718718
}
719719

720-
r._parentDom = NULL;
720+
r._parentDom = r._globalContext = NULL;
721721
}
722722

723723
if ((r = vnode._children)) {

src/render.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ export function render(vnode, parentDom) {
5656

5757
// Flush all queued effects
5858
commitRoot(commitQueue, parentDom._children, refQueue);
59+
60+
// The live children are tracked on _children after diffing.
61+
parentDom._children.props.children = NULL;
5962
}
6063

6164
/**

test/browser/render.test.jsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,30 @@ describe('render()', () => {
227227
expect(scratch.innerHTML).to.equal('<span class="hello">Hello!</span>');
228228
});
229229

230+
it('should not keep the root input vnode in props.children', () => {
231+
let update;
232+
class App extends Component {
233+
constructor(props) {
234+
super(props);
235+
this.state = { value: 'a' };
236+
update = this.setState.bind(this);
237+
}
238+
239+
render() {
240+
return <button>{this.state.value}</button>;
241+
}
242+
}
243+
244+
render(<App />, scratch);
245+
let firstAppVNode = scratch._children._children[0];
246+
247+
update({ value: 'b' });
248+
rerender();
249+
250+
expect(scratch._children._children[0]).to.not.equal(firstAppVNode);
251+
expect(scratch._children.props.children).to.equal(null);
252+
});
253+
230254
it('should nest empty nodes', () => {
231255
render(
232256
<div>

0 commit comments

Comments
 (0)