| Index: src/array.js
|
| ===================================================================
|
| --- src/array.js (revision 2131)
|
| +++ src/array.js (working copy)
|
| @@ -769,6 +769,63 @@
|
| }
|
| }
|
|
|
| + function SafeRemoveArrayHoles(obj) {
|
| + // Copy defined elements from the end to fill in all holes and undefineds
|
| + // in the beginning of the array. Write undefineds and holes at the end
|
| + // after loop is finished.
|
| + var first_undefined = 0;
|
| + var last_defined = length - 1;
|
| + var num_holes = 0;
|
| + while (first_undefined < last_defined) {
|
| + // Find first undefined element.
|
| + while (first_undefined < last_defined &&
|
| + !IS_UNDEFINED(obj[first_undefined])) {
|
| + first_undefined++;
|
| + }
|
| + // Maintain the invariant num_holes = the number of holes in the original
|
| + // array with indices <= first_undefined or > last_defined.
|
| + if (!obj.hasOwnProperty(first_undefined)) {
|
| + num_holes++;
|
| + }
|
| +
|
| + // Find last defined element.
|
| + while (first_undefined < last_defined &&
|
| + IS_UNDEFINED(obj[last_defined])) {
|
| + if (!obj.hasOwnProperty(last_defined)) {
|
| + num_holes++;
|
| + }
|
| + last_defined--;
|
| + }
|
| + if (first_undefined < last_defined) {
|
| + // Fill in hole or undefined.
|
| + obj[first_undefined] = obj[last_defined];
|
| + obj[last_defined] = void 0;
|
| + }
|
| + }
|
| + // If there were any undefineds in the entire array, first_undefined
|
| + // points to one past the last defined element. Make this true if
|
| + // there were no undefineds, as well, so that first_undefined == number
|
| + // of defined elements.
|
| + if (!IS_UNDEFINED(obj[first_undefined])) first_undefined++;
|
| + // Fill in the undefineds and the holes. There may be a hole where
|
| + // an undefined should be and vice versa.
|
| + var i;
|
| + for (i = first_undefined; i < length - num_holes; i++) {
|
| + obj[i] = void 0;
|
| + }
|
| + for (i = length - num_holes; i < length; i++) {
|
| + // For compatability with Webkit, do not expose elements in the prototype.
|
| + if (i in obj.__proto__) {
|
| + obj[i] = void 0;
|
| + } else {
|
| + delete obj[i];
|
| + }
|
| + }
|
| +
|
| + // Return the number of defined elements.
|
| + return first_undefined;
|
| + }
|
| +
|
| var length = ToUint32(this.length);
|
| if (length < 2) return this;
|
|
|
| @@ -787,6 +844,12 @@
|
| }
|
|
|
| var num_non_undefined = %RemoveArrayHoles(this, length);
|
| + if (num_non_undefined == -1) {
|
| + // There were indexed accessors in the array. Move array holes and
|
| + // undefineds to the end using a Javascript function that is safe
|
| + // in the presence of accessors.
|
| + num_non_undefined = SafeRemoveArrayHoles(this);
|
| + }
|
|
|
| QuickSort(this, 0, num_non_undefined);
|
|
|
|
|