123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 |
- 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
- }
|