package goja

import (
	
	
)

func ( *Runtime) ( []Value,  *Object, ,  bool) *Object {
	var  StringBuilder
	if  {
		if  {
			.WriteString(asciiString("(async function* anonymous("))
		} else {
			.WriteString(asciiString("(async function anonymous("))
		}
	} else {
		if  {
			.WriteString(asciiString("(function* anonymous("))
		} else {
			.WriteString(asciiString("(function anonymous("))
		}
	}
	if len() > 1 {
		 := [:len()-1]
		for ,  := range  {
			.WriteString(.toString())
			if  < len()-1 {
				.WriteRune(',')
			}
		}
	}
	.WriteString(asciiString("\n) {\n"))
	if len() > 0 {
		.WriteString([len()-1].toString())
	}
	.WriteString(asciiString("\n})"))

	 := .toObject(.eval(.String(), false, false))
	.self.setProto(, true)
	return 
}

func ( *Runtime) ( []Value,  *Object) *Object {
	return .functionCtor(, , false, false)
}

func ( *Runtime) ( []Value,  *Object) *Object {
	return .functionCtor(, , true, false)
}

func ( *Runtime) ( []Value,  *Object) *Object {
	return .functionCtor(, , false, true)
}

func ( *Runtime) ( FunctionCall) Value {
	 := .toObject(.This)
	switch f := .self.(type) {
	case funcObjectImpl:
		return .source()
	case *proxyObject:
		if ,  := .target.self.(funcObjectImpl);  {
			return asciiString("function () { [native code] }")
		}
	}
	panic(.NewTypeError("Function.prototype.toString requires that 'this' be a Function"))
}

func ( *Runtime) ( FunctionCall) Value {
	if ,  := .This.(*Object);  {
		if _,  = .self.assertCallable();  {
			return .toBoolean(.self.hasInstance(.Argument(0)))
		}
	}

	return valueFalse
}

func ( *Runtime) ( Value) []Value {
	 := .toObject()
	if  := .checkStdArrayObj();  != nil {
		return .values
	}
	 := toLength(.self.getStr("length", nil))
	 := make([]Value, 0, )
	for  := int64(0);  < ; ++ {
		 = append(, nilSafe(.self.getIdx(valueInt(), nil)))
	}
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	var  []Value
	if len(.Arguments) >= 2 {
		 = .createListFromArrayLike(.Arguments[1])
	}

	 := .toCallable(.This)
	return (FunctionCall{
		This:      .Argument(0),
		Arguments: ,
	})
}

func ( *Runtime) ( FunctionCall) Value {
	var  []Value
	if len(.Arguments) > 0 {
		 = .Arguments[1:]
	}

	 := .toCallable(.This)
	return (FunctionCall{
		This:      .Argument(0),
		Arguments: ,
	})
}

func ( *Runtime) ( func(FunctionCall) Value,  []Value) func(FunctionCall) Value {
	var  Value
	var  []Value
	if len() > 0 {
		 = [0]
		 = make([]Value, len()-1)
		copy(, [1:])
	} else {
		 = _undefined
	}
	return func( FunctionCall) Value {
		 := append(, .Arguments...)
		return (FunctionCall{
			This:      ,
			Arguments: ,
		})
	}
}

func ( *Runtime) ( *Object,  func([]Value, *Object) *Object,  []Value) func([]Value, *Object) *Object {
	if  == nil {
		return nil
	}
	var  []Value
	if len() > 1 {
		 = make([]Value, len()-1)
		copy(, [1:])
	}
	return func( []Value,  *Object) *Object {
		 := append(, ...)
		if  ==  {
			 = nil
		}
		return (, )
	}
}

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

	 := .toCallable(.This)
	 := .self.assertConstructor()

	var  = _positiveZero
	if .self.hasOwnPropertyStr("length") {
		var  int64
		switch lenProp := nilSafe(.self.getStr("length", nil)).(type) {
		case valueInt:
			 = .ToInteger()
		case valueFloat:
			switch  {
			case _positiveInf:
				 = 
				goto 
			case _negativeInf:
				goto 
			case _negativeZero:
				// no-op, li == 0
			default:
				if !math.IsNaN(float64()) {
					 = int64(math.Abs(float64()))
				} // else li = 0
			}
		}
		if len(.Arguments) > 1 {
			 -= int64(len(.Arguments)) - 1
		}
		if  < 0 {
			 = 0
		}
		 = intToValue()
	}
:
	 := .self.getStr("name", nil)
	 := stringBound_
	if ,  := .(String);  {
		 = .Concat()
	}

	 := &Object{runtime: }
	 := .newNativeFuncAndConstruct(, .boundCallable(, .Arguments), .boundConstruct(, , .Arguments), nil, .string(), )
	 := &boundFuncObject{
		nativeFuncObject: *,
		wrapped:          ,
	}
	.prototype = .self.proto()
	.self = 

	return 
}

