go.ketch.com/lib/goja@v0.0.1/object.go (about)

     1  package goja
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"reflect"
     7  	"sort"
     8  
     9  	"go.ketch.com/lib/goja/unistring"
    10  )
    11  
    12  const (
    13  	classObject   = "Object"
    14  	classArray    = "Array"
    15  	classWeakSet  = "WeakSet"
    16  	classWeakMap  = "WeakMap"
    17  	classMap      = "Map"
    18  	classMath     = "Math"
    19  	classSet      = "Set"
    20  	classFunction = "Function"
    21  	classNumber   = "Number"
    22  	classString   = "String"
    23  	classBoolean  = "Boolean"
    24  	classError    = "Error"
    25  	classAggError = "AggregateError"
    26  	classRegExp   = "RegExp"
    27  	classDate     = "Date"
    28  	classJSON     = "JSON"
    29  	classGlobal   = "global"
    30  	classPromise  = "Promise"
    31  
    32  	classArrayIterator        = "Array Iterator"
    33  	classMapIterator          = "Map Iterator"
    34  	classSetIterator          = "Set Iterator"
    35  	classStringIterator       = "String Iterator"
    36  	classRegExpStringIterator = "RegExp String Iterator"
    37  )
    38  
    39  var (
    40  	hintDefault Value = asciiString("default")
    41  	hintNumber  Value = asciiString("number")
    42  	hintString  Value = asciiString("string")
    43  )
    44  
    45  type Object struct {
    46  	id      uint64
    47  	runtime *Runtime
    48  	self    objectImpl
    49  
    50  	weakRefs map[weakMap]Value
    51  }
    52  
    53  type iterNextFunc func() (propIterItem, iterNextFunc)
    54  
    55  type PropertyDescriptor struct {
    56  	jsDescriptor *Object
    57  
    58  	Value Value
    59  
    60  	Writable, Configurable, Enumerable Flag
    61  
    62  	Getter, Setter Value
    63  }
    64  
    65  func (p *PropertyDescriptor) Empty() bool {
    66  	var empty PropertyDescriptor
    67  	return *p == empty
    68  }
    69  
    70  func (p *PropertyDescriptor) IsAccessor() bool {
    71  	return p.Setter != nil || p.Getter != nil
    72  }
    73  
    74  func (p *PropertyDescriptor) IsData() bool {
    75  	return p.Value != nil || p.Writable != FLAG_NOT_SET
    76  }
    77  
    78  func (p *PropertyDescriptor) IsGeneric() bool {
    79  	return !p.IsAccessor() && !p.IsData()
    80  }
    81  
    82  func (p *PropertyDescriptor) toValue(r *Runtime) Value {
    83  	if p.jsDescriptor != nil {
    84  		return p.jsDescriptor
    85  	}
    86  	if p.Empty() {
    87  		return _undefined
    88  	}
    89  	o := r.NewObject()
    90  	s := o.self
    91  
    92  	if p.Value != nil {
    93  		s._putProp("value", p.Value, true, true, true)
    94  	}
    95  
    96  	if p.Writable != FLAG_NOT_SET {
    97  		s._putProp("writable", valueBool(p.Writable.Bool()), true, true, true)
    98  	}
    99  
   100  	if p.Enumerable != FLAG_NOT_SET {
   101  		s._putProp("enumerable", valueBool(p.Enumerable.Bool()), true, true, true)
   102  	}
   103  
   104  	if p.Configurable != FLAG_NOT_SET {
   105  		s._putProp("configurable", valueBool(p.Configurable.Bool()), true, true, true)
   106  	}
   107  
   108  	if p.Getter != nil {
   109  		s._putProp("get", p.Getter, true, true, true)
   110  	}
   111  	if p.Setter != nil {
   112  		s._putProp("set", p.Setter, true, true, true)
   113  	}
   114  
   115  	return o
   116  }
   117  
   118  func (p *PropertyDescriptor) complete() {
   119  	if p.Getter == nil && p.Setter == nil {
   120  		if p.Value == nil {
   121  			p.Value = _undefined
   122  		}
   123  		if p.Writable == FLAG_NOT_SET {
   124  			p.Writable = FLAG_FALSE
   125  		}
   126  	} else {
   127  		if p.Getter == nil {
   128  			p.Getter = _undefined
   129  		}
   130  		if p.Setter == nil {
   131  			p.Setter = _undefined
   132  		}
   133  	}
   134  	if p.Enumerable == FLAG_NOT_SET {
   135  		p.Enumerable = FLAG_FALSE
   136  	}
   137  	if p.Configurable == FLAG_NOT_SET {
   138  		p.Configurable = FLAG_FALSE
   139  	}
   140  }
   141  
   142  type objectExportCacheItem map[reflect.Type]interface{}
   143  
   144  type objectExportCtx struct {
   145  	cache map[*Object]interface{}
   146  }
   147  
   148  type objectImpl interface {
   149  	sortable
   150  	className() string
   151  	getStr(p unistring.String, receiver Value) Value
   152  	getIdx(p valueInt, receiver Value) Value
   153  	getSym(p *Symbol, receiver Value) Value
   154  
   155  	getOwnPropStr(unistring.String) Value
   156  	getOwnPropIdx(valueInt) Value
   157  	getOwnPropSym(*Symbol) Value
   158  
   159  	setOwnStr(p unistring.String, v Value, throw bool) bool
   160  	setOwnIdx(p valueInt, v Value, throw bool) bool
   161  	setOwnSym(p *Symbol, v Value, throw bool) bool
   162  
   163  	setForeignStr(p unistring.String, v, receiver Value, throw bool) (res bool, handled bool)
   164  	setForeignIdx(p valueInt, v, receiver Value, throw bool) (res bool, handled bool)
   165  	setForeignSym(p *Symbol, v, receiver Value, throw bool) (res bool, handled bool)
   166  
   167  	hasPropertyStr(unistring.String) bool
   168  	hasPropertyIdx(idx valueInt) bool
   169  	hasPropertySym(s *Symbol) bool
   170  
   171  	hasOwnPropertyStr(unistring.String) bool
   172  	hasOwnPropertyIdx(valueInt) bool
   173  	hasOwnPropertySym(s *Symbol) bool
   174  
   175  	defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool
   176  	defineOwnPropertyIdx(name valueInt, desc PropertyDescriptor, throw bool) bool
   177  	defineOwnPropertySym(name *Symbol, desc PropertyDescriptor, throw bool) bool
   178  
   179  	deleteStr(name unistring.String, throw bool) bool
   180  	deleteIdx(idx valueInt, throw bool) bool
   181  	deleteSym(s *Symbol, throw bool) bool
   182  
   183  	toPrimitiveNumber() Value
   184  	toPrimitiveString() Value
   185  	toPrimitive() Value
   186  	assertCallable() (call func(FunctionCall) Value, ok bool)
   187  	assertConstructor() func(args []Value, newTarget *Object) *Object
   188  	proto() *Object
   189  	setProto(proto *Object, throw bool) bool
   190  	hasInstance(v Value) bool
   191  	isExtensible() bool
   192  	preventExtensions(throw bool) bool
   193  
   194  	export(ctx *objectExportCtx) interface{}
   195  	exportType() reflect.Type
   196  	exportToMap(m reflect.Value, typ reflect.Type, ctx *objectExportCtx) error
   197  	exportToArrayOrSlice(s reflect.Value, typ reflect.Type, ctx *objectExportCtx) error
   198  	equal(objectImpl) bool
   199  
   200  	iterateStringKeys() iterNextFunc
   201  	iterateSymbols() iterNextFunc
   202  	iterateKeys() iterNextFunc
   203  
   204  	stringKeys(all bool, accum []Value) []Value
   205  	symbols(all bool, accum []Value) []Value
   206  	keys(all bool, accum []Value) []Value
   207  
   208  	_putProp(name unistring.String, value Value, writable, enumerable, configurable bool) Value
   209  	_putSym(s *Symbol, prop Value)
   210  	getPrivateEnv(typ *privateEnvType, create bool) *privateElements
   211  }
   212  
   213  type baseObject struct {
   214  	class      string
   215  	val        *Object
   216  	prototype  *Object
   217  	extensible bool
   218  
   219  	values    map[unistring.String]Value
   220  	propNames []unistring.String
   221  
   222  	lastSortedPropLen, idxPropCount int
   223  
   224  	symValues *orderedMap
   225  
   226  	privateElements map[*privateEnvType]*privateElements
   227  }
   228  
   229  type guardedObject struct {
   230  	baseObject
   231  	guardedProps map[unistring.String]struct{}
   232  }
   233  
   234  type primitiveValueObject struct {
   235  	baseObject
   236  	pValue Value
   237  }
   238  
   239  func (o *primitiveValueObject) export(*objectExportCtx) interface{} {
   240  	return o.pValue.Export()
   241  }
   242  
   243  func (o *primitiveValueObject) exportType() reflect.Type {
   244  	return o.pValue.ExportType()
   245  }
   246  
   247  type FunctionCall struct {
   248  	This      Value
   249  	Arguments []Value
   250  }
   251  
   252  type ConstructorCall struct {
   253  	This      *Object
   254  	Arguments []Value
   255  	NewTarget *Object
   256  }
   257  
   258  func (f FunctionCall) Argument(idx int) Value {
   259  	if idx < len(f.Arguments) {
   260  		return f.Arguments[idx]
   261  	}
   262  	return _undefined
   263  }
   264  
   265  func (f ConstructorCall) Argument(idx int) Value {
   266  	if idx < len(f.Arguments) {
   267  		return f.Arguments[idx]
   268  	}
   269  	return _undefined
   270  }
   271  
   272  func (o *baseObject) init() {
   273  	o.values = make(map[unistring.String]Value)
   274  }
   275  
   276  func (o *baseObject) className() string {
   277  	return o.class
   278  }
   279  
   280  func (o *baseObject) hasPropertyStr(name unistring.String) bool {
   281  	if o.val.self.hasOwnPropertyStr(name) {
   282  		return true
   283  	}
   284  	if o.prototype != nil {
   285  		return o.prototype.self.hasPropertyStr(name)
   286  	}
   287  	return false
   288  }
   289  
   290  func (o *baseObject) hasPropertyIdx(idx valueInt) bool {
   291  	return o.val.self.hasPropertyStr(idx.string())
   292  }
   293  
   294  func (o *baseObject) hasPropertySym(s *Symbol) bool {
   295  	if o.hasOwnPropertySym(s) {
   296  		return true
   297  	}
   298  	if o.prototype != nil {
   299  		return o.prototype.self.hasPropertySym(s)
   300  	}
   301  	return false
   302  }
   303  
   304  func (o *baseObject) getWithOwnProp(prop, p, receiver Value) Value {
   305  	if prop == nil && o.prototype != nil {
   306  		if receiver == nil {
   307  			return o.prototype.get(p, o.val)
   308  		}
   309  		return o.prototype.get(p, receiver)
   310  	}
   311  	if prop, ok := prop.(*valueProperty); ok {
   312  		if receiver == nil {
   313  			return prop.get(o.val)
   314  		}
   315  		return prop.get(receiver)
   316  	}
   317  	return prop
   318  }
   319  
   320  func (o *baseObject) getStrWithOwnProp(prop Value, name unistring.String, receiver Value) Value {
   321  	if prop == nil && o.prototype != nil {
   322  		if receiver == nil {
   323  			return o.prototype.self.getStr(name, o.val)
   324  		}
   325  		return o.prototype.self.getStr(name, receiver)
   326  	}
   327  	if prop, ok := prop.(*valueProperty); ok {
   328  		if receiver == nil {
   329  			return prop.get(o.val)
   330  		}
   331  		return prop.get(receiver)
   332  	}
   333  	return prop
   334  }
   335  
   336  func (o *baseObject) getIdx(idx valueInt, receiver Value) Value {
   337  	return o.val.self.getStr(idx.string(), receiver)
   338  }
   339  
   340  func (o *baseObject) getSym(s *Symbol, receiver Value) Value {
   341  	return o.getWithOwnProp(o.getOwnPropSym(s), s, receiver)
   342  }
   343  
   344  func (o *baseObject) getStr(name unistring.String, receiver Value) Value {
   345  	prop := o.values[name]
   346  	if prop == nil {
   347  		if o.prototype != nil {
   348  			if receiver == nil {
   349  				return o.prototype.self.getStr(name, o.val)
   350  			}
   351  			return o.prototype.self.getStr(name, receiver)
   352  		}
   353  	}
   354  	if prop, ok := prop.(*valueProperty); ok {
   355  		if receiver == nil {
   356  			return prop.get(o.val)
   357  		}
   358  		return prop.get(receiver)
   359  	}
   360  	return prop
   361  }
   362  
   363  func (o *baseObject) getOwnPropIdx(idx valueInt) Value {
   364  	return o.val.self.getOwnPropStr(idx.string())
   365  }
   366  
   367  func (o *baseObject) getOwnPropSym(s *Symbol) Value {
   368  	if o.symValues != nil {
   369  		return o.symValues.get(s)
   370  	}
   371  	return nil
   372  }
   373  
   374  func (o *baseObject) getOwnPropStr(name unistring.String) Value {
   375  	return o.values[name]
   376  }
   377  
   378  func (o *baseObject) checkDeleteProp(name unistring.String, prop *valueProperty, throw bool) bool {
   379  	if !prop.configurable {
   380  		if throw {
   381  			r := o.val.runtime
   382  			panic(r.NewTypeError("Cannot delete property '%s' of %s", name, r.objectproto_toString(FunctionCall{This: o.val})))
   383  		}
   384  		return false
   385  	}
   386  	return true
   387  }
   388  
   389  func (o *baseObject) checkDelete(name unistring.String, val Value, throw bool) bool {
   390  	if val, ok := val.(*valueProperty); ok {
   391  		return o.checkDeleteProp(name, val, throw)
   392  	}
   393  	return true
   394  }
   395  
   396  func (o *baseObject) _delete(name unistring.String) {
   397  	delete(o.values, name)
   398  	for i, n := range o.propNames {
   399  		if n == name {
   400  			names := o.propNames
   401  			if namesMarkedForCopy(names) {
   402  				newNames := make([]unistring.String, len(names)-1, shrinkCap(len(names), cap(names)))
   403  				copy(newNames, names[:i])
   404  				copy(newNames[i:], names[i+1:])
   405  				o.propNames = newNames
   406  			} else {
   407  				copy(names[i:], names[i+1:])
   408  				names[len(names)-1] = ""
   409  				o.propNames = names[:len(names)-1]
   410  			}
   411  			if i < o.lastSortedPropLen {
   412  				o.lastSortedPropLen--
   413  				if i < o.idxPropCount {
   414  					o.idxPropCount--
   415  				}
   416  			}
   417  			break
   418  		}
   419  	}
   420  }
   421  
   422  func (o *baseObject) deleteIdx(idx valueInt, throw bool) bool {
   423  	return o.val.self.deleteStr(idx.string(), throw)
   424  }
   425  
   426  func (o *baseObject) deleteSym(s *Symbol, throw bool) bool {
   427  	if o.symValues != nil {
   428  		if val := o.symValues.get(s); val != nil {
   429  			if !o.checkDelete(s.descriptiveString().string(), val, throw) {
   430  				return false
   431  			}
   432  			o.symValues.remove(s)
   433  		}
   434  	}
   435  	return true
   436  }
   437  
   438  func (o *baseObject) deleteStr(name unistring.String, throw bool) bool {
   439  	if val, exists := o.values[name]; exists {
   440  		if !o.checkDelete(name, val, throw) {
   441  			return false
   442  		}
   443  		o._delete(name)
   444  	}
   445  	return true
   446  }
   447  
   448  func (o *baseObject) setProto(proto *Object, throw bool) bool {
   449  	current := o.prototype
   450  	if current.SameAs(proto) {
   451  		return true
   452  	}
   453  	if !o.extensible {
   454  		o.val.runtime.typeErrorResult(throw, "%s is not extensible", o.val)
   455  		return false
   456  	}
   457  	for p := proto; p != nil; p = p.self.proto() {
   458  		if p.SameAs(o.val) {
   459  			o.val.runtime.typeErrorResult(throw, "Cyclic __proto__ value")
   460  			return false
   461  		}
   462  		if _, ok := p.self.(*proxyObject); ok {
   463  			break
   464  		}
   465  	}
   466  	o.prototype = proto
   467  	return true
   468  }
   469  
   470  func (o *baseObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
   471  	ownDesc := o.values[name]
   472  	if ownDesc == nil {
   473  		if proto := o.prototype; proto != nil {
   474  			// we know it's foreign because prototype loops are not allowed
   475  			if res, handled := proto.self.setForeignStr(name, val, o.val, throw); handled {
   476  				return res
   477  			}
   478  		}
   479  		// new property
   480  		if !o.extensible {
   481  			o.val.runtime.typeErrorResult(throw, "Cannot add property %s, object is not extensible", name)
   482  			return false
   483  		} else {
   484  			o.values[name] = val
   485  			names := copyNamesIfNeeded(o.propNames, 1)
   486  			o.propNames = append(names, name)
   487  		}
   488  		return true
   489  	}
   490  	if prop, ok := ownDesc.(*valueProperty); ok {
   491  		if !prop.isWritable() {
   492  			o.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%s'", name)
   493  			return false
   494  		} else {
   495  			prop.set(o.val, val)
   496  		}
   497  	} else {
   498  		o.values[name] = val
   499  	}
   500  	return true
   501  }
   502  
   503  func (o *baseObject) setOwnIdx(idx valueInt, val Value, throw bool) bool {
   504  	return o.val.self.setOwnStr(idx.string(), val, throw)
   505  }
   506  
   507  func (o *baseObject) setOwnSym(name *Symbol, val Value, throw bool) bool {
   508  	var ownDesc Value
   509  	if o.symValues != nil {
   510  		ownDesc = o.symValues.get(name)
   511  	}
   512  	if ownDesc == nil {
   513  		if proto := o.prototype; proto != nil {
   514  			// we know it's foreign because prototype loops are not allowed
   515  			if res, handled := proto.self.setForeignSym(name, val, o.val, throw); handled {
   516  				return res
   517  			}
   518  		}
   519  		// new property
   520  		if !o.extensible {
   521  			o.val.runtime.typeErrorResult(throw, "Cannot add property %s, object is not extensible", name)
   522  			return false
   523  		} else {
   524  			if o.symValues == nil {
   525  				o.symValues = newOrderedMap(nil)
   526  			}
   527  			o.symValues.set(name, val)
   528  		}
   529  		return true
   530  	}
   531  	if prop, ok := ownDesc.(*valueProperty); ok {
   532  		if !prop.isWritable() {
   533  			o.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%s'", name)
   534  			return false
   535  		} else {
   536  			prop.set(o.val, val)
   537  		}
   538  	} else {
   539  		o.symValues.set(name, val)
   540  	}
   541  	return true
   542  }
   543  
   544  func (o *baseObject) _setForeignStr(name unistring.String, prop, val, receiver Value, throw bool) (bool, bool) {
   545  	if prop != nil {
   546  		if prop, ok := prop.(*valueProperty); ok {
   547  			if !prop.isWritable() {
   548  				o.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%s'", name)
   549  				return false, true
   550  			}
   551  			if prop.setterFunc != nil {
   552  				prop.set(receiver, val)
   553  				return true, true
   554  			}
   555  		}
   556  	} else {
   557  		if proto := o.prototype; proto != nil {
   558  			if receiver != proto {
   559  				return proto.self.setForeignStr(name, val, receiver, throw)
   560  			}
   561  			return proto.self.setOwnStr(name, val, throw), true
   562  		}
   563  	}
   564  	return false, false
   565  }
   566  
   567  func (o *baseObject) _setForeignIdx(idx valueInt, prop, val, receiver Value, throw bool) (bool, bool) {
   568  	if prop != nil {
   569  		if prop, ok := prop.(*valueProperty); ok {
   570  			if !prop.isWritable() {
   571  				o.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%d'", idx)
   572  				return false, true
   573  			}
   574  			if prop.setterFunc != nil {
   575  				prop.set(receiver, val)
   576  				return true, true
   577  			}
   578  		}
   579  	} else {
   580  		if proto := o.prototype; proto != nil {
   581  			if receiver != proto {
   582  				return proto.self.setForeignIdx(idx, val, receiver, throw)
   583  			}
   584  			return proto.self.setOwnIdx(idx, val, throw), true
   585  		}
   586  	}
   587  	return false, false
   588  }
   589  
   590  func (o *baseObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
   591  	return o._setForeignStr(name, o.values[name], val, receiver, throw)
   592  }
   593  
   594  func (o *baseObject) setForeignIdx(name valueInt, val, receiver Value, throw bool) (bool, bool) {
   595  	if idx := toIdx(name); idx != math.MaxUint32 {
   596  		o.ensurePropOrder()
   597  		if o.idxPropCount == 0 {
   598  			return o._setForeignIdx(name, name, nil, receiver, throw)
   599  		}
   600  	}
   601  	return o.setForeignStr(name.string(), val, receiver, throw)
   602  }
   603  
   604  func (o *baseObject) setForeignSym(name *Symbol, val, receiver Value, throw bool) (bool, bool) {
   605  	var prop Value
   606  	if o.symValues != nil {
   607  		prop = o.symValues.get(name)
   608  	}
   609  	if prop != nil {
   610  		if prop, ok := prop.(*valueProperty); ok {
   611  			if !prop.isWritable() {
   612  				o.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%s'", name)
   613  				return false, true
   614  			}
   615  			if prop.setterFunc != nil {
   616  				prop.set(receiver, val)
   617  				return true, true
   618  			}
   619  		}
   620  	} else {
   621  		if proto := o.prototype; proto != nil {
   622  			if receiver != o.val {
   623  				return proto.self.setForeignSym(name, val, receiver, throw)
   624  			}
   625  			return proto.self.setOwnSym(name, val, throw), true
   626  		}
   627  	}
   628  	return false, false
   629  }
   630  
   631  func (o *baseObject) hasOwnPropertySym(s *Symbol) bool {
   632  	if o.symValues != nil {
   633  		return o.symValues.has(s)
   634  	}
   635  	return false
   636  }
   637  
   638  func (o *baseObject) hasOwnPropertyStr(name unistring.String) bool {
   639  	_, exists := o.values[name]
   640  	return exists
   641  }
   642  
   643  func (o *baseObject) hasOwnPropertyIdx(idx valueInt) bool {
   644  	return o.val.self.hasOwnPropertyStr(idx.string())
   645  }
   646  
   647  func (o *baseObject) _defineOwnProperty(name unistring.String, existingValue Value, descr PropertyDescriptor, throw bool) (val Value, ok bool) {
   648  
   649  	getterObj, _ := descr.Getter.(*Object)
   650  	setterObj, _ := descr.Setter.(*Object)
   651  
   652  	var existing *valueProperty
   653  
   654  	if existingValue == nil {
   655  		if !o.extensible {
   656  			o.val.runtime.typeErrorResult(throw, "Cannot define property %s, object is not extensible", name)
   657  			return nil, false
   658  		}
   659  		existing = &valueProperty{}
   660  	} else {
   661  		if existing, ok = existingValue.(*valueProperty); !ok {
   662  			existing = &valueProperty{
   663  				writable:     true,
   664  				enumerable:   true,
   665  				configurable: true,
   666  				value:        existingValue,
   667  			}
   668  		}
   669  
   670  		if !existing.configurable {
   671  			if descr.Configurable == FLAG_TRUE {
   672  				goto Reject
   673  			}
   674  			if descr.Enumerable != FLAG_NOT_SET && descr.Enumerable.Bool() != existing.enumerable {
   675  				goto Reject
   676  			}
   677  		}
   678  		if existing.accessor && descr.Value != nil || !existing.accessor && (getterObj != nil || setterObj != nil) {
   679  			if !existing.configurable {
   680  				goto Reject
   681  			}
   682  		} else if !existing.accessor {
   683  			if !existing.configurable {
   684  				if !existing.writable {
   685  					if descr.Writable == FLAG_TRUE {
   686  						goto Reject
   687  					}
   688  					if descr.Value != nil && !descr.Value.SameAs(existing.value) {
   689  						goto Reject
   690  					}
   691  				}
   692  			}
   693  		} else {
   694  			if !existing.configurable {
   695  				if descr.Getter != nil && existing.getterFunc != getterObj || descr.Setter != nil && existing.setterFunc != setterObj {
   696  					goto Reject
   697  				}
   698  			}
   699  		}
   700  	}
   701  
   702  	if descr.Writable == FLAG_TRUE && descr.Enumerable == FLAG_TRUE && descr.Configurable == FLAG_TRUE && descr.Value != nil {
   703  		return descr.Value, true
   704  	}
   705  
   706  	if descr.Writable != FLAG_NOT_SET {
   707  		existing.writable = descr.Writable.Bool()
   708  	}
   709  	if descr.Enumerable != FLAG_NOT_SET {
   710  		existing.enumerable = descr.Enumerable.Bool()
   711  	}
   712  	if descr.Configurable != FLAG_NOT_SET {
   713  		existing.configurable = descr.Configurable.Bool()
   714  	}
   715  
   716  	if descr.Value != nil {
   717  		existing.value = descr.Value
   718  		existing.getterFunc = nil
   719  		existing.setterFunc = nil
   720  	}
   721  
   722  	if descr.Value != nil || descr.Writable != FLAG_NOT_SET {
   723  		existing.accessor = false
   724  	}
   725  
   726  	if descr.Getter != nil {
   727  		existing.getterFunc = propGetter(o.val, descr.Getter, o.val.runtime)
   728  		existing.value = nil
   729  		existing.accessor = true
   730  	}
   731  
   732  	if descr.Setter != nil {
   733  		existing.setterFunc = propSetter(o.val, descr.Setter, o.val.runtime)
   734  		existing.value = nil
   735  		existing.accessor = true
   736  	}
   737  
   738  	if !existing.accessor && existing.value == nil {
   739  		existing.value = _undefined
   740  	}
   741  
   742  	return existing, true
   743  
   744  Reject:
   745  	o.val.runtime.typeErrorResult(throw, "Cannot redefine property: %s", name)
   746  	return nil, false
   747  
   748  }
   749  
   750  func (o *baseObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
   751  	existingVal := o.values[name]
   752  	if v, ok := o._defineOwnProperty(name, existingVal, descr, throw); ok {
   753  		o.values[name] = v
   754  		if existingVal == nil {
   755  			names := copyNamesIfNeeded(o.propNames, 1)
   756  			o.propNames = append(names, name)
   757  		}
   758  		return true
   759  	}
   760  	return false
   761  }
   762  
   763  func (o *baseObject) defineOwnPropertyIdx(idx valueInt, desc PropertyDescriptor, throw bool) bool {
   764  	return o.val.self.defineOwnPropertyStr(idx.string(), desc, throw)
   765  }
   766  
   767  func (o *baseObject) defineOwnPropertySym(s *Symbol, descr PropertyDescriptor, throw bool) bool {
   768  	var existingVal Value
   769  	if o.symValues != nil {
   770  		existingVal = o.symValues.get(s)
   771  	}
   772  	if v, ok := o._defineOwnProperty(s.descriptiveString().string(), existingVal, descr, throw); ok {
   773  		if o.symValues == nil {
   774  			o.symValues = newOrderedMap(nil)
   775  		}
   776  		o.symValues.set(s, v)
   777  		return true
   778  	}
   779  	return false
   780  }
   781  
   782  func (o *baseObject) _put(name unistring.String, v Value) {
   783  	if _, exists := o.values[name]; !exists {
   784  		names := copyNamesIfNeeded(o.propNames, 1)
   785  		o.propNames = append(names, name)
   786  	}
   787  
   788  	o.values[name] = v
   789  }
   790  
   791  func valueProp(value Value, writable, enumerable, configurable bool) Value {
   792  	if writable && enumerable && configurable {
   793  		return value
   794  	}
   795  	return &valueProperty{
   796  		value:        value,
   797  		writable:     writable,
   798  		enumerable:   enumerable,
   799  		configurable: configurable,
   800  	}
   801  }
   802  
   803  func (o *baseObject) _putProp(name unistring.String, value Value, writable, enumerable, configurable bool) Value {
   804  	prop := valueProp(value, writable, enumerable, configurable)
   805  	o._put(name, prop)
   806  	return prop
   807  }
   808  
   809  func (o *baseObject) _putSym(s *Symbol, prop Value) {
   810  	if o.symValues == nil {
   811  		o.symValues = newOrderedMap(nil)
   812  	}
   813  	o.symValues.set(s, prop)
   814  }
   815  
   816  func (o *baseObject) getPrivateEnv(typ *privateEnvType, create bool) *privateElements {
   817  	env := o.privateElements[typ]
   818  	if env != nil && create {
   819  		panic(o.val.runtime.NewTypeError("Private fields for the class have already been set"))
   820  	}
   821  	if env == nil && create {
   822  		env = &privateElements{
   823  			fields: make([]Value, typ.numFields),
   824  		}
   825  		if o.privateElements == nil {
   826  			o.privateElements = make(map[*privateEnvType]*privateElements)
   827  		}
   828  		o.privateElements[typ] = env
   829  	}
   830  	return env
   831  }
   832  
   833  func (o *Object) tryPrimitive(methodName unistring.String) Value {
   834  	if method, ok := o.self.getStr(methodName, nil).(*Object); ok {
   835  		if call, ok := method.self.assertCallable(); ok {
   836  			v := call(FunctionCall{
   837  				This: o,
   838  			})
   839  			if _, fail := v.(*Object); !fail {
   840  				return v
   841  			}
   842  		}
   843  	}
   844  	return nil
   845  }
   846  
   847  func (o *Object) genericToPrimitiveNumber() Value {
   848  	if v := o.tryPrimitive("valueOf"); v != nil {
   849  		return v
   850  	}
   851  
   852  	if v := o.tryPrimitive("toString"); v != nil {
   853  		return v
   854  	}
   855  
   856  	panic(o.runtime.NewTypeError("Could not convert %v to primitive", o.self))
   857  }
   858  
   859  func (o *baseObject) toPrimitiveNumber() Value {
   860  	return o.val.genericToPrimitiveNumber()
   861  }
   862  
   863  func (o *Object) genericToPrimitiveString() Value {
   864  	if v := o.tryPrimitive("toString"); v != nil {
   865  		return v
   866  	}
   867  
   868  	if v := o.tryPrimitive("valueOf"); v != nil {
   869  		return v
   870  	}
   871  
   872  	panic(o.runtime.NewTypeError("Could not convert %v to primitive", o.self))
   873  }
   874  
   875  func (o *Object) genericToPrimitive() Value {
   876  	return o.genericToPrimitiveNumber()
   877  }
   878  
   879  func (o *baseObject) toPrimitiveString() Value {
   880  	return o.val.genericToPrimitiveString()
   881  }
   882  
   883  func (o *baseObject) toPrimitive() Value {
   884  	return o.val.genericToPrimitiveNumber()
   885  }
   886  
   887  func (o *Object) tryExoticToPrimitive(hint Value) Value {
   888  	exoticToPrimitive := toMethod(o.self.getSym(SymToPrimitive, nil))
   889  	if exoticToPrimitive != nil {
   890  		ret := exoticToPrimitive(FunctionCall{
   891  			This:      o,
   892  			Arguments: []Value{hint},
   893  		})
   894  		if _, fail := ret.(*Object); !fail {
   895  			return ret
   896  		}
   897  		panic(o.runtime.NewTypeError("Cannot convert object to primitive value"))
   898  	}
   899  	return nil
   900  }
   901  
   902  func (o *Object) toPrimitiveNumber() Value {
   903  	if v := o.tryExoticToPrimitive(hintNumber); v != nil {
   904  		return v
   905  	}
   906  
   907  	return o.self.toPrimitiveNumber()
   908  }
   909  
   910  func (o *Object) toPrimitiveString() Value {
   911  	if v := o.tryExoticToPrimitive(hintString); v != nil {
   912  		return v
   913  	}
   914  
   915  	return o.self.toPrimitiveString()
   916  }
   917  
   918  func (o *Object) toPrimitive() Value {
   919  	if v := o.tryExoticToPrimitive(hintDefault); v != nil {
   920  		return v
   921  	}
   922  	return o.self.toPrimitive()
   923  }
   924  
   925  func (o *baseObject) assertCallable() (func(FunctionCall) Value, bool) {
   926  	return nil, false
   927  }
   928  
   929  func (o *baseObject) assertConstructor() func(args []Value, newTarget *Object) *Object {
   930  	return nil
   931  }
   932  
   933  func (o *baseObject) proto() *Object {
   934  	return o.prototype
   935  }
   936  
   937  func (o *baseObject) isExtensible() bool {
   938  	return o.extensible
   939  }
   940  
   941  func (o *baseObject) preventExtensions(bool) bool {
   942  	o.extensible = false
   943  	return true
   944  }
   945  
   946  func (o *baseObject) sortLen() int {
   947  	return toIntStrict(toLength(o.val.self.getStr("length", nil)))
   948  }
   949  
   950  func (o *baseObject) sortGet(i int) Value {
   951  	return o.val.self.getIdx(valueInt(i), nil)
   952  }
   953  
   954  func (o *baseObject) swap(i int, j int) {
   955  	ii := valueInt(i)
   956  	jj := valueInt(j)
   957  
   958  	x := o.val.self.getIdx(ii, nil)
   959  	y := o.val.self.getIdx(jj, nil)
   960  
   961  	o.val.self.setOwnIdx(ii, y, false)
   962  	o.val.self.setOwnIdx(jj, x, false)
   963  }
   964  
   965  func (o *baseObject) export(ctx *objectExportCtx) interface{} {
   966  	if v, exists := ctx.get(o.val); exists {
   967  		return v
   968  	}
   969  	keys := o.stringKeys(false, nil)
   970  	m := make(map[string]interface{}, len(keys))
   971  	ctx.put(o.val, m)
   972  	for _, itemName := range keys {
   973  		itemNameStr := itemName.String()
   974  		v := o.val.self.getStr(itemName.string(), nil)
   975  		if v != nil {
   976  			m[itemNameStr] = exportValue(v, ctx)
   977  		} else {
   978  			m[itemNameStr] = nil
   979  		}
   980  	}
   981  
   982  	return m
   983  }
   984  
   985  func (o *baseObject) exportType() reflect.Type {
   986  	return reflectTypeMap
   987  }
   988  
   989  func genericExportToMap(o *Object, dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
   990  	dst.Set(reflect.MakeMap(typ))
   991  	ctx.putTyped(o, typ, dst.Interface())
   992  	keyTyp := typ.Key()
   993  	elemTyp := typ.Elem()
   994  	needConvertKeys := !reflectTypeString.AssignableTo(keyTyp)
   995  	iter := &enumerableIter{
   996  		o:       o,
   997  		wrapped: o.self.iterateStringKeys(),
   998  	}
   999  	r := o.runtime
  1000  	for item, next := iter.next(); next != nil; item, next = next() {
  1001  		var kv reflect.Value
  1002  		var err error
  1003  		if needConvertKeys {
  1004  			kv = reflect.New(keyTyp).Elem()
  1005  			err = r.toReflectValue(item.name, kv, ctx)
  1006  			if err != nil {
  1007  				return fmt.Errorf("could not convert map key %s to %v: %w", item.name.String(), typ, err)
  1008  			}
  1009  		} else {
  1010  			kv = reflect.ValueOf(item.name.String())
  1011  		}
  1012  
  1013  		ival := o.self.getStr(item.name.string(), nil)
  1014  		if ival != nil {
  1015  			vv := reflect.New(elemTyp).Elem()
  1016  			err = r.toReflectValue(ival, vv, ctx)
  1017  			if err != nil {
  1018  				return fmt.Errorf("could not convert map value %v to %v at key %s: %w", ival, typ, item.name.String(), err)
  1019  			}
  1020  			dst.SetMapIndex(kv, vv)
  1021  		} else {
  1022  			dst.SetMapIndex(kv, reflect.Zero(elemTyp))
  1023  		}
  1024  	}
  1025  
  1026  	return nil
  1027  }
  1028  
  1029  func (o *baseObject) exportToMap(m reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
  1030  	return genericExportToMap(o.val, m, typ, ctx)
  1031  }
  1032  
  1033  func genericExportToArrayOrSlice(o *Object, dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) (err error) {
  1034  	r := o.runtime
  1035  
  1036  	if method := toMethod(r.getV(o, SymIterator)); method != nil {
  1037  		// iterable
  1038  
  1039  		var values []Value
  1040  		// cannot change (append to) the slice once it's been put into the cache, so we need to know its length beforehand
  1041  		ex := r.try(func() {
  1042  			values = r.iterableToList(o, method)
  1043  		})
  1044  		if ex != nil {
  1045  			return ex
  1046  		}
  1047  		if typ.Kind() == reflect.Array {
  1048  			if dst.Len() != len(values) {
  1049  				return fmt.Errorf("cannot convert an iterable into an array, lengths mismatch (have %d, need %d)", len(values), dst.Len())
  1050  			}
  1051  		} else {
  1052  			dst.Set(reflect.MakeSlice(typ, len(values), len(values)))
  1053  		}
  1054  		ctx.putTyped(o, typ, dst.Interface())
  1055  		for i, val := range values {
  1056  			err = r.toReflectValue(val, dst.Index(i), ctx)
  1057  			if err != nil {
  1058  				return
  1059  			}
  1060  		}
  1061  	} else {
  1062  		// array-like
  1063  		var lp Value
  1064  		if _, ok := o.self.assertCallable(); !ok {
  1065  			lp = o.self.getStr("length", nil)
  1066  		}
  1067  		if lp == nil {
  1068  			return fmt.Errorf("cannot convert %v to %v: not an array or iterable", o, typ)
  1069  		}
  1070  		l := toIntStrict(toLength(lp))
  1071  		if dst.Len() != l {
  1072  			if typ.Kind() == reflect.Array {
  1073  				return fmt.Errorf("cannot convert an array-like object into an array, lengths mismatch (have %d, need %d)", l, dst.Len())
  1074  			} else {
  1075  				dst.Set(reflect.MakeSlice(typ, l, l))
  1076  			}
  1077  		}
  1078  		ctx.putTyped(o, typ, dst.Interface())
  1079  		for i := 0; i < l; i++ {
  1080  			val := nilSafe(o.self.getIdx(valueInt(i), nil))
  1081  			err = r.toReflectValue(val, dst.Index(i), ctx)
  1082  			if err != nil {
  1083  				return
  1084  			}
  1085  		}
  1086  	}
  1087  
  1088  	return
  1089  }
  1090  
  1091  func (o *baseObject) exportToArrayOrSlice(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
  1092  	return genericExportToArrayOrSlice(o.val, dst, typ, ctx)
  1093  }
  1094  
  1095  type enumerableFlag int
  1096  
  1097  const (
  1098  	_ENUM_UNKNOWN enumerableFlag = iota
  1099  	_ENUM_FALSE
  1100  	_ENUM_TRUE
  1101  )
  1102  
  1103  type propIterItem struct {
  1104  	name       Value
  1105  	value      Value
  1106  	enumerable enumerableFlag
  1107  }
  1108  
  1109  type objectPropIter struct {
  1110  	o         *baseObject
  1111  	propNames []unistring.String
  1112  	idx       int
  1113  }
  1114  
  1115  type recursivePropIter struct {
  1116  	o    objectImpl
  1117  	cur  iterNextFunc
  1118  	seen map[unistring.String]struct{}
  1119  }
  1120  
  1121  type enumerableIter struct {
  1122  	o       *Object
  1123  	wrapped iterNextFunc
  1124  }
  1125  
  1126  func (i *enumerableIter) next() (propIterItem, iterNextFunc) {
  1127  	for {
  1128  		var item propIterItem
  1129  		item, i.wrapped = i.wrapped()
  1130  		if i.wrapped == nil {
  1131  			return item, nil
  1132  		}
  1133  		if item.enumerable == _ENUM_FALSE {
  1134  			continue
  1135  		}
  1136  		if item.enumerable == _ENUM_UNKNOWN {
  1137  			var prop Value
  1138  			if item.value == nil {
  1139  				prop = i.o.getOwnProp(item.name)
  1140  			} else {
  1141  				prop = item.value
  1142  			}
  1143  			if prop == nil {
  1144  				continue
  1145  			}
  1146  			if prop, ok := prop.(*valueProperty); ok {
  1147  				if !prop.enumerable {
  1148  					continue
  1149  				}
  1150  			}
  1151  		}
  1152  		return item, i.next
  1153  	}
  1154  }
  1155  
  1156  func (i *recursivePropIter) next() (propIterItem, iterNextFunc) {
  1157  	for {
  1158  		var item propIterItem
  1159  		item, i.cur = i.cur()
  1160  		if i.cur == nil {
  1161  			if proto := i.o.proto(); proto != nil {
  1162  				i.cur = proto.self.iterateStringKeys()
  1163  				i.o = proto.self
  1164  				continue
  1165  			}
  1166  			return propIterItem{}, nil
  1167  		}
  1168  		name := item.name.string()
  1169  		if _, exists := i.seen[name]; !exists {
  1170  			i.seen[name] = struct{}{}
  1171  			return item, i.next
  1172  		}
  1173  	}
  1174  }
  1175  
  1176  func enumerateRecursive(o *Object) iterNextFunc {
  1177  	return (&enumerableIter{
  1178  		o: o,
  1179  		wrapped: (&recursivePropIter{
  1180  			o:    o.self,
  1181  			cur:  o.self.iterateStringKeys(),
  1182  			seen: make(map[unistring.String]struct{}),
  1183  		}).next,
  1184  	}).next
  1185  }
  1186  
  1187  func (i *objectPropIter) next() (propIterItem, iterNextFunc) {
  1188  	for i.idx < len(i.propNames) {
  1189  		name := i.propNames[i.idx]
  1190  		i.idx++
  1191  		prop := i.o.values[name]
  1192  		if prop != nil {
  1193  			return propIterItem{name: stringValueFromRaw(name), value: prop}, i.next
  1194  		}
  1195  	}
  1196  	clearNamesCopyMarker(i.propNames)
  1197  	return propIterItem{}, nil
  1198  }
  1199  
  1200  var copyMarker = unistring.String(" ")
  1201  
  1202  // Set a copy-on-write flag so that any subsequent modifications of anything below the current length
  1203  // trigger a copy.
  1204  // The marker is a special value put at the index position of cap-1. Capacity is set so that the marker is
  1205  // beyond the current length (therefore invisible to normal slice operations).
  1206  // This function is called before an iteration begins to avoid copying of the names array if
  1207  // there are no modifications within the iteration.
  1208  // Note that the copying also occurs in two cases: nested iterations (on the same object) and
  1209  // iterations after a previously abandoned iteration (because there is currently no mechanism to close an
  1210  // iterator). It is still better than copying every time.
  1211  func prepareNamesForCopy(names []unistring.String) []unistring.String {
  1212  	if len(names) == 0 {
  1213  		return names
  1214  	}
  1215  	if namesMarkedForCopy(names) || cap(names) == len(names) {
  1216  		var newcap int
  1217  		if cap(names) == len(names) {
  1218  			newcap = growCap(len(names)+1, len(names), cap(names))
  1219  		} else {
  1220  			newcap = cap(names)
  1221  		}
  1222  		newNames := make([]unistring.String, len(names), newcap)
  1223  		copy(newNames, names)
  1224  		names = newNames
  1225  	}
  1226  	names[cap(names)-1 : cap(names)][0] = copyMarker
  1227  	return names
  1228  }
  1229  
  1230  func namesMarkedForCopy(names []unistring.String) bool {
  1231  	return cap(names) > len(names) && names[cap(names)-1 : cap(names)][0] == copyMarker
  1232  }
  1233  
  1234  func clearNamesCopyMarker(names []unistring.String) {
  1235  	if cap(names) > len(names) {
  1236  		names[cap(names)-1 : cap(names)][0] = ""
  1237  	}
  1238  }
  1239  
  1240  func copyNamesIfNeeded(names []unistring.String, extraCap int) []unistring.String {
  1241  	if namesMarkedForCopy(names) && len(names)+extraCap >= cap(names) {
  1242  		var newcap int
  1243  		newsize := len(names) + extraCap + 1
  1244  		if newsize > cap(names) {
  1245  			newcap = growCap(newsize, len(names), cap(names))
  1246  		} else {
  1247  			newcap = cap(names)
  1248  		}
  1249  		newNames := make([]unistring.String, len(names), newcap)
  1250  		copy(newNames, names)
  1251  		return newNames
  1252  	}
  1253  	return names
  1254  }
  1255  
  1256  func (o *baseObject) iterateStringKeys() iterNextFunc {
  1257  	o.ensurePropOrder()
  1258  	propNames := prepareNamesForCopy(o.propNames)
  1259  	o.propNames = propNames
  1260  	return (&objectPropIter{
  1261  		o:         o,
  1262  		propNames: propNames,
  1263  	}).next
  1264  }
  1265  
  1266  type objectSymbolIter struct {
  1267  	iter *orderedMapIter
  1268  }
  1269  
  1270  func (i *objectSymbolIter) next() (propIterItem, iterNextFunc) {
  1271  	entry := i.iter.next()
  1272  	if entry != nil {
  1273  		return propIterItem{
  1274  			name:  entry.key,
  1275  			value: entry.value,
  1276  		}, i.next
  1277  	}
  1278  	return propIterItem{}, nil
  1279  }
  1280  
  1281  func (o *baseObject) iterateSymbols() iterNextFunc {
  1282  	if o.symValues != nil {
  1283  		return (&objectSymbolIter{
  1284  			iter: o.symValues.newIter(),
  1285  		}).next
  1286  	}
  1287  	return func() (propIterItem, iterNextFunc) {
  1288  		return propIterItem{}, nil
  1289  	}
  1290  }
  1291  
  1292  type objectAllPropIter struct {
  1293  	o      *Object
  1294  	curStr iterNextFunc
  1295  }
  1296  
  1297  func (i *objectAllPropIter) next() (propIterItem, iterNextFunc) {
  1298  	item, next := i.curStr()
  1299  	if next != nil {
  1300  		i.curStr = next
  1301  		return item, i.next
  1302  	}
  1303  	return i.o.self.iterateSymbols()()
  1304  }
  1305  
  1306  func (o *baseObject) iterateKeys() iterNextFunc {
  1307  	return (&objectAllPropIter{
  1308  		o:      o.val,
  1309  		curStr: o.val.self.iterateStringKeys(),
  1310  	}).next
  1311  }
  1312  
  1313  func (o *baseObject) equal(objectImpl) bool {
  1314  	// Rely on parent reference comparison
  1315  	return false
  1316  }
  1317  
  1318  // hopefully this gets inlined
  1319  func (o *baseObject) ensurePropOrder() {
  1320  	if o.lastSortedPropLen < len(o.propNames) {
  1321  		o.fixPropOrder()
  1322  	}
  1323  }
  1324  
  1325  // Reorder property names so that any integer properties are shifted to the beginning of the list
  1326  // in ascending order. This is to conform to https://262.ecma-international.org/#sec-ordinaryownpropertykeys.
  1327  // Personally I think this requirement is strange. I can sort of understand where they are coming from,
  1328  // this way arrays can be specified just as objects with a 'magic' length property. However, I think
  1329  // it's safe to assume most devs don't use Objects to store integer properties. Therefore, performing
  1330  // property type checks when adding (and potentially looking up) properties would be unreasonable.
  1331  // Instead, we keep insertion order and only change it when (if) the properties get enumerated.
  1332  func (o *baseObject) fixPropOrder() {
  1333  	names := o.propNames
  1334  	for i := o.lastSortedPropLen; i < len(names); i++ {
  1335  		name := names[i]
  1336  		if idx := strToArrayIdx(name); idx != math.MaxUint32 {
  1337  			k := sort.Search(o.idxPropCount, func(j int) bool {
  1338  				return strToArrayIdx(names[j]) >= idx
  1339  			})
  1340  			if k < i {
  1341  				if namesMarkedForCopy(names) {
  1342  					newNames := make([]unistring.String, len(names), cap(names))
  1343  					copy(newNames[:k], names)
  1344  					copy(newNames[k+1:i+1], names[k:i])
  1345  					copy(newNames[i+1:], names[i+1:])
  1346  					names = newNames
  1347  					o.propNames = names
  1348  				} else {
  1349  					copy(names[k+1:i+1], names[k:i])
  1350  				}
  1351  				names[k] = name
  1352  			}
  1353  			o.idxPropCount++
  1354  		}
  1355  	}
  1356  	o.lastSortedPropLen = len(names)
  1357  }
  1358  
  1359  func (o *baseObject) stringKeys(all bool, keys []Value) []Value {
  1360  	o.ensurePropOrder()
  1361  	if all {
  1362  		for _, k := range o.propNames {
  1363  			keys = append(keys, stringValueFromRaw(k))
  1364  		}
  1365  	} else {
  1366  		for _, k := range o.propNames {
  1367  			prop := o.values[k]
  1368  			if prop, ok := prop.(*valueProperty); ok && !prop.enumerable {
  1369  				continue
  1370  			}
  1371  			keys = append(keys, stringValueFromRaw(k))
  1372  		}
  1373  	}
  1374  	return keys
  1375  }
  1376  
  1377  func (o *baseObject) symbols(all bool, accum []Value) []Value {
  1378  	if o.symValues != nil {
  1379  		iter := o.symValues.newIter()
  1380  		if all {
  1381  			for {
  1382  				entry := iter.next()
  1383  				if entry == nil {
  1384  					break
  1385  				}
  1386  				accum = append(accum, entry.key)
  1387  			}
  1388  		} else {
  1389  			for {
  1390  				entry := iter.next()
  1391  				if entry == nil {
  1392  					break
  1393  				}
  1394  				if prop, ok := entry.value.(*valueProperty); ok {
  1395  					if !prop.enumerable {
  1396  						continue
  1397  					}
  1398  				}
  1399  				accum = append(accum, entry.key)
  1400  			}
  1401  		}
  1402  	}
  1403  
  1404  	return accum
  1405  }
  1406  
  1407  func (o *baseObject) keys(all bool, accum []Value) []Value {
  1408  	return o.symbols(all, o.val.self.stringKeys(all, accum))
  1409  }
  1410  
  1411  func (o *baseObject) hasInstance(Value) bool {
  1412  	panic(o.val.runtime.NewTypeError("Expecting a function in instanceof check, but got %s", o.val.toString()))
  1413  }
  1414  
  1415  func toMethod(v Value) func(FunctionCall) Value {
  1416  	if v == nil || IsUndefined(v) || IsNull(v) {
  1417  		return nil
  1418  	}
  1419  	if obj, ok := v.(*Object); ok {
  1420  		if call, ok := obj.self.assertCallable(); ok {
  1421  			return call
  1422  		}
  1423  	}
  1424  	panic(newTypeError("%s is not a method", v.String()))
  1425  }
  1426  
  1427  func instanceOfOperator(o Value, c *Object) bool {
  1428  	if instOfHandler := toMethod(c.self.getSym(SymHasInstance, c)); instOfHandler != nil {
  1429  		return instOfHandler(FunctionCall{
  1430  			This:      c,
  1431  			Arguments: []Value{o},
  1432  		}).ToBoolean()
  1433  	}
  1434  
  1435  	return c.self.hasInstance(o)
  1436  }
  1437  
  1438  func (o *Object) get(p Value, receiver Value) Value {
  1439  	switch p := p.(type) {
  1440  	case valueInt:
  1441  		return o.self.getIdx(p, receiver)
  1442  	case *Symbol:
  1443  		return o.self.getSym(p, receiver)
  1444  	default:
  1445  		return o.self.getStr(p.string(), receiver)
  1446  	}
  1447  }
  1448  
  1449  func (o *Object) getOwnProp(p Value) Value {
  1450  	switch p := p.(type) {
  1451  	case valueInt:
  1452  		return o.self.getOwnPropIdx(p)
  1453  	case *Symbol:
  1454  		return o.self.getOwnPropSym(p)
  1455  	default:
  1456  		return o.self.getOwnPropStr(p.string())
  1457  	}
  1458  }
  1459  
  1460  func (o *Object) hasOwnProperty(p Value) bool {
  1461  	switch p := p.(type) {
  1462  	case valueInt:
  1463  		return o.self.hasOwnPropertyIdx(p)
  1464  	case *Symbol:
  1465  		return o.self.hasOwnPropertySym(p)
  1466  	default:
  1467  		return o.self.hasOwnPropertyStr(p.string())
  1468  	}
  1469  }
  1470  
  1471  func (o *Object) hasProperty(p Value) bool {
  1472  	switch p := p.(type) {
  1473  	case valueInt:
  1474  		return o.self.hasPropertyIdx(p)
  1475  	case *Symbol:
  1476  		return o.self.hasPropertySym(p)
  1477  	default:
  1478  		return o.self.hasPropertyStr(p.string())
  1479  	}
  1480  }
  1481  
  1482  func (o *Object) setStr(name unistring.String, val, receiver Value, throw bool) bool {
  1483  	if receiver == o {
  1484  		return o.self.setOwnStr(name, val, throw)
  1485  	} else {
  1486  		if res, ok := o.self.setForeignStr(name, val, receiver, throw); !ok {
  1487  			if robj, ok := receiver.(*Object); ok {
  1488  				if prop := robj.self.getOwnPropStr(name); prop != nil {
  1489  					if desc, ok := prop.(*valueProperty); ok {
  1490  						if desc.accessor {
  1491  							o.runtime.typeErrorResult(throw, "Receiver property %s is an accessor", name)
  1492  							return false
  1493  						}
  1494  						if !desc.writable {
  1495  							o.runtime.typeErrorResult(throw, "Cannot assign to read only property '%s'", name)
  1496  							return false
  1497  						}
  1498  					}
  1499  					return robj.self.defineOwnPropertyStr(name, PropertyDescriptor{Value: val}, throw)
  1500  				} else {
  1501  					return robj.self.defineOwnPropertyStr(name, PropertyDescriptor{
  1502  						Value:        val,
  1503  						Writable:     FLAG_TRUE,
  1504  						Configurable: FLAG_TRUE,
  1505  						Enumerable:   FLAG_TRUE,
  1506  					}, throw)
  1507  				}
  1508  			} else {
  1509  				o.runtime.typeErrorResult(throw, "Receiver is not an object: %v", receiver)
  1510  				return false
  1511  			}
  1512  		} else {
  1513  			return res
  1514  		}
  1515  	}
  1516  }
  1517  
  1518  func (o *Object) set(name Value, val, receiver Value, throw bool) bool {
  1519  	switch name := name.(type) {
  1520  	case valueInt:
  1521  		return o.setIdx(name, val, receiver, throw)
  1522  	case *Symbol:
  1523  		return o.setSym(name, val, receiver, throw)
  1524  	default:
  1525  		return o.setStr(name.string(), val, receiver, throw)
  1526  	}
  1527  }
  1528  
  1529  func (o *Object) setOwn(name Value, val Value, throw bool) bool {
  1530  	switch name := name.(type) {
  1531  	case valueInt:
  1532  		return o.self.setOwnIdx(name, val, throw)
  1533  	case *Symbol:
  1534  		return o.self.setOwnSym(name, val, throw)
  1535  	default:
  1536  		return o.self.setOwnStr(name.string(), val, throw)
  1537  	}
  1538  }
  1539  
  1540  func (o *Object) setIdx(name valueInt, val, receiver Value, throw bool) bool {
  1541  	if receiver == o {
  1542  		return o.self.setOwnIdx(name, val, throw)
  1543  	} else {
  1544  		if res, ok := o.self.setForeignIdx(name, val, receiver, throw); !ok {
  1545  			if robj, ok := receiver.(*Object); ok {
  1546  				if prop := robj.self.getOwnPropIdx(name); prop != nil {
  1547  					if desc, ok := prop.(*valueProperty); ok {
  1548  						if desc.accessor {
  1549  							o.runtime.typeErrorResult(throw, "Receiver property %s is an accessor", name)
  1550  							return false
  1551  						}
  1552  						if !desc.writable {
  1553  							o.runtime.typeErrorResult(throw, "Cannot assign to read only property '%s'", name)
  1554  							return false
  1555  						}
  1556  					}
  1557  					robj.self.defineOwnPropertyIdx(name, PropertyDescriptor{Value: val}, throw)
  1558  				} else {
  1559  					robj.self.defineOwnPropertyIdx(name, PropertyDescriptor{
  1560  						Value:        val,
  1561  						Writable:     FLAG_TRUE,
  1562  						Configurable: FLAG_TRUE,
  1563  						Enumerable:   FLAG_TRUE,
  1564  					}, throw)
  1565  				}
  1566  			} else {
  1567  				o.runtime.typeErrorResult(throw, "Receiver is not an object: %v", receiver)
  1568  				return false
  1569  			}
  1570  		} else {
  1571  			return res
  1572  		}
  1573  	}
  1574  	return true
  1575  }
  1576  
  1577  func (o *Object) setSym(name *Symbol, val, receiver Value, throw bool) bool {
  1578  	if receiver == o {
  1579  		return o.self.setOwnSym(name, val, throw)
  1580  	} else {
  1581  		if res, ok := o.self.setForeignSym(name, val, receiver, throw); !ok {
  1582  			if robj, ok := receiver.(*Object); ok {
  1583  				if prop := robj.self.getOwnPropSym(name); prop != nil {
  1584  					if desc, ok := prop.(*valueProperty); ok {
  1585  						if desc.accessor {
  1586  							o.runtime.typeErrorResult(throw, "Receiver property %s is an accessor", name)
  1587  							return false
  1588  						}
  1589  						if !desc.writable {
  1590  							o.runtime.typeErrorResult(throw, "Cannot assign to read only property '%s'", name)
  1591  							return false
  1592  						}
  1593  					}
  1594  					robj.self.defineOwnPropertySym(name, PropertyDescriptor{Value: val}, throw)
  1595  				} else {
  1596  					robj.self.defineOwnPropertySym(name, PropertyDescriptor{
  1597  						Value:        val,
  1598  						Writable:     FLAG_TRUE,
  1599  						Configurable: FLAG_TRUE,
  1600  						Enumerable:   FLAG_TRUE,
  1601  					}, throw)
  1602  				}
  1603  			} else {
  1604  				o.runtime.typeErrorResult(throw, "Receiver is not an object: %v", receiver)
  1605  				return false
  1606  			}
  1607  		} else {
  1608  			return res
  1609  		}
  1610  	}
  1611  	return true
  1612  }
  1613  
  1614  func (o *Object) delete(n Value, throw bool) bool {
  1615  	switch n := n.(type) {
  1616  	case valueInt:
  1617  		return o.self.deleteIdx(n, throw)
  1618  	case *Symbol:
  1619  		return o.self.deleteSym(n, throw)
  1620  	default:
  1621  		return o.self.deleteStr(n.string(), throw)
  1622  	}
  1623  }
  1624  
  1625  func (o *Object) defineOwnProperty(n Value, desc PropertyDescriptor, throw bool) bool {
  1626  	switch n := n.(type) {
  1627  	case valueInt:
  1628  		return o.self.defineOwnPropertyIdx(n, desc, throw)
  1629  	case *Symbol:
  1630  		return o.self.defineOwnPropertySym(n, desc, throw)
  1631  	default:
  1632  		return o.self.defineOwnPropertyStr(n.string(), desc, throw)
  1633  	}
  1634  }
  1635  
  1636  func (o *Object) getWeakRefs() map[weakMap]Value {
  1637  	refs := o.weakRefs
  1638  	if refs == nil {
  1639  		refs = make(map[weakMap]Value)
  1640  		o.weakRefs = refs
  1641  	}
  1642  	return refs
  1643  }
  1644  
  1645  func (o *Object) getId() uint64 {
  1646  	id := o.id
  1647  	if id == 0 {
  1648  		id = o.runtime.genId()
  1649  		o.id = id
  1650  	}
  1651  	return id
  1652  }
  1653  
  1654  func (o *guardedObject) guard(props ...unistring.String) {
  1655  	if o.guardedProps == nil {
  1656  		o.guardedProps = make(map[unistring.String]struct{})
  1657  	}
  1658  	for _, p := range props {
  1659  		o.guardedProps[p] = struct{}{}
  1660  	}
  1661  }
  1662  
  1663  func (o *guardedObject) check(p unistring.String) {
  1664  	if _, exists := o.guardedProps[p]; exists {
  1665  		o.val.self = &o.baseObject
  1666  	}
  1667  }
  1668  
  1669  func (o *guardedObject) setOwnStr(p unistring.String, v Value, throw bool) bool {
  1670  	res := o.baseObject.setOwnStr(p, v, throw)
  1671  	if res {
  1672  		o.check(p)
  1673  	}
  1674  	return res
  1675  }
  1676  
  1677  func (o *guardedObject) defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool {
  1678  	res := o.baseObject.defineOwnPropertyStr(name, desc, throw)
  1679  	if res {
  1680  		o.check(name)
  1681  	}
  1682  	return res
  1683  }
  1684  
  1685  func (o *guardedObject) deleteStr(name unistring.String, throw bool) bool {
  1686  	res := o.baseObject.deleteStr(name, throw)
  1687  	if res {
  1688  		o.check(name)
  1689  	}
  1690  	return res
  1691  }
  1692  
  1693  func (ctx *objectExportCtx) get(key *Object) (interface{}, bool) {
  1694  	if v, exists := ctx.cache[key]; exists {
  1695  		if item, ok := v.(objectExportCacheItem); ok {
  1696  			r, exists := item[key.self.exportType()]
  1697  			return r, exists
  1698  		} else {
  1699  			return v, true
  1700  		}
  1701  	}
  1702  	return nil, false
  1703  }
  1704  
  1705  func (ctx *objectExportCtx) getTyped(key *Object, typ reflect.Type) (interface{}, bool) {
  1706  	if v, exists := ctx.cache[key]; exists {
  1707  		if item, ok := v.(objectExportCacheItem); ok {
  1708  			r, exists := item[typ]
  1709  			return r, exists
  1710  		} else {
  1711  			if reflect.TypeOf(v) == typ {
  1712  				return v, true
  1713  			}
  1714  		}
  1715  	}
  1716  	return nil, false
  1717  }
  1718  
  1719  func (ctx *objectExportCtx) put(key *Object, value interface{}) {
  1720  	if ctx.cache == nil {
  1721  		ctx.cache = make(map[*Object]interface{})
  1722  	}
  1723  	if item, ok := ctx.cache[key].(objectExportCacheItem); ok {
  1724  		item[key.self.exportType()] = value
  1725  	} else {
  1726  		ctx.cache[key] = value
  1727  	}
  1728  }
  1729  
  1730  func (ctx *objectExportCtx) putTyped(key *Object, typ reflect.Type, value interface{}) {
  1731  	if ctx.cache == nil {
  1732  		ctx.cache = make(map[*Object]interface{})
  1733  	}
  1734  	v, exists := ctx.cache[key]
  1735  	if exists {
  1736  		if item, ok := ctx.cache[key].(objectExportCacheItem); ok {
  1737  			item[typ] = value
  1738  		} else {
  1739  			m := make(objectExportCacheItem, 2)
  1740  			m[key.self.exportType()] = v
  1741  			m[typ] = value
  1742  			ctx.cache[key] = m
  1743  		}
  1744  	} else {
  1745  		m := make(objectExportCacheItem)
  1746  		m[typ] = value
  1747  		ctx.cache[key] = m
  1748  	}
  1749  }
  1750  
  1751  type enumPropertiesIter struct {
  1752  	o       *Object
  1753  	wrapped iterNextFunc
  1754  }
  1755  
  1756  func (i *enumPropertiesIter) next() (propIterItem, iterNextFunc) {
  1757  	for i.wrapped != nil {
  1758  		item, next := i.wrapped()
  1759  		i.wrapped = next
  1760  		if next == nil {
  1761  			break
  1762  		}
  1763  		if item.value == nil {
  1764  			item.value = i.o.get(item.name, nil)
  1765  			if item.value == nil {
  1766  				continue
  1767  			}
  1768  		} else {
  1769  			if prop, ok := item.value.(*valueProperty); ok {
  1770  				item.value = prop.get(i.o)
  1771  			}
  1772  		}
  1773  		return item, i.next
  1774  	}
  1775  	return propIterItem{}, nil
  1776  }
  1777  
  1778  func iterateEnumerableProperties(o *Object) iterNextFunc {
  1779  	return (&enumPropertiesIter{
  1780  		o: o,
  1781  		wrapped: (&enumerableIter{
  1782  			o:       o,
  1783  			wrapped: o.self.iterateKeys(),
  1784  		}).next,
  1785  	}).next
  1786  }
  1787  
  1788  func iterateEnumerableStringProperties(o *Object) iterNextFunc {
  1789  	return (&enumPropertiesIter{
  1790  		o: o,
  1791  		wrapped: (&enumerableIter{
  1792  			o:       o,
  1793  			wrapped: o.self.iterateStringKeys(),
  1794  		}).next,
  1795  	}).next
  1796  }
  1797  
  1798  type privateId struct {
  1799  	typ      *privateEnvType
  1800  	name     unistring.String
  1801  	idx      uint32
  1802  	isMethod bool
  1803  }
  1804  
  1805  type privateEnvType struct {
  1806  	numFields, numMethods uint32
  1807  }
  1808  
  1809  type privateNames map[unistring.String]*privateId
  1810  
  1811  type privateEnv struct {
  1812  	instanceType, staticType *privateEnvType
  1813  
  1814  	names privateNames
  1815  
  1816  	outer *privateEnv
  1817  }
  1818  
  1819  type privateElements struct {
  1820  	methods []Value
  1821  	fields  []Value
  1822  }
  1823  
  1824  func (i *privateId) String() string {
  1825  	return "#" + i.name.String()
  1826  }
  1827  
  1828  func (i *privateId) string() unistring.String {
  1829  	return privateIdString(i.name)
  1830  }