package goja

import (
	
	
	
)

func ( *Runtime) ( *Object) ( *arrayObject) {
	 := &Object{runtime: }

	 = &arrayObject{}
	.class = classArray
	.val = 
	.extensible = true
	.self = 
	.prototype = 
	.init()
	return
}

func ( *Runtime) () *arrayObject {
	return .newArray(.getArrayPrototype())
}

func setArrayValues( *arrayObject,  []Value) *arrayObject {
	.values = 
	.length = uint32(len())
	.objCount = len()
	return 
}

func setArrayLength( *arrayObject,  int64) *arrayObject {
	.setOwnStr("length", intToValue(), true)
	return 
}

func arraySpeciesCreate( *Object,  int64) *Object {
	if isArray() {
		 := .self.getStr("constructor", nil)
		if ,  := .(*Object);  {
			 = .self.getSym(SymSpecies, nil)
			if  == _null {
				 = nil
			}
		}

		if  != nil &&  != _undefined {
			,  := .(*Object)
			if  != nil {
				if  := .self.assertConstructor();  != nil {
					return ([]Value{intToValue()}, )
				}
			}
			panic(.runtime.NewTypeError("Species is not a constructor"))
		}
	}
	return .runtime.newArrayLength()
}

func max(,  int64) int64 {
	if  >  {
		return 
	}
	return 
}

func min(,  int64) int64 {
	if  <  {
		return 
	}
	return 
}

func relToIdx(,  int64) int64 {
	if  >= 0 {
		return min(, )
	}
	return max(+, 0)
}

func ( *Runtime) ( []Value) *Object {
	return setArrayValues(.newArrayObject(), ).val
}

func ( *Runtime) ( int64) *Object {
	return setArrayLength(.newArrayObject(), ).val
}

func ( *Runtime) ( []Value,  *Object) *Object {
	 := len()
	if  == 1 {
		if ,  := [0].(valueInt);  {
			return setArrayLength(.newArray(), int64()).val
		} else if ,  := [0].(valueFloat);  {
			 := int64()
			if float64() == float64() {
				return .newArrayLength()
			} else {
				panic(.newError(.getRangeError(), "Invalid array length"))
			}
		}
		return setArrayValues(.newArray(), []Value{[0]}).val
	} else {
		 := make([]Value, )
		copy(, )
		return setArrayValues(.newArray(), ).val
	}
}

func ( *Runtime) ( *Object,  FunctionCall) Value {
	 := toLength(.self.getStr("length", nil))
	 :=  + int64(len(.Arguments))
	if  >= maxInt {
		.typeErrorResult(true, "Invalid array length")
		panic("unreachable")
	}
	for ,  := range .Arguments {
		.self.setOwnIdx(valueInt(+int64()), , true)
	}
	 := valueInt()
	.self.setOwnStr("length", , true)
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	return .generic_push(, )
}

func ( *Runtime) ( *Object) Value {
	 := toLength(.self.getStr("length", nil))
	if  == 0 {
		.self.setOwnStr("length", intToValue(0), true)
		return _undefined
	}
	 := valueInt( - 1)
	 := .self.getIdx(, nil)
	.self.deleteIdx(, true)
	.self.setOwnStr("length", , true)
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	if ,  := .self.(*arrayObject);  {
		 := .length
		var  Value
		if  > 0 {
			--
			if  < uint32(len(.values)) {
				 = .values[]
			}
			if  == nil {
				// optimisation bail-out
				return .arrayproto_pop_generic()
			}
			if ,  := .(*valueProperty);  {
				// optimisation bail-out
				return .arrayproto_pop_generic()
			}
			//a._setLengthInt(l, false)
			.values[] = nil
			.values = .values[:]
		} else {
			 = _undefined
		}
		if .lengthProp.writable {
			.length = 
		} else {
			.setLength(0, true) // will throw
		}
		return 
	} else {
		return .arrayproto_pop_generic()
	}
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := int(toLength(.self.getStr("length", nil)))
	var  String
	if  := .Argument(0);  != _undefined {
		 = .toString()
	} else {
		 = asciiString(",")
	}
	if  == 0 {
		return stringEmpty
	}

	var  StringBuilder

	 := .self.getIdx(valueInt(0), nil)
	if  != nil &&  != _undefined &&  != _null {
		.WriteString(.toString())
	}

	for  := 1;  < ; ++ {
		.WriteString()
		 := .self.getIdx(valueInt(int64()), nil)
		if  != nil &&  != _undefined &&  != _null {
			.WriteString(.toString())
		}
	}

	return .String()
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	var  func() Value
	switch a := .self.(type) {
	case *objectGoSliceReflect:
		 = .toString
	case *objectGoArrayReflect:
		 = .toString
	}
	if  != nil {
		return ()
	}
	 := .self.getStr("join", nil)
	if ,  := .(*Object);  {
		if ,  := .self.assertCallable();  {
			return (FunctionCall{
				This: ,
			})
		}
	}
	return .objectproto_toString(FunctionCall{
		This: ,
	})
}

func ( *Runtime) ( Value,  *StringBuilder) {
	if  != nil &&  != _undefined &&  != _null {
		if ,  := .getVStr(, "toLocaleString").(*Object);  {
			if ,  := .self.assertCallable();  {
				 := (FunctionCall{
					This: ,
				})
				.WriteString(.toString())
				return
			}
		}
		.typeErrorResult(true, "Property 'toLocaleString' of object %s is not a function", )
	}
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	var  StringBuilder
	if  := .checkStdArrayObj();  != nil {
		for ,  := range .values {
			if  > 0 {
				.WriteRune(',')
			}
			.writeItemLocaleString(, &)
		}
	} else {
		 := toLength(.self.getStr("length", nil))
		for  := int64(0);  < ; ++ {
			if  > 0 {
				.WriteRune(',')
			}
			 := .self.getIdx(valueInt(), nil)
			.writeItemLocaleString(, &)
		}
	}

	return .String()
}

