Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion lib/ui/jsvar.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,14 @@ type JsVar[T any] struct {
dirtyTag any // current dirty tag, set during render; read via JawsGetTag
}

// JawsGetPath returns the value at jsPath, logging lookup errors on elem when possible.
// JawsGetPath returns the value at jsPath.
//
// A path containing only empty components returns the same logical root value
// as [JsVar.JawsGet]. Lookup errors are logged on elem when possible.
func (jsvar *JsVar[T]) JawsGetPath(elem *jaws.Element, jsPath string) (value any) {
if strings.Trim(jsPath, ".") == "" {
return jsvar.JawsGet(elem)
}
value, err := jsvar.getPath(jsPath)
if elem != nil {
_ = elem.Jaws.Log(err)
Expand Down
41 changes: 41 additions & 0 deletions lib/ui/jsvar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,44 @@ func TestJsVar_RenderSetAndEvent(t *testing.T) {
}
}

func TestJsVar_GetPathRootReturnsLogicalValue(t *testing.T) {
value := jsVarNilData{Value: "bound"}
tests := []struct {
name string
ptr *jsVarNilData
}{
{name: "Bound", ptr: &value},
{name: "Nil"},
}
paths := []string{"", ".", "..", "..."}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
jsvar := NewJsVar(new(sync.Mutex), tt.ptr)
want := jsvar.JawsGet(nil)
for _, jsPath := range paths {
t.Run(fmt.Sprintf("path_%q", jsPath), func(t *testing.T) {
gotValue := jsvar.JawsGetPath(nil, jsPath)
got, ok := gotValue.(jsVarNilData)
if !ok {
t.Fatalf("JawsGetPath(%q) returned %T, want jsVarNilData", jsPath, gotValue)
}
if got != want {
t.Fatalf("JawsGetPath(%q) = %#v, want JawsGet result %#v", jsPath, got, want)
}
})
}
if tt.ptr != nil {
if got := jsvar.JawsGetPath(nil, "..value.."); got != want.Value {
t.Fatalf("nested JawsGetPath = %#v, want %q", got, want.Value)
}
} else if got := jsvar.JawsGetPath(nil, "value"); got != nil {
t.Fatalf("nested JawsGetPath with nil Ptr = %#v, want nil", got)
}
})
}
}

func TestJsVar_RenderInitialHTMLAttrRunsOutsideBindingLock(t *testing.T) {
_, rq := newCoreRequest(t)

Expand Down Expand Up @@ -381,6 +419,9 @@ func testJsVarGetPathLoggerReentry(t *testing.T, bindingLocker jsVarTryLocker) {
if got := jsvar.JawsGetPath(elem, "text"); got != state.Text {
t.Fatalf("successful JawsGetPath = %#v, want %q", got, state.Text)
}
if got := jsvar.JawsGetPath(elem, "."); got != state {
t.Fatalf("successful root JawsGetPath = %#v, want %#v", got, state)
}
testSyncLogger(t, jw)
select {
case result := <-logger.results:
Expand Down
Loading