From 2acae8741688ec29fff74118ffa0d0347ae8fc4d Mon Sep 17 00:00:00 2001 From: Richard Musiol Date: Thu, 5 Jul 2018 19:55:08 +0200 Subject: [PATCH] syscall/js: improve panic messages This commit adds the actual type to the panic message when calling a method of Value on a Value with a bad type. It also adds better panic messages to Value.Invoke and Value.Call. Change-Id: Ic4b3aa29d3bef8e357be40cd07664ad602ffab12 Reviewed-on: https://go-review.googlesource.com/122376 Reviewed-by: Brad Fitzpatrick Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- src/syscall/js/js.go | 35 ++++++++++++++++++++++++++++++----- src/syscall/js/js_test.go | 6 ++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/syscall/js/js.go b/src/syscall/js/js.go index cc7907a928..0cc98bd52c 100644 --- a/src/syscall/js/js.go +++ b/src/syscall/js/js.go @@ -257,6 +257,12 @@ func valueLength(v ref) int func (v Value) Call(m string, args ...interface{}) Value { res, ok := valueCall(v.ref, m, makeArgs(args)) if !ok { + if vType := v.Type(); vType != TypeObject && vType != TypeFunction { // check here to avoid overhead in success case + panic(&ValueError{"Value.Call", vType}) + } + if propType := v.Get(m).Type(); propType != TypeFunction { + panic("syscall/js: Value.Call: property " + m + " is not a function, got " + propType.String()) + } panic(Error{makeValue(res)}) } return makeValue(res) @@ -269,6 +275,9 @@ func valueCall(v ref, m string, args []ref) (ref, bool) func (v Value) Invoke(args ...interface{}) Value { res, ok := valueInvoke(v.ref, makeArgs(args)) if !ok { + if vType := v.Type(); vType != TypeFunction { // check here to avoid overhead in success case + panic(&ValueError{"Value.Invoke", vType}) + } panic(Error{makeValue(res)}) } return makeValue(res) @@ -292,17 +301,21 @@ func (v Value) isNumber() bool { return v.ref>>32&nanHead != nanHead || v.ref == valueNaN.ref } -// Float returns the value v as a float64. It panics if v is not a JavaScript number. -func (v Value) Float() float64 { +func (v Value) float(method string) float64 { if !v.isNumber() { - panic("syscall/js: not a number") + panic(&ValueError{method, v.Type()}) } return *(*float64)(unsafe.Pointer(&v.ref)) } +// Float returns the value v as a float64. It panics if v is not a JavaScript number. +func (v Value) Float() float64 { + return v.float("Value.Float") +} + // Int returns the value v truncated to an int. It panics if v is not a JavaScript number. func (v Value) Int() int { - return int(v.Float()) + return int(v.float("Value.Int")) } // Bool returns the value v as a bool. It panics if v is not a JavaScript boolean. @@ -313,7 +326,7 @@ func (v Value) Bool() bool { case valueFalse.ref: return false default: - panic("syscall/js: not a boolean") + panic(&ValueError{"Value.Bool", v.Type()}) } } @@ -335,3 +348,15 @@ func (v Value) InstanceOf(t Value) bool { } func valueInstanceOf(v ref, t ref) bool + +// A ValueError occurs when a Value method is invoked on +// a Value that does not support it. Such cases are documented +// in the description of each method. +type ValueError struct { + Method string + Type Type +} + +func (e *ValueError) Error() string { + return "syscall/js: call of " + e.Method + " on " + e.Type.String() +} diff --git a/src/syscall/js/js_test.go b/src/syscall/js/js_test.go index d47afe1da7..753e262d52 100644 --- a/src/syscall/js/js_test.go +++ b/src/syscall/js/js_test.go @@ -53,6 +53,12 @@ func TestString(t *testing.T) { if dummys.Get("someString") != dummys.Get("someString") { t.Errorf("same value not equal") } + + wantInt := "42" + o = dummys.Get("someInt") + if got := o.String(); got != wantInt { + t.Errorf("got %#v, want %#v", got, wantInt) + } } func TestInt(t *testing.T) { -- 2.50.0