github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/object_gomap.go (about) 1 package goja 2 3 import ( 4 "reflect" 5 6 "github.com/nuvolaris/goja/unistring" 7 ) 8 9 type objectGoMapSimple struct { 10 baseObject 11 data map[string]interface{} 12 } 13 14 func (o *objectGoMapSimple) init() { 15 o.baseObject.init() 16 o.prototype = o.val.runtime.global.ObjectPrototype 17 o.class = classObject 18 o.extensible = true 19 } 20 21 func (o *objectGoMapSimple) _getStr(name string) Value { 22 v, exists := o.data[name] 23 if !exists { 24 return nil 25 } 26 return o.val.runtime.ToValue(v) 27 } 28 29 func (o *objectGoMapSimple) getStr(name unistring.String, receiver Value) Value { 30 if v := o._getStr(name.String()); v != nil { 31 return v 32 } 33 return o.baseObject.getStr(name, receiver) 34 } 35 36 func (o *objectGoMapSimple) getOwnPropStr(name unistring.String) Value { 37 if v := o._getStr(name.String()); v != nil { 38 return v 39 } 40 return nil 41 } 42 43 func (o *objectGoMapSimple) setOwnStr(name unistring.String, val Value, throw bool) bool { 44 n := name.String() 45 if _, exists := o.data[n]; exists { 46 o.data[n] = val.Export() 47 return true 48 } 49 if proto := o.prototype; proto != nil { 50 // we know it's foreign because prototype loops are not allowed 51 if res, ok := proto.self.setForeignStr(name, val, o.val, throw); ok { 52 return res 53 } 54 } 55 // new property 56 if !o.extensible { 57 o.val.runtime.typeErrorResult(throw, "Cannot add property %s, object is not extensible", name) 58 return false 59 } else { 60 o.data[n] = val.Export() 61 } 62 return true 63 } 64 65 func trueValIfPresent(present bool) Value { 66 if present { 67 return valueTrue 68 } 69 return nil 70 } 71 72 func (o *objectGoMapSimple) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) { 73 return o._setForeignStr(name, trueValIfPresent(o._hasStr(name.String())), val, receiver, throw) 74 } 75 76 func (o *objectGoMapSimple) _hasStr(name string) bool { 77 _, exists := o.data[name] 78 return exists 79 } 80 81 func (o *objectGoMapSimple) hasOwnPropertyStr(name unistring.String) bool { 82 return o._hasStr(name.String()) 83 } 84 85 func (o *objectGoMapSimple) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool { 86 if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) { 87 return false 88 } 89 90 n := name.String() 91 if o.extensible || o._hasStr(n) { 92 o.data[n] = descr.Value.Export() 93 return true 94 } 95 96 o.val.runtime.typeErrorResult(throw, "Cannot define property %s, object is not extensible", n) 97 return false 98 } 99 100 func (o *objectGoMapSimple) deleteStr(name unistring.String, _ bool) bool { 101 delete(o.data, name.String()) 102 return true 103 } 104 105 type gomapPropIter struct { 106 o *objectGoMapSimple 107 propNames []string 108 idx int 109 } 110 111 func (i *gomapPropIter) next() (propIterItem, iterNextFunc) { 112 for i.idx < len(i.propNames) { 113 name := i.propNames[i.idx] 114 i.idx++ 115 if _, exists := i.o.data[name]; exists { 116 return propIterItem{name: newStringValue(name), enumerable: _ENUM_TRUE}, i.next 117 } 118 } 119 120 return propIterItem{}, nil 121 } 122 123 func (o *objectGoMapSimple) iterateStringKeys() iterNextFunc { 124 propNames := make([]string, len(o.data)) 125 i := 0 126 for key := range o.data { 127 propNames[i] = key 128 i++ 129 } 130 131 return (&gomapPropIter{ 132 o: o, 133 propNames: propNames, 134 }).next 135 } 136 137 func (o *objectGoMapSimple) stringKeys(_ bool, accum []Value) []Value { 138 // all own keys are enumerable 139 for key := range o.data { 140 accum = append(accum, newStringValue(key)) 141 } 142 return accum 143 } 144 145 func (o *objectGoMapSimple) export(*objectExportCtx) interface{} { 146 return o.data 147 } 148 149 func (o *objectGoMapSimple) exportType() reflect.Type { 150 return reflectTypeMap 151 } 152 153 func (o *objectGoMapSimple) equal(other objectImpl) bool { 154 if other, ok := other.(*objectGoMapSimple); ok { 155 return o == other 156 } 157 return false 158 }