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

     1  package goja
     2  
     3  import "github.com/nuvolaris/goja/unistring"
     4  
     5  type argumentsObject struct {
     6  	baseObject
     7  	length int
     8  }
     9  
    10  type mappedProperty struct {
    11  	valueProperty
    12  	v *Value
    13  }
    14  
    15  func (a *argumentsObject) getStr(name unistring.String, receiver Value) Value {
    16  	return a.getStrWithOwnProp(a.getOwnPropStr(name), name, receiver)
    17  }
    18  
    19  func (a *argumentsObject) getOwnPropStr(name unistring.String) Value {
    20  	if mapped, ok := a.values[name].(*mappedProperty); ok {
    21  		if mapped.writable && mapped.enumerable && mapped.configurable {
    22  			return *mapped.v
    23  		}
    24  		return &valueProperty{
    25  			value:        *mapped.v,
    26  			writable:     mapped.writable,
    27  			configurable: mapped.configurable,
    28  			enumerable:   mapped.enumerable,
    29  		}
    30  	}
    31  
    32  	return a.baseObject.getOwnPropStr(name)
    33  }
    34  
    35  func (a *argumentsObject) init() {
    36  	a.baseObject.init()
    37  	a._putProp("length", intToValue(int64(a.length)), true, false, true)
    38  }
    39  
    40  func (a *argumentsObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
    41  	if prop, ok := a.values[name].(*mappedProperty); ok {
    42  		if !prop.writable {
    43  			a.val.runtime.typeErrorResult(throw, "Property is not writable: %s", name)
    44  			return false
    45  		}
    46  		*prop.v = val
    47  		return true
    48  	}
    49  	return a.baseObject.setOwnStr(name, val, throw)
    50  }
    51  
    52  func (a *argumentsObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
    53  	return a._setForeignStr(name, a.getOwnPropStr(name), val, receiver, throw)
    54  }
    55  
    56  func (a *argumentsObject) deleteStr(name unistring.String, throw bool) bool {
    57  	if prop, ok := a.values[name].(*mappedProperty); ok {
    58  		if !a.checkDeleteProp(name, &prop.valueProperty, throw) {
    59  			return false
    60  		}
    61  		a._delete(name)
    62  		return true
    63  	}
    64  
    65  	return a.baseObject.deleteStr(name, throw)
    66  }
    67  
    68  type argumentsPropIter struct {
    69  	wrapped iterNextFunc
    70  }
    71  
    72  func (i *argumentsPropIter) next() (propIterItem, iterNextFunc) {
    73  	var item propIterItem
    74  	item, i.wrapped = i.wrapped()
    75  	if i.wrapped == nil {
    76  		return propIterItem{}, nil
    77  	}
    78  	if prop, ok := item.value.(*mappedProperty); ok {
    79  		item.value = *prop.v
    80  	}
    81  	return item, i.next
    82  }
    83  
    84  func (a *argumentsObject) iterateStringKeys() iterNextFunc {
    85  	return (&argumentsPropIter{
    86  		wrapped: a.baseObject.iterateStringKeys(),
    87  	}).next
    88  }
    89  
    90  func (a *argumentsObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
    91  	if mapped, ok := a.values[name].(*mappedProperty); ok {
    92  		existing := &valueProperty{
    93  			configurable: mapped.configurable,
    94  			writable:     true,
    95  			enumerable:   mapped.enumerable,
    96  			value:        *mapped.v,
    97  		}
    98  
    99  		val, ok := a.baseObject._defineOwnProperty(name, existing, descr, throw)
   100  		if !ok {
   101  			return false
   102  		}
   103  
   104  		if prop, ok := val.(*valueProperty); ok {
   105  			if !prop.accessor {
   106  				*mapped.v = prop.value
   107  			}
   108  			if prop.accessor || !prop.writable {
   109  				a._put(name, prop)
   110  				return true
   111  			}
   112  			mapped.configurable = prop.configurable
   113  			mapped.enumerable = prop.enumerable
   114  		} else {
   115  			*mapped.v = val
   116  			mapped.configurable = true
   117  			mapped.enumerable = true
   118  		}
   119  
   120  		return true
   121  	}
   122  
   123  	return a.baseObject.defineOwnPropertyStr(name, descr, throw)
   124  }
   125  
   126  func (a *argumentsObject) export(ctx *objectExportCtx) interface{} {
   127  	if v, exists := ctx.get(a.val); exists {
   128  		return v
   129  	}
   130  	arr := make([]interface{}, a.length)
   131  	ctx.put(a.val, arr)
   132  	for i := range arr {
   133  		v := a.getIdx(valueInt(int64(i)), nil)
   134  		if v != nil {
   135  			arr[i] = exportValue(v, ctx)
   136  		}
   137  	}
   138  	return arr
   139  }