Index: src/array.js |
diff --git a/src/array.js b/src/array.js |
index c01c0c81333f7336ca4b89b4c772e34e9f8eef95..22885bcdad6bba2e86e9469df0ff30c8bd877dba 100644 |
--- a/src/array.js |
+++ b/src/array.js |
@@ -709,13 +709,94 @@ function ArraySort(comparefn) { |
QuickSort(a, high_start, to); |
} |
+ // Copies elements in the range 0..length from obj's prototype chain |
+ // to obj itself, if obj has holes. Returns one more than the maximal index |
+ // of a prototype property. |
+ function CopyFromPrototype(obj, length) { |
+ var max = 0; |
+ for (var o = obj.__proto__; o; o = o.__proto__) { |
Erik Corry
2009/05/01 09:58:55
Can't we call o proto or something? These 1-lette
|
+ var indices = %GetArrayKeys(o, length); |
+ if (indices.length > 0) { |
+ if (indices[0] == -1) { |
+ // It's an interval |
Erik Corry
2009/05/01 09:58:55
Missing full stop.
|
+ var proto_length = indices[1]; |
+ for (var i = 0; i < proto_length; i++) { |
+ if (!obj.hasOwnProperty(i) && o.hasOwnProperty(i)) { |
+ obj[i] = o[i]; |
+ if (i >= max) { max = i + 1; } |
+ } |
+ } |
+ } else { |
+ for (var i = 0; i < indices.length; i++) { |
+ var index = indices[i]; |
+ if (!IS_UNDEFINED(index) && |
+ !obj.hasOwnProperty(index) && o.hasOwnProperty(index)) { |
+ obj[index] = o[index]; |
+ if (index >= max) { max = index + 1; } |
+ } |
+ } |
+ } |
+ } |
+ } |
+ return max; |
+ } |
+ |
+ // Set a value of "undefined" on all indices in the range from..to |
+ // where a prototype of obj has an element. I.e., shadow all prototype |
+ // elements in that range. |
+ function ShadowPrototypeElements(obj, from, to) { |
+ for (var o = obj.__proto__; o; o = o.__proto__) { |
Erik Corry
2009/05/01 09:58:55
And here.
|
+ var indices = %GetArrayKeys(o, to); |
+ if (indices.length > 0) { |
+ if (indices[0] == -1) { |
+ // It's an interval |
Erik Corry
2009/05/01 09:58:55
And here.
|
+ var proto_length = indices[1]; |
+ if (proto_length > from) { |
Erik Corry
2009/05/01 09:58:55
>= perhaps?
Lasse Reichstein
2009/05/01 10:05:39
Wouldn't make a difference. The next line is a loo
|
+ for (var i = from; i < proto_length; i++) { |
+ if (o.hasOwnProperty(i)) { |
+ obj[i] = void 0; |
+ } |
+ } |
+ } |
+ } else { |
+ for (var i = 0; i < indices.length; i++) { |
+ var index = indices[i]; |
+ if (!IS_UNDEFINED(index) && from <= index && |
+ o.hasOwnProperty(index)) { |
+ obj[index] = void 0; |
+ } |
+ } |
+ } |
+ } |
+ } |
+ } |
+ |
var length = ToUint32(this.length); |
if (length < 2) return this; |
+ var is_array = IS_ARRAY(this); |
+ if (!is_array) { |
+ // For compatibility with JSC, we also sort elements inherited from |
+ // the prototype chain on non-Array objects. |
+ // We do this by copying them to this object and sorting only |
+ // local elements. This is not very efficient, but sorting with |
+ // inherited elements happens very, very rarely, if at all. |
+ // The specification allows "implementation dependent" behavior |
+ // if an element on the prototype chain has an element that |
+ // might interact with sorting. |
+ var max_prototype_element = CopyFromPrototype(this, length); |
Erik Corry
2009/05/01 09:58:55
I think the var declaration should be hoisted out
|
+ } |
+ |
var num_non_undefined = %RemoveArrayHoles(this, length); |
QuickSort(this, 0, num_non_undefined); |
+ if (!is_array && (num_non_undefined + 1 < max_prototype_element)) { |
+ // For compatibility with JSC, we shadow any elements in the prototype |
+ // chain that has become exposed by sort moving a hole to its position. |
+ ShadowPrototypeElements(this, num_non_undefined, max_prototype_element); |
+ } |
+ |
return this; |
} |