Changeset 27608 in webkit for trunk/JavaScriptCore/kjs/array_object.cpp
- Timestamp:
- Nov 8, 2007, 12:31:26 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/array_object.cpp
r27474 r27608 41 41 /* Source for array_object.lut.h 42 42 @begin arrayTable 16 43 toString ArrayProtoFunc::ToStringDontEnum|Function 044 toLocaleString ArrayProtoFunc::ToLocaleStringDontEnum|Function 045 concat ArrayProtoFunc::ConcatDontEnum|Function 146 join ArrayProtoFunc::JoinDontEnum|Function 147 pop ArrayProtoFunc::PopDontEnum|Function 048 push ArrayProtoFunc::PushDontEnum|Function 149 reverse ArrayProtoFunc::Reverse DontEnum|Function 050 shift ArrayProtoFunc::ShiftDontEnum|Function 051 slice ArrayProtoFunc::Slice DontEnum|Function 252 sort ArrayProtoFunc::SortDontEnum|Function 153 splice ArrayProtoFunc::Splice DontEnum|Function 254 unshift ArrayProtoFunc::UnShiftDontEnum|Function 155 every ArrayProtoFunc::EveryDontEnum|Function 156 forEach ArrayProtoFunc::ForEachDontEnum|Function 157 some ArrayProtoFunc::Some DontEnum|Function 158 indexOf ArrayProtoFunc::IndexOfDontEnum|Function 159 lastIndexOf ArrayProtoFunc::LastIndexOfDontEnum|Function 160 filter ArrayProtoFunc::FilterDontEnum|Function 161 map ArrayProtoFunc::MapDontEnum|Function 143 toString &ArrayProtoFuncToString::create DontEnum|Function 0 44 toLocaleString &ArrayProtoFuncToLocaleString::create DontEnum|Function 0 45 concat &ArrayProtoFuncConcat::create DontEnum|Function 1 46 join &ArrayProtoFuncJoin::create DontEnum|Function 1 47 pop &ArrayProtoFuncPop::create DontEnum|Function 0 48 push &ArrayProtoFuncPush::create DontEnum|Function 1 49 reverse &ArrayProtoFuncReverse::create DontEnum|Function 0 50 shift &ArrayProtoFuncShift::create DontEnum|Function 0 51 slice &ArrayProtoFuncSlice::create DontEnum|Function 2 52 sort &ArrayProtoFuncSort::create DontEnum|Function 1 53 splice &ArrayProtoFuncSplice::create DontEnum|Function 2 54 unshift &ArrayProtoFuncUnShift::create DontEnum|Function 1 55 every &ArrayProtoFuncEvery::create DontEnum|Function 1 56 forEach &ArrayProtoFuncForEach::create DontEnum|Function 1 57 some &ArrayProtoFuncSome::create DontEnum|Function 1 58 indexOf &ArrayProtoFuncIndexOf::create DontEnum|Function 1 59 lastIndexOf &ArrayProtoFuncLastIndexOf::create DontEnum|Function 1 60 filter &ArrayProtoFuncFilter::create DontEnum|Function 1 61 map &ArrayProtoFuncMap::create DontEnum|Function 1 62 62 @end 63 63 */ … … 71 71 bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) 72 72 { 73 return getStaticFunctionSlot<ArrayProtoFunc, ArrayInstance>(exec, &arrayTable, this, propertyName, slot); 74 } 75 76 // ------------------------------ ArrayProtoFunc ---------------------------- 77 78 ArrayProtoFunc::ArrayProtoFunc(ExecState* exec, int i, int len, const Identifier& name) 79 : InternalFunctionImp(static_cast<FunctionPrototype*> 80 (exec->lexicalInterpreter()->builtinFunctionPrototype()), name) 81 , id(i) 82 { 83 put(exec, exec->propertyNames().length, jsNumber(len), DontDelete | ReadOnly | DontEnum); 84 } 85 86 static JSValue *getProperty(ExecState *exec, JSObject *obj, unsigned index) 73 return getStaticFunctionSlot<ArrayInstance>(exec, &arrayTable, this, propertyName, slot); 74 } 75 76 77 // ------------------------------ Array Functions ---------------------------- 78 79 // Helper function 80 static JSValue* getProperty(ExecState* exec, JSObject* obj, unsigned index) 87 81 { 88 82 PropertySlot slot; 89 83 if (!obj->getPropertySlot(exec, index, slot)) 90 return NULL;84 return 0; 91 85 return slot.getValue(exec, obj, index); 92 86 } 93 87 94 // ECMA 15.4.4 95 JSValue* ArrayProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 96 { 97 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 98 99 JSValue *result = 0; // work around gcc 4.0 bug in uninitialized variable warning 100 101 switch (id) { 102 case ToLocaleString: 103 case ToString: 104 88 JSValue* ArrayProtoFuncToString::callAsFunction(ExecState* exec, JSObject* thisObj, const List&) 89 { 105 90 if (!thisObj->inherits(&ArrayInstance::info)) 106 return throwError(exec, TypeError); 107 108 // fall through 109 case Join: { 91 return throwError(exec, TypeError); 92 110 93 static HashSet<JSObject*> visitedElems; 111 94 static const UString* empty = new UString(""); … … 117 100 UString str = *empty; 118 101 119 if (id == Join && !args[0]->isUndefined()) 120 separator = args[0]->toString(exec); 102 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 121 103 for (unsigned int k = 0; k < length; k++) { 122 104 if (k >= 1) … … 132 114 continue; 133 115 134 bool fallback = false; 135 if (id == ToLocaleString) { 136 JSObject* o = element->toObject(exec); 137 JSValue* conversionFunction = o->get(exec, exec->propertyNames().toLocaleString); 138 if (conversionFunction->isObject() && static_cast<JSObject*>(conversionFunction)->implementsCall()) { 139 List args; 140 str += static_cast<JSObject*>(conversionFunction)->call(exec, o, args)->toString(exec); 141 } else { 142 // try toString() fallback 143 fallback = true; 144 } 145 } 146 147 if (id == ToString || id == Join || fallback) 148 str += element->toString(exec); 116 str += element->toString(exec); 149 117 150 118 if (str.isNull()) { … … 157 125 } 158 126 visitedElems.remove(thisObj); 159 result = jsString(str); 160 break; 161 } 162 case Concat: { 163 JSObject *arr = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec,List::empty())); 127 return jsString(str); 128 } 129 130 JSValue* ArrayProtoFuncToLocaleString::callAsFunction(ExecState* exec, JSObject* thisObj, const List&) 131 { 132 if (!thisObj->inherits(&ArrayInstance::info)) 133 return throwError(exec, TypeError); 134 135 static HashSet<JSObject*> visitedElems; 136 static const UString* empty = new UString(""); 137 static const UString* comma = new UString(","); 138 bool alreadyVisited = !visitedElems.add(thisObj).second; 139 if (alreadyVisited) 140 return jsString(*empty); 141 UString separator = *comma; 142 UString str = *empty; 143 144 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 145 for (unsigned int k = 0; k < length; k++) { 146 if (k >= 1) 147 str += separator; 148 if (str.isNull()) { 149 JSObject *error = Error::create(exec, GeneralError, "Out of memory"); 150 exec->setException(error); 151 break; 152 } 153 154 JSValue* element = thisObj->get(exec, k); 155 if (element->isUndefinedOrNull()) 156 continue; 157 158 bool fallback = false; 159 JSObject* o = element->toObject(exec); 160 JSValue* conversionFunction = o->get(exec, exec->propertyNames().toLocaleString); 161 if (conversionFunction->isObject() && static_cast<JSObject*>(conversionFunction)->implementsCall()) { 162 List args; 163 str += static_cast<JSObject*>(conversionFunction)->call(exec, o, args)->toString(exec); 164 } else { 165 // try toString() fallback 166 fallback = true; 167 } 168 169 if (fallback) 170 str += element->toString(exec); 171 172 if (str.isNull()) { 173 JSObject *error = Error::create(exec, GeneralError, "Out of memory"); 174 exec->setException(error); 175 } 176 177 if (exec->hadException()) 178 break; 179 } 180 visitedElems.remove(thisObj); 181 return jsString(str); 182 } 183 184 JSValue* ArrayProtoFuncJoin::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 185 { 186 static HashSet<JSObject*> visitedElems; 187 static const UString* empty = new UString(""); 188 static const UString* comma = new UString(","); 189 bool alreadyVisited = !visitedElems.add(thisObj).second; 190 if (alreadyVisited) 191 return jsString(*empty); 192 UString separator = *comma; 193 UString str = *empty; 194 195 if (!args[0]->isUndefined()) 196 separator = args[0]->toString(exec); 197 198 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 199 for (unsigned int k = 0; k < length; k++) { 200 if (k >= 1) 201 str += separator; 202 if (str.isNull()) { 203 JSObject *error = Error::create(exec, GeneralError, "Out of memory"); 204 exec->setException(error); 205 break; 206 } 207 208 JSValue* element = thisObj->get(exec, k); 209 if (element->isUndefinedOrNull()) 210 continue; 211 212 str += element->toString(exec); 213 214 if (str.isNull()) { 215 JSObject *error = Error::create(exec, GeneralError, "Out of memory"); 216 exec->setException(error); 217 } 218 219 if (exec->hadException()) 220 break; 221 } 222 visitedElems.remove(thisObj); 223 return jsString(str); 224 } 225 226 JSValue* ArrayProtoFuncConcat::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 227 { 228 JSObject* arr = static_cast<JSObject*>(exec->lexicalInterpreter()->builtinArray()->construct(exec, List::empty())); 164 229 int n = 0; 165 230 JSValue *curArg = thisObj; … … 167 232 List::const_iterator it = args.begin(); 168 233 List::const_iterator end = args.end(); 234 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 169 235 for (;;) { 170 if (curArg->isObject() &&171 curObj->inherits(&ArrayInstance::info)) {172 unsigned int k = 0;173 // Older versions tried to optimize out getting the length of thisObj174 // by checking for n != 0, but that doesn't work if thisObj is an empty array.175 length = curObj->get(exec, exec->propertyNames().length)->toUInt32(exec);176 while (k < length) {177 if (JSValue *v = getProperty(exec, curObj, k))178 arr->put(exec, n, v);179 n++;180 k++;181 }182 } else {183 arr->put(exec, n, curArg);184 n++;185 }186 if (it == end)187 break;188 curArg = *it;189 curObj = static_cast<JSObject*>(curArg); // may be 0190 ++it;236 if (curArg->isObject() && 237 curObj->inherits(&ArrayInstance::info)) { 238 unsigned int k = 0; 239 // Older versions tried to optimize out getting the length of thisObj 240 // by checking for n != 0, but that doesn't work if thisObj is an empty array. 241 length = curObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 242 while (k < length) { 243 if (JSValue *v = getProperty(exec, curObj, k)) 244 arr->put(exec, n, v); 245 n++; 246 k++; 247 } 248 } else { 249 arr->put(exec, n, curArg); 250 n++; 251 } 252 if (it == end) 253 break; 254 curArg = *it; 255 curObj = static_cast<JSObject*>(curArg); // may be 0 256 ++it; 191 257 } 192 258 arr->put(exec, exec->propertyNames().length, jsNumber(n), DontEnum | DontDelete); 193 194 result = arr; 195 break; 196 } 197 case Pop:{ 259 return arr; 260 } 261 262 JSValue* ArrayProtoFuncPop::callAsFunction(ExecState* exec, JSObject* thisObj, const List&) 263 { 264 JSValue* result = 0; 265 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 198 266 if (length == 0) { 199 267 thisObj->put(exec, exec->propertyNames().length, jsNumber(length), DontEnum | DontDelete); … … 203 271 thisObj->put(exec, exec->propertyNames().length, jsNumber(length - 1), DontEnum | DontDelete); 204 272 } 205 break; 206 } 207 case Push: { 273 return result; 274 } 275 276 JSValue* ArrayProtoFuncPush::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 277 { 278 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 208 279 for (unsigned int n = 0; n < args.size(); n++) 209 thisObj->put(exec, length + n, args[n]);280 thisObj->put(exec, length + n, args[n]); 210 281 length += args.size(); 211 282 thisObj->put(exec, exec->propertyNames().length, jsNumber(length), DontEnum | DontDelete); 212 result = jsNumber(length); 213 break; 214 } 215 case Reverse: { 216 283 return jsNumber(length); 284 } 285 286 JSValue* ArrayProtoFuncReverse::callAsFunction(ExecState* exec, JSObject* thisObj, const List&) 287 { 288 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 217 289 unsigned int middle = length / 2; 218 290 219 291 for (unsigned int k = 0; k < middle; k++) { 220 unsigned lk1 = length - k - 1; 221 JSValue *obj2 = getProperty(exec, thisObj, lk1); 222 JSValue *obj = getProperty(exec, thisObj, k); 223 224 if (obj2) 225 thisObj->put(exec, k, obj2); 226 else 227 thisObj->deleteProperty(exec, k); 228 229 if (obj) 230 thisObj->put(exec, lk1, obj); 231 else 232 thisObj->deleteProperty(exec, lk1); 233 } 234 result = thisObj; 235 break; 236 } 237 case Shift: { 292 unsigned lk1 = length - k - 1; 293 JSValue *obj2 = getProperty(exec, thisObj, lk1); 294 JSValue *obj = getProperty(exec, thisObj, k); 295 296 if (obj2) 297 thisObj->put(exec, k, obj2); 298 else 299 thisObj->deleteProperty(exec, k); 300 301 if (obj) 302 thisObj->put(exec, lk1, obj); 303 else 304 thisObj->deleteProperty(exec, lk1); 305 } 306 return thisObj; 307 } 308 309 JSValue* ArrayProtoFuncShift::callAsFunction(ExecState* exec, JSObject* thisObj, const List&) 310 { 311 JSValue* result = 0; 312 313 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 238 314 if (length == 0) { 239 315 thisObj->put(exec, exec->propertyNames().length, jsNumber(length), DontEnum | DontDelete); … … 250 326 thisObj->put(exec, exec->propertyNames().length, jsNumber(length - 1), DontEnum | DontDelete); 251 327 } 252 break; 253 } 254 case Slice: { 328 return result; 329 } 330 331 JSValue* ArrayProtoFuncSlice::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 332 { 255 333 // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10 256 334 257 335 // We return a new array 258 336 JSObject *resObj = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec,List::empty())); 259 result = resObj;337 JSValue* result = resObj; 260 338 double begin = args[0]->toInteger(exec); 339 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 261 340 if (begin >= 0) { 262 if (begin > length)263 begin = length;341 if (begin > length) 342 begin = length; 264 343 } else { 265 begin += length;266 if (begin < 0)267 begin = 0;344 begin += length; 345 if (begin < 0) 346 begin = 0; 268 347 } 269 348 double end; 270 349 if (args[1]->isUndefined()) 271 end = length;350 end = length; 272 351 else { 273 end = args[1]->toInteger(exec);274 if (end < 0) {275 end += length;276 if (end < 0)277 end = 0;278 } else {279 if (end > length)280 end = length;281 }352 end = args[1]->toInteger(exec); 353 if (end < 0) { 354 end += length; 355 if (end < 0) 356 end = 0; 357 } else { 358 if (end > length) 359 end = length; 360 } 282 361 } 283 362 … … 286 365 int e = static_cast<int>(end); 287 366 for(int k = b; k < e; k++, n++) { 288 if (JSValue *v = getProperty(exec, thisObj, k))289 resObj->put(exec, n, v);367 if (JSValue *v = getProperty(exec, thisObj, k)) 368 resObj->put(exec, n, v); 290 369 } 291 370 resObj->put(exec, exec->propertyNames().length, jsNumber(n), DontEnum | DontDelete); 292 break; 293 } 294 case Sort:{ 371 return result; 372 } 373 374 JSValue* ArrayProtoFuncSort::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 375 { 295 376 #if 0 296 377 printf("KJS Array::Sort length=%d\n", length); … … 311 392 else 312 393 ((ArrayInstance *)thisObj)->sort(exec); 313 result = thisObj; 314 break; 315 } 394 return thisObj; 395 } 396 397 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 316 398 317 399 if (length == 0) { 318 400 thisObj->put(exec, exec->propertyNames().length, jsNumber(0), DontEnum | DontDelete); 319 result = thisObj; 320 break; 401 return thisObj; 321 402 } 322 403 … … 357 438 thisObj->put( exec, themin, iObj ); 358 439 } 359 440 } 360 441 #if 0 361 442 printf("KJS Array::Sort -- Resulting array:\n"); … … 363 444 printf("KJS Array::Sort: %d: %s\n", i, thisObj->get(exec, i)->toString(exec).ascii() ); 364 445 #endif 365 result = thisObj; 366 break; 367 } 368 case Splice: { 446 return thisObj; 447 } 448 449 JSValue* ArrayProtoFuncSplice::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 450 { 369 451 // 15.4.4.12 - oh boy this is huge 370 JSObject *resObj = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec,List::empty())); 371 result = resObj; 452 JSObject *resObj = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec, List::empty())); 453 JSValue* result = resObj; 454 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 372 455 int begin = args[0]->toUInt32(exec); 373 456 if ( begin < 0 ) … … 415 498 } 416 499 thisObj->put(exec, exec->propertyNames().length, jsNumber(length - deleteCount + additionalArgs), DontEnum | DontDelete); 417 break; 418 } 419 case UnShift: { // 15.4.4.13 500 return result; 501 } 502 503 JSValue* ArrayProtoFuncUnShift::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 504 { 505 // 15.4.4.13 506 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 420 507 unsigned int nrArgs = args.size(); 421 508 for ( unsigned int k = length; k > 0; --k ) … … 428 515 for ( unsigned int k = 0; k < nrArgs; ++k ) 429 516 thisObj->put(exec, k, args[k]); 430 result = jsNumber(length + nrArgs);517 JSValue* result = jsNumber(length + nrArgs); 431 518 thisObj->put(exec, exec->propertyNames().length, result, DontEnum | DontDelete); 432 break; 433 } 434 case Filter: 435 case Map: { 519 return result; 520 } 521 522 JSValue* ArrayProtoFuncFilter::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 523 { 524 JSObject* eachFunction = args[0]->toObject(exec); 525 526 if (!eachFunction->implementsCall()) 527 return throwError(exec, TypeError); 528 529 JSObject *applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicInterpreter()->globalObject() : args[1]->toObject(exec); 530 JSObject *resultArray = static_cast<JSObject*>(exec->lexicalInterpreter()->builtinArray()->construct(exec, List::empty())); 531 532 unsigned filterIndex = 0; 533 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 534 for (unsigned k = 0; k < length && !exec->hadException(); ++k) { 535 PropertySlot slot; 536 537 if (!thisObj->getPropertySlot(exec, k, slot)) 538 continue; 539 540 JSValue *v = slot.getValue(exec, thisObj, k); 541 542 List eachArguments; 543 544 eachArguments.append(v); 545 eachArguments.append(jsNumber(k)); 546 eachArguments.append(thisObj); 547 548 JSValue *result = eachFunction->call(exec, applyThis, eachArguments); 549 550 if (result->toBoolean(exec)) 551 resultArray->put(exec, filterIndex++, v); 552 } 553 return resultArray; 554 } 555 556 JSValue* ArrayProtoFuncMap::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 557 { 558 JSObject* eachFunction = args[0]->toObject(exec); 559 if (!eachFunction->implementsCall()) 560 return throwError(exec, TypeError); 561 562 JSObject *applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicInterpreter()->globalObject() : args[1]->toObject(exec); 563 564 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 565 566 List mapArgs; 567 mapArgs.append(jsNumber(length)); 568 JSObject* resultArray = static_cast<JSObject*>(exec->lexicalInterpreter()->builtinArray()->construct(exec, mapArgs)); 569 570 for (unsigned k = 0; k < length && !exec->hadException(); ++k) { 571 PropertySlot slot; 572 if (!thisObj->getPropertySlot(exec, k, slot)) 573 continue; 574 575 JSValue *v = slot.getValue(exec, thisObj, k); 576 577 List eachArguments; 578 579 eachArguments.append(v); 580 eachArguments.append(jsNumber(k)); 581 eachArguments.append(thisObj); 582 583 JSValue *result = eachFunction->call(exec, applyThis, eachArguments); 584 resultArray->put(exec, k, result); 585 } 586 587 return resultArray; 588 } 589 590 // Documentation for these three is available at: 591 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every 592 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach 593 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some 594 595 JSValue* ArrayProtoFuncEvery::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 596 { 436 597 JSObject *eachFunction = args[0]->toObject(exec); 437 598 438 599 if (!eachFunction->implementsCall()) 439 return throwError(exec, TypeError); 440 441 JSObject *applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicInterpreter()->globalObject() : args[1]->toObject(exec); 442 JSObject *resultArray; 443 444 if (id == Filter) 445 resultArray = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec, List::empty())); 446 else { 447 List args; 448 args.append(jsNumber(length)); 449 resultArray = static_cast<JSObject *>(exec->lexicalInterpreter()->builtinArray()->construct(exec, args)); 450 } 451 452 unsigned filterIndex = 0; 453 for (unsigned k = 0; k < length && !exec->hadException(); ++k) { 454 PropertySlot slot; 455 456 if (!thisObj->getPropertySlot(exec, k, slot)) 457 continue; 458 459 JSValue *v = slot.getValue(exec, thisObj, k); 460 461 List eachArguments; 462 463 eachArguments.append(v); 464 eachArguments.append(jsNumber(k)); 465 eachArguments.append(thisObj); 466 467 JSValue *result = eachFunction->call(exec, applyThis, eachArguments); 468 469 if (id == Map) 470 resultArray->put(exec, k, result); 471 else if (result->toBoolean(exec)) 472 resultArray->put(exec, filterIndex++, v); 473 } 474 475 return resultArray; 476 } 477 case Every: 478 case ForEach: 479 case Some: { 480 //Documentation for these three is available at: 481 //http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every 482 //http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach 483 //http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some 484 485 JSObject *eachFunction = args[0]->toObject(exec); 486 487 if (!eachFunction->implementsCall()) 488 return throwError(exec, TypeError); 600 return throwError(exec, TypeError); 489 601 490 602 JSObject *applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicInterpreter()->globalObject() : args[1]->toObject(exec); 491 603 492 if (id == Some || id == Every) 493 result = jsBoolean(id == Every); 494 else 495 result = jsUndefined(); 604 JSValue* result = jsBoolean(true); 496 605 606 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 497 607 for (unsigned k = 0; k < length && !exec->hadException(); ++k) { 498 PropertySlot slot; 608 PropertySlot slot; 609 610 if (!thisObj->getPropertySlot(exec, k, slot)) 611 continue; 612 613 List eachArguments; 499 614 500 if (!thisObj->getPropertySlot(exec, k, slot)) 501 continue; 615 eachArguments.append(slot.getValue(exec, thisObj, k)); 616 eachArguments.append(jsNumber(k)); 617 eachArguments.append(thisObj); 502 618 503 List eachArguments;619 bool predicateResult = eachFunction->call(exec, applyThis, eachArguments)->toBoolean(exec); 504 620 505 eachArguments.append(slot.getValue(exec, thisObj, k)); 506 eachArguments.append(jsNumber(k)); 507 eachArguments.append(thisObj); 508 509 bool predicateResult = eachFunction->call(exec, applyThis, eachArguments)->toBoolean(exec); 510 511 if (id == Every && !predicateResult) { 512 result = jsBoolean(false); 513 break; 514 } 515 if (id == Some && predicateResult) { 516 result = jsBoolean(true); 517 break; 518 } 519 } 520 break; 521 } 522 523 case IndexOf: { 621 if (!predicateResult) { 622 result = jsBoolean(false); 623 break; 624 } 625 } 626 627 return result; 628 } 629 630 JSValue* ArrayProtoFuncForEach::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 631 { 632 JSObject* eachFunction = args[0]->toObject(exec); 633 634 if (!eachFunction->implementsCall()) 635 return throwError(exec, TypeError); 636 637 JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicInterpreter()->globalObject() : args[1]->toObject(exec); 638 639 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 640 for (unsigned k = 0; k < length && !exec->hadException(); ++k) { 641 PropertySlot slot; 642 if (!thisObj->getPropertySlot(exec, k, slot)) 643 continue; 644 645 List eachArguments; 646 eachArguments.append(slot.getValue(exec, thisObj, k)); 647 eachArguments.append(jsNumber(k)); 648 eachArguments.append(thisObj); 649 650 eachFunction->call(exec, applyThis, eachArguments); 651 } 652 return jsUndefined(); 653 } 654 655 JSValue* ArrayProtoFuncSome::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 656 { 657 JSObject* eachFunction = args[0]->toObject(exec); 658 659 if (!eachFunction->implementsCall()) 660 return throwError(exec, TypeError); 661 662 JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicInterpreter()->globalObject() : args[1]->toObject(exec); 663 664 JSValue* result = jsBoolean(false); 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; 669 if (!thisObj->getPropertySlot(exec, k, slot)) 670 continue; 671 672 List eachArguments; 673 eachArguments.append(slot.getValue(exec, thisObj, k)); 674 eachArguments.append(jsNumber(k)); 675 eachArguments.append(thisObj); 676 677 bool predicateResult = eachFunction->call(exec, applyThis, eachArguments)->toBoolean(exec); 678 679 if (predicateResult) { 680 result = jsBoolean(true); 681 break; 682 } 683 } 684 return result; 685 } 686 687 JSValue* ArrayProtoFuncIndexOf::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 688 { 524 689 // JavaScript 1.5 Extension by Mozilla 525 690 // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf … … 527 692 unsigned index = 0; 528 693 double d = args[1]->toInteger(exec); 694 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 529 695 if (d < 0) 530 696 d += length; … … 546 712 547 713 return jsNumber(-1); 548 } 549 case LastIndexOf: { 550 // JavaScript 1.6 Extension by Mozilla 551 // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf 552 714 } 715 716 JSValue* ArrayProtoFuncLastIndexOf::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 717 { 718 // JavaScript 1.6 Extension by Mozilla 719 // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf 720 721 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 553 722 int index = length - 1; 554 723 double d = args[1]->toIntegerPreserveNaN(exec); … … 573 742 return jsNumber(-1); 574 743 } 575 default:576 ASSERT(0);577 result = 0;578 break;579 }580 return result;581 }582 744 583 745 // ------------------------------ ArrayObjectImp -------------------------------
Note:
See TracChangeset
for help on using the changeset viewer.