Skip to content

Commit c4f7fa4

Browse files
fix: dispose old buffers in BufferSet.Reset() to prevent marker leaks
BufferSet.Reset() created new Buffer instances without disposing the old ones, leaving markers and their event listeners on the old CircularList alive. This adds Buffer.Dispose() and calls it from BufferSet.Reset() and BufferSet.Dispose() before replacing or releasing buffers. Fixes #24 Co-authored-by: Ona <no-reply@ona.com>
1 parent 116150c commit c4f7fa4

4 files changed

Lines changed: 78 additions & 1 deletion

File tree

buffer.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,11 @@ func (b *Buffer) ClearAllMarkers() {
574574
b.isClearing = false
575575
}
576576

577+
// Dispose cleans up the buffer by disposing all markers and their event listeners.
578+
func (b *Buffer) Dispose() {
579+
b.ClearAllMarkers()
580+
}
581+
577582
// AddMarker creates a marker at the given line and registers it for
578583
// automatic adjustment on trim/insert/delete events.
579584
func (b *Buffer) AddMarker(y int) *Marker {

buffer_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,23 @@ func TestBufferClearAllMarkers(t *testing.T) {
438438
}
439439
}
440440

441+
func TestBufferDispose(t *testing.T) {
442+
t.Parallel()
443+
type Expectation struct {
444+
MarkerCount int
445+
MarkerDisposed bool
446+
}
447+
b := NewBuffer(defaultBufferOpts())
448+
b.FillViewportRows(nil)
449+
m := b.AddMarker(3)
450+
b.Dispose()
451+
got := Expectation{MarkerCount: len(b.Markers), MarkerDisposed: m.IsDisposed}
452+
expected := Expectation{MarkerCount: 0, MarkerDisposed: true}
453+
if diff := cmp.Diff(expected, got); diff != "" {
454+
t.Errorf("(-want +got):\n%s", diff)
455+
}
456+
}
457+
441458
func TestBufferGetNullCell(t *testing.T) {
442459
t.Parallel()
443460
type Expectation struct {

bufferset.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,14 @@ func NewBufferSet(cols, rows, scrollback, tabStopWidth int) *BufferSet {
3535
}
3636

3737
// Reset recreates both buffers and activates the normal buffer.
38+
// Old buffers are disposed to clean up markers and event listeners.
3839
func (bs *BufferSet) Reset() {
40+
if bs.normal != nil {
41+
bs.normal.Dispose()
42+
}
43+
if bs.alt != nil {
44+
bs.alt.Dispose()
45+
}
3946
bs.normal = NewBuffer(BufferOptions{
4047
Cols: bs.cols,
4148
Rows: bs.rows,
@@ -119,7 +126,13 @@ func (bs *BufferSet) SetupTabStops(startCol int) {
119126
bs.alt.SetupTabStops(startCol)
120127
}
121128

122-
// Dispose cleans up event emitters.
129+
// Dispose cleans up buffers and event emitters.
123130
func (bs *BufferSet) Dispose() {
131+
if bs.normal != nil {
132+
bs.normal.Dispose()
133+
}
134+
if bs.alt != nil {
135+
bs.alt.Dispose()
136+
}
124137
bs.OnBufferActivateEmitter.Dispose()
125138
}

bufferset_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,48 @@ func TestBufferSetReset(t *testing.T) {
141141
}
142142
}
143143

144+
func TestBufferSetResetDisposesOldMarkers(t *testing.T) {
145+
t.Parallel()
146+
type Expectation struct {
147+
NormalMarkerDisposed bool
148+
AltMarkerDisposed bool
149+
NewNormalMarkerCount int
150+
}
151+
bs := NewBufferSet(80, 24, 1000, 8)
152+
normalMarker := bs.Normal().AddMarker(0)
153+
bs.ActivateAltBuffer(nil)
154+
altMarker := bs.Alt().AddMarker(0)
155+
bs.Reset()
156+
got := Expectation{
157+
NormalMarkerDisposed: normalMarker.IsDisposed,
158+
AltMarkerDisposed: altMarker.IsDisposed,
159+
NewNormalMarkerCount: len(bs.Normal().Markers),
160+
}
161+
expected := Expectation{
162+
NormalMarkerDisposed: true,
163+
AltMarkerDisposed: true,
164+
NewNormalMarkerCount: 0,
165+
}
166+
if diff := cmp.Diff(expected, got); diff != "" {
167+
t.Errorf("(-want +got):\n%s", diff)
168+
}
169+
}
170+
171+
func TestBufferSetDisposeDisposesBufferMarkers(t *testing.T) {
172+
t.Parallel()
173+
type Expectation struct {
174+
MarkerDisposed bool
175+
}
176+
bs := NewBufferSet(80, 24, 1000, 8)
177+
marker := bs.Normal().AddMarker(0)
178+
bs.Dispose()
179+
got := Expectation{MarkerDisposed: marker.IsDisposed}
180+
expected := Expectation{MarkerDisposed: true}
181+
if diff := cmp.Diff(expected, got); diff != "" {
182+
t.Errorf("(-want +got):\n%s", diff)
183+
}
184+
}
185+
144186
func TestBufferSetResize(t *testing.T) {
145187
t.Parallel()
146188
type Expectation struct {

0 commit comments

Comments
 (0)