|
@@ -0,0 +1,203 @@
|
|
|
|
+package goja
|
|
|
|
+
|
|
|
|
+import "reflect"
|
|
|
|
+
|
|
|
|
+type objectGoMapReflect struct {
|
|
|
|
+ objectGoReflect
|
|
|
|
+
|
|
|
|
+ keyType, valueType reflect.Type
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) init() {
|
|
|
|
+ o.objectGoReflect.init()
|
|
|
|
+ o.keyType = o.value.Type().Key()
|
|
|
|
+ o.valueType = o.value.Type().Elem()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) toKey(n Value) reflect.Value {
|
|
|
|
+ key, err := o.val.runtime.toReflectValue(n, o.keyType)
|
|
|
|
+ if err != nil {
|
|
|
|
+ o.val.runtime.typeErrorResult(true, "map key conversion error: %v", err)
|
|
|
|
+ panic("unreachable")
|
|
|
|
+ }
|
|
|
|
+ return key
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) strToKey(name string) reflect.Value {
|
|
|
|
+ if o.keyType.Kind() == reflect.String {
|
|
|
|
+ return reflect.ValueOf(name).Convert(o.keyType)
|
|
|
|
+ }
|
|
|
|
+ return o.toKey(newStringValue(name))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) _get(n Value) Value {
|
|
|
|
+ if v := o.value.MapIndex(o.toKey(n)); v.IsValid() {
|
|
|
|
+ return o.val.runtime.ToValue(v.Interface())
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) _getStr(name string) Value {
|
|
|
|
+ if v := o.value.MapIndex(o.strToKey(name)); v.IsValid() {
|
|
|
|
+ return o.val.runtime.ToValue(v.Interface())
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) get(n Value) Value {
|
|
|
|
+ if v := o._get(n); v != nil {
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+ return o.objectGoReflect.get(n)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) getStr(name string) Value {
|
|
|
|
+ if v := o._getStr(name); v != nil {
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+ return o.objectGoReflect.getStr(name)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) getProp(n Value) Value {
|
|
|
|
+ return o.get(n)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) getPropStr(name string) Value {
|
|
|
|
+ return o.getStr(name)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) getOwnProp(name string) Value {
|
|
|
|
+ if v := o._getStr(name); v != nil {
|
|
|
|
+ return &valueProperty{
|
|
|
|
+ value: v,
|
|
|
|
+ writable: true,
|
|
|
|
+ enumerable: true,
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return o.objectGoReflect.getOwnProp(name)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) toValue(val Value, throw bool) (reflect.Value, bool) {
|
|
|
|
+ v, err := o.val.runtime.toReflectValue(val, o.valueType)
|
|
|
|
+ if err != nil {
|
|
|
|
+ o.val.runtime.typeErrorResult(throw, "map value conversion error: %v", err)
|
|
|
|
+ return reflect.Value{}, false
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return v, true
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) put(key, val Value, throw bool) {
|
|
|
|
+ k := o.toKey(key)
|
|
|
|
+ v, ok := o.toValue(val, throw)
|
|
|
|
+ if !ok {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ o.value.SetMapIndex(k, v)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) putStr(name string, val Value, throw bool) {
|
|
|
|
+ k := o.strToKey(name)
|
|
|
|
+ v, ok := o.toValue(val, throw)
|
|
|
|
+ if !ok {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ o.value.SetMapIndex(k, v)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) _putProp(name string, value Value, writable, enumerable, configurable bool) Value {
|
|
|
|
+ o.putStr(name, value, true)
|
|
|
|
+ return value
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) defineOwnProperty(n Value, descr objectImpl, throw bool) bool {
|
|
|
|
+ name := n.String()
|
|
|
|
+ if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ o.put(n, descr.getStr("value"), throw)
|
|
|
|
+ return true
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) hasOwnPropertyStr(name string) bool {
|
|
|
|
+ return o.value.MapIndex(o.strToKey(name)).IsValid()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) hasOwnProperty(n Value) bool {
|
|
|
|
+ return o.value.MapIndex(o.toKey(n)).IsValid()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) hasProperty(n Value) bool {
|
|
|
|
+ if o.hasOwnProperty(n) {
|
|
|
|
+ return true
|
|
|
|
+ }
|
|
|
|
+ return o.objectGoReflect.hasProperty(n)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) hasPropertyStr(name string) bool {
|
|
|
|
+ if o.hasOwnPropertyStr(name) {
|
|
|
|
+ return true
|
|
|
|
+ }
|
|
|
|
+ return o.objectGoReflect.hasPropertyStr(name)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) delete(n Value, throw bool) bool {
|
|
|
|
+ o.value.SetMapIndex(o.toKey(n), reflect.Value{})
|
|
|
|
+ return true
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) deleteStr(name string, throw bool) bool {
|
|
|
|
+ o.value.SetMapIndex(o.strToKey(name), reflect.Value{})
|
|
|
|
+ return true
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type gomapReflectPropIter struct {
|
|
|
|
+ o *objectGoMapReflect
|
|
|
|
+ keys []reflect.Value
|
|
|
|
+ idx int
|
|
|
|
+ recursive bool
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (i *gomapReflectPropIter) next() (propIterItem, iterNextFunc) {
|
|
|
|
+ for i.idx < len(i.keys) {
|
|
|
|
+ key := i.keys[i.idx]
|
|
|
|
+ v := i.o.value.MapIndex(key)
|
|
|
|
+ i.idx++
|
|
|
|
+ if v.IsValid() {
|
|
|
|
+ return propIterItem{name: key.String(), enumerable: _ENUM_TRUE}, i.next
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if i.recursive {
|
|
|
|
+ return i.o.objectGoReflect._enumerate(true)()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return propIterItem{}, nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) _enumerate(recusrive bool) iterNextFunc {
|
|
|
|
+ r := &gomapReflectPropIter{
|
|
|
|
+ o: o,
|
|
|
|
+ keys: o.value.MapKeys(),
|
|
|
|
+ recursive: recusrive,
|
|
|
|
+ }
|
|
|
|
+ return r.next
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) enumerate(all, recursive bool) iterNextFunc {
|
|
|
|
+ return (&propFilterIter{
|
|
|
|
+ wrapped: o._enumerate(recursive),
|
|
|
|
+ all: all,
|
|
|
|
+ seen: make(map[string]bool),
|
|
|
|
+ }).next
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (o *objectGoMapReflect) equal(other objectImpl) bool {
|
|
|
|
+ if other, ok := other.(*objectGoMapReflect); ok {
|
|
|
|
+ return o.value.Interface() == other.value.Interface()
|
|
|
|
+ }
|
|
|
|
+ return false
|
|
|
|
+}
|