]>
Commit | Line | Data |
---|---|---|
9dae56ea A |
1 | /* |
2 | * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) | |
3 | * Copyright (C) 2001 Peter Kelly (pmk@post.com) | |
f9bf01c6 | 4 | * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. |
9dae56ea A |
5 | * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) |
6 | * Copyright (C) 2007 Maks Orlovich | |
7 | * | |
8 | * This library is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Library General Public | |
10 | * License as published by the Free Software Foundation; either | |
11 | * version 2 of the License, or (at your option) any later version. | |
12 | * | |
13 | * This library is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * Library General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU Library General Public License | |
19 | * along with this library; see the file COPYING.LIB. If not, write to | |
20 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
21 | * Boston, MA 02110-1301, USA. | |
22 | * | |
23 | */ | |
24 | ||
25 | #include "config.h" | |
26 | #include "Arguments.h" | |
27 | ||
28 | #include "JSActivation.h" | |
29 | #include "JSFunction.h" | |
30 | #include "JSGlobalObject.h" | |
31 | ||
32 | using namespace std; | |
33 | ||
34 | namespace JSC { | |
35 | ||
36 | ASSERT_CLASS_FITS_IN_CELL(Arguments); | |
37 | ||
38 | const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 }; | |
39 | ||
40 | Arguments::~Arguments() | |
41 | { | |
42 | if (d->extraArguments != d->extraArgumentsFixedBuffer) | |
43 | delete [] d->extraArguments; | |
44 | } | |
45 | ||
f9bf01c6 | 46 | void Arguments::markChildren(MarkStack& markStack) |
9dae56ea | 47 | { |
f9bf01c6 | 48 | JSObject::markChildren(markStack); |
9dae56ea | 49 | |
f9bf01c6 A |
50 | if (d->registerArray) |
51 | markStack.appendValues(reinterpret_cast<JSValue*>(d->registerArray.get()), d->numParameters); | |
9dae56ea A |
52 | |
53 | if (d->extraArguments) { | |
54 | unsigned numExtraArguments = d->numArguments - d->numParameters; | |
f9bf01c6 | 55 | markStack.appendValues(reinterpret_cast<JSValue*>(d->extraArguments), numExtraArguments); |
9dae56ea A |
56 | } |
57 | ||
f9bf01c6 | 58 | markStack.append(d->callee); |
9dae56ea | 59 | |
f9bf01c6 A |
60 | if (d->activation) |
61 | markStack.append(d->activation); | |
9dae56ea A |
62 | } |
63 | ||
ba379fdc | 64 | void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize) |
9dae56ea | 65 | { |
ba379fdc A |
66 | if (UNLIKELY(d->overrodeLength)) { |
67 | unsigned length = min(get(exec, exec->propertyNames().length).toUInt32(exec), maxSize); | |
68 | for (unsigned i = 0; i < length; i++) | |
69 | buffer[i] = get(exec, i); | |
70 | return; | |
71 | } | |
72 | ||
73 | if (LIKELY(!d->deletedArguments)) { | |
74 | unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize); | |
75 | unsigned i = 0; | |
76 | for (; i < parametersLength; ++i) | |
77 | buffer[i] = d->registers[d->firstParameterIndex + i].jsValue(); | |
78 | for (; i < d->numArguments; ++i) | |
79 | buffer[i] = d->extraArguments[i - d->numParameters].jsValue(); | |
80 | return; | |
81 | } | |
82 | ||
83 | unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize); | |
84 | unsigned i = 0; | |
85 | for (; i < parametersLength; ++i) { | |
86 | if (!d->deletedArguments[i]) | |
87 | buffer[i] = d->registers[d->firstParameterIndex + i].jsValue(); | |
88 | else | |
89 | buffer[i] = get(exec, i); | |
90 | } | |
91 | for (; i < d->numArguments; ++i) { | |
92 | if (!d->deletedArguments[i]) | |
93 | buffer[i] = d->extraArguments[i - d->numParameters].jsValue(); | |
94 | else | |
95 | buffer[i] = get(exec, i); | |
96 | } | |
97 | } | |
98 | ||
99 | void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args) | |
100 | { | |
101 | if (UNLIKELY(d->overrodeLength)) { | |
102 | unsigned length = get(exec, exec->propertyNames().length).toUInt32(exec); | |
103 | for (unsigned i = 0; i < length; i++) | |
104 | args.append(get(exec, i)); | |
105 | return; | |
106 | } | |
107 | ||
9dae56ea A |
108 | if (LIKELY(!d->deletedArguments)) { |
109 | if (LIKELY(!d->numParameters)) { | |
110 | args.initialize(d->extraArguments, d->numArguments); | |
111 | return; | |
112 | } | |
113 | ||
114 | if (d->numParameters == d->numArguments) { | |
115 | args.initialize(&d->registers[d->firstParameterIndex], d->numArguments); | |
116 | return; | |
117 | } | |
118 | ||
119 | unsigned parametersLength = min(d->numParameters, d->numArguments); | |
120 | unsigned i = 0; | |
121 | for (; i < parametersLength; ++i) | |
ba379fdc | 122 | args.append(d->registers[d->firstParameterIndex + i].jsValue()); |
9dae56ea | 123 | for (; i < d->numArguments; ++i) |
ba379fdc | 124 | args.append(d->extraArguments[i - d->numParameters].jsValue()); |
9dae56ea A |
125 | return; |
126 | } | |
127 | ||
128 | unsigned parametersLength = min(d->numParameters, d->numArguments); | |
129 | unsigned i = 0; | |
130 | for (; i < parametersLength; ++i) { | |
131 | if (!d->deletedArguments[i]) | |
ba379fdc | 132 | args.append(d->registers[d->firstParameterIndex + i].jsValue()); |
9dae56ea A |
133 | else |
134 | args.append(get(exec, i)); | |
135 | } | |
136 | for (; i < d->numArguments; ++i) { | |
137 | if (!d->deletedArguments[i]) | |
ba379fdc | 138 | args.append(d->extraArguments[i - d->numParameters].jsValue()); |
9dae56ea A |
139 | else |
140 | args.append(get(exec, i)); | |
141 | } | |
142 | } | |
143 | ||
144 | bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot) | |
145 | { | |
146 | if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { | |
147 | if (i < d->numParameters) { | |
148 | slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]); | |
149 | } else | |
ba379fdc | 150 | slot.setValue(d->extraArguments[i - d->numParameters].jsValue()); |
9dae56ea A |
151 | return true; |
152 | } | |
153 | ||
154 | return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::from(i)), slot); | |
155 | } | |
156 | ||
157 | bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) | |
158 | { | |
159 | bool isArrayIndex; | |
160 | unsigned i = propertyName.toArrayIndex(&isArrayIndex); | |
161 | if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { | |
162 | if (i < d->numParameters) { | |
163 | slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]); | |
164 | } else | |
ba379fdc | 165 | slot.setValue(d->extraArguments[i - d->numParameters].jsValue()); |
9dae56ea A |
166 | return true; |
167 | } | |
168 | ||
169 | if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) { | |
170 | slot.setValue(jsNumber(exec, d->numArguments)); | |
171 | return true; | |
172 | } | |
173 | ||
174 | if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) { | |
175 | slot.setValue(d->callee); | |
176 | return true; | |
177 | } | |
178 | ||
179 | return JSObject::getOwnPropertySlot(exec, propertyName, slot); | |
180 | } | |
181 | ||
f9bf01c6 A |
182 | bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) |
183 | { | |
184 | bool isArrayIndex; | |
185 | unsigned i = propertyName.toArrayIndex(&isArrayIndex); | |
186 | if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { | |
187 | if (i < d->numParameters) { | |
188 | descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].jsValue(), DontEnum); | |
189 | } else | |
190 | descriptor.setDescriptor(d->extraArguments[i - d->numParameters].jsValue(), DontEnum); | |
191 | return true; | |
192 | } | |
193 | ||
194 | if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) { | |
195 | descriptor.setDescriptor(jsNumber(exec, d->numArguments), DontEnum); | |
196 | return true; | |
197 | } | |
198 | ||
199 | if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) { | |
200 | descriptor.setDescriptor(d->callee, DontEnum); | |
201 | return true; | |
202 | } | |
203 | ||
204 | return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); | |
205 | } | |
206 | ||
207 | void Arguments::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) | |
208 | { | |
209 | if (mode == IncludeDontEnumProperties) { | |
210 | for (unsigned i = 0; i < d->numArguments; ++i) { | |
211 | if (!d->deletedArguments || !d->deletedArguments[i]) | |
212 | propertyNames.add(Identifier(exec, UString::from(i))); | |
213 | } | |
214 | propertyNames.add(exec->propertyNames().callee); | |
215 | propertyNames.add(exec->propertyNames().length); | |
216 | } | |
217 | JSObject::getOwnPropertyNames(exec, propertyNames, mode); | |
218 | } | |
219 | ||
ba379fdc | 220 | void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot) |
9dae56ea A |
221 | { |
222 | if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { | |
223 | if (i < d->numParameters) | |
ba379fdc | 224 | d->registers[d->firstParameterIndex + i] = JSValue(value); |
9dae56ea | 225 | else |
ba379fdc | 226 | d->extraArguments[i - d->numParameters] = JSValue(value); |
9dae56ea A |
227 | return; |
228 | } | |
229 | ||
230 | JSObject::put(exec, Identifier(exec, UString::from(i)), value, slot); | |
231 | } | |
232 | ||
ba379fdc | 233 | void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) |
9dae56ea A |
234 | { |
235 | bool isArrayIndex; | |
236 | unsigned i = propertyName.toArrayIndex(&isArrayIndex); | |
237 | if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { | |
238 | if (i < d->numParameters) | |
ba379fdc | 239 | d->registers[d->firstParameterIndex + i] = JSValue(value); |
9dae56ea | 240 | else |
ba379fdc | 241 | d->extraArguments[i - d->numParameters] = JSValue(value); |
9dae56ea A |
242 | return; |
243 | } | |
244 | ||
245 | if (propertyName == exec->propertyNames().length && !d->overrodeLength) { | |
246 | d->overrodeLength = true; | |
247 | putDirect(propertyName, value, DontEnum); | |
248 | return; | |
249 | } | |
250 | ||
251 | if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) { | |
252 | d->overrodeCallee = true; | |
253 | putDirect(propertyName, value, DontEnum); | |
254 | return; | |
255 | } | |
256 | ||
257 | JSObject::put(exec, propertyName, value, slot); | |
258 | } | |
259 | ||
260 | bool Arguments::deleteProperty(ExecState* exec, unsigned i) | |
261 | { | |
262 | if (i < d->numArguments) { | |
263 | if (!d->deletedArguments) { | |
264 | d->deletedArguments.set(new bool[d->numArguments]); | |
265 | memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments); | |
266 | } | |
267 | if (!d->deletedArguments[i]) { | |
268 | d->deletedArguments[i] = true; | |
269 | return true; | |
270 | } | |
271 | } | |
272 | ||
273 | return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i))); | |
274 | } | |
275 | ||
276 | bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName) | |
277 | { | |
278 | bool isArrayIndex; | |
279 | unsigned i = propertyName.toArrayIndex(&isArrayIndex); | |
280 | if (isArrayIndex && i < d->numArguments) { | |
281 | if (!d->deletedArguments) { | |
282 | d->deletedArguments.set(new bool[d->numArguments]); | |
283 | memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments); | |
284 | } | |
285 | if (!d->deletedArguments[i]) { | |
286 | d->deletedArguments[i] = true; | |
287 | return true; | |
288 | } | |
289 | } | |
290 | ||
291 | if (propertyName == exec->propertyNames().length && !d->overrodeLength) { | |
292 | d->overrodeLength = true; | |
293 | return true; | |
294 | } | |
295 | ||
296 | if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) { | |
297 | d->overrodeCallee = true; | |
298 | return true; | |
299 | } | |
300 | ||
301 | return JSObject::deleteProperty(exec, propertyName); | |
302 | } | |
303 | ||
304 | } // namespace JSC |