package goja

import (
	
	

	
)

// Proxy is a Go wrapper around ECMAScript Proxy. Calling Runtime.ToValue() on it
// returns the underlying Proxy. Calling Export() on an ECMAScript Proxy returns a wrapper.
// Use Runtime.NewProxy() to create one.
type Proxy struct {
	proxy *proxyObject
}

var (
	proxyType = reflect.TypeOf(Proxy{})
)

type proxyPropIter struct {
	p     *proxyObject
	names []Value
	idx   int
}

func ( *proxyPropIter) () (propIterItem, iterNextFunc) {
	for .idx < len(.names) {
		 := .names[.idx]
		.idx++
		return propIterItem{name: }, .
	}
	return propIterItem{}, nil
}

func ( *Runtime) (, ,  *Object) *proxyObject {
	return ._newProxyObject(, &jsProxyHandler{handler: }, )
}

func ( *Runtime) ( *Object,  proxyHandler,  *Object) *proxyObject {
	 := &Object{runtime: }
	 := &proxyObject{}
	.self = 
	.val = 
	.class = classObject
	if  == nil {
		.prototype = .global.ObjectPrototype
	} else {
		.prototype = 
	}
	.extensible = false
	.init()
	.target = 
	.handler = 
	if ,  := .self.assertCallable();  {
		.call = 
	}
	if  := .self.assertConstructor();  != nil {
		.ctor = 
	}
	return 
}

func ( Proxy) () {
	.proxy.revoke()
}

func ( Proxy) () *Object {
	if  := .proxy.handler;  != nil {
		return .toObject(.proxy.val.runtime)
	}
	return nil
}

func ( Proxy) () *Object {
	return .proxy.target
}

func ( Proxy) ( *Runtime) Value {
	if .proxy == nil {
		return _null
	}
	 := .proxy.val
	if .runtime !=  {
		panic(.NewTypeError("Illegal runtime transition of a Proxy"))
	}
	return 
}

type proxyTrap string

const (
	proxy_trap_getPrototypeOf           = "getPrototypeOf"
	proxy_trap_setPrototypeOf           = "setPrototypeOf"
	proxy_trap_isExtensible             = "isExtensible"
	proxy_trap_preventExtensions        = "preventExtensions"
	proxy_trap_getOwnPropertyDescriptor = "getOwnPropertyDescriptor"
	proxy_trap_defineProperty           = "defineProperty"
	proxy_trap_has                      = "has"
	proxy_trap_get                      = "get"
	proxy_trap_set                      = "set"
	proxy_trap_deleteProperty           = "deleteProperty"
	proxy_trap_ownKeys                  = "ownKeys"
	proxy_trap_apply                    = "apply"
	proxy_trap_construct                = "construct"
)

func ( proxyTrap) () ( string) {
	return string()
}

type proxyHandler interface {
	getPrototypeOf(target *Object) (Value, bool)
	setPrototypeOf(target *Object, proto *Object) (bool, bool)
	isExtensible(target *Object) (bool, bool)
	preventExtensions(target *Object) (bool, bool)

	getOwnPropertyDescriptorStr(target *Object, prop unistring.String) (Value, bool)
	getOwnPropertyDescriptorIdx(target *Object, prop valueInt) (Value, bool)
	getOwnPropertyDescriptorSym(target *Object, prop *Symbol) (Value, bool)

	definePropertyStr(target *Object, prop unistring.String, desc PropertyDescriptor) (bool, bool)
	definePropertyIdx(target *Object, prop valueInt, desc PropertyDescriptor) (bool, bool)
	definePropertySym(target *Object, prop *Symbol, desc PropertyDescriptor) (bool, bool)

	hasStr(target *Object, prop unistring.String) (bool, bool)
	hasIdx(target *Object, prop valueInt) (bool, bool)
	hasSym(target *Object, prop *Symbol) (bool, bool)

	getStr(target *Object, prop unistring.String, receiver Value) (Value, bool)
	getIdx(target *Object, prop valueInt, receiver Value) (Value, bool)
	getSym(target *Object, prop *Symbol, receiver Value) (Value, bool)

	setStr(target *Object, prop unistring.String, value Value, receiver Value) (bool, bool)
	setIdx(target *Object, prop valueInt, value Value, receiver Value) (bool, bool)
	setSym(target *Object, prop *Symbol, value Value, receiver Value) (bool, bool)

	deleteStr(target *Object, prop unistring.String) (bool, bool)
	deleteIdx(target *Object, prop valueInt) (bool, bool)
	deleteSym(target *Object, prop *Symbol) (bool, bool)

	ownKeys(target *Object) (*Object, bool)
	apply(target *Object, this Value, args []Value) (Value, bool)
	construct(target *Object, args []Value, newTarget *Object) (Value, bool)

	toObject(*Runtime) *Object
}

