fix: fix memory leaks in destroy methods#1023
Conversation
- Fix AbstractGraph.destroy() to iterate plugins Map correctly and set null container reference - Fix PanningHandler.onDestroy() to call panningManager.destroy() - Fix PanningManager.destroy() to call stop() to clear interval timer - Fix RubberBandHandler.onDestroy() to remove gestureHandler listener - Fix SelectionCellsHandler.onDestroy() to remove listener from selectionModel - Add EventSource.destroy() to clear eventListeners, call super.destroy() in children classes - Add destroy tests for all modified classes
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughAdds an explicit destruction propagation and listener cleanup path: new EventSource.destroy(), many destroy/onDestroy methods marked Changes
Sequence Diagram(s)sequenceDiagram
participant Caller as Destroy Caller
participant Instance as ComponentInstance
participant EventSrc as EventSource
participant Plugins as PluginsCollection
participant Super as BaseClass
Caller->>Instance: destroy()
Instance->>Instance: local cleanup (DOM refs, timers, managers)
Instance->>EventSrc: EventSource.destroy() (clears eventListeners)
Instance->>Plugins: plugins.forEach(p => p.onDestroy())
Instance->>Super: super.destroy()
Super->>Super: base cleanup
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/core/src/view/GraphView.ts (1)
2363-2401:⚠️ Potential issue | 🟡 MinorConsider moving
super.destroy()outside the conditional block.The
super.destroy()call is currently inside theif (root && root.parentNode)block. If this condition is false (e.g., the canvas is already detached or null), the base class cleanup won't execute and event listeners inEventSource.eventListenerswill remain, potentially causing memory leaks.Suggested fix
override destroy(): void { let root: SVGElement | HTMLElement | null = null; if (this.canvas && this.canvas instanceof SVGElement) { root = this.canvas.ownerSVGElement as SVGElement; } if (!root) { root = this.canvas; } if (root && root.parentNode) { this.clear(this.currentRoot, true); InternalEvent.removeGestureListeners( document, null, this.moveHandler, this.endHandler ); InternalEvent.release(this.graph.container); root.parentNode.removeChild(root); this.moveHandler = null; this.endHandler = null; // `@ts-expect-error` Can be null when destroyed. this.canvas = null; // `@ts-expect-error` Can be null when destroyed. this.backgroundPane = null; // `@ts-expect-error` Can be null when destroyed. this.drawPane = null; // `@ts-expect-error` Can be null when destroyed. this.overlayPane = null; // `@ts-expect-error` Can be null when destroyed. this.decoratorPane = null; - - super.destroy(); } + + super.destroy(); }
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9feb3b8e-62d2-4e78-90c4-f46b23b704d9
📒 Files selected for processing (8)
packages/core/__tests__/view/BaseGraph.test.tspackages/core/src/gui/MaxToolbar.tspackages/core/src/view/AbstractGraph.tspackages/core/src/view/GraphView.tspackages/core/src/view/cell/CellMarker.tspackages/core/src/view/event/EventSource.tspackages/core/src/view/layout/LayoutManager.tspackages/core/src/view/layout/SwimlaneManager.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/core/src/view/AbstractGraph.ts
|



PR Checklist
maxGraph, and you are assigned to the issue.packages/core/_tests_or a new or altered Storybook story inpackages/html/stories(an existing story may also demonstrate the change).Overview
Changes:
- Fix AbstractGraph.destroy() to iterate plugins Map correctly and set null container reference
- Fix PanningHandler.onDestroy() to call panningManager.destroy()
- Fix PanningManager.destroy() to call stop() to clear interval timer
- Fix RubberBandHandler.onDestroy() to remove gestureHandler listener
- Fix SelectionCellsHandler.onDestroy() to remove listener from selectionModel
- Add EventSource.destroy() to clear eventListeners, call super.destroy() in children classes
- Add destroy tests for all modified classes
Notes
The scope of this PR is wider than what is described in #994.
I did a systematic search on destroy methods and look for missing resources releasing.
Summary by CodeRabbit
Tests
Refactor