github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/builtin_array.go (about)

     1  package goja
     2  
     3  import (
     4  	"math"
     5  	"sort"
     6  )
     7  
     8  func (r *Runtime) newArray(prototype *Object) (a *arrayObject) {
     9  	v := &Object{runtime: r}
    10  
    11  	a = &arrayObject{}
    12  	a.class = classArray
    13  	a.val = v
    14  	a.extensible = true
    15  	v.self = a
    16  	a.prototype = prototype
    17  	a.init()
    18  	return
    19  }
    20  
    21  func (r *Runtime) newArrayObject() *arrayObject {
    22  	return r.newArray(r.global.ArrayPrototype)
    23  }
    24  
    25  func setArrayValues(a *arrayObject, values []Value) *arrayObject {
    26  	a.values = values
    27  	a.length = uint32(len(values))
    28  	a.objCount = len(values)
    29  	return a
    30  }
    31  
    32  func setArrayLength(a *arrayObject, l int64) *arrayObject {
    33  	a.setOwnStr("length", intToValue(l), true)
    34  	return a
    35  }
    36  
    37  func arraySpeciesCreate(obj *Object, size int64) *Object {
    38  	if isArray(obj) {
    39  		v := obj.self.getStr("constructor", nil)
    40  		if constructObj, ok := v.(*Object); ok {
    41  			v = constructObj.self.getSym(SymSpecies, nil)
    42  			if v == _null {
    43  				v = nil
    44  			}
    45  		}
    46  
    47  		if v != nil && v != _undefined {
    48  			constructObj, _ := v.(*Object)
    49  			if constructObj != nil {
    50  				if constructor := constructObj.self.assertConstructor(); constructor != nil {
    51  					return constructor([]Value{intToValue(size)}, constructObj)
    52  				}
    53  			}
    54  			panic(obj.runtime.NewTypeError("Species is not a constructor"))
    55  		}
    56  	}
    57  	return obj.runtime.newArrayLength(size)
    58  }
    59  
    60  func max(a, b int64) int64 {
    61  	if a > b {
    62  		return a
    63  	}
    64  	return b
    65  }
    66  
    67  func min(a, b int64) int64 {
    68  	if a < b {
    69  		return a
    70  	}
    71  	return b
    72  }
    73  
    74  func relToIdx(rel, l int64) int64 {
    75  	if rel >= 0 {
    76  		return min(rel, l)
    77  	}
    78  	return max(l+rel, 0)
    79  }
    80  
    81  func (r *Runtime) newArrayValues(values []Value) *Object {
    82  	return setArrayValues(r.newArrayObject(), values).val
    83  }
    84  
    85  func (r *Runtime) newArrayLength(l int64) *Object {
    86  	return setArrayLength(r.newArrayObject(), l).val
    87  }
    88  
    89  func (r *Runtime) builtin_newArray(args []Value, proto *Object) *Object {
    90  	l := len(args)
    91  	if l == 1 {
    92  		if al, ok := args[0].(valueInt); ok {
    93  			return setArrayLength(r.newArray(proto), int64(al)).val
    94  		} else if f, ok := args[0].(valueFloat); ok {
    95  			al := int64(f)
    96  			if float64(al) == float64(f) {
    97  				return r.newArrayLength(al)
    98  			} else {
    99  				panic(r.newError(r.global.RangeError, "Invalid array length"))
   100  			}
   101  		}
   102  		return setArrayValues(r.newArray(proto), []Value{args[0]}).val
   103  	} else {
   104  		argsCopy := make([]Value, l)
   105  		copy(argsCopy, args)
   106  		return setArrayValues(r.newArray(proto), argsCopy).val
   107  	}
   108  }
   109  
   110  func (r *Runtime) generic_push(obj *Object, call FunctionCall) Value {
   111  	l := toLength(obj.self.getStr("length", nil))
   112  	nl := l + int64(len(call.Arguments))
   113  	if nl >= maxInt {
   114  		r.typeErrorResult(true, "Invalid array length")
   115  		panic("unreachable")
   116  	}
   117  	for i, arg := range call.Arguments {
   118  		obj.self.setOwnIdx(valueInt(l+int64(i)), arg, true)
   119  	}
   120  	n := valueInt(nl)
   121  	obj.self.setOwnStr("length", n, true)
   122  	return n
   123  }
   124  
   125  func (r *Runtime) arrayproto_push(call FunctionCall) Value {
   126  	obj := call.This.ToObject(r)
   127  	return r.generic_push(obj, call)
   128  }
   129  
   130  func (r *Runtime) arrayproto_pop_generic(obj *Object) Value {
   131  	l := toLength(obj.self.getStr("length", nil))
   132  	if l == 0 {
   133  		obj.self.setOwnStr("length", intToValue(0), true)
   134  		return _undefined
   135  	}
   136  	idx := valueInt(l - 1)
   137  	val := obj.self.getIdx(idx, nil)
   138  	obj.self.deleteIdx(idx, true)
   139  	obj.self.setOwnStr("length", idx, true)
   140  	return val
   141  }
   142  
   143  func (r *Runtime) arrayproto_pop(call FunctionCall) Value {
   144  	obj := call.This.ToObject(r)
   145  	if a, ok := obj.self.(*arrayObject); ok {
   146  		l := a.length
   147  		var val Value
   148  		if l > 0 {
   149  			l--
   150  			if l < uint32(len(a.values)) {
   151  				val = a.values[l]
   152  			}
   153  			if val == nil {
   154  				// optimisation bail-out
   155  				return r.arrayproto_pop_generic(obj)
   156  			}
   157  			if _, ok := val.(*valueProperty); ok {
   158  				// optimisation bail-out
   159  				return r.arrayproto_pop_generic(obj)
   160  			}
   161  			//a._setLengthInt(l, false)
   162  			a.values[l] = nil
   163  			a.values = a.values[:l]
   164  		} else {
   165  			val = _undefined
   166  		}
   167  		if a.lengthProp.writable {
   168  			a.length = l
   169  		} else {
   170  			a.setLength(0, true) // will throw
   171  		}
   172  		return val
   173  	} else {
   174  		return r.arrayproto_pop_generic(obj)
   175  	}
   176  }
   177  
   178  func (r *Runtime) arrayproto_join(call FunctionCall) Value {
   179  	o := call.This.ToObject(r)
   180  	l := int(toLength(o.self.getStr("length", nil)))
   181  	var sep String
   182  	if s := call.Argument(0); s != _undefined {
   183  		sep = s.toString()
   184  	} else {
   185  		sep = asciiString(",")
   186  	}
   187  	if l == 0 {
   188  		return stringEmpty
   189  	}
   190  
   191  	var buf StringBuilder
   192  
   193  	element0 := o.self.getIdx(valueInt(0), nil)
   194  	if element0 != nil && element0 != _undefined && element0 != _null {
   195  		buf.WriteString(element0.toString())
   196  	}
   197  
   198  	for i := 1; i < l; i++ {
   199  		buf.WriteString(sep)
   200  		element := o.self.getIdx(valueInt(int64(i)), nil)
   201  		if element != nil && element != _undefined && element != _null {
   202  			buf.WriteString(element.toString())
   203  		}
   204  	}
   205  
   206  	return buf.String()
   207  }
   208  
   209  func (r *Runtime) arrayproto_toString(call FunctionCall) Value {
   210  	array := call.This.ToObject(r)
   211  	var toString func() Value
   212  	switch a := array.self.(type) {
   213  	case *objectGoSliceReflect:
   214  		toString = a.toString
   215  	case *objectGoArrayReflect:
   216  		toString = a.toString
   217  	}
   218  	if toString != nil {
   219  		return toString()
   220  	}
   221  	f := array.self.getStr("join", nil)
   222  	if fObj, ok := f.(*Object); ok {
   223  		if fcall, ok := fObj.self.assertCallable(); ok {
   224  			return fcall(FunctionCall{
   225  				This: array,
   226  			})
   227  		}
   228  	}
   229  	return r.objectproto_toString(FunctionCall{
   230  		This: array,
   231  	})
   232  }
   233  
   234  func (r *Runtime) writeItemLocaleString(item Value, buf *StringBuilder) {
   235  	if item != nil && item != _undefined && item != _null {
   236  		if f, ok := r.getVStr(item, "toLocaleString").(*Object); ok {
   237  			if c, ok := f.self.assertCallable(); ok {
   238  				strVal := c(FunctionCall{
   239  					This: item,
   240  				})
   241  				buf.WriteString(strVal.toString())
   242  				return
   243  			}
   244  		}
   245  		r.typeErrorResult(true, "Property 'toLocaleString' of object %s is not a function", item)
   246  	}
   247  }
   248  
   249  func (r *Runtime) arrayproto_toLocaleString(call FunctionCall) Value {
   250  	array := call.This.ToObject(r)
   251  	var buf StringBuilder
   252  	if a := r.checkStdArrayObj(array); a != nil {
   253  		for i, item := range a.values {
   254  			if i > 0 {
   255  				buf.WriteRune(',')
   256  			}
   257  			r.writeItemLocaleString(item, &buf)
   258  		}
   259  	} else {
   260  		length := toLength(array.self.getStr("length", nil))
   261  		for i := int64(0); i < length; i++ {
   262  			if i > 0 {
   263  				buf.WriteRune(',')
   264  			}
   265  			item := array.self.getIdx(valueInt(i), nil)
   266  			r.writeItemLocaleString(item, &buf)
   267  		}
   268  	}
   269  
   270  	return buf.String()
   271  }
   272  
   273  func isConcatSpreadable(obj *Object) bool {
   274  	spreadable := obj.self.getSym(SymIsConcatSpreadable, nil)
   275  	if spreadable != nil && spreadable != _undefined {
   276  		return spreadable.ToBoolean()
   277  	}
   278  	return isArray(obj)
   279  }
   280  
   281  func (r *Runtime) arrayproto_concat_append(a *Object, item Value) {
   282  	aLength := toLength(a.self.getStr("length", nil))
   283  	if obj, ok := item.(*Object); ok && isConcatSpreadable(obj) {
   284  		length := toLength(obj.self.getStr("length", nil))
   285  		if aLength+length >= maxInt {
   286  			panic(r.NewTypeError("Invalid array length"))
   287  		}
   288  		for i := int64(0); i < length; i++ {
   289  			v := obj.self.getIdx(valueInt(i), nil)
   290  			if v != nil {
   291  				createDataPropertyOrThrow(a, intToValue(aLength), v)
   292  			}
   293  			aLength++
   294  		}
   295  	} else {
   296  		createDataPropertyOrThrow(a, intToValue(aLength), item)
   297  		aLength++
   298  	}
   299  	a.self.setOwnStr("length", intToValue(aLength), true)
   300  }
   301  
   302  func (r *Runtime) arrayproto_concat(call FunctionCall) Value {
   303  	obj := call.This.ToObject(r)
   304  	a := arraySpeciesCreate(obj, 0)
   305  	r.arrayproto_concat_append(a, call.This.ToObject(r))
   306  	for _, item := range call.Arguments {
   307  		r.arrayproto_concat_append(a, item)
   308  	}
   309  	return a
   310  }
   311  
   312  func (r *Runtime) arrayproto_slice(call FunctionCall) Value {
   313  	o := call.This.ToObject(r)
   314  	length := toLength(o.self.getStr("length", nil))
   315  	start := relToIdx(call.Argument(0).ToInteger(), length)
   316  	var end int64
   317  	if endArg := call.Argument(1); endArg != _undefined {
   318  		end = endArg.ToInteger()
   319  	} else {
   320  		end = length
   321  	}
   322  	end = relToIdx(end, length)
   323  
   324  	count := end - start
   325  	if count < 0 {
   326  		count = 0
   327  	}
   328  
   329  	a := arraySpeciesCreate(o, count)
   330  	if src := r.checkStdArrayObj(o); src != nil {
   331  		if dst := r.checkStdArrayObjWithProto(a); dst != nil {
   332  			values := make([]Value, count)
   333  			copy(values, src.values[start:])
   334  			setArrayValues(dst, values)
   335  			return a
   336  		}
   337  	}
   338  
   339  	n := int64(0)
   340  	for start < end {
   341  		p := o.self.getIdx(valueInt(start), nil)
   342  		if p != nil {
   343  			createDataPropertyOrThrow(a, valueInt(n), p)
   344  		}
   345  		start++
   346  		n++
   347  	}
   348  	return a
   349  }
   350  
   351  func (r *Runtime) arrayproto_sort(call FunctionCall) Value {
   352  	o := call.This.ToObject(r)
   353  
   354  	var compareFn func(FunctionCall) Value
   355  	arg := call.Argument(0)
   356  	if arg != _undefined {
   357  		if arg, ok := call.Argument(0).(*Object); ok {
   358  			compareFn, _ = arg.self.assertCallable()
   359  		}
   360  		if compareFn == nil {
   361  			panic(r.NewTypeError("The comparison function must be either a function or undefined"))
   362  		}
   363  	}
   364  
   365  	var s sortable
   366  	if r.checkStdArrayObj(o) != nil {
   367  		s = o.self
   368  	} else if _, ok := o.self.(reflectValueWrapper); ok {
   369  		s = o.self
   370  	}
   371  
   372  	if s != nil {
   373  		ctx := arraySortCtx{
   374  			obj:     s,
   375  			compare: compareFn,
   376  		}
   377  
   378  		sort.Stable(&ctx)
   379  	} else {
   380  		length := toLength(o.self.getStr("length", nil))
   381  		a := make([]Value, 0, length)
   382  		for i := int64(0); i < length; i++ {
   383  			idx := valueInt(i)
   384  			if o.self.hasPropertyIdx(idx) {
   385  				a = append(a, nilSafe(o.self.getIdx(idx, nil)))
   386  			}
   387  		}
   388  		ar := r.newArrayValues(a)
   389  		ctx := arraySortCtx{
   390  			obj:     ar.self,
   391  			compare: compareFn,
   392  		}
   393  
   394  		sort.Stable(&ctx)
   395  		for i := 0; i < len(a); i++ {
   396  			o.self.setOwnIdx(valueInt(i), a[i], true)
   397  		}
   398  		for i := int64(len(a)); i < length; i++ {
   399  			o.self.deleteIdx(valueInt(i), true)
   400  		}
   401  	}
   402  	return o
   403  }
   404  
   405  func (r *Runtime) arrayproto_splice(call FunctionCall) Value {
   406  	o := call.This.ToObject(r)
   407  	length := toLength(o.self.getStr("length", nil))
   408  	actualStart := relToIdx(call.Argument(0).ToInteger(), length)
   409  	var actualDeleteCount int64
   410  	switch len(call.Arguments) {
   411  	case 0:
   412  	case 1:
   413  		actualDeleteCount = length - actualStart
   414  	default:
   415  		actualDeleteCount = min(max(call.Argument(1).ToInteger(), 0), length-actualStart)
   416  	}
   417  	itemCount := max(int64(len(call.Arguments)-2), 0)
   418  	newLength := length - actualDeleteCount + itemCount
   419  	if newLength >= maxInt {
   420  		panic(r.NewTypeError("Invalid array length"))
   421  	}
   422  	a := arraySpeciesCreate(o, actualDeleteCount)
   423  	if src := r.checkStdArrayObj(o); src != nil {
   424  		if dst := r.checkStdArrayObjWithProto(a); dst != nil {
   425  			values := make([]Value, actualDeleteCount)
   426  			copy(values, src.values[actualStart:])
   427  			setArrayValues(dst, values)
   428  		} else {
   429  			for k := int64(0); k < actualDeleteCount; k++ {
   430  				createDataPropertyOrThrow(a, intToValue(k), src.values[k+actualStart])
   431  			}
   432  			a.self.setOwnStr("length", intToValue(actualDeleteCount), true)
   433  		}
   434  		var values []Value
   435  		if itemCount < actualDeleteCount {
   436  			values = src.values
   437  			copy(values[actualStart+itemCount:], values[actualStart+actualDeleteCount:])
   438  			tail := values[newLength:]
   439  			for k := range tail {
   440  				tail[k] = nil
   441  			}
   442  			values = values[:newLength]
   443  		} else if itemCount > actualDeleteCount {
   444  			if int64(cap(src.values)) >= newLength {
   445  				values = src.values[:newLength]
   446  				copy(values[actualStart+itemCount:], values[actualStart+actualDeleteCount:length])
   447  			} else {
   448  				values = make([]Value, newLength)
   449  				copy(values, src.values[:actualStart])
   450  				copy(values[actualStart+itemCount:], src.values[actualStart+actualDeleteCount:])
   451  			}
   452  		} else {
   453  			values = src.values
   454  		}
   455  		if itemCount > 0 {
   456  			copy(values[actualStart:], call.Arguments[2:])
   457  		}
   458  		src.values = values
   459  		src.objCount = len(values)
   460  	} else {
   461  		for k := int64(0); k < actualDeleteCount; k++ {
   462  			from := valueInt(k + actualStart)
   463  			if o.self.hasPropertyIdx(from) {
   464  				createDataPropertyOrThrow(a, valueInt(k), nilSafe(o.self.getIdx(from, nil)))
   465  			}
   466  		}
   467  
   468  		if itemCount < actualDeleteCount {
   469  			for k := actualStart; k < length-actualDeleteCount; k++ {
   470  				from := valueInt(k + actualDeleteCount)
   471  				to := valueInt(k + itemCount)
   472  				if o.self.hasPropertyIdx(from) {
   473  					o.self.setOwnIdx(to, nilSafe(o.self.getIdx(from, nil)), true)
   474  				} else {
   475  					o.self.deleteIdx(to, true)
   476  				}
   477  			}
   478  
   479  			for k := length; k > length-actualDeleteCount+itemCount; k-- {
   480  				o.self.deleteIdx(valueInt(k-1), true)
   481  			}
   482  		} else if itemCount > actualDeleteCount {
   483  			for k := length - actualDeleteCount; k > actualStart; k-- {
   484  				from := valueInt(k + actualDeleteCount - 1)
   485  				to := valueInt(k + itemCount - 1)
   486  				if o.self.hasPropertyIdx(from) {
   487  					o.self.setOwnIdx(to, nilSafe(o.self.getIdx(from, nil)), true)
   488  				} else {
   489  					o.self.deleteIdx(to, true)
   490  				}
   491  			}
   492  		}
   493  
   494  		if itemCount > 0 {
   495  			for i, item := range call.Arguments[2:] {
   496  				o.self.setOwnIdx(valueInt(actualStart+int64(i)), item, true)
   497  			}
   498  		}
   499  	}
   500  
   501  	o.self.setOwnStr("length", intToValue(newLength), true)
   502  
   503  	return a
   504  }
   505  
   506  func (r *Runtime) arrayproto_unshift(call FunctionCall) Value {
   507  	o := call.This.ToObject(r)
   508  	length := toLength(o.self.getStr("length", nil))
   509  	argCount := int64(len(call.Arguments))
   510  	newLen := intToValue(length + argCount)
   511  	if argCount > 0 {
   512  		newSize := length + argCount
   513  		if newSize >= maxInt {
   514  			panic(r.NewTypeError("Invalid array length"))
   515  		}
   516  		if arr := r.checkStdArrayObjWithProto(o); arr != nil && newSize < math.MaxUint32 {
   517  			if int64(cap(arr.values)) >= newSize {
   518  				arr.values = arr.values[:newSize]
   519  				copy(arr.values[argCount:], arr.values[:length])
   520  			} else {
   521  				values := make([]Value, newSize)
   522  				copy(values[argCount:], arr.values)
   523  				arr.values = values
   524  			}
   525  			copy(arr.values, call.Arguments)
   526  			arr.objCount = int(arr.length)
   527  		} else {
   528  			for k := length - 1; k >= 0; k-- {
   529  				from := valueInt(k)
   530  				to := valueInt(k + argCount)
   531  				if o.self.hasPropertyIdx(from) {
   532  					o.self.setOwnIdx(to, nilSafe(o.self.getIdx(from, nil)), true)
   533  				} else {
   534  					o.self.deleteIdx(to, true)
   535  				}
   536  			}
   537  
   538  			for k, arg := range call.Arguments {
   539  				o.self.setOwnIdx(valueInt(int64(k)), arg, true)
   540  			}
   541  		}
   542  	}
   543  
   544  	o.self.setOwnStr("length", newLen, true)
   545  	return newLen
   546  }
   547  
   548  func (r *Runtime) arrayproto_at(call FunctionCall) Value {
   549  	o := call.This.ToObject(r)
   550  	idx := call.Argument(0).ToInteger()
   551  	length := toLength(o.self.getStr("length", nil))
   552  	if idx < 0 {
   553  		idx = length + idx
   554  	}
   555  	if idx >= length || idx < 0 {
   556  		return _undefined
   557  	}
   558  	i := valueInt(idx)
   559  	if o.self.hasPropertyIdx(i) {
   560  		return o.self.getIdx(i, nil)
   561  	}
   562  	return _undefined
   563  }
   564  
   565  func (r *Runtime) arrayproto_indexOf(call FunctionCall) Value {
   566  	o := call.This.ToObject(r)
   567  	length := toLength(o.self.getStr("length", nil))
   568  	if length == 0 {
   569  		return intToValue(-1)
   570  	}
   571  
   572  	n := call.Argument(1).ToInteger()
   573  	if n >= length {
   574  		return intToValue(-1)
   575  	}
   576  
   577  	if n < 0 {
   578  		n = max(length+n, 0)
   579  	}
   580  
   581  	searchElement := call.Argument(0)
   582  
   583  	if arr := r.checkStdArrayObj(o); arr != nil {
   584  		for i, val := range arr.values[n:] {
   585  			if searchElement.StrictEquals(val) {
   586  				return intToValue(n + int64(i))
   587  			}
   588  		}
   589  		return intToValue(-1)
   590  	}
   591  
   592  	for ; n < length; n++ {
   593  		idx := valueInt(n)
   594  		if o.self.hasPropertyIdx(idx) {
   595  			if val := o.self.getIdx(idx, nil); val != nil {
   596  				if searchElement.StrictEquals(val) {
   597  					return idx
   598  				}
   599  			}
   600  		}
   601  	}
   602  
   603  	return intToValue(-1)
   604  }
   605  
   606  func (r *Runtime) arrayproto_includes(call FunctionCall) Value {
   607  	o := call.This.ToObject(r)
   608  	length := toLength(o.self.getStr("length", nil))
   609  	if length == 0 {
   610  		return valueFalse
   611  	}
   612  
   613  	n := call.Argument(1).ToInteger()
   614  	if n >= length {
   615  		return valueFalse
   616  	}
   617  
   618  	if n < 0 {
   619  		n = max(length+n, 0)
   620  	}
   621  
   622  	searchElement := call.Argument(0)
   623  	if searchElement == _negativeZero {
   624  		searchElement = _positiveZero
   625  	}
   626  
   627  	if arr := r.checkStdArrayObj(o); arr != nil {
   628  		for _, val := range arr.values[n:] {
   629  			if searchElement.SameAs(val) {
   630  				return valueTrue
   631  			}
   632  		}
   633  		return valueFalse
   634  	}
   635  
   636  	for ; n < length; n++ {
   637  		idx := valueInt(n)
   638  		val := nilSafe(o.self.getIdx(idx, nil))
   639  		if searchElement.SameAs(val) {
   640  			return valueTrue
   641  		}
   642  	}
   643  
   644  	return valueFalse
   645  }
   646  
   647  func (r *Runtime) arrayproto_lastIndexOf(call FunctionCall) Value {
   648  	o := call.This.ToObject(r)
   649  	length := toLength(o.self.getStr("length", nil))
   650  	if length == 0 {
   651  		return intToValue(-1)
   652  	}
   653  
   654  	var fromIndex int64
   655  
   656  	if len(call.Arguments) < 2 {
   657  		fromIndex = length - 1
   658  	} else {
   659  		fromIndex = call.Argument(1).ToInteger()
   660  		if fromIndex >= 0 {
   661  			fromIndex = min(fromIndex, length-1)
   662  		} else {
   663  			fromIndex += length
   664  		}
   665  	}
   666  
   667  	searchElement := call.Argument(0)
   668  
   669  	if arr := r.checkStdArrayObj(o); arr != nil {
   670  		vals := arr.values
   671  		for k := fromIndex; k >= 0; k-- {
   672  			if v := vals[k]; v != nil && searchElement.StrictEquals(v) {
   673  				return intToValue(k)
   674  			}
   675  		}
   676  		return intToValue(-1)
   677  	}
   678  
   679  	for k := fromIndex; k >= 0; k-- {
   680  		idx := valueInt(k)
   681  		if o.self.hasPropertyIdx(idx) {
   682  			if val := o.self.getIdx(idx, nil); val != nil {
   683  				if searchElement.StrictEquals(val) {
   684  					return idx
   685  				}
   686  			}
   687  		}
   688  	}
   689  
   690  	return intToValue(-1)
   691  }
   692  
   693  func (r *Runtime) arrayproto_every(call FunctionCall) Value {
   694  	o := call.This.ToObject(r)
   695  	length := toLength(o.self.getStr("length", nil))
   696  	callbackFn := r.toCallable(call.Argument(0))
   697  	fc := FunctionCall{
   698  		This:      call.Argument(1),
   699  		Arguments: []Value{nil, nil, o},
   700  	}
   701  	for k := int64(0); k < length; k++ {
   702  		idx := valueInt(k)
   703  		if val := o.self.getIdx(idx, nil); val != nil {
   704  			fc.Arguments[0] = val
   705  			fc.Arguments[1] = idx
   706  			if !callbackFn(fc).ToBoolean() {
   707  				return valueFalse
   708  			}
   709  		}
   710  	}
   711  	return valueTrue
   712  }
   713  
   714  func (r *Runtime) arrayproto_some(call FunctionCall) Value {
   715  	o := call.This.ToObject(r)
   716  	length := toLength(o.self.getStr("length", nil))
   717  	callbackFn := r.toCallable(call.Argument(0))
   718  	fc := FunctionCall{
   719  		This:      call.Argument(1),
   720  		Arguments: []Value{nil, nil, o},
   721  	}
   722  	for k := int64(0); k < length; k++ {
   723  		idx := valueInt(k)
   724  		if val := o.self.getIdx(idx, nil); val != nil {
   725  			fc.Arguments[0] = val
   726  			fc.Arguments[1] = idx
   727  			if callbackFn(fc).ToBoolean() {
   728  				return valueTrue
   729  			}
   730  		}
   731  	}
   732  	return valueFalse
   733  }
   734  
   735  func (r *Runtime) arrayproto_forEach(call FunctionCall) Value {
   736  	o := call.This.ToObject(r)
   737  	length := toLength(o.self.getStr("length", nil))
   738  	callbackFn := r.toCallable(call.Argument(0))
   739  	fc := FunctionCall{
   740  		This:      call.Argument(1),
   741  		Arguments: []Value{nil, nil, o},
   742  	}
   743  	for k := int64(0); k < length; k++ {
   744  		idx := valueInt(k)
   745  		if val := o.self.getIdx(idx, nil); val != nil {
   746  			fc.Arguments[0] = val
   747  			fc.Arguments[1] = idx
   748  			callbackFn(fc)
   749  		}
   750  	}
   751  	return _undefined
   752  }
   753  
   754  func (r *Runtime) arrayproto_map(call FunctionCall) Value {
   755  	o := call.This.ToObject(r)
   756  	length := toLength(o.self.getStr("length", nil))
   757  	callbackFn := r.toCallable(call.Argument(0))
   758  	fc := FunctionCall{
   759  		This:      call.Argument(1),
   760  		Arguments: []Value{nil, nil, o},
   761  	}
   762  	a := arraySpeciesCreate(o, length)
   763  	if _, stdSrc := o.self.(*arrayObject); stdSrc {
   764  		if arr, ok := a.self.(*arrayObject); ok {
   765  			values := make([]Value, length)
   766  			for k := int64(0); k < length; k++ {
   767  				idx := valueInt(k)
   768  				if val := o.self.getIdx(idx, nil); val != nil {
   769  					fc.Arguments[0] = val
   770  					fc.Arguments[1] = idx
   771  					values[k] = callbackFn(fc)
   772  				}
   773  			}
   774  			setArrayValues(arr, values)
   775  			return a
   776  		}
   777  	}
   778  	for k := int64(0); k < length; k++ {
   779  		idx := valueInt(k)
   780  		if val := o.self.getIdx(idx, nil); val != nil {
   781  			fc.Arguments[0] = val
   782  			fc.Arguments[1] = idx
   783  			createDataPropertyOrThrow(a, idx, callbackFn(fc))
   784  		}
   785  	}
   786  	return a
   787  }
   788  
   789  func (r *Runtime) arrayproto_filter(call FunctionCall) Value {
   790  	o := call.This.ToObject(r)
   791  	length := toLength(o.self.getStr("length", nil))
   792  	callbackFn := call.Argument(0).ToObject(r)
   793  	if callbackFn, ok := callbackFn.self.assertCallable(); ok {
   794  		a := arraySpeciesCreate(o, 0)
   795  		fc := FunctionCall{
   796  			This:      call.Argument(1),
   797  			Arguments: []Value{nil, nil, o},
   798  		}
   799  		if _, stdSrc := o.self.(*arrayObject); stdSrc {
   800  			if arr := r.checkStdArrayObj(a); arr != nil {
   801  				var values []Value
   802  				for k := int64(0); k < length; k++ {
   803  					idx := valueInt(k)
   804  					if val := o.self.getIdx(idx, nil); val != nil {
   805  						fc.Arguments[0] = val
   806  						fc.Arguments[1] = idx
   807  						if callbackFn(fc).ToBoolean() {
   808  							values = append(values, val)
   809  						}
   810  					}
   811  				}
   812  				setArrayValues(arr, values)
   813  				return a
   814  			}
   815  		}
   816  
   817  		to := int64(0)
   818  		for k := int64(0); k < length; k++ {
   819  			idx := valueInt(k)
   820  			if val := o.self.getIdx(idx, nil); val != nil {
   821  				fc.Arguments[0] = val
   822  				fc.Arguments[1] = idx
   823  				if callbackFn(fc).ToBoolean() {
   824  					createDataPropertyOrThrow(a, intToValue(to), val)
   825  					to++
   826  				}
   827  			}
   828  		}
   829  		return a
   830  	} else {
   831  		r.typeErrorResult(true, "%s is not a function", call.Argument(0))
   832  	}
   833  	panic("unreachable")
   834  }
   835  
   836  func (r *Runtime) arrayproto_reduce(call FunctionCall) Value {
   837  	o := call.This.ToObject(r)
   838  	length := toLength(o.self.getStr("length", nil))
   839  	callbackFn := call.Argument(0).ToObject(r)
   840  	if callbackFn, ok := callbackFn.self.assertCallable(); ok {
   841  		fc := FunctionCall{
   842  			This:      _undefined,
   843  			Arguments: []Value{nil, nil, nil, o},
   844  		}
   845  
   846  		var k int64
   847  
   848  		if len(call.Arguments) >= 2 {
   849  			fc.Arguments[0] = call.Argument(1)
   850  		} else {
   851  			for ; k < length; k++ {
   852  				idx := valueInt(k)
   853  				if val := o.self.getIdx(idx, nil); val != nil {
   854  					fc.Arguments[0] = val
   855  					break
   856  				}
   857  			}
   858  			if fc.Arguments[0] == nil {
   859  				r.typeErrorResult(true, "No initial value")
   860  				panic("unreachable")
   861  			}
   862  			k++
   863  		}
   864  
   865  		for ; k < length; k++ {
   866  			idx := valueInt(k)
   867  			if val := o.self.getIdx(idx, nil); val != nil {
   868  				fc.Arguments[1] = val
   869  				fc.Arguments[2] = idx
   870  				fc.Arguments[0] = callbackFn(fc)
   871  			}
   872  		}
   873  		return fc.Arguments[0]
   874  	} else {
   875  		r.typeErrorResult(true, "%s is not a function", call.Argument(0))
   876  	}
   877  	panic("unreachable")
   878  }
   879  
   880  func (r *Runtime) arrayproto_reduceRight(call FunctionCall) Value {
   881  	o := call.This.ToObject(r)
   882  	length := toLength(o.self.getStr("length", nil))
   883  	callbackFn := call.Argument(0).ToObject(r)
   884  	if callbackFn, ok := callbackFn.self.assertCallable(); ok {
   885  		fc := FunctionCall{
   886  			This:      _undefined,
   887  			Arguments: []Value{nil, nil, nil, o},
   888  		}
   889  
   890  		k := length - 1
   891  
   892  		if len(call.Arguments) >= 2 {
   893  			fc.Arguments[0] = call.Argument(1)
   894  		} else {
   895  			for ; k >= 0; k-- {
   896  				idx := valueInt(k)
   897  				if val := o.self.getIdx(idx, nil); val != nil {
   898  					fc.Arguments[0] = val
   899  					break
   900  				}
   901  			}
   902  			if fc.Arguments[0] == nil {
   903  				r.typeErrorResult(true, "No initial value")
   904  				panic("unreachable")
   905  			}
   906  			k--
   907  		}
   908  
   909  		for ; k >= 0; k-- {
   910  			idx := valueInt(k)
   911  			if val := o.self.getIdx(idx, nil); val != nil {
   912  				fc.Arguments[1] = val
   913  				fc.Arguments[2] = idx
   914  				fc.Arguments[0] = callbackFn(fc)
   915  			}
   916  		}
   917  		return fc.Arguments[0]
   918  	} else {
   919  		r.typeErrorResult(true, "%s is not a function", call.Argument(0))
   920  	}
   921  	panic("unreachable")
   922  }
   923  
   924  func arrayproto_reverse_generic_step(o *Object, lower, upper int64) {
   925  	lowerP := valueInt(lower)
   926  	upperP := valueInt(upper)
   927  	var lowerValue, upperValue Value
   928  	lowerExists := o.self.hasPropertyIdx(lowerP)
   929  	if lowerExists {
   930  		lowerValue = nilSafe(o.self.getIdx(lowerP, nil))
   931  	}
   932  	upperExists := o.self.hasPropertyIdx(upperP)
   933  	if upperExists {
   934  		upperValue = nilSafe(o.self.getIdx(upperP, nil))
   935  	}
   936  	if lowerExists && upperExists {
   937  		o.self.setOwnIdx(lowerP, upperValue, true)
   938  		o.self.setOwnIdx(upperP, lowerValue, true)
   939  	} else if !lowerExists && upperExists {
   940  		o.self.setOwnIdx(lowerP, upperValue, true)
   941  		o.self.deleteIdx(upperP, true)
   942  	} else if lowerExists && !upperExists {
   943  		o.self.deleteIdx(lowerP, true)
   944  		o.self.setOwnIdx(upperP, lowerValue, true)
   945  	}
   946  }
   947  
   948  func (r *Runtime) arrayproto_reverse_generic(o *Object, start int64) {
   949  	l := toLength(o.self.getStr("length", nil))
   950  	middle := l / 2
   951  	for lower := start; lower != middle; lower++ {
   952  		arrayproto_reverse_generic_step(o, lower, l-lower-1)
   953  	}
   954  }
   955  
   956  func (r *Runtime) arrayproto_reverse(call FunctionCall) Value {
   957  	o := call.This.ToObject(r)
   958  	if a := r.checkStdArrayObj(o); a != nil {
   959  		l := len(a.values)
   960  		middle := l / 2
   961  		for lower := 0; lower != middle; lower++ {
   962  			upper := l - lower - 1
   963  			a.values[lower], a.values[upper] = a.values[upper], a.values[lower]
   964  		}
   965  		//TODO: go arrays
   966  	} else {
   967  		r.arrayproto_reverse_generic(o, 0)
   968  	}
   969  	return o
   970  }
   971  
   972  func (r *Runtime) arrayproto_shift(call FunctionCall) Value {
   973  	o := call.This.ToObject(r)
   974  	if a := r.checkStdArrayObjWithProto(o); a != nil {
   975  		if len(a.values) == 0 {
   976  			if !a.lengthProp.writable {
   977  				a.setLength(0, true) // will throw
   978  			}
   979  			return _undefined
   980  		}
   981  		first := a.values[0]
   982  		copy(a.values, a.values[1:])
   983  		a.values[len(a.values)-1] = nil
   984  		a.values = a.values[:len(a.values)-1]
   985  		a.length--
   986  		return first
   987  	}
   988  	length := toLength(o.self.getStr("length", nil))
   989  	if length == 0 {
   990  		o.self.setOwnStr("length", intToValue(0), true)
   991  		return _undefined
   992  	}
   993  	first := o.self.getIdx(valueInt(0), nil)
   994  	for i := int64(1); i < length; i++ {
   995  		idxFrom := valueInt(i)
   996  		idxTo := valueInt(i - 1)
   997  		if o.self.hasPropertyIdx(idxFrom) {
   998  			o.self.setOwnIdx(idxTo, nilSafe(o.self.getIdx(idxFrom, nil)), true)
   999  		} else {
  1000  			o.self.deleteIdx(idxTo, true)
  1001  		}
  1002  	}
  1003  
  1004  	lv := valueInt(length - 1)
  1005  	o.self.deleteIdx(lv, true)
  1006  	o.self.setOwnStr("length", lv, true)
  1007  
  1008  	return first
  1009  }
  1010  
  1011  func (r *Runtime) arrayproto_values(call FunctionCall) Value {
  1012  	return r.createArrayIterator(call.This.ToObject(r), iterationKindValue)
  1013  }
  1014  
  1015  func (r *Runtime) arrayproto_keys(call FunctionCall) Value {
  1016  	return r.createArrayIterator(call.This.ToObject(r), iterationKindKey)
  1017  }
  1018  
  1019  func (r *Runtime) arrayproto_copyWithin(call FunctionCall) Value {
  1020  	o := call.This.ToObject(r)
  1021  	l := toLength(o.self.getStr("length", nil))
  1022  	var relEnd, dir int64
  1023  	to := relToIdx(call.Argument(0).ToInteger(), l)
  1024  	from := relToIdx(call.Argument(1).ToInteger(), l)
  1025  	if end := call.Argument(2); end != _undefined {
  1026  		relEnd = end.ToInteger()
  1027  	} else {
  1028  		relEnd = l
  1029  	}
  1030  	final := relToIdx(relEnd, l)
  1031  	count := min(final-from, l-to)
  1032  	if arr := r.checkStdArrayObj(o); arr != nil {
  1033  		if count > 0 {
  1034  			copy(arr.values[to:to+count], arr.values[from:from+count])
  1035  		}
  1036  		return o
  1037  	}
  1038  	if from < to && to < from+count {
  1039  		dir = -1
  1040  		from = from + count - 1
  1041  		to = to + count - 1
  1042  	} else {
  1043  		dir = 1
  1044  	}
  1045  	for count > 0 {
  1046  		if o.self.hasPropertyIdx(valueInt(from)) {
  1047  			o.self.setOwnIdx(valueInt(to), nilSafe(o.self.getIdx(valueInt(from), nil)), true)
  1048  		} else {
  1049  			o.self.deleteIdx(valueInt(to), true)
  1050  		}
  1051  		from += dir
  1052  		to += dir
  1053  		count--
  1054  	}
  1055  
  1056  	return o
  1057  }
  1058  
  1059  func (r *Runtime) arrayproto_entries(call FunctionCall) Value {
  1060  	return r.createArrayIterator(call.This.ToObject(r), iterationKindKeyValue)
  1061  }
  1062  
  1063  func (r *Runtime) arrayproto_fill(call FunctionCall) Value {
  1064  	o := call.This.ToObject(r)
  1065  	l := toLength(o.self.getStr("length", nil))
  1066  	k := relToIdx(call.Argument(1).ToInteger(), l)
  1067  	var relEnd int64
  1068  	if endArg := call.Argument(2); endArg != _undefined {
  1069  		relEnd = endArg.ToInteger()
  1070  	} else {
  1071  		relEnd = l
  1072  	}
  1073  	final := relToIdx(relEnd, l)
  1074  	value := call.Argument(0)
  1075  	if arr := r.checkStdArrayObj(o); arr != nil {
  1076  		for ; k < final; k++ {
  1077  			arr.values[k] = value
  1078  		}
  1079  	} else {
  1080  		for ; k < final; k++ {
  1081  			o.self.setOwnIdx(valueInt(k), value, true)
  1082  		}
  1083  	}
  1084  	return o
  1085  }
  1086  
  1087  func (r *Runtime) arrayproto_find(call FunctionCall) Value {
  1088  	o := call.This.ToObject(r)
  1089  	l := toLength(o.self.getStr("length", nil))
  1090  	predicate := r.toCallable(call.Argument(0))
  1091  	fc := FunctionCall{
  1092  		This:      call.Argument(1),
  1093  		Arguments: []Value{nil, nil, o},
  1094  	}
  1095  	for k := int64(0); k < l; k++ {
  1096  		idx := valueInt(k)
  1097  		kValue := o.self.getIdx(idx, nil)
  1098  		fc.Arguments[0], fc.Arguments[1] = kValue, idx
  1099  		if predicate(fc).ToBoolean() {
  1100  			return kValue
  1101  		}
  1102  	}
  1103  
  1104  	return _undefined
  1105  }
  1106  
  1107  func (r *Runtime) arrayproto_findIndex(call FunctionCall) Value {
  1108  	o := call.This.ToObject(r)
  1109  	l := toLength(o.self.getStr("length", nil))
  1110  	predicate := r.toCallable(call.Argument(0))
  1111  	fc := FunctionCall{
  1112  		This:      call.Argument(1),
  1113  		Arguments: []Value{nil, nil, o},
  1114  	}
  1115  	for k := int64(0); k < l; k++ {
  1116  		idx := valueInt(k)
  1117  		kValue := o.self.getIdx(idx, nil)
  1118  		fc.Arguments[0], fc.Arguments[1] = kValue, idx
  1119  		if predicate(fc).ToBoolean() {
  1120  			return idx
  1121  		}
  1122  	}
  1123  
  1124  	return intToValue(-1)
  1125  }
  1126  
  1127  func (r *Runtime) arrayproto_findLast(call FunctionCall) Value {
  1128  	o := call.This.ToObject(r)
  1129  	l := toLength(o.self.getStr("length", nil))
  1130  	predicate := r.toCallable(call.Argument(0))
  1131  	fc := FunctionCall{
  1132  		This:      call.Argument(1),
  1133  		Arguments: []Value{nil, nil, o},
  1134  	}
  1135  	for k := int64(l - 1); k >= 0; k-- {
  1136  		idx := valueInt(k)
  1137  		kValue := o.self.getIdx(idx, nil)
  1138  		fc.Arguments[0], fc.Arguments[1] = kValue, idx
  1139  		if predicate(fc).ToBoolean() {
  1140  			return kValue
  1141  		}
  1142  	}
  1143  
  1144  	return _undefined
  1145  }
  1146  
  1147  func (r *Runtime) arrayproto_findLastIndex(call FunctionCall) Value {
  1148  	o := call.This.ToObject(r)
  1149  	l := toLength(o.self.getStr("length", nil))
  1150  	predicate := r.toCallable(call.Argument(0))
  1151  	fc := FunctionCall{
  1152  		This:      call.Argument(1),
  1153  		Arguments: []Value{nil, nil, o},
  1154  	}
  1155  	for k := int64(l - 1); k >= 0; k-- {
  1156  		idx := valueInt(k)
  1157  		kValue := o.self.getIdx(idx, nil)
  1158  		fc.Arguments[0], fc.Arguments[1] = kValue, idx
  1159  		if predicate(fc).ToBoolean() {
  1160  			return idx
  1161  		}
  1162  	}
  1163  
  1164  	return intToValue(-1)
  1165  }
  1166  
  1167  func (r *Runtime) arrayproto_flat(call FunctionCall) Value {
  1168  	o := call.This.ToObject(r)
  1169  	l := toLength(o.self.getStr("length", nil))
  1170  	depthNum := int64(1)
  1171  	if len(call.Arguments) > 0 {
  1172  		depthNum = call.Argument(0).ToInteger()
  1173  	}
  1174  	a := arraySpeciesCreate(o, 0)
  1175  	r.flattenIntoArray(a, o, l, 0, depthNum, nil, nil)
  1176  	return a
  1177  }
  1178  
  1179  func (r *Runtime) flattenIntoArray(target, source *Object, sourceLen, start, depth int64, mapperFunction func(FunctionCall) Value, thisArg Value) int64 {
  1180  	targetIndex, sourceIndex := start, int64(0)
  1181  	for sourceIndex < sourceLen {
  1182  		p := intToValue(sourceIndex)
  1183  		if source.hasProperty(p.toString()) {
  1184  			element := nilSafe(source.get(p, source))
  1185  			if mapperFunction != nil {
  1186  				element = mapperFunction(FunctionCall{
  1187  					This:      thisArg,
  1188  					Arguments: []Value{element, p, source},
  1189  				})
  1190  			}
  1191  			var elementArray *Object
  1192  			if depth > 0 {
  1193  				if elementObj, ok := element.(*Object); ok && isArray(elementObj) {
  1194  					elementArray = elementObj
  1195  				}
  1196  			}
  1197  			if elementArray != nil {
  1198  				elementLen := toLength(elementArray.self.getStr("length", nil))
  1199  				targetIndex = r.flattenIntoArray(target, elementArray, elementLen, targetIndex, depth-1, nil, nil)
  1200  			} else {
  1201  				if targetIndex >= maxInt-1 {
  1202  					panic(r.NewTypeError("Invalid array length"))
  1203  				}
  1204  				createDataPropertyOrThrow(target, intToValue(targetIndex), element)
  1205  				targetIndex++
  1206  			}
  1207  		}
  1208  		sourceIndex++
  1209  	}
  1210  	return targetIndex
  1211  }
  1212  
  1213  func (r *Runtime) arrayproto_flatMap(call FunctionCall) Value {
  1214  	o := call.This.ToObject(r)
  1215  	l := toLength(o.self.getStr("length", nil))
  1216  	callbackFn := r.toCallable(call.Argument(0))
  1217  	thisArg := Undefined()
  1218  	if len(call.Arguments) > 1 {
  1219  		thisArg = call.Argument(1)
  1220  	}
  1221  	a := arraySpeciesCreate(o, 0)
  1222  	r.flattenIntoArray(a, o, l, 0, 1, callbackFn, thisArg)
  1223  	return a
  1224  }
  1225  
  1226  func (r *Runtime) checkStdArrayObj(obj *Object) *arrayObject {
  1227  	if arr, ok := obj.self.(*arrayObject); ok &&
  1228  		arr.propValueCount == 0 &&
  1229  		arr.length == uint32(len(arr.values)) &&
  1230  		uint32(arr.objCount) == arr.length {
  1231  
  1232  		return arr
  1233  	}
  1234  
  1235  	return nil
  1236  }
  1237  
  1238  func (r *Runtime) checkStdArrayObjWithProto(obj *Object) *arrayObject {
  1239  	if arr := r.checkStdArrayObj(obj); arr != nil {
  1240  		if p1, ok := arr.prototype.self.(*arrayObject); ok && p1.propValueCount == 0 {
  1241  			if p2, ok := p1.prototype.self.(*baseObject); ok && p2.prototype == nil {
  1242  				p2.ensurePropOrder()
  1243  				if p2.idxPropCount == 0 {
  1244  					return arr
  1245  				}
  1246  			}
  1247  		}
  1248  	}
  1249  	return nil
  1250  }
  1251  
  1252  func (r *Runtime) checkStdArray(v Value) *arrayObject {
  1253  	if obj, ok := v.(*Object); ok {
  1254  		return r.checkStdArrayObj(obj)
  1255  	}
  1256  
  1257  	return nil
  1258  }
  1259  
  1260  func (r *Runtime) checkStdArrayIter(v Value) *arrayObject {
  1261  	if arr := r.checkStdArray(v); arr != nil &&
  1262  		arr.getSym(SymIterator, nil) == r.global.arrayValues {
  1263  
  1264  		return arr
  1265  	}
  1266  
  1267  	return nil
  1268  }
  1269  
  1270  func (r *Runtime) array_from(call FunctionCall) Value {
  1271  	var mapFn func(FunctionCall) Value
  1272  	if mapFnArg := call.Argument(1); mapFnArg != _undefined {
  1273  		if mapFnObj, ok := mapFnArg.(*Object); ok {
  1274  			if fn, ok := mapFnObj.self.assertCallable(); ok {
  1275  				mapFn = fn
  1276  			}
  1277  		}
  1278  		if mapFn == nil {
  1279  			panic(r.NewTypeError("%s is not a function", mapFnArg))
  1280  		}
  1281  	}
  1282  	t := call.Argument(2)
  1283  	items := call.Argument(0)
  1284  	if mapFn == nil && call.This == r.global.Array { // mapFn may mutate the array
  1285  		if arr := r.checkStdArrayIter(items); arr != nil {
  1286  			items := make([]Value, len(arr.values))
  1287  			copy(items, arr.values)
  1288  			return r.newArrayValues(items)
  1289  		}
  1290  	}
  1291  
  1292  	var ctor func(args []Value, newTarget *Object) *Object
  1293  	if call.This != r.global.Array {
  1294  		if o, ok := call.This.(*Object); ok {
  1295  			if c := o.self.assertConstructor(); c != nil {
  1296  				ctor = c
  1297  			}
  1298  		}
  1299  	}
  1300  	var arr *Object
  1301  	if usingIterator := toMethod(r.getV(items, SymIterator)); usingIterator != nil {
  1302  		if ctor != nil {
  1303  			arr = ctor([]Value{}, nil)
  1304  		} else {
  1305  			arr = r.newArrayValues(nil)
  1306  		}
  1307  		iter := r.getIterator(items, usingIterator)
  1308  		if mapFn == nil {
  1309  			if a := r.checkStdArrayObjWithProto(arr); a != nil {
  1310  				var values []Value
  1311  				iter.iterate(func(val Value) {
  1312  					values = append(values, val)
  1313  				})
  1314  				setArrayValues(a, values)
  1315  				return arr
  1316  			}
  1317  		}
  1318  		k := int64(0)
  1319  		iter.iterate(func(val Value) {
  1320  			if mapFn != nil {
  1321  				val = mapFn(FunctionCall{This: t, Arguments: []Value{val, intToValue(k)}})
  1322  			}
  1323  			createDataPropertyOrThrow(arr, intToValue(k), val)
  1324  			k++
  1325  		})
  1326  		arr.self.setOwnStr("length", intToValue(k), true)
  1327  	} else {
  1328  		arrayLike := items.ToObject(r)
  1329  		l := toLength(arrayLike.self.getStr("length", nil))
  1330  		if ctor != nil {
  1331  			arr = ctor([]Value{intToValue(l)}, nil)
  1332  		} else {
  1333  			arr = r.newArrayValues(nil)
  1334  		}
  1335  		if mapFn == nil {
  1336  			if a := r.checkStdArrayObjWithProto(arr); a != nil {
  1337  				values := make([]Value, l)
  1338  				for k := int64(0); k < l; k++ {
  1339  					values[k] = nilSafe(arrayLike.self.getIdx(valueInt(k), nil))
  1340  				}
  1341  				setArrayValues(a, values)
  1342  				return arr
  1343  			}
  1344  		}
  1345  		for k := int64(0); k < l; k++ {
  1346  			idx := valueInt(k)
  1347  			item := arrayLike.self.getIdx(idx, nil)
  1348  			if mapFn != nil {
  1349  				item = mapFn(FunctionCall{This: t, Arguments: []Value{item, idx}})
  1350  			} else {
  1351  				item = nilSafe(item)
  1352  			}
  1353  			createDataPropertyOrThrow(arr, idx, item)
  1354  		}
  1355  		arr.self.setOwnStr("length", intToValue(l), true)
  1356  	}
  1357  
  1358  	return arr
  1359  }
  1360  
  1361  func (r *Runtime) array_isArray(call FunctionCall) Value {
  1362  	if o, ok := call.Argument(0).(*Object); ok {
  1363  		if isArray(o) {
  1364  			return valueTrue
  1365  		}
  1366  	}
  1367  	return valueFalse
  1368  }
  1369  
  1370  func (r *Runtime) array_of(call FunctionCall) Value {
  1371  	var ctor func(args []Value, newTarget *Object) *Object
  1372  	if call.This != r.global.Array {
  1373  		if o, ok := call.This.(*Object); ok {
  1374  			if c := o.self.assertConstructor(); c != nil {
  1375  				ctor = c
  1376  			}
  1377  		}
  1378  	}
  1379  	if ctor == nil {
  1380  		values := make([]Value, len(call.Arguments))
  1381  		copy(values, call.Arguments)
  1382  		return r.newArrayValues(values)
  1383  	}
  1384  	l := intToValue(int64(len(call.Arguments)))
  1385  	arr := ctor([]Value{l}, nil)
  1386  	for i, val := range call.Arguments {
  1387  		createDataPropertyOrThrow(arr, intToValue(int64(i)), val)
  1388  	}
  1389  	arr.self.setOwnStr("length", l, true)
  1390  	return arr
  1391  }
  1392  
  1393  func (r *Runtime) arrayIterProto_next(call FunctionCall) Value {
  1394  	thisObj := r.toObject(call.This)
  1395  	if iter, ok := thisObj.self.(*arrayIterObject); ok {
  1396  		return iter.next()
  1397  	}
  1398  	panic(r.NewTypeError("Method Array Iterator.prototype.next called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
  1399  }
  1400  
  1401  func (r *Runtime) createArrayProto(val *Object) objectImpl {
  1402  	o := &arrayObject{
  1403  		baseObject: baseObject{
  1404  			class:      classArray,
  1405  			val:        val,
  1406  			extensible: true,
  1407  			prototype:  r.global.ObjectPrototype,
  1408  		},
  1409  	}
  1410  	o.init()
  1411  
  1412  	o._putProp("at", r.newNativeFunc(r.arrayproto_at, nil, "at", nil, 1), true, false, true)
  1413  	o._putProp("constructor", r.global.Array, true, false, true)
  1414  	o._putProp("concat", r.newNativeFunc(r.arrayproto_concat, nil, "concat", nil, 1), true, false, true)
  1415  	o._putProp("copyWithin", r.newNativeFunc(r.arrayproto_copyWithin, nil, "copyWithin", nil, 2), true, false, true)
  1416  	o._putProp("entries", r.newNativeFunc(r.arrayproto_entries, nil, "entries", nil, 0), true, false, true)
  1417  	o._putProp("every", r.newNativeFunc(r.arrayproto_every, nil, "every", nil, 1), true, false, true)
  1418  	o._putProp("fill", r.newNativeFunc(r.arrayproto_fill, nil, "fill", nil, 1), true, false, true)
  1419  	o._putProp("filter", r.newNativeFunc(r.arrayproto_filter, nil, "filter", nil, 1), true, false, true)
  1420  	o._putProp("find", r.newNativeFunc(r.arrayproto_find, nil, "find", nil, 1), true, false, true)
  1421  	o._putProp("findIndex", r.newNativeFunc(r.arrayproto_findIndex, nil, "findIndex", nil, 1), true, false, true)
  1422  	o._putProp("findLast", r.newNativeFunc(r.arrayproto_findLast, nil, "findLast", nil, 1), true, false, true)
  1423  	o._putProp("findLastIndex", r.newNativeFunc(r.arrayproto_findLastIndex, nil, "findLastIndex", nil, 1), true, false, true)
  1424  	o._putProp("flat", r.newNativeFunc(r.arrayproto_flat, nil, "flat", nil, 0), true, false, true)
  1425  	o._putProp("flatMap", r.newNativeFunc(r.arrayproto_flatMap, nil, "flatMap", nil, 1), true, false, true)
  1426  	o._putProp("forEach", r.newNativeFunc(r.arrayproto_forEach, nil, "forEach", nil, 1), true, false, true)
  1427  	o._putProp("includes", r.newNativeFunc(r.arrayproto_includes, nil, "includes", nil, 1), true, false, true)
  1428  	o._putProp("indexOf", r.newNativeFunc(r.arrayproto_indexOf, nil, "indexOf", nil, 1), true, false, true)
  1429  	o._putProp("join", r.newNativeFunc(r.arrayproto_join, nil, "join", nil, 1), true, false, true)
  1430  	o._putProp("keys", r.newNativeFunc(r.arrayproto_keys, nil, "keys", nil, 0), true, false, true)
  1431  	o._putProp("lastIndexOf", r.newNativeFunc(r.arrayproto_lastIndexOf, nil, "lastIndexOf", nil, 1), true, false, true)
  1432  	o._putProp("map", r.newNativeFunc(r.arrayproto_map, nil, "map", nil, 1), true, false, true)
  1433  	o._putProp("pop", r.newNativeFunc(r.arrayproto_pop, nil, "pop", nil, 0), true, false, true)
  1434  	o._putProp("push", r.newNativeFunc(r.arrayproto_push, nil, "push", nil, 1), true, false, true)
  1435  	o._putProp("reduce", r.newNativeFunc(r.arrayproto_reduce, nil, "reduce", nil, 1), true, false, true)
  1436  	o._putProp("reduceRight", r.newNativeFunc(r.arrayproto_reduceRight, nil, "reduceRight", nil, 1), true, false, true)
  1437  	o._putProp("reverse", r.newNativeFunc(r.arrayproto_reverse, nil, "reverse", nil, 0), true, false, true)
  1438  	o._putProp("shift", r.newNativeFunc(r.arrayproto_shift, nil, "shift", nil, 0), true, false, true)
  1439  	o._putProp("slice", r.newNativeFunc(r.arrayproto_slice, nil, "slice", nil, 2), true, false, true)
  1440  	o._putProp("some", r.newNativeFunc(r.arrayproto_some, nil, "some", nil, 1), true, false, true)
  1441  	o._putProp("sort", r.newNativeFunc(r.arrayproto_sort, nil, "sort", nil, 1), true, false, true)
  1442  	o._putProp("splice", r.newNativeFunc(r.arrayproto_splice, nil, "splice", nil, 2), true, false, true)
  1443  	o._putProp("toLocaleString", r.newNativeFunc(r.arrayproto_toLocaleString, nil, "toLocaleString", nil, 0), true, false, true)
  1444  	o._putProp("toString", r.global.arrayToString, true, false, true)
  1445  	o._putProp("unshift", r.newNativeFunc(r.arrayproto_unshift, nil, "unshift", nil, 1), true, false, true)
  1446  	o._putProp("values", r.global.arrayValues, true, false, true)
  1447  
  1448  	o._putSym(SymIterator, valueProp(r.global.arrayValues, true, false, true))
  1449  
  1450  	bl := r.newBaseObject(nil, classObject)
  1451  	bl.setOwnStr("copyWithin", valueTrue, true)
  1452  	bl.setOwnStr("entries", valueTrue, true)
  1453  	bl.setOwnStr("fill", valueTrue, true)
  1454  	bl.setOwnStr("find", valueTrue, true)
  1455  	bl.setOwnStr("findIndex", valueTrue, true)
  1456  	bl.setOwnStr("findLast", valueTrue, true)
  1457  	bl.setOwnStr("findLastIndex", valueTrue, true)
  1458  	bl.setOwnStr("flat", valueTrue, true)
  1459  	bl.setOwnStr("flatMap", valueTrue, true)
  1460  	bl.setOwnStr("includes", valueTrue, true)
  1461  	bl.setOwnStr("keys", valueTrue, true)
  1462  	bl.setOwnStr("values", valueTrue, true)
  1463  	bl.setOwnStr("groupBy", valueTrue, true)
  1464  	bl.setOwnStr("groupByToMap", valueTrue, true)
  1465  	o._putSym(SymUnscopables, valueProp(bl.val, false, false, true))
  1466  
  1467  	return o
  1468  }
  1469  
  1470  func (r *Runtime) createArray(val *Object) objectImpl {
  1471  	o := r.newNativeFuncConstructObj(val, r.builtin_newArray, "Array", r.global.ArrayPrototype, 1)
  1472  	o._putProp("from", r.newNativeFunc(r.array_from, nil, "from", nil, 1), true, false, true)
  1473  	o._putProp("isArray", r.newNativeFunc(r.array_isArray, nil, "isArray", nil, 1), true, false, true)
  1474  	o._putProp("of", r.newNativeFunc(r.array_of, nil, "of", nil, 0), true, false, true)
  1475  	r.putSpeciesReturnThis(o)
  1476  
  1477  	return o
  1478  }
  1479  
  1480  func (r *Runtime) createArrayIterProto(val *Object) objectImpl {
  1481  	o := newBaseObjectObj(val, r.getIteratorPrototype(), classObject)
  1482  
  1483  	o._putProp("next", r.newNativeFunc(r.arrayIterProto_next, nil, "next", nil, 0), true, false, true)
  1484  	o._putSym(SymToStringTag, valueProp(asciiString(classArrayIterator), false, false, true))
  1485  
  1486  	return o
  1487  }
  1488  
  1489  func (r *Runtime) initArray() {
  1490  	r.global.arrayValues = r.newNativeFunc(r.arrayproto_values, nil, "values", nil, 0)
  1491  	r.global.arrayToString = r.newNativeFunc(r.arrayproto_toString, nil, "toString", nil, 0)
  1492  
  1493  	r.global.ArrayPrototype = r.newLazyObject(r.createArrayProto)
  1494  
  1495  	r.global.Array = r.newLazyObject(r.createArray)
  1496  	r.addToGlobal("Array", r.global.Array)
  1497  }
  1498  
  1499  func (r *Runtime) getArrayIteratorPrototype() *Object {
  1500  	var o *Object
  1501  	if o = r.global.ArrayIteratorPrototype; o == nil {
  1502  		o = &Object{runtime: r}
  1503  		r.global.ArrayIteratorPrototype = o
  1504  		o.self = r.createArrayIterProto(o)
  1505  	}
  1506  	return o
  1507  
  1508  }
  1509  
  1510  type sortable interface {
  1511  	sortLen() int
  1512  	sortGet(int) Value
  1513  	swap(int, int)
  1514  }
  1515  
  1516  type arraySortCtx struct {
  1517  	obj     sortable
  1518  	compare func(FunctionCall) Value
  1519  }
  1520  
  1521  func (a *arraySortCtx) sortCompare(x, y Value) int {
  1522  	if x == nil && y == nil {
  1523  		return 0
  1524  	}
  1525  
  1526  	if x == nil {
  1527  		return 1
  1528  	}
  1529  
  1530  	if y == nil {
  1531  		return -1
  1532  	}
  1533  
  1534  	if x == _undefined && y == _undefined {
  1535  		return 0
  1536  	}
  1537  
  1538  	if x == _undefined {
  1539  		return 1
  1540  	}
  1541  
  1542  	if y == _undefined {
  1543  		return -1
  1544  	}
  1545  
  1546  	if a.compare != nil {
  1547  		f := a.compare(FunctionCall{
  1548  			This:      _undefined,
  1549  			Arguments: []Value{x, y},
  1550  		}).ToFloat()
  1551  		if f > 0 {
  1552  			return 1
  1553  		}
  1554  		if f < 0 {
  1555  			return -1
  1556  		}
  1557  		if math.Signbit(f) {
  1558  			return -1
  1559  		}
  1560  		return 0
  1561  	}
  1562  	return x.toString().CompareTo(y.toString())
  1563  }
  1564  
  1565  // sort.Interface
  1566  
  1567  func (a *arraySortCtx) Len() int {
  1568  	return a.obj.sortLen()
  1569  }
  1570  
  1571  func (a *arraySortCtx) Less(j, k int) bool {
  1572  	return a.sortCompare(a.obj.sortGet(j), a.obj.sortGet(k)) < 0
  1573  }
  1574  
  1575  func (a *arraySortCtx) Swap(j, k int) {
  1576  	a.obj.swap(j, k)
  1577  }