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