builtin_map.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. package goja
  2. type mapObject struct {
  3. baseObject
  4. m *orderedMap
  5. }
  6. type mapIterObject struct {
  7. baseObject
  8. iter *orderedMapIter
  9. kind iterationKind
  10. }
  11. func (o *mapIterObject) next() Value {
  12. if o.iter == nil {
  13. return o.val.runtime.createIterResultObject(_undefined, true)
  14. }
  15. entry := o.iter.next()
  16. if entry == nil {
  17. o.iter = nil
  18. return o.val.runtime.createIterResultObject(_undefined, true)
  19. }
  20. var result Value
  21. switch o.kind {
  22. case iterationKindKey:
  23. result = entry.key
  24. case iterationKindValue:
  25. result = entry.value
  26. default:
  27. result = o.val.runtime.newArrayValues([]Value{entry.key, entry.value})
  28. }
  29. return o.val.runtime.createIterResultObject(result, false)
  30. }
  31. func (mo *mapObject) init() {
  32. mo.baseObject.init()
  33. mo.m = newOrderedMap(mo.val.runtime.getHash())
  34. }
  35. func (r *Runtime) mapProto_clear(call FunctionCall) Value {
  36. thisObj := r.toObject(call.This)
  37. mo, ok := thisObj.self.(*mapObject)
  38. if !ok {
  39. panic(r.NewTypeError("Method Map.prototype.clear called on incompatible receiver %s", thisObj.String()))
  40. }
  41. mo.m.clear()
  42. return _undefined
  43. }
  44. func (r *Runtime) mapProto_delete(call FunctionCall) Value {
  45. thisObj := r.toObject(call.This)
  46. mo, ok := thisObj.self.(*mapObject)
  47. if !ok {
  48. panic(r.NewTypeError("Method Map.prototype.delete called on incompatible receiver %s", thisObj.String()))
  49. }
  50. return r.toBoolean(mo.m.remove(call.Argument(0)))
  51. }
  52. func (r *Runtime) mapProto_get(call FunctionCall) Value {
  53. thisObj := r.toObject(call.This)
  54. mo, ok := thisObj.self.(*mapObject)
  55. if !ok {
  56. panic(r.NewTypeError("Method Map.prototype.get called on incompatible receiver %s", thisObj.String()))
  57. }
  58. return nilSafe(mo.m.get(call.Argument(0)))
  59. }
  60. func (r *Runtime) mapProto_has(call FunctionCall) Value {
  61. thisObj := r.toObject(call.This)
  62. mo, ok := thisObj.self.(*mapObject)
  63. if !ok {
  64. panic(r.NewTypeError("Method Map.prototype.has called on incompatible receiver %s", thisObj.String()))
  65. }
  66. if mo.m.has(call.Argument(0)) {
  67. return valueTrue
  68. }
  69. return valueFalse
  70. }
  71. func (r *Runtime) mapProto_set(call FunctionCall) Value {
  72. thisObj := r.toObject(call.This)
  73. mo, ok := thisObj.self.(*mapObject)
  74. if !ok {
  75. panic(r.NewTypeError("Method Map.prototype.set called on incompatible receiver %s", thisObj.String()))
  76. }
  77. mo.m.set(call.Argument(0), call.Argument(1))
  78. return call.This
  79. }
  80. func (r *Runtime) mapProto_entries(call FunctionCall) Value {
  81. return r.createMapIterator(call.This, iterationKindKeyValue)
  82. }
  83. func (r *Runtime) mapProto_forEach(call FunctionCall) Value {
  84. thisObj := r.toObject(call.This)
  85. mo, ok := thisObj.self.(*mapObject)
  86. if !ok {
  87. panic(r.NewTypeError("Method Map.prototype.forEach called on incompatible receiver %s", thisObj.String()))
  88. }
  89. callbackFn, ok := r.toObject(call.Argument(0)).self.assertCallable()
  90. if !ok {
  91. panic(r.NewTypeError("object is not a function %s"))
  92. }
  93. t := call.Argument(1)
  94. iter := mo.m.newIter()
  95. for {
  96. entry := iter.next()
  97. if entry == nil {
  98. break
  99. }
  100. callbackFn(FunctionCall{This: t, Arguments: []Value{entry.value, entry.key, thisObj}})
  101. }
  102. return _undefined
  103. }
  104. func (r *Runtime) mapProto_keys(call FunctionCall) Value {
  105. return r.createMapIterator(call.This, iterationKindKey)
  106. }
  107. func (r *Runtime) mapProto_values(call FunctionCall) Value {
  108. return r.createMapIterator(call.This, iterationKindValue)
  109. }
  110. func (r *Runtime) mapProto_getSize(call FunctionCall) Value {
  111. thisObj := r.toObject(call.This)
  112. mo, ok := thisObj.self.(*mapObject)
  113. if !ok {
  114. panic(r.NewTypeError("Method get Map.prototype.size called on incompatible receiver %s", thisObj.String()))
  115. }
  116. return intToValue(int64(mo.m.size))
  117. }
  118. func (r *Runtime) builtin_newMap(args []Value, newTarget *Object) *Object {
  119. if newTarget == nil {
  120. panic(r.needNew("Map"))
  121. }
  122. proto := r.getPrototypeFromCtor(newTarget, r.global.Map, r.global.MapPrototype)
  123. o := &Object{runtime: r}
  124. mo := &mapObject{}
  125. mo.class = classMap
  126. mo.val = o
  127. mo.extensible = true
  128. o.self = mo
  129. mo.prototype = proto
  130. mo.init()
  131. if len(args) > 0 {
  132. if arg := args[0]; arg != nil && arg != _undefined && arg != _null {
  133. adder := mo.getStr("set", nil)
  134. iter := r.getIterator(arg, nil)
  135. i0 := valueInt(0)
  136. i1 := valueInt(1)
  137. if adder == r.global.mapAdder {
  138. iter.iterate(func(item Value) {
  139. itemObj := r.toObject(item)
  140. k := nilSafe(itemObj.self.getIdx(i0, nil))
  141. v := nilSafe(itemObj.self.getIdx(i1, nil))
  142. mo.m.set(k, v)
  143. })
  144. } else {
  145. adderFn := toMethod(adder)
  146. if adderFn == nil {
  147. panic(r.NewTypeError("Map.set in missing"))
  148. }
  149. iter.iterate(func(item Value) {
  150. itemObj := r.toObject(item)
  151. k := itemObj.self.getIdx(i0, nil)
  152. v := itemObj.self.getIdx(i1, nil)
  153. adderFn(FunctionCall{This: o, Arguments: []Value{k, v}})
  154. })
  155. }
  156. }
  157. }
  158. return o
  159. }
  160. func (r *Runtime) createMapIterator(mapValue Value, kind iterationKind) Value {
  161. obj := r.toObject(mapValue)
  162. mapObj, ok := obj.self.(*mapObject)
  163. if !ok {
  164. panic(r.NewTypeError("Object is not a Map"))
  165. }
  166. o := &Object{runtime: r}
  167. mi := &mapIterObject{
  168. iter: mapObj.m.newIter(),
  169. kind: kind,
  170. }
  171. mi.class = classMapIterator
  172. mi.val = o
  173. mi.extensible = true
  174. o.self = mi
  175. mi.prototype = r.global.MapIteratorPrototype
  176. mi.init()
  177. return o
  178. }
  179. func (r *Runtime) mapIterProto_next(call FunctionCall) Value {
  180. thisObj := r.toObject(call.This)
  181. if iter, ok := thisObj.self.(*mapIterObject); ok {
  182. return iter.next()
  183. }
  184. panic(r.NewTypeError("Method Map Iterator.prototype.next called on incompatible receiver %s", thisObj.String()))
  185. }
  186. func (r *Runtime) createMapProto(val *Object) objectImpl {
  187. o := newBaseObjectObj(val, r.global.ObjectPrototype, classObject)
  188. o._putProp("constructor", r.global.Map, true, false, true)
  189. o._putProp("clear", r.newNativeFunc(r.mapProto_clear, nil, "clear", nil, 0), true, false, true)
  190. r.global.mapAdder = r.newNativeFunc(r.mapProto_set, nil, "set", nil, 2)
  191. o._putProp("set", r.global.mapAdder, true, false, true)
  192. o._putProp("delete", r.newNativeFunc(r.mapProto_delete, nil, "delete", nil, 1), true, false, true)
  193. o._putProp("forEach", r.newNativeFunc(r.mapProto_forEach, nil, "forEach", nil, 1), true, false, true)
  194. o._putProp("has", r.newNativeFunc(r.mapProto_has, nil, "has", nil, 1), true, false, true)
  195. o._putProp("get", r.newNativeFunc(r.mapProto_get, nil, "get", nil, 1), true, false, true)
  196. o.setOwnStr("size", &valueProperty{
  197. getterFunc: r.newNativeFunc(r.mapProto_getSize, nil, "get size", nil, 0),
  198. accessor: true,
  199. writable: true,
  200. configurable: true,
  201. }, true)
  202. o._putProp("keys", r.newNativeFunc(r.mapProto_keys, nil, "keys", nil, 0), true, false, true)
  203. o._putProp("values", r.newNativeFunc(r.mapProto_values, nil, "values", nil, 0), true, false, true)
  204. entriesFunc := r.newNativeFunc(r.mapProto_entries, nil, "entries", nil, 0)
  205. o._putProp("entries", entriesFunc, true, false, true)
  206. o._putSym(SymIterator, valueProp(entriesFunc, true, false, true))
  207. o._putSym(SymToStringTag, valueProp(asciiString(classMap), false, false, true))
  208. return o
  209. }
  210. func (r *Runtime) createMap(val *Object) objectImpl {
  211. o := r.newNativeConstructOnly(val, r.builtin_newMap, r.global.MapPrototype, "Map", 0)
  212. r.putSpeciesReturnThis(o)
  213. return o
  214. }
  215. func (r *Runtime) createMapIterProto(val *Object) objectImpl {
  216. o := newBaseObjectObj(val, r.global.IteratorPrototype, classObject)
  217. o._putProp("next", r.newNativeFunc(r.mapIterProto_next, nil, "next", nil, 0), true, false, true)
  218. o._putSym(SymToStringTag, valueProp(asciiString(classMapIterator), false, false, true))
  219. return o
  220. }
  221. func (r *Runtime) initMap() {
  222. r.global.MapIteratorPrototype = r.newLazyObject(r.createMapIterProto)
  223. r.global.MapPrototype = r.newLazyObject(r.createMapProto)
  224. r.global.Map = r.newLazyObject(r.createMap)
  225. r.addToGlobal("Map", r.global.Map)
  226. }