From 149f94f9fb6a3510f1d714d31242b17c0e62803d Mon Sep 17 00:00:00 2001 From: Robert Krimen Date: Tue, 30 Apr 2013 00:15:24 +0200 Subject: [PATCH] Fix that we were using a non-runtime toValue method with go_array, go_map, and go_struct This will fix #13 --- bug_test.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++ type_go_array.go | 12 ++++++---- type_go_map.go | 12 ++++++---- type_go_struct.go | 16 ++++++++----- 4 files changed, 85 insertions(+), 14 deletions(-) diff --git a/bug_test.go b/bug_test.go index c87f2a0..bc57983 100644 --- a/bug_test.go +++ b/bug_test.go @@ -21,3 +21,62 @@ func Test_issue5(t *testing.T) { test(`'abc' === 'def'`, "false") test(`'\t' === '\r'`, "false") } + +func Test_issue13(t *testing.T) { + Terst(t) + + otto, test := runTestWithOtto() + value, err := otto.ToValue(map[string]interface{}{ + "string": "Xyzzy", + "number": 42, + "array": []string{"def", "ghi"}, + }) + if err != nil { + FailNow(err) + } + fn, err := otto.Object(` + (function(value){ + return ""+[value.string, value.number, value.array] + }) + `) + if err != nil { + FailNow(err) + } + result, err := fn.Value().Call(fn.Value(), value) + if err != nil { + FailNow(err) + } + Is(result.toString(), "Xyzzy,42,def,ghi") + + anything := struct { + Abc interface{} + }{ + Abc: map[string]interface{}{ + "def": []interface{}{ + []interface{}{ + "a", "b", "c", "", "d", "e", + }, + map[string]interface{}{ + "jkl": "Nothing happens.", + }, + }, + "ghi": -1, + }, + } + otto.Set("anything", anything) + test(` + [ + anything, + "~", + anything.Abc, + "~", + anything.Abc.def, + "~", + anything.Abc.def[1].jkl, + "~", + anything.Abc.ghi, + ]; + `, "[object Object],~,[object Object],~,a,b,c,,d,e,[object Object],~,Nothing happens.,~,-1", + ) + +} diff --git a/type_go_array.go b/type_go_array.go index 7d17686..69e7b5c 100644 --- a/type_go_array.go +++ b/type_go_array.go @@ -8,7 +8,7 @@ import ( func (runtime *_runtime) newGoArrayObject(value reflect.Value) *_object { self := runtime.newObject() self.class = "Array" // TODO Should this be something else? - self.stash = newGoArrayStash(value, self.stash) + self.stash = newGoArrayStash(value, self.stash, runtime) return self } @@ -17,9 +17,12 @@ type _goArrayStash struct { writable bool propertyMode _propertyMode _stash + // We pass the runtime to the stash to it can do deep + // value promotion + runtime *_runtime } -func newGoArrayStash(value reflect.Value, stash _stash) *_goArrayStash { +func newGoArrayStash(value reflect.Value, stash _stash, runtime *_runtime) *_goArrayStash { propertyMode := _propertyMode(0111) writable := true switch value.Kind() { @@ -37,6 +40,7 @@ func newGoArrayStash(value reflect.Value, stash _stash) *_goArrayStash { writable: writable, propertyMode: propertyMode, _stash: stash, + runtime: runtime, } return self } @@ -91,7 +95,7 @@ func (self *_goArrayStash) get(name string) Value { if !exists { return UndefinedValue() } - return toValue(value) + return self.runtime.toValue(value.Interface()) } return self._stash.get(name) @@ -113,7 +117,7 @@ func (self *_goArrayStash) property(name string) *_property { value := UndefinedValue() reflectValue, exists := self.getValue(int(index)) if exists { - value = toValue(reflectValue) + value = self.runtime.toValue(reflectValue.Interface()) } return &_property{ value: value, diff --git a/type_go_map.go b/type_go_map.go index 39a8f30..808a949 100644 --- a/type_go_map.go +++ b/type_go_map.go @@ -7,7 +7,7 @@ import ( func (runtime *_runtime) newGoMapObject(value reflect.Value) *_object { self := runtime.newObject() self.class = "Object" // TODO Should this be something else? - self.stash = newGoMapStash(value, self.stash) + self.stash = newGoMapStash(value, self.stash, runtime) return self } @@ -16,9 +16,12 @@ type _goMapStash struct { keyKind reflect.Kind valueKind reflect.Kind _stash + // We pass the runtime to the stash to it can do deep + // value promotion + runtime *_runtime } -func newGoMapStash(value reflect.Value, stash _stash) *_goMapStash { +func newGoMapStash(value reflect.Value, stash _stash, runtime *_runtime) *_goMapStash { if value.Kind() != reflect.Map { dbgf("%/panic//%@: %v != reflect.Map", value.Kind()) } @@ -27,6 +30,7 @@ func newGoMapStash(value reflect.Value, stash _stash) *_goMapStash { keyKind: value.Type().Key().Kind(), valueKind: value.Type().Elem().Kind(), _stash: stash, + runtime: runtime, } return self } @@ -60,7 +64,7 @@ func (self *_goMapStash) test(name string) bool { func (self *_goMapStash) get(name string) Value { value := self.value.MapIndex(self.toKey(name)) if value.IsValid() { - return toValue(value) + return self.runtime.toValue(value.Interface()) } return UndefinedValue() @@ -70,7 +74,7 @@ func (self *_goMapStash) property(name string) *_property { value := self.value.MapIndex(self.toKey(name)) if value.IsValid() { return &_property{ - toValue(value), + self.runtime.toValue(value.Interface()), 0111, // +Write +Enumerate +Configure } } diff --git a/type_go_struct.go b/type_go_struct.go index d58b5b8..a4e59fa 100644 --- a/type_go_struct.go +++ b/type_go_struct.go @@ -7,22 +7,26 @@ import ( func (runtime *_runtime) newGoStructObject(value reflect.Value) *_object { self := runtime.newObject() self.class = "Object" // TODO Should this be something else? - self.stash = newGoStructStash(value, self.stash) + self.stash = newGoStructStash(value, self.stash, runtime) return self } type _goStructStash struct { value reflect.Value _stash + // We pass the runtime to the stash to it can do deep + // value promotion + runtime *_runtime } -func newGoStructStash(value reflect.Value, stash _stash) *_goStructStash { +func newGoStructStash(value reflect.Value, stash _stash, runtime *_runtime) *_goStructStash { if value.Kind() != reflect.Struct { dbgf("%/panic//%@: %v != reflect.Struct", value.Kind()) } self := &_goStructStash{ - value: value, - _stash: stash, + value: value, + _stash: stash, + runtime: runtime, } return self } @@ -62,7 +66,7 @@ func (self *_goStructStash) test(name string) bool { func (self *_goStructStash) get(name string) Value { value := self.getValue(name) if value.IsValid() { - return toValue(value) + return self.runtime.toValue(value.Interface()) } return self._stash.get(name) @@ -72,7 +76,7 @@ func (self *_goStructStash) property(name string) *_property { value := self.getValue(name) if value.IsValid() { return &_property{ - toValue(value), + self.runtime.toValue(value.Interface()), 0111, // +Write +Enumerate +Configure } }