Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: src/array.js

Issue 6223: Make sure that the name accessor on functions return the expected... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/apinatives.js ('k') | src/date-delay.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 if (i != 0) builder.add(separator); 125 if (i != 0) builder.add(separator);
126 if (!IS_UNDEFINED(e) || (i in array)) { 126 if (!IS_UNDEFINED(e) || (i in array)) {
127 builder.add(convert(e)); 127 builder.add(convert(e));
128 } 128 }
129 } 129 }
130 return builder.generate(); 130 return builder.generate();
131 } finally { 131 } finally {
132 // Make sure to pop the visited array no matter what happens. 132 // Make sure to pop the visited array no matter what happens.
133 if (is_array) visited_arrays.pop(); 133 if (is_array) visited_arrays.pop();
134 } 134 }
135 }; 135 }
136 136
137 137
138 function ConvertToString(e) { 138 function ConvertToString(e) {
139 if (e == null) return ''; 139 if (e == null) return '';
140 else return ToString(e); 140 else return ToString(e);
141 }; 141 }
142 142
143 143
144 function ConvertToLocaleString(e) { 144 function ConvertToLocaleString(e) {
145 if (e == null) return ''; 145 if (e == null) return '';
146 else { 146 else {
147 // e_obj's toLocaleString might be overwritten, check if it is a function. 147 // e_obj's toLocaleString might be overwritten, check if it is a function.
148 // Call ToString if toLocaleString is not a function. 148 // Call ToString if toLocaleString is not a function.
149 // See issue 877615. 149 // See issue 877615.
150 var e_obj = ToObject(e); 150 var e_obj = ToObject(e);
151 if (IS_FUNCTION(e_obj.toLocaleString)) 151 if (IS_FUNCTION(e_obj.toLocaleString))
152 return e_obj.toLocaleString(); 152 return e_obj.toLocaleString();
153 else 153 else
154 return ToString(e); 154 return ToString(e);
155 } 155 }
156 }; 156 }
157 157
158 158
159 // This function implements the optimized splice implementation that can use 159 // This function implements the optimized splice implementation that can use
160 // special array operations to handle sparse arrays in a sensible fashion. 160 // special array operations to handle sparse arrays in a sensible fashion.
161 function SmartSlice(array, start_i, del_count, len, deleted_elements) { 161 function SmartSlice(array, start_i, del_count, len, deleted_elements) {
162 // Move deleted elements to a new array (the return value from splice). 162 // Move deleted elements to a new array (the return value from splice).
163 // Intervals array can contain keys and intervals. See comment in Concat. 163 // Intervals array can contain keys and intervals. See comment in Concat.
164 var intervals = %GetArrayKeys(array, start_i + del_count); 164 var intervals = %GetArrayKeys(array, start_i + del_count);
165 var length = intervals.length; 165 var length = intervals.length;
166 for (var k = 0; k < length; k++) { 166 for (var k = 0; k < length; k++) {
(...skipping 22 matching lines...) Expand all
189 // appropriate test. We follow KJS in consulting the 189 // appropriate test. We follow KJS in consulting the
190 // prototype. 190 // prototype.
191 var current = array[key]; 191 var current = array[key];
192 if (!IS_UNDEFINED(current) || key in array) { 192 if (!IS_UNDEFINED(current) || key in array) {
193 deleted_elements[key - start_i] = current; 193 deleted_elements[key - start_i] = current;
194 } 194 }
195 } 195 }
196 } 196 }
197 } 197 }
198 } 198 }
199 }; 199 }
200 200
201 201
202 // This function implements the optimized splice implementation that can use 202 // This function implements the optimized splice implementation that can use
203 // special array operations to handle sparse arrays in a sensible fashion. 203 // special array operations to handle sparse arrays in a sensible fashion.
204 function SmartMove(array, start_i, del_count, len, num_additional_args) { 204 function SmartMove(array, start_i, del_count, len, num_additional_args) {
205 // Move data to new array. 205 // Move data to new array.
206 var new_array = new $Array(len - del_count + num_additional_args); 206 var new_array = new $Array(len - del_count + num_additional_args);
207 var intervals = %GetArrayKeys(array, len); 207 var intervals = %GetArrayKeys(array, len);
208 var length = intervals.length; 208 var length = intervals.length;
209 for (var k = 0; k < length; k++) { 209 for (var k = 0; k < length; k++) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 var current = array[key]; 251 var current = array[key];
252 if (!IS_UNDEFINED(current) || key in array) { 252 if (!IS_UNDEFINED(current) || key in array) {
253 new_array[key - del_count + num_additional_args] = current; 253 new_array[key - del_count + num_additional_args] = current;
254 } 254 }
255 } 255 }
256 } 256 }
257 } 257 }
258 } 258 }
259 // Move contents of new_array into this array 259 // Move contents of new_array into this array
260 %MoveArrayContents(new_array, array); 260 %MoveArrayContents(new_array, array);
261 }; 261 }
262 262
263 263
264 // This is part of the old simple-minded splice. We are using it either 264 // This is part of the old simple-minded splice. We are using it either
265 // because the receiver is not an array (so we have no choice) or because we 265 // because the receiver is not an array (so we have no choice) or because we
266 // know we are not deleting or moving a lot of elements. 266 // know we are not deleting or moving a lot of elements.
267 function SimpleSlice(array, start_i, del_count, len, deleted_elements) { 267 function SimpleSlice(array, start_i, del_count, len, deleted_elements) {
268 for (var i = 0; i < del_count; i++) { 268 for (var i = 0; i < del_count; i++) {
269 var index = start_i + i; 269 var index = start_i + i;
270 // The spec could also be interpreted such that %HasLocalProperty 270 // The spec could also be interpreted such that %HasLocalProperty
271 // would be the appropriate test. We follow KJS in consulting the 271 // would be the appropriate test. We follow KJS in consulting the
272 // prototype. 272 // prototype.
273 var current = array[index]; 273 var current = array[index];
274 if (!IS_UNDEFINED(current) || index in array) 274 if (!IS_UNDEFINED(current) || index in array)
275 deleted_elements[i] = current; 275 deleted_elements[i] = current;
276 } 276 }
277 }; 277 }
278 278
279 279
280 function SimpleMove(array, start_i, del_count, len, num_additional_args) { 280 function SimpleMove(array, start_i, del_count, len, num_additional_args) {
281 if (num_additional_args !== del_count) { 281 if (num_additional_args !== del_count) {
282 // Move the existing elements after the elements to be deleted 282 // Move the existing elements after the elements to be deleted
283 // to the right position in the resulting array. 283 // to the right position in the resulting array.
284 if (num_additional_args > del_count) { 284 if (num_additional_args > del_count) {
285 for (var i = len - del_count; i > start_i; i--) { 285 for (var i = len - del_count; i > start_i; i--) {
286 var from_index = i + del_count - 1; 286 var from_index = i + del_count - 1;
287 var to_index = i + num_additional_args - 1; 287 var to_index = i + num_additional_args - 1;
(...skipping 19 matching lines...) Expand all
307 array[to_index] = current; 307 array[to_index] = current;
308 } else { 308 } else {
309 delete array[to_index]; 309 delete array[to_index];
310 } 310 }
311 } 311 }
312 for (var i = len; i > len - del_count + num_additional_args; i--) { 312 for (var i = len; i > len - del_count + num_additional_args; i--) {
313 delete array[i - 1]; 313 delete array[i - 1];
314 } 314 }
315 } 315 }
316 } 316 }
317 }; 317 }
318 318
319 319
320 // ------------------------------------------------------------------- 320 // -------------------------------------------------------------------
321 321
322 322
323 function ArrayToString() { 323 function ArrayToString() {
324 if (!IS_ARRAY(this)) { 324 if (!IS_ARRAY(this)) {
325 throw new $TypeError('Array.prototype.toString is not generic'); 325 throw new $TypeError('Array.prototype.toString is not generic');
326 } 326 }
327 return Join(this, this.length, ',', ConvertToString); 327 return Join(this, this.length, ',', ConvertToString);
328 }; 328 }
329 329
330 330
331 function ArrayToLocaleString() { 331 function ArrayToLocaleString() {
332 if (!IS_ARRAY(this)) { 332 if (!IS_ARRAY(this)) {
333 throw new $TypeError('Array.prototype.toString is not generic'); 333 throw new $TypeError('Array.prototype.toString is not generic');
334 } 334 }
335 return Join(this, this.length, ',', ConvertToLocaleString); 335 return Join(this, this.length, ',', ConvertToLocaleString);
336 }; 336 }
337 337
338 338
339 function ArrayJoin(separator) { 339 function ArrayJoin(separator) {
340 if (IS_UNDEFINED(separator)) separator = ','; 340 if (IS_UNDEFINED(separator)) separator = ',';
341 else separator = ToString(separator); 341 else separator = ToString(separator);
342 return Join(this, ToUint32(this.length), separator, ConvertToString); 342 return Join(this, ToUint32(this.length), separator, ConvertToString);
343 }; 343 }
344 344
345 345
346 // Removes the last element from the array and returns it. See 346 // Removes the last element from the array and returns it. See
347 // ECMA-262, section 15.4.4.6. 347 // ECMA-262, section 15.4.4.6.
348 function ArrayPop() { 348 function ArrayPop() {
349 var n = ToUint32(this.length); 349 var n = ToUint32(this.length);
350 if (n == 0) { 350 if (n == 0) {
351 this.length = n; 351 this.length = n;
352 return; 352 return;
353 } 353 }
354 n--; 354 n--;
355 var value = this[n]; 355 var value = this[n];
356 this.length = n; 356 this.length = n;
357 delete this[n]; 357 delete this[n];
358 return value; 358 return value;
359 }; 359 }
360 360
361 361
362 // Appends the arguments to the end of the array and returns the new 362 // Appends the arguments to the end of the array and returns the new
363 // length of the array. See ECMA-262, section 15.4.4.7. 363 // length of the array. See ECMA-262, section 15.4.4.7.
364 function ArrayPush() { 364 function ArrayPush() {
365 var n = ToUint32(this.length); 365 var n = ToUint32(this.length);
366 var m = %_ArgumentsLength(); 366 var m = %_ArgumentsLength();
367 for (var i = 0; i < m; i++) { 367 for (var i = 0; i < m; i++) {
368 this[i+n] = %_Arguments(i); 368 this[i+n] = %_Arguments(i);
369 } 369 }
370 this.length = n + m; 370 this.length = n + m;
371 return this.length; 371 return this.length;
372 }; 372 }
373 373
374 374
375 function ArrayConcat(arg1) { // length == 1 375 function ArrayConcat(arg1) { // length == 1
376 var arg_number = 0, arg_count = %_ArgumentsLength(); 376 var arg_number = 0, arg_count = %_ArgumentsLength();
377 var n = 0; 377 var n = 0;
378 378
379 var A = $Array(1 + arg_count); 379 var A = $Array(1 + arg_count);
380 var E = this; 380 var E = this;
381 381
382 while (true) { 382 while (true) {
(...skipping 25 matching lines...) Expand all
408 n += E.length; 408 n += E.length;
409 } else { 409 } else {
410 A[n++] = E; 410 A[n++] = E;
411 } 411 }
412 if (arg_number == arg_count) break; 412 if (arg_number == arg_count) break;
413 E = %_Arguments(arg_number++); 413 E = %_Arguments(arg_number++);
414 } 414 }
415 415
416 A.length = n; // may contain empty arrays 416 A.length = n; // may contain empty arrays
417 return A; 417 return A;
418 }; 418 }
419 419
420 420
421 // For implementing reverse() on large, sparse arrays. 421 // For implementing reverse() on large, sparse arrays.
422 function SparseReverse(array, len) { 422 function SparseReverse(array, len) {
423 var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len)); 423 var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
424 var high_counter = keys.length - 1; 424 var high_counter = keys.length - 1;
425 var low_counter = 0; 425 var low_counter = 0;
426 while (low_counter <= high_counter) { 426 while (low_counter <= high_counter) {
427 var i = keys[low_counter]; 427 var i = keys[low_counter];
428 var j = keys[high_counter]; 428 var j = keys[high_counter];
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 } 483 }
484 } else { 484 } else {
485 var current_j = this[j]; 485 var current_j = this[j];
486 if (!IS_UNDEFINED(current_j) || j in this) { 486 if (!IS_UNDEFINED(current_j) || j in this) {
487 this[i] = current_j; 487 this[i] = current_j;
488 delete this[j]; 488 delete this[j];
489 } 489 }
490 } 490 }
491 } 491 }
492 return this; 492 return this;
493 }; 493 }
494 494
495 495
496 function ArrayShift() { 496 function ArrayShift() {
497 var len = ToUint32(this.length); 497 var len = ToUint32(this.length);
498 498
499 if (len === 0) { 499 if (len === 0) {
500 this.length = 0; 500 this.length = 0;
501 return; 501 return;
502 } 502 }
503 503
504 var first = this[0]; 504 var first = this[0];
505 505
506 if (IS_ARRAY(this)) 506 if (IS_ARRAY(this))
507 SmartMove(this, 0, 1, len, 0); 507 SmartMove(this, 0, 1, len, 0);
508 else 508 else
509 SimpleMove(this, 0, 1, len, 0); 509 SimpleMove(this, 0, 1, len, 0);
510 510
511 this.length = len - 1; 511 this.length = len - 1;
512 512
513 return first; 513 return first;
514 }; 514 }
515 515
516 516
517 function ArrayUnshift(arg1) { // length == 1 517 function ArrayUnshift(arg1) { // length == 1
518 var len = ToUint32(this.length); 518 var len = ToUint32(this.length);
519 var num_arguments = %_ArgumentsLength(); 519 var num_arguments = %_ArgumentsLength();
520 520
521 if (IS_ARRAY(this)) 521 if (IS_ARRAY(this))
522 SmartMove(this, 0, 0, len, num_arguments); 522 SmartMove(this, 0, 0, len, num_arguments);
523 else 523 else
524 SimpleMove(this, 0, 0, len, num_arguments); 524 SimpleMove(this, 0, 0, len, num_arguments);
525 525
526 for (var i = 0; i < num_arguments; i++) { 526 for (var i = 0; i < num_arguments; i++) {
527 this[i] = %_Arguments(i); 527 this[i] = %_Arguments(i);
528 } 528 }
529 529
530 this.length = len + num_arguments; 530 this.length = len + num_arguments;
531 531
532 return len + num_arguments; 532 return len + num_arguments;
533 }; 533 }
534 534
535 535
536 function ArraySlice(start, end) { 536 function ArraySlice(start, end) {
537 var len = ToUint32(this.length); 537 var len = ToUint32(this.length);
538 var start_i = TO_INTEGER(start); 538 var start_i = TO_INTEGER(start);
539 var end_i = len; 539 var end_i = len;
540 540
541 if (end !== void 0) end_i = TO_INTEGER(end); 541 if (end !== void 0) end_i = TO_INTEGER(end);
542 542
543 if (start_i < 0) { 543 if (start_i < 0) {
544 start_i += len; 544 start_i += len;
545 if (start_i < 0) start_i = 0; 545 if (start_i < 0) start_i = 0;
546 } else { 546 } else {
547 if (start_i > len) start_i = len; 547 if (start_i > len) start_i = len;
548 } 548 }
549 549
550 if (end_i < 0) { 550 if (end_i < 0) {
551 end_i += len; 551 end_i += len;
552 if (end_i < 0) end_i = 0; 552 if (end_i < 0) end_i = 0;
553 } else { 553 } else {
554 if (end_i > len) end_i = len; 554 if (end_i > len) end_i = len;
555 } 555 }
556 556
557 var result = []; 557 var result = [];
558 558
559 if (end_i < start_i) 559 if (end_i < start_i) return result;
560 return result; 560
561 561 if (IS_ARRAY(this)) {
562 if (IS_ARRAY(this))
563 SmartSlice(this, start_i, end_i - start_i, len, result); 562 SmartSlice(this, start_i, end_i - start_i, len, result);
564 else 563 } else {
565 SimpleSlice(this, start_i, end_i - start_i, len, result); 564 SimpleSlice(this, start_i, end_i - start_i, len, result);
566 565 }
566
567 result.length = end_i - start_i; 567 result.length = end_i - start_i;
568 568
569 return result; 569 return result;
570 }; 570 }
571 571
572 572
573 function ArraySplice(start, delete_count) { 573 function ArraySplice(start, delete_count) {
574 var num_arguments = %_ArgumentsLength(); 574 var num_arguments = %_ArgumentsLength();
575 575
576 // SpiderMonkey and KJS return undefined in the case where no 576 // SpiderMonkey and KJS return undefined in the case where no
577 // arguments are given instead of using the implicit undefined 577 // arguments are given instead of using the implicit undefined
578 // arguments. This does not follow ECMA-262, but we do the same for 578 // arguments. This does not follow ECMA-262, but we do the same for
579 // compatibility. 579 // compatibility.
580 if (num_arguments == 0) return; 580 if (num_arguments == 0) return;
581 581
582 var len = ToUint32(this.length); 582 var len = ToUint32(this.length);
583 var start_i = TO_INTEGER(start); 583 var start_i = TO_INTEGER(start);
584 584
585 if (start_i < 0) { 585 if (start_i < 0) {
586 start_i += len; 586 start_i += len;
587 if (start_i < 0) start_i = 0; 587 if (start_i < 0) start_i = 0;
588 } else { 588 } else {
589 if (start_i > len) start_i = len; 589 if (start_i > len) start_i = len;
590 } 590 }
591 591
592 // SpiderMonkey and KJS treat the case where no delete count is 592 // SpiderMonkey and KJS treat the case where no delete count is
593 // given differently from when an undefined delete count is given. 593 // given differently from when an undefined delete count is given.
594 // This does not follow ECMA-262, but we do the same for 594 // This does not follow ECMA-262, but we do the same for
595 // compatibility. 595 // compatibility.
596 var del_count = 0; 596 var del_count = 0;
597 if (num_arguments > 1) { 597 if (num_arguments > 1) {
598 del_count = TO_INTEGER(delete_count); 598 del_count = TO_INTEGER(delete_count);
599 if (del_count < 0) del_count = 0; 599 if (del_count < 0) del_count = 0;
600 if (del_count > len - start_i) del_count = len - start_i; 600 if (del_count > len - start_i) del_count = len - start_i;
601 } else { 601 } else {
602 del_count = len - start_i; 602 del_count = len - start_i;
603 } 603 }
604 604
605 var deleted_elements = []; 605 var deleted_elements = [];
606 deleted_elements.length = del_count; 606 deleted_elements.length = del_count;
607 607
608 // Number of elements to add. 608 // Number of elements to add.
609 var num_additional_args = 0; 609 var num_additional_args = 0;
610 if (num_arguments > 2) { 610 if (num_arguments > 2) {
611 num_additional_args = num_arguments - 2; 611 num_additional_args = num_arguments - 2;
612 } 612 }
613 613
614 var use_simple_splice = true; 614 var use_simple_splice = true;
615 615
616 if (IS_ARRAY(this) && num_additional_args !== del_count) { 616 if (IS_ARRAY(this) && num_additional_args !== del_count) {
617 // If we are only deleting/moving a few things near the end of the 617 // If we are only deleting/moving a few things near the end of the
618 // array then the simple version is going to be faster, because it 618 // array then the simple version is going to be faster, because it
619 // doesn't touch most of the array. 619 // doesn't touch most of the array.
620 var estimated_non_hole_elements = %EstimateNumberOfElements(this); 620 var estimated_non_hole_elements = %EstimateNumberOfElements(this);
621 if (len > 20 && (estimated_non_hole_elements >> 2) < (len - start_i)) { 621 if (len > 20 && (estimated_non_hole_elements >> 2) < (len - start_i)) {
622 use_simple_splice = false; 622 use_simple_splice = false;
623 } 623 }
624 } 624 }
625 625
626 if (use_simple_splice) { 626 if (use_simple_splice) {
627 SimpleSlice(this, start_i, del_count, len, deleted_elements); 627 SimpleSlice(this, start_i, del_count, len, deleted_elements);
628 SimpleMove(this, start_i, del_count, len, num_additional_args); 628 SimpleMove(this, start_i, del_count, len, num_additional_args);
629 } else { 629 } else {
630 SmartSlice(this, start_i, del_count, len, deleted_elements); 630 SmartSlice(this, start_i, del_count, len, deleted_elements);
631 SmartMove(this, start_i, del_count, len, num_additional_args); 631 SmartMove(this, start_i, del_count, len, num_additional_args);
632 } 632 }
633 633
634 // Insert the arguments into the resulting array in 634 // Insert the arguments into the resulting array in
635 // place of the deleted elements. 635 // place of the deleted elements.
636 var i = start_i; 636 var i = start_i;
637 var arguments_index = 2; 637 var arguments_index = 2;
638 var arguments_length = %_ArgumentsLength(); 638 var arguments_length = %_ArgumentsLength();
639 while (arguments_index < arguments_length) { 639 while (arguments_index < arguments_length) {
640 this[i++] = %_Arguments(arguments_index++); 640 this[i++] = %_Arguments(arguments_index++);
641 } 641 }
642 this.length = len - del_count + num_additional_args; 642 this.length = len - del_count + num_additional_args;
643 643
644 // Return the deleted elements. 644 // Return the deleted elements.
645 return deleted_elements; 645 return deleted_elements;
646 }; 646 }
647 647
648 648
649 function ArraySort(comparefn) { 649 function ArraySort(comparefn) {
650 // In-place QuickSort algorithm. 650 // In-place QuickSort algorithm.
651 // For short (length <= 22) arrays, insertion sort is used for efficiency. 651 // For short (length <= 22) arrays, insertion sort is used for efficiency.
652 652
653 var custom_compare = IS_FUNCTION(comparefn); 653 var custom_compare = IS_FUNCTION(comparefn);
654 654
655 function Compare(x,y) { 655 function Compare(x,y) {
656 if (custom_compare) { 656 if (custom_compare) {
657 return comparefn.call(null, x, y); 657 return comparefn.call(null, x, y);
658 } 658 }
659 if (%_IsSmi(x) && %_IsSmi(y)) { 659 if (%_IsSmi(x) && %_IsSmi(y)) {
660 return %SmiLexicographicCompare(x, y); 660 return %SmiLexicographicCompare(x, y);
661 } 661 }
662 x = ToString(x); 662 x = ToString(x);
663 y = ToString(y); 663 y = ToString(y);
664 if (x == y) return 0; 664 if (x == y) return 0;
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
753 753
754 // We only changed the length of the this object (in 754 // We only changed the length of the this object (in
755 // RemoveArrayHoles) if it was an array. We are not allowed to set 755 // RemoveArrayHoles) if it was an array. We are not allowed to set
756 // the length of the this object if it is not an array because this 756 // the length of the this object if it is not an array because this
757 // might introduce a new length property. 757 // might introduce a new length property.
758 if (IS_ARRAY(this)) { 758 if (IS_ARRAY(this)) {
759 this.length = old_length; 759 this.length = old_length;
760 } 760 }
761 761
762 return this; 762 return this;
763 }; 763 }
764 764
765 765
766 // The following functions cannot be made efficient on sparse arrays while 766 // The following functions cannot be made efficient on sparse arrays while
767 // preserving the semantics, since the calls to the receiver function can add 767 // preserving the semantics, since the calls to the receiver function can add
768 // or delete elements from the array. 768 // or delete elements from the array.
769
770 function ArrayFilter(f, receiver) { 769 function ArrayFilter(f, receiver) {
771 if (!IS_FUNCTION(f)) { 770 if (!IS_FUNCTION(f)) {
772 throw MakeTypeError('called_non_callable', [ f ]); 771 throw MakeTypeError('called_non_callable', [ f ]);
773 } 772 }
774 // Pull out the length so that modifications to the length in the 773 // Pull out the length so that modifications to the length in the
775 // loop will not affect the looping. 774 // loop will not affect the looping.
776 var length = this.length; 775 var length = this.length;
777 var result = []; 776 var result = [];
778 for (var i = 0; i < length; i++) { 777 for (var i = 0; i < length; i++) {
779 var current = this[i]; 778 var current = this[i];
780 if (!IS_UNDEFINED(current) || i in this) { 779 if (!IS_UNDEFINED(current) || i in this) {
781 if (f.call(receiver, current, i, this)) result.push(current); 780 if (f.call(receiver, current, i, this)) result.push(current);
782 } 781 }
783 } 782 }
784 return result; 783 return result;
785 }; 784 }
786 785
787 786
788 function ArrayForEach(f, receiver) { 787 function ArrayForEach(f, receiver) {
789 if (!IS_FUNCTION(f)) { 788 if (!IS_FUNCTION(f)) {
790 throw MakeTypeError('called_non_callable', [ f ]); 789 throw MakeTypeError('called_non_callable', [ f ]);
791 } 790 }
792 // Pull out the length so that modifications to the length in the 791 // Pull out the length so that modifications to the length in the
793 // loop will not affect the looping. 792 // loop will not affect the looping.
794 var length = this.length; 793 var length = this.length;
795 for (var i = 0; i < length; i++) { 794 for (var i = 0; i < length; i++) {
796 var current = this[i]; 795 var current = this[i];
797 if (!IS_UNDEFINED(current) || i in this) { 796 if (!IS_UNDEFINED(current) || i in this) {
798 f.call(receiver, current, i, this); 797 f.call(receiver, current, i, this);
799 } 798 }
800 } 799 }
801 }; 800 }
802 801
803 802
804 // Executes the function once for each element present in the 803 // Executes the function once for each element present in the
805 // array until it finds one where callback returns true. 804 // array until it finds one where callback returns true.
806 function ArraySome(f, receiver) { 805 function ArraySome(f, receiver) {
807 if (!IS_FUNCTION(f)) { 806 if (!IS_FUNCTION(f)) {
808 throw MakeTypeError('called_non_callable', [ f ]); 807 throw MakeTypeError('called_non_callable', [ f ]);
809 } 808 }
810 // Pull out the length so that modifications to the length in the 809 // Pull out the length so that modifications to the length in the
811 // loop will not affect the looping. 810 // loop will not affect the looping.
812 var length = this.length; 811 var length = this.length;
813 for (var i = 0; i < length; i++) { 812 for (var i = 0; i < length; i++) {
814 var current = this[i]; 813 var current = this[i];
815 if (!IS_UNDEFINED(current) || i in this) { 814 if (!IS_UNDEFINED(current) || i in this) {
816 if (f.call(receiver, current, i, this)) return true; 815 if (f.call(receiver, current, i, this)) return true;
817 } 816 }
818 } 817 }
819 return false; 818 return false;
820 }; 819 }
821 820
822 821
823 function ArrayEvery(f, receiver) { 822 function ArrayEvery(f, receiver) {
824 if (!IS_FUNCTION(f)) { 823 if (!IS_FUNCTION(f)) {
825 throw MakeTypeError('called_non_callable', [ f ]); 824 throw MakeTypeError('called_non_callable', [ f ]);
826 } 825 }
827 // Pull out the length so that modifications to the length in the 826 // Pull out the length so that modifications to the length in the
828 // loop will not affect the looping. 827 // loop will not affect the looping.
829 var length = this.length; 828 var length = this.length;
830 for (var i = 0; i < length; i++) { 829 for (var i = 0; i < length; i++) {
831 var current = this[i]; 830 var current = this[i];
832 if (!IS_UNDEFINED(current) || i in this) { 831 if (!IS_UNDEFINED(current) || i in this) {
833 if (!f.call(receiver, current, i, this)) return false; 832 if (!f.call(receiver, current, i, this)) return false;
834 } 833 }
835 } 834 }
836 835
837 return true; 836 return true;
838 }; 837 }
839 838
840 839
841 function ArrayMap(f, receiver) { 840 function ArrayMap(f, receiver) {
842 if (!IS_FUNCTION(f)) { 841 if (!IS_FUNCTION(f)) {
843 throw MakeTypeError('called_non_callable', [ f ]); 842 throw MakeTypeError('called_non_callable', [ f ]);
844 } 843 }
845 // Pull out the length so that modifications to the length in the 844 // Pull out the length so that modifications to the length in the
846 // loop will not affect the looping. 845 // loop will not affect the looping.
847 var length = this.length; 846 var length = this.length;
848 var result = new $Array(length); 847 var result = new $Array(length);
849 for (var i = 0; i < length; i++) { 848 for (var i = 0; i < length; i++) {
850 var current = this[i]; 849 var current = this[i];
851 if (!IS_UNDEFINED(current) || i in this) { 850 if (!IS_UNDEFINED(current) || i in this) {
852 result[i] = f.call(receiver, current, i, this); 851 result[i] = f.call(receiver, current, i, this);
853 } 852 }
854 } 853 }
855 return result; 854 return result;
856 }; 855 }
857 856
858 857
859 function ArrayIndexOf(element, index) { 858 function ArrayIndexOf(element, index) {
860 var length = this.length; 859 var length = this.length;
861 if (index == null) { 860 if (index == null) {
862 index = 0; 861 index = 0;
863 } else { 862 } else {
864 index = TO_INTEGER(index); 863 index = TO_INTEGER(index);
865 // If index is negative, index from the end of the array. 864 // If index is negative, index from the end of the array.
866 if (index < 0) index = length + index; 865 if (index < 0) index = length + index;
867 // If index is still negative, search the entire array. 866 // If index is still negative, search the entire array.
868 if (index < 0) index = 0; 867 if (index < 0) index = 0;
869 } 868 }
870 // Lookup through the array. 869 // Lookup through the array.
871 for (var i = index; i < length; i++) { 870 for (var i = index; i < length; i++) {
872 var current = this[i]; 871 var current = this[i];
873 if (!IS_UNDEFINED(current) || i in this) { 872 if (!IS_UNDEFINED(current) || i in this) {
874 if (current === element) return i; 873 if (current === element) return i;
875 } 874 }
876 } 875 }
877 return -1; 876 return -1;
878 }; 877 }
879 878
880 879
881 function ArrayLastIndexOf(element, index) { 880 function ArrayLastIndexOf(element, index) {
882 var length = this.length; 881 var length = this.length;
883 if (index == null) { 882 if (index == null) {
884 index = length - 1; 883 index = length - 1;
885 } else { 884 } else {
886 index = TO_INTEGER(index); 885 index = TO_INTEGER(index);
887 // If index is negative, index from end of the array. 886 // If index is negative, index from end of the array.
888 if (index < 0) index = length + index; 887 if (index < 0) index = length + index;
889 // If index is still negative, do not search the array. 888 // If index is still negative, do not search the array.
890 if (index < 0) index = -1; 889 if (index < 0) index = -1;
891 else if (index >= length) index = length - 1; 890 else if (index >= length) index = length - 1;
892 } 891 }
893 // Lookup through the array. 892 // Lookup through the array.
894 for (var i = index; i >= 0; i--) { 893 for (var i = index; i >= 0; i--) {
895 var current = this[i]; 894 var current = this[i];
896 if (!IS_UNDEFINED(current) || i in this) { 895 if (!IS_UNDEFINED(current) || i in this) {
897 if (current === element) return i; 896 if (current === element) return i;
898 } 897 }
899 } 898 }
900 return -1; 899 return -1;
901 }; 900 }
902 901
903 902
904 // ------------------------------------------------------------------- 903 // -------------------------------------------------------------------
905 904
906 function InstallProperties(prototype, attributes, properties) { 905 function InstallFunctions(prototype, attributes, functions) {
907 for (var key in properties) { 906 for (var i = 0; i < functions.length; i += 2) {
908 %AddProperty(prototype, key, properties[key], attributes); 907 var key = functions[i];
908 var f = functions[i + 1];
909 %FunctionSetName(f, key);
910 %AddProperty(prototype, key, f, attributes);
909 } 911 }
910 }; 912 }
911 913
912 914
913 function UpdateFunctionLengths(lengths) { 915 function UpdateFunctionLengths(lengths) {
914 for (var key in lengths) { 916 for (var key in lengths) {
915 %FunctionSetLength(this[key], lengths[key]); 917 %FunctionSetLength(this[key], lengths[key]);
916 } 918 }
917 }; 919 }
918 920
919 921
920 // ------------------------------------------------------------------- 922 // -------------------------------------------------------------------
921 923
922 function SetupArray() { 924 function SetupArray() {
923 // Setup non-enumerable properties of the Array.prototype object. 925 // Setup non-enumerable constructor property on the Array.prototype
924 InstallProperties($Array.prototype, DONT_ENUM, { 926 // object.
925 constructor: $Array, 927 %AddProperty($Array.prototype, "constructor", $Array, DONT_ENUM);
926 toString: ArrayToString, 928
927 toLocaleString: ArrayToLocaleString, 929 // Setup non-enumerable functions of the Array.prototype object and
928 join: ArrayJoin, 930 // set their names.
929 pop: ArrayPop, 931 InstallFunctions($Array.prototype, DONT_ENUM, $Array(
930 push: ArrayPush, 932 "toString", ArrayToString,
931 concat: ArrayConcat, 933 "toLocaleString", ArrayToLocaleString,
932 reverse: ArrayReverse, 934 "join", ArrayJoin,
933 shift: ArrayShift, 935 "pop", ArrayPop,
934 unshift: ArrayUnshift, 936 "push", ArrayPush,
935 slice: ArraySlice, 937 "concat", ArrayConcat,
936 splice: ArraySplice, 938 "reverse", ArrayReverse,
937 sort: ArraySort, 939 "shift", ArrayShift,
938 filter: ArrayFilter, 940 "unshift", ArrayUnshift,
939 forEach: ArrayForEach, 941 "slice", ArraySlice,
940 some: ArraySome, 942 "splice", ArraySplice,
941 every: ArrayEvery, 943 "sort", ArraySort,
942 map: ArrayMap, 944 "filter", ArrayFilter,
943 indexOf: ArrayIndexOf, 945 "forEach", ArrayForEach,
944 lastIndexOf: ArrayLastIndexOf 946 "some", ArraySome,
945 }); 947 "every", ArrayEvery,
948 "map", ArrayMap,
949 "indexOf", ArrayIndexOf,
950 "lastIndexOf", ArrayLastIndexOf
951 ));
946 952
947 // Manipulate the length of some of the functions to meet 953 // Manipulate the length of some of the functions to meet
948 // expectations set by ECMA-262 or Mozilla. 954 // expectations set by ECMA-262 or Mozilla.
949 UpdateFunctionLengths({ 955 UpdateFunctionLengths({
950 ArrayFilter: 1, 956 ArrayFilter: 1,
951 ArrayForEach: 1, 957 ArrayForEach: 1,
952 ArraySome: 1, 958 ArraySome: 1,
953 ArrayEvery: 1, 959 ArrayEvery: 1,
954 ArrayMap: 1, 960 ArrayMap: 1,
955 ArrayIndexOf: 1, 961 ArrayIndexOf: 1,
956 ArrayLastIndexOf: 1, 962 ArrayLastIndexOf: 1,
957 ArrayPush: 1 963 ArrayPush: 1
958 }); 964 });
959 }; 965 }
960 966
961 967
962 SetupArray(); 968 SetupArray();
OLDNEW
« no previous file with comments | « src/apinatives.js ('k') | src/date-delay.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698