123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- package goja
- import (
- "reflect"
- "strconv"
- )
- type objectGoSlice struct {
- baseObject
- data *[]interface{}
- lengthProp valueProperty
- sliceExtensible bool
- }
- func (o *objectGoSlice) init() {
- o.baseObject.init()
- o.class = classArray
- o.prototype = o.val.runtime.global.ArrayPrototype
- o.lengthProp.writable = o.sliceExtensible
- o._setLen()
- o.baseObject._put("length", &o.lengthProp)
- }
- func (o *objectGoSlice) _setLen() {
- o.lengthProp.value = intToValue(int64(len(*o.data)))
- }
- func (o *objectGoSlice) getIdx(idx int64) Value {
- if idx < int64(len(*o.data)) {
- return o.val.runtime.ToValue((*o.data)[idx])
- }
- return nil
- }
- func (o *objectGoSlice) _get(n Value) Value {
- if idx := toIdx(n); idx >= 0 {
- return o.getIdx(idx)
- }
- return nil
- }
- func (o *objectGoSlice) _getStr(name string) Value {
- if idx := strToIdx(name); idx >= 0 {
- return o.getIdx(idx)
- }
- return nil
- }
- func (o *objectGoSlice) get(n Value) Value {
- if v := o._get(n); v != nil {
- return v
- }
- return o.baseObject._getStr(n.String())
- }
- func (o *objectGoSlice) getStr(name string) Value {
- if v := o._getStr(name); v != nil {
- return v
- }
- return o.baseObject._getStr(name)
- }
- func (o *objectGoSlice) getProp(n Value) Value {
- if v := o._get(n); v != nil {
- return v
- }
- return o.baseObject.getPropStr(n.String())
- }
- func (o *objectGoSlice) getPropStr(name string) Value {
- if v := o._getStr(name); v != nil {
- return v
- }
- return o.baseObject.getPropStr(name)
- }
- func (o *objectGoSlice) getOwnProp(name string) Value {
- if v := o._getStr(name); v != nil {
- return &valueProperty{
- value: v,
- writable: true,
- enumerable: true,
- }
- }
- return o.baseObject.getOwnProp(name)
- }
- func (o *objectGoSlice) grow(size int64) {
- newcap := int64(cap(*o.data))
- if newcap < size {
- // Use the same algorithm as in runtime.growSlice
- doublecap := newcap + newcap
- if size > doublecap {
- newcap = size
- } else {
- if len(*o.data) < 1024 {
- newcap = doublecap
- } else {
- for newcap < size {
- newcap += newcap / 4
- }
- }
- }
- n := make([]interface{}, size, newcap)
- copy(n, *o.data)
- *o.data = n
- } else {
- *o.data = (*o.data)[:size]
- }
- o._setLen()
- }
- func (o *objectGoSlice) putIdx(idx int64, v Value, throw bool) {
- if idx >= int64(len(*o.data)) {
- if !o.sliceExtensible {
- o.val.runtime.typeErrorResult(throw, "Cannot extend Go slice")
- return
- }
- o.grow(idx + 1)
- }
- (*o.data)[idx] = v.Export()
- }
- func (o *objectGoSlice) put(n Value, val Value, throw bool) {
- if idx := toIdx(n); idx >= 0 {
- o.putIdx(idx, val, throw)
- return
- }
- // TODO: length
- o.baseObject.put(n, val, throw)
- }
- func (o *objectGoSlice) putStr(name string, val Value, throw bool) {
- if idx := strToIdx(name); idx >= 0 {
- o.putIdx(idx, val, throw)
- return
- }
- // TODO: length
- o.baseObject.putStr(name, val, throw)
- }
- func (o *objectGoSlice) _has(n Value) bool {
- if idx := toIdx(n); idx >= 0 {
- return idx < int64(len(*o.data))
- }
- return false
- }
- func (o *objectGoSlice) _hasStr(name string) bool {
- if idx := strToIdx(name); idx >= 0 {
- return idx < int64(len(*o.data))
- }
- return false
- }
- func (o *objectGoSlice) hasProperty(n Value) bool {
- if o._has(n) {
- return true
- }
- return o.baseObject.hasProperty(n)
- }
- func (o *objectGoSlice) hasPropertyStr(name string) bool {
- if o._hasStr(name) {
- return true
- }
- return o.baseObject.hasPropertyStr(name)
- }
- func (o *objectGoSlice) hasOwnProperty(n Value) bool {
- if o._has(n) {
- return true
- }
- return o.baseObject.hasOwnProperty(n)
- }
- func (o *objectGoSlice) hasOwnPropertyStr(name string) bool {
- if o._hasStr(name) {
- return true
- }
- return o.baseObject.hasOwnPropertyStr(name)
- }
- func (o *objectGoSlice) _putProp(name string, value Value, writable, enumerable, configurable bool) Value {
- o.putStr(name, value, false)
- return value
- }
- func (o *objectGoSlice) defineOwnProperty(n Value, descr propertyDescr, throw bool) bool {
- if idx := toIdx(n); idx >= 0 {
- if !o.val.runtime.checkHostObjectPropertyDescr(n.String(), descr, throw) {
- return false
- }
- val := descr.Value
- if val == nil {
- val = _undefined
- }
- o.putIdx(idx, val, throw)
- return true
- }
- return o.baseObject.defineOwnProperty(n, descr, throw)
- }
- func (o *objectGoSlice) toPrimitiveNumber() Value {
- return o.toPrimitiveString()
- }
- func (o *objectGoSlice) toPrimitiveString() Value {
- return o.val.runtime.arrayproto_join(FunctionCall{
- This: o.val,
- })
- }
- func (o *objectGoSlice) toPrimitive() Value {
- return o.toPrimitiveString()
- }
- func (o *objectGoSlice) deleteStr(name string, throw bool) bool {
- if idx := strToIdx(name); idx >= 0 && idx < int64(len(*o.data)) {
- (*o.data)[idx] = nil
- return true
- }
- return o.baseObject.deleteStr(name, throw)
- }
- func (o *objectGoSlice) delete(name Value, throw bool) bool {
- if idx := toIdx(name); idx >= 0 && idx < int64(len(*o.data)) {
- (*o.data)[idx] = nil
- return true
- }
- return o.baseObject.delete(name, throw)
- }
- type goslicePropIter struct {
- o *objectGoSlice
- recursive bool
- idx, limit int
- }
- func (i *goslicePropIter) next() (propIterItem, iterNextFunc) {
- if i.idx < i.limit && i.idx < len(*i.o.data) {
- name := strconv.Itoa(i.idx)
- i.idx++
- return propIterItem{name: name, enumerable: _ENUM_TRUE}, i.next
- }
- if i.recursive {
- return i.o.prototype.self._enumerate(i.recursive)()
- }
- return propIterItem{}, nil
- }
- func (o *objectGoSlice) enumerate(all, recursive bool) iterNextFunc {
- return (&propFilterIter{
- wrapped: o._enumerate(recursive),
- all: all,
- seen: make(map[string]bool),
- }).next
- }
- func (o *objectGoSlice) _enumerate(recursive bool) iterNextFunc {
- return (&goslicePropIter{
- o: o,
- recursive: recursive,
- limit: len(*o.data),
- }).next
- }
- func (o *objectGoSlice) export() interface{} {
- return *o.data
- }
- func (o *objectGoSlice) exportType() reflect.Type {
- return reflectTypeArray
- }
- func (o *objectGoSlice) equal(other objectImpl) bool {
- if other, ok := other.(*objectGoSlice); ok {
- return o.data == other.data
- }
- return false
- }
- func (o *objectGoSlice) sortLen() int64 {
- return int64(len(*o.data))
- }
- func (o *objectGoSlice) sortGet(i int64) Value {
- return o.get(intToValue(i))
- }
- func (o *objectGoSlice) swap(i, j int64) {
- ii := intToValue(i)
- jj := intToValue(j)
- x := o.get(ii)
- y := o.get(jj)
- o.put(ii, y, false)
- o.put(jj, x, false)
- }
|