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