func isConcatSpreadable( *Object) bool {
	 := .self.getSym(SymIsConcatSpreadable, nil)
	if  != nil &&  != _undefined {
		return .ToBoolean()
	}
	return isArray()
}

func ( *Runtime) ( *Object,  Value) {
	 := toLength(.self.getStr("length", nil))
	if ,  := .(*Object);  && isConcatSpreadable() {
		 := toLength(.self.getStr("length", nil))
		if + >= maxInt {
			panic(.NewTypeError("Invalid array length"))
		}
		for  := int64(0);  < ; ++ {
			 := .self.getIdx(valueInt(), nil)
			if  != nil {
				createDataPropertyOrThrow(, intToValue(), )
			}
			++
		}
	} else {
		createDataPropertyOrThrow(, intToValue(), )
		++
	}
	.self.setOwnStr("length", intToValue(), true)
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := arraySpeciesCreate(, 0)
	.arrayproto_concat_append(, .This.ToObject())
	for ,  := range .Arguments {
		.arrayproto_concat_append(, )
	}
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := relToIdx(.Argument(0).ToInteger(), )
	var  int64
	if  := .Argument(1);  != _undefined {
		 = .ToInteger()
	} else {
		 = 
	}
	 = relToIdx(, )

	 :=  - 
	if  < 0 {
		 = 0
	}

	 := arraySpeciesCreate(, )
	if  := .checkStdArrayObj();  != nil {
		if  := .checkStdArrayObjWithProto();  != nil {
			 := make([]Value, )
			copy(, .values[:])
			setArrayValues(, )
			return 
		}
	}

	 := int64(0)
	for  <  {
		 := .self.getIdx(valueInt(), nil)
		if  != nil {
			createDataPropertyOrThrow(, valueInt(), )
		}
		++
		++
	}
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()

	var  func(FunctionCall) Value
	 := .Argument(0)
	if  != _undefined {
		if ,  := .Argument(0).(*Object);  {
			, _ = .self.assertCallable()
		}
		if  == nil {
			panic(.NewTypeError("The comparison function must be either a function or undefined"))
		}
	}

	var  sortable
	if .checkStdArrayObj() != nil {
		 = .self
	} else if ,  := .self.(reflectValueWrapper);  {
		 = .self
	}

	if  != nil {
		 := arraySortCtx{
			obj:     ,
			compare: ,
		}

		sort.Stable(&)
	} else {
		 := toLength(.self.getStr("length", nil))
		 := make([]Value, 0, )
		for  := int64(0);  < ; ++ {
			 := valueInt()
			if .self.hasPropertyIdx() {
				 = append(, nilSafe(.self.getIdx(, nil)))
			}
		}
		 := .newArrayValues()
		 := arraySortCtx{
			obj:     .self,
			compare: ,
		}

		sort.Stable(&)
		for  := 0;  < len(); ++ {
			.self.setOwnIdx(valueInt(), [], true)
		}
		for  := int64(len());  < ; ++ {
			.self.deleteIdx(valueInt(), true)
		}
	}
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := relToIdx(.Argument(0).ToInteger(), )
	var  int64
	switch len(.Arguments) {
	case 0:
	case 1:
		 =  - 
	default:
		 = min(max(.Argument(1).ToInteger(), 0), -)
	}
	 := max(int64(len(.Arguments)-2), 0)
	 :=  -  + 
	if  >= maxInt {
		panic(.NewTypeError("Invalid array length"))
	}
	 := arraySpeciesCreate(, )
	if  := .checkStdArrayObj();  != nil {
		if  := .checkStdArrayObjWithProto();  != nil {
			 := make([]Value, )
			copy(, .values[:])
			setArrayValues(, )
		} else {
			for  := int64(0);  < ; ++ {
				createDataPropertyOrThrow(, intToValue(), .values[+])
			}
			.self.setOwnStr("length", intToValue(), true)
		}
		var  []Value
		if  <  {
			 = .values
			copy([+:], [+:])
			 := [:]
			for  := range  {
				[] = nil
			}
			 = [:]
		} else if  >  {
			if int64(cap(.values)) >=  {
				 = .values[:]
				copy([+:], [+:])
			} else {
				 = make([]Value, )
				copy(, .values[:])
				copy([+:], .values[+:])
			}
		} else {
			 = .values
		}
		if  > 0 {
			copy([:], .Arguments[2:])
		}
		.values = 
		.objCount = len()
	} else {
		for  := int64(0);  < ; ++ {
			 := valueInt( + )
			if .self.hasPropertyIdx() {
				createDataPropertyOrThrow(, valueInt(), nilSafe(.self.getIdx(, nil)))
			}
		}

		if  <  {
			for  := ;  < -; ++ {
				 := valueInt( + )
				 := valueInt( + )
				if .self.hasPropertyIdx() {
					.self.setOwnIdx(, nilSafe(.self.getIdx(, nil)), true)
				} else {
					.self.deleteIdx(, true)
				}
			}

			for  := ;  > -+; -- {
				.self.deleteIdx(valueInt(-1), true)
			}
		} else if  >  {
			for  :=  - ;  > ; -- {
				 := valueInt( +  - 1)
				 := valueInt( +  - 1)
				if .self.hasPropertyIdx() {
					.self.setOwnIdx(, nilSafe(.self.getIdx(, nil)), true)
				} else {
					.self.deleteIdx(, true)
				}
			}
		}

		if  > 0 {
			for ,  := range .Arguments[2:] {
				.self.setOwnIdx(valueInt(+int64()), , true)
			}
		}
	}

	.self.setOwnStr("length", intToValue(), true)

	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := int64(len(.Arguments))
	 := intToValue( + )
	if  > 0 {
		 :=  + 
		if  >= maxInt {
			panic(.NewTypeError("Invalid array length"))
		}
		if  := .checkStdArrayObjWithProto();  != nil &&  < math.MaxUint32 {
			if int64(cap(.values)) >=  {
				.values = .values[:]
				copy(.values[:], .values[:])
			} else {
				 := make([]Value, )
				copy([:], .values)
				.values = 
			}
			copy(.values, .Arguments)
			.objCount = int(.length)
		} else {
			for  :=  - 1;  >= 0; -- {
				 := valueInt()
				 := valueInt( + )
				if .self.hasPropertyIdx() {
					.self.setOwnIdx(, nilSafe(.self.getIdx(, nil)), true)
				} else {
					.self.deleteIdx(, true)
				}
			}

			for ,  := range .Arguments {
				.self.setOwnIdx(valueInt(int64()), , true)
			}
		}
	}

	.self.setOwnStr("length", , true)
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := .Argument(0).ToInteger()
	 := toLength(.self.getStr("length", nil))
	if  < 0 {
		 =  + 
	}
	if  >=  ||  < 0 {
		return _undefined
	}
	 := valueInt()
	if .self.hasPropertyIdx() {
		return .self.getIdx(, nil)
	}
	return _undefined
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	if  == 0 {
		return intToValue(-1)
	}

	 := .Argument(1).ToInteger()
	if  >=  {
		return intToValue(-1)
	}

	if  < 0 {
		 = max(+, 0)
	}

	 := .Argument(0)

	if  := .checkStdArrayObj();  != nil {
		for ,  := range .values[:] {
			if .StrictEquals() {
				return intToValue( + int64())
			}
		}
		return intToValue(-1)
	}

	for ;  < ; ++ {
		 := valueInt()
		if .self.hasPropertyIdx() {
			if  := .self.getIdx(, nil);  != nil {
				if .StrictEquals() {
					return 
				}
			}
		}
	}

	return intToValue(-1)
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	if  == 0 {
		return valueFalse
	}

	 := .Argument(1).ToInteger()
	if  >=  {
		return valueFalse
	}

	if  < 0 {
		 = max(+, 0)
	}

	 := .Argument(0)
	if  == _negativeZero {
		 = _positiveZero
	}

	if  := .checkStdArrayObj();  != nil {
		for ,  := range .values[:] {
			if .SameAs() {
				return valueTrue
			}
		}
		return valueFalse
	}

	for ;  < ; ++ {
		 := valueInt()
		 := nilSafe(.self.getIdx(, nil))
		if .SameAs() {
			return valueTrue
		}
	}

	return valueFalse
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	if  == 0 {
		return intToValue(-1)
	}

	var  int64

	if len(.Arguments) < 2 {
		 =  - 1
	} else {
		 = .Argument(1).ToInteger()
		if  >= 0 {
			 = min(, -1)
		} else {
			 += 
		}
	}

	 := .Argument(0)

	if  := .checkStdArrayObj();  != nil {
		 := .values
		for  := ;  >= 0; -- {
			if  := [];  != nil && .StrictEquals() {
				return intToValue()
			}
		}
		return intToValue(-1)
	}

	for  := ;  >= 0; -- {
		 := valueInt()
		if .self.hasPropertyIdx() {
			if  := .self.getIdx(, nil);  != nil {
				if .StrictEquals() {
					return 
				}
			}
		}
	}

	return intToValue(-1)
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := .toCallable(.Argument(0))
	 := FunctionCall{
		This:      .Argument(1),
		Arguments: []Value{nil, nil, },
	}
	for  := int64(0);  < ; ++ {
		 := valueInt()
		if  := .self.getIdx(, nil);  != nil {
			.Arguments[0] = 
			.Arguments[1] = 
			if !().ToBoolean() {
				return valueFalse
			}
		}
	}
	return valueTrue
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := .toCallable(.Argument(0))
	 := FunctionCall{
		This:      .Argument(1),
		Arguments: []Value{nil, nil, },
	}
	for  := int64(0);  < ; ++ {
		 := valueInt()
		if  := .self.getIdx(, nil);  != nil {
			.Arguments[0] = 
			.Arguments[1] = 
			if ().ToBoolean() {
				return valueTrue
			}
		}
	}
	return valueFalse
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := .toCallable(.Argument(0))
	 := FunctionCall{
		This:      .Argument(1),
		Arguments: []Value{nil, nil, },
	}
	for  := int64(0);  < ; ++ {
		 := valueInt()
		if  := .self.getIdx(, nil);  != nil {
			.Arguments[0] = 
			.Arguments[1] = 
			()
		}
	}
	return _undefined
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := .toCallable(.Argument(0))
	 := FunctionCall{
		This:      .Argument(1),
		Arguments: []Value{nil, nil, },
	}
	 := arraySpeciesCreate(, )
	if ,  := .self.(*arrayObject);  {
		if ,  := .self.(*arrayObject);  {
			 := make([]Value, )
			for  := int64(0);  < ; ++ {
				 := valueInt()
				if  := .self.getIdx(, nil);  != nil {
					.Arguments[0] = 
					.Arguments[1] = 
					[] = ()
				}
			}
			setArrayValues(, )
			return 
		}
	}
	for  := int64(0);  < ; ++ {
		 := valueInt()
		if  := .self.getIdx(, nil);  != nil {
			.Arguments[0] = 
			.Arguments[1] = 
			createDataPropertyOrThrow(, , ())
		}
	}
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := .Argument(0).ToObject()
	if ,  := .self.assertCallable();  {
		 := arraySpeciesCreate(, 0)
		 := FunctionCall{
			This:      .Argument(1),
			Arguments: []Value{nil, nil, },
		}
		if ,  := .self.(*arrayObject);  {
			if  := .checkStdArrayObj();  != nil {
				var  []Value
				for  := int64(0);  < ; ++ {
					 := valueInt()
					if  := .self.getIdx(, nil);  != nil {
						.Arguments[0] = 
						.Arguments[1] = 
						if ().ToBoolean() {
							 = append(, )
						}
					}
				}
				setArrayValues(, )
				return 
			}
		}

		 := int64(0)
		for  := int64(0);  < ; ++ {
			 := valueInt()
			if  := .self.getIdx(, nil);  != nil {
				.Arguments[0] = 
				.Arguments[1] = 
				if ().ToBoolean() {
					createDataPropertyOrThrow(, intToValue(), )
					++
				}
			}
		}
		return 
	} else {
		.typeErrorResult(true, "%s is not a function", .Argument(0))
	}
	panic("unreachable")
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := .Argument(0).ToObject()
	if ,  := .self.assertCallable();  {
		 := FunctionCall{
			This:      _undefined,
			Arguments: []Value{nil, nil, nil, },
		}

		var  int64

		if len(.Arguments) >= 2 {
			.Arguments[0] = .Argument(1)
		} else {
			for ;  < ; ++ {
				 := valueInt()
				if  := .self.getIdx(, nil);  != nil {
					.Arguments[0] = 
					break
				}
			}
			if .Arguments[0] == nil {
				.typeErrorResult(true, "No initial value")
				panic("unreachable")
			}
			++
		}

		for ;  < ; ++ {
			 := valueInt()
			if  := .self.getIdx(, nil);  != nil {
				.Arguments[1] = 
				.Arguments[2] = 
				.Arguments[0] = ()
			}
		}
		return .Arguments[0]
	} else {
		.typeErrorResult(true, "%s is not a function", .Argument(0))
	}
	panic("unreachable")
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := .Argument(0).ToObject()
	if ,  := .self.assertCallable();  {
		 := FunctionCall{
			This:      _undefined,
			Arguments: []Value{nil, nil, nil, },
		}

		 :=  - 1

		if len(.Arguments) >= 2 {
			.Arguments[0] = .Argument(1)
		} else {
			for ;  >= 0; -- {
				 := valueInt()
				if  := .self.getIdx(, nil);  != nil {
					.Arguments[0] = 
					break
				}
			}
			if .Arguments[0] == nil {
				.typeErrorResult(true, "No initial value")
				panic("unreachable")
			}
			--
		}

		for ;  >= 0; -- {
			 := valueInt()
			if  := .self.getIdx(, nil);  != nil {
				.Arguments[1] = 
				.Arguments[2] = 
				.Arguments[0] = ()
			}
		}
		return .Arguments[0]
	} else {
		.typeErrorResult(true, "%s is not a function", .Argument(0))
	}
	panic("unreachable")
}

