fix: preserve context map aliasing
This commit is contained in:
parent
fb13048db2
commit
bfecee9685
2 changed files with 42 additions and 1 deletions
21
context.go
21
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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue