perf: speed up Selection.Text by outlining recursion

Replace the recursive closure in Selection.Text with a helper method call.
This keeps behavior unchanged while reducing runtime overhead in the hot path.

Benchmark (BenchmarkText, benchstat, n=12):
- sec/op: 2.133us -> 1.692us (-20.70%, p=0.000)
- B/op: 504 -> 504 (no change)
- allocs/op: 6 -> 6 (no change)
This commit is contained in:
jvoisin
2026-05-27 21:12:36 +02:00
parent e2468fa06d
commit ece69fc2fd
+13 -15
View File
@@ -59,27 +59,25 @@ func (s *Selection) SetAttr(attrName, val string) *Selection {
// elements, including their descendants.
func (s *Selection) Text() string {
var builder strings.Builder
// Slightly optimized vs calling Each: no single selection object created
var f func(*html.Node)
f = func(n *html.Node) {
if n.Type == html.TextNode {
// Keep newlines and spaces, like jQuery
builder.WriteString(n.Data)
}
if n.FirstChild != nil {
for c := n.FirstChild; c != nil; c = c.NextSibling {
f(c)
}
}
}
for _, n := range s.Nodes {
f(n)
s.textHelper(n, &builder)
}
return builder.String()
}
func (s *Selection) textHelper(n *html.Node, builder *strings.Builder) {
if n.Type == html.TextNode {
// Keep newlines and spaces, like jQuery
builder.WriteString(n.Data)
}
if n.FirstChild != nil {
for c := n.FirstChild; c != nil; c = c.NextSibling {
s.textHelper(c, builder)
}
}
}
// Size is an alias for Length.
func (s *Selection) Size() int {
return s.Length()