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

Merge pull request #6 from stevenh/array-types

Export arrays to common type if possible
This commit is contained in:
Steven Hartland 2015-02-19 11:08:22 +00:00
commit 9cb5e6bc30
2 changed files with 64 additions and 3 deletions

View File

@ -523,6 +523,46 @@ func Test_reflectArray(t *testing.T) {
is(abc[len(abc)-1], true) is(abc[len(abc)-1], true)
} }
// no common type
{
test(`
abc = [1, 2.2, "str"];
abc;
`, "1,2.2,str")
val, err := vm.Get("abc")
is(err, nil)
abc, err := val.Export()
is(err, nil)
is(abc, []interface{}{int64(1), 2.2, "str"})
}
// common type int
{
test(`
abc = [1, 2, 3];
abc;
`, "1,2,3")
val, err := vm.Get("abc")
is(err, nil)
abc, err := val.Export()
is(err, nil)
is(abc, []int64{1, 2, 3})
}
// common type string
{
test(`
abc = ["str1", "str2", "str3"];
abc;
`, "str1,str2,str3")
val, err := vm.Get("abc")
is(err, nil)
abc, err := val.Export()
is(err, nil)
is(abc, []string{"str1", "str2", "str3"})
}
}) })
} }

View File

@ -680,15 +680,36 @@ func (self Value) export() interface{} {
result := make([]interface{}, 0) result := make([]interface{}, 0)
lengthValue := object.get("length") lengthValue := object.get("length")
length := lengthValue.value.(uint32) length := lengthValue.value.(uint32)
kind := reflect.Invalid
state := 0
var t reflect.Type
for index := uint32(0); index < length; index += 1 { for index := uint32(0); index < length; index += 1 {
name := strconv.FormatInt(int64(index), 10) name := strconv.FormatInt(int64(index), 10)
if !object.hasProperty(name) { if !object.hasProperty(name) {
continue continue
} }
value := object.get(name) value := object.get(name).export()
result = append(result, value.export()) t = reflect.TypeOf(value)
if state == 0 {
kind = t.Kind()
state = 1
} else if state == 1 && kind != t.Kind() {
state = 2
}
result = append(result, value)
} }
return result
if state != 1 || kind == reflect.Interface {
// No common type
return result
}
// Convert to the common type
val := reflect.MakeSlice(reflect.SliceOf(t), len(result), len(result))
for i, v := range result {
val.Index(i).Set(reflect.ValueOf(v))
}
return val.Interface()
} else { } else {
result := make(map[string]interface{}) result := make(map[string]interface{})
// TODO Should we export everything? Or just what is enumerable? // TODO Should we export everything? Or just what is enumerable?