2015-02-16 05:28:33 -08:00
|
|
|
package otto
|
|
|
|
|
|
|
|
import (
|
|
|
|
"reflect"
|
|
|
|
"strconv"
|
|
|
|
)
|
|
|
|
|
|
|
|
func (runtime *_runtime) newGoArrayObject(value reflect.Value) *_object {
|
|
|
|
self := runtime.newObject()
|
|
|
|
self.class = "GoArray"
|
|
|
|
self.objectClass = _classGoArray
|
|
|
|
self.value = _newGoArrayObject(value)
|
|
|
|
return self
|
|
|
|
}
|
|
|
|
|
|
|
|
type _goArrayObject struct {
|
|
|
|
value reflect.Value
|
|
|
|
writable bool
|
|
|
|
propertyMode _propertyMode
|
|
|
|
}
|
|
|
|
|
|
|
|
func _newGoArrayObject(value reflect.Value) *_goArrayObject {
|
|
|
|
writable := value.Kind() == reflect.Ptr // The Array is addressable (like a Slice)
|
|
|
|
mode := _propertyMode(0010)
|
|
|
|
if writable {
|
|
|
|
mode = 0110
|
|
|
|
}
|
|
|
|
self := &_goArrayObject{
|
|
|
|
value: value,
|
|
|
|
writable: writable,
|
|
|
|
propertyMode: mode,
|
|
|
|
}
|
|
|
|
return self
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self _goArrayObject) getValue(index int64) (reflect.Value, bool) {
|
|
|
|
value := reflect.Indirect(self.value)
|
|
|
|
if index < int64(value.Len()) {
|
|
|
|
return value.Index(int(index)), true
|
|
|
|
}
|
|
|
|
return reflect.Value{}, false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self _goArrayObject) setValue(index int64, value Value) bool {
|
|
|
|
indexValue, exists := self.getValue(index)
|
|
|
|
if !exists {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
reflectValue, err := value.toReflectValue(reflect.Indirect(self.value).Type().Elem().Kind())
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
indexValue.Set(reflectValue)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func goArrayGetOwnProperty(self *_object, name string) *_property {
|
|
|
|
// length
|
|
|
|
if name == "length" {
|
|
|
|
return &_property{
|
|
|
|
value: toValue(reflect.Indirect(self.value.(*_goArrayObject).value).Len()),
|
|
|
|
mode: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// .0, .1, .2, ...
|
|
|
|
index := stringToArrayIndex(name)
|
|
|
|
if index >= 0 {
|
|
|
|
object := self.value.(*_goArrayObject)
|
2015-03-20 05:22:01 -07:00
|
|
|
value := Value{}
|
2015-02-16 05:28:33 -08:00
|
|
|
reflectValue, exists := object.getValue(index)
|
|
|
|
if exists {
|
|
|
|
value = self.runtime.toValue(reflectValue.Interface())
|
|
|
|
}
|
|
|
|
return &_property{
|
|
|
|
value: value,
|
|
|
|
mode: object.propertyMode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return objectGetOwnProperty(self, name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func goArrayEnumerate(self *_object, all bool, each func(string) bool) {
|
|
|
|
object := self.value.(*_goArrayObject)
|
|
|
|
// .0, .1, .2, ...
|
|
|
|
|
|
|
|
for index, length := 0, object.value.Len(); index < length; index++ {
|
|
|
|
name := strconv.FormatInt(int64(index), 10)
|
|
|
|
if !each(name) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
objectEnumerate(self, all, each)
|
|
|
|
}
|
|
|
|
|
|
|
|
func goArrayDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool {
|
|
|
|
if name == "length" {
|
2015-03-20 05:22:01 -07:00
|
|
|
return self.runtime.typeErrorResult(throw)
|
2015-02-16 05:28:33 -08:00
|
|
|
} else if index := stringToArrayIndex(name); index >= 0 {
|
|
|
|
object := self.value.(*_goArrayObject)
|
|
|
|
if object.writable {
|
|
|
|
if self.value.(*_goArrayObject).setValue(index, descriptor.value.(Value)) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
2015-03-20 05:22:01 -07:00
|
|
|
return self.runtime.typeErrorResult(throw)
|
2015-02-16 05:28:33 -08:00
|
|
|
}
|
|
|
|
return objectDefineOwnProperty(self, name, descriptor, throw)
|
|
|
|
}
|
|
|
|
|
|
|
|
func goArrayDelete(self *_object, name string, throw bool) bool {
|
|
|
|
// length
|
|
|
|
if name == "length" {
|
2015-03-20 05:22:01 -07:00
|
|
|
return self.runtime.typeErrorResult(throw)
|
2015-02-16 05:28:33 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// .0, .1, .2, ...
|
|
|
|
index := stringToArrayIndex(name)
|
|
|
|
if index >= 0 {
|
|
|
|
object := self.value.(*_goArrayObject)
|
|
|
|
if object.writable {
|
|
|
|
indexValue, exists := object.getValue(index)
|
|
|
|
if exists {
|
|
|
|
indexValue.Set(reflect.Zero(reflect.Indirect(object.value).Type().Elem()))
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
2015-03-20 05:22:01 -07:00
|
|
|
return self.runtime.typeErrorResult(throw)
|
2015-02-16 05:28:33 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return self.delete(name, throw)
|
|
|
|
}
|