func arrayproto_reverse_generic_step( *Object, ,  int64) {
	 := valueInt()
	 := valueInt()
	var ,  Value
	 := .self.hasPropertyIdx()
	if  {
		 = nilSafe(.self.getIdx(, nil))
	}
	 := .self.hasPropertyIdx()
	if  {
		 = nilSafe(.self.getIdx(, nil))
	}
	if  &&  {
		.self.setOwnIdx(, , true)
		.self.setOwnIdx(, , true)
	} else if ! &&  {
		.self.setOwnIdx(, , true)
		.self.deleteIdx(, true)
	} else if  && ! {
		.self.deleteIdx(, true)
		.self.setOwnIdx(, , true)
	}
}

func ( *Runtime) ( *Object,  int64) {
	 := toLength(.self.getStr("length", nil))
	 :=  / 2
	for  := ;  != ; ++ {
		arrayproto_reverse_generic_step(, , --1)
	}
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	if  := .checkStdArrayObj();  != nil {
		 := len(.values)
		 :=  / 2
		for  := 0;  != ; ++ {
			 :=  -  - 1
			.values[], .values[] = .values[], .values[]
		}
		//TODO: go arrays
	} else {
		.arrayproto_reverse_generic(, 0)
	}
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	if  := .checkStdArrayObjWithProto();  != nil {
		if len(.values) == 0 {
			if !.lengthProp.writable {
				.setLength(0, true) // will throw
			}
			return _undefined
		}
		 := .values[0]
		copy(.values, .values[1:])
		.values[len(.values)-1] = nil
		.values = .values[:len(.values)-1]
		.length--
		return 
	}
	 := toLength(.self.getStr("length", nil))
	if  == 0 {
		.self.setOwnStr("length", intToValue(0), true)
		return _undefined
	}
	 := .self.getIdx(valueInt(0), nil)
	for  := int64(1);  < ; ++ {
		 := valueInt()
		 := valueInt( - 1)
		if .self.hasPropertyIdx() {
			.self.setOwnIdx(, nilSafe(.self.getIdx(, nil)), true)
		} else {
			.self.deleteIdx(, true)
		}
	}

	 := valueInt( - 1)
	.self.deleteIdx(, true)
	.self.setOwnStr("length", , true)

	return 
}

