1package goja 2 3import "github.com/dop251/goja/unistring" 4 5type argumentsObject struct { 6 baseObject 7 length int 8} 9 10type mappedProperty struct { 11 valueProperty 12 v *Value 13} 14 15func (a *argumentsObject) getStr(name unistring.String, receiver Value) Value { 16 return a.getStrWithOwnProp(a.getOwnPropStr(name), name, receiver) 17} 18 19func (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 35func (a *argumentsObject) init() { 36 a.baseObject.init() 37 a._putProp("length", intToValue(int64(a.length)), true, false, true) 38} 39 40func (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 52func (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 56func (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 68type argumentsPropIter struct { 69 wrapped iterNextFunc 70} 71 72func (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 84func (a *argumentsObject) enumerateOwnKeys() iterNextFunc { 85 return (&argumentsPropIter{ 86 wrapped: a.baseObject.enumerateOwnKeys(), 87 }).next 88} 89 90func (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 126func (a *argumentsObject) export(ctx *objectExportCtx) interface{} { 127 if v, exists := ctx.get(a); exists { 128 return v 129 } 130 arr := make([]interface{}, a.length) 131 ctx.put(a, 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} 140