diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index 06ef854f..c9f67020 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -5479,28 +5479,30 @@ func TestReadClosure(t *testing.T) { accV := evalVariable(p, t, "acc") t.Log(api.ConvertVar(accV).MultilineString("", "")) if len(accV.Children) != 2 { - t.Error("wrong number of children") - } else { - found := 0 - for j := range accV.Children { - v := &accV.Children[j] - switch v.Name { - case "scale": - found++ - if val, _ := constant.Int64Val(v.Value); val != 3 { - t.Error("wrong value for scale") - } - case "a": - found++ - if val, _ := constant.Int64Val(v.Value); val != avalues[i] { - t.Errorf("wrong value for a: %d", val) - } + t.Fatal("wrong number of children") + } + found := 0 + for j := range accV.Children { + v := &accV.Children[j] + switch v.Name { + case "scale": + found++ + if val, _ := constant.Int64Val(v.Value); val != 3 { + t.Error("wrong value for scale") + } + case "a": + found++ + if val, _ := constant.Int64Val(v.Value); val != avalues[i] { + t.Errorf("wrong value for a: %d", val) } } - if found != 2 { - t.Error("wrong captured variables") - } } + if found != 2 { + t.Error("wrong captured variables") + } + + assertVariable(t, evalVariable(p, t, "acc.scale"), varTest{name: "acc.scale", preserveName: true, value: "3", varType: "int"}) + assertVariable(t, evalVariable(p, t, "acc.a"), varTest{name: "acc.a", preserveName: true, value: fmt.Sprintf("%d", avalues[i]), varType: "int"}) } }) } diff --git a/pkg/proc/variables.go b/pkg/proc/variables.go index 1c3c19fd..b9923cb0 100644 --- a/pkg/proc/variables.go +++ b/pkg/proc/variables.go @@ -1101,6 +1101,7 @@ func (v *Variable) structMember(memberName string) (*Variable, error) { } return nil, fmt.Errorf("%s has no member %s", vname, memberName) } + closure := false switch v.Kind { case reflect.Chan: v = v.clone() @@ -1110,6 +1111,19 @@ func (v *Variable) structMember(memberName string) (*Variable, error) { if len(v.Children) > 0 { v = &v.Children[0] } + case reflect.Func: + v.loadFunctionPtr(0, LoadConfig{MaxVariableRecurse: -1}) + if v.Unreadable != nil { + return nil, v.Unreadable + } + if v.closureAddr != 0 { + fn := v.bi.PCToFunc(v.Base) + if fn != nil { + cst := fn.extra(v.bi).closureStructType + v = v.newVariable(v.Name, v.closureAddr, cst, v.mem) + closure = true + } + } } queue := []*Variable{v} @@ -1136,6 +1150,13 @@ func (v *Variable) structMember(memberName string) (*Variable, error) { if field.Name == memberName { return structVar.toField(field) } + if len(queue) == 0 && field.Name == "&"+memberName && closure { + f, err := structVar.toField(field) + if err != nil { + return nil, err + } + return f.maybeDereference(), nil + } isEmbeddedStructMember := field.Embedded || (field.Type.Common().Name == field.Name) ||