func ( *Runtime) ( FunctionCall) Value {
	return .createArrayIterator(.This.ToObject(), iterationKindValue)
}

func ( *Runtime) ( FunctionCall) Value {
	return .createArrayIterator(.This.ToObject(), iterationKindKey)
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	var ,  int64
	 := relToIdx(.Argument(0).ToInteger(), )
	 := relToIdx(.Argument(1).ToInteger(), )
	if  := .Argument(2);  != _undefined {
		 = .ToInteger()
	} else {
		 = 
	}
	 := relToIdx(, )
	 := min(-, -)
	if  := .checkStdArrayObj();  != nil {
		if  > 0 {
			copy(.values[:+], .values[:+])
		}
		return 
	}
	if  <  &&  < + {
		 = -1
		 =  +  - 1
		 =  +  - 1
	} else {
		 = 1
	}
	for  > 0 {
		if .self.hasPropertyIdx(valueInt()) {
			.self.setOwnIdx(valueInt(), nilSafe(.self.getIdx(valueInt(), nil)), true)
		} else {
			.self.deleteIdx(valueInt(), true)
		}
		 += 
		 += 
		--
	}

	return 
}

func ( *Runtime) ( FunctionCall) Value {
	return .createArrayIterator(.This.ToObject(), iterationKindKeyValue)
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := relToIdx(.Argument(1).ToInteger(), )
	var  int64
	if  := .Argument(2);  != _undefined {
		 = .ToInteger()
	} else {
		 = 
	}
	 := relToIdx(, )
	 := .Argument(0)
	if  := .checkStdArrayObj();  != nil {
		for ;  < ; ++ {
			.values[] = 
		}
	} else {
		for ;  < ; ++ {
			.self.setOwnIdx(valueInt(), , true)
		}
	}
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := .toCallable(.Argument(0))
	 := FunctionCall{
		This:      .Argument(1),
		Arguments: []Value{nil, nil, },
	}
	for  := int64(0);  < ; ++ {
		 := valueInt()
		 := .self.getIdx(, nil)
		.Arguments[0], .Arguments[1] = , 
		if ().ToBoolean() {
			return 
		}
	}

	return _undefined
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := .toCallable(.Argument(0))
	 := FunctionCall{
		This:      .Argument(1),
		Arguments: []Value{nil, nil, },
	}
	for  := int64(0);  < ; ++ {
		 := valueInt()
		 := .self.getIdx(, nil)
		.Arguments[0], .Arguments[1] = , 
		if ().ToBoolean() {
			return 
		}
	}

	return intToValue(-1)
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := .toCallable(.Argument(0))
	 := FunctionCall{
		This:      .Argument(1),
		Arguments: []Value{nil, nil, },
	}
	for  := int64( - 1);  >= 0; -- {
		 := valueInt()
		 := .self.getIdx(, nil)
		.Arguments[0], .Arguments[1] = , 
		if ().ToBoolean() {
			return 
		}
	}

	return _undefined
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := .toCallable(.Argument(0))
	 := FunctionCall{
		This:      .Argument(1),
		Arguments: []Value{nil, nil, },
	}
	for  := int64( - 1);  >= 0; -- {
		 := valueInt()
		 := .self.getIdx(, nil)
		.Arguments[0], .Arguments[1] = , 
		if ().ToBoolean() {
			return 
		}
	}

	return intToValue(-1)
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := int64(1)
	if len(.Arguments) > 0 {
		 = .Argument(0).ToInteger()
	}
	 := arraySpeciesCreate(, 0)
	.flattenIntoArray(, , , 0, , nil, nil)
	return 
}