type jsProxyHandler struct {
	handler *Object
}

func ( *jsProxyHandler) (*Runtime) *Object {
	return .handler
}

func ( *jsProxyHandler) ( proxyTrap,  ...Value) (Value, bool) {
	 := .handler.runtime

	if  := toMethod(.getVStr(.handler, unistring.String(.String())));  != nil {
		return (FunctionCall{
			This:      .handler,
			Arguments: ,
		}), true
	}

	return nil, false
}

func ( *jsProxyHandler) ( proxyTrap,  ...Value) (bool, bool) {
	if ,  := .proxyCall(, ...);  {
		return .ToBoolean(), true
	}
	return false, false
}

func ( *jsProxyHandler) ( *Object) (Value, bool) {
	return .proxyCall(proxy_trap_getPrototypeOf, )
}

func ( *jsProxyHandler) ( *Object,  *Object) (bool, bool) {
	var  Value
	if  != nil {
		 = 
	} else {
		 = _null
	}
	return .boolProxyCall(proxy_trap_setPrototypeOf, , )
}

func ( *jsProxyHandler) ( *Object) (bool, bool) {
	return .boolProxyCall(proxy_trap_isExtensible, )
}

func ( *jsProxyHandler) ( *Object) (bool, bool) {
	return .boolProxyCall(proxy_trap_preventExtensions, )
}

func ( *jsProxyHandler) ( *Object,  unistring.String) (Value, bool) {
	return .proxyCall(proxy_trap_getOwnPropertyDescriptor, , stringValueFromRaw())
}

func ( *jsProxyHandler) ( *Object,  valueInt) (Value, bool) {
	return .proxyCall(proxy_trap_getOwnPropertyDescriptor, , .toString())
}

func ( *jsProxyHandler) ( *Object,  *Symbol) (Value, bool) {
	return .proxyCall(proxy_trap_getOwnPropertyDescriptor, , )
}

func ( *jsProxyHandler) ( *Object,  unistring.String,  PropertyDescriptor) (bool, bool) {
	return .boolProxyCall(proxy_trap_defineProperty, , stringValueFromRaw(), .toValue(.handler.runtime))
}

func ( *jsProxyHandler) ( *Object,  valueInt,  PropertyDescriptor) (bool, bool) {
	return .boolProxyCall(proxy_trap_defineProperty, , .toString(), .toValue(.handler.runtime))
}

func ( *jsProxyHandler) ( *Object,  *Symbol,  PropertyDescriptor) (bool, bool) {
	return .boolProxyCall(proxy_trap_defineProperty, , , .toValue(.handler.runtime))
}

func ( *jsProxyHandler) ( *Object,  unistring.String) (bool, bool) {
	return .boolProxyCall(proxy_trap_has, , stringValueFromRaw())
}

func ( *jsProxyHandler) ( *Object,  valueInt) (bool, bool) {
	return .boolProxyCall(proxy_trap_has, , .toString())
}

func ( *jsProxyHandler) ( *Object,  *Symbol) (bool, bool) {
	return .boolProxyCall(proxy_trap_has, , )
}

func ( *jsProxyHandler) ( *Object,  unistring.String,  Value) (Value, bool) {
	return .proxyCall(proxy_trap_get, , stringValueFromRaw(), )
}

