github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/object_goslice_reflect.go (about) 1 package goja 2 3 import ( 4 "math" 5 "math/bits" 6 "reflect" 7 8 "github.com/nuvolaris/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 } 52 53 func (o *objectGoSliceReflect) shrink(size int) { 54 o.valueCache.shrink(size) 55 tail := o.fieldsValue.Slice(size, o.fieldsValue.Len()) 56 zero := reflect.Zero(o.fieldsValue.Type().Elem()) 57 for i := 0; i < tail.Len(); i++ { 58 tail.Index(i).Set(zero) 59 } 60 o.fieldsValue.SetLen(size) 61 } 62 63 func (o *objectGoSliceReflect) putLength(v uint32, throw bool) bool { 64 if bits.UintSize == 32 && v > math.MaxInt32 { 65 panic(rangeError("Integer value overflows 32-bit int")) 66 } 67 newLen := int(v) 68 curLen := o.fieldsValue.Len() 69 if newLen > curLen { 70 o.grow(newLen) 71 } else if newLen < curLen { 72 o.shrink(newLen) 73 } 74 return true 75 } 76 77 func (o *objectGoSliceReflect) setOwnStr(name unistring.String, val Value, throw bool) bool { 78 if name == "length" { 79 return o.putLength(o.val.runtime.toLengthUint32(val), throw) 80 } 81 return o.objectGoArrayReflect.setOwnStr(name, val, throw) 82 } 83 84 func (o *objectGoSliceReflect) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool { 85 if name == "length" { 86 return o.val.runtime.defineArrayLength(&o.lengthProp, descr, o.putLength, throw) 87 } 88 return o.objectGoArrayReflect.defineOwnPropertyStr(name, descr, throw) 89 }