Changeset 34843 in webkit for trunk/JavaScriptCore/kjs/ArrayConstructor.cpp
- Timestamp:
- Jun 27, 2008, 9:29:48 PM (17 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/ArrayConstructor.cpp
r34842 r34843 23 23 24 24 #include "config.h" 25 #include "ArrayConstructor.h" 26 25 27 #include "ArrayPrototype.h" 26 27 #include "Machine.h" 28 #include "JSArray.h" 28 29 #include "error_object.h" 29 30 #include "lookup.h" 30 #include "operations.h"31 #include <stdio.h>32 #include <wtf/Assertions.h>33 #include <wtf/HashSet.h>34 35 #include <algorithm> // for std::min36 31 37 32 namespace KJS { 38 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&);58 59 }60 61 #include "ArrayPrototype.lut.h"62 63 namespace KJS {64 65 // ------------------------------ ArrayPrototype ----------------------------66 67 const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::arrayTable};68 69 /* Source for ArrayPrototype.lut.h70 @begin arrayTable 1671 toString arrayProtoFuncToString DontEnum|Function 072 toLocaleString arrayProtoFuncToLocaleString DontEnum|Function 073 concat arrayProtoFuncConcat DontEnum|Function 174 join arrayProtoFuncJoin DontEnum|Function 175 pop arrayProtoFuncPop DontEnum|Function 076 push arrayProtoFuncPush DontEnum|Function 177 reverse arrayProtoFuncReverse DontEnum|Function 078 shift arrayProtoFuncShift DontEnum|Function 079 slice arrayProtoFuncSlice DontEnum|Function 280 sort arrayProtoFuncSort DontEnum|Function 181 splice arrayProtoFuncSplice DontEnum|Function 282 unshift arrayProtoFuncUnShift DontEnum|Function 183 every arrayProtoFuncEvery DontEnum|Function 184 forEach arrayProtoFuncForEach DontEnum|Function 185 some arrayProtoFuncSome DontEnum|Function 186 indexOf arrayProtoFuncIndexOf DontEnum|Function 187 lastIndexOf arrayProtoFuncLastIndexOf DontEnum|Function 188 filter arrayProtoFuncFilter DontEnum|Function 189 map arrayProtoFuncMap DontEnum|Function 190 @end91 */92 93 // ECMA 15.4.494 ArrayPrototype::ArrayPrototype(ExecState*, ObjectPrototype* objProto)95 : JSArray(objProto, 0)96 {97 }98 99 bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)100 {101 return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, slot);102 }103 104 105 // ------------------------------ Array Functions ----------------------------106 107 // Helper function108 static JSValue* getProperty(ExecState* exec, JSObject* obj, unsigned index)109 {110 PropertySlot slot(obj);111 if (!obj->getPropertySlot(exec, index, slot))112 return 0;113 return slot.getValue(exec, index);114 }115 116 JSValue* arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)117 {118 if (!thisValue->isObject(&JSArray::info))119 return throwError(exec, TypeError);120 JSObject* thisObj = static_cast<JSArray*>(thisValue);121 122 HashSet<JSObject*>& arrayVisitedElements = exec->dynamicGlobalObject()->arrayVisitedElements();123 if (arrayVisitedElements.size() > MaxReentryDepth)124 return throwError(exec, RangeError, "Maximum call stack size exceeded.");125 126 bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;127 Vector<UChar, 256> strBuffer;128 if (alreadyVisited)129 return jsString(exec, UString(0, 0)); // return an empty string, avoding infinite recursion.130 131 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);132 for (unsigned k = 0; k < length; k++) {133 if (k >= 1)134 strBuffer.append(',');135 if (!strBuffer.data()) {136 JSObject* error = Error::create(exec, GeneralError, "Out of memory");137 exec->setException(error);138 break;139 }140 141 JSValue* element = thisObj->get(exec, k);142 if (element->isUndefinedOrNull())143 continue;144 145 UString str = element->toString(exec);146 strBuffer.append(str.data(), str.size());147 148 if (!strBuffer.data()) {149 JSObject* error = Error::create(exec, GeneralError, "Out of memory");150 exec->setException(error);151 }152 153 if (exec->hadException())154 break;155 }156 exec->dynamicGlobalObject()->arrayVisitedElements().remove(thisObj);157 return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));158 }159 160 JSValue* arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)161 {162 if (!thisValue->isObject(&JSArray::info))163 return throwError(exec, TypeError);164 JSObject* thisObj = static_cast<JSArray*>(thisValue);165 166 HashSet<JSObject*>& arrayVisitedElements = exec->dynamicGlobalObject()->arrayVisitedElements();167 if (arrayVisitedElements.size() > MaxReentryDepth)168 return throwError(exec, RangeError, "Maximum call stack size exceeded.");169 170 bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;171 Vector<UChar, 256> strBuffer;172 if (alreadyVisited)173 return jsString(exec, UString(0, 0)); // return an empty string, avoding infinite recursion.174 175 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);176 for (unsigned k = 0; k < length; k++) {177 if (k >= 1)178 strBuffer.append(',');179 if (!strBuffer.data()) {180 JSObject* error = Error::create(exec, GeneralError, "Out of memory");181 exec->setException(error);182 break;183 }184 185 JSValue* element = thisObj->get(exec, k);186 if (element->isUndefinedOrNull())187 continue;188 189 JSObject* o = element->toObject(exec);190 JSValue* conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);191 UString str;192 CallData callData;193 CallType callType = conversionFunction->getCallData(callData);194 if (callType != CallTypeNone)195 str = call(exec, conversionFunction, callType, callData, element, exec->emptyList())->toString(exec);196 else197 str = element->toString(exec);198 strBuffer.append(str.data(), str.size());199 200 if (!strBuffer.data()) {201 JSObject* error = Error::create(exec, GeneralError, "Out of memory");202 exec->setException(error);203 }204 205 if (exec->hadException())206 break;207 }208 exec->dynamicGlobalObject()->arrayVisitedElements().remove(thisObj);209 return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));210 }211 212 JSValue* arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)213 {214 JSObject* thisObj = thisValue->toThisObject(exec);215 216 HashSet<JSObject*>& arrayVisitedElements = exec->dynamicGlobalObject()->arrayVisitedElements();217 if (arrayVisitedElements.size() > MaxReentryDepth)218 return throwError(exec, RangeError, "Maximum call stack size exceeded.");219 220 bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;221 Vector<UChar, 256> strBuffer;222 if (alreadyVisited)223 return jsString(exec, UString(0, 0)); // return an empty string, avoding infinite recursion.224 225 UChar comma = ',';226 UString separator = args[0]->isUndefined() ? UString(&comma, 1) : args[0]->toString(exec);227 228 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);229 for (unsigned k = 0; k < length; k++) {230 if (k >= 1)231 strBuffer.append(separator.data(), separator.size());232 if (!strBuffer.data()) {233 JSObject* error = Error::create(exec, GeneralError, "Out of memory");234 exec->setException(error);235 break;236 }237 238 JSValue* element = thisObj->get(exec, k);239 if (element->isUndefinedOrNull())240 continue;241 242 UString str = element->toString(exec);243 strBuffer.append(str.data(), str.size());244 245 if (!strBuffer.data()) {246 JSObject* error = Error::create(exec, GeneralError, "Out of memory");247 exec->setException(error);248 }249 250 if (exec->hadException())251 break;252 }253 exec->dynamicGlobalObject()->arrayVisitedElements().remove(thisObj);254 return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));255 }256 257 JSValue* arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)258 {259 JSArray* arr = constructEmptyArray(exec);260 int n = 0;261 JSValue* curArg = thisValue->toThisObject(exec);262 ArgList::const_iterator it = args.begin();263 ArgList::const_iterator end = args.end();264 while (1) {265 if (curArg->isObject(&JSArray::info)) {266 JSArray* curArray = static_cast<JSArray*>(curArg);267 unsigned length = curArray->getLength();268 for (unsigned k = 0; k < length; ++k) {269 if (JSValue* v = curArray->getItem(k))270 arr->put(exec, n, v);271 n++;272 }273 } else {274 arr->put(exec, n, curArg);275 n++;276 }277 if (it == end)278 break;279 curArg = *it;280 ++it;281 }282 arr->setLength(n);283 return arr;284 }285 286 JSValue* arrayProtoFuncPop(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)287 {288 JSObject* thisObj = thisValue->toThisObject(exec);289 JSValue* result = 0;290 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);291 if (length == 0) {292 thisObj->put(exec, exec->propertyNames().length, jsNumber(exec, length));293 result = jsUndefined();294 } else {295 result = thisObj->get(exec, length - 1);296 thisObj->deleteProperty(exec, length - 1);297 thisObj->put(exec, exec->propertyNames().length, jsNumber(exec, length - 1));298 }299 return result;300 }301 302 JSValue* arrayProtoFuncPush(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)303 {304 JSObject* thisObj = thisValue->toThisObject(exec);305 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);306 for (unsigned n = 0; n < args.size(); n++)307 thisObj->put(exec, length + n, args[n]);308 length += args.size();309 thisObj->put(exec, exec->propertyNames().length, jsNumber(exec, length));310 return jsNumber(exec, length);311 }312 313 JSValue* arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)314 {315 JSObject* thisObj = thisValue->toThisObject(exec);316 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);317 unsigned middle = length / 2;318 319 for (unsigned k = 0; k < middle; k++) {320 unsigned lk1 = length - k - 1;321 JSValue* obj2 = getProperty(exec, thisObj, lk1);322 JSValue* obj = getProperty(exec, thisObj, k);323 324 if (obj2)325 thisObj->put(exec, k, obj2);326 else327 thisObj->deleteProperty(exec, k);328 329 if (obj)330 thisObj->put(exec, lk1, obj);331 else332 thisObj->deleteProperty(exec, lk1);333 }334 return thisObj;335 }336 337 JSValue* arrayProtoFuncShift(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)338 {339 JSObject* thisObj = thisValue->toThisObject(exec);340 JSValue* result = 0;341 342 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);343 if (length == 0) {344 thisObj->put(exec, exec->propertyNames().length, jsNumber(exec, length));345 result = jsUndefined();346 } else {347 result = thisObj->get(exec, 0);348 for (unsigned k = 1; k < length; k++) {349 if (JSValue* obj = getProperty(exec, thisObj, k))350 thisObj->put(exec, k - 1, obj);351 else352 thisObj->deleteProperty(exec, k - 1);353 }354 thisObj->deleteProperty(exec, length - 1);355 thisObj->put(exec, exec->propertyNames().length, jsNumber(exec, length - 1));356 }357 return result;358 }359 360 JSValue* arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)361 {362 // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10363 364 JSObject* thisObj = thisValue->toThisObject(exec);365 366 // We return a new array367 JSArray* resObj = constructEmptyArray(exec);368 JSValue* result = resObj;369 double begin = args[0]->toInteger(exec);370 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);371 if (begin >= 0) {372 if (begin > length)373 begin = length;374 } else {375 begin += length;376 if (begin < 0)377 begin = 0;378 }379 double end;380 if (args[1]->isUndefined())381 end = length;382 else {383 end = args[1]->toInteger(exec);384 if (end < 0) {385 end += length;386 if (end < 0)387 end = 0;388 } else {389 if (end > length)390 end = length;391 }392 }393 394 int n = 0;395 int b = static_cast<int>(begin);396 int e = static_cast<int>(end);397 for (int k = b; k < e; k++, n++) {398 if (JSValue* v = getProperty(exec, thisObj, k))399 resObj->put(exec, n, v);400 }401 resObj->setLength(n);402 return result;403 }404 405 JSValue* arrayProtoFuncSort(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)406 {407 JSObject* thisObj = thisValue->toThisObject(exec);408 409 JSValue* function = args[0];410 CallData callData;411 CallType callType = function->getCallData(callData);412 413 if (thisObj->classInfo() == &JSArray::info) {414 if (callType != CallTypeNone)415 static_cast<JSArray*>(thisObj)->sort(exec, function, callType, callData);416 else417 static_cast<JSArray*>(thisObj)->sort(exec);418 return thisObj;419 }420 421 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);422 423 if (!length)424 return thisObj;425 426 // "Min" sort. Not the fastest, but definitely less code than heapsort427 // or quicksort, and much less swapping than bubblesort/insertionsort.428 for (unsigned i = 0; i < length - 1; ++i) {429 JSValue* iObj = thisObj->get(exec, i);430 unsigned themin = i;431 JSValue* minObj = iObj;432 for (unsigned j = i + 1; j < length; ++j) {433 JSValue* jObj = thisObj->get(exec, j);434 double compareResult;435 if (jObj->isUndefined())436 compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1)437 else if (minObj->isUndefined())438 compareResult = -1;439 else if (callType != CallTypeNone) {440 ArgList l;441 l.append(jObj);442 l.append(minObj);443 compareResult = call(exec, function, callType, callData, exec->globalThisValue(), l)->toNumber(exec);444 } else445 compareResult = (jObj->toString(exec) < minObj->toString(exec)) ? -1 : 1;446 447 if (compareResult < 0) {448 themin = j;449 minObj = jObj;450 }451 }452 // Swap themin and i453 if (themin > i) {454 thisObj->put(exec, i, minObj);455 thisObj->put(exec, themin, iObj);456 }457 }458 return thisObj;459 }460 461 JSValue* arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)462 {463 JSObject* thisObj = thisValue->toThisObject(exec);464 465 // 15.4.4.12466 JSArray* resObj = constructEmptyArray(exec);467 JSValue* result = resObj;468 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);469 if (!args.size())470 return jsUndefined();471 int begin = args[0]->toUInt32(exec);472 if (begin < 0)473 begin = std::max<int>(begin + length, 0);474 else475 begin = std::min<int>(begin, length);476 477 unsigned deleteCount;478 if (args.size() > 1)479 deleteCount = std::min<int>(std::max<int>(args[1]->toUInt32(exec), 0), length - begin);480 else481 deleteCount = length - begin;482 483 for (unsigned k = 0; k < deleteCount; k++) {484 if (JSValue* v = getProperty(exec, thisObj, k + begin))485 resObj->put(exec, k, v);486 }487 resObj->setLength(deleteCount);488 489 unsigned additionalArgs = std::max<int>(args.size() - 2, 0);490 if (additionalArgs != deleteCount) {491 if (additionalArgs < deleteCount) {492 for (unsigned k = begin; k < length - deleteCount; ++k) {493 if (JSValue* v = getProperty(exec, thisObj, k + deleteCount))494 thisObj->put(exec, k + additionalArgs, v);495 else496 thisObj->deleteProperty(exec, k + additionalArgs);497 }498 for (unsigned k = length; k > length - deleteCount + additionalArgs; --k)499 thisObj->deleteProperty(exec, k - 1);500 } else {501 for (unsigned k = length - deleteCount; (int)k > begin; --k) {502 if (JSValue* obj = getProperty(exec, thisObj, k + deleteCount - 1))503 thisObj->put(exec, k + additionalArgs - 1, obj);504 else505 thisObj->deleteProperty(exec, k + additionalArgs - 1);506 }507 }508 }509 for (unsigned k = 0; k < additionalArgs; ++k)510 thisObj->put(exec, k + begin, args[k + 2]);511 512 thisObj->put(exec, exec->propertyNames().length, jsNumber(exec, length - deleteCount + additionalArgs));513 return result;514 }515 516 JSValue* arrayProtoFuncUnShift(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)517 {518 JSObject* thisObj = thisValue->toThisObject(exec);519 520 // 15.4.4.13521 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);522 unsigned nrArgs = args.size();523 if (nrArgs) {524 for (unsigned k = length; k > 0; --k) {525 if (JSValue* v = getProperty(exec, thisObj, k - 1))526 thisObj->put(exec, k + nrArgs - 1, v);527 else528 thisObj->deleteProperty(exec, k + nrArgs - 1);529 }530 }531 for (unsigned k = 0; k < nrArgs; ++k)532 thisObj->put(exec, k, args[k]);533 JSValue* result = jsNumber(exec, length + nrArgs);534 thisObj->put(exec, exec->propertyNames().length, result);535 return result;536 }537 538 JSValue* arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)539 {540 JSObject* thisObj = thisValue->toThisObject(exec);541 542 JSValue* function = args[0];543 CallData callData;544 CallType callType = function->getCallData(callData);545 if (callType == CallTypeNone)546 return throwError(exec, TypeError);547 548 JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->globalThisValue() : args[1]->toObject(exec);549 JSArray* resultArray = constructEmptyArray(exec);550 551 unsigned filterIndex = 0;552 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);553 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {554 PropertySlot slot(thisObj);555 556 if (!thisObj->getPropertySlot(exec, k, slot))557 continue;558 559 JSValue* v = slot.getValue(exec, k);560 561 ArgList eachArguments;562 563 eachArguments.append(v);564 eachArguments.append(jsNumber(exec, k));565 eachArguments.append(thisObj);566 567 JSValue* result = call(exec, function, callType, callData, applyThis, eachArguments);568 569 if (result->toBoolean(exec))570 resultArray->put(exec, filterIndex++, v);571 }572 return resultArray;573 }574 575 JSValue* arrayProtoFuncMap(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)576 {577 JSObject* thisObj = thisValue->toThisObject(exec);578 579 JSValue* function = args[0];580 CallData callData;581 CallType callType = function->getCallData(callData);582 if (callType == CallTypeNone)583 return throwError(exec, TypeError);584 585 JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->globalThisValue() : args[1]->toObject(exec);586 587 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);588 589 JSArray* resultArray = constructEmptyArray(exec, length);590 591 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {592 PropertySlot slot(thisObj);593 if (!thisObj->getPropertySlot(exec, k, slot))594 continue;595 596 JSValue* v = slot.getValue(exec, k);597 598 ArgList eachArguments;599 600 eachArguments.append(v);601 eachArguments.append(jsNumber(exec, k));602 eachArguments.append(thisObj);603 604 JSValue* result = call(exec, function, callType, callData, applyThis, eachArguments);605 resultArray->put(exec, k, result);606 }607 608 return resultArray;609 }610 611 // Documentation for these three is available at:612 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every613 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach614 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some615 616 JSValue* arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)617 {618 JSObject* thisObj = thisValue->toThisObject(exec);619 620 JSValue* function = args[0];621 CallData callData;622 CallType callType = function->getCallData(callData);623 if (callType == CallTypeNone)624 return throwError(exec, TypeError);625 626 JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->globalThisValue() : args[1]->toObject(exec);627 628 JSValue* result = jsBoolean(true);629 630 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);631 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {632 PropertySlot slot(thisObj);633 634 if (!thisObj->getPropertySlot(exec, k, slot))635 continue;636 637 ArgList eachArguments;638 639 eachArguments.append(slot.getValue(exec, k));640 eachArguments.append(jsNumber(exec, k));641 eachArguments.append(thisObj);642 643 bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments)->toBoolean(exec);644 645 if (!predicateResult) {646 result = jsBoolean(false);647 break;648 }649 }650 651 return result;652 }653 654 JSValue* arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)655 {656 JSObject* thisObj = thisValue->toThisObject(exec);657 658 JSValue* function = args[0];659 CallData callData;660 CallType callType = function->getCallData(callData);661 if (callType == CallTypeNone)662 return throwError(exec, TypeError);663 664 JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->globalThisValue() : args[1]->toObject(exec);665 666 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);667 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {668 PropertySlot slot(thisObj);669 if (!thisObj->getPropertySlot(exec, k, slot))670 continue;671 672 ArgList eachArguments;673 eachArguments.append(slot.getValue(exec, k));674 eachArguments.append(jsNumber(exec, k));675 eachArguments.append(thisObj);676 677 call(exec, function, callType, callData, applyThis, eachArguments);678 }679 return jsUndefined();680 }681 682 JSValue* arrayProtoFuncSome(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)683 {684 JSObject* thisObj = thisValue->toThisObject(exec);685 686 JSValue* function = args[0];687 CallData callData;688 CallType callType = function->getCallData(callData);689 if (callType == CallTypeNone)690 return throwError(exec, TypeError);691 692 JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->globalThisValue() : args[1]->toObject(exec);693 694 JSValue* result = jsBoolean(false);695 696 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);697 for (unsigned k = 0; k < length && !exec->hadException(); ++k) {698 PropertySlot slot(thisObj);699 if (!thisObj->getPropertySlot(exec, k, slot))700 continue;701 702 ArgList eachArguments;703 eachArguments.append(slot.getValue(exec, k));704 eachArguments.append(jsNumber(exec, k));705 eachArguments.append(thisObj);706 707 bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments)->toBoolean(exec);708 709 if (predicateResult) {710 result = jsBoolean(true);711 break;712 }713 }714 return result;715 }716 717 JSValue* arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)718 {719 // JavaScript 1.5 Extension by Mozilla720 // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf721 722 JSObject* thisObj = thisValue->toThisObject(exec);723 724 unsigned index = 0;725 double d = args[1]->toInteger(exec);726 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);727 if (d < 0)728 d += length;729 if (d > 0) {730 if (d > length)731 index = length;732 else733 index = static_cast<unsigned>(d);734 }735 736 JSValue* searchElement = args[0];737 for (; index < length; ++index) {738 JSValue* e = getProperty(exec, thisObj, index);739 if (!e)740 continue;741 if (strictEqual(searchElement, e))742 return jsNumber(exec, index);743 }744 745 return jsNumber(exec, -1);746 }747 748 JSValue* arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)749 {750 // JavaScript 1.6 Extension by Mozilla751 // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf752 753 JSObject* thisObj = thisValue->toThisObject(exec);754 755 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);756 int index = length - 1;757 double d = args[1]->toIntegerPreserveNaN(exec);758 759 if (d < 0) {760 d += length;761 if (d < 0)762 return jsNumber(exec, -1);763 }764 if (d < length)765 index = static_cast<int>(d);766 767 JSValue* searchElement = args[0];768 for (; index >= 0; --index) {769 JSValue* e = getProperty(exec, thisObj, index);770 if (!e)771 continue;772 if (strictEqual(searchElement, e))773 return jsNumber(exec, index);774 }775 776 return jsNumber(exec, -1);777 }778 779 // ------------------------------ ArrayConstructor -------------------------------780 33 781 34 ArrayConstructor::ArrayConstructor(ExecState* exec, FunctionPrototype* funcProto, ArrayPrototype* arrayProto)
Note:
See TracChangeset
for help on using the changeset viewer.