array.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. package goja
  2. import (
  3. "math"
  4. "reflect"
  5. "strconv"
  6. )
  7. type arrayObject struct {
  8. baseObject
  9. values []Value
  10. length int64
  11. objCount int64
  12. propValueCount int
  13. lengthProp valueProperty
  14. }
  15. func (a *arrayObject) init() {
  16. a.baseObject.init()
  17. a.lengthProp.writable = true
  18. a._put("length", &a.lengthProp)
  19. }
  20. func (a *arrayObject) getLength() Value {
  21. return intToValue(a.length)
  22. }
  23. func (a *arrayObject) _setLengthInt(l int64, throw bool) bool {
  24. if l >= 0 && l <= math.MaxUint32 {
  25. ret := true
  26. if l <= a.length {
  27. if a.propValueCount > 0 {
  28. // Slow path
  29. var s int64
  30. if a.length < int64(len(a.values)) {
  31. s = a.length - 1
  32. } else {
  33. s = int64(len(a.values)) - 1
  34. }
  35. for i := s; i >= l; i-- {
  36. if prop, ok := a.values[i].(*valueProperty); ok {
  37. if !prop.configurable {
  38. l = i + 1
  39. ret = false
  40. break
  41. }
  42. a.propValueCount--
  43. }
  44. }
  45. }
  46. }
  47. if l <= int64(len(a.values)) {
  48. if l >= 16 && l < int64(cap(a.values))>>2 {
  49. ar := make([]Value, l)
  50. copy(ar, a.values)
  51. a.values = ar
  52. } else {
  53. ar := a.values[l:len(a.values)]
  54. for i, _ := range ar {
  55. ar[i] = nil
  56. }
  57. a.values = a.values[:l]
  58. }
  59. }
  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 *arrayObject) setLengthInt(l int64, throw bool) bool {
  69. if l == 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 *arrayObject) setLength(v Value, throw bool) bool {
  79. l, ok := toIntIgnoreNegZero(v)
  80. if ok && l == 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 *arrayObject) getIdx(idx int64, origNameStr string, origName Value) (v Value) {
  93. if idx >= 0 && idx < int64(len(a.values)) {
  94. v = a.values[idx]
  95. }
  96. if v == nil && a.prototype != nil {
  97. if origName != nil {
  98. v = a.prototype.self.getProp(origName)
  99. } else {
  100. v = a.prototype.self.getPropStr(origNameStr)
  101. }
  102. }
  103. return
  104. }
  105. func (a *arrayObject) sortLen() int64 {
  106. return int64(len(a.values))
  107. }
  108. func (a *arrayObject) sortGet(i int64) Value {
  109. v := a.values[i]
  110. if p, ok := v.(*valueProperty); ok {
  111. v = p.get(a.val)
  112. }
  113. return v
  114. }
  115. func (a *arrayObject) swap(i, j int64) {
  116. a.values[i], a.values[j] = a.values[j], a.values[i]
  117. }
  118. func toIdx(v Value) (idx int64) {
  119. idx = -1
  120. if idxVal, ok1 := v.(valueInt); ok1 {
  121. idx = int64(idxVal)
  122. } else {
  123. if i, err := strconv.ParseInt(v.String(), 10, 64); err == nil {
  124. idx = i
  125. }
  126. }
  127. if idx >= 0 && idx < math.MaxUint32 {
  128. return
  129. }
  130. return -1
  131. }
  132. func strToIdx(s string) (idx int64) {
  133. idx = -1
  134. if i, err := strconv.ParseInt(s, 10, 64); err == nil {
  135. idx = i
  136. }
  137. if idx >= 0 && idx < math.MaxUint32 {
  138. return
  139. }
  140. return -1
  141. }
  142. func (a *arrayObject) getProp(n Value) Value {
  143. if idx := toIdx(n); idx >= 0 {
  144. return a.getIdx(idx, "", n)
  145. }
  146. if n.String() == "length" {
  147. return a.getLengthProp()
  148. }
  149. return a.baseObject.getProp(n)
  150. }
  151. func (a *arrayObject) getLengthProp() Value {
  152. a.lengthProp.value = intToValue(a.length)
  153. return &a.lengthProp
  154. }
  155. func (a *arrayObject) getPropStr(name string) Value {
  156. if i := strToIdx(name); i >= 0 {
  157. return a.getIdx(i, name, nil)
  158. }
  159. if name == "length" {
  160. return a.getLengthProp()
  161. }
  162. return a.baseObject.getPropStr(name)
  163. }
  164. func (a *arrayObject) getOwnProp(name string) Value {
  165. if i := strToIdx(name); i >= 0 {
  166. if i >= 0 && i < int64(len(a.values)) {
  167. return a.values[i]
  168. }
  169. }
  170. if name == "length" {
  171. return a.getLengthProp()
  172. }
  173. return a.baseObject.getOwnProp(name)
  174. }
  175. func (a *arrayObject) putIdx(idx int64, val Value, throw bool, origNameStr string, origName Value) {
  176. var prop Value
  177. if idx < int64(len(a.values)) {
  178. prop = a.values[idx]
  179. }
  180. if prop == nil {
  181. if a.prototype != nil {
  182. var pprop Value
  183. if origName != nil {
  184. pprop = a.prototype.self.getProp(origName)
  185. } else {
  186. pprop = a.prototype.self.getPropStr(origNameStr)
  187. }
  188. if pprop, ok := pprop.(*valueProperty); ok {
  189. if !pprop.isWritable() {
  190. a.val.runtime.typeErrorResult(throw)
  191. return
  192. }
  193. if pprop.accessor {
  194. pprop.set(a.val, val)
  195. return
  196. }
  197. }
  198. }
  199. if !a.extensible {
  200. a.val.runtime.typeErrorResult(throw)
  201. return
  202. }
  203. if idx >= a.length {
  204. if !a.setLengthInt(idx+1, throw) {
  205. return
  206. }
  207. }
  208. if idx >= int64(len(a.values)) {
  209. if !a.expand(idx) {
  210. a.val.self.(*sparseArrayObject).putIdx(idx, val, throw, origNameStr, origName)
  211. return
  212. }
  213. }
  214. } else {
  215. if prop, ok := prop.(*valueProperty); ok {
  216. if !prop.isWritable() {
  217. a.val.runtime.typeErrorResult(throw)
  218. return
  219. }
  220. prop.set(a.val, val)
  221. return
  222. }
  223. }
  224. a.values[idx] = val
  225. a.objCount++
  226. }
  227. func (a *arrayObject) put(n Value, val Value, throw bool) {
  228. if idx := toIdx(n); idx >= 0 {
  229. a.putIdx(idx, val, throw, "", n)
  230. } else {
  231. if n.String() == "length" {
  232. a.setLength(val, throw)
  233. } else {
  234. a.baseObject.put(n, val, throw)
  235. }
  236. }
  237. }
  238. func (a *arrayObject) putStr(name string, val Value, throw bool) {
  239. if idx := strToIdx(name); idx >= 0 {
  240. a.putIdx(idx, val, throw, name, nil)
  241. } else {
  242. if name == "length" {
  243. a.setLength(val, throw)
  244. } else {
  245. a.baseObject.putStr(name, val, throw)
  246. }
  247. }
  248. }
  249. type arrayPropIter struct {
  250. a *arrayObject
  251. recursive bool
  252. idx int
  253. }
  254. func (i *arrayPropIter) next() (propIterItem, iterNextFunc) {
  255. for i.idx < len(i.a.values) {
  256. name := strconv.Itoa(i.idx)
  257. prop := i.a.values[i.idx]
  258. i.idx++
  259. if prop != nil {
  260. return propIterItem{name: name, value: prop}, i.next
  261. }
  262. }
  263. return i.a.baseObject._enumerate(i.recursive)()
  264. }
  265. func (a *arrayObject) _enumerate(recursive bool) iterNextFunc {
  266. return (&arrayPropIter{
  267. a: a,
  268. recursive: recursive,
  269. }).next
  270. }
  271. func (a *arrayObject) enumerate(all, recursive bool) iterNextFunc {
  272. return (&propFilterIter{
  273. wrapped: a._enumerate(recursive),
  274. all: all,
  275. seen: make(map[string]bool),
  276. }).next
  277. }
  278. func (a *arrayObject) hasOwnProperty(n Value) bool {
  279. if idx := toIdx(n); idx >= 0 {
  280. return idx < int64(len(a.values)) && a.values[idx] != nil && a.values[idx] != _undefined
  281. } else {
  282. return a.baseObject.hasOwnProperty(n)
  283. }
  284. }
  285. func (a *arrayObject) hasOwnPropertyStr(name string) bool {
  286. if idx := strToIdx(name); idx >= 0 {
  287. return idx < int64(len(a.values)) && a.values[idx] != nil && a.values[idx] != _undefined
  288. } else {
  289. return a.baseObject.hasOwnPropertyStr(name)
  290. }
  291. }
  292. func (a *arrayObject) expand(idx int64) bool {
  293. targetLen := idx + 1
  294. if targetLen > int64(len(a.values)) {
  295. if targetLen < int64(cap(a.values)) {
  296. a.values = a.values[:targetLen]
  297. } else {
  298. if idx > 4096 && (a.objCount == 0 || idx/a.objCount > 10) {
  299. //log.Println("Switching standard->sparse")
  300. sa := &sparseArrayObject{
  301. baseObject: a.baseObject,
  302. length: a.length,
  303. propValueCount: a.propValueCount,
  304. }
  305. sa.setValues(a.values)
  306. sa.val.self = sa
  307. sa.init()
  308. sa.lengthProp.writable = a.lengthProp.writable
  309. return false
  310. } else {
  311. // Use the same algorithm as in runtime.growSlice
  312. newcap := int64(cap(a.values))
  313. doublecap := newcap + newcap
  314. if targetLen > doublecap {
  315. newcap = targetLen
  316. } else {
  317. if len(a.values) < 1024 {
  318. newcap = doublecap
  319. } else {
  320. for newcap < targetLen {
  321. newcap += newcap / 4
  322. }
  323. }
  324. }
  325. newValues := make([]Value, targetLen, newcap)
  326. copy(newValues, a.values)
  327. a.values = newValues
  328. }
  329. }
  330. }
  331. return true
  332. }
  333. func (r *Runtime) defineArrayLength(prop *valueProperty, descr propertyDescr, setter func(Value, bool) bool, throw bool) bool {
  334. ret := true
  335. if descr.Configurable == FLAG_TRUE || descr.Enumerable == FLAG_TRUE || descr.Getter != nil || descr.Setter != nil {
  336. ret = false
  337. goto Reject
  338. }
  339. if newLen := descr.Value; newLen != nil {
  340. ret = setter(newLen, false)
  341. } else {
  342. ret = true
  343. }
  344. if descr.Writable != FLAG_NOT_SET {
  345. w := descr.Writable.Bool()
  346. if prop.writable {
  347. prop.writable = w
  348. } else {
  349. if w {
  350. ret = false
  351. goto Reject
  352. }
  353. }
  354. }
  355. Reject:
  356. if !ret {
  357. r.typeErrorResult(throw, "Cannot redefine property: length")
  358. }
  359. return ret
  360. }
  361. func (a *arrayObject) defineOwnProperty(n Value, descr propertyDescr, throw bool) bool {
  362. if idx := toIdx(n); idx >= 0 {
  363. var existing Value
  364. if idx < int64(len(a.values)) {
  365. existing = a.values[idx]
  366. }
  367. prop, ok := a.baseObject._defineOwnProperty(n, existing, descr, throw)
  368. if ok {
  369. if idx >= a.length {
  370. if !a.setLengthInt(idx+1, throw) {
  371. return false
  372. }
  373. }
  374. if a.expand(idx) {
  375. a.values[idx] = prop
  376. a.objCount++
  377. if _, ok := prop.(*valueProperty); ok {
  378. a.propValueCount++
  379. }
  380. } else {
  381. a.val.self.(*sparseArrayObject).putIdx(idx, prop, throw, "", nil)
  382. }
  383. }
  384. return ok
  385. } else {
  386. if n.String() == "length" {
  387. return a.val.runtime.defineArrayLength(&a.lengthProp, descr, a.setLength, throw)
  388. }
  389. return a.baseObject.defineOwnProperty(n, descr, throw)
  390. }
  391. }
  392. func (a *arrayObject) _deleteProp(idx int64, throw bool) bool {
  393. if idx < int64(len(a.values)) {
  394. if v := a.values[idx]; v != nil {
  395. if p, ok := v.(*valueProperty); ok {
  396. if !p.configurable {
  397. a.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of %s", idx, a.val.ToString())
  398. return false
  399. }
  400. a.propValueCount--
  401. }
  402. a.values[idx] = nil
  403. a.objCount--
  404. }
  405. }
  406. return true
  407. }
  408. func (a *arrayObject) delete(n Value, throw bool) bool {
  409. if idx := toIdx(n); idx >= 0 {
  410. return a._deleteProp(idx, throw)
  411. }
  412. return a.baseObject.delete(n, throw)
  413. }
  414. func (a *arrayObject) deleteStr(name string, throw bool) bool {
  415. if idx := strToIdx(name); idx >= 0 {
  416. return a._deleteProp(idx, throw)
  417. }
  418. return a.baseObject.deleteStr(name, throw)
  419. }
  420. func (a *arrayObject) export() interface{} {
  421. arr := make([]interface{}, a.length)
  422. for i, v := range a.values {
  423. if v != nil {
  424. arr[i] = v.Export()
  425. }
  426. }
  427. return arr
  428. }
  429. func (a *arrayObject) exportType() reflect.Type {
  430. return reflectTypeArray
  431. }
  432. func (a *arrayObject) setValuesFromSparse(items []sparseArrayItem) {
  433. a.values = make([]Value, int(items[len(items)-1].idx+1))
  434. for _, item := range items {
  435. a.values[item.idx] = item.value
  436. }
  437. a.objCount = int64(len(items))
  438. }