2 * Copyright (C) 2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef GenericArgumentsInlines_h
27 #define GenericArgumentsInlines_h
29 #include "GenericArguments.h"
30 #include "JSCInlines.h"
34 template<typename Type
>
35 bool GenericArguments
<Type
>::getOwnPropertySlot(JSObject
* object
, ExecState
* exec
, PropertyName ident
, PropertySlot
& slot
)
37 Type
* thisObject
= jsCast
<Type
*>(object
);
40 if (!thisObject
->overrodeThings()) {
41 if (ident
== vm
.propertyNames
->length
) {
42 slot
.setValue(thisObject
, DontEnum
, jsNumber(thisObject
->internalLength()));
45 if (ident
== vm
.propertyNames
->callee
) {
46 slot
.setValue(thisObject
, DontEnum
, thisObject
->callee().get());
49 if (ident
== vm
.propertyNames
->iteratorSymbol
) {
50 slot
.setValue(thisObject
, DontEnum
, thisObject
->globalObject()->arrayProtoValuesFunction());
55 Optional
<uint32_t> index
= parseIndex(ident
);
56 if (index
&& thisObject
->canAccessIndexQuickly(index
.value())) {
57 slot
.setValue(thisObject
, None
, thisObject
->getIndexQuickly(index
.value()));
61 return Base::getOwnPropertySlot(thisObject
, exec
, ident
, slot
);
64 template<typename Type
>
65 bool GenericArguments
<Type
>::getOwnPropertySlotByIndex(JSObject
* object
, ExecState
* exec
, unsigned index
, PropertySlot
& slot
)
67 Type
* thisObject
= jsCast
<Type
*>(object
);
69 if (thisObject
->canAccessIndexQuickly(index
)) {
70 slot
.setValue(thisObject
, None
, thisObject
->getIndexQuickly(index
));
74 return Base::getOwnPropertySlotByIndex(object
, exec
, index
, slot
);
77 template<typename Type
>
78 void GenericArguments
<Type
>::getOwnPropertyNames(JSObject
* object
, ExecState
* exec
, PropertyNameArray
& array
, EnumerationMode mode
)
80 Type
* thisObject
= jsCast
<Type
*>(object
);
82 for (unsigned i
= 0; i
< thisObject
->internalLength(); ++i
) {
83 if (!thisObject
->canAccessIndexQuickly(i
))
85 array
.add(Identifier::from(exec
, i
));
87 if (mode
.includeDontEnumProperties() && !thisObject
->overrodeThings()) {
88 array
.add(exec
->propertyNames().length
);
89 array
.add(exec
->propertyNames().callee
);
90 if (mode
.includeSymbolProperties())
91 array
.add(exec
->propertyNames().iteratorSymbol
);
93 Base::getOwnPropertyNames(thisObject
, exec
, array
, mode
);
96 template<typename Type
>
97 void GenericArguments
<Type
>::put(JSCell
* cell
, ExecState
* exec
, PropertyName ident
, JSValue value
, PutPropertySlot
& slot
)
99 Type
* thisObject
= jsCast
<Type
*>(cell
);
102 if (!thisObject
->overrodeThings()
103 && (ident
== vm
.propertyNames
->length
104 || ident
== vm
.propertyNames
->callee
105 || ident
== vm
.propertyNames
->iteratorSymbol
)) {
106 thisObject
->overrideThings(vm
);
107 PutPropertySlot dummy
= slot
; // This put is not cacheable, so we shadow the slot that was given to us.
108 Base::put(thisObject
, exec
, ident
, value
, dummy
);
112 Optional
<uint32_t> index
= parseIndex(ident
);
113 if (index
&& thisObject
->canAccessIndexQuickly(index
.value())) {
114 thisObject
->setIndexQuickly(vm
, index
.value(), value
);
118 Base::put(thisObject
, exec
, ident
, value
, slot
);
121 template<typename Type
>
122 void GenericArguments
<Type
>::putByIndex(JSCell
* cell
, ExecState
* exec
, unsigned index
, JSValue value
, bool shouldThrow
)
124 Type
* thisObject
= jsCast
<Type
*>(cell
);
127 if (thisObject
->canAccessIndexQuickly(index
)) {
128 thisObject
->setIndexQuickly(vm
, index
, value
);
132 return Base::putByIndex(cell
, exec
, index
, value
, shouldThrow
);
135 template<typename Type
>
136 bool GenericArguments
<Type
>::deleteProperty(JSCell
* cell
, ExecState
* exec
, PropertyName ident
)
138 Type
* thisObject
= jsCast
<Type
*>(cell
);
141 if (!thisObject
->overrodeThings()
142 && (ident
== vm
.propertyNames
->length
143 || ident
== vm
.propertyNames
->callee
144 || ident
== vm
.propertyNames
->iteratorSymbol
))
145 thisObject
->overrideThings(vm
);
147 Optional
<uint32_t> index
= parseIndex(ident
);
148 if (index
&& thisObject
->canAccessIndexQuickly(index
.value())) {
149 thisObject
->overrideArgument(vm
, index
.value());
153 return Base::deleteProperty(thisObject
, exec
, ident
);
156 template<typename Type
>
157 bool GenericArguments
<Type
>::deletePropertyByIndex(JSCell
* cell
, ExecState
* exec
, unsigned index
)
159 Type
* thisObject
= jsCast
<Type
*>(cell
);
162 if (thisObject
->canAccessIndexQuickly(index
)) {
163 thisObject
->overrideArgument(vm
, index
);
167 return Base::deletePropertyByIndex(cell
, exec
, index
);
170 template<typename Type
>
171 bool GenericArguments
<Type
>::defineOwnProperty(JSObject
* object
, ExecState
* exec
, PropertyName ident
, const PropertyDescriptor
& descriptor
, bool shouldThrow
)
173 Type
* thisObject
= jsCast
<Type
*>(object
);
176 if (ident
== vm
.propertyNames
->length
177 || ident
== vm
.propertyNames
->callee
178 || ident
== vm
.propertyNames
->iteratorSymbol
)
179 thisObject
->overrideThingsIfNecessary(vm
);
181 Optional
<uint32_t> optionalIndex
= parseIndex(ident
);
182 if (optionalIndex
&& thisObject
->canAccessIndexQuickly(optionalIndex
.value())) {
183 uint32_t index
= optionalIndex
.value();
184 if (!descriptor
.isAccessorDescriptor()) {
185 // If the property is not deleted and we are using a non-accessor descriptor, then
186 // make sure that the aliased argument sees the value.
187 if (descriptor
.value())
188 thisObject
->setIndexQuickly(vm
, index
, descriptor
.value());
190 // If the property is not deleted and we are using a non-accessor, writable
191 // descriptor, then we are done. The argument continues to be aliased. Note that we
192 // ignore the request to change enumerability. We appear to have always done so, in
193 // cases where the argument was still aliased.
194 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141952
195 if (descriptor
.writable())
199 // If the property is a non-deleted argument, then move it into the base object and
201 JSValue value
= thisObject
->getIndexQuickly(index
);
203 object
->putDirectMayBeIndex(exec
, ident
, value
);
204 thisObject
->overrideArgument(vm
, index
);
208 // Now just let the normal object machinery do its thing.
209 return Base::defineOwnProperty(object
, exec
, ident
, descriptor
, shouldThrow
);
212 template<typename Type
>
213 void GenericArguments
<Type
>::copyToArguments(ExecState
* exec
, VirtualRegister firstElementDest
, unsigned offset
, unsigned length
)
215 Type
* thisObject
= static_cast<Type
*>(this);
216 for (unsigned i
= 0; i
< length
; ++i
) {
217 if (thisObject
->canAccessIndexQuickly(i
+ offset
))
218 exec
->r(firstElementDest
+ i
) = thisObject
->getIndexQuickly(i
+ offset
);
220 exec
->r(firstElementDest
+ i
) = get(exec
, i
+ offset
);
221 if (UNLIKELY(exec
->vm().exception()))
229 #endif // GenericArgumentsInlines_h