summaryrefslogtreecommitdiff
path: root/deps/v8/src/array.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/array.js')
-rw-r--r--deps/v8/src/array.js167
1 files changed, 142 insertions, 25 deletions
diff --git a/deps/v8/src/array.js b/deps/v8/src/array.js
index d30a98960..ed84b5f72 100644
--- a/deps/v8/src/array.js
+++ b/deps/v8/src/array.js
@@ -709,32 +709,91 @@ function ArraySort(comparefn) {
QuickSort(a, high_start, to);
}
- var old_length = ToUint32(this.length);
- if (old_length < 2) return this;
+ // 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 proto = obj.__proto__; proto; proto = proto.__proto__) {
+ var indices = %GetArrayKeys(proto, length);
+ if (indices.length > 0) {
+ if (indices[0] == -1) {
+ // It's an interval.
+ var proto_length = indices[1];
+ for (var i = 0; i < proto_length; i++) {
+ if (!obj.hasOwnProperty(i) && proto.hasOwnProperty(i)) {
+ obj[i] = proto[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) && proto.hasOwnProperty(index)) {
+ obj[index] = proto[index];
+ if (index >= max) { max = index + 1; }
+ }
+ }
+ }
+ }
+ }
+ return max;
+ }
- %RemoveArrayHoles(this);
+ // 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 proto = obj.__proto__; proto; proto = proto.__proto__) {
+ var indices = %GetArrayKeys(proto, to);
+ if (indices.length > 0) {
+ if (indices[0] == -1) {
+ // It's an interval.
+ var proto_length = indices[1];
+ for (var i = from; i < proto_length; i++) {
+ if (proto.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 &&
+ proto.hasOwnProperty(index)) {
+ obj[index] = void 0;
+ }
+ }
+ }
+ }
+ }
+ }
var length = ToUint32(this.length);
-
- // Move undefined elements to the end of the array.
- for (var i = 0; i < length; ) {
- if (IS_UNDEFINED(this[i])) {
- length--;
- this[i] = this[length];
- this[length] = void 0;
- } else {
- i++;
- }
+ if (length < 2) return this;
+
+ var is_array = IS_ARRAY(this);
+ var max_prototype_element;
+ 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.
+ max_prototype_element = CopyFromPrototype(this, length);
}
- QuickSort(this, 0, length);
+ var num_non_undefined = %RemoveArrayHoles(this, length);
- // We only changed the length of the this object (in
- // RemoveArrayHoles) if it was an array. We are not allowed to set
- // the length of the this object if it is not an array because this
- // might introduce a new length property.
- if (IS_ARRAY(this)) {
- this.length = old_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;
@@ -879,6 +938,62 @@ function ArrayLastIndexOf(element, index) {
}
+function ArrayReduce(callback, current) {
+ if (!IS_FUNCTION(callback)) {
+ throw MakeTypeError('called_non_callable', [callback]);
+ }
+ // Pull out the length so that modifications to the length in the
+ // loop will not affect the looping.
+ var length = this.length;
+ var i = 0;
+
+ find_initial: if (%_ArgumentsLength() < 2) {
+ for (; i < length; i++) {
+ current = this[i];
+ if (!IS_UNDEFINED(current) || i in this) {
+ i++;
+ break find_initial;
+ }
+ }
+ throw MakeTypeError('reduce_no_initial', []);
+ }
+
+ for (; i < length; i++) {
+ var element = this[i];
+ if (!IS_UNDEFINED(element) || i in this) {
+ current = callback.call(null, current, element, i, this);
+ }
+ }
+ return current;
+}
+
+function ArrayReduceRight(callback, current) {
+ if (!IS_FUNCTION(callback)) {
+ throw MakeTypeError('called_non_callable', [callback]);
+ }
+ var i = this.length - 1;
+
+ find_initial: if (%_ArgumentsLength() < 2) {
+ for (; i >= 0; i--) {
+ current = this[i];
+ if (!IS_UNDEFINED(current) || i in this) {
+ i--;
+ break find_initial;
+ }
+ }
+ throw MakeTypeError('reduce_no_initial', []);
+ }
+
+ for (; i >= 0; i--) {
+ var element = this[i];
+ if (!IS_UNDEFINED(element) || i in this) {
+ current = callback.call(null, current, element, i, this);
+ }
+ }
+ return current;
+}
+
+
// -------------------------------------------------------------------
@@ -890,7 +1005,6 @@ function UpdateFunctionLengths(lengths) {
// -------------------------------------------------------------------
-
function SetupArray() {
// Setup non-enumerable constructor property on the Array.prototype
// object.
@@ -898,7 +1012,7 @@ function SetupArray() {
// Setup non-enumerable functions of the Array.prototype object and
// set their names.
- InstallFunctions($Array.prototype, DONT_ENUM, $Array(
+ InstallFunctionsOnHiddenPrototype($Array.prototype, DONT_ENUM, $Array(
"toString", ArrayToString,
"toLocaleString", ArrayToLocaleString,
"join", ArrayJoin,
@@ -917,8 +1031,9 @@ function SetupArray() {
"every", ArrayEvery,
"map", ArrayMap,
"indexOf", ArrayIndexOf,
- "lastIndexOf", ArrayLastIndexOf
- ));
+ "lastIndexOf", ArrayLastIndexOf,
+ "reduce", ArrayReduce,
+ "reduceRight", ArrayReduceRight));
// Manipulate the length of some of the functions to meet
// expectations set by ECMA-262 or Mozilla.
@@ -930,7 +1045,9 @@ function SetupArray() {
ArrayMap: 1,
ArrayIndexOf: 1,
ArrayLastIndexOf: 1,
- ArrayPush: 1
+ ArrayPush: 1,
+ ArrayReduce: 1,
+ ArrayReduceRight: 1
});
}