func ( *Runtime) (,  *Object, , ,  int64,  func(FunctionCall) Value,  Value) int64 {
	,  := , int64(0)
	for  <  {
		 := intToValue()
		if .hasProperty(.toString()) {
			 := nilSafe(.get(, ))
			if  != nil {
				 = (FunctionCall{
					This:      ,
					Arguments: []Value{, , },
				})
			}
			var  *Object
			if  > 0 {
				if ,  := .(*Object);  && isArray() {
					 = 
				}
			}
			if  != nil {
				 := toLength(.self.getStr("length", nil))
				 = .(, , , , -1, nil, nil)
			} else {
				if  >= maxInt-1 {
					panic(.NewTypeError("Invalid array length"))
				}
				createDataPropertyOrThrow(, intToValue(), )
				++
			}
		}
		++
	}
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := .toCallable(.Argument(0))
	 := Undefined()
	if len(.Arguments) > 1 {
		 = .Argument(1)
	}
	 := arraySpeciesCreate(, 0)
	.flattenIntoArray(, , , 0, 1, , )
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := .Argument(0).ToInteger()
	 := .Argument(1)
	 := toLength(.self.getStr("length", nil))

	 := int64(0)
	if  >= 0 {
		 = 
	} else {
		 =  + 
	}
	if  >=  ||  < 0 {
		panic(.newError(.getRangeError(), "Invalid index %s", .Argument(0).String()))
	}

	if  := .checkStdArrayObj();  != nil {
		 := make([]Value, 0, )
		for  := int64(0);  < ; ++ {
			 := valueInt()
			var  Value
			if  ==  {
				 = 
			} else {
				 = .values[]
			}
			 = append(, )
		}
		return .newArrayValues()
	} else {
		 := .newArrayLength()
		for  := int64(0);  < ; ++ {
			 := valueInt()
			var  Value
			if  ==  {
				 = 
			} else {
				 = .self.getIdx(, nil)
			}
			createDataPropertyOrThrow(, , )
		}
		return 
	}
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))

	if  := .checkStdArrayObj();  != nil {
		 := make([]Value, 0, )
		for  := int64(0);  < ; ++ {
			 := valueInt( -  - 1)
			 := .values[]
			 = append(, )
		}
		return .newArrayValues()
	} else {
		 := .newArrayLength()
		for  := int64(0);  < ; ++ {
			 := valueInt()
			 := valueInt( -  - 1)
			 := .self.getIdx(, nil)
			createDataPropertyOrThrow(, , )
		}
		return 
	}
}

