Changeset 1799 in webkit for trunk/JavaScriptCore/kjs/array_object.cpp
- Timestamp:
- Aug 12, 2002, 1:14:02 PM (23 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/array_object.cpp
r1623 r1799 40 40 const ClassInfo ArrayInstanceImp::info = {"Array", 0, 0, 0}; 41 41 42 ArrayInstanceImp::ArrayInstanceImp(const Object &proto )42 ArrayInstanceImp::ArrayInstanceImp(const Object &proto, unsigned initialLength) 43 43 : ObjectImp(proto) 44 { 44 , length(initialLength) 45 , capacity(length) 46 , storage(length ? new Undefined[length] : 0) 47 { 48 } 49 50 ArrayInstanceImp::ArrayInstanceImp(const Object &proto, const List &list) 51 : ObjectImp(proto) 52 , length(list.size()) 53 , capacity(length) 54 , storage(length ? new Undefined[length] : 0) 55 { 56 ListIterator it = list.begin(); 57 const unsigned l = length; 58 for (unsigned i = 0; i < l; ++i) { 59 storage[i] = it++; 60 } 61 } 62 63 ArrayInstanceImp::~ArrayInstanceImp() 64 { 65 delete [] storage; 66 } 67 68 Value ArrayInstanceImp::get(ExecState *exec, const UString &propertyName) const 69 { 70 if (propertyName == lengthPropertyName) 71 return Number(length); 72 73 bool ok; 74 unsigned index = propertyName.toULong(&ok); 75 if (ok) { 76 if (index >= length) 77 return Undefined(); 78 return storage[index]; 79 } 80 81 return ObjectImp::get(exec, propertyName); 82 } 83 84 Value ArrayInstanceImp::get(ExecState *exec, unsigned index) const 85 { 86 if (index >= length) 87 return Undefined(); 88 return storage[index]; 45 89 } 46 90 … … 48 92 void ArrayInstanceImp::put(ExecState *exec, const UString &propertyName, const Value &value, int attr) 49 93 { 50 if ((attr == None || attr == DontDelete) && !canPut(exec,propertyName)) 94 if (propertyName == lengthPropertyName) { 95 setLength(value.toUInt32(exec)); 51 96 return; 52 53 if (hasProperty(exec,propertyName)) { 54 if (propertyName == "length") { 55 Value len = get(exec,"length"); 56 unsigned int oldLen = len.toUInt32(exec); 57 unsigned int newLen = value.toUInt32(exec); 58 // shrink array 59 for (unsigned int u = newLen; u < oldLen; u++) { 60 UString p = UString::from(u); 61 if (hasOwnProperty(exec, p)) 62 deleteProperty(exec, p); 63 } 64 ObjectImp::put(exec, "length", Number(newLen), DontEnum | DontDelete); 65 return; 66 } 67 // put(p, v); 68 } // } else 69 ObjectImp::put(exec, propertyName, value, attr); 70 71 // array index ? 72 unsigned int idx; 73 if (!sscanf(propertyName.cstring().c_str(), "%u", &idx)) /* TODO */ 97 } 98 99 bool ok; 100 unsigned index = propertyName.toULong(&ok); 101 if (ok) { 102 setLength(index + 1); 103 storage[index] = value; 74 104 return; 75 76 // do we need to update/create the length property ? 77 if (hasOwnProperty(exec, "length")) { 78 Value len = get(exec, "length"); 79 if (idx < len.toUInt32(exec)) 80 return; 81 } 82 83 ObjectImp::put(exec, "length", Number(idx+1), DontDelete | DontEnum); 84 } 85 86 void ArrayInstanceImp::putDirect(ExecState *exec, const UString &propertyName, const Value &value, int attr) 87 { 88 ObjectImp::put(exec,propertyName,value,attr); 89 } 90 91 bool ArrayInstanceImp::hasOwnProperty(ExecState *exec, 92 const UString &propertyName) 93 { 94 // disable this object's prototype temporarily for the hasProperty() call 95 Value protoBackup = prototype(); 96 setPrototype(Undefined()); 97 bool b = hasProperty(exec, propertyName); 98 setPrototype(protoBackup); 99 return b; 105 } 106 107 ObjectImp::put(exec, propertyName, value, attr); 108 } 109 110 void ArrayInstanceImp::put(ExecState *exec, unsigned index, const Value &value, int attr) 111 { 112 setLength(index + 1); 113 storage[index] = value; 114 } 115 116 bool ArrayInstanceImp::hasProperty(ExecState *exec, const UString &propertyName) const 117 { 118 if (propertyName == lengthPropertyName) 119 return true; 120 121 bool ok; 122 unsigned index = propertyName.toULong(&ok); 123 if (ok) { 124 if (index >= length) 125 return false; 126 return !storage[index].isA(UndefinedType); 127 } 128 129 return ObjectImp::hasProperty(exec, propertyName); 130 } 131 132 bool ArrayInstanceImp::hasProperty(ExecState *exec, unsigned index) const 133 { 134 if (index >= length) 135 return false; 136 return !storage[index].isA(UndefinedType); 137 } 138 139 bool ArrayInstanceImp::deleteProperty(ExecState *exec, const UString &propertyName) 140 { 141 if (propertyName == lengthPropertyName) 142 return false; 143 144 bool ok; 145 unsigned index = propertyName.toULong(&ok); 146 if (ok) { 147 if (index >= length) 148 return true; 149 storage[index] = Undefined(); 150 return true; 151 } 152 153 return ObjectImp::deleteProperty(exec, propertyName); 154 } 155 156 bool ArrayInstanceImp::deleteProperty(ExecState *exec, unsigned index) 157 { 158 if (index >= length) 159 return true; 160 storage[index] = Undefined(); 161 return true; 162 } 163 164 void ArrayInstanceImp::setLength(unsigned newLength) 165 { 166 if (newLength < length) { 167 const unsigned l = length; 168 for (unsigned i = newLength; i < l; ++i) 169 storage[i] = Undefined(); 170 } 171 if (newLength > capacity) { 172 unsigned newCapacity = (newLength * 3 + 1) / 2; 173 Value *newStorage = new Undefined [newCapacity]; 174 const unsigned l = length; 175 for (unsigned i = 0; i < l; ++i) 176 newStorage[i] = storage[i]; 177 delete [] storage; 178 storage = newStorage; 179 capacity = newCapacity; 180 } 181 length = newLength; 182 } 183 184 void ArrayInstanceImp::mark() 185 { 186 ObjectImp::mark(); 187 const unsigned l = length; 188 for (unsigned i = 0; i < l; ++i) { 189 ValueImp *imp = storage[i].imp(); 190 if (!imp->marked()) 191 imp->mark(); 192 } 100 193 } 101 194 … … 124 217 ArrayPrototypeImp::ArrayPrototypeImp(ExecState *exec, 125 218 ObjectPrototypeImp *objProto) 126 : ArrayInstanceImp(Object(objProto) )219 : ArrayInstanceImp(Object(objProto), 0) 127 220 { 128 221 Value protect(this); 129 222 setInternalValue(Null()); 130 131 // The constructor will be added later, by InterpreterImp, once ArrayObjectImp has been constructed.132 put(exec,"length", Number(0), DontEnum | DontDelete);133 223 } 134 224 … … 147 237 { 148 238 Value protect(this); 149 put(exec, "length",Number(len),DontDelete|ReadOnly|DontEnum);239 put(exec,lengthPropertyName,Number(len),DontDelete|ReadOnly|DontEnum); 150 240 } 151 241 … … 158 248 Value ArrayProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args) 159 249 { 160 unsigned int length = thisObj.get(exec, "length").toUInt32(exec);250 unsigned int length = thisObj.get(exec,lengthPropertyName).toUInt32(exec); 161 251 162 252 Value result; … … 184 274 if (k >= 1) 185 275 str += separator; 186 Value element = thisObj.get(exec, UString::from(k));276 Value element = thisObj.get(exec,k); 187 277 if (element.type() != UndefinedType && element.type() != NullType) 188 278 str += element.toString(exec); … … 202 292 unsigned int k = 0; 203 293 if (n > 0) 204 length = curObj.get(exec, "length").toUInt32(exec);294 length = curObj.get(exec,lengthPropertyName).toUInt32(exec); 205 295 while (k < length) { 206 UString p = UString::from(k); 207 if (curObj.hasProperty(exec,p)) 208 arr.put(exec,UString::from(n), curObj.get(exec,p)); 296 if (curObj.hasProperty(exec,k)) 297 arr.put(exec, n, curObj.get(exec, k)); 209 298 n++; 210 299 k++; 211 300 } 212 301 } else { 213 arr.put(exec, UString::from(n), curArg);302 arr.put(exec, n, curArg); 214 303 n++; 215 304 } … … 219 308 curObj = Object::dynamicCast(it++); // may be 0 220 309 } 221 arr.put(exec, "length", Number(n), DontEnum | DontDelete);310 arr.put(exec,lengthPropertyName, Number(n), DontEnum | DontDelete); 222 311 223 312 result = arr; … … 225 314 } 226 315 case Pop:{ 227 228 316 if (length == 0) { 229 thisObj.put(exec, "length", Number(length), DontEnum | DontDelete);317 thisObj.put(exec, lengthPropertyName, Number(length), DontEnum | DontDelete); 230 318 result = Undefined(); 231 319 } else { 232 UString str = UString::from(length - 1); 233 result = thisObj.get(exec,str); 234 thisObj.deleteProperty(exec, str); 235 thisObj.put(exec, "length", Number(length - 1), DontEnum | DontDelete); 320 result = thisObj.get(exec, length - 1); 321 thisObj.put(exec, lengthPropertyName, Number(length - 1), DontEnum | DontDelete); 236 322 } 237 323 break; … … 239 325 case Push: { 240 326 for (int n = 0; n < args.size(); n++) 241 thisObj.put(exec, UString::from(length + n), args[n]);327 thisObj.put(exec, length + n, args[n]); 242 328 length += args.size(); 243 thisObj.put(exec, "length", Number(length), DontEnum | DontDelete);329 thisObj.put(exec,lengthPropertyName, Number(length), DontEnum | DontDelete); 244 330 result = Number(length); 245 331 break; … … 250 336 251 337 for (unsigned int k = 0; k < middle; k++) { 252 UString str = UString::from(k); 253 UString str2 = UString::from(length - k - 1); 254 Value obj = thisObj.get(exec,str); 255 Value obj2 = thisObj.get(exec,str2); 256 if (thisObj.hasProperty(exec,str2)) { 257 if (thisObj.hasProperty(exec,str)) { 258 thisObj.put(exec, str, obj2); 259 thisObj.put(exec, str2, obj); 338 unsigned lk1 = length - k - 1; 339 Value obj = thisObj.get(exec,k); 340 Value obj2 = thisObj.get(exec,lk1); 341 if (thisObj.hasProperty(exec,lk1)) { 342 if (thisObj.hasProperty(exec,k)) { 343 thisObj.put(exec, k, obj2); 344 thisObj.put(exec, lk1, obj); 260 345 } else { 261 thisObj.put(exec, str, obj2);262 thisObj.deleteProperty(exec, str2);346 thisObj.put(exec, k, obj2); 347 thisObj.deleteProperty(exec, lk1); 263 348 } 264 349 } else { 265 if (thisObj.hasProperty(exec, str)) {266 thisObj.deleteProperty(exec, str);267 thisObj.put(exec, str2, obj);350 if (thisObj.hasProperty(exec, k)) { 351 thisObj.deleteProperty(exec, k); 352 thisObj.put(exec, lk1, obj); 268 353 } else { 269 354 // why delete something that's not there ? Strange. 270 thisObj.deleteProperty(exec, str);271 thisObj.deleteProperty(exec, str2);355 thisObj.deleteProperty(exec, k); 356 thisObj.deleteProperty(exec, lk1); 272 357 } 273 358 } … … 278 363 case Shift: { 279 364 if (length == 0) { 280 thisObj.put(exec, "length", Number(length), DontEnum | DontDelete);365 thisObj.put(exec, lengthPropertyName, Number(length), DontEnum | DontDelete); 281 366 result = Undefined(); 282 367 } else { 283 result = thisObj.get(exec, "0");368 result = thisObj.get(exec, 0); 284 369 for(unsigned int k = 1; k < length; k++) { 285 UString str = UString::from(k); 286 UString str2 = UString::from(k-1); 287 if (thisObj.hasProperty(exec, str)) { 288 Value obj = thisObj.get(exec, str); 289 thisObj.put(exec, str2, obj); 370 if (thisObj.hasProperty(exec, k)) { 371 Value obj = thisObj.get(exec, k); 372 thisObj.put(exec, k-1, obj); 290 373 } else 291 thisObj.deleteProperty(exec, str2);292 } 293 thisObj.deleteProperty(exec, UString::from(length - 1));294 thisObj.put(exec, "length", Number(length - 1), DontEnum | DontDelete);374 thisObj.deleteProperty(exec, k-1); 375 } 376 thisObj.deleteProperty(exec, length - 1); 377 thisObj.put(exec, lengthPropertyName, Number(length - 1), DontEnum | DontDelete); 295 378 } 296 379 break; … … 319 402 //printf( "Slicing from %d to %d \n", begin, end ); 320 403 for(unsigned int k = 0; k < (unsigned int) end-begin; k++) { 321 UString str = UString::from(k+begin); 322 if (thisObj.hasProperty(exec,str)) { 323 UString str2 = UString::from(k); 324 Value obj = thisObj.get(exec, str); 325 resObj.put(exec, str2, obj); 326 } 327 } 328 resObj.put(exec, "length", Number(end - begin), DontEnum | DontDelete); 404 if (thisObj.hasProperty(exec,k+begin)) { 405 Value obj = thisObj.get(exec, k+begin); 406 resObj.put(exec, k, obj); 407 } 408 } 409 resObj.put(exec, lengthPropertyName, Number(end - begin), DontEnum | DontDelete); 329 410 break; 330 411 } … … 333 414 printf("KJS Array::Sort length=%d\n", length); 334 415 for ( unsigned int i = 0 ; i<length ; ++i ) 335 printf("KJS Array::Sort: %d: %s\n", i, thisObj.get( UString::from(i)).toString().value().ascii() );416 printf("KJS Array::Sort: %d: %s\n", i, thisObj.get(i).toString().value().ascii() ); 336 417 #endif 337 418 Object sortFunction; … … 345 426 346 427 if (length == 0) { 347 thisObj.put(exec, "length", Number(0), DontEnum | DontDelete);428 thisObj.put(exec, lengthPropertyName, Number(0), DontEnum | DontDelete); 348 429 result = Undefined(); 349 430 break; … … 354 435 for ( unsigned int i = 0 ; i<length-1 ; ++i ) 355 436 { 356 Value iObj = thisObj.get(exec, UString::from(i));437 Value iObj = thisObj.get(exec,i); 357 438 unsigned int themin = i; 358 439 Value minObj = iObj; 359 440 for ( unsigned int j = i+1 ; j<length ; ++j ) 360 441 { 361 Value jObj = thisObj.get(exec, UString::from(j));442 Value jObj = thisObj.get(exec,j); 362 443 int cmp; 363 444 if (jObj.type() == UndefinedType) { … … 384 465 { 385 466 //printf("KJS Array::Sort: swapping %d and %d\n", i, themin ); 386 thisObj.put( exec, UString::from(i), minObj );387 thisObj.put( exec, UString::from(themin), iObj );467 thisObj.put( exec, i, minObj ); 468 thisObj.put( exec, themin, iObj ); 388 469 } 389 470 } … … 391 472 printf("KJS Array::Sort -- Resulting array:\n"); 392 473 for ( unsigned int i = 0 ; i<length ; ++i ) 393 printf("KJS Array::Sort: %d: %s\n", i, thisObj.get( UString::from(i)).toString().value().ascii() );474 printf("KJS Array::Sort: %d: %s\n", i, thisObj.get(i).toString().value().ascii() ); 394 475 #endif 395 476 result = thisObj; … … 409 490 //printf( "Splicing from %d, deleteCount=%d \n", begin, deleteCount ); 410 491 for(unsigned int k = 0; k < deleteCount; k++) { 411 UString str = UString::from(k+begin); 412 if (thisObj.hasProperty(exec,str)) { 413 UString str2 = UString::from(k); 414 Value obj = thisObj.get(exec, str); 415 resObj.put(exec, str2, obj); 416 } 417 } 418 resObj.put(exec, "length", Number(deleteCount), DontEnum | DontDelete); 492 if (thisObj.hasProperty(exec,k+begin)) { 493 Value obj = thisObj.get(exec, k+begin); 494 resObj.put(exec, k, obj); 495 } 496 } 497 resObj.put(exec, lengthPropertyName, Number(deleteCount), DontEnum | DontDelete); 419 498 420 499 unsigned int additionalArgs = maxInt( args.size() - 2, 0 ); … … 425 504 for ( unsigned int k = begin; k < length - deleteCount; ++k ) 426 505 { 427 UString str = UString::from(k+deleteCount); 428 UString str2 = UString::from(k+additionalArgs); 429 if (thisObj.hasProperty(exec,str)) { 430 Value obj = thisObj.get(exec, str); 431 thisObj.put(exec, str2, obj); 506 if (thisObj.hasProperty(exec,k+deleteCount)) { 507 Value obj = thisObj.get(exec, k+deleteCount); 508 thisObj.put(exec, k+additionalArgs, obj); 432 509 } 433 510 else 434 thisObj.deleteProperty(exec, str2);511 thisObj.deleteProperty(exec, k+additionalArgs); 435 512 } 436 513 for ( unsigned int k = length ; k > length - deleteCount + additionalArgs; --k ) 437 thisObj.deleteProperty(exec, UString::from(k-1));514 thisObj.deleteProperty(exec, k-1); 438 515 } 439 516 else … … 441 518 for ( unsigned int k = length - deleteCount; (int)k > begin; --k ) 442 519 { 443 UString str = UString::from(k+deleteCount-1); 444 UString str2 = UString::from(k+additionalArgs-1); 445 if (thisObj.hasProperty(exec,str)) { 446 Value obj = thisObj.get(exec, str); 447 thisObj.put(exec, str2, obj); 520 if (thisObj.hasProperty(exec,k+deleteCount-1)) { 521 Value obj = thisObj.get(exec, k+deleteCount-1); 522 thisObj.put(exec, k+additionalArgs-1, obj); 448 523 } 449 524 else 450 thisObj.deleteProperty(exec, str2);525 thisObj.deleteProperty(exec, k+additionalArgs-1); 451 526 } 452 527 } … … 454 529 for ( unsigned int k = 0; k < additionalArgs; ++k ) 455 530 { 456 thisObj.put(exec, UString::from(k+begin), args[k+2]);457 } 458 thisObj.put(exec, "length", Number(length - deleteCount + additionalArgs), DontEnum | DontDelete);531 thisObj.put(exec, k+begin, args[k+2]); 532 } 533 thisObj.put(exec, lengthPropertyName, Number(length - deleteCount + additionalArgs), DontEnum | DontDelete); 459 534 break; 460 535 } … … 463 538 for ( unsigned int k = length; k > 0; --k ) 464 539 { 465 UString str = UString::from(k-1); 466 UString str2 = UString::from(k+nrArgs-1); 467 if (thisObj.hasProperty(exec,str)) { 468 Value obj = thisObj.get(exec, str); 469 thisObj.put(exec, str2, obj); 540 if (thisObj.hasProperty(exec,k-1)) { 541 Value obj = thisObj.get(exec, k-1); 542 thisObj.put(exec, k+nrArgs-1, obj); 470 543 } else { 471 thisObj.deleteProperty(exec, str2);544 thisObj.deleteProperty(exec, k+nrArgs-1); 472 545 } 473 546 } 474 547 for ( unsigned int k = 0; k < nrArgs; ++k ) 475 thisObj.put(exec, UString::from(k), args[k]);548 thisObj.put(exec, k, args[k]); 476 549 result = Number(length + nrArgs); 477 thisObj.put(exec, "length", result, DontEnum | DontDelete);550 thisObj.put(exec, lengthPropertyName, result, DontEnum | DontDelete); 478 551 break; 479 552 } … … 494 567 Value protect(this); 495 568 // ECMA 15.4.3.1 Array.prototype 496 put(exec, "prototype", Object(arrayProto), DontEnum|DontDelete|ReadOnly);569 put(exec,prototypePropertyName, Object(arrayProto), DontEnum|DontDelete|ReadOnly); 497 570 498 571 // no. of arguments for constructor 499 put(exec, "length", Number(1), ReadOnly|DontDelete|DontEnum);572 put(exec,lengthPropertyName, Number(1), ReadOnly|DontDelete|DontEnum); 500 573 } 501 574 … … 508 581 Object ArrayObjectImp::construct(ExecState *exec, const List &args) 509 582 { 510 Object result(new ArrayInstanceImp(exec->interpreter()->builtinArrayPrototype())); 511 512 unsigned int len; 513 ListIterator it = args.begin(); 514 // a single argument might denote the array size 515 if (args.size() == 1 && it->type() == NumberType) 516 len = it->toUInt32(exec); 517 else { 518 // initialize array 519 len = args.size(); 520 for (unsigned int u = 0; it != args.end(); it++, u++) 521 result.put(exec, UString::from(u), *it); 522 } 523 524 // array size 525 result.put(exec, "length", Number(len), DontEnum | DontDelete); 526 static_cast<ArrayInstanceImp*>(result.imp())->putDirect(exec, "length", Number(len), DontEnum | DontDelete); 527 528 return result; 583 // a single numeric argument denotes the array size (!) 584 if (args.size() == 1 && args[0].type() == NumberType) 585 return Object(new ArrayInstanceImp(exec->interpreter()->builtinArrayPrototype(), args[0].toUInt32(exec))); 586 587 // otherwise the array is constructed with the arguments in it 588 return Object(new ArrayInstanceImp(exec->interpreter()->builtinArrayPrototype(), args)); 529 589 } 530 590
Note:
See TracChangeset
for help on using the changeset viewer.