builtin_set.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. package goja
  2. type setObject struct {
  3. baseObject
  4. m *orderedMap
  5. }
  6. type setIterObject struct {
  7. baseObject
  8. iter *orderedMapIter
  9. kind iterationKind
  10. }
  11. func (o *setIterObject) 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 iterationKindValue:
  23. result = entry.key
  24. default:
  25. result = o.val.runtime.newArrayValues([]Value{entry.key, entry.key})
  26. }
  27. return o.val.runtime.createIterResultObject(result, false)
  28. }
  29. func (so *setObject) init() {
  30. so.baseObject.init()
  31. so.m = newOrderedMap()
  32. }
  33. func (r *Runtime) setProto_add(call FunctionCall) Value {
  34. thisObj := r.toObject(call.This)
  35. so, ok := thisObj.self.(*setObject)
  36. if !ok {
  37. panic(r.NewTypeError("Method Set.prototype.add called on incompatible receiver %s", thisObj.String()))
  38. }
  39. so.m.set(call.Argument(0), nil)
  40. return call.This
  41. }
  42. func (r *Runtime) setProto_clear(call FunctionCall) Value {
  43. thisObj := r.toObject(call.This)
  44. so, ok := thisObj.self.(*setObject)
  45. if !ok {
  46. panic(r.NewTypeError("Method Set.prototype.clear called on incompatible receiver %s", thisObj.String()))
  47. }
  48. so.m.clear()
  49. return _undefined
  50. }
  51. func (r *Runtime) setProto_delete(call FunctionCall) Value {
  52. thisObj := r.toObject(call.This)
  53. so, ok := thisObj.self.(*setObject)
  54. if !ok {
  55. panic(r.NewTypeError("Method Set.prototype.delete called on incompatible receiver %s", thisObj.String()))
  56. }
  57. return r.toBoolean(so.m.remove(call.Argument(0)))
  58. }
  59. func (r *Runtime) setProto_entries(call FunctionCall) Value {
  60. return r.createSetIterator(call.This, iterationKindKeyValue)
  61. }
  62. func (r *Runtime) setProto_forEach(call FunctionCall) Value {
  63. thisObj := r.toObject(call.This)
  64. so, ok := thisObj.self.(*setObject)
  65. if !ok {
  66. panic(r.NewTypeError("Method Set.prototype.forEach called on incompatible receiver %s", thisObj.String()))
  67. }
  68. callbackFn, ok := r.toObject(call.Argument(0)).self.assertCallable()
  69. if !ok {
  70. panic(r.NewTypeError("object is not a function %s"))
  71. }
  72. t := call.Argument(1)
  73. iter := so.m.newIter()
  74. for {
  75. entry := iter.next()
  76. if entry == nil {
  77. break
  78. }
  79. callbackFn(FunctionCall{This: t, Arguments: []Value{entry.key, entry.key, thisObj}})
  80. }
  81. return _undefined
  82. }
  83. func (r *Runtime) setProto_has(call FunctionCall) Value {
  84. thisObj := r.toObject(call.This)
  85. so, ok := thisObj.self.(*setObject)
  86. if !ok {
  87. panic(r.NewTypeError("Method Set.prototype.has called on incompatible receiver %s", thisObj.String()))
  88. }
  89. return r.toBoolean(so.m.has(call.Argument(0)))
  90. }
  91. func (r *Runtime) setProto_getSize(call FunctionCall) Value {
  92. thisObj := r.toObject(call.This)
  93. so, ok := thisObj.self.(*setObject)
  94. if !ok {
  95. panic(r.NewTypeError("Method get Set.prototype.size called on incompatible receiver %s", thisObj.String()))
  96. }
  97. return intToValue(int64(so.m.size))
  98. }
  99. func (r *Runtime) setProto_values(call FunctionCall) Value {
  100. return r.createSetIterator(call.This, iterationKindValue)
  101. }
  102. func (r *Runtime) builtin_newSet(args []Value, proto *Object) *Object {
  103. o := &Object{runtime: r}
  104. so := &setObject{}
  105. so.class = classSet
  106. so.val = o
  107. so.extensible = true
  108. o.self = so
  109. so.prototype = proto
  110. so.init()
  111. if len(args) > 0 {
  112. if arg := args[0]; arg != nil && arg != _undefined && arg != _null {
  113. adder := so.getStr("add", nil)
  114. iter := r.getIterator(arg, nil)
  115. if adder == r.global.setAdder {
  116. r.iterate(iter, func(item Value) {
  117. so.m.set(item, nil)
  118. })
  119. } else {
  120. adderFn := toMethod(adder)
  121. if adderFn == nil {
  122. panic(r.NewTypeError("Set.add in missing"))
  123. }
  124. r.iterate(iter, func(item Value) {
  125. adderFn(FunctionCall{This: o, Arguments: []Value{item}})
  126. })
  127. }
  128. }
  129. }
  130. return o
  131. }
  132. func (r *Runtime) createSetIterator(setValue Value, kind iterationKind) Value {
  133. obj := r.toObject(setValue)
  134. setObj, ok := obj.self.(*setObject)
  135. if !ok {
  136. panic(r.NewTypeError("Object is not a Set"))
  137. }
  138. o := &Object{runtime: r}
  139. si := &setIterObject{
  140. iter: setObj.m.newIter(),
  141. kind: kind,
  142. }
  143. si.class = classSetIterator
  144. si.val = o
  145. si.extensible = true
  146. o.self = si
  147. si.prototype = r.global.SetIteratorPrototype
  148. si.init()
  149. return o
  150. }
  151. func (r *Runtime) setIterProto_next(call FunctionCall) Value {
  152. thisObj := r.toObject(call.This)
  153. if iter, ok := thisObj.self.(*setIterObject); ok {
  154. return iter.next()
  155. }
  156. panic(r.NewTypeError("Method Set Iterator.prototype.next called on incompatible receiver %s", thisObj.String()))
  157. }
  158. func (r *Runtime) createSetProto(val *Object) objectImpl {
  159. o := newBaseObjectObj(val, r.global.ObjectPrototype, classObject)
  160. o._putProp("constructor", r.global.Set, true, false, true)
  161. r.global.setAdder = r.newNativeFunc(r.setProto_add, nil, "add", nil, 1)
  162. o._putProp("add", r.global.setAdder, true, false, true)
  163. o._putProp("clear", r.newNativeFunc(r.setProto_clear, nil, "clear", nil, 0), true, false, true)
  164. o._putProp("delete", r.newNativeFunc(r.setProto_delete, nil, "delete", nil, 1), true, false, true)
  165. o._putProp("forEach", r.newNativeFunc(r.setProto_forEach, nil, "forEach", nil, 1), true, false, true)
  166. o._putProp("has", r.newNativeFunc(r.setProto_has, nil, "has", nil, 1), true, false, true)
  167. o.setOwnStr("size", &valueProperty{
  168. getterFunc: r.newNativeFunc(r.setProto_getSize, nil, "get size", nil, 0),
  169. accessor: true,
  170. writable: true,
  171. configurable: true,
  172. }, true)
  173. valuesFunc := r.newNativeFunc(r.setProto_values, nil, "values", nil, 0)
  174. o._putProp("values", valuesFunc, true, false, true)
  175. o._putProp("keys", valuesFunc, true, false, true)
  176. o._putProp("entries", r.newNativeFunc(r.setProto_entries, nil, "entries", nil, 0), true, false, true)
  177. o._putSym(symIterator, valueProp(valuesFunc, true, false, true))
  178. o._putSym(symToStringTag, valueProp(asciiString(classSet), false, false, true))
  179. return o
  180. }
  181. func (r *Runtime) createSet(val *Object) objectImpl {
  182. o := r.newNativeFuncObj(val, r.constructorThrower("Set"), r.builtin_newSet, "Set", r.global.SetPrototype, 0)
  183. o._putSym(symSpecies, &valueProperty{
  184. getterFunc: r.newNativeFunc(r.returnThis, nil, "get [Symbol.species]", nil, 0),
  185. accessor: true,
  186. configurable: true,
  187. })
  188. return o
  189. }
  190. func (r *Runtime) createSetIterProto(val *Object) objectImpl {
  191. o := newBaseObjectObj(val, r.global.IteratorPrototype, classObject)
  192. o._putProp("next", r.newNativeFunc(r.setIterProto_next, nil, "next", nil, 0), true, false, true)
  193. o._putSym(symToStringTag, valueProp(asciiString(classSetIterator), false, false, true))
  194. return o
  195. }
  196. func (r *Runtime) initSet() {
  197. r.global.SetIteratorPrototype = r.newLazyObject(r.createSetIterProto)
  198. r.global.SetPrototype = r.newLazyObject(r.createSetProto)
  199. r.global.Set = r.newLazyObject(r.createSet)
  200. r.addToGlobal("Set", r.global.Set)
  201. }