func ( *Runtime) ( FunctionCall) Value {
	var  func(FunctionCall) Value
	 := .Argument(0)
	if  != _undefined {
		if ,  := .(*Object);  {
			, _ = .self.assertCallable()
		}
		if  == nil {
			panic(.NewTypeError("The comparison function must be either a function or undefined"))
		}
	}

	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	if  >= math.MaxUint32 {
		panic(.newError(.getRangeError(), "Invalid array length"))
	}
	var  []Value

	if  := .checkStdArrayObj();  != nil {
		 = make([]Value, )
		copy(, .values)
	} else {
		 = make([]Value, 0, )
		for  := int64(0);  < ; ++ {
			 := valueInt()
			 = append(, nilSafe(.self.getIdx(, nil)))
		}
	}

	 := .newArrayValues()
	 := arraySortCtx{
		obj:     .self,
		compare: ,
	}

	sort.Stable(&)
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .This.ToObject()
	 := toLength(.self.getStr("length", nil))
	 := relToIdx(.Argument(0).ToInteger(), )
	var  int64
	if len(.Arguments) == 1 {
		 =  - 
	} else if len(.Arguments) > 1 {
		 = min(max(.Argument(1).ToInteger(), 0), -)
	}
	 := max(int64(len(.Arguments)-2), 0)
	 :=  -  + 
	if  >= maxInt {
		panic(.NewTypeError("Invalid array length"))
	}

	if  := .checkStdArrayObj();  != nil {
		var  []Value
		if  ==  {
			 = make([]Value, len(.values))
			copy(, .values)
		} else {
			 = make([]Value, )
			copy(, .values[:])
			copy([+:], .values[+:])
		}
		if  > 0 {
			copy([:], .Arguments[2:])
		}
		return .newArrayValues()
	} else {
		 := .newArrayLength()
		var  int64
		 :=  + 

		for  <  {
			 := valueInt()
			 := nilSafe(.self.getIdx(, nil))
			createDataPropertyOrThrow(, , )
			++
		}

		if  > 0 {
			for ,  := range .Arguments[2:] {
				createDataPropertyOrThrow(, valueInt(), nilSafe())
				++
			}
		}

		for  <  {
			 := valueInt()
			 := valueInt()
			 := nilSafe(.self.getIdx(, nil))
			createDataPropertyOrThrow(, , )
			++
			++
		}

		return 
	}
}

func ( *Runtime) ( *Object) *arrayObject {
	if ,  := .self.(*arrayObject);  &&
		.propValueCount == 0 &&
		.length == uint32(len(.values)) &&
		uint32(.objCount) == .length {

		return 
	}

	return nil
}

func ( *Runtime) ( *Object) *arrayObject {
	if  := .checkStdArrayObj();  != nil {
		if ,  := .prototype.self.(*arrayObject);  && .propValueCount == 0 {
			if ,  := .prototype.self.(*baseObject);  && .prototype == nil {
				.ensurePropOrder()
				if .idxPropCount == 0 {
					return 
				}
			}
		}
	}
	return nil
}

func ( *Runtime) ( Value) *arrayObject {
	if ,  := .(*Object);  {
		return .checkStdArrayObj()
	}

	return nil
}

func ( *Runtime) ( Value) *arrayObject {
	if  := .checkStdArray();  != nil &&
		.getSym(SymIterator, nil) == .getArrayValues() {

		return 
	}

	return nil
}

func ( *Runtime) ( FunctionCall) Value {
	var  func(FunctionCall) Value
	if  := .Argument(1);  != _undefined {
		if ,  := .(*Object);  {
			if ,  := .self.assertCallable();  {
				 = 
			}
		}
		if  == nil {
			panic(.NewTypeError("%s is not a function", ))
		}
	}
	 := .Argument(2)
	 := .Argument(0)
	if  == nil && .This == .global.Array { // mapFn may mutate the array
		if  := .checkStdArrayIter();  != nil {
			 := make([]Value, len(.values))
			copy(, .values)
			return .newArrayValues()
		}
	}

	var  func( []Value,  *Object) *Object
	if .This != .global.Array {
		if ,  := .This.(*Object);  {
			if  := .self.assertConstructor();  != nil {
				 = 
			}
		}
	}
	var  *Object
	if  := toMethod(.getV(, SymIterator));  != nil {
		if  != nil {
			 = ([]Value{}, nil)
		} else {
			 = .newArrayValues(nil)
		}
		 := .getIterator(, )
		if  == nil {
			if  := .checkStdArrayObjWithProto();  != nil {
				var  []Value
				.iterate(func( Value) {
					 = append(, )
				})
				setArrayValues(, )
				return 
			}
		}
		 := int64(0)
		.iterate(func( Value) {
			if  != nil {
				 = (FunctionCall{This: , Arguments: []Value{, intToValue()}})
			}
			createDataPropertyOrThrow(, intToValue(), )
			++
		})
		.self.setOwnStr("length", intToValue(), true)
	} else {
		 := .ToObject()
		 := toLength(.self.getStr("length", nil))
		if  != nil {
			 = ([]Value{intToValue()}, nil)
		} else {
			 = .newArrayValues(nil)
		}
		if  == nil {
			if  := .checkStdArrayObjWithProto();  != nil {
				 := make([]Value, )
				for  := int64(0);  < ; ++ {
					[] = nilSafe(.self.getIdx(valueInt(), nil))
				}
				setArrayValues(, )
				return 
			}
		}
		for  := int64(0);  < ; ++ {
			 := valueInt()
			 := .self.getIdx(, nil)
			if  != nil {
				 = (FunctionCall{This: , Arguments: []Value{, }})
			} else {
				 = nilSafe()
			}
			createDataPropertyOrThrow(, , )
		}
		.self.setOwnStr("length", intToValue(), true)
	}

	return 
}

