diff --git a/context.go b/context.go index 1554f9c..0ef7d71 100644 --- a/context.go +++ b/context.go @@ -1,5 +1,7 @@ package html +import "reflect" + // Translator provides Text() lookups for a rendering context. // Usage example: ctx := NewContextWithService(myTranslator) // @@ -92,13 +94,22 @@ func cloneContext(ctx *Context) *Context { } clone := *ctx + // Preserve the shared Data/Metadata alias when callers pointed both fields + // at the same map. + if sameMetadataMap(ctx.Data, ctx.Metadata) { + shared := cloneMetadataMap(ctx.Data) + clone.Data = shared + clone.Metadata = shared + return &clone + } + clone.Data = cloneMetadataMap(ctx.Data) clone.Metadata = cloneMetadataMap(ctx.Metadata) return &clone } func cloneMetadataMap(src map[string]any) map[string]any { - if len(src) == 0 { + if src == nil { return nil } @@ -108,3 +119,11 @@ func cloneMetadataMap(src map[string]any) map[string]any { } return dst } + +func sameMetadataMap(a, b map[string]any) bool { + if a == nil || b == nil { + return a == nil && b == nil + } + + return reflect.ValueOf(a).Pointer() == reflect.ValueOf(b).Pointer() +} diff --git a/context_test.go b/context_test.go index bd02baf..69e93bb 100644 --- a/context_test.go +++ b/context_test.go @@ -134,3 +134,25 @@ func TestContext_SetLocale_NilContext_Ugly(t *testing.T) { t.Fatal("SetLocale on nil context should return nil") } } + +func TestCloneContext_PreservesMetadataAlias_Good(t *testing.T) { + ctx := NewContext() + ctx.Data["count"] = 3 + + clone := cloneContext(ctx) + if clone == nil { + t.Fatal("cloneContext returned nil") + } + if clone.Data == nil || clone.Metadata == nil { + t.Fatal("cloneContext should preserve non-nil metadata maps") + } + + dataPtr := reflect.ValueOf(clone.Data).Pointer() + metadataPtr := reflect.ValueOf(clone.Metadata).Pointer() + if dataPtr != metadataPtr { + t.Fatalf("cloneContext should keep Data and Metadata aliased, got %x and %x", dataPtr, metadataPtr) + } + if clone.Data["count"] != 3 || clone.Metadata["count"] != 3 { + t.Fatalf("cloneContext should copy map contents, got Data=%v Metadata=%v", clone.Data, clone.Metadata) + } +}