123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- package goja
- import "sync"
- type weakSet struct {
- // need to synchronise access to the data map because it may be accessed
- // from the finalizer goroutine
- sync.Mutex
- data map[uintptr]struct{}
- }
- type weakSetObject struct {
- baseObject
- s *weakSet
- }
- func newWeakSet() *weakSet {
- return &weakSet{
- data: make(map[uintptr]struct{}),
- }
- }
- func (ws *weakSetObject) init() {
- ws.baseObject.init()
- ws.s = newWeakSet()
- }
- func (ws *weakSet) removePtr(ptr uintptr) {
- ws.Lock()
- delete(ws.data, ptr)
- ws.Unlock()
- }
- func (ws *weakSet) add(o *Object) {
- refs := o.getWeakCollRefs()
- ws.Lock()
- ws.data[refs.id()] = struct{}{}
- ws.Unlock()
- refs.add(ws)
- }
- func (ws *weakSet) remove(o *Object) bool {
- if o.weakColls == nil {
- return false
- }
- id := o.weakColls.id()
- ws.Lock()
- _, exists := ws.data[id]
- if exists {
- delete(ws.data, id)
- }
- ws.Unlock()
- if exists {
- o.weakColls.remove(ws)
- }
- return exists
- }
- func (ws *weakSet) has(o *Object) bool {
- if o.weakColls == nil {
- return false
- }
- ws.Lock()
- _, exists := ws.data[o.weakColls.id()]
- ws.Unlock()
- return exists
- }
- func (r *Runtime) weakSetProto_add(call FunctionCall) Value {
- thisObj := r.toObject(call.This)
- wso, ok := thisObj.self.(*weakSetObject)
- if !ok {
- panic(r.NewTypeError("Method WeakSet.prototype.add called on incompatible receiver %s", thisObj.String()))
- }
- wso.s.add(r.toObject(call.Argument(0)))
- return call.This
- }
- func (r *Runtime) weakSetProto_delete(call FunctionCall) Value {
- thisObj := r.toObject(call.This)
- wso, ok := thisObj.self.(*weakSetObject)
- if !ok {
- panic(r.NewTypeError("Method WeakSet.prototype.delete called on incompatible receiver %s", thisObj.String()))
- }
- obj, ok := call.Argument(0).(*Object)
- if ok && wso.s.remove(obj) {
- return valueTrue
- }
- return valueFalse
- }
- func (r *Runtime) weakSetProto_has(call FunctionCall) Value {
- thisObj := r.toObject(call.This)
- wso, ok := thisObj.self.(*weakSetObject)
- if !ok {
- panic(r.NewTypeError("Method WeakSet.prototype.has called on incompatible receiver %s", thisObj.String()))
- }
- obj, ok := call.Argument(0).(*Object)
- if ok && wso.s.has(obj) {
- return valueTrue
- }
- return valueFalse
- }
- func (r *Runtime) populateWeakSetGeneric(s *Object, adderValue Value, iterable Value) {
- adder := toMethod(adderValue)
- if adder == nil {
- panic(r.NewTypeError("WeakSet.add is not set"))
- }
- iter := r.getIterator(iterable, nil)
- r.iterate(iter, func(val Value) {
- adder(FunctionCall{This: s, Arguments: []Value{val}})
- })
- }
- func (r *Runtime) builtin_newWeakSet(args []Value, proto *Object) *Object {
- o := &Object{runtime: r}
- wso := &weakSetObject{}
- wso.class = classWeakSet
- wso.val = o
- wso.extensible = true
- o.self = wso
- wso.prototype = proto
- wso.init()
- if len(args) > 0 {
- if arg := args[0]; arg != nil && arg != _undefined && arg != _null {
- adder := wso.getStr("add", nil)
- if adder == r.global.weakSetAdder {
- if arr := r.checkStdArrayIter(arg); arr != nil {
- for _, v := range arr.values {
- wso.s.add(r.toObject(v))
- }
- return o
- }
- }
- r.populateWeakSetGeneric(o, adder, arg)
- }
- }
- return o
- }
- func (r *Runtime) createWeakSetProto(val *Object) objectImpl {
- o := newBaseObjectObj(val, r.global.ObjectPrototype, classObject)
- o._putProp("constructor", r.global.WeakSet, true, false, true)
- r.global.weakSetAdder = r.newNativeFunc(r.weakSetProto_add, nil, "add", nil, 1)
- o._putProp("add", r.global.weakSetAdder, true, false, true)
- o._putProp("delete", r.newNativeFunc(r.weakSetProto_delete, nil, "delete", nil, 1), true, false, true)
- o._putProp("has", r.newNativeFunc(r.weakSetProto_has, nil, "has", nil, 1), true, false, true)
- o._putSym(symToStringTag, valueProp(asciiString(classWeakSet), false, false, true))
- return o
- }
- func (r *Runtime) createWeakSet(val *Object) objectImpl {
- o := r.newNativeFuncObj(val, r.constructorThrower("WeakSet"), r.builtin_newWeakSet, "WeakSet", r.global.WeakSetPrototype, 0)
- return o
- }
- func (r *Runtime) initWeakSet() {
- r.global.WeakSetPrototype = r.newLazyObject(r.createWeakSetProto)
- r.global.WeakSet = r.newLazyObject(r.createWeakSet)
- r.addToGlobal("WeakSet", r.global.WeakSet)
- }
|