builtin_weakset.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package goja
  2. type weakSet struct {
  3. data map[uint64]struct{}
  4. }
  5. type weakSetObject struct {
  6. baseObject
  7. s *weakSet
  8. }
  9. func newWeakSet() *weakSet {
  10. return &weakSet{
  11. data: make(map[uint64]struct{}),
  12. }
  13. }
  14. func (ws *weakSetObject) init() {
  15. ws.baseObject.init()
  16. ws.s = newWeakSet()
  17. }
  18. func (ws *weakSet) removeId(id uint64) {
  19. delete(ws.data, id)
  20. }
  21. func (ws *weakSet) add(o *Object) {
  22. ref := o.getWeakRef()
  23. ws.data[ref.id] = struct{}{}
  24. o.runtime.addWeakKey(ref.id, ws)
  25. }
  26. func (ws *weakSet) remove(o *Object) bool {
  27. ref := o.weakRef
  28. if ref == nil {
  29. return false
  30. }
  31. _, exists := ws.data[ref.id]
  32. if exists {
  33. delete(ws.data, ref.id)
  34. o.runtime.removeWeakKey(ref.id, ws)
  35. }
  36. return exists
  37. }
  38. func (ws *weakSet) has(o *Object) bool {
  39. ref := o.weakRef
  40. if ref == nil {
  41. return false
  42. }
  43. _, exists := ws.data[ref.id]
  44. return exists
  45. }
  46. func (r *Runtime) weakSetProto_add(call FunctionCall) Value {
  47. thisObj := r.toObject(call.This)
  48. wso, ok := thisObj.self.(*weakSetObject)
  49. if !ok {
  50. panic(r.NewTypeError("Method WeakSet.prototype.add called on incompatible receiver %s", thisObj.String()))
  51. }
  52. wso.s.add(r.toObject(call.Argument(0)))
  53. return call.This
  54. }
  55. func (r *Runtime) weakSetProto_delete(call FunctionCall) Value {
  56. thisObj := r.toObject(call.This)
  57. wso, ok := thisObj.self.(*weakSetObject)
  58. if !ok {
  59. panic(r.NewTypeError("Method WeakSet.prototype.delete called on incompatible receiver %s", thisObj.String()))
  60. }
  61. obj, ok := call.Argument(0).(*Object)
  62. if ok && wso.s.remove(obj) {
  63. return valueTrue
  64. }
  65. return valueFalse
  66. }
  67. func (r *Runtime) weakSetProto_has(call FunctionCall) Value {
  68. thisObj := r.toObject(call.This)
  69. wso, ok := thisObj.self.(*weakSetObject)
  70. if !ok {
  71. panic(r.NewTypeError("Method WeakSet.prototype.has called on incompatible receiver %s", thisObj.String()))
  72. }
  73. obj, ok := call.Argument(0).(*Object)
  74. if ok && wso.s.has(obj) {
  75. return valueTrue
  76. }
  77. return valueFalse
  78. }
  79. func (r *Runtime) populateWeakSetGeneric(s *Object, adderValue Value, iterable Value) {
  80. adder := toMethod(adderValue)
  81. if adder == nil {
  82. panic(r.NewTypeError("WeakSet.add is not set"))
  83. }
  84. iter := r.getIterator(iterable, nil)
  85. r.iterate(iter, func(val Value) {
  86. adder(FunctionCall{This: s, Arguments: []Value{val}})
  87. })
  88. }
  89. func (r *Runtime) builtin_newWeakSet(args []Value, newTarget *Object) *Object {
  90. if newTarget == nil {
  91. panic(r.needNew("WeakSet"))
  92. }
  93. proto := r.getPrototypeFromCtor(newTarget, r.global.WeakSet, r.global.WeakSetPrototype)
  94. o := &Object{runtime: r}
  95. wso := &weakSetObject{}
  96. wso.class = classWeakSet
  97. wso.val = o
  98. wso.extensible = true
  99. o.self = wso
  100. wso.prototype = proto
  101. wso.init()
  102. if len(args) > 0 {
  103. if arg := args[0]; arg != nil && arg != _undefined && arg != _null {
  104. adder := wso.getStr("add", nil)
  105. if adder == r.global.weakSetAdder {
  106. if arr := r.checkStdArrayIter(arg); arr != nil {
  107. for _, v := range arr.values {
  108. wso.s.add(r.toObject(v))
  109. }
  110. return o
  111. }
  112. }
  113. r.populateWeakSetGeneric(o, adder, arg)
  114. }
  115. }
  116. return o
  117. }
  118. func (r *Runtime) createWeakSetProto(val *Object) objectImpl {
  119. o := newBaseObjectObj(val, r.global.ObjectPrototype, classObject)
  120. o._putProp("constructor", r.global.WeakSet, true, false, true)
  121. r.global.weakSetAdder = r.newNativeFunc(r.weakSetProto_add, nil, "add", nil, 1)
  122. o._putProp("add", r.global.weakSetAdder, true, false, true)
  123. o._putProp("delete", r.newNativeFunc(r.weakSetProto_delete, nil, "delete", nil, 1), true, false, true)
  124. o._putProp("has", r.newNativeFunc(r.weakSetProto_has, nil, "has", nil, 1), true, false, true)
  125. o._putSym(SymToStringTag, valueProp(asciiString(classWeakSet), false, false, true))
  126. return o
  127. }
  128. func (r *Runtime) createWeakSet(val *Object) objectImpl {
  129. o := r.newNativeConstructOnly(val, r.builtin_newWeakSet, r.global.WeakSetPrototype, "WeakSet", 0)
  130. return o
  131. }
  132. func (r *Runtime) initWeakSet() {
  133. r.global.WeakSetPrototype = r.newLazyObject(r.createWeakSetProto)
  134. r.global.WeakSet = r.newLazyObject(r.createWeakSet)
  135. r.addToGlobal("WeakSet", r.global.WeakSet)
  136. }