builtin_map.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. package goja
  2. import (
  3. "reflect"
  4. )
  5. var mapExportType = reflect.TypeOf([][2]interface{}{})
  6. type mapObject struct {
  7. baseObject
  8. m *orderedMap
  9. }
  10. type mapIterObject struct {
  11. baseObject
  12. iter *orderedMapIter
  13. kind iterationKind
  14. }
  15. func (o *mapIterObject) next() Value {
  16. if o.iter == nil {
  17. return o.val.runtime.createIterResultObject(_undefined, true)
  18. }
  19. entry := o.iter.next()
  20. if entry == nil {
  21. o.iter = nil
  22. return o.val.runtime.createIterResultObject(_undefined, true)
  23. }
  24. var result Value
  25. switch o.kind {
  26. case iterationKindKey:
  27. result = entry.key
  28. case iterationKindValue:
  29. result = entry.value
  30. default:
  31. result = o.val.runtime.newArrayValues([]Value{entry.key, entry.value})
  32. }
  33. return o.val.runtime.createIterResultObject(result, false)
  34. }
  35. func (mo *mapObject) init() {
  36. mo.baseObject.init()
  37. mo.m = newOrderedMap(mo.val.runtime.getHash())
  38. }
  39. func (mo *mapObject) exportType() reflect.Type {
  40. return mapExportType
  41. }
  42. func (mo *mapObject) export(ctx *objectExportCtx) interface{} {
  43. m := make([][2]interface{}, mo.m.size)
  44. ctx.put(mo.val, m)
  45. iter := mo.m.newIter()
  46. for i := 0; i < len(m); i++ {
  47. entry := iter.next()
  48. if entry == nil {
  49. break
  50. }
  51. m[i][0] = exportValue(entry.key, ctx)
  52. m[i][1] = exportValue(entry.value, ctx)
  53. }
  54. return m
  55. }
  56. func (mo *mapObject) exportToMap(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
  57. dst.Set(reflect.MakeMap(typ))
  58. ctx.putTyped(mo.val, typ, dst.Interface())
  59. keyTyp := typ.Key()
  60. elemTyp := typ.Elem()
  61. iter := mo.m.newIter()
  62. r := mo.val.runtime
  63. for {
  64. entry := iter.next()
  65. if entry == nil {
  66. break
  67. }
  68. keyVal := reflect.New(keyTyp).Elem()
  69. err := r.toReflectValue(entry.key, keyVal, ctx)
  70. if err != nil {
  71. return err
  72. }
  73. elemVal := reflect.New(elemTyp).Elem()
  74. err = r.toReflectValue(entry.value, elemVal, ctx)
  75. if err != nil {
  76. return err
  77. }
  78. dst.SetMapIndex(keyVal, elemVal)
  79. }
  80. return nil
  81. }
  82. func (r *Runtime) mapProto_clear(call FunctionCall) Value {
  83. thisObj := r.toObject(call.This)
  84. mo, ok := thisObj.self.(*mapObject)
  85. if !ok {
  86. panic(r.NewTypeError("Method Map.prototype.clear called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
  87. }
  88. mo.m.clear()
  89. return _undefined
  90. }
  91. func (r *Runtime) mapProto_delete(call FunctionCall) Value {
  92. thisObj := r.toObject(call.This)
  93. mo, ok := thisObj.self.(*mapObject)
  94. if !ok {
  95. panic(r.NewTypeError("Method Map.prototype.delete called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
  96. }
  97. return r.toBoolean(mo.m.remove(call.Argument(0)))
  98. }
  99. func (r *Runtime) mapProto_get(call FunctionCall) Value {
  100. thisObj := r.toObject(call.This)
  101. mo, ok := thisObj.self.(*mapObject)
  102. if !ok {
  103. panic(r.NewTypeError("Method Map.prototype.get called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
  104. }
  105. return nilSafe(mo.m.get(call.Argument(0)))
  106. }
  107. func (r *Runtime) mapProto_has(call FunctionCall) Value {
  108. thisObj := r.toObject(call.This)
  109. mo, ok := thisObj.self.(*mapObject)
  110. if !ok {
  111. panic(r.NewTypeError("Method Map.prototype.has called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
  112. }
  113. if mo.m.has(call.Argument(0)) {
  114. return valueTrue
  115. }
  116. return valueFalse
  117. }
  118. func (r *Runtime) mapProto_set(call FunctionCall) Value {
  119. thisObj := r.toObject(call.This)
  120. mo, ok := thisObj.self.(*mapObject)
  121. if !ok {
  122. panic(r.NewTypeError("Method Map.prototype.set called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
  123. }
  124. mo.m.set(call.Argument(0), call.Argument(1))
  125. return call.This
  126. }
  127. func (r *Runtime) mapProto_entries(call FunctionCall) Value {
  128. return r.createMapIterator(call.This, iterationKindKeyValue)
  129. }
  130. func (r *Runtime) mapProto_forEach(call FunctionCall) Value {
  131. thisObj := r.toObject(call.This)
  132. mo, ok := thisObj.self.(*mapObject)
  133. if !ok {
  134. panic(r.NewTypeError("Method Map.prototype.forEach called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
  135. }
  136. callbackFn, ok := r.toObject(call.Argument(0)).self.assertCallable()
  137. if !ok {
  138. panic(r.NewTypeError("object is not a function %s"))
  139. }
  140. t := call.Argument(1)
  141. iter := mo.m.newIter()
  142. for {
  143. entry := iter.next()
  144. if entry == nil {
  145. break
  146. }
  147. callbackFn(FunctionCall{This: t, Arguments: []Value{entry.value, entry.key, thisObj}})
  148. }
  149. return _undefined
  150. }
  151. func (r *Runtime) mapProto_keys(call FunctionCall) Value {
  152. return r.createMapIterator(call.This, iterationKindKey)
  153. }
  154. func (r *Runtime) mapProto_values(call FunctionCall) Value {
  155. return r.createMapIterator(call.This, iterationKindValue)
  156. }
  157. func (r *Runtime) mapProto_getSize(call FunctionCall) Value {
  158. thisObj := r.toObject(call.This)
  159. mo, ok := thisObj.self.(*mapObject)
  160. if !ok {
  161. panic(r.NewTypeError("Method get Map.prototype.size called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
  162. }
  163. return intToValue(int64(mo.m.size))
  164. }
  165. func (r *Runtime) builtin_newMap(args []Value, newTarget *Object) *Object {
  166. if newTarget == nil {
  167. panic(r.needNew("Map"))
  168. }
  169. proto := r.getPrototypeFromCtor(newTarget, r.global.Map, r.global.MapPrototype)
  170. o := &Object{runtime: r}
  171. mo := &mapObject{}
  172. mo.class = classObject
  173. mo.val = o
  174. mo.extensible = true
  175. o.self = mo
  176. mo.prototype = proto
  177. mo.init()
  178. if len(args) > 0 {
  179. if arg := args[0]; arg != nil && arg != _undefined && arg != _null {
  180. adder := mo.getStr("set", nil)
  181. adderFn := toMethod(adder)
  182. if adderFn == nil {
  183. panic(r.NewTypeError("Map.set in missing"))
  184. }
  185. iter := r.getIterator(arg, nil)
  186. i0 := valueInt(0)
  187. i1 := valueInt(1)
  188. if adder == r.global.mapAdder {
  189. iter.iterate(func(item Value) {
  190. itemObj := r.toObject(item)
  191. k := nilSafe(itemObj.self.getIdx(i0, nil))
  192. v := nilSafe(itemObj.self.getIdx(i1, nil))
  193. mo.m.set(k, v)
  194. })
  195. } else {
  196. iter.iterate(func(item Value) {
  197. itemObj := r.toObject(item)
  198. k := itemObj.self.getIdx(i0, nil)
  199. v := itemObj.self.getIdx(i1, nil)
  200. adderFn(FunctionCall{This: o, Arguments: []Value{k, v}})
  201. })
  202. }
  203. }
  204. }
  205. return o
  206. }
  207. func (r *Runtime) createMapIterator(mapValue Value, kind iterationKind) Value {
  208. obj := r.toObject(mapValue)
  209. mapObj, ok := obj.self.(*mapObject)
  210. if !ok {
  211. panic(r.NewTypeError("Object is not a Map"))
  212. }
  213. o := &Object{runtime: r}
  214. mi := &mapIterObject{
  215. iter: mapObj.m.newIter(),
  216. kind: kind,
  217. }
  218. mi.class = classObject
  219. mi.val = o
  220. mi.extensible = true
  221. o.self = mi
  222. mi.prototype = r.getMapIteratorPrototype()
  223. mi.init()
  224. return o
  225. }
  226. func (r *Runtime) mapIterProto_next(call FunctionCall) Value {
  227. thisObj := r.toObject(call.This)
  228. if iter, ok := thisObj.self.(*mapIterObject); ok {
  229. return iter.next()
  230. }
  231. panic(r.NewTypeError("Method Map Iterator.prototype.next called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
  232. }
  233. func (r *Runtime) createMapProto(val *Object) objectImpl {
  234. o := newBaseObjectObj(val, r.global.ObjectPrototype, classObject)
  235. o._putProp("constructor", r.getMap(), true, false, true)
  236. o._putProp("clear", r.newNativeFunc(r.mapProto_clear, "clear", 0), true, false, true)
  237. r.global.mapAdder = r.newNativeFunc(r.mapProto_set, "set", 2)
  238. o._putProp("set", r.global.mapAdder, true, false, true)
  239. o._putProp("delete", r.newNativeFunc(r.mapProto_delete, "delete", 1), true, false, true)
  240. o._putProp("forEach", r.newNativeFunc(r.mapProto_forEach, "forEach", 1), true, false, true)
  241. o._putProp("has", r.newNativeFunc(r.mapProto_has, "has", 1), true, false, true)
  242. o._putProp("get", r.newNativeFunc(r.mapProto_get, "get", 1), true, false, true)
  243. o.setOwnStr("size", &valueProperty{
  244. getterFunc: r.newNativeFunc(r.mapProto_getSize, "get size", 0),
  245. accessor: true,
  246. writable: true,
  247. configurable: true,
  248. }, true)
  249. o._putProp("keys", r.newNativeFunc(r.mapProto_keys, "keys", 0), true, false, true)
  250. o._putProp("values", r.newNativeFunc(r.mapProto_values, "values", 0), true, false, true)
  251. entriesFunc := r.newNativeFunc(r.mapProto_entries, "entries", 0)
  252. o._putProp("entries", entriesFunc, true, false, true)
  253. o._putSym(SymIterator, valueProp(entriesFunc, true, false, true))
  254. o._putSym(SymToStringTag, valueProp(asciiString(classMap), false, false, true))
  255. return o
  256. }
  257. func (r *Runtime) createMap(val *Object) objectImpl {
  258. o := r.newNativeConstructOnly(val, r.builtin_newMap, r.getMapPrototype(), "Map", 0)
  259. r.putSpeciesReturnThis(o)
  260. return o
  261. }
  262. func (r *Runtime) createMapIterProto(val *Object) objectImpl {
  263. o := newBaseObjectObj(val, r.getIteratorPrototype(), classObject)
  264. o._putProp("next", r.newNativeFunc(r.mapIterProto_next, "next", 0), true, false, true)
  265. o._putSym(SymToStringTag, valueProp(asciiString(classMapIterator), false, false, true))
  266. return o
  267. }
  268. func (r *Runtime) getMapIteratorPrototype() *Object {
  269. var o *Object
  270. if o = r.global.MapIteratorPrototype; o == nil {
  271. o = &Object{runtime: r}
  272. r.global.MapIteratorPrototype = o
  273. o.self = r.createMapIterProto(o)
  274. }
  275. return o
  276. }
  277. func (r *Runtime) getMapPrototype() *Object {
  278. ret := r.global.MapPrototype
  279. if ret == nil {
  280. ret = &Object{runtime: r}
  281. r.global.MapPrototype = ret
  282. ret.self = r.createMapProto(ret)
  283. }
  284. return ret
  285. }
  286. func (r *Runtime) getMap() *Object {
  287. ret := r.global.Map
  288. if ret == nil {
  289. ret = &Object{runtime: r}
  290. r.global.Map = ret
  291. ret.self = r.createMap(ret)
  292. }
  293. return ret
  294. }