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"
28 #include "ObjectPrototype.h"
30 #include "operations.h"
32 #include <wtf/Assertions.h>
33 #include <wtf/HashSet.h>
37 ASSERT_CLASS_FITS_IN_CELL(ArrayPrototype);
39 static JSValue* arrayProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);
40 static JSValue* arrayProtoFuncToLocaleString(ExecState*, JSObject*, JSValue*, const ArgList&);
41 static JSValue* arrayProtoFuncConcat(ExecState*, JSObject*, JSValue*, const ArgList&);
42 static JSValue* arrayProtoFuncJoin(ExecState*, JSObject*, JSValue*, const ArgList&);
43 static JSValue* arrayProtoFuncPop(ExecState*, JSObject*, JSValue*, const ArgList&);
44 static JSValue* arrayProtoFuncPush(ExecState*, JSObject*, JSValue*, const ArgList&);
45 static JSValue* arrayProtoFuncReverse(ExecState*, JSObject*, JSValue*, const ArgList&);
46 static JSValue* arrayProtoFuncShift(ExecState*, JSObject*, JSValue*, const ArgList&);
47 static JSValue* arrayProtoFuncSlice(ExecState*, JSObject*, JSValue*, const ArgList&);
48 static JSValue* arrayProtoFuncSort(ExecState*, JSObject*, JSValue*, const ArgList&);
49 static JSValue* arrayProtoFuncSplice(ExecState*, JSObject*, JSValue*, const ArgList&);
50 static JSValue* arrayProtoFuncUnShift(ExecState*, JSObject*, JSValue*, const ArgList&);
51 static JSValue* arrayProtoFuncEvery(ExecState*, JSObject*, JSValue*, const ArgList&);
52 static JSValue* arrayProtoFuncForEach(ExecState*, JSObject*, JSValue*, const ArgList&);
53 static JSValue* arrayProtoFuncSome(ExecState*, JSObject*, JSValue*, const ArgList&);
54 static JSValue* arrayProtoFuncIndexOf(ExecState*, JSObject*, JSValue*, const ArgList&);
55 static JSValue* arrayProtoFuncFilter(ExecState*, JSObject*, JSValue*, const ArgList&);
56 static JSValue* arrayProtoFuncMap(ExecState*, JSObject*, JSValue*, const ArgList&);
57 static JSValue* arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JSValue*, const ArgList&);
61 #include "ArrayPrototype.lut.h"
65 // ------------------------------ ArrayPrototype ----------------------------
67 const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::arrayTable};
69 /* Source for ArrayPrototype.lut.h
71 toString arrayProtoFuncToString DontEnum|Function 0
72 toLocaleString arrayProtoFuncToLocaleString DontEnum|Function 0
73 concat arrayProtoFuncConcat DontEnum|Function 1
74 join arrayProtoFuncJoin DontEnum|Function 1
75 pop arrayProtoFuncPop DontEnum|Function 0
76 push arrayProtoFuncPush DontEnum|Function 1
77 reverse arrayProtoFuncReverse DontEnum|Function 0
78 shift arrayProtoFuncShift DontEnum|Function 0
79 slice arrayProtoFuncSlice DontEnum|Function 2
80 sort arrayProtoFuncSort DontEnum|Function 1
81 splice arrayProtoFuncSplice DontEnum|Function 2
82 unshift arrayProtoFuncUnShift DontEnum|Function 1
83 every arrayProtoFuncEvery DontEnum|Function 1
84 forEach arrayProtoFuncForEach DontEnum|Function 1
85 some arrayProtoFuncSome DontEnum|Function 1
86 indexOf arrayProtoFuncIndexOf DontEnum|Function 1
87 lastIndexOf arrayProtoFuncLastIndexOf DontEnum|Function 1
88 filter arrayProtoFuncFilter DontEnum|Function 1
89 map arrayProtoFuncMap DontEnum|Function 1
94 ArrayPrototype::ArrayPrototype(PassRefPtr<StructureID> structure)
99 bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
101 return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, slot);
104 // ------------------------------ Array Functions ----------------------------
107 static JSValue* getProperty(ExecState* exec, JSObject* obj, unsigned index)
109 PropertySlot slot(obj);
110 if (!obj->getPropertySlot(exec, index, slot))
112 return slot.getValue(exec, index);
115 static void putProperty(ExecState* exec, JSObject* obj, const Identifier& propertyName, JSValue* value)
117 PutPropertySlot slot;
118 obj->put(exec, propertyName, value, slot);
121 JSValue* arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
123 if (!thisValue->isObject(&JSArray::info))
124 return throwError(exec, TypeError);
125 JSObject* thisObj = asArray(thisValue);
127 HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
128 if (arrayVisitedElements.size() > MaxReentryDepth)
129 return throwError(exec, RangeError, "Maximum call stack size exceeded.");
131 bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
133 return jsEmptyString(exec); // return an empty string, avoiding infinite recursion.
135 Vector<UChar, 256> strBuffer;
136 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
137 for (unsigned k = 0; k < length; k++) {
139 strBuffer.append(',');
140 if (!strBuffer.data()) {
141 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
142 exec->setException(error);
146 JSValue* element = thisObj->get(exec, k);
147 if (element->isUndefinedOrNull())
150 UString str = element->toString(exec);
151 strBuffer.append(str.data(), str.size());
153 if (!strBuffer.data()) {
154 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
155 exec->setException(error);
158 if (exec->hadException())
161 arrayVisitedElements.remove(thisObj);
162 return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
165 JSValue* arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
167 if (!thisValue->isObject(&JSArray::info))
168 return throwError(exec, TypeError);
169 JSObject* thisObj = asArray(thisValue);
171 HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
172 if (arrayVisitedElements.size() > MaxReentryDepth)
173 return throwError(exec, RangeError, "Maximum call stack size exceeded.");
175 bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
177 return jsEmptyString(exec); // return an empty string, avoding infinite recursion.
179 Vector<UChar, 256> strBuffer;
180 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
181 for (unsigned k = 0; k < length; k++) {
183 strBuffer.append(',');
184 if (!strBuffer.data()) {
185 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
186 exec->setException(error);
190 JSValue* element = thisObj->get(exec, k);
191 if (element->isUndefinedOrNull())
194 JSObject* o = element->toObject(exec);
195 JSValue* conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
198 CallType callType = conversionFunction->getCallData(callData);
199 if (callType != CallTypeNone)
200 str = call(exec, conversionFunction, callType, callData, element, exec->emptyList())->toString(exec);
202 str = element->toString(exec);
203 strBuffer.append(str.data(), str.size());
205 if (!strBuffer.data()) {
206 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
207 exec->setException(error);
210 if (exec->hadException())
213 arrayVisitedElements.remove(thisObj);
214 return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
217 JSValue* arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
219 JSObject* thisObj = thisValue->toThisObject(exec);
221 HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
222 if (arrayVisitedElements.size() > MaxReentryDepth)
223 return throwError(exec, RangeError, "Maximum call stack size exceeded.");
225 bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
227 return jsEmptyString(exec); // return an empty string, avoding infinite recursion.
229 Vector<UChar, 256> strBuffer;
232 UString separator = args.at(exec, 0)->isUndefined() ? UString(&comma, 1) : args.at(exec, 0)->toString(exec);
234 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
235 for (unsigned k = 0; k < length; k++) {
237 strBuffer.append(separator.data(), separator.size());
238 if (!strBuffer.data()) {
239 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
240 exec->setException(error);
244 JSValue* element = thisObj->get(exec, k);
245 if (element->isUndefinedOrNull())
248 UString str = element->toString(exec);
249 strBuffer.append(str.data(), str.size());
251 if (!strBuffer.data()) {
252 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
253 exec->setException(error);
256 if (exec->hadException())
259 arrayVisitedElements.remove(thisObj);
260 return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
263 JSValue* arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
265 JSArray* arr = constructEmptyArray(exec);
267 JSValue* curArg = thisValue->toThisObject(exec);
268 ArgList::const_iterator it = args.begin();
269 ArgList::const_iterator end = args.end();
271 if (curArg->isObject(&JSArray::info)) {
272 JSArray* curArray = asArray(curArg);
273 unsigned length = curArray->length();
274 for (unsigned k = 0; k < length; ++k) {
275 if (JSValue* v = getProperty(exec, curArray, k))
276 arr->put(exec, n, v);
280 arr->put(exec, n, curArg);
285 curArg = (*it).jsValue(exec);
292 JSValue* arrayProtoFuncPop(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
294 if (exec->machine()->isJSArray(thisValue))
295 return asArray(thisValue)->pop();
297 JSObject* thisObj = thisValue->toThisObject(exec);
299 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
301 putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
302 result = jsUndefined();
304 result = thisObj->get(exec, length - 1);
305 thisObj->deleteProperty(exec, length - 1);
306 putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - 1));
311 JSValue* arrayProtoFuncPush(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
313 if (exec->machine()->isJSArray(thisValue) && args.size() == 1) {
314 JSArray* array = asArray(thisValue);
315 array->push(exec, args.begin()->jsValue(exec));
316 return jsNumber(exec, array->length());
319 JSObject* thisObj = thisValue->toThisObject(exec);
320 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
321 for (unsigned n = 0; n < args.size(); n++)
322 thisObj->put(exec, length + n, args.at(exec, n));
323 length += args.size();
324 putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
325 return jsNumber(exec, length);
328 JSValue* arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
330 JSObject* thisObj = thisValue->toThisObject(exec);
331 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
332 unsigned middle = length / 2;
334 for (unsigned k = 0; k < middle; k++) {
335 unsigned lk1 = length - k - 1;
336 JSValue* obj2 = getProperty(exec, thisObj, lk1);
337 JSValue* obj = getProperty(exec, thisObj, k);
340 thisObj->put(exec, k, obj2);
342 thisObj->deleteProperty(exec, k);
345 thisObj->put(exec, lk1, obj);
347 thisObj->deleteProperty(exec, lk1);
352 JSValue* arrayProtoFuncShift(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
354 JSObject* thisObj = thisValue->toThisObject(exec);
357 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
359 putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
360 result = jsUndefined();
362 result = thisObj->get(exec, 0);
363 for (unsigned k = 1; k < length; k++) {
364 if (JSValue* obj = getProperty(exec, thisObj, k))
365 thisObj->put(exec, k - 1, obj);
367 thisObj->deleteProperty(exec, k - 1);
369 thisObj->deleteProperty(exec, length - 1);
370 putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - 1));
375 JSValue* arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
377 // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
379 JSObject* thisObj = thisValue->toThisObject(exec);
381 // We return a new array
382 JSArray* resObj = constructEmptyArray(exec);
383 JSValue* result = resObj;
384 double begin = args.at(exec, 0)->toInteger(exec);
385 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
395 if (args.at(exec, 1)->isUndefined())
398 end = args.at(exec, 1)->toInteger(exec);
410 int b = static_cast<int>(begin);
411 int e = static_cast<int>(end);
412 for (int k = b; k < e; k++, n++) {
413 if (JSValue* v = getProperty(exec, thisObj, k))
414 resObj->put(exec, n, v);
416 resObj->setLength(n);
420 JSValue* arrayProtoFuncSort(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
422 JSObject* thisObj = thisValue->toThisObject(exec);
424 JSValue* function = args.at(exec, 0);
426 CallType callType = function->getCallData(callData);
428 if (thisObj->classInfo() == &JSArray::info) {
429 if (callType != CallTypeNone)
430 asArray(thisObj)->sort(exec, function, callType, callData);
432 asArray(thisObj)->sort(exec);
436 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
441 // "Min" sort. Not the fastest, but definitely less code than heapsort
442 // or quicksort, and much less swapping than bubblesort/insertionsort.
443 for (unsigned i = 0; i < length - 1; ++i) {
444 JSValue* iObj = thisObj->get(exec, i);
446 JSValue* minObj = iObj;
447 for (unsigned j = i + 1; j < length; ++j) {
448 JSValue* jObj = thisObj->get(exec, j);
449 double compareResult;
450 if (jObj->isUndefined())
451 compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1)
452 else if (minObj->isUndefined())
454 else if (callType != CallTypeNone) {
458 compareResult = call(exec, function, callType, callData, exec->globalThisValue(), l)->toNumber(exec);
460 compareResult = (jObj->toString(exec) < minObj->toString(exec)) ? -1 : 1;
462 if (compareResult < 0) {
469 thisObj->put(exec, i, minObj);
470 thisObj->put(exec, themin, iObj);
476 JSValue* arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
478 JSObject* thisObj = thisValue->toThisObject(exec);
481 JSArray* resObj = constructEmptyArray(exec);
482 JSValue* result = resObj;
483 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
485 return jsUndefined();
486 int begin = args.at(exec, 0)->toUInt32(exec);
488 begin = std::max<int>(begin + length, 0);
490 begin = std::min<int>(begin, length);
492 unsigned deleteCount;
494 deleteCount = std::min<int>(std::max<int>(args.at(exec, 1)->toUInt32(exec), 0), length - begin);
496 deleteCount = length - begin;
498 for (unsigned k = 0; k < deleteCount; k++) {
499 if (JSValue* v = getProperty(exec, thisObj, k + begin))
500 resObj->put(exec, k, v);
502 resObj->setLength(deleteCount);
504 unsigned additionalArgs = std::max<int>(args.size() - 2, 0);
505 if (additionalArgs != deleteCount) {
506 if (additionalArgs < deleteCount) {
507 for (unsigned k = begin; k < length - deleteCount; ++k) {
508 if (JSValue* v = getProperty(exec, thisObj, k + deleteCount))
509 thisObj->put(exec, k + additionalArgs, v);
511 thisObj->deleteProperty(exec, k + additionalArgs);
513 for (unsigned k = length; k > length - deleteCount + additionalArgs; --k)
514 thisObj->deleteProperty(exec, k - 1);
516 for (unsigned k = length - deleteCount; (int)k > begin; --k) {
517 if (JSValue* obj = getProperty(exec, thisObj, k + deleteCount - 1))
518 thisObj->put(exec, k + additionalArgs - 1, obj);
520 thisObj->deleteProperty(exec, k + additionalArgs - 1);
524 for (unsigned k = 0; k < additionalArgs; ++k)
525 thisObj->put(exec, k + begin, args.at(exec, k + 2));
527 putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - deleteCount + additionalArgs));
531 JSValue* arrayProtoFuncUnShift(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
533 JSObject* thisObj = thisValue->toThisObject(exec);
536 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
537 unsigned nrArgs = args.size();
539 for (unsigned k = length; k > 0; --k) {
540 if (JSValue* v = getProperty(exec, thisObj, k - 1))
541 thisObj->put(exec, k + nrArgs - 1, v);
543 thisObj->deleteProperty(exec, k + nrArgs - 1);
546 for (unsigned k = 0; k < nrArgs; ++k)
547 thisObj->put(exec, k, args.at(exec, k));
548 JSValue* result = jsNumber(exec, length + nrArgs);
549 putProperty(exec, thisObj, exec->propertyNames().length, result);
553 JSValue* arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
555 JSObject* thisObj = thisValue->toThisObject(exec);
557 JSValue* function = args.at(exec, 0);
559 CallType callType = function->getCallData(callData);
560 if (callType == CallTypeNone)
561 return throwError(exec, TypeError);
563 JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec);
564 JSArray* resultArray = constructEmptyArray(exec);
566 unsigned filterIndex = 0;
567 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
568 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
569 PropertySlot slot(thisObj);
571 if (!thisObj->getPropertySlot(exec, k, slot))
574 JSValue* v = slot.getValue(exec, k);
576 ArgList eachArguments;
578 eachArguments.append(v);
579 eachArguments.append(jsNumber(exec, k));
580 eachArguments.append(thisObj);
582 JSValue* result = call(exec, function, callType, callData, applyThis, eachArguments);
584 if (result->toBoolean(exec))
585 resultArray->put(exec, filterIndex++, v);
590 JSValue* arrayProtoFuncMap(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
592 JSObject* thisObj = thisValue->toThisObject(exec);
594 JSValue* function = args.at(exec, 0);
596 CallType callType = function->getCallData(callData);
597 if (callType == CallTypeNone)
598 return throwError(exec, TypeError);
600 JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec);
602 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
604 JSArray* resultArray = constructEmptyArray(exec, length);
606 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
607 PropertySlot slot(thisObj);
608 if (!thisObj->getPropertySlot(exec, k, slot))
611 JSValue* v = slot.getValue(exec, k);
613 ArgList eachArguments;
615 eachArguments.append(v);
616 eachArguments.append(jsNumber(exec, k));
617 eachArguments.append(thisObj);
619 JSValue* result = call(exec, function, callType, callData, applyThis, eachArguments);
620 resultArray->put(exec, k, result);
626 // Documentation for these three is available at:
627 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every
628 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
629 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some
631 JSValue* arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
633 JSObject* thisObj = thisValue->toThisObject(exec);
635 JSValue* function = args.at(exec, 0);
637 CallType callType = function->getCallData(callData);
638 if (callType == CallTypeNone)
639 return throwError(exec, TypeError);
641 JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec);
643 JSValue* result = jsBoolean(true);
645 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
646 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
647 PropertySlot slot(thisObj);
649 if (!thisObj->getPropertySlot(exec, k, slot))
652 ArgList eachArguments;
654 eachArguments.append(slot.getValue(exec, k));
655 eachArguments.append(jsNumber(exec, k));
656 eachArguments.append(thisObj);
658 bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments)->toBoolean(exec);
660 if (!predicateResult) {
661 result = jsBoolean(false);
669 JSValue* arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
671 JSObject* thisObj = thisValue->toThisObject(exec);
673 JSValue* function = args.at(exec, 0);
675 CallType callType = function->getCallData(callData);
676 if (callType == CallTypeNone)
677 return throwError(exec, TypeError);
679 JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec);
681 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
682 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
683 PropertySlot slot(thisObj);
684 if (!thisObj->getPropertySlot(exec, k, slot))
687 ArgList eachArguments;
688 eachArguments.append(slot.getValue(exec, k));
689 eachArguments.append(jsNumber(exec, k));
690 eachArguments.append(thisObj);
692 call(exec, function, callType, callData, applyThis, eachArguments);
694 return jsUndefined();
697 JSValue* arrayProtoFuncSome(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
699 JSObject* thisObj = thisValue->toThisObject(exec);
701 JSValue* function = args.at(exec, 0);
703 CallType callType = function->getCallData(callData);
704 if (callType == CallTypeNone)
705 return throwError(exec, TypeError);
707 JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec);
709 JSValue* result = jsBoolean(false);
711 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
712 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
713 PropertySlot slot(thisObj);
714 if (!thisObj->getPropertySlot(exec, k, slot))
717 ArgList eachArguments;
718 eachArguments.append(slot.getValue(exec, k));
719 eachArguments.append(jsNumber(exec, k));
720 eachArguments.append(thisObj);
722 bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments)->toBoolean(exec);
724 if (predicateResult) {
725 result = jsBoolean(true);
732 JSValue* arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
734 // JavaScript 1.5 Extension by Mozilla
735 // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf
737 JSObject* thisObj = thisValue->toThisObject(exec);
740 double d = args.at(exec, 1)->toInteger(exec);
741 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
748 index = static_cast<unsigned>(d);
751 JSValue* searchElement = args.at(exec, 0);
752 for (; index < length; ++index) {
753 JSValue* e = getProperty(exec, thisObj, index);
756 if (strictEqual(searchElement, e))
757 return jsNumber(exec, index);
760 return jsNumber(exec, -1);
763 JSValue* arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
765 // JavaScript 1.6 Extension by Mozilla
766 // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf
768 JSObject* thisObj = thisValue->toThisObject(exec);
770 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
771 int index = length - 1;
772 double d = args.at(exec, 1)->toIntegerPreserveNaN(exec);
777 return jsNumber(exec, -1);
780 index = static_cast<int>(d);
782 JSValue* searchElement = args.at(exec, 0);
783 for (; index >= 0; --index) {
784 JSValue* e = getProperty(exec, thisObj, index);
787 if (strictEqual(searchElement, e))
788 return jsNumber(exec, index);
791 return jsNumber(exec, -1);