func ( *Runtime) () *Object {
	 := .global.thrower
	if  == nil {
		 = .newNativeFunc(.builtin_thrower, "", 0)
		.global.thrower = 
		.object_freeze(FunctionCall{Arguments: []Value{}})
	}
	return 
}

func ( *Runtime) ( bool) Value {
	 := .getThrower()
	return &valueProperty{
		getterFunc:   ,
		setterFunc:   ,
		accessor:     true,
		configurable: ,
	}
}

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

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

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

	.putStr("apply", func( *Runtime) Value { return .methodProp(.functionproto_apply, "apply", 2) })
	.putStr("bind", func( *Runtime) Value { return .methodProp(.functionproto_bind, "bind", 1) })
	.putStr("call", func( *Runtime) Value { return .methodProp(.functionproto_call, "call", 1) })
	.putStr("toString", func( *Runtime) Value { return .methodProp(.functionproto_toString, "toString", 0) })

	.putStr("caller", func( *Runtime) Value { return .newThrowerProperty(true) })
	.putStr("arguments", func( *Runtime) Value { return .newThrowerProperty(true) })

	.putSym(SymHasInstance, func( *Runtime) Value {
		return valueProp(.newNativeFunc(.functionproto_hasInstance, "[Symbol.hasInstance]", 1), false, false, false)
	})

	return 
}

var functionProtoTemplate *objectTemplate
var functionProtoTemplateOnce sync.Once

func getFunctionProtoTemplate() *objectTemplate {
	functionProtoTemplateOnce.Do(func() {
		functionProtoTemplate = createFunctionProtoTemplate()
	})
	return functionProtoTemplate
}

func ( *Runtime) () *Object {
	 := .global.FunctionPrototype
	if  == nil {
		 = &Object{runtime: }
		.global.FunctionPrototype = 
		.newTemplatedFuncObject(getFunctionProtoTemplate(), , func(FunctionCall) Value {
			return _undefined
		}, nil)
	}
	return 
}

func ( *Runtime) ( *Object) objectImpl {
	return .newNativeFuncConstructObj(, .builtin_Function, "Function", .getFunctionPrototype(), 1)
}

func ( *Runtime) ( *Object) objectImpl {
	 := &baseObject{
		class:      classObject,
		val:        ,
		extensible: true,
		prototype:  .getFunctionPrototype(),
	}
	.init()

	._putProp("constructor", .getAsyncFunction(), true, false, true)

	._putSym(SymToStringTag, valueProp(asciiString(classAsyncFunction), false, false, true))

	return 
}

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

func ( *Runtime) ( *Object) objectImpl {
	 := .newNativeFuncConstructObj(, .builtin_asyncFunction, "AsyncFunction", .getAsyncFunctionPrototype(), 1)

	return 
}

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

func ( *Runtime) ( FunctionCall) Value {
	if ,  := .This.(*Object);  {
		if ,  := .self.(*generatorObject);  {
			return .next(.Argument(0))
		}
	}
	panic(.NewTypeError("Method [Generator].prototype.next called on incompatible receiver"))
}

func ( *Runtime) ( FunctionCall) Value {
	if ,  := .This.(*Object);  {
		if ,  := .self.(*generatorObject);  {
			return ._return(.Argument(0))
		}
	}
	panic(.NewTypeError("Method [Generator].prototype.return called on incompatible receiver"))
}

func ( *Runtime) ( FunctionCall) Value {
	if ,  := .This.(*Object);  {
		if ,  := .self.(*generatorObject);  {
			return .throw(.Argument(0))
		}
	}
	panic(.NewTypeError("Method [Generator].prototype.throw called on incompatible receiver"))
}

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

	._putProp("constructor", .getGeneratorFunction(), false, false, true)
	._putProp("prototype", .getGeneratorPrototype(), false, false, true)
	._putSym(SymToStringTag, valueProp(asciiString(classGeneratorFunction), false, false, true))

	return 
}

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

func ( *Runtime) ( *Object) objectImpl {
	 := .newNativeFuncConstructObj(, .builtin_generatorFunction, "GeneratorFunction", .getGeneratorFunctionPrototype(), 1)
	return 
}

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

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

	._putProp("constructor", .getGeneratorFunctionPrototype(), false, false, true)
	._putProp("next", .newNativeFunc(.builtin_genproto_next, "next", 1), true, false, true)
	._putProp("return", .newNativeFunc(.builtin_genproto_return, "return", 1), true, false, true)
	._putProp("throw", .newNativeFunc(.builtin_genproto_throw, "throw", 1), true, false, true)

	._putSym(SymToStringTag, valueProp(asciiString(classGenerator), false, false, true))

	return 
}

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

func ( *Runtime) () *Object {
	 := .global.Function
	if  == nil {
		 = &Object{runtime: }
		.global.Function = 
		.self = .createFunction()
	}

	return 
}