object_gomap_reflect.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. package goja
  2. import "reflect"
  3. type objectGoMapReflect struct {
  4. objectGoReflect
  5. keyType, valueType reflect.Type
  6. }
  7. func (o *objectGoMapReflect) init() {
  8. o.objectGoReflect.init()
  9. o.keyType = o.value.Type().Key()
  10. o.valueType = o.value.Type().Elem()
  11. }
  12. func (o *objectGoMapReflect) toKey(n Value, throw bool) reflect.Value {
  13. key, err := o.val.runtime.toReflectValue(n, o.keyType)
  14. if err != nil {
  15. o.val.runtime.typeErrorResult(throw, "map key conversion error: %v", err)
  16. return reflect.Value{}
  17. }
  18. return key
  19. }
  20. func (o *objectGoMapReflect) strToKey(name string, throw bool) reflect.Value {
  21. if o.keyType.Kind() == reflect.String {
  22. return reflect.ValueOf(name).Convert(o.keyType)
  23. }
  24. return o.toKey(newStringValue(name), throw)
  25. }
  26. func (o *objectGoMapReflect) _get(n Value) Value {
  27. key := o.toKey(n, false)
  28. if !key.IsValid() {
  29. return nil
  30. }
  31. if v := o.value.MapIndex(key); v.IsValid() {
  32. return o.val.runtime.ToValue(v.Interface())
  33. }
  34. return nil
  35. }
  36. func (o *objectGoMapReflect) _getStr(name string) Value {
  37. key := o.strToKey(name, false)
  38. if !key.IsValid() {
  39. return nil
  40. }
  41. if v := o.value.MapIndex(key); v.IsValid() {
  42. return o.val.runtime.ToValue(v.Interface())
  43. }
  44. return nil
  45. }
  46. func (o *objectGoMapReflect) getStr(name string, receiver Value) Value {
  47. if v := o._getStr(name); v != nil {
  48. return v
  49. }
  50. return o.objectGoReflect.getStr(name, receiver)
  51. }
  52. func (o *objectGoMapReflect) getIdx(idx valueInt, receiver Value) Value {
  53. if v := o._get(idx); v != nil {
  54. return v
  55. }
  56. return o.objectGoReflect.getIdx(idx, receiver)
  57. }
  58. func (o *objectGoMapReflect) getOwnPropStr(name string) Value {
  59. if v := o._getStr(name); v != nil {
  60. return &valueProperty{
  61. value: v,
  62. writable: true,
  63. enumerable: true,
  64. }
  65. }
  66. return o.objectGoReflect.getOwnPropStr(name)
  67. }
  68. func (o *objectGoMapReflect) getOwnPropIdx(idx valueInt) Value {
  69. if v := o._get(idx); v != nil {
  70. return &valueProperty{
  71. value: v,
  72. writable: true,
  73. enumerable: true,
  74. }
  75. }
  76. return o.objectGoReflect.getOwnPropStr(idx.String())
  77. }
  78. func (o *objectGoMapReflect) toValue(val Value, throw bool) (reflect.Value, bool) {
  79. v, err := o.val.runtime.toReflectValue(val, o.valueType)
  80. if err != nil {
  81. o.val.runtime.typeErrorResult(throw, "map value conversion error: %v", err)
  82. return reflect.Value{}, false
  83. }
  84. return v, true
  85. }
  86. func (o *objectGoMapReflect) _put(key reflect.Value, val Value, throw bool) bool {
  87. if key.IsValid() {
  88. if o.extensible || o.value.MapIndex(key).IsValid() {
  89. v, ok := o.toValue(val, throw)
  90. if !ok {
  91. return false
  92. }
  93. o.value.SetMapIndex(key, v)
  94. } else {
  95. o.val.runtime.typeErrorResult(throw, "Cannot set property %s, object is not extensible", key.String())
  96. return false
  97. }
  98. return true
  99. }
  100. return false
  101. }
  102. func (o *objectGoMapReflect) setOwnStr(name string, val Value, throw bool) bool {
  103. key := o.strToKey(name, false)
  104. if !key.IsValid() || !o.value.MapIndex(key).IsValid() {
  105. if proto := o.prototype; proto != nil {
  106. // we know it's foreign because prototype loops are not allowed
  107. if res, ok := proto.self.setForeignStr(name, val, o.val, throw); ok {
  108. return res
  109. }
  110. }
  111. // new property
  112. if !o.extensible {
  113. o.val.runtime.typeErrorResult(throw, "Cannot add property %s, object is not extensible", name)
  114. return false
  115. } else {
  116. if throw && !key.IsValid() {
  117. o.strToKey(name, true)
  118. return false
  119. }
  120. }
  121. }
  122. o._put(key, val, throw)
  123. return true
  124. }
  125. func (o *objectGoMapReflect) setOwnIdx(idx valueInt, val Value, throw bool) bool {
  126. key := o.toKey(idx, false)
  127. if !key.IsValid() || !o.value.MapIndex(key).IsValid() {
  128. if proto := o.prototype; proto != nil {
  129. // we know it's foreign because prototype loops are not allowed
  130. if res, ok := proto.self.setForeignIdx(idx, val, o.val, throw); ok {
  131. return res
  132. }
  133. }
  134. // new property
  135. if !o.extensible {
  136. o.val.runtime.typeErrorResult(throw, "Cannot add property %d, object is not extensible", idx)
  137. return false
  138. } else {
  139. if throw && !key.IsValid() {
  140. o.toKey(idx, true)
  141. return false
  142. }
  143. }
  144. }
  145. o._put(key, val, throw)
  146. return true
  147. }
  148. func (o *objectGoMapReflect) setForeignStr(name string, val, receiver Value, throw bool) (bool, bool) {
  149. return o._setForeignStr(name, trueValIfPresent(o.hasOwnPropertyStr(name)), val, receiver, throw)
  150. }
  151. func (o *objectGoMapReflect) setForeignIdx(idx valueInt, val, receiver Value, throw bool) (bool, bool) {
  152. return o._setForeignIdx(idx, trueValIfPresent(o.hasOwnPropertyIdx(idx)), val, receiver, throw)
  153. }
  154. func (o *objectGoMapReflect) defineOwnPropertyStr(name string, descr PropertyDescriptor, throw bool) bool {
  155. if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) {
  156. return false
  157. }
  158. return o._put(o.strToKey(name, throw), descr.Value, throw)
  159. }
  160. func (o *objectGoMapReflect) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
  161. if !o.val.runtime.checkHostObjectPropertyDescr(idx.String(), descr, throw) {
  162. return false
  163. }
  164. return o._put(o.toKey(idx, throw), descr.Value, throw)
  165. }
  166. func (o *objectGoMapReflect) hasOwnPropertyStr(name string) bool {
  167. key := o.strToKey(name, false)
  168. if key.IsValid() && o.value.MapIndex(key).IsValid() {
  169. return true
  170. }
  171. return false
  172. }
  173. func (o *objectGoMapReflect) hasOwnPropertyIdx(idx valueInt) bool {
  174. key := o.toKey(idx, false)
  175. if key.IsValid() && o.value.MapIndex(key).IsValid() {
  176. return true
  177. }
  178. return false
  179. }
  180. func (o *objectGoMapReflect) deleteStr(name string, throw bool) bool {
  181. key := o.strToKey(name, throw)
  182. if !key.IsValid() {
  183. return false
  184. }
  185. o.value.SetMapIndex(key, reflect.Value{})
  186. return true
  187. }
  188. func (o *objectGoMapReflect) deleteIdx(idx valueInt, throw bool) bool {
  189. key := o.toKey(idx, throw)
  190. if !key.IsValid() {
  191. return false
  192. }
  193. o.value.SetMapIndex(key, reflect.Value{})
  194. return true
  195. }
  196. type gomapReflectPropIter struct {
  197. o *objectGoMapReflect
  198. keys []reflect.Value
  199. idx int
  200. }
  201. func (i *gomapReflectPropIter) next() (propIterItem, iterNextFunc) {
  202. for i.idx < len(i.keys) {
  203. key := i.keys[i.idx]
  204. v := i.o.value.MapIndex(key)
  205. i.idx++
  206. if v.IsValid() {
  207. return propIterItem{name: key.String(), enumerable: _ENUM_TRUE}, i.next
  208. }
  209. }
  210. if i.o.prototype != nil {
  211. return i.o.prototype.self.enumerateUnfiltered()()
  212. }
  213. return propIterItem{}, nil
  214. }
  215. func (o *objectGoMapReflect) enumerateUnfiltered() iterNextFunc {
  216. return (&gomapReflectPropIter{
  217. o: o,
  218. keys: o.value.MapKeys(),
  219. }).next
  220. }
  221. func (o *objectGoMapReflect) ownKeys(_ bool, accum []Value) []Value {
  222. // all own keys are enumerable
  223. for _, key := range o.value.MapKeys() {
  224. accum = append(accum, newStringValue(key.String()))
  225. }
  226. return accum
  227. }
  228. func (o *objectGoMapReflect) equal(other objectImpl) bool {
  229. if other, ok := other.(*objectGoMapReflect); ok {
  230. return o.value.Interface() == other.value.Interface()
  231. }
  232. return false
  233. }