func ( *Runtime) ( FunctionCall) Value {
	if ,  := .Argument(0).(*Object);  {
		if isArray() {
			return valueTrue
		}
	}
	return valueFalse
}

func ( *Runtime) ( FunctionCall) Value {
	var  func( []Value,  *Object) *Object
	if .This != .global.Array {
		if ,  := .This.(*Object);  {
			if  := .self.assertConstructor();  != nil {
				 = 
			}
		}
	}
	if  == nil {
		 := make([]Value, len(.Arguments))
		copy(, .Arguments)
		return .newArrayValues()
	}
	 := intToValue(int64(len(.Arguments)))
	 := ([]Value{}, nil)
	for ,  := range .Arguments {
		createDataPropertyOrThrow(, intToValue(int64()), )
	}
	.self.setOwnStr("length", , true)
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .toObject(.This)
	if ,  := .self.(*arrayIterObject);  {
		return .next()
	}
	panic(.NewTypeError("Method Array Iterator.prototype.next called on incompatible receiver %s", .objectproto_toString(FunctionCall{This: })))
}

func createArrayProtoTemplate() *objectTemplate {
	 := newObjectTemplate()
	.protoFactory = func( *Runtime) *Object {
		return .global.ObjectPrototype
	}

	.putStr("length", func( *Runtime) Value { return valueProp(_positiveZero, true, false, false) })

	.putStr("constructor", func( *Runtime) Value { return valueProp(.getArray(), true, false, true) })

	.putStr("at", func( *Runtime) Value { return .methodProp(.arrayproto_at, "at", 1) })
	.putStr("concat", func( *Runtime) Value { return .methodProp(.arrayproto_concat, "concat", 1) })
	.putStr("copyWithin", func( *Runtime) Value { return .methodProp(.arrayproto_copyWithin, "copyWithin", 2) })
	.putStr("entries", func( *Runtime) Value { return .methodProp(.arrayproto_entries, "entries", 0) })
	.putStr("every", func( *Runtime) Value { return .methodProp(.arrayproto_every, "every", 1) })
	.putStr("fill", func( *Runtime) Value { return .methodProp(.arrayproto_fill, "fill", 1) })
	.putStr("filter", func( *Runtime) Value { return .methodProp(.arrayproto_filter, "filter", 1) })
	.putStr("find", func( *Runtime) Value { return .methodProp(.arrayproto_find, "find", 1) })
	.putStr("findIndex", func( *Runtime) Value { return .methodProp(.arrayproto_findIndex, "findIndex", 1) })
	.putStr("findLast", func( *Runtime) Value { return .methodProp(.arrayproto_findLast, "findLast", 1) })
	.putStr("findLastIndex", func( *Runtime) Value { return .methodProp(.arrayproto_findLastIndex, "findLastIndex", 1) })
	.putStr("flat", func( *Runtime) Value { return .methodProp(.arrayproto_flat, "flat", 0) })
	.putStr("flatMap", func( *Runtime) Value { return .methodProp(.arrayproto_flatMap, "flatMap", 1) })
	.putStr("forEach", func( *Runtime) Value { return .methodProp(.arrayproto_forEach, "forEach", 1) })
	.putStr("includes", func( *Runtime) Value { return .methodProp(.arrayproto_includes, "includes", 1) })
	.putStr("indexOf", func( *Runtime) Value { return .methodProp(.arrayproto_indexOf, "indexOf", 1) })
	.putStr("join", func( *Runtime) Value { return .methodProp(.arrayproto_join, "join", 1) })
	.putStr("keys", func( *Runtime) Value { return .methodProp(.arrayproto_keys, "keys", 0) })
	.putStr("lastIndexOf", func( *Runtime) Value { return .methodProp(.arrayproto_lastIndexOf, "lastIndexOf", 1) })
	.putStr("map", func( *Runtime) Value { return .methodProp(.arrayproto_map, "map", 1) })
	.putStr("pop", func( *Runtime) Value { return .methodProp(.arrayproto_pop, "pop", 0) })
	.putStr("push", func( *Runtime) Value { return .methodProp(.arrayproto_push, "push", 1) })
	.putStr("reduce", func( *Runtime) Value { return .methodProp(.arrayproto_reduce, "reduce", 1) })
	.putStr("reduceRight", func( *Runtime) Value { return .methodProp(.arrayproto_reduceRight, "reduceRight", 1) })
	.putStr("reverse", func( *Runtime) Value { return .methodProp(.arrayproto_reverse, "reverse", 0) })
	.putStr("shift", func( *Runtime) Value { return .methodProp(.arrayproto_shift, "shift", 0) })
	.putStr("slice", func( *Runtime) Value { return .methodProp(.arrayproto_slice, "slice", 2) })
	.putStr("some", func( *Runtime) Value { return .methodProp(.arrayproto_some, "some", 1) })
	.putStr("sort", func( *Runtime) Value { return .methodProp(.arrayproto_sort, "sort", 1) })
	.putStr("splice", func( *Runtime) Value { return .methodProp(.arrayproto_splice, "splice", 2) })
	.putStr("toLocaleString", func( *Runtime) Value { return .methodProp(.arrayproto_toLocaleString, "toLocaleString", 0) })
	.putStr("toString", func( *Runtime) Value { return valueProp(.getArrayToString(), true, false, true) })
	.putStr("unshift", func( *Runtime) Value { return .methodProp(.arrayproto_unshift, "unshift", 1) })
	.putStr("with", func( *Runtime) Value { return .methodProp(.arrayproto_with, "with", 2) })
	.putStr("toReversed", func( *Runtime) Value { return .methodProp(.arrayproto_toReversed, "toReversed", 0) })
	.putStr("toSorted", func( *Runtime) Value { return .methodProp(.arrayproto_toSorted, "toSorted", 1) })
	.putStr("toSpliced", func( *Runtime) Value { return .methodProp(.arrayproto_toSpliced, "toSpliced", 2) })
	.putStr("values", func( *Runtime) Value { return valueProp(.getArrayValues(), true, false, true) })

	.putSym(SymIterator, func( *Runtime) Value { return valueProp(.getArrayValues(), true, false, true) })
	.putSym(SymUnscopables, func( *Runtime) Value {
		 := .newBaseObject(nil, classObject)
		.setOwnStr("copyWithin", valueTrue, true)
		.setOwnStr("entries", valueTrue, true)
		.setOwnStr("fill", valueTrue, true)
		.setOwnStr("find", valueTrue, true)
		.setOwnStr("findIndex", valueTrue, true)
		.setOwnStr("findLast", valueTrue, true)
		.setOwnStr("findLastIndex", valueTrue, true)
		.setOwnStr("flat", valueTrue, true)
		.setOwnStr("flatMap", valueTrue, true)
		.setOwnStr("includes", valueTrue, true)
		.setOwnStr("keys", valueTrue, true)
		.setOwnStr("values", valueTrue, true)
		.setOwnStr("groupBy", valueTrue, true)
		.setOwnStr("groupByToMap", valueTrue, true)
		.setOwnStr("toReversed", valueTrue, true)
		.setOwnStr("toSorted", valueTrue, true)
		.setOwnStr("toSpliced", valueTrue, true)

		return valueProp(.val, false, false, true)
	})

	return 
}

