object_goslice_reflect.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. package goja
  2. import (
  3. "math"
  4. "math/bits"
  5. "reflect"
  6. "strconv"
  7. "github.com/dop251/goja/unistring"
  8. )
  9. type objectGoSliceReflect struct {
  10. objectGoReflect
  11. lengthProp valueProperty
  12. }
  13. func (o *objectGoSliceReflect) init() {
  14. o.objectGoReflect.init()
  15. o.class = classArray
  16. o.prototype = o.val.runtime.global.ArrayPrototype
  17. if !o.value.CanSet() {
  18. value := reflect.Indirect(reflect.New(o.value.Type()))
  19. value.Set(o.value)
  20. o.value = value
  21. }
  22. o.lengthProp.writable = true
  23. o.updateLen()
  24. o.baseObject._put("length", &o.lengthProp)
  25. }
  26. func (o *objectGoSliceReflect) updateLen() {
  27. o.lengthProp.value = intToValue(int64(o.value.Len()))
  28. }
  29. func (o *objectGoSliceReflect) _hasIdx(idx valueInt) bool {
  30. if idx := int64(idx); idx >= 0 && idx < int64(o.value.Len()) {
  31. return true
  32. }
  33. return false
  34. }
  35. func (o *objectGoSliceReflect) _hasStr(name unistring.String) bool {
  36. if idx := strToIdx64(name); idx >= 0 && idx < int64(o.value.Len()) {
  37. return true
  38. }
  39. return false
  40. }
  41. func (o *objectGoSliceReflect) _getIdx(idx int) Value {
  42. v := o.value.Index(idx)
  43. if (v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface) && v.IsNil() {
  44. return _null
  45. }
  46. return o.val.runtime.ToValue(v.Interface())
  47. }
  48. func (o *objectGoSliceReflect) getIdx(idx valueInt, receiver Value) Value {
  49. if idx := toIntStrict(int64(idx)); idx >= 0 && idx < o.value.Len() {
  50. return o._getIdx(idx)
  51. }
  52. return o.objectGoReflect.getStr(idx.string(), receiver)
  53. }
  54. func (o *objectGoSliceReflect) getStr(name unistring.String, receiver Value) Value {
  55. var ownProp Value
  56. if idx := strToGoIdx(name); idx >= 0 && idx < o.value.Len() {
  57. ownProp = o._getIdx(idx)
  58. } else if name == "length" {
  59. ownProp = &o.lengthProp
  60. } else {
  61. ownProp = o.objectGoReflect.getOwnPropStr(name)
  62. }
  63. return o.getStrWithOwnProp(ownProp, name, receiver)
  64. }
  65. func (o *objectGoSliceReflect) getOwnPropStr(name unistring.String) Value {
  66. if idx := strToGoIdx(name); idx >= 0 {
  67. if idx < o.value.Len() {
  68. return &valueProperty{
  69. value: o._getIdx(idx),
  70. writable: true,
  71. enumerable: true,
  72. }
  73. }
  74. return nil
  75. }
  76. if name == "length" {
  77. return &o.lengthProp
  78. }
  79. return o.objectGoReflect.getOwnPropStr(name)
  80. }
  81. func (o *objectGoSliceReflect) getOwnPropIdx(idx valueInt) Value {
  82. if idx := toIntStrict(int64(idx)); idx >= 0 && idx < o.value.Len() {
  83. return &valueProperty{
  84. value: o._getIdx(idx),
  85. writable: true,
  86. enumerable: true,
  87. }
  88. }
  89. return nil
  90. }
  91. func (o *objectGoSliceReflect) putIdx(idx int, v Value, throw bool) bool {
  92. if idx >= o.value.Len() {
  93. o.grow(idx + 1)
  94. }
  95. err := o.val.runtime.toReflectValue(v, o.value.Index(idx), &objectExportCtx{})
  96. if err != nil {
  97. o.val.runtime.typeErrorResult(throw, "Go type conversion error: %v", err)
  98. return false
  99. }
  100. return true
  101. }
  102. func (o *objectGoSliceReflect) grow(size int) {
  103. oldcap := o.value.Cap()
  104. if oldcap < size {
  105. n := reflect.MakeSlice(o.value.Type(), size, growCap(size, o.value.Len(), oldcap))
  106. reflect.Copy(n, o.value)
  107. o.value.Set(n)
  108. } else {
  109. tail := o.value.Slice(o.value.Len(), size)
  110. zero := reflect.Zero(o.value.Type().Elem())
  111. for i := 0; i < tail.Len(); i++ {
  112. tail.Index(i).Set(zero)
  113. }
  114. o.value.SetLen(size)
  115. }
  116. o.updateLen()
  117. }
  118. func (o *objectGoSliceReflect) shrink(size int) {
  119. tail := o.value.Slice(size, o.value.Len())
  120. zero := reflect.Zero(o.value.Type().Elem())
  121. for i := 0; i < tail.Len(); i++ {
  122. tail.Index(i).Set(zero)
  123. }
  124. o.value.SetLen(size)
  125. o.updateLen()
  126. }
  127. func (o *objectGoSliceReflect) putLength(v uint32, throw bool) bool {
  128. if bits.UintSize == 32 && v > math.MaxInt32 {
  129. panic(rangeError("Integer value overflows 32-bit int"))
  130. }
  131. newLen := int(v)
  132. curLen := o.value.Len()
  133. if newLen > curLen {
  134. o.grow(newLen)
  135. } else if newLen < curLen {
  136. o.shrink(newLen)
  137. }
  138. return true
  139. }
  140. func (o *objectGoSliceReflect) setOwnIdx(idx valueInt, val Value, throw bool) bool {
  141. if i := toIntStrict(int64(idx)); i >= 0 {
  142. if i >= o.value.Len() {
  143. if res, ok := o._setForeignIdx(idx, nil, val, o.val, throw); ok {
  144. return res
  145. }
  146. }
  147. o.putIdx(i, val, throw)
  148. } else {
  149. name := idx.string()
  150. if res, ok := o._setForeignStr(name, nil, val, o.val, throw); !ok {
  151. o.val.runtime.typeErrorResult(throw, "Can't set property '%s' on Go slice", name)
  152. return false
  153. } else {
  154. return res
  155. }
  156. }
  157. return true
  158. }
  159. func (o *objectGoSliceReflect) setOwnStr(name unistring.String, val Value, throw bool) bool {
  160. if idx := strToGoIdx(name); idx >= 0 {
  161. if idx >= o.value.Len() {
  162. if res, ok := o._setForeignStr(name, nil, val, o.val, throw); ok {
  163. return res
  164. }
  165. }
  166. o.putIdx(idx, val, throw)
  167. } else {
  168. if name == "length" {
  169. return o.putLength(o.val.runtime.toLengthUint32(val), throw)
  170. }
  171. if res, ok := o._setForeignStr(name, nil, val, o.val, throw); !ok {
  172. o.val.runtime.typeErrorResult(throw, "Can't set property '%s' on Go slice", name)
  173. return false
  174. } else {
  175. return res
  176. }
  177. }
  178. return true
  179. }
  180. func (o *objectGoSliceReflect) setForeignIdx(idx valueInt, val, receiver Value, throw bool) (bool, bool) {
  181. return o._setForeignIdx(idx, trueValIfPresent(o._hasIdx(idx)), val, receiver, throw)
  182. }
  183. func (o *objectGoSliceReflect) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
  184. return o._setForeignStr(name, trueValIfPresent(o.hasOwnPropertyStr(name)), val, receiver, throw)
  185. }
  186. func (o *objectGoSliceReflect) hasOwnPropertyIdx(idx valueInt) bool {
  187. return o._hasIdx(idx)
  188. }
  189. func (o *objectGoSliceReflect) hasOwnPropertyStr(name unistring.String) bool {
  190. if o._hasStr(name) || name == "length" {
  191. return true
  192. }
  193. return o.objectGoReflect._has(name.String())
  194. }
  195. func (o *objectGoSliceReflect) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
  196. if i := toIntStrict(int64(idx)); i >= 0 {
  197. if !o.val.runtime.checkHostObjectPropertyDescr(idx.string(), descr, throw) {
  198. return false
  199. }
  200. val := descr.Value
  201. if val == nil {
  202. val = _undefined
  203. }
  204. o.putIdx(i, val, throw)
  205. return true
  206. }
  207. o.val.runtime.typeErrorResult(throw, "Cannot define property '%d' on a Go slice", idx)
  208. return false
  209. }
  210. func (o *objectGoSliceReflect) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
  211. if idx := strToGoIdx(name); idx >= 0 {
  212. if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) {
  213. return false
  214. }
  215. val := descr.Value
  216. if val == nil {
  217. val = _undefined
  218. }
  219. o.putIdx(idx, val, throw)
  220. return true
  221. }
  222. if name == "length" {
  223. return o.val.runtime.defineArrayLength(&o.lengthProp, descr, o.putLength, throw)
  224. }
  225. o.val.runtime.typeErrorResult(throw, "Cannot define property '%s' on a Go slice", name)
  226. return false
  227. }
  228. func (o *objectGoSliceReflect) toPrimitiveNumber() Value {
  229. return o.toPrimitiveString()
  230. }
  231. func (o *objectGoSliceReflect) toPrimitiveString() Value {
  232. return o.val.runtime.arrayproto_join(FunctionCall{
  233. This: o.val,
  234. })
  235. }
  236. func (o *objectGoSliceReflect) toPrimitive() Value {
  237. return o.toPrimitiveString()
  238. }
  239. func (o *objectGoSliceReflect) _deleteIdx(idx int) {
  240. if idx < o.value.Len() {
  241. o.value.Index(idx).Set(reflect.Zero(o.value.Type().Elem()))
  242. }
  243. }
  244. func (o *objectGoSliceReflect) deleteStr(name unistring.String, throw bool) bool {
  245. if idx := strToGoIdx(name); idx >= 0 {
  246. o._deleteIdx(idx)
  247. return true
  248. }
  249. return o.objectGoReflect.deleteStr(name, throw)
  250. }
  251. func (o *objectGoSliceReflect) deleteIdx(i valueInt, throw bool) bool {
  252. idx := toIntStrict(int64(i))
  253. if idx >= 0 {
  254. o._deleteIdx(idx)
  255. }
  256. return true
  257. }
  258. type gosliceReflectPropIter struct {
  259. o *objectGoSliceReflect
  260. idx, limit int
  261. }
  262. func (i *gosliceReflectPropIter) next() (propIterItem, iterNextFunc) {
  263. if i.idx < i.limit && i.idx < i.o.value.Len() {
  264. name := strconv.Itoa(i.idx)
  265. i.idx++
  266. return propIterItem{name: asciiString(name), enumerable: _ENUM_TRUE}, i.next
  267. }
  268. return i.o.objectGoReflect.iterateStringKeys()()
  269. }
  270. func (o *objectGoSliceReflect) stringKeys(all bool, accum []Value) []Value {
  271. for i := 0; i < o.value.Len(); i++ {
  272. accum = append(accum, asciiString(strconv.Itoa(i)))
  273. }
  274. return o.objectGoReflect.stringKeys(all, accum)
  275. }
  276. func (o *objectGoSliceReflect) iterateStringKeys() iterNextFunc {
  277. return (&gosliceReflectPropIter{
  278. o: o,
  279. limit: o.value.Len(),
  280. }).next
  281. }
  282. func (o *objectGoSliceReflect) equal(other objectImpl) bool {
  283. if other, ok := other.(*objectGoSliceReflect); ok {
  284. return o.value.Interface() == other.value.Interface()
  285. }
  286. return false
  287. }
  288. func (o *objectGoSliceReflect) sortLen() int64 {
  289. return int64(o.value.Len())
  290. }
  291. func (o *objectGoSliceReflect) sortGet(i int64) Value {
  292. return o.getIdx(valueInt(i), nil)
  293. }
  294. func (o *objectGoSliceReflect) swap(i, j int64) {
  295. ii := valueInt(i)
  296. jj := valueInt(j)
  297. x := o.getIdx(ii, nil)
  298. y := o.getIdx(jj, nil)
  299. o.setOwnIdx(ii, y, false)
  300. o.setOwnIdx(jj, x, false)
  301. }