1 package goja
2
3 import "github.com/dop251/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 }
140
View as plain text