func ( *jsProxyHandler) ( *Object,  valueInt,  Value) (Value, bool) {
	return .proxyCall(proxy_trap_get, , .toString(), )
}

func ( *jsProxyHandler) ( *Object,  *Symbol,  Value) (Value, bool) {
	return .proxyCall(proxy_trap_get, , , )
}

func ( *jsProxyHandler) ( *Object,  unistring.String,  Value,  Value) (bool, bool) {
	return .boolProxyCall(proxy_trap_set, , stringValueFromRaw(), , )
}

func ( *jsProxyHandler) ( *Object,  valueInt,  Value,  Value) (bool, bool) {
	return .boolProxyCall(proxy_trap_set, , .toString(), , )
}

func ( *jsProxyHandler) ( *Object,  *Symbol,  Value,  Value) (bool, bool) {
	return .boolProxyCall(proxy_trap_set, , , , )
}

func ( *jsProxyHandler) ( *Object,  unistring.String) (bool, bool) {
	return .boolProxyCall(proxy_trap_deleteProperty, , stringValueFromRaw())
}

func ( *jsProxyHandler) ( *Object,  valueInt) (bool, bool) {
	return .boolProxyCall(proxy_trap_deleteProperty, , .toString())
}

func ( *jsProxyHandler) ( *Object,  *Symbol) (bool, bool) {
	return .boolProxyCall(proxy_trap_deleteProperty, , )
}

func ( *jsProxyHandler) ( *Object) (*Object, bool) {
	if ,  := .proxyCall(proxy_trap_ownKeys, );  {
		return .handler.runtime.toObject(), true
	}
	return nil, false
}

func ( *jsProxyHandler) ( *Object,  Value,  []Value) (Value, bool) {
	return .proxyCall(proxy_trap_apply, , , .handler.runtime.newArrayValues())
}

func ( *jsProxyHandler) ( *Object,  []Value,  *Object) (Value, bool) {
	return .proxyCall(proxy_trap_construct, , .handler.runtime.newArrayValues(), )
}

type proxyObject struct {
	baseObject
	target  *Object
	handler proxyHandler
	call    func(FunctionCall) Value
	ctor    func(args []Value, newTarget *Object) *Object
}

func ( *proxyObject) () proxyHandler {
	 := .val.runtime
	if  := .handler;  != nil {
		return 
	}
	panic(.NewTypeError("Proxy already revoked"))
}

func ( *proxyObject) () *Object {
	 := .target
	if ,  := .checkHandler().getPrototypeOf();  {
		var  *Object
		if  != _null {
			 = .val.runtime.toObject()
		}
		if !.self.isExtensible() && !.__sameValue(, .self.proto()) {
			panic(.val.runtime.NewTypeError("'getPrototypeOf' on proxy: proxy target is non-extensible but the trap did not return its actual prototype"))
		}
		return 
	}

	return .self.proto()
}

func ( *proxyObject) ( *Object,  bool) bool {
	 := .target
	if ,  := .checkHandler().setPrototypeOf(, );  {
		if  {
			if !.self.isExtensible() && !.__sameValue(, .self.proto()) {
				panic(.val.runtime.NewTypeError("'setPrototypeOf' on proxy: trap returned truish for setting a new prototype on the non-extensible proxy target"))
			}
			return true
		} else {
			.val.runtime.typeErrorResult(, "'setPrototypeOf' on proxy: trap returned falsish")
			return false
		}
	}

	return .self.setProto(, )
}

func ( *proxyObject) () bool {
	 := .target
	if ,  := .checkHandler().isExtensible(.target);  {
		if  := .self.isExtensible();  !=  {
			panic(.val.runtime.NewTypeError("'isExtensible' on proxy: trap result does not reflect extensibility of proxy target (which is '%v')", ))
		}
		return 
	}

	return .self.isExtensible()
}

