go.ketch.com/lib/goja@v0.0.1/object_goslice_reflect.go (about) 1 package goja 2 3 import ( 4 "math" 5 "math/bits" 6 "reflect" 7 8 "go.ketch.com/lib/goja/unistring" 9 ) 10 11 type objectGoSliceReflect struct { 12 objectGoArrayReflect 13 } 14 15 func (o *objectGoSliceReflect) init() { 16 o.objectGoArrayReflect._init() 17 o.lengthProp.writable = true 18 o.putIdx = o._putIdx 19 } 20 21 func (o *objectGoSliceReflect) _putIdx(idx int, v Value, throw bool) bool { 22 if idx >= o.fieldsValue.Len() { 23 o.grow(idx + 1) 24 } 25 return o.objectGoArrayReflect._putIdx(idx, v, throw) 26 } 27 28 func (o *objectGoSliceReflect) grow(size int) { 29 oldcap := o.fieldsValue.Cap() 30 if oldcap < size { 31 n := reflect.MakeSlice(o.fieldsValue.Type(), size, growCap(size, o.fieldsValue.Len(), oldcap)) 32 reflect.Copy(n, o.fieldsValue) 33 o.fieldsValue.Set(n) 34 l := len(o.valueCache) 35 if l > size { 36 l = size 37 } 38 for i, w := range o.valueCache[:l] { 39 if w != nil { 40 w.setReflectValue(o.fieldsValue.Index(i)) 41 } 42 } 43 } else { 44 tail := o.fieldsValue.Slice(o.fieldsValue.Len(), size) 45 zero := reflect.Zero(o.fieldsValue.Type().Elem()) 46 for i := 0; i < tail.Len(); i++ { 47 tail.Index(i).Set(zero) 48 } 49 o.fieldsValue.SetLen(size) 50 } 51 o.updateLen() 52 } 53 54 func (o *objectGoSliceReflect) shrink(size int) { 55 o.valueCache.shrink(size) 56 tail := o.fieldsValue.Slice(size, o.fieldsValue.Len()) 57 zero := reflect.Zero(o.fieldsValue.Type().Elem()) 58 for i := 0; i < tail.Len(); i++ { 59 tail.Index(i).Set(zero) 60 } 61 o.fieldsValue.SetLen(size) 62 o.updateLen() 63 } 64 65 func (o *objectGoSliceReflect) putLength(v uint32, throw bool) bool { 66 if bits.UintSize == 32 && v > math.MaxInt32 { 67 panic(rangeError("Integer value overflows 32-bit int")) 68 } 69 newLen := int(v) 70 curLen := o.fieldsValue.Len() 71 if newLen > curLen { 72 o.grow(newLen) 73 } else if newLen < curLen { 74 o.shrink(newLen) 75 } 76 return true 77 } 78 79 func (o *objectGoSliceReflect) setOwnStr(name unistring.String, val Value, throw bool) bool { 80 if name == "length" { 81 return o.putLength(o.val.runtime.toLengthUint32(val), throw) 82 } 83 return o.objectGoArrayReflect.setOwnStr(name, val, throw) 84 } 85 86 func (o *objectGoSliceReflect) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool { 87 if name == "length" { 88 return o.val.runtime.defineArrayLength(&o.lengthProp, descr, o.putLength, throw) 89 } 90 return o.objectGoArrayReflect.defineOwnPropertyStr(name, descr, throw) 91 }