var arrayProtoTemplate *objectTemplate
var arrayProtoTemplateOnce sync.Once

func getArrayProtoTemplate() *objectTemplate {
	arrayProtoTemplateOnce.Do(func() {
		arrayProtoTemplate = createArrayProtoTemplate()
	})
	return arrayProtoTemplate
}

func ( *Runtime) () *Object {
	 := .global.ArrayPrototype
	if  == nil {
		 = &Object{runtime: }
		.global.ArrayPrototype = 
		.newTemplatedArrayObject(getArrayProtoTemplate(), )
	}
	return 
}

func ( *Runtime) () *Object {
	 := .global.Array
	if  == nil {
		 = &Object{runtime: }
		.self = .createArray()
		.global.Array = 
	}
	return 
}

func ( *Runtime) ( *Object) objectImpl {
	 := .newNativeFuncConstructObj(, .builtin_newArray, "Array", .getArrayPrototype(), 1)
	._putProp("from", .newNativeFunc(.array_from, "from", 1), true, false, true)
	._putProp("isArray", .newNativeFunc(.array_isArray, "isArray", 1), true, false, true)
	._putProp("of", .newNativeFunc(.array_of, "of", 0), true, false, true)
	.putSpeciesReturnThis()

	return 
}

func ( *Runtime) ( *Object) objectImpl {
	 := newBaseObjectObj(, .getIteratorPrototype(), classObject)

	._putProp("next", .newNativeFunc(.arrayIterProto_next, "next", 0), true, false, true)
	._putSym(SymToStringTag, valueProp(asciiString(classArrayIterator), false, false, true))

	return 
}

func ( *Runtime) () *Object {
	 := .global.arrayValues
	if  == nil {
		 = .newNativeFunc(.arrayproto_values, "values", 0)
		.global.arrayValues = 
	}
	return 
}

func ( *Runtime) () *Object {
	 := .global.arrayToString
	if  == nil {
		 = .newNativeFunc(.arrayproto_toString, "toString", 0)
		.global.arrayToString = 
	}
	return 
}

func ( *Runtime) () *Object {
	var  *Object
	if  = .global.ArrayIteratorPrototype;  == nil {
		 = &Object{runtime: }
		.global.ArrayIteratorPrototype = 
		.self = .createArrayIterProto()
	}
	return 

}

type sortable interface {
	sortLen() int
	sortGet(int) Value
	swap(int, int)
}

type arraySortCtx struct {
	obj     sortable
	compare func(FunctionCall) Value
}

func ( *arraySortCtx) (,  Value) int {
	if  == nil &&  == nil {
		return 0
	}

	if  == nil {
		return 1
	}

	if  == nil {
		return -1
	}

	if  == _undefined &&  == _undefined {
		return 0
	}

	if  == _undefined {
		return 1
	}

	if  == _undefined {
		return -1
	}

	if .compare != nil {
		 := .compare(FunctionCall{
			This:      _undefined,
			Arguments: []Value{, },
		}).ToFloat()
		if  > 0 {
			return 1
		}
		if  < 0 {
			return -1
		}
		if math.Signbit() {
			return -1
		}
		return 0
	}
	return .toString().CompareTo(.toString())
}

// sort.Interface

func ( *arraySortCtx) () int {
	return .obj.sortLen()
}

func ( *arraySortCtx) (,  int) bool {
	return .sortCompare(.obj.sortGet(), .obj.sortGet()) < 0
}

func ( *arraySortCtx) (,  int) {
	.obj.swap(, )
}