From 036536b9f7cf7de2829f5945d9caa4cb0304dba4 Mon Sep 17 00:00:00 2001 From: haoqixu Date: Tue, 11 Nov 2025 19:48:01 +0800 Subject: [PATCH 1/2] fix syncmap panic on nil --- internal/collections/syncmap.go | 18 +++++++++++++++-- internal/collections/syncmap_test.go | 30 ++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 internal/collections/syncmap_test.go 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..3202c12d53 --- /dev/null +++ b/internal/collections/syncmap_test.go @@ -0,0 +1,30 @@ +package collections_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/collections" + "gotest.tools/v3/assert" +) + +func TestSyncMapWithNil(t *testing.T) { + 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 + }) +} From 0f9609554fa87ef47bef3f5e1c3523d79b99ec5e Mon Sep 17 00:00:00 2001 From: haoqixu Date: Tue, 11 Nov 2025 20:01:17 +0800 Subject: [PATCH 2/2] fix lint --- internal/collections/syncmap_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/collections/syncmap_test.go b/internal/collections/syncmap_test.go index 3202c12d53..5fe7c578f4 100644 --- a/internal/collections/syncmap_test.go +++ b/internal/collections/syncmap_test.go @@ -8,6 +8,8 @@ import ( ) func TestSyncMapWithNil(t *testing.T) { + t.Parallel() + var m collections.SyncMap[string, any] got1, ok := m.Load("foo")