object_gomap_reflect.go 6.8 KB

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