...

Source file src/github.com/dop251/goja/builtin_weakmap.go

Documentation: github.com/dop251/goja

     1  package goja
     2  
     3  type weakMap uint64
     4  
     5  type weakMapObject struct {
     6  	baseObject
     7  	m weakMap
     8  }
     9  
    10  func (wmo *weakMapObject) init() {
    11  	wmo.baseObject.init()
    12  	wmo.m = weakMap(wmo.val.runtime.genId())
    13  }
    14  
    15  func (wm weakMap) set(key *Object, value Value) {
    16  	key.getWeakRefs()[wm] = value
    17  }
    18  
    19  func (wm weakMap) get(key *Object) Value {
    20  	return key.weakRefs[wm]
    21  }
    22  
    23  func (wm weakMap) remove(key *Object) bool {
    24  	if _, exists := key.weakRefs[wm]; exists {
    25  		delete(key.weakRefs, wm)
    26  		return true
    27  	}
    28  	return false
    29  }
    30  
    31  func (wm weakMap) has(key *Object) bool {
    32  	_, exists := key.weakRefs[wm]
    33  	return exists
    34  }
    35  
    36  func (r *Runtime) weakMapProto_delete(call FunctionCall) Value {
    37  	thisObj := r.toObject(call.This)
    38  	wmo, ok := thisObj.self.(*weakMapObject)
    39  	if !ok {
    40  		panic(r.NewTypeError("Method WeakMap.prototype.delete called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
    41  	}
    42  	key, ok := call.Argument(0).(*Object)
    43  	if ok && wmo.m.remove(key) {
    44  		return valueTrue
    45  	}
    46  	return valueFalse
    47  }
    48  
    49  func (r *Runtime) weakMapProto_get(call FunctionCall) Value {
    50  	thisObj := r.toObject(call.This)
    51  	wmo, ok := thisObj.self.(*weakMapObject)
    52  	if !ok {
    53  		panic(r.NewTypeError("Method WeakMap.prototype.get called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
    54  	}
    55  	var res Value
    56  	if key, ok := call.Argument(0).(*Object); ok {
    57  		res = wmo.m.get(key)
    58  	}
    59  	if res == nil {
    60  		return _undefined
    61  	}
    62  	return res
    63  }
    64  
    65  func (r *Runtime) weakMapProto_has(call FunctionCall) Value {
    66  	thisObj := r.toObject(call.This)
    67  	wmo, ok := thisObj.self.(*weakMapObject)
    68  	if !ok {
    69  		panic(r.NewTypeError("Method WeakMap.prototype.has called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
    70  	}
    71  	key, ok := call.Argument(0).(*Object)
    72  	if ok && wmo.m.has(key) {
    73  		return valueTrue
    74  	}
    75  	return valueFalse
    76  }
    77  
    78  func (r *Runtime) weakMapProto_set(call FunctionCall) Value {
    79  	thisObj := r.toObject(call.This)
    80  	wmo, ok := thisObj.self.(*weakMapObject)
    81  	if !ok {
    82  		panic(r.NewTypeError("Method WeakMap.prototype.set called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
    83  	}
    84  	key := r.toObject(call.Argument(0))
    85  	wmo.m.set(key, call.Argument(1))
    86  	return call.This
    87  }
    88  
    89  func (r *Runtime) needNew(name string) *Object {
    90  	return r.NewTypeError("Constructor %s requires 'new'", name)
    91  }
    92  
    93  func (r *Runtime) builtin_newWeakMap(args []Value, newTarget *Object) *Object {
    94  	if newTarget == nil {
    95  		panic(r.needNew("WeakMap"))
    96  	}
    97  	proto := r.getPrototypeFromCtor(newTarget, r.global.WeakMap, r.global.WeakMapPrototype)
    98  	o := &Object{runtime: r}
    99  
   100  	wmo := &weakMapObject{}
   101  	wmo.class = classObject
   102  	wmo.val = o
   103  	wmo.extensible = true
   104  	o.self = wmo
   105  	wmo.prototype = proto
   106  	wmo.init()
   107  	if len(args) > 0 {
   108  		if arg := args[0]; arg != nil && arg != _undefined && arg != _null {
   109  			adder := wmo.getStr("set", nil)
   110  			adderFn := toMethod(adder)
   111  			if adderFn == nil {
   112  				panic(r.NewTypeError("WeakMap.set in missing"))
   113  			}
   114  			iter := r.getIterator(arg, nil)
   115  			i0 := valueInt(0)
   116  			i1 := valueInt(1)
   117  			if adder == r.global.weakMapAdder {
   118  				iter.iterate(func(item Value) {
   119  					itemObj := r.toObject(item)
   120  					k := itemObj.self.getIdx(i0, nil)
   121  					v := nilSafe(itemObj.self.getIdx(i1, nil))
   122  					wmo.m.set(r.toObject(k), v)
   123  				})
   124  			} else {
   125  				iter.iterate(func(item Value) {
   126  					itemObj := r.toObject(item)
   127  					k := itemObj.self.getIdx(i0, nil)
   128  					v := itemObj.self.getIdx(i1, nil)
   129  					adderFn(FunctionCall{This: o, Arguments: []Value{k, v}})
   130  				})
   131  			}
   132  		}
   133  	}
   134  	return o
   135  }
   136  
   137  func (r *Runtime) createWeakMapProto(val *Object) objectImpl {
   138  	o := newBaseObjectObj(val, r.global.ObjectPrototype, classObject)
   139  
   140  	o._putProp("constructor", r.getWeakMap(), true, false, true)
   141  	r.global.weakMapAdder = r.newNativeFunc(r.weakMapProto_set, "set", 2)
   142  	o._putProp("set", r.global.weakMapAdder, true, false, true)
   143  	o._putProp("delete", r.newNativeFunc(r.weakMapProto_delete, "delete", 1), true, false, true)
   144  	o._putProp("has", r.newNativeFunc(r.weakMapProto_has, "has", 1), true, false, true)
   145  	o._putProp("get", r.newNativeFunc(r.weakMapProto_get, "get", 1), true, false, true)
   146  
   147  	o._putSym(SymToStringTag, valueProp(asciiString(classWeakMap), false, false, true))
   148  
   149  	return o
   150  }
   151  
   152  func (r *Runtime) createWeakMap(val *Object) objectImpl {
   153  	o := r.newNativeConstructOnly(val, r.builtin_newWeakMap, r.getWeakMapPrototype(), "WeakMap", 0)
   154  
   155  	return o
   156  }
   157  
   158  func (r *Runtime) getWeakMapPrototype() *Object {
   159  	ret := r.global.WeakMapPrototype
   160  	if ret == nil {
   161  		ret = &Object{runtime: r}
   162  		r.global.WeakMapPrototype = ret
   163  		ret.self = r.createWeakMapProto(ret)
   164  	}
   165  	return ret
   166  }
   167  
   168  func (r *Runtime) getWeakMap() *Object {
   169  	ret := r.global.WeakMap
   170  	if ret == nil {
   171  		ret = &Object{runtime: r}
   172  		r.global.WeakMap = ret
   173  		ret.self = r.createWeakMap(ret)
   174  	}
   175  	return ret
   176  }
   177  

View as plain text