Ignore:
Timestamp:
Jun 27, 2008, 9:29:48 PM (17 years ago)
Author:
[email protected]
Message:

2008-06-27 Sam Weinig <[email protected]>

Rubber-stamped by Oliver Hunt.

Splits ArrayConstructor out of ArrayPrototype.h/cpp
Splits BooleanConstructor and BooleanPrototype out of BooleanObject.h/cpp

  • GNUmakefile.am:
  • JavaScriptCore.pri:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • JavaScriptCoreSources.bkl:
  • VM/Machine.cpp:
  • kjs/AllInOneFile.cpp:
  • kjs/ArrayConstructor.cpp: Copied from kjs/ArrayPrototype.cpp.
  • kjs/ArrayConstructor.h: Copied from kjs/ArrayPrototype.h.
  • kjs/ArrayPrototype.cpp:
  • kjs/ArrayPrototype.h:
  • kjs/BooleanConstructor.cpp: Copied from kjs/BooleanObject.cpp.
  • kjs/BooleanConstructor.h: Copied from kjs/BooleanObject.h.
  • kjs/BooleanObject.cpp:
  • kjs/BooleanObject.h:
  • kjs/BooleanPrototype.cpp: Copied from kjs/BooleanObject.cpp.
  • kjs/BooleanPrototype.h: Copied from kjs/BooleanObject.h.
  • kjs/CommonIdentifiers.h:
  • kjs/FunctionPrototype.cpp:
  • kjs/JSArray.cpp:
  • kjs/JSGlobalObject.cpp:
  • kjs/JSImmediate.cpp:
  • kjs/Shell.cpp:
  • kjs/internal.cpp:
  • kjs/nodes.cpp:
  • kjs/string_object.cpp:
File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/ArrayConstructor.cpp

    r34842 r34843  
    2323
    2424#include "config.h"
     25#include "ArrayConstructor.h"
     26
    2527#include "ArrayPrototype.h"
    26 
    27 #include "Machine.h"
     28#include "JSArray.h"
    2829#include "error_object.h"
    2930#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::min
    3631
    3732namespace 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.h
    70 @begin arrayTable 16
    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
    90 @end
    91 */
    92 
    93 // ECMA 15.4.4
    94 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 function
    108 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         else
    197             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         else
    327             thisObj->deleteProperty(exec, k);
    328 
    329         if (obj)
    330             thisObj->put(exec, lk1, obj);
    331         else
    332             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             else
    352                 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.10
    363 
    364     JSObject* thisObj = thisValue->toThisObject(exec);
    365 
    366     // We return a new array
    367     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         else
    417             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 heapsort
    427     // 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             } else
    445                 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 i
    453         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.12
    466     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     else
    475         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     else
    481         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                 else
    496                     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                 else
    505                     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.13
    521     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             else
    528                 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:every
    613 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
    614 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some
    615 
    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 Mozilla
    720     // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf
    721 
    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         else
    733             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 Mozilla
    751     // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf
    752 
    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 -------------------------------
    78033
    78134ArrayConstructor::ArrayConstructor(ExecState* exec, FunctionPrototype* funcProto, ArrayPrototype* arrayProto)
Note: See TracChangeset for help on using the changeset viewer.