textinput: prevent data race from debounce function

Protect access to fields in textinput. Concurrent access can happen in
the main event loop and the completion debounce function.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
Tim Culverhouse 2022-09-25 14:38:48 -05:00 committed by Robin Jarry
parent 978768bff6
commit 4c3565653a

View file

@ -3,6 +3,7 @@ package ui
import ( import (
"math" "math"
"strings" "strings"
"sync"
"time" "time"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
@ -17,6 +18,7 @@ import (
type TextInput struct { type TextInput struct {
Invalidatable Invalidatable
sync.Mutex
cells int cells int
ctx *Context ctx *Context
focus bool focus bool
@ -294,7 +296,9 @@ func (ti *TextInput) updateCompletions() {
if ti.completeDebouncer == nil { if ti.completeDebouncer == nil {
ti.completeDebouncer = time.AfterFunc(ti.completeDelay, func() { ti.completeDebouncer = time.AfterFunc(ti.completeDelay, func() {
defer logging.PanicHandler() defer logging.PanicHandler()
ti.Lock()
ti.showCompletions() ti.showCompletions()
ti.Unlock()
}) })
} else { } else {
ti.completeDebouncer.Stop() ti.completeDebouncer.Stop()
@ -321,6 +325,8 @@ func (ti *TextInput) OnFocusLost(onFocusLost func(ti *TextInput)) {
} }
func (ti *TextInput) Event(event tcell.Event) bool { func (ti *TextInput) Event(event tcell.Event) bool {
ti.Lock()
defer ti.Unlock()
if event, ok := event.(*tcell.EventKey); ok { if event, ok := event.(*tcell.EventKey); ok {
switch event.Key() { switch event.Key() {
case tcell.KeyBackspace, tcell.KeyBackspace2: case tcell.KeyBackspace, tcell.KeyBackspace2: