diff --git a/reflect_test.go b/reflect_test.go index a95263a..5b654e9 100644 --- a/reflect_test.go +++ b/reflect_test.go @@ -4,6 +4,7 @@ import ( "fmt" "math" "reflect" + "strings" "testing" ) @@ -843,3 +844,39 @@ func TestStructCallParameterConversion(t *testing.T) { } }) } + +type TestTextUnmarshallerCallParameterConversion_MyStruct struct{} + +func (m *TestTextUnmarshallerCallParameterConversion_MyStruct) UnmarshalText(b []byte) error { + if string(b) == "good" { + return nil + } + + return fmt.Errorf("NOT_GOOD: %s", string(b)) +} + +func TestTextUnmarshallerCallParameterConversion(t *testing.T) { + tt(t, func() { + test, vm := test() + + vm.Set("f", func(t TestTextUnmarshallerCallParameterConversion_MyStruct) bool { return true }) + + // success + test("f('good')", true) + + // explicit failure, should pass error message up + if _, err := vm.Run("f('bad')"); err == nil || !strings.Contains(err.Error(), "NOT_GOOD: bad") { + t.Fail() + } + + // wrong input + if _, err := vm.Run("f(null)"); err == nil { + t.Fail() + } + + // no input + if _, err := vm.Run("f()"); err == nil { + t.Fail() + } + }) +} diff --git a/runtime.go b/runtime.go index bacada2..2bf2cba 100644 --- a/runtime.go +++ b/runtime.go @@ -1,6 +1,7 @@ package otto import ( + "encoding" "errors" "fmt" "math" @@ -530,6 +531,20 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu return reflect.ValueOf(v.String()) } + if v.kind == valueString { + var s encoding.TextUnmarshaler + + if reflect.PtrTo(t).Implements(reflect.TypeOf(&s).Elem()) { + r := reflect.New(t) + + if err := r.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(v.string())); err != nil { + panic(self.panicSyntaxError("can't convert to %s: %s", t.String(), err.Error())) + } + + return r.Elem() + } + } + s := "OTTO DOES NOT UNDERSTAND THIS TYPE" switch v.kind { case valueBoolean: