Skip to content

Commit 42be89d

Browse files
committed
delete element if render fails
1 parent 97445de commit 42be89d

2 files changed

Lines changed: 31 additions & 2 deletions

File tree

ui/requestwriter.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@ type RequestWriter struct {
1212
io.Writer
1313
}
1414

15-
func (rqw RequestWriter) UI(ui core.UI, params ...any) error {
16-
return rqw.NewElement(ui).JawsRender(rqw, params)
15+
func (rqw RequestWriter) UI(ui core.UI, params ...any) (err error) {
16+
elem := rqw.NewElement(ui)
17+
if err = elem.JawsRender(rqw, params); err != nil {
18+
rqw.DeleteElement(elem)
19+
}
20+
return
1721
}
1822

1923
func (rqw RequestWriter) Write(p []byte) (n int, err error) {

ui/requestwriter_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package ui
33
import (
44
"bytes"
55
"errors"
6+
"html/template"
67
"net/http"
78
"net/http/httptest"
89
"strings"
@@ -20,6 +21,14 @@ func (u *testRWUpdater) JawsUpdate(*core.Element) {
2021
u.called++
2122
}
2223

24+
type requestWriterFailGetter struct {
25+
err error
26+
}
27+
28+
func (g requestWriterFailGetter) JawsGetHTML(*core.Element) template.HTML { return "x" }
29+
func (g requestWriterFailGetter) JawsGetTag(*core.Request) any { return g }
30+
func (g requestWriterFailGetter) JawsInit(*core.Element) error { return g.err }
31+
2332
func newSessionBoundRequest(t *testing.T) (*core.Jaws, *core.Request) {
2433
t.Helper()
2534
jw, err := core.New()
@@ -143,3 +152,19 @@ func TestErrMissingTemplateAndRWLocker(t *testing.T) {
143152
t.Fatal("expected errors.Is match")
144153
}
145154
}
155+
156+
func TestRequestWriterUI_RenderErrorDoesNotLeakElement(t *testing.T) {
157+
core.NextJid = 0
158+
_, rq := newRequest(t)
159+
var buf bytes.Buffer
160+
rw := RequestWriter{Request: rq, Writer: &buf}
161+
162+
renderErr := errors.New("render failed")
163+
if err := rw.UI(NewA(requestWriterFailGetter{err: renderErr})); !errors.Is(err, renderErr) {
164+
t.Fatalf("want %v got %v", renderErr, err)
165+
}
166+
167+
if leaked := rq.GetElementByJid(1); leaked != nil {
168+
t.Fatalf("expected failed render element to be removed from request registry: %v", leaked.Jid())
169+
}
170+
}

0 commit comments

Comments
 (0)