array_sparse.go 11 KB

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