Changeset 29046 in webkit for trunk/JavaScriptCore/kjs/array_object.cpp
- Timestamp:
- Dec 30, 2007, 11:03:05 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/array_object.cpp
r29045 r29046 67 67 // ECMA 15.4.4 68 68 ArrayPrototype::ArrayPrototype(ExecState*, ObjectPrototype* objProto) 69 : ArrayInstance(objProto, 0)69 : ArrayInstance(objProto, 0) 70 70 { 71 71 } … … 73 73 bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) 74 74 { 75 return getStaticFunctionSlot<ArrayInstance>(exec, &arrayTable, this, propertyName, slot);75 return getStaticFunctionSlot<ArrayInstance>(exec, &arrayTable, this, propertyName, slot); 76 76 } 77 77 … … 236 236 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 237 237 for (;;) { 238 if (curArg->isObject() && 239 curObj->inherits(&ArrayInstance::info)) { 238 if (curArg->isObject() && curObj->inherits(&ArrayInstance::info)) { 240 239 unsigned int k = 0; 241 240 // Older versions tried to optimize out getting the length of thisObj … … 267 266 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 268 267 if (length == 0) { 269 thisObj->put(exec, exec->propertyNames().length, jsNumber(length), DontEnum | DontDelete);270 result = jsUndefined();268 thisObj->put(exec, exec->propertyNames().length, jsNumber(length), DontEnum | DontDelete); 269 result = jsUndefined(); 271 270 } else { 272 result = thisObj->get(exec, length - 1);273 thisObj->put(exec, exec->propertyNames().length, jsNumber(length - 1), DontEnum | DontDelete);271 result = thisObj->get(exec, length - 1); 272 thisObj->put(exec, exec->propertyNames().length, jsNumber(length - 1), DontEnum | DontDelete); 274 273 } 275 274 return result; … … 296 295 JSValue *obj = getProperty(exec, thisObj, k); 297 296 298 if (obj2) 297 if (obj2) 299 298 thisObj->put(exec, k, obj2); 300 299 else … … 315 314 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 316 315 if (length == 0) { 317 thisObj->put(exec, exec->propertyNames().length, jsNumber(length), DontEnum | DontDelete);318 result = jsUndefined();316 thisObj->put(exec, exec->propertyNames().length, jsNumber(length), DontEnum | DontDelete); 317 result = jsUndefined(); 319 318 } else { 320 result = thisObj->get(exec, 0);321 for(unsigned int k = 1; k < length; k++) {322 if (JSValue *obj = getProperty(exec, thisObj, k))323 thisObj->put(exec, k-1, obj);324 else325 thisObj->deleteProperty(exec, k-1);326 }327 thisObj->deleteProperty(exec, length - 1);328 thisObj->put(exec, exec->propertyNames().length, jsNumber(length - 1), DontEnum | DontDelete);319 result = thisObj->get(exec, 0); 320 for (unsigned int k = 1; k < length; k++) { 321 if (JSValue *obj = getProperty(exec, thisObj, k)) 322 thisObj->put(exec, k-1, obj); 323 else 324 thisObj->deleteProperty(exec, k-1); 325 } 326 thisObj->deleteProperty(exec, length - 1); 327 thisObj->put(exec, exec->propertyNames().length, jsNumber(length - 1), DontEnum | DontDelete); 329 328 } 330 329 return result; … … 366 365 int b = static_cast<int>(begin); 367 366 int e = static_cast<int>(end); 368 for (int k = b; k < e; k++, n++) {367 for (int k = b; k < e; k++, n++) { 369 368 if (JSValue *v = getProperty(exec, thisObj, k)) 370 369 resObj->put(exec, n, v); … … 378 377 #if 0 379 378 printf("KJS Array::Sort length=%d\n", length); 380 for ( unsigned int i = 0 ; i<length ; ++i)381 printf("KJS Array::Sort: %d: %s\n", i, thisObj->get(exec, i)->toString(exec).ascii());379 for (unsigned int i = 0 ; i<length ; ++i) 380 printf("KJS Array::Sort: %d: %s\n", i, thisObj->get(exec, i)->toString(exec).ascii()); 382 381 #endif 383 382 JSObject *sortFunction = NULL; 384 if (!args[0]->isUndefined()) 385 { 383 if (!args[0]->isUndefined()) { 386 384 sortFunction = args[0]->toObject(exec); 387 385 if (!sortFunction->implementsCall()) 388 sortFunction = NULL;389 390 386 sortFunction = NULL; 387 } 388 391 389 if (thisObj->classInfo() == &ArrayInstance::info) { 392 if (sortFunction)393 ((ArrayInstance *)thisObj)->sort(exec, sortFunction);394 else395 ((ArrayInstance *)thisObj)->sort(exec);396 return thisObj;390 if (sortFunction) 391 ((ArrayInstance *)thisObj)->sort(exec, sortFunction); 392 else 393 ((ArrayInstance *)thisObj)->sort(exec); 394 return thisObj; 397 395 } 398 396 … … 400 398 401 399 if (length == 0) { 402 thisObj->put(exec, exec->propertyNames().length, jsNumber(0), DontEnum | DontDelete);403 return thisObj;400 thisObj->put(exec, exec->propertyNames().length, jsNumber(0), DontEnum | DontDelete); 401 return thisObj; 404 402 } 405 403 406 404 // "Min" sort. Not the fastest, but definitely less code than heapsort 407 405 // or quicksort, and much less swapping than bubblesort/insertionsort. 408 for ( unsigned int i = 0 ; i<length-1 ; ++i ) 409 { 406 for (unsigned int i = 0 ; i<length-1 ; ++i) { 410 407 JSValue *iObj = thisObj->get(exec,i); 411 408 unsigned int themin = i; 412 409 JSValue *minObj = iObj; 413 for ( unsigned int j = i+1 ; j<length ; ++j ) 414 { 410 for (unsigned int j = i+1 ; j<length ; ++j) { 415 411 JSValue *jObj = thisObj->get(exec,j); 416 412 double cmp; 417 413 if (jObj->isUndefined()) { 418 cmp = 1; // don't check minObj because there's no need to differentiate == (0) from > (1)414 cmp = 1; // don't check minObj because there's no need to differentiate == (0) from > (1) 419 415 } else if (minObj->isUndefined()) { 420 cmp = -1;416 cmp = -1; 421 417 } else if (sortFunction) { 422 418 List l; … … 425 421 cmp = sortFunction->call(exec, exec->dynamicGlobalObject(), l)->toNumber(exec); 426 422 } else { 427 cmp = (jObj->toString(exec) < minObj->toString(exec)) ? -1 : 1;423 cmp = (jObj->toString(exec) < minObj->toString(exec)) ? -1 : 1; 428 424 } 429 if ( cmp < 0 ) 430 { 425 if (cmp < 0) { 431 426 themin = j; 432 427 minObj = jObj; 433 434 428 } 429 } 435 430 // Swap themin and i 436 if ( themin > i ) 437 { 438 //printf("KJS Array::Sort: swapping %d and %d\n", i, themin ); 439 thisObj->put( exec, i, minObj ); 440 thisObj->put( exec, themin, iObj ); 441 } 431 if (themin > i) { 432 //printf("KJS Array::Sort: swapping %d and %d\n", i, themin); 433 thisObj->put(exec, i, minObj); 434 thisObj->put(exec, themin, iObj); 435 } 442 436 } 443 437 #if 0 444 438 printf("KJS Array::Sort -- Resulting array:\n"); 445 for ( unsigned int i = 0 ; i<length ; ++i)446 printf("KJS Array::Sort: %d: %s\n", i, thisObj->get(exec, i)->toString(exec).ascii());439 for (unsigned int i = 0 ; i<length ; ++i) 440 printf("KJS Array::Sort: %d: %s\n", i, thisObj->get(exec, i)->toString(exec).ascii()); 447 441 #endif 448 442 return thisObj; … … 462 456 unsigned int deleteCount = std::min<int>(std::max<int>(args[1]->toUInt32(exec), 0), length - begin); 463 457 464 for (unsigned int k = 0; k < deleteCount; k++) {465 if (JSValue *v = getProperty(exec, thisObj, k+begin))466 resObj->put(exec, k, v);458 for (unsigned int k = 0; k < deleteCount; k++) { 459 if (JSValue *v = getProperty(exec, thisObj, k+begin)) 460 resObj->put(exec, k, v); 467 461 } 468 462 resObj->put(exec, exec->propertyNames().length, jsNumber(deleteCount), DontEnum | DontDelete); 469 463 470 464 unsigned int additionalArgs = std::max<int>(args.size() - 2, 0); 471 if ( additionalArgs != deleteCount ) 472 { 473 if ( additionalArgs < deleteCount ) 474 { 475 for ( unsigned int k = begin; k < length - deleteCount; ++k ) 476 { 477 if (JSValue *v = getProperty(exec, thisObj, k+deleteCount)) 478 thisObj->put(exec, k+additionalArgs, v); 479 else 480 thisObj->deleteProperty(exec, k+additionalArgs); 481 } 482 for ( unsigned int k = length ; k > length - deleteCount + additionalArgs; --k ) 483 thisObj->deleteProperty(exec, k-1); 484 } 485 else 486 { 487 for ( unsigned int k = length - deleteCount; (int)k > begin; --k ) 488 { 489 if (JSValue *obj = getProperty(exec, thisObj, k + deleteCount - 1)) 490 thisObj->put(exec, k + additionalArgs - 1, obj); 491 else 492 thisObj->deleteProperty(exec, k+additionalArgs-1); 493 } 494 } 495 } 496 for ( unsigned int k = 0; k < additionalArgs; ++k ) 497 { 498 thisObj->put(exec, k+begin, args[k+2]); 465 if (additionalArgs != deleteCount) { 466 if (additionalArgs < deleteCount) { 467 for (unsigned int k = begin; k < length - deleteCount; ++k) { 468 if (JSValue *v = getProperty(exec, thisObj, k+deleteCount)) 469 thisObj->put(exec, k+additionalArgs, v); 470 else 471 thisObj->deleteProperty(exec, k+additionalArgs); 472 } 473 for (unsigned int k = length ; k > length - deleteCount + additionalArgs; --k) 474 thisObj->deleteProperty(exec, k-1); 475 } else { 476 for (unsigned int k = length - deleteCount; (int)k > begin; --k) { 477 if (JSValue *obj = getProperty(exec, thisObj, k + deleteCount - 1)) 478 thisObj->put(exec, k + additionalArgs - 1, obj); 479 else 480 thisObj->deleteProperty(exec, k+additionalArgs-1); 481 } 482 } 483 } 484 for (unsigned int k = 0; k < additionalArgs; ++k) { 485 thisObj->put(exec, k+begin, args[k+2]); 499 486 } 500 487 thisObj->put(exec, exec->propertyNames().length, jsNumber(length - deleteCount + additionalArgs), DontEnum | DontDelete); … … 507 494 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 508 495 unsigned int nrArgs = args.size(); 509 for ( unsigned int k = length; k > 0; --k ) 510 { 511 if (JSValue *v = getProperty(exec, thisObj, k - 1)) 512 thisObj->put(exec, k+nrArgs-1, v); 513 else 514 thisObj->deleteProperty(exec, k+nrArgs-1); 515 } 516 for ( unsigned int k = 0; k < nrArgs; ++k ) 517 thisObj->put(exec, k, args[k]); 496 for (unsigned int k = length; k > 0; --k) { 497 if (JSValue *v = getProperty(exec, thisObj, k - 1)) 498 thisObj->put(exec, k+nrArgs-1, v); 499 else 500 thisObj->deleteProperty(exec, k+nrArgs-1); 501 } 502 for (unsigned int k = 0; k < nrArgs; ++k) 503 thisObj->put(exec, k, args[k]); 518 504 JSValue* result = jsNumber(length + nrArgs); 519 505 thisObj->put(exec, exec->propertyNames().length, result, DontEnum | DontDelete); … … 524 510 { 525 511 JSObject* eachFunction = args[0]->toObject(exec); 526 512 527 513 if (!eachFunction->implementsCall()) 528 514 return throwError(exec, TypeError); 529 515 530 516 JSObject *applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicGlobalObject() : args[1]->toObject(exec); 531 517 JSObject *resultArray = static_cast<JSObject*>(exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, List::empty())); … … 538 524 if (!thisObj->getPropertySlot(exec, k, slot)) 539 525 continue; 540 526 541 527 JSValue *v = slot.getValue(exec, thisObj, k); 542 528 543 529 List eachArguments; 544 530 545 531 eachArguments.append(v); 546 532 eachArguments.append(jsNumber(k)); 547 533 eachArguments.append(thisObj); 548 534 549 535 JSValue *result = eachFunction->call(exec, applyThis, eachArguments); 550 551 if (result->toBoolean(exec)) 536 537 if (result->toBoolean(exec)) 552 538 resultArray->put(exec, filterIndex++, v); 553 539 } … … 560 546 if (!eachFunction->implementsCall()) 561 547 return throwError(exec, TypeError); 562 548 563 549 JSObject *applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicGlobalObject() : args[1]->toObject(exec); 564 550 … … 597 583 { 598 584 JSObject *eachFunction = args[0]->toObject(exec); 599 585 600 586 if (!eachFunction->implementsCall()) 601 587 return throwError(exec, TypeError); 602 588 603 589 JSObject *applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicGlobalObject() : args[1]->toObject(exec); 604 590 605 591 JSValue* result = jsBoolean(true); 606 592 607 593 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); 608 594 for (unsigned k = 0; k < length && !exec->hadException(); ++k) { 609 595 PropertySlot slot; 610 596 611 597 if (!thisObj->getPropertySlot(exec, k, slot)) 612 598 continue; 613 599 614 600 List eachArguments; 615 601 616 602 eachArguments.append(slot.getValue(exec, thisObj, k)); 617 603 eachArguments.append(jsNumber(k)); 618 604 eachArguments.append(thisObj); 619 605 620 606 bool predicateResult = eachFunction->call(exec, applyThis, eachArguments)->toBoolean(exec); 621 607 622 608 if (!predicateResult) { 623 609 result = jsBoolean(false); … … 718 704 { 719 705 // JavaScript 1.6 Extension by Mozilla 720 // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf 706 // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf 721 707 722 708 unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); … … 726 712 if (d < 0) { 727 713 d += length; 728 if (d < 0) 714 if (d < 0) 729 715 return jsNumber(-1); 730 716 } 731 717 if (d < length) 732 718 index = static_cast<int>(d); 733 719 734 720 JSValue* searchElement = args[0]; 735 721 for (; index >= 0; --index) { … … 740 726 return jsNumber(index); 741 727 } 742 728 743 729 return jsNumber(-1); 744 730 } … … 749 735 FunctionPrototype *funcProto, 750 736 ArrayPrototype *arrayProto) 751 : InternalFunctionImp(funcProto)752 { 753 // ECMA 15.4.3.1 Array.prototype754 put(exec, exec->propertyNames().prototype, arrayProto, DontEnum|DontDelete|ReadOnly);755 756 // no. of arguments for constructor757 put(exec, exec->propertyNames().length, jsNumber(1), ReadOnly|DontDelete|DontEnum);737 : InternalFunctionImp(funcProto) 738 { 739 // ECMA 15.4.3.1 Array.prototype 740 put(exec, exec->propertyNames().prototype, arrayProto, DontEnum|DontDelete|ReadOnly); 741 742 // no. of arguments for constructor 743 put(exec, exec->propertyNames().length, jsNumber(1), ReadOnly|DontDelete|DontEnum); 758 744 } 759 745 760 746 bool ArrayObjectImp::implementsConstruct() const 761 747 { 762 return true;748 return true; 763 749 } 764 750 … … 766 752 JSObject *ArrayObjectImp::construct(ExecState *exec, const List &args) 767 753 { 768 // a single numeric argument denotes the array size (!)769 if (args.size() == 1 && args[0]->isNumber()) {770 uint32_t n = args[0]->toUInt32(exec);771 if (n != args[0]->toNumber(exec))772 return throwError(exec, RangeError, "Array size is not a small enough positive integer.");773 return new ArrayInstance(exec->lexicalGlobalObject()->arrayPrototype(), n);774 }775 776 // otherwise the array is constructed with the arguments in it777 return new ArrayInstance(exec->lexicalGlobalObject()->arrayPrototype(), args);754 // a single numeric argument denotes the array size (!) 755 if (args.size() == 1 && args[0]->isNumber()) { 756 uint32_t n = args[0]->toUInt32(exec); 757 if (n != args[0]->toNumber(exec)) 758 return throwError(exec, RangeError, "Array size is not a small enough positive integer."); 759 return new ArrayInstance(exec->lexicalGlobalObject()->arrayPrototype(), n); 760 } 761 762 // otherwise the array is constructed with the arguments in it 763 return new ArrayInstance(exec->lexicalGlobalObject()->arrayPrototype(), args); 778 764 } 779 765 … … 781 767 JSValue *ArrayObjectImp::callAsFunction(ExecState *exec, JSObject *, const List &args) 782 768 { 783 // equivalent to 'new Array(....)'784 return construct(exec,args);785 } 786 787 } 769 // equivalent to 'new Array(....)' 770 return construct(exec,args); 771 } 772 773 }
Note:
See TracChangeset
for help on using the changeset viewer.