github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/object_gomap.go (about)

     1  package goja
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"github.com/nuvolaris/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  func (o *objectGoMapSimple) deleteStr(name unistring.String, _ bool) bool {
   101  	delete(o.data, name.String())
   102  	return true
   103  }
   104  
   105  type gomapPropIter struct {
   106  	o         *objectGoMapSimple
   107  	propNames []string
   108  	idx       int
   109  }
   110  
   111  func (i *gomapPropIter) next() (propIterItem, iterNextFunc) {
   112  	for i.idx < len(i.propNames) {
   113  		name := i.propNames[i.idx]
   114  		i.idx++
   115  		if _, exists := i.o.data[name]; exists {
   116  			return propIterItem{name: newStringValue(name), enumerable: _ENUM_TRUE}, i.next
   117  		}
   118  	}
   119  
   120  	return propIterItem{}, nil
   121  }
   122  
   123  func (o *objectGoMapSimple) iterateStringKeys() iterNextFunc {
   124  	propNames := make([]string, len(o.data))
   125  	i := 0
   126  	for key := range o.data {
   127  		propNames[i] = key
   128  		i++
   129  	}
   130  
   131  	return (&gomapPropIter{
   132  		o:         o,
   133  		propNames: propNames,
   134  	}).next
   135  }
   136  
   137  func (o *objectGoMapSimple) stringKeys(_ bool, accum []Value) []Value {
   138  	// all own keys are enumerable
   139  	for key := range o.data {
   140  		accum = append(accum, newStringValue(key))
   141  	}
   142  	return accum
   143  }
   144  
   145  func (o *objectGoMapSimple) export(*objectExportCtx) interface{} {
   146  	return o.data
   147  }
   148  
   149  func (o *objectGoMapSimple) exportType() reflect.Type {
   150  	return reflectTypeMap
   151  }
   152  
   153  func (o *objectGoMapSimple) equal(other objectImpl) bool {
   154  	if other, ok := other.(*objectGoMapSimple); ok {
   155  		return o == other
   156  	}
   157  	return false
   158  }