func (o *Object) OrdinaryOwnPropertyKeys() []StringOrSymbol {
	keys := []StringOrSymbol{}
	secs := make(map[int][]StringOrSymbol)
	const (
		integerIndex int = iota
		stringIndex
		symbolIndex
	)
	for k := range o.fields {
		if n, err := strconv.ParseInt(k.String().Value().(string), 10, 64); err == nil && n >= 0 {
			secs[integerIndex] = append(secs[integerIndex], k)
			continue
		}
		if k.Type() == TypeString {
			secs[stringIndex] = append(secs[stringIndex], k)
		}
		if k.Type() == TypeSymbol {
			secs[symbolIndex] = append(secs[symbolIndex], k)
		}
	}
	keys = append(keys, secs[integerIndex]...)
	keys = append(keys, secs[stringIndex]...)
	keys = append(keys, secs[symbolIndex]...)
	return keys
}
OrdinaryOwnPropertyKeys returns a list of names of the properties of this
object. That is, given an object with the properties 'A', 'B', and 'C',
OrdinaryOwnPropertyKeys will return ['A', 'B', 'C'].

TODO: add comment on ordering and grouping of property names

OrdinaryOwnPropertyKeys is specified in 9.1.11.1.
package lang
import (
	"reflect"
	"strconv"
	"github.com/gojisvm/gojis/internal/runtime/errors"
)
var _ Value = (*Object)(nil)  
type FunctionMode uint8
const (
	FunctionModeUnknown FunctionMode = iota
	FunctionModeLexical
	FunctionModeStrict
	FunctionModeGlobal
)
type FunctionKind uint8
const (
	FunctionKindUnknown FunctionKind = iota
	FunctionKindNormal
	FunctionKindClassGenerator
	FunctionKindGenerator
	FunctionKindAsync
)
type ConstructorKind uint8
const (
	ConstructorKindUnknown ConstructorKind = iota
	ConstructorKindBase
	ConstructorKindDerived
)
type Object struct {
	fields map[StringOrSymbol]*Property
	slots  map[StringOrSymbol]Value
	Prototype  Value  
	Extensible bool
	Environment      InternalValue
	FormalParameters interface{}
	FunctionKind     FunctionKind
	ConstructorKind  ConstructorKind
	Realm            InternalValue
	ScriptOrModule   interface{}
	ThisMode         FunctionMode
	Strict           bool
	HomeObject       *Object
	Call NativeFunction
	Construct func(*Object, ...Value) (*Object, errors.Error)
}
func ObjectCreate(proto Value, internalSlotsList ...StringOrSymbol) *Object {
	if internalSlotsList == nil {
		internalSlotsList = []StringOrSymbol{}
	}
	obj := new(Object)
	obj.fields = make(map[StringOrSymbol]*Property)
	obj.slots = make(map[StringOrSymbol]Value)
	for _, slot := range internalSlotsList {
		obj.slots[slot] = Undefined
	}
	EnsureTypeOneOf(proto, TypeObject, TypeNull)  
	obj.Prototype = proto
	obj.Extensible = true
	return obj
}
func (o *Object) Value() interface{} { return o }
func (o *Object) Type() Type { return TypeObject }
func (o *Object) GetPrototypeOf() Value {
	return o.OrdinaryGetPrototypeOf()
}
func (o *Object) OrdinaryGetPrototypeOf() Value {
	return o.Prototype
}
func (o *Object) SetPrototypeOf(v Value) Boolean {
	return o.OrdinarySetPrototypeOf(v)
}
func (o *Object) OrdinarySetPrototypeOf(v Value) Boolean {
	EnsureTypeOneOf(v, TypeObject, TypeNull)
	extensible := o.Extensible
	current := o.Prototype
	if InternalSameValue(v, current) {
		return True
	}
	if !extensible {
		return False
	}
	p := v
	done := false
	for !done {
		if p == Null {
			done = true
		} else if InternalSameValue(p, o) {
			return False
		} else {
			p = p.(*Object).Prototype  
		}
	}
	o.Prototype = v
	return True
}
func (o *Object) IsExtensible() Boolean {
	return o.OrdinaryIsExtensible()
}
func (o *Object) OrdinaryIsExtensible() Boolean {
	return Boolean(o.Extensible)
}
func (o *Object) PreventExtensions() Boolean {
	return o.OrdinaryPreventExtensions()
}
func (o *Object) OrdinaryPreventExtensions() Boolean {
	o.Extensible = false
	return True
}
func (o *Object) GetOwnProperty(p StringOrSymbol) *Property {
	return o.OrdinaryGetOwnProperty(p)
}
func (o *Object) OrdinaryGetOwnProperty(p StringOrSymbol) *Property {
	x, ok := o.fields[p]
	if !ok {
		return nil  
	}
	d := NewProperty()
	if x.IsDataDescriptor() {
		d.SetField(FieldNameValue, x.Value())
		d.SetField(FieldNameWritable, x.Writable())
	} else if x.IsAccessorDescriptor() {
		d.SetField(FieldNameGet, x.Get())
		d.SetField(FieldNameSet, x.Set())
	}
	d.SetField(FieldNameEnumerable, x.Enumerable())
	d.SetField(FieldNameConfigurable, x.Configurable())
	return d
}
func (o *Object) DefineOwnProperty(p StringOrSymbol, desc *Property) Boolean {
	return o.OrdinaryDefineOwnProperty(p, desc)
}
func (o *Object) OrdinaryDefineOwnProperty(p StringOrSymbol, desc *Property) Boolean {
	current := o.GetOwnProperty(p)
	extensible := o.Extensible
	return o.ValidateAndApplyPropertyDescriptor(p, extensible, desc, current)
}
func (o *Object) IsCompatiblePropertyDescriptor(extensible bool, desc, current *Property) Boolean {
	return ((*Object)(nil)).ValidateAndApplyPropertyDescriptor(StringOrSymbol{}, extensible, desc, current)
}
func (o *Object) ValidateAndApplyPropertyDescriptor(p StringOrSymbol, extensible bool, desc, current *Property) Boolean {
	if current == nil {
		if !extensible {
			return False
		}
		if desc.IsGenericDescriptor() || desc.IsDataDescriptor() {
			if o != nil {
				panic("TODO")
			}
		} else {
			panic("TODO")
		}
	}
	if len(desc.Record.fields) == 0 {
		return True
	}
	if !current.Configurable() {
		if desc.Configurable() {
			return False
		}
		if desc.Enumerable() && (current.Enumerable() == !desc.Enumerable()) {
			return False
		}
	}
	if desc.IsGenericDescriptor() {
	} else if current.IsDataDescriptor() != desc.IsDataDescriptor() {
		if !current.Configurable() {
			return False
		}
		if current.IsDataDescriptor() {
			panic("TODO")
		} else {
			panic("TODO")
		}
	} else if current.IsDataDescriptor() && desc.IsDataDescriptor() {
		if !current.Configurable() && !current.Writable() {
			if desc.Writable() {
				return False
			}
			if _, ok := desc.GetField(FieldNameValue); ok && !InternalSameValue(desc.Value(), current.Value()) {
				return False
			}
			return True
		}
	} else if current.IsAccessorDescriptor() && desc.IsAccessorDescriptor() {
		if !current.Configurable() {
			if _, ok := desc.GetField(FieldNameSet); ok && reflect.ValueOf(desc.Set()).Pointer() != reflect.ValueOf(current.Set()).Pointer() {
				return False
			}
			return True
		}
	}
	if o != nil {
		prop := o.fields[p]
		for k, v := range desc.Record.fields {
			prop.fields[k] = v
		}
	}
	return True
}
func (o *Object) HasProperty(p StringOrSymbol) Boolean {
	return o.OrdinaryHasProperty(p)
}
func (o *Object) OrdinaryHasProperty(p StringOrSymbol) Boolean {
	if o.GetOwnProperty(p) != nil {
		return True
	}
	parent := o.GetPrototypeOf()
	if parent != Null {
		return parent.(*Object).HasProperty(p)
	}
	return False
}
func (o *Object) Get(p StringOrSymbol, receiver Value) (Value, errors.Error) {
	return o.OrdinaryGet(p, receiver)
}
func (o *Object) OrdinaryGet(p StringOrSymbol, receiver Value) (Value, errors.Error) {
	desc := o.GetOwnProperty(p)
	if desc == nil {
		parent := o.GetPrototypeOf()
		if parent == Null {
			return Undefined, nil
		}
		return parent.(*Object).Get(p, receiver)
	}
	if desc.IsDataDescriptor() {
		return desc.Value(), nil
	}
	if getter := desc.Get(); getter != Undefined {
		return Call(getter.(*Object), receiver)
	}
	return Undefined, nil
}
func (o *Object) Set(p StringOrSymbol, v, receiver Value) (Boolean, errors.Error) {
	return o.OrdinarySet(p, v, receiver)
}
func (o *Object) OrdinarySet(p StringOrSymbol, v, receiver Value) (Boolean, errors.Error) {
	return o.OrdinarySetWithOwnDescriptor(p, v, receiver, o.GetOwnProperty(p))
}
func (o *Object) OrdinarySetWithOwnDescriptor(p StringOrSymbol, v, receiver Value, ownDesc *Property) (Boolean, errors.Error) {
	if ownDesc == nil {
		parent := o.GetPrototypeOf()
		if parent != Null {
			return parent.(*Object).Set(p, v, receiver)
		}
		ownDesc = NewDataProperty(Undefined, True, True, True)
	}
	if ownDesc.IsDataDescriptor() {
		if !ownDesc.Writable() {
			return False, nil
		}
		if receiver.Type() != TypeObject {
			return False, nil
		}
		receiverObj := receiver.(*Object)
		existingDescriptor := receiverObj.GetOwnProperty(p)
		if existingDescriptor != nil {
			if existingDescriptor.IsAccessorDescriptor() {
				return False, nil
			}
			if !existingDescriptor.Writable() {
				return False, nil
			}
			valueDesc := NewProperty()
			valueDesc.SetField(FieldNameValue, v)
			return receiverObj.DefineOwnProperty(p, valueDesc), nil
		}
		return CreateDataProperty(receiverObj, p, v), nil
	}
	if setter := ownDesc.Set(); setter != Undefined {
		_, err := Call(setter.(*Object), receiver, v)
		if err != nil {
			return False, err
		}
		return True, nil
	}
	return False, nil
}
func (o *Object) Delete(p StringOrSymbol) Boolean {
	return o.OrdinaryDelete(p)
}
func (o *Object) OrdinaryDelete(p StringOrSymbol) Boolean {
	desc := o.GetOwnProperty(p)
	if desc == nil {
		return True
	}
	if desc.Configurable() {
		delete(o.fields, p)
		return True
	}
	return False
}
func (o *Object) OwnPropertyKeys() []StringOrSymbol {
	return o.OrdinaryOwnPropertyKeys()
}