diff --git a/internal/collections/syncmap.go b/internal/collections/syncmap.go index 9a020bc23e..c191430535 100644 --- a/internal/collections/syncmap.go +++ b/internal/collections/syncmap.go @@ -13,7 +13,7 @@ type SyncMap[K comparable, V any] struct { func (s *SyncMap[K, V]) Load(key K) (value V, ok bool) { val, ok := s.m.Load(key) - if !ok { + if !ok || val == nil { return value, ok } return val.(V), true @@ -25,6 +25,10 @@ func (s *SyncMap[K, V]) Store(key K, value V) { func (s *SyncMap[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) { actualAny, loaded := s.m.LoadOrStore(key, value) + if actualAny == nil { + return actual, loaded + } + return actualAny.(V), loaded } @@ -38,7 +42,17 @@ func (s *SyncMap[K, V]) Clear() { func (s *SyncMap[K, V]) Range(f func(key K, value V) bool) { s.m.Range(func(key, value any) bool { - return f(key.(K), value.(V)) + var k K + if key != nil { + k = key.(K) + } + + var v V + if value != nil { + v = value.(V) + } + + return f(k, v) }) } diff --git a/internal/collections/syncmap_test.go b/internal/collections/syncmap_test.go new file mode 100644 index 0000000000..5fe7c578f4 --- /dev/null +++ b/internal/collections/syncmap_test.go @@ -0,0 +1,32 @@ +package collections_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/collections" + "gotest.tools/v3/assert" +) + +func TestSyncMapWithNil(t *testing.T) { + t.Parallel() + + var m collections.SyncMap[string, any] + + got1, ok := m.Load("foo") + assert.Assert(t, !ok) + assert.Equal(t, got1, nil) + + m.Store("foo", nil) + + got2, ok := m.Load("foo") + assert.Assert(t, ok) + assert.Equal(t, got2, nil) + + too, loaded := m.LoadOrStore("too", nil) + assert.Assert(t, !loaded) + assert.Equal(t, too, nil) + + m.Range(func(k string, v any) bool { + return true + }) +}