func ( *proxyObject) ( bool) bool {
	 := .target
	if ,  := .checkHandler().preventExtensions();  {
		if ! {
			.val.runtime.typeErrorResult(, "'preventExtensions' on proxy: trap returned falsish")
			return false
		}
		if  := .self.isExtensible();  &&  {
			panic(.val.runtime.NewTypeError("'preventExtensions' on proxy: trap returned truish but the proxy target is extensible"))
		}
	}

	return .self.preventExtensions()
}

func propToValueProp( Value) *valueProperty {
	if  == nil {
		return nil
	}
	if ,  := .(*valueProperty);  {
		return 
	}
	return &valueProperty{
		value:        ,
		writable:     true,
		configurable: true,
		enumerable:   true,
	}
}

func ( *proxyObject) (,  bool) bool {
	if ! {
		.val.runtime.typeErrorResult(, "'defineProperty' on proxy: trap returned falsish")
		return false
	}
	return true
}

func ( *proxyObject) ( Value,  *Object,  PropertyDescriptor) {
	 := propToValueProp()
	 := .self.isExtensible()
	 := .Configurable == FLAG_FALSE
	if  == nil {
		if ! {
			panic(.val.runtime.NewTypeError())
		}
		if  {
			panic(.val.runtime.NewTypeError())
		}
	} else {
		if !.__isCompatibleDescriptor(, &, ) {
			panic(.val.runtime.NewTypeError())
		}
		if  && .configurable {
			panic(.val.runtime.NewTypeError())
		}
		if .value != nil && !.configurable && .writable {
			if .Writable == FLAG_FALSE {
				panic(.val.runtime.NewTypeError())
			}
		}
	}
}

func ( *proxyObject) ( unistring.String,  PropertyDescriptor,  bool) bool {
	 := .target
	if ,  := .checkHandler().definePropertyStr(, , );  {
		if !.proxyDefineOwnPropertyPreCheck(, ) {
			return false
		}
		.proxyDefineOwnPropertyPostCheck(.self.getOwnPropStr(), , )
		return true
	}
	return .self.defineOwnPropertyStr(, , )
}

func ( *proxyObject) ( valueInt,  PropertyDescriptor,  bool) bool {
	 := .target
	if ,  := .checkHandler().definePropertyIdx(, , );  {
		if !.proxyDefineOwnPropertyPreCheck(, ) {
			return false
		}
		.proxyDefineOwnPropertyPostCheck(.self.getOwnPropIdx(), , )
		return true
	}

	return .self.defineOwnPropertyIdx(, , )
}

func ( *proxyObject) ( *Symbol,  PropertyDescriptor,  bool) bool {
	 := .target
	if ,  := .checkHandler().definePropertySym(, , );  {
		if !.proxyDefineOwnPropertyPreCheck(, ) {
			return false
		}
		.proxyDefineOwnPropertyPostCheck(.self.getOwnPropSym(), , )
		return true
	}

	return .self.defineOwnPropertySym(, , )
}

func ( *proxyObject) ( Value,  *Object,  fmt.Stringer) {
	 := propToValueProp()
	if  != nil {
		if !.configurable {
			panic(.val.runtime.NewTypeError("'has' on proxy: trap returned falsish for property '%s' which exists in the proxy target as non-configurable", .String()))
		}
		if !.self.isExtensible() {
			panic(.val.runtime.NewTypeError("'has' on proxy: trap returned falsish for property '%s' but the proxy target is not extensible", .String()))
		}
	}
}

func ( *proxyObject) ( unistring.String) bool {
	 := .target
	if ,  := .checkHandler().hasStr(, );  {
		if ! {
			.proxyHasChecks(.self.getOwnPropStr(), , )
		}
		return 
	}

	return .self.hasPropertyStr()
}

func ( *proxyObject) ( valueInt) bool {
	 := .target
	if ,  := .checkHandler().hasIdx(, );  {
		if ! {
			.proxyHasChecks(.self.getOwnPropIdx(), , )
		}
		return 
	}

	return .self.hasPropertyIdx()
}

