package goja
import (
"fmt"
"reflect"
)
var setExportType = reflectTypeArray
type setObject struct {
baseObject
m *orderedMap
}
type setIterObject struct {
baseObject
iter *orderedMapIter
kind iterationKind
}
func (o *setIterObject ) next () Value {
if o .iter == nil {
return o .val .runtime .createIterResultObject (_undefined , true )
}
entry := o .iter .next ()
if entry == nil {
o .iter = nil
return o .val .runtime .createIterResultObject (_undefined , true )
}
var result Value
switch o .kind {
case iterationKindValue :
result = entry .key
default :
result = o .val .runtime .newArrayValues ([]Value {entry .key , entry .key })
}
return o .val .runtime .createIterResultObject (result , false )
}
func (so *setObject ) init () {
so .baseObject .init ()
so .m = newOrderedMap (so .val .runtime .getHash ())
}
func (so *setObject ) exportType () reflect .Type {
return setExportType
}
func (so *setObject ) export (ctx *objectExportCtx ) interface {} {
a := make ([]interface {}, so .m .size )
ctx .put (so .val , a )
iter := so .m .newIter ()
for i := 0 ; i < len (a ); i ++ {
entry := iter .next ()
if entry == nil {
break
}
a [i ] = exportValue (entry .key , ctx )
}
return a
}
func (so *setObject ) exportToArrayOrSlice (dst reflect .Value , typ reflect .Type , ctx *objectExportCtx ) error {
l := so .m .size
if typ .Kind () == reflect .Array {
if dst .Len () != l {
return fmt .Errorf ("cannot convert a Set into an array, lengths mismatch: have %d, need %d)" , l , dst .Len ())
}
} else {
dst .Set (reflect .MakeSlice (typ , l , l ))
}
ctx .putTyped (so .val , typ , dst .Interface ())
iter := so .m .newIter ()
r := so .val .runtime
for i := 0 ; i < l ; i ++ {
entry := iter .next ()
if entry == nil {
break
}
err := r .toReflectValue (entry .key , dst .Index (i ), ctx )
if err != nil {
return err
}
}
return nil
}
func (so *setObject ) exportToMap (dst reflect .Value , typ reflect .Type , ctx *objectExportCtx ) error {
dst .Set (reflect .MakeMap (typ ))
keyTyp := typ .Key ()
elemTyp := typ .Elem ()
iter := so .m .newIter ()
r := so .val .runtime
for {
entry := iter .next ()
if entry == nil {
break
}
keyVal := reflect .New (keyTyp ).Elem ()
err := r .toReflectValue (entry .key , keyVal , ctx )
if err != nil {
return err
}
dst .SetMapIndex (keyVal , reflect .Zero (elemTyp ))
}
return nil
}
func (r *Runtime ) setProto_add (call FunctionCall ) Value {
thisObj := r .toObject (call .This )
so , ok := thisObj .self .(*setObject )
if !ok {
panic (r .NewTypeError ("Method Set.prototype.add called on incompatible receiver %s" , r .objectproto_toString (FunctionCall {This : thisObj })))
}
so .m .set (call .Argument (0 ), nil )
return call .This
}
func (r *Runtime ) setProto_clear (call FunctionCall ) Value {
thisObj := r .toObject (call .This )
so , ok := thisObj .self .(*setObject )
if !ok {
panic (r .NewTypeError ("Method Set.prototype.clear called on incompatible receiver %s" , r .objectproto_toString (FunctionCall {This : thisObj })))
}
so .m .clear ()
return _undefined
}
func (r *Runtime ) setProto_delete (call FunctionCall ) Value {
thisObj := r .toObject (call .This )
so , ok := thisObj .self .(*setObject )
if !ok {
panic (r .NewTypeError ("Method Set.prototype.delete called on incompatible receiver %s" , r .objectproto_toString (FunctionCall {This : thisObj })))
}
return r .toBoolean (so .m .remove (call .Argument (0 )))
}
func (r *Runtime ) setProto_entries (call FunctionCall ) Value {
return r .createSetIterator (call .This , iterationKindKeyValue )
}
func (r *Runtime ) setProto_forEach (call FunctionCall ) Value {
thisObj := r .toObject (call .This )
so , ok := thisObj .self .(*setObject )
if !ok {
panic (r .NewTypeError ("Method Set.prototype.forEach called on incompatible receiver %s" , r .objectproto_toString (FunctionCall {This : thisObj })))
}
callbackFn , ok := r .toObject (call .Argument (0 )).self .assertCallable ()
if !ok {
panic (r .NewTypeError ("object is not a function %s" ))
}
t := call .Argument (1 )
iter := so .m .newIter ()
for {
entry := iter .next ()
if entry == nil {
break
}
callbackFn (FunctionCall {This : t , Arguments : []Value {entry .key , entry .key , thisObj }})
}
return _undefined
}
func (r *Runtime ) setProto_has (call FunctionCall ) Value {
thisObj := r .toObject (call .This )
so , ok := thisObj .self .(*setObject )
if !ok {
panic (r .NewTypeError ("Method Set.prototype.has called on incompatible receiver %s" , r .objectproto_toString (FunctionCall {This : thisObj })))
}
return r .toBoolean (so .m .has (call .Argument (0 )))
}
func (r *Runtime ) setProto_getSize (call FunctionCall ) Value {
thisObj := r .toObject (call .This )
so , ok := thisObj .self .(*setObject )
if !ok {
panic (r .NewTypeError ("Method get Set.prototype.size called on incompatible receiver %s" , r .objectproto_toString (FunctionCall {This : thisObj })))
}
return intToValue (int64 (so .m .size ))
}
func (r *Runtime ) setProto_values (call FunctionCall ) Value {
return r .createSetIterator (call .This , iterationKindValue )
}
func (r *Runtime ) builtin_newSet (args []Value , newTarget *Object ) *Object {
if newTarget == nil {
panic (r .needNew ("Set" ))
}
proto := r .getPrototypeFromCtor (newTarget , r .global .Set , r .global .SetPrototype )
o := &Object {runtime : r }
so := &setObject {}
so .class = classObject
so .val = o
so .extensible = true
o .self = so
so .prototype = proto
so .init ()
if len (args ) > 0 {
if arg := args [0 ]; arg != nil && arg != _undefined && arg != _null {
adder := so .getStr ("add" , nil )
stdArr := r .checkStdArrayIter (arg )
if adder == r .global .setAdder {
if stdArr != nil {
for _ , v := range stdArr .values {
so .m .set (v , nil )
}
} else {
r .getIterator (arg , nil ).iterate (func (item Value ) {
so .m .set (item , nil )
})
}
} else {
adderFn := toMethod (adder )
if adderFn == nil {
panic (r .NewTypeError ("Set.add in missing" ))
}
if stdArr != nil {
for _ , item := range stdArr .values {
adderFn (FunctionCall {This : o , Arguments : []Value {item }})
}
} else {
r .getIterator (arg , nil ).iterate (func (item Value ) {
adderFn (FunctionCall {This : o , Arguments : []Value {item }})
})
}
}
}
}
return o
}
func (r *Runtime ) createSetIterator (setValue Value , kind iterationKind ) Value {
obj := r .toObject (setValue )
setObj , ok := obj .self .(*setObject )
if !ok {
panic (r .NewTypeError ("Object is not a Set" ))
}
o := &Object {runtime : r }
si := &setIterObject {
iter : setObj .m .newIter (),
kind : kind ,
}
si .class = classObject
si .val = o
si .extensible = true
o .self = si
si .prototype = r .getSetIteratorPrototype ()
si .init ()
return o
}
func (r *Runtime ) setIterProto_next (call FunctionCall ) Value {
thisObj := r .toObject (call .This )
if iter , ok := thisObj .self .(*setIterObject ); ok {
return iter .next ()
}
panic (r .NewTypeError ("Method Set Iterator.prototype.next called on incompatible receiver %s" , r .objectproto_toString (FunctionCall {This : thisObj })))
}
func (r *Runtime ) createSetProto (val *Object ) objectImpl {
o := newBaseObjectObj (val , r .global .ObjectPrototype , classObject )
o ._putProp ("constructor" , r .getSet (), true , false , true )
r .global .setAdder = r .newNativeFunc (r .setProto_add , "add" , 1 )
o ._putProp ("add" , r .global .setAdder , true , false , true )
o ._putProp ("clear" , r .newNativeFunc (r .setProto_clear , "clear" , 0 ), true , false , true )
o ._putProp ("delete" , r .newNativeFunc (r .setProto_delete , "delete" , 1 ), true , false , true )
o ._putProp ("forEach" , r .newNativeFunc (r .setProto_forEach , "forEach" , 1 ), true , false , true )
o ._putProp ("has" , r .newNativeFunc (r .setProto_has , "has" , 1 ), true , false , true )
o .setOwnStr ("size" , &valueProperty {
getterFunc : r .newNativeFunc (r .setProto_getSize , "get size" , 0 ),
accessor : true ,
writable : true ,
configurable : true ,
}, true )
valuesFunc := r .newNativeFunc (r .setProto_values , "values" , 0 )
o ._putProp ("values" , valuesFunc , true , false , true )
o ._putProp ("keys" , valuesFunc , true , false , true )
o ._putProp ("entries" , r .newNativeFunc (r .setProto_entries , "entries" , 0 ), true , false , true )
o ._putSym (SymIterator , valueProp (valuesFunc , true , false , true ))
o ._putSym (SymToStringTag , valueProp (asciiString (classSet ), false , false , true ))
return o
}
func (r *Runtime ) createSet (val *Object ) objectImpl {
o := r .newNativeConstructOnly (val , r .builtin_newSet , r .getSetPrototype (), "Set" , 0 )
r .putSpeciesReturnThis (o )
return o
}
func (r *Runtime ) createSetIterProto (val *Object ) objectImpl {
o := newBaseObjectObj (val , r .getIteratorPrototype (), classObject )
o ._putProp ("next" , r .newNativeFunc (r .setIterProto_next , "next" , 0 ), true , false , true )
o ._putSym (SymToStringTag , valueProp (asciiString (classSetIterator ), false , false , true ))
return o
}
func (r *Runtime ) getSetIteratorPrototype () *Object {
var o *Object
if o = r .global .SetIteratorPrototype ; o == nil {
o = &Object {runtime : r }
r .global .SetIteratorPrototype = o
o .self = r .createSetIterProto (o )
}
return o
}
func (r *Runtime ) getSetPrototype () *Object {
ret := r .global .SetPrototype
if ret == nil {
ret = &Object {runtime : r }
r .global .SetPrototype = ret
ret .self = r .createSetProto (ret )
}
return ret
}
func (r *Runtime ) getSet () *Object {
ret := r .global .Set
if ret == nil {
ret = &Object {runtime : r }
r .global .Set = ret
ret .self = r .createSet (ret )
}
return ret
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .