2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
4 * Copyright (C) 2003 Peter Kelly (pmk@post.com)
5 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
25 #include "ArrayPrototype.h"
27 #include "CodeBlock.h"
28 #include "Interpreter.h"
29 #include "ObjectPrototype.h"
31 #include "Operations.h"
33 #include <wtf/Assertions.h>
34 #include <wtf/HashSet.h>
38 ASSERT_CLASS_FITS_IN_CELL(ArrayPrototype);
40 static JSValuePtr arrayProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
41 static JSValuePtr arrayProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
42 static JSValuePtr arrayProtoFuncConcat(ExecState*, JSObject*, JSValuePtr, const ArgList&);
43 static JSValuePtr arrayProtoFuncJoin(ExecState*, JSObject*, JSValuePtr, const ArgList&);
44 static JSValuePtr arrayProtoFuncPop(ExecState*, JSObject*, JSValuePtr, const ArgList&);
45 static JSValuePtr arrayProtoFuncPush(ExecState*, JSObject*, JSValuePtr, const ArgList&);
46 static JSValuePtr arrayProtoFuncReverse(ExecState*, JSObject*, JSValuePtr, const ArgList&);
47 static JSValuePtr arrayProtoFuncShift(ExecState*, JSObject*, JSValuePtr, const ArgList&);
48 static JSValuePtr arrayProtoFuncSlice(ExecState*, JSObject*, JSValuePtr, const ArgList&);
49 static JSValuePtr arrayProtoFuncSort(ExecState*, JSObject*, JSValuePtr, const ArgList&);
50 static JSValuePtr arrayProtoFuncSplice(ExecState*, JSObject*, JSValuePtr, const ArgList&);
51 static JSValuePtr arrayProtoFuncUnShift(ExecState*, JSObject*, JSValuePtr, const ArgList&);
52 static JSValuePtr arrayProtoFuncEvery(ExecState*, JSObject*, JSValuePtr, const ArgList&);
53 static JSValuePtr arrayProtoFuncForEach(ExecState*, JSObject*, JSValuePtr, const ArgList&);
54 static JSValuePtr arrayProtoFuncSome(ExecState*, JSObject*, JSValuePtr, const ArgList&);
55 static JSValuePtr arrayProtoFuncIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);
56 static JSValuePtr arrayProtoFuncFilter(ExecState*, JSObject*, JSValuePtr, const ArgList&);
57 static JSValuePtr arrayProtoFuncMap(ExecState*, JSObject*, JSValuePtr, const ArgList&);
58 static JSValuePtr arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);
62 #include "ArrayPrototype.lut.h"
66 static inline bool isNumericCompareFunction(CallType callType, const CallData& callData)
68 if (callType != CallTypeJS)
71 return callData.js.functionBody->bytecode(callData.js.scopeChain).isNumericCompareFunction();
74 // ------------------------------ ArrayPrototype ----------------------------
76 const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::arrayTable};
78 /* Source for ArrayPrototype.lut.h
80 toString arrayProtoFuncToString DontEnum|Function 0
81 toLocaleString arrayProtoFuncToLocaleString DontEnum|Function 0
82 concat arrayProtoFuncConcat DontEnum|Function 1
83 join arrayProtoFuncJoin DontEnum|Function 1
84 pop arrayProtoFuncPop DontEnum|Function 0
85 push arrayProtoFuncPush DontEnum|Function 1
86 reverse arrayProtoFuncReverse DontEnum|Function 0
87 shift arrayProtoFuncShift DontEnum|Function 0
88 slice arrayProtoFuncSlice DontEnum|Function 2
89 sort arrayProtoFuncSort DontEnum|Function 1
90 splice arrayProtoFuncSplice DontEnum|Function 2
91 unshift arrayProtoFuncUnShift DontEnum|Function 1
92 every arrayProtoFuncEvery DontEnum|Function 1
93 forEach arrayProtoFuncForEach DontEnum|Function 1
94 some arrayProtoFuncSome DontEnum|Function 1
95 indexOf arrayProtoFuncIndexOf DontEnum|Function 1
96 lastIndexOf arrayProtoFuncLastIndexOf DontEnum|Function 1
97 filter arrayProtoFuncFilter DontEnum|Function 1
98 map arrayProtoFuncMap DontEnum|Function 1
103 ArrayPrototype::ArrayPrototype(PassRefPtr<Structure> structure)
108 bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
110 return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, slot);
113 // ------------------------------ Array Functions ----------------------------
116 static JSValuePtr getProperty(ExecState* exec, JSObject* obj, unsigned index)
118 PropertySlot slot(obj);
119 if (!obj->getPropertySlot(exec, index, slot))
121 return slot.getValue(exec, index);
124 static void putProperty(ExecState* exec, JSObject* obj, const Identifier& propertyName, JSValuePtr value)
126 PutPropertySlot slot;
127 obj->put(exec, propertyName, value, slot);
130 JSValuePtr arrayProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
132 if (!thisValue.isObject(&JSArray::info))
133 return throwError(exec, TypeError);
134 JSObject* thisObj = asArray(thisValue);
136 HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
137 if (arrayVisitedElements.size() > MaxReentryDepth)
138 return throwError(exec, RangeError, "Maximum call stack size exceeded.");
140 bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
142 return jsEmptyString(exec); // return an empty string, avoiding infinite recursion.
144 Vector<UChar, 256> strBuffer;
145 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
146 for (unsigned k = 0; k < length; k++) {
148 strBuffer.append(',');
149 if (!strBuffer.data()) {
150 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
151 exec->setException(error);
155 JSValuePtr element = thisObj->get(exec, k);
156 if (element.isUndefinedOrNull())
159 UString str = element.toString(exec);
160 strBuffer.append(str.data(), str.size());
162 if (!strBuffer.data()) {
163 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
164 exec->setException(error);
167 if (exec->hadException())
170 arrayVisitedElements.remove(thisObj);
171 return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
174 JSValuePtr arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
176 if (!thisValue.isObject(&JSArray::info))
177 return throwError(exec, TypeError);
178 JSObject* thisObj = asArray(thisValue);
180 HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
181 if (arrayVisitedElements.size() > MaxReentryDepth)
182 return throwError(exec, RangeError, "Maximum call stack size exceeded.");
184 bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
186 return jsEmptyString(exec); // return an empty string, avoding infinite recursion.
188 Vector<UChar, 256> strBuffer;
189 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
190 for (unsigned k = 0; k < length; k++) {
192 strBuffer.append(',');
193 if (!strBuffer.data()) {
194 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
195 exec->setException(error);
199 JSValuePtr element = thisObj->get(exec, k);
200 if (element.isUndefinedOrNull())
203 JSObject* o = element.toObject(exec);
204 JSValuePtr conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
207 CallType callType = conversionFunction.getCallData(callData);
208 if (callType != CallTypeNone)
209 str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec);
211 str = element.toString(exec);
212 strBuffer.append(str.data(), str.size());
214 if (!strBuffer.data()) {
215 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
216 exec->setException(error);
219 if (exec->hadException())
222 arrayVisitedElements.remove(thisObj);
223 return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
226 JSValuePtr arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
228 JSObject* thisObj = thisValue.toThisObject(exec);
230 HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
231 if (arrayVisitedElements.size() > MaxReentryDepth)
232 return throwError(exec, RangeError, "Maximum call stack size exceeded.");
234 bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
236 return jsEmptyString(exec); // return an empty string, avoding infinite recursion.
238 Vector<UChar, 256> strBuffer;
241 UString separator = args.at(exec, 0).isUndefined() ? UString(&comma, 1) : args.at(exec, 0).toString(exec);
243 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
244 for (unsigned k = 0; k < length; k++) {
246 strBuffer.append(separator.data(), separator.size());
247 if (!strBuffer.data()) {
248 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
249 exec->setException(error);
253 JSValuePtr element = thisObj->get(exec, k);
254 if (element.isUndefinedOrNull())
257 UString str = element.toString(exec);
258 strBuffer.append(str.data(), str.size());
260 if (!strBuffer.data()) {
261 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
262 exec->setException(error);
265 if (exec->hadException())
268 arrayVisitedElements.remove(thisObj);
269 return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
272 JSValuePtr arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
274 JSArray* arr = constructEmptyArray(exec);
276 JSValuePtr curArg = thisValue.toThisObject(exec);
277 ArgList::const_iterator it = args.begin();
278 ArgList::const_iterator end = args.end();
280 if (curArg.isObject(&JSArray::info)) {
281 JSArray* curArray = asArray(curArg);
282 unsigned length = curArray->length();
283 for (unsigned k = 0; k < length; ++k) {
284 if (JSValuePtr v = getProperty(exec, curArray, k))
285 arr->put(exec, n, v);
289 arr->put(exec, n, curArg);
294 curArg = (*it).jsValue(exec);
301 JSValuePtr arrayProtoFuncPop(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
303 if (exec->interpreter()->isJSArray(thisValue))
304 return asArray(thisValue)->pop();
306 JSObject* thisObj = thisValue.toThisObject(exec);
308 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
310 putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
311 result = jsUndefined();
313 result = thisObj->get(exec, length - 1);
314 thisObj->deleteProperty(exec, length - 1);
315 putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - 1));
320 JSValuePtr arrayProtoFuncPush(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
322 if (exec->interpreter()->isJSArray(thisValue) && args.size() == 1) {
323 JSArray* array = asArray(thisValue);
324 array->push(exec, args.begin()->jsValue(exec));
325 return jsNumber(exec, array->length());
328 JSObject* thisObj = thisValue.toThisObject(exec);
329 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
330 for (unsigned n = 0; n < args.size(); n++)
331 thisObj->put(exec, length + n, args.at(exec, n));
332 length += args.size();
333 putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
334 return jsNumber(exec, length);
337 JSValuePtr arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
339 JSObject* thisObj = thisValue.toThisObject(exec);
340 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
341 unsigned middle = length / 2;
343 for (unsigned k = 0; k < middle; k++) {
344 unsigned lk1 = length - k - 1;
345 JSValuePtr obj2 = getProperty(exec, thisObj, lk1);
346 JSValuePtr obj = getProperty(exec, thisObj, k);
349 thisObj->put(exec, k, obj2);
351 thisObj->deleteProperty(exec, k);
354 thisObj->put(exec, lk1, obj);
356 thisObj->deleteProperty(exec, lk1);
361 JSValuePtr arrayProtoFuncShift(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
363 JSObject* thisObj = thisValue.toThisObject(exec);
366 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
368 putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
369 result = jsUndefined();
371 result = thisObj->get(exec, 0);
372 for (unsigned k = 1; k < length; k++) {
373 if (JSValuePtr obj = getProperty(exec, thisObj, k))
374 thisObj->put(exec, k - 1, obj);
376 thisObj->deleteProperty(exec, k - 1);
378 thisObj->deleteProperty(exec, length - 1);
379 putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - 1));
384 JSValuePtr arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
386 // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
388 JSObject* thisObj = thisValue.toThisObject(exec);
390 // We return a new array
391 JSArray* resObj = constructEmptyArray(exec);
392 JSValuePtr result = resObj;
393 double begin = args.at(exec, 0).toInteger(exec);
394 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
404 if (args.at(exec, 1).isUndefined())
407 end = args.at(exec, 1).toInteger(exec);
419 int b = static_cast<int>(begin);
420 int e = static_cast<int>(end);
421 for (int k = b; k < e; k++, n++) {
422 if (JSValuePtr v = getProperty(exec, thisObj, k))
423 resObj->put(exec, n, v);
425 resObj->setLength(n);
429 JSValuePtr arrayProtoFuncSort(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
431 JSObject* thisObj = thisValue.toThisObject(exec);
433 JSValuePtr function = args.at(exec, 0);
435 CallType callType = function.getCallData(callData);
437 if (thisObj->classInfo() == &JSArray::info) {
438 if (isNumericCompareFunction(callType, callData))
439 asArray(thisObj)->sortNumeric(exec, function, callType, callData);
440 else if (callType != CallTypeNone)
441 asArray(thisObj)->sort(exec, function, callType, callData);
443 asArray(thisObj)->sort(exec);
447 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
452 // "Min" sort. Not the fastest, but definitely less code than heapsort
453 // or quicksort, and much less swapping than bubblesort/insertionsort.
454 for (unsigned i = 0; i < length - 1; ++i) {
455 JSValuePtr iObj = thisObj->get(exec, i);
457 JSValuePtr minObj = iObj;
458 for (unsigned j = i + 1; j < length; ++j) {
459 JSValuePtr jObj = thisObj->get(exec, j);
460 double compareResult;
461 if (jObj.isUndefined())
462 compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1)
463 else if (minObj.isUndefined())
465 else if (callType != CallTypeNone) {
469 compareResult = call(exec, function, callType, callData, exec->globalThisValue(), l).toNumber(exec);
471 compareResult = (jObj.toString(exec) < minObj.toString(exec)) ? -1 : 1;
473 if (compareResult < 0) {
480 thisObj->put(exec, i, minObj);
481 thisObj->put(exec, themin, iObj);
487 JSValuePtr arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
489 JSObject* thisObj = thisValue.toThisObject(exec);
492 JSArray* resObj = constructEmptyArray(exec);
493 JSValuePtr result = resObj;
494 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
496 return jsUndefined();
497 int begin = args.at(exec, 0).toUInt32(exec);
499 begin = std::max<int>(begin + length, 0);
501 begin = std::min<int>(begin, length);
503 unsigned deleteCount;
505 deleteCount = std::min<int>(std::max<int>(args.at(exec, 1).toUInt32(exec), 0), length - begin);
507 deleteCount = length - begin;
509 for (unsigned k = 0; k < deleteCount; k++) {
510 if (JSValuePtr v = getProperty(exec, thisObj, k + begin))
511 resObj->put(exec, k, v);
513 resObj->setLength(deleteCount);
515 unsigned additionalArgs = std::max<int>(args.size() - 2, 0);
516 if (additionalArgs != deleteCount) {
517 if (additionalArgs < deleteCount) {
518 for (unsigned k = begin; k < length - deleteCount; ++k) {
519 if (JSValuePtr v = getProperty(exec, thisObj, k + deleteCount))
520 thisObj->put(exec, k + additionalArgs, v);
522 thisObj->deleteProperty(exec, k + additionalArgs);
524 for (unsigned k = length; k > length - deleteCount + additionalArgs; --k)
525 thisObj->deleteProperty(exec, k - 1);
527 for (unsigned k = length - deleteCount; (int)k > begin; --k) {
528 if (JSValuePtr obj = getProperty(exec, thisObj, k + deleteCount - 1))
529 thisObj->put(exec, k + additionalArgs - 1, obj);
531 thisObj->deleteProperty(exec, k + additionalArgs - 1);
535 for (unsigned k = 0; k < additionalArgs; ++k)
536 thisObj->put(exec, k + begin, args.at(exec, k + 2));
538 putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - deleteCount + additionalArgs));
542 JSValuePtr arrayProtoFuncUnShift(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
544 JSObject* thisObj = thisValue.toThisObject(exec);
547 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
548 unsigned nrArgs = args.size();
550 for (unsigned k = length; k > 0; --k) {
551 if (JSValuePtr v = getProperty(exec, thisObj, k - 1))
552 thisObj->put(exec, k + nrArgs - 1, v);
554 thisObj->deleteProperty(exec, k + nrArgs - 1);
557 for (unsigned k = 0; k < nrArgs; ++k)
558 thisObj->put(exec, k, args.at(exec, k));
559 JSValuePtr result = jsNumber(exec, length + nrArgs);
560 putProperty(exec, thisObj, exec->propertyNames().length, result);
564 JSValuePtr arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
566 JSObject* thisObj = thisValue.toThisObject(exec);
568 JSValuePtr function = args.at(exec, 0);
570 CallType callType = function.getCallData(callData);
571 if (callType == CallTypeNone)
572 return throwError(exec, TypeError);
574 JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec);
575 JSArray* resultArray = constructEmptyArray(exec);
577 unsigned filterIndex = 0;
578 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
579 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
580 PropertySlot slot(thisObj);
582 if (!thisObj->getPropertySlot(exec, k, slot))
585 JSValuePtr v = slot.getValue(exec, k);
587 ArgList eachArguments;
589 eachArguments.append(v);
590 eachArguments.append(jsNumber(exec, k));
591 eachArguments.append(thisObj);
593 JSValuePtr result = call(exec, function, callType, callData, applyThis, eachArguments);
595 if (result.toBoolean(exec))
596 resultArray->put(exec, filterIndex++, v);
601 JSValuePtr arrayProtoFuncMap(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
603 JSObject* thisObj = thisValue.toThisObject(exec);
605 JSValuePtr function = args.at(exec, 0);
607 CallType callType = function.getCallData(callData);
608 if (callType == CallTypeNone)
609 return throwError(exec, TypeError);
611 JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec);
613 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
615 JSArray* resultArray = constructEmptyArray(exec, length);
617 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
618 PropertySlot slot(thisObj);
619 if (!thisObj->getPropertySlot(exec, k, slot))
622 JSValuePtr v = slot.getValue(exec, k);
624 ArgList eachArguments;
626 eachArguments.append(v);
627 eachArguments.append(jsNumber(exec, k));
628 eachArguments.append(thisObj);
630 JSValuePtr result = call(exec, function, callType, callData, applyThis, eachArguments);
631 resultArray->put(exec, k, result);
637 // Documentation for these three is available at:
638 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every
639 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
640 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some
642 JSValuePtr arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
644 JSObject* thisObj = thisValue.toThisObject(exec);
646 JSValuePtr function = args.at(exec, 0);
648 CallType callType = function.getCallData(callData);
649 if (callType == CallTypeNone)
650 return throwError(exec, TypeError);
652 JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec);
654 JSValuePtr result = jsBoolean(true);
656 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
657 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
658 PropertySlot slot(thisObj);
660 if (!thisObj->getPropertySlot(exec, k, slot))
663 ArgList eachArguments;
665 eachArguments.append(slot.getValue(exec, k));
666 eachArguments.append(jsNumber(exec, k));
667 eachArguments.append(thisObj);
669 bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec);
671 if (!predicateResult) {
672 result = jsBoolean(false);
680 JSValuePtr arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
682 JSObject* thisObj = thisValue.toThisObject(exec);
684 JSValuePtr function = args.at(exec, 0);
686 CallType callType = function.getCallData(callData);
687 if (callType == CallTypeNone)
688 return throwError(exec, TypeError);
690 JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec);
692 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
693 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
694 PropertySlot slot(thisObj);
695 if (!thisObj->getPropertySlot(exec, k, slot))
698 ArgList eachArguments;
699 eachArguments.append(slot.getValue(exec, k));
700 eachArguments.append(jsNumber(exec, k));
701 eachArguments.append(thisObj);
703 call(exec, function, callType, callData, applyThis, eachArguments);
705 return jsUndefined();
708 JSValuePtr arrayProtoFuncSome(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
710 JSObject* thisObj = thisValue.toThisObject(exec);
712 JSValuePtr function = args.at(exec, 0);
714 CallType callType = function.getCallData(callData);
715 if (callType == CallTypeNone)
716 return throwError(exec, TypeError);
718 JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec);
720 JSValuePtr result = jsBoolean(false);
722 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
723 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
724 PropertySlot slot(thisObj);
725 if (!thisObj->getPropertySlot(exec, k, slot))
728 ArgList eachArguments;
729 eachArguments.append(slot.getValue(exec, k));
730 eachArguments.append(jsNumber(exec, k));
731 eachArguments.append(thisObj);
733 bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec);
735 if (predicateResult) {
736 result = jsBoolean(true);
743 JSValuePtr arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
745 // JavaScript 1.5 Extension by Mozilla
746 // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf
748 JSObject* thisObj = thisValue.toThisObject(exec);
751 double d = args.at(exec, 1).toInteger(exec);
752 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
759 index = static_cast<unsigned>(d);
762 JSValuePtr searchElement = args.at(exec, 0);
763 for (; index < length; ++index) {
764 JSValuePtr e = getProperty(exec, thisObj, index);
767 if (JSValuePtr::strictEqual(searchElement, e))
768 return jsNumber(exec, index);
771 return jsNumber(exec, -1);
774 JSValuePtr arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
776 // JavaScript 1.6 Extension by Mozilla
777 // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf
779 JSObject* thisObj = thisValue.toThisObject(exec);
781 unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
782 int index = length - 1;
783 double d = args.at(exec, 1).toIntegerPreserveNaN(exec);
788 return jsNumber(exec, -1);
791 index = static_cast<int>(d);
793 JSValuePtr searchElement = args.at(exec, 0);
794 for (; index >= 0; --index) {
795 JSValuePtr e = getProperty(exec, thisObj, index);
798 if (JSValuePtr::strictEqual(searchElement, e))
799 return jsNumber(exec, index);
802 return jsNumber(exec, -1);