func ( *proxyObject) ( *Symbol) bool {
	 := .target
	if ,  := .checkHandler().hasSym(, );  {
		if ! {
			.proxyHasChecks(.self.getOwnPropSym(), , )
		}
		return 
	}

	return .self.hasPropertySym()
}

func ( *proxyObject) ( unistring.String) bool {
	return .getOwnPropStr() != nil
}

func ( *proxyObject) ( valueInt) bool {
	return .getOwnPropIdx() != nil
}

func ( *proxyObject) ( *Symbol) bool {
	return .getOwnPropSym() != nil
}

func ( *proxyObject) ( Value,  *Object,  Value,  fmt.Stringer) Value {
	 := .val.runtime
	 := propToValueProp()
	var  *Object
	if  != nil &&  != _undefined {
		if ,  := .(*Object);  {
			 = 
		} else {
			panic(.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap returned neither object nor undefined for property '%s'", .String()))
		}
	}
	if  == nil {
		if  == nil {
			return nil
		}
		if !.configurable {
			panic(.NewTypeError())
		}
		if !.self.isExtensible() {
			panic(.NewTypeError())
		}
		return nil
	}
	 := .self.isExtensible()
	 := .toPropertyDescriptor()
	.complete()
	if !.__isCompatibleDescriptor(, &, ) {
		panic(.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap returned descriptor for property '%s' that is incompatible with the existing property in the proxy target", .String()))
	}

	if .Configurable == FLAG_FALSE {
		if  == nil {
			panic(.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property '%s' which is non-existent in the proxy target", .String()))
		}

		if .configurable {
			panic(.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property '%s' which is configurable in the proxy target", .String()))
		}

		if .Writable == FLAG_FALSE && .writable {
			panic(.NewTypeError("'getOwnPropertyDescriptor' on proxy: trap reported non-configurable and writable for property '%s' which is non-configurable, non-writable in the proxy target", .String()))
		}
	}

	if .Writable == FLAG_TRUE && .Configurable == FLAG_TRUE &&
		.Enumerable == FLAG_TRUE {
		return .Value
	}
	return .toValueProp()
}

func ( *proxyObject) ( unistring.String) Value {
	 := .target
	if ,  := .checkHandler().getOwnPropertyDescriptorStr(, );  {
		return .proxyGetOwnPropertyDescriptor(.self.getOwnPropStr(), , , )
	}

	return .self.getOwnPropStr()
}

func ( *proxyObject) ( valueInt) Value {
	 := .target
	if ,  := .checkHandler().getOwnPropertyDescriptorIdx(, );  {
		return .proxyGetOwnPropertyDescriptor(.self.getOwnPropIdx(), , , )
	}

	return .self.getOwnPropIdx()
}

func ( *proxyObject) ( *Symbol) Value {
	 := .target
	if ,  := .checkHandler().getOwnPropertyDescriptorSym(, );  {
		return .proxyGetOwnPropertyDescriptor(.self.getOwnPropSym(), , , )
	}

	return .self.getOwnPropSym()
}

func ( *proxyObject) (,  Value,  fmt.Stringer) {
	if ,  := .(*valueProperty);  {
		if !.accessor {
			if !.writable && !.configurable && !.SameAs(.value) {
				panic(.val.runtime.NewTypeError("'get' on proxy: property '%s' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '%s' but got '%s')", .String(), nilSafe(.value), ret))
			}
		} else {
			if !.configurable && .getterFunc == nil &&  != _undefined {
				panic(.val.runtime.NewTypeError("'get' on proxy: property '%s' is a non-configurable accessor property on the proxy target and does not have a getter function, but the trap did not return 'undefined' (got '%s')", .String(), ret))
			}
		}
	}
}

func ( *proxyObject) ( unistring.String,  Value) Value {
	 := .target
	if  == nil {
		 = .val
	}
	if ,  := .checkHandler().getStr(, , );  {
		.proxyGetChecks(.self.getOwnPropStr(), , )
		return 
	}
	return .self.getStr(, )
}

func ( *proxyObject) ( valueInt,  Value) Value {
	 := .target
	if  == nil {
		 = .val
	}
	if ,  := .checkHandler().getIdx(, , );  {
		.proxyGetChecks(.self.getOwnPropIdx(), , )
		return 
	}
	return .self.getIdx(, )
}

func ( *proxyObject) ( *Symbol,  Value) Value {
	 := .target
	if  == nil {
		 = .val
	}
	if ,  := .checkHandler().getSym(, , );  {
		.proxyGetChecks(.self.getOwnPropSym(), , )
		return 
	}

	return .self.getSym(, )
}

func ( *proxyObject) (,  bool,  fmt.Stringer) bool {
	if ! {
		.val.runtime.typeErrorResult(, "'set' on proxy: trap returned falsish for property '%s'", .String())
	}
	return 
}

func ( *proxyObject) (,  Value,  fmt.Stringer) {
	if ,  := .(*valueProperty);  {
		if .accessor {
			if !.configurable && .setterFunc == nil {
				panic(.val.runtime.NewTypeError("'set' on proxy: trap returned truish for property '%s' which exists in the proxy target as a non-configurable and non-writable accessor property without a setter", .String()))
			}
		} else if !.configurable && !.writable && !.__sameValue(.value, ) {
			panic(.val.runtime.NewTypeError("'set' on proxy: trap returned truish for property '%s' which exists in the proxy target as a non-configurable and non-writable data property with a different value", .String()))
		}
	}
}

func ( *proxyObject) ( unistring.String, ,  Value,  bool) bool {
	 := .target
	if ,  := .checkHandler().setStr(, , , );  {
		if .proxySetPreCheck(, , ) {
			.proxySetPostCheck(.self.getOwnPropStr(), , )
			return true
		}
		return false
	}
	return .setStr(, , , )
}

func ( *proxyObject) ( valueInt, ,  Value,  bool) bool {
	 := .target
	if ,  := .checkHandler().setIdx(, , , );  {
		if .proxySetPreCheck(, , ) {
			.proxySetPostCheck(.self.getOwnPropIdx(), , )
			return true
		}
		return false
	}
	return .setIdx(, , , )
}

func ( *proxyObject) ( *Symbol, ,  Value,  bool) bool {
	 := .target
	if ,  := .checkHandler().setSym(, , , );  {
		if .proxySetPreCheck(, , ) {
			.proxySetPostCheck(.self.getOwnPropSym(), , )
			return true
		}
		return false
	}
	return .setSym(, , , )
}

func ( *proxyObject) ( unistring.String,  Value,  bool) bool {
	return .proxySetStr(, , .val, )
}

func ( *proxyObject) ( valueInt,  Value,  bool) bool {
	return .proxySetIdx(, , .val, )
}

func ( *proxyObject) ( *Symbol,  Value,  bool) bool {
	return .proxySetSym(, , .val, )
}

func ( *proxyObject) ( unistring.String, ,  Value,  bool) (bool, bool) {
	return .proxySetStr(, , , ), true
}

func ( *proxyObject) ( valueInt, ,  Value,  bool) (bool, bool) {
	return .proxySetIdx(, , , ), true
}

func ( *proxyObject) ( *Symbol, ,  Value,  bool) (bool, bool) {
	return .proxySetSym(, , , ), true
}

func ( *proxyObject) ( bool,  Value,  fmt.Stringer,  *Object,  bool) {
	if  {
		if  == nil {
			return
		}
		if ,  := .(*valueProperty);  {
			if !.configurable {
				panic(.val.runtime.NewTypeError("'deleteProperty' on proxy: property '%s' is a non-configurable property but the trap returned truish", .String()))
			}
		}
		if !.self.isExtensible() {
			panic(.val.runtime.NewTypeError("'deleteProperty' on proxy: trap returned truish for property '%s' but the proxy target is non-extensible", .String()))
		}
	} else {
		.val.runtime.typeErrorResult(, "'deleteProperty' on proxy: trap returned falsish for property '%s'", .String())
	}
}

func ( *proxyObject) ( unistring.String,  bool) bool {
	 := .target
	if ,  := .checkHandler().deleteStr(, );  {
		.proxyDeleteCheck(, .self.getOwnPropStr(), , , )
		return 
	}

	return .self.deleteStr(, )
}

func ( *proxyObject) ( valueInt,  bool) bool {
	 := .target
	if ,  := .checkHandler().deleteIdx(, );  {
		.proxyDeleteCheck(, .self.getOwnPropIdx(), , , )
		return 
	}

	return .self.deleteIdx(, )
}

func ( *proxyObject) ( *Symbol,  bool) bool {
	 := .target
	if ,  := .checkHandler().deleteSym(, );  {
		.proxyDeleteCheck(, .self.getOwnPropSym(), , , )
		return 
	}

	return .self.deleteSym(, )
}

func ( *proxyObject) ( bool,  []Value) []Value {
	if ,  := .proxyOwnKeys();  {
		if ! {
			 := 0
			for ,  := range  {
				 := .val.getOwnProp()
				if  == nil ||  == _undefined {
					continue
				}
				if ,  := .(*valueProperty);  && !.enumerable {
					continue
				}
				if  !=  {
					[] = []
				}
				++
			}
			 = [:]
		}
		return 
	}
	return .target.self.keys(, nil)
}

func ( *proxyObject) () ([]Value, bool) {
	 := .target
	if ,  := .checkHandler().ownKeys();  {
		 := .val.runtime.toObject()
		var  []Value
		 := make(map[Value]struct{})
		 := toLength(.self.getStr("length", nil))
		for  := int64(0);  < ; ++ {
			 := .self.getIdx(valueInt(), nil)
			if ,  := .(String); ! {
				if ,  := .(*Symbol); ! {
					panic(.val.runtime.NewTypeError("%s is not a valid property name", .String()))
				}
			}
			if ,  := [];  {
				panic(.val.runtime.NewTypeError("'ownKeys' on proxy: trap returned duplicate entries"))
			}
			 = append(, )
			[] = struct{}{}
		}
		 := .self.isExtensible()
		for ,  := .self.iterateKeys()();  != nil; ,  = () {
			if ,  := [.name];  {
				delete(, .name)
			} else {
				if ! {
					panic(.val.runtime.NewTypeError("'ownKeys' on proxy: trap result did not include '%s'", .name.String()))
				}
				var  Value
				if .value == nil {
					 = .getOwnProp(.name)
				} else {
					 = .value
				}
				if ,  := .(*valueProperty);  && !.configurable {
					panic(.val.runtime.NewTypeError("'ownKeys' on proxy: trap result did not include non-configurable '%s'", .name.String()))
				}
			}
		}
		if ! && len() > 0 && len() > 0 {
			panic(.val.runtime.NewTypeError("'ownKeys' on proxy: trap returned extra keys but proxy target is non-extensible"))
		}

		return , true
	}

	return nil, false
}

func ( *proxyObject) () iterNextFunc {
	return (&proxyPropIter{
		p:     ,
		names: .stringKeys(true, nil),
	}).next
}

func ( *proxyObject) () iterNextFunc {
	return (&proxyPropIter{
		p:     ,
		names: .symbols(true, nil),
	}).next
}

func ( *proxyObject) () iterNextFunc {
	return (&proxyPropIter{
		p:     ,
		names: .keys(true, nil),
	}).next
}

func ( *proxyObject) () ( func(FunctionCall) Value,  bool) {
	if .call != nil {
		return func( FunctionCall) Value {
			return .apply()
		}, true
	}
	return nil, false
}

func ( *proxyObject) ( *vm,  int) {
	.pushCtx()
	.prg = nil
	.sb = .sp -  // so that [sb-1] points to the callee
	 := .apply(FunctionCall{This: .stack[.sp--2], Arguments: .stack[.sp- : .sp]})
	if  == nil {
		 = _undefined
	}
	.stack[.sp--2] = 
	.popCtx()
	.sp -=  + 1
	.pc++
}

func ( *proxyObject) () func( []Value,  *Object) *Object {
	if .ctor != nil {
		return .construct
	}
	return nil
}

func ( *proxyObject) ( FunctionCall) Value {
	if .call == nil {
		panic(.val.runtime.NewTypeError("proxy target is not a function"))
	}
	if ,  := .checkHandler().apply(.target, nilSafe(.This), .Arguments);  {
		return 
	}
	return .call()
}

func ( *proxyObject) ( []Value,  *Object) *Object {
	if .ctor == nil {
		panic(.val.runtime.NewTypeError("proxy target is not a constructor"))
	}
	if  == nil {
		 = .val
	}
	if ,  := .checkHandler().construct(.target, , );  {
		return .val.runtime.toObject()
	}
	return .ctor(, )
}

func ( *proxyObject) ( bool,  *PropertyDescriptor,  *valueProperty) bool {
	if  == nil {
		return 
	}

	if !.configurable {
		if .Configurable == FLAG_TRUE {
			return false
		}

		if .Enumerable != FLAG_NOT_SET && .Enumerable.Bool() != .enumerable {
			return false
		}

		if .IsGeneric() {
			return true
		}

		if .IsData() != !.accessor {
			return .Configurable != FLAG_FALSE
		}

		if .IsData() && !.accessor {
			if !.configurable {
				if .Writable == FLAG_TRUE && !.writable {
					return false
				}
				if !.writable {
					if .Value != nil && !.Value.SameAs(.value) {
						return false
					}
				}
			}
			return true
		}
		if .IsAccessor() && .accessor {
			if !.configurable {
				if .Setter != nil && .Setter.SameAs(.setterFunc) {
					return false
				}
				if .Getter != nil && .Getter.SameAs(.getterFunc) {
					return false
				}
			}
		}
	}
	return true
}

func ( *proxyObject) (,  Value) bool {
	if  == nil &&  == nil {
		return true
	}
	if  != nil {
		return .SameAs()
	}
	return false
}

func ( *proxyObject) ( []Value, ,  bool) []Value {
	if ! {
		 := 0
		for ,  := range  {
			var  Value
			if  {
				if ,  := .(*Symbol);  {
					 = .getOwnPropSym()
				} else {
					continue
				}
			} else {
				if ,  := .(*Symbol); ! {
					 = .getOwnPropStr(.string())
				} else {
					continue
				}
			}
			if  == nil {
				continue
			}
			if ,  := .(*valueProperty);  && !.enumerable {
				continue
			}
			if  !=  {
				[] = []
			}
			++
		}
		 = [:]
	} else {
		 := 0
		for ,  := range  {
			if ,  := .(*Symbol);  !=  {
				continue
			}
			if  !=  {
				[] = []
			}
			++
		}
		 = [:]
	}
	return 
}

func ( *proxyObject) ( bool,  []Value) []Value { // we can assume accum is empty
	var  []Value
	if ,  := .proxyOwnKeys();  {
		 = 
	} else {
		 = .target.self.stringKeys(true, nil)
	}

	return .filterKeys(, , false)
}

func ( *proxyObject) ( bool,  []Value) []Value {
	var  []Value
	if ,  := .proxyOwnKeys();  {
		 = 
	} else {
		 = .target.self.symbols(true, nil)
	}
	 = .filterKeys(, , true)
	if  == nil {
		return 
	}
	 = append(, ...)
	return 
}

func ( *proxyObject) () string {
	if .target == nil {
		panic(.val.runtime.NewTypeError("proxy has been revoked"))
	}
	if .call != nil || .ctor != nil {
		return classFunction
	}
	return classObject
}

func ( *proxyObject) () String {
	if .call == nil {
		return stringObjectC
	}

	return stringFunction
}

func ( *proxyObject) () reflect.Type {
	return proxyType
}

func ( *proxyObject) (*objectExportCtx) interface{} {
	return Proxy{
		proxy: ,
	}
}

func ( *proxyObject) () {
	.handler = nil
	.target = nil
}