1
0
mirror of https://github.com/robertkrimen/otto synced 2025-10-12 20:27:30 +08:00

Fix that we were using a non-runtime toValue method with go_array, go_map, and go_struct

This will fix #13
This commit is contained in:
Robert Krimen 2013-04-30 00:15:24 +02:00
parent b477d8eaed
commit 149f94f9fb
4 changed files with 85 additions and 14 deletions

View File

@ -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",
)
}

View File

@ -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,

View File

@ -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
}
}

View File

@ -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
}
}