go.ketch.com/lib/goja@v0.0.1/object_gomap.go (about)

     1  package goja
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"go.ketch.com/lib/goja/unistring"
     7  )
     8  
     9  type objectGoMapSimple struct {
    10  	baseObject
    11  	data map[string]interface{}
    12  }
    13  
    14  func (o *objectGoMapSimple) init() {
    15  	o.baseObject.init()
    16  	o.prototype = o.val.runtime.global.ObjectPrototype
    17  	o.class = classObject
    18  	o.extensible = true
    19  }
    20  
    21  func (o *objectGoMapSimple) _getStr(name string) Value {
    22  	v, exists := o.data[name]
    23  	if !exists {
    24  		return nil
    25  	}
    26  	return o.val.runtime.ToValue(v)
    27  }
    28  
    29  func (o *objectGoMapSimple) getStr(name unistring.String, receiver Value) Value {
    30  	if v := o._getStr(name.String()); v != nil {
    31  		return v
    32  	}
    33  	return o.baseObject.getStr(name, receiver)
    34  }
    35  
    36  func (o *objectGoMapSimple) getOwnPropStr(name unistring.String) Value {
    37  	if v := o._getStr(name.String()); v != nil {
    38  		return v
    39  	}
    40  	return nil
    41  }
    42  
    43  func (o *objectGoMapSimple) setOwnStr(name unistring.String, val Value, throw bool) bool {
    44  	n := name.String()
    45  	if _, exists := o.data[n]; exists {
    46  		o.data[n] = val.Export()
    47  		return true
    48  	}
    49  	if proto := o.prototype; proto != nil {
    50  		// we know it's foreign because prototype loops are not allowed
    51  		if res, ok := proto.self.setForeignStr(name, val, o.val, throw); ok {
    52  			return res
    53  		}
    54  	}
    55  	// new property
    56  	if !o.extensible {
    57  		o.val.runtime.typeErrorResult(throw, "Cannot add property %s, object is not extensible", name)
    58  		return false
    59  	} else {
    60  		o.data[n] = val.Export()
    61  	}
    62  	return true
    63  }
    64  
    65  func trueValIfPresent(present bool) Value {
    66  	if present {
    67  		return valueTrue
    68  	}
    69  	return nil
    70  }
    71  
    72  func (o *objectGoMapSimple) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
    73  	return o._setForeignStr(name, trueValIfPresent(o._hasStr(name.String())), val, receiver, throw)
    74  }
    75  
    76  func (o *objectGoMapSimple) _hasStr(name string) bool {
    77  	_, exists := o.data[name]
    78  	return exists
    79  }
    80  
    81  func (o *objectGoMapSimple) hasOwnPropertyStr(name unistring.String) bool {
    82  	return o._hasStr(name.String())
    83  }
    84  
    85  func (o *objectGoMapSimple) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
    86  	if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) {
    87  		return false
    88  	}
    89  
    90  	n := name.String()
    91  	if o.extensible || o._hasStr(n) {
    92  		o.data[n] = descr.Value.Export()
    93  		return true
    94  	}
    95  
    96  	o.val.runtime.typeErrorResult(throw, "Cannot define property %s, object is not extensible", n)
    97  	return false
    98  }
    99  
   100  /*
   101  func (o *objectGoMapSimple) toPrimitiveNumber() Value {
   102  	return o.toPrimitiveString()
   103  }
   104  
   105  func (o *objectGoMapSimple) toPrimitiveString() Value {
   106  	return stringObjectObject
   107  }
   108  
   109  func (o *objectGoMapSimple) toPrimitive() Value {
   110  	return o.toPrimitiveString()
   111  }
   112  
   113  func (o *objectGoMapSimple) assertCallable() (call func(FunctionCall) Value, ok bool) {
   114  	return nil, false
   115  }
   116  */
   117  
   118  func (o *objectGoMapSimple) deleteStr(name unistring.String, _ bool) bool {
   119  	delete(o.data, name.String())
   120  	return true
   121  }
   122  
   123  type gomapPropIter struct {
   124  	o         *objectGoMapSimple
   125  	propNames []string
   126  	idx       int
   127  }
   128  
   129  func (i *gomapPropIter) next() (propIterItem, iterNextFunc) {
   130  	for i.idx < len(i.propNames) {
   131  		name := i.propNames[i.idx]
   132  		i.idx++
   133  		if _, exists := i.o.data[name]; exists {
   134  			return propIterItem{name: newStringValue(name), enumerable: _ENUM_TRUE}, i.next
   135  		}
   136  	}
   137  
   138  	return propIterItem{}, nil
   139  }
   140  
   141  func (o *objectGoMapSimple) iterateStringKeys() iterNextFunc {
   142  	propNames := make([]string, len(o.data))
   143  	i := 0
   144  	for key := range o.data {
   145  		propNames[i] = key
   146  		i++
   147  	}
   148  
   149  	return (&gomapPropIter{
   150  		o:         o,
   151  		propNames: propNames,
   152  	}).next
   153  }
   154  
   155  func (o *objectGoMapSimple) stringKeys(_ bool, accum []Value) []Value {
   156  	// all own keys are enumerable
   157  	for key := range o.data {
   158  		accum = append(accum, newStringValue(key))
   159  	}
   160  	return accum
   161  }
   162  
   163  func (o *objectGoMapSimple) export(*objectExportCtx) interface{} {
   164  	return o.data
   165  }
   166  
   167  func (o *objectGoMapSimple) exportType() reflect.Type {
   168  	return reflectTypeMap
   169  }
   170  
   171  func (o *objectGoMapSimple) equal(other objectImpl) bool {
   172  	if other, ok := other.(*objectGoMapSimple); ok {
   173  		return o == other
   174  	}
   175  	return false
   176  }