package goja
import (
"fmt"
"reflect"
"github.com/dop251/goja/unistring"
)
type objectGoMapReflect struct {
objectGoReflect
keyType, valueType reflect .Type
}
func (o *objectGoMapReflect ) init () {
o .objectGoReflect .init ()
o .keyType = o .fieldsValue .Type ().Key ()
o .valueType = o .fieldsValue .Type ().Elem ()
}
func (o *objectGoMapReflect ) toKey (n Value , throw bool ) reflect .Value {
key := reflect .New (o .keyType ).Elem ()
err := o .val .runtime .toReflectValue (n , key , &objectExportCtx {})
if err != nil {
o .val .runtime .typeErrorResult (throw , "map key conversion error: %v" , err )
return reflect .Value {}
}
return key
}
func (o *objectGoMapReflect ) strToKey (name string , throw bool ) reflect .Value {
if o .keyType .Kind () == reflect .String {
return reflect .ValueOf (name ).Convert (o .keyType )
}
return o .toKey (newStringValue (name ), throw )
}
func (o *objectGoMapReflect ) _getKey (key reflect .Value ) Value {
if !key .IsValid () {
return nil
}
if v := o .fieldsValue .MapIndex (key ); v .IsValid () {
rv := v
if rv .Kind () == reflect .Interface {
rv = rv .Elem ()
}
return o .val .runtime .toValue (v .Interface (), rv )
}
return nil
}
func (o *objectGoMapReflect ) _get (n Value ) Value {
return o ._getKey (o .toKey (n , false ))
}
func (o *objectGoMapReflect ) _getStr (name string ) Value {
return o ._getKey (o .strToKey (name , false ))
}
func (o *objectGoMapReflect ) getStr (name unistring .String , receiver Value ) Value {
if v := o ._getStr (name .String ()); v != nil {
return v
}
return o .objectGoReflect .getStr (name , receiver )
}
func (o *objectGoMapReflect ) getIdx (idx valueInt , receiver Value ) Value {
if v := o ._get (idx ); v != nil {
return v
}
return o .objectGoReflect .getIdx (idx , receiver )
}
func (o *objectGoMapReflect ) getOwnPropStr (name unistring .String ) Value {
if v := o ._getStr (name .String ()); v != nil {
return &valueProperty {
value : v ,
writable : true ,
enumerable : true ,
}
}
return o .objectGoReflect .getOwnPropStr (name )
}
func (o *objectGoMapReflect ) getOwnPropIdx (idx valueInt ) Value {
if v := o ._get (idx ); v != nil {
return &valueProperty {
value : v ,
writable : true ,
enumerable : true ,
}
}
return o .objectGoReflect .getOwnPropStr (idx .string ())
}
func (o *objectGoMapReflect ) toValue (val Value , throw bool ) (reflect .Value , bool ) {
v := reflect .New (o .valueType ).Elem ()
err := o .val .runtime .toReflectValue (val , v , &objectExportCtx {})
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 reflect .Value , val Value , throw bool ) bool {
if key .IsValid () {
if o .extensible || o .fieldsValue .MapIndex (key ).IsValid () {
v , ok := o .toValue (val , throw )
if !ok {
return false
}
o .fieldsValue .SetMapIndex (key , v )
} else {
o .val .runtime .typeErrorResult (throw , "Cannot set property %v, object is not extensible" , key )
return false
}
return true
}
return false
}
func (o *objectGoMapReflect ) setOwnStr (name unistring .String , val Value , throw bool ) bool {
n := name .String ()
key := o .strToKey (n , false )
if !key .IsValid () || !o .fieldsValue .MapIndex (key ).IsValid () {
if proto := o .prototype ; proto != nil {
if res , ok := proto .self .setForeignStr (name , val , o .val , throw ); ok {
return res
}
}
if !o .extensible {
o .val .runtime .typeErrorResult (throw , "Cannot add property %s, object is not extensible" , n )
return false
} else {
if throw && !key .IsValid () {
o .strToKey (n , true )
return false
}
}
}
o ._put (key , val , throw )
return true
}
func (o *objectGoMapReflect ) setOwnIdx (idx valueInt , val Value , throw bool ) bool {
key := o .toKey (idx , false )
if !key .IsValid () || !o .fieldsValue .MapIndex (key ).IsValid () {
if proto := o .prototype ; proto != nil {
if res , ok := proto .self .setForeignIdx (idx , val , o .val , throw ); ok {
return res
}
}
if !o .extensible {
o .val .runtime .typeErrorResult (throw , "Cannot add property %d, object is not extensible" , idx )
return false
} else {
if throw && !key .IsValid () {
o .toKey (idx , true )
return false
}
}
}
o ._put (key , val , throw )
return true
}
func (o *objectGoMapReflect ) setForeignStr (name unistring .String , val , receiver Value , throw bool ) (bool , bool ) {
return o ._setForeignStr (name , trueValIfPresent (o .hasOwnPropertyStr (name )), val , receiver , throw )
}
func (o *objectGoMapReflect ) setForeignIdx (idx valueInt , val , receiver Value , throw bool ) (bool , bool ) {
return o ._setForeignIdx (idx , trueValIfPresent (o .hasOwnPropertyIdx (idx )), val , receiver , throw )
}
func (o *objectGoMapReflect ) defineOwnPropertyStr (name unistring .String , descr PropertyDescriptor , throw bool ) bool {
if !o .val .runtime .checkHostObjectPropertyDescr (name , descr , throw ) {
return false
}
return o ._put (o .strToKey (name .String (), throw ), descr .Value , throw )
}
func (o *objectGoMapReflect ) defineOwnPropertyIdx (idx valueInt , descr PropertyDescriptor , throw bool ) bool {
if !o .val .runtime .checkHostObjectPropertyDescr (idx .string (), descr , throw ) {
return false
}
return o ._put (o .toKey (idx , throw ), descr .Value , throw )
}
func (o *objectGoMapReflect ) hasOwnPropertyStr (name unistring .String ) bool {
key := o .strToKey (name .String (), false )
if key .IsValid () && o .fieldsValue .MapIndex (key ).IsValid () {
return true
}
return false
}
func (o *objectGoMapReflect ) hasOwnPropertyIdx (idx valueInt ) bool {
key := o .toKey (idx , false )
if key .IsValid () && o .fieldsValue .MapIndex (key ).IsValid () {
return true
}
return false
}
func (o *objectGoMapReflect ) deleteStr (name unistring .String , throw bool ) bool {
key := o .strToKey (name .String (), throw )
if !key .IsValid () {
return false
}
o .fieldsValue .SetMapIndex (key , reflect .Value {})
return true
}
func (o *objectGoMapReflect ) deleteIdx (idx valueInt , throw bool ) bool {
key := o .toKey (idx , throw )
if !key .IsValid () {
return false
}
o .fieldsValue .SetMapIndex (key , reflect .Value {})
return true
}
type gomapReflectPropIter struct {
o *objectGoMapReflect
keys []reflect .Value
idx int
}
func (i *gomapReflectPropIter ) next () (propIterItem , iterNextFunc ) {
for i .idx < len (i .keys ) {
key := i .keys [i .idx ]
v := i .o .fieldsValue .MapIndex (key )
i .idx ++
if v .IsValid () {
return propIterItem {name : i .o .keyToString (key ), enumerable : _ENUM_TRUE }, i .next
}
}
return propIterItem {}, nil
}
func (o *objectGoMapReflect ) iterateStringKeys () iterNextFunc {
return (&gomapReflectPropIter {
o : o ,
keys : o .fieldsValue .MapKeys (),
}).next
}
func (o *objectGoMapReflect ) stringKeys (_ bool , accum []Value ) []Value {
for _ , key := range o .fieldsValue .MapKeys () {
accum = append (accum , o .keyToString (key ))
}
return accum
}
func (*objectGoMapReflect ) keyToString (key reflect .Value ) String {
kind := key .Kind ()
if kind == reflect .String {
return newStringValue (key .String ())
}
str := fmt .Sprintf ("%v" , key )
switch kind {
case reflect .Int ,
reflect .Int8 ,
reflect .Int16 ,
reflect .Int32 ,
reflect .Int64 ,
reflect .Uint ,
reflect .Uint8 ,
reflect .Uint16 ,
reflect .Uint32 ,
reflect .Uint64 ,
reflect .Float32 ,
reflect .Float64 :
return asciiString (str )
default :
return newStringValue (str )
}
}
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 .