diff --git a/browser_test.go b/browser_test.go index 968347d4..c0173004 100644 --- a/browser_test.go +++ b/browser_test.go @@ -268,8 +268,12 @@ func TestTestTry(t *testing.T) { var errVal *rod.ErrTry g.True(errors.As(err, &errVal)) g.Is(err, &rod.ErrTry{}) + g.Eq(errVal.Unwrap().Error(), "1") g.Eq(1, errVal.Value) - g.Eq(errVal.Error(), "error value: 1") + g.Has(errVal.Error(), "error value: 1\ngoroutine") + + errVal = rod.Try(func() { panic(errors.New("t")) }).(*rod.ErrTry) + g.Eq(errVal.Unwrap().Error(), "t") } func TestBrowserOthers(t *testing.T) { diff --git a/error.go b/error.go index bdb3c6ea..2c35555c 100644 --- a/error.go +++ b/error.go @@ -12,10 +12,11 @@ import ( // ErrTry error type ErrTry struct { Value interface{} + Stack string } func (e *ErrTry) Error() string { - return fmt.Sprintf("error value: %#v", e.Value) + return fmt.Sprintf("error value: %#v\n%s", e.Value, e.Stack) } // Is interface @@ -23,6 +24,14 @@ func (e *ErrTry) Is(err error) bool { return reflect.TypeOf(e) == reflect.TypeOf(err) } +// Unwrap stdlib interface +func (e *ErrTry) Unwrap() error { + if err, ok := e.Value.(error); ok { + return err + } + return fmt.Errorf("%v", e.Value) +} + // ErrExpectElement error type ErrExpectElement struct { *proto.RuntimeRemoteObject diff --git a/utils.go b/utils.go index 65547e85..66291f7a 100644 --- a/utils.go +++ b/utils.go @@ -13,6 +13,7 @@ import ( "path/filepath" "reflect" "regexp" + "runtime/debug" "sync" "time" @@ -204,15 +205,11 @@ func (sr *StreamReader) Close() error { return proto.IOClose{Handle: sr.handle}.Call(sr.c) } -// Try try fn with recover, return the panic as value +// Try try fn with recover, return the panic as rod.ErrTry func Try(fn func()) (err error) { defer func() { if val := recover(); val != nil { - var ok bool - err, ok = val.(error) - if !ok { - err = &ErrTry{val} - } + err = &ErrTry{val, string(debug.Stack())} } }()