array_sparse.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. package goja
  2. import (
  3. "math"
  4. "math/bits"
  5. "reflect"
  6. "sort"
  7. "strconv"
  8. )
  9. type sparseArrayItem struct {
  10. idx uint32
  11. value Value
  12. }
  13. type sparseArrayObject struct {
  14. baseObject
  15. items []sparseArrayItem
  16. length uint32
  17. propValueCount int
  18. lengthProp valueProperty
  19. }
  20. func (a *sparseArrayObject) init() {
  21. a.baseObject.init()
  22. a.lengthProp.writable = true
  23. a._put("length", &a.lengthProp)
  24. }
  25. func (a *sparseArrayObject) findIdx(idx uint32) int {
  26. return sort.Search(len(a.items), func(i int) bool {
  27. return a.items[i].idx >= idx
  28. })
  29. }
  30. func (a *sparseArrayObject) _setLengthInt(l int64, throw bool) bool {
  31. if l >= 0 && l <= math.MaxUint32 {
  32. ret := true
  33. l := uint32(l)
  34. if l <= a.length {
  35. if a.propValueCount > 0 {
  36. // Slow path
  37. for i := len(a.items) - 1; i >= 0; i-- {
  38. item := a.items[i]
  39. if item.idx <= l {
  40. break
  41. }
  42. if prop, ok := item.value.(*valueProperty); ok {
  43. if !prop.configurable {
  44. l = item.idx + 1
  45. ret = false
  46. break
  47. }
  48. a.propValueCount--
  49. }
  50. }
  51. }
  52. }
  53. idx := a.findIdx(l)
  54. aa := a.items[idx:]
  55. for i := range aa {
  56. aa[i].value = nil
  57. }
  58. a.items = a.items[:idx]
  59. a.length = l
  60. if !ret {
  61. a.val.runtime.typeErrorResult(throw, "Cannot redefine property: length")
  62. }
  63. return ret
  64. }
  65. panic(a.val.runtime.newError(a.val.runtime.global.RangeError, "Invalid array length"))
  66. }
  67. func (a *sparseArrayObject) setLengthInt(l int64, throw bool) bool {
  68. if l == int64(a.length) {
  69. return true
  70. }
  71. if !a.lengthProp.writable {
  72. a.val.runtime.typeErrorResult(throw, "length is not writable")
  73. return false
  74. }
  75. return a._setLengthInt(l, throw)
  76. }
  77. func (a *sparseArrayObject) setLength(v Value, throw bool) bool {
  78. l, ok := toIntIgnoreNegZero(v)
  79. if ok && l == int64(a.length) {
  80. return true
  81. }
  82. if !a.lengthProp.writable {
  83. a.val.runtime.typeErrorResult(throw, "length is not writable")
  84. return false
  85. }
  86. if ok {
  87. return a._setLengthInt(l, throw)
  88. }
  89. panic(a.val.runtime.newError(a.val.runtime.global.RangeError, "Invalid array length"))
  90. }
  91. func (a *sparseArrayObject) _getIdx(idx uint32) Value {
  92. i := a.findIdx(idx)
  93. if i < len(a.items) && a.items[i].idx == idx {
  94. return a.items[i].value
  95. }
  96. return nil
  97. }
  98. func (a *sparseArrayObject) getStr(name string, receiver Value) Value {
  99. return a.getStrWithOwnProp(a.getOwnPropStr(name), name, receiver)
  100. }
  101. func (a *sparseArrayObject) getIdx(idx valueInt, receiver Value) Value {
  102. prop := a.getOwnPropIdx(idx)
  103. if prop == nil {
  104. if a.prototype != nil {
  105. if receiver == nil {
  106. return a.prototype.self.getIdx(idx, a.val)
  107. }
  108. return a.prototype.self.getIdx(idx, receiver)
  109. }
  110. }
  111. if prop, ok := prop.(*valueProperty); ok {
  112. if receiver == nil {
  113. return prop.get(a.val)
  114. }
  115. return prop.get(receiver)
  116. }
  117. return prop
  118. }
  119. func (a *sparseArrayObject) getLengthProp() Value {
  120. a.lengthProp.value = intToValue(int64(a.length))
  121. return &a.lengthProp
  122. }
  123. func (a *sparseArrayObject) getOwnPropStr(name string) Value {
  124. if idx := strToIdx(name); idx != math.MaxUint32 {
  125. return a._getIdx(idx)
  126. }
  127. if name == "length" {
  128. return a.getLengthProp()
  129. }
  130. return a.baseObject.getOwnPropStr(name)
  131. }
  132. func (a *sparseArrayObject) getOwnPropIdx(idx valueInt) Value {
  133. if idx := toIdx(idx); idx != math.MaxUint32 {
  134. return a._getIdx(idx)
  135. }
  136. return a.baseObject.getOwnPropStr(idx.String())
  137. }
  138. func (a *sparseArrayObject) add(idx uint32, val Value) {
  139. i := a.findIdx(idx)
  140. a.items = append(a.items, sparseArrayItem{})
  141. copy(a.items[i+1:], a.items[i:])
  142. a.items[i] = sparseArrayItem{
  143. idx: idx,
  144. value: val,
  145. }
  146. }
  147. func (a *sparseArrayObject) _setOwnIdx(idx uint32, val Value, throw bool) bool {
  148. var prop Value
  149. i := a.findIdx(idx)
  150. if i < len(a.items) && a.items[i].idx == idx {
  151. prop = a.items[i].value
  152. }
  153. if prop == nil {
  154. if proto := a.prototype; proto != nil {
  155. // we know it's foreign because prototype loops are not allowed
  156. if res, ok := proto.self.setForeignIdx(valueInt(idx), val, a.val, throw); ok {
  157. return res
  158. }
  159. }
  160. // new property
  161. if !a.extensible {
  162. a.val.runtime.typeErrorResult(throw, "Cannot add property %d, object is not extensible", idx)
  163. return false
  164. }
  165. if idx >= a.length {
  166. if !a.setLengthInt(int64(idx)+1, throw) {
  167. return false
  168. }
  169. }
  170. if a.expand(idx) {
  171. a.items = append(a.items, sparseArrayItem{})
  172. copy(a.items[i+1:], a.items[i:])
  173. a.items[i] = sparseArrayItem{
  174. idx: idx,
  175. value: val,
  176. }
  177. } else {
  178. ar := a.val.self.(*arrayObject)
  179. ar.values[idx] = val
  180. ar.objCount++
  181. return true
  182. }
  183. } else {
  184. if prop, ok := prop.(*valueProperty); ok {
  185. if !prop.isWritable() {
  186. a.val.runtime.typeErrorResult(throw)
  187. return false
  188. }
  189. prop.set(a.val, val)
  190. } else {
  191. a.items[i].value = val
  192. }
  193. }
  194. return true
  195. }
  196. func (a *sparseArrayObject) setOwnStr(name string, val Value, throw bool) bool {
  197. if idx := strToIdx(name); idx != math.MaxUint32 {
  198. return a._setOwnIdx(idx, val, throw)
  199. } else {
  200. if name == "length" {
  201. return a.setLength(val, throw)
  202. } else {
  203. return a.baseObject.setOwnStr(name, val, throw)
  204. }
  205. }
  206. }
  207. func (a *sparseArrayObject) setOwnIdx(idx valueInt, val Value, throw bool) bool {
  208. if idx := toIdx(idx); idx != math.MaxUint32 {
  209. return a._setOwnIdx(idx, val, throw)
  210. }
  211. return a.baseObject.setOwnStr(idx.String(), val, throw)
  212. }
  213. func (a *sparseArrayObject) setForeignStr(name string, val, receiver Value, throw bool) (bool, bool) {
  214. return a._setForeignStr(name, a.getOwnPropStr(name), val, receiver, throw)
  215. }
  216. func (a *sparseArrayObject) setForeignIdx(name valueInt, val, receiver Value, throw bool) (bool, bool) {
  217. return a._setForeignIdx(name, a.getOwnPropIdx(name), val, receiver, throw)
  218. }
  219. type sparseArrayPropIter struct {
  220. a *sparseArrayObject
  221. idx int
  222. }
  223. func (i *sparseArrayPropIter) next() (propIterItem, iterNextFunc) {
  224. for i.idx < len(i.a.items) {
  225. name := strconv.Itoa(int(i.a.items[i.idx].idx))
  226. prop := i.a.items[i.idx].value
  227. i.idx++
  228. if prop != nil {
  229. return propIterItem{name: name, value: prop}, i.next
  230. }
  231. }
  232. return i.a.baseObject.enumerateUnfiltered()()
  233. }
  234. func (a *sparseArrayObject) enumerateUnfiltered() iterNextFunc {
  235. return (&sparseArrayPropIter{
  236. a: a,
  237. }).next
  238. }
  239. func (a *sparseArrayObject) ownKeys(all bool, accum []Value) []Value {
  240. if all {
  241. for _, item := range a.items {
  242. accum = append(accum, asciiString(strconv.FormatUint(uint64(item.idx), 10)))
  243. }
  244. } else {
  245. for _, item := range a.items {
  246. if prop, ok := item.value.(*valueProperty); ok && !prop.enumerable {
  247. continue
  248. }
  249. accum = append(accum, asciiString(strconv.FormatUint(uint64(item.idx), 10)))
  250. }
  251. }
  252. return a.baseObject.ownKeys(all, accum)
  253. }
  254. func (a *sparseArrayObject) setValues(values []Value, objCount int) {
  255. a.items = make([]sparseArrayItem, 0, objCount)
  256. for i, val := range values {
  257. if val != nil {
  258. a.items = append(a.items, sparseArrayItem{
  259. idx: uint32(i),
  260. value: val,
  261. })
  262. }
  263. }
  264. }
  265. func (a *sparseArrayObject) hasOwnPropertyStr(name string) bool {
  266. if idx := strToIdx(name); idx != math.MaxUint32 {
  267. i := a.findIdx(idx)
  268. return i < len(a.items) && a.items[i].idx == idx
  269. } else {
  270. return a.baseObject.hasOwnPropertyStr(name)
  271. }
  272. }
  273. func (a *sparseArrayObject) hasOwnPropertyIdx(idx valueInt) bool {
  274. if idx := toIdx(idx); idx != math.MaxUint32 {
  275. i := a.findIdx(idx)
  276. return i < len(a.items) && a.items[i].idx == idx
  277. }
  278. return a.baseObject.hasOwnPropertyStr(idx.String())
  279. }
  280. func (a *sparseArrayObject) expand(idx uint32) bool {
  281. if l := len(a.items); l >= 1024 {
  282. if ii := a.items[l-1].idx; ii > idx {
  283. idx = ii
  284. }
  285. if (bits.UintSize == 64 || idx < math.MaxInt32) && int(idx)>>3 < l {
  286. //log.Println("Switching sparse->standard")
  287. ar := &arrayObject{
  288. baseObject: a.baseObject,
  289. length: a.length,
  290. propValueCount: a.propValueCount,
  291. }
  292. ar.setValuesFromSparse(a.items, int(idx))
  293. ar.val.self = ar
  294. ar.init()
  295. ar.lengthProp.writable = a.lengthProp.writable
  296. return false
  297. }
  298. }
  299. return true
  300. }
  301. func (a *sparseArrayObject) _defineIdxProperty(idx uint32, desc PropertyDescriptor, throw bool) bool {
  302. var existing Value
  303. i := a.findIdx(idx)
  304. if i < len(a.items) && a.items[i].idx == idx {
  305. existing = a.items[i].value
  306. }
  307. prop, ok := a.baseObject._defineOwnProperty(strconv.FormatUint(uint64(idx), 10), existing, desc, throw)
  308. if ok {
  309. if idx >= a.length {
  310. if !a.setLengthInt(int64(idx)+1, throw) {
  311. return false
  312. }
  313. }
  314. if i >= len(a.items) || a.items[i].idx != idx {
  315. if a.expand(idx) {
  316. a.items = append(a.items, sparseArrayItem{})
  317. copy(a.items[i+1:], a.items[i:])
  318. a.items[i] = sparseArrayItem{
  319. idx: idx,
  320. value: prop,
  321. }
  322. if idx >= a.length {
  323. a.length = idx + 1
  324. }
  325. } else {
  326. a.val.self.(*arrayObject).values[idx] = prop
  327. }
  328. } else {
  329. a.items[i].value = prop
  330. }
  331. if _, ok := prop.(*valueProperty); ok {
  332. a.propValueCount++
  333. }
  334. }
  335. return ok
  336. }
  337. func (a *sparseArrayObject) defineOwnPropertyStr(name string, descr PropertyDescriptor, throw bool) bool {
  338. if idx := strToIdx(name); idx != math.MaxUint32 {
  339. return a._defineIdxProperty(idx, descr, throw)
  340. }
  341. if name == "length" {
  342. return a.val.runtime.defineArrayLength(&a.lengthProp, descr, a.setLength, throw)
  343. }
  344. return a.baseObject.defineOwnPropertyStr(name, descr, throw)
  345. }
  346. func (a *sparseArrayObject) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
  347. if idx := toIdx(idx); idx != math.MaxUint32 {
  348. return a._defineIdxProperty(idx, descr, throw)
  349. }
  350. return a.baseObject.defineOwnPropertyStr(idx.String(), descr, throw)
  351. }
  352. func (a *sparseArrayObject) _deleteIdxProp(idx uint32, throw bool) bool {
  353. i := a.findIdx(idx)
  354. if i < len(a.items) && a.items[i].idx == idx {
  355. if p, ok := a.items[i].value.(*valueProperty); ok {
  356. if !p.configurable {
  357. a.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of %s", idx, a.val.toString())
  358. return false
  359. }
  360. a.propValueCount--
  361. }
  362. copy(a.items[i:], a.items[i+1:])
  363. a.items[len(a.items)-1].value = nil
  364. a.items = a.items[:len(a.items)-1]
  365. }
  366. return true
  367. }
  368. func (a *sparseArrayObject) deleteStr(name string, throw bool) bool {
  369. if idx := strToIdx(name); idx != math.MaxUint32 {
  370. return a._deleteIdxProp(idx, throw)
  371. }
  372. return a.baseObject.deleteStr(name, throw)
  373. }
  374. func (a *sparseArrayObject) deleteIdx(idx valueInt, throw bool) bool {
  375. if idx := toIdx(idx); idx != math.MaxUint32 {
  376. return a._deleteIdxProp(idx, throw)
  377. }
  378. return a.baseObject.deleteStr(idx.String(), throw)
  379. }
  380. func (a *sparseArrayObject) sortLen() int64 {
  381. if len(a.items) > 0 {
  382. return int64(a.items[len(a.items)-1].idx) + 1
  383. }
  384. return 0
  385. }
  386. func (a *sparseArrayObject) export() interface{} {
  387. arr := make([]interface{}, a.length)
  388. for _, item := range a.items {
  389. if item.value != nil {
  390. arr[item.idx] = item.value.Export()
  391. }
  392. }
  393. return arr
  394. }
  395. func (a *sparseArrayObject) exportType() reflect.Type {
  396. return reflectTypeArray
  397. }