fix: deterministic attributes and thread-safe nested layouts
Sort attribute keys for deterministic HTML output (I-1). Clone nested layouts before mutating path in Render (I-3), preventing data races when the same tree is rendered concurrently. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
7e484aba8b
commit
40da0d8b1d
2 changed files with 14 additions and 4 deletions
|
|
@ -100,9 +100,12 @@ func (l *Layout) Render(ctx *Context) string {
|
|||
b.WriteString(`">`)
|
||||
|
||||
for _, child := range children {
|
||||
// Propagate path to nested layouts.
|
||||
// Clone nested layouts before setting path (thread-safe).
|
||||
if inner, ok := child.(*Layout); ok {
|
||||
inner.path = bid + "-"
|
||||
clone := *inner
|
||||
clone.path = bid + "-"
|
||||
b.WriteString(clone.Render(ctx))
|
||||
continue
|
||||
}
|
||||
b.WriteString(child.Render(ctx))
|
||||
}
|
||||
|
|
|
|||
11
node.go
11
node.go
|
|
@ -1,6 +1,7 @@
|
|||
package html
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
i18n "forge.lthn.ai/core/go-i18n"
|
||||
|
|
@ -76,11 +77,17 @@ func (n *elNode) Render(ctx *Context) string {
|
|||
b.WriteByte('<')
|
||||
b.WriteString(n.tag)
|
||||
|
||||
for key, val := range n.attrs {
|
||||
// Sort attribute keys for deterministic output.
|
||||
keys := make([]string, 0, len(n.attrs))
|
||||
for k := range n.attrs {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, key := range keys {
|
||||
b.WriteByte(' ')
|
||||
b.WriteString(key)
|
||||
b.WriteString(`="`)
|
||||
b.WriteString(escapeAttr(val))
|
||||
b.WriteString(escapeAttr(n.attrs[key]))
|
||||
b.WriteByte('"')
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue