summaryrefslogtreecommitdiffstats
path: root/V8Binding/v8/src/array.js
diff options
context:
space:
mode:
Diffstat (limited to 'V8Binding/v8/src/array.js')
-rw-r--r--V8Binding/v8/src/array.js1120
1 files changed, 0 insertions, 1120 deletions
diff --git a/V8Binding/v8/src/array.js b/V8Binding/v8/src/array.js
deleted file mode 100644
index f8e63d0..0000000
--- a/V8Binding/v8/src/array.js
+++ /dev/null
@@ -1,1120 +0,0 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This file relies on the fact that the following declarations have been made
-// in runtime.js:
-// const $Array = global.Array;
-
-// -------------------------------------------------------------------
-
-// Global list of arrays visited during toString, toLocaleString and
-// join invocations.
-var visited_arrays = new $Array();
-
-
-// Gets a sorted array of array keys. Useful for operations on sparse
-// arrays. Dupes have not been removed.
-function GetSortedArrayKeys(array, intervals) {
- var length = intervals.length;
- var keys = [];
- for (var k = 0; k < length; k++) {
- var key = intervals[k];
- if (key < 0) {
- var j = -1 - key;
- var limit = j + intervals[++k];
- for (; j < limit; j++) {
- var e = array[j];
- if (!IS_UNDEFINED(e) || j in array) {
- keys.push(j);
- }
- }
- } else {
- // The case where key is undefined also ends here.
- if (!IS_UNDEFINED(key)) {
- var e = array[key];
- if (!IS_UNDEFINED(e) || key in array) {
- keys.push(key);
- }
- }
- }
- }
- keys.sort(function(a, b) { return a - b; });
- return keys;
-}
-
-
-// Optimized for sparse arrays if separator is ''.
-function SparseJoin(array, len, convert) {
- var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
- var builder = new StringBuilder();
- var last_key = -1;
- var keys_length = keys.length;
- for (var i = 0; i < keys_length; i++) {
- var key = keys[i];
- if (key != last_key) {
- var e = array[key];
- builder.add(convert(e));
- last_key = key;
- }
- }
- return builder.generate();
-}
-
-
-function UseSparseVariant(object, length, is_array) {
- return is_array &&
- length > 1000 &&
- (!%_IsSmi(length) ||
- %EstimateNumberOfElements(object) < (length >> 2));
-}
-
-
-function Join(array, length, separator, convert) {
- if (length == 0) return '';
-
- var is_array = IS_ARRAY(array);
-
- if (is_array) {
- // If the array is cyclic, return the empty string for already
- // visited arrays.
- if (!%PushIfAbsent(visited_arrays, array)) return '';
- }
-
- // Attempt to convert the elements.
- try {
- if (UseSparseVariant(array, length, is_array) && separator === '') {
- return SparseJoin(array, length, convert);
- }
-
- // Fast case for one-element arrays.
- if (length == 1) {
- var e = array[0];
- if (!IS_UNDEFINED(e) || (0 in array)) {
- return convert(e);
- }
- }
-
- var builder = new StringBuilder();
-
- for (var i = 0; i < length; i++) {
- var e = array[i];
- if (i != 0) builder.add(separator);
- if (!IS_UNDEFINED(e) || (i in array)) {
- builder.add(convert(e));
- }
- }
- return builder.generate();
- } finally {
- // Make sure to pop the visited array no matter what happens.
- if (is_array) visited_arrays.pop();
- }
-}
-
-
-function ConvertToString(e) {
- if (e == null) return '';
- else return ToString(e);
-}
-
-
-function ConvertToLocaleString(e) {
- if (e == null) return '';
- else {
- // e_obj's toLocaleString might be overwritten, check if it is a function.
- // Call ToString if toLocaleString is not a function.
- // See issue 877615.
- var e_obj = ToObject(e);
- if (IS_FUNCTION(e_obj.toLocaleString))
- return e_obj.toLocaleString();
- else
- return ToString(e);
- }
-}
-
-
-// This function implements the optimized splice implementation that can use
-// special array operations to handle sparse arrays in a sensible fashion.
-function SmartSlice(array, start_i, del_count, len, deleted_elements) {
- // Move deleted elements to a new array (the return value from splice).
- // Intervals array can contain keys and intervals. See comment in Concat.
- var intervals = %GetArrayKeys(array, start_i + del_count);
- var length = intervals.length;
- for (var k = 0; k < length; k++) {
- var key = intervals[k];
- if (key < 0) {
- var j = -1 - key;
- var interval_limit = j + intervals[++k];
- if (j < start_i) {
- j = start_i;
- }
- for (; j < interval_limit; j++) {
- // ECMA-262 15.4.4.12 line 10. The spec could also be
- // interpreted such that %HasLocalProperty would be the
- // appropriate test. We follow KJS in consulting the
- // prototype.
- var current = array[j];
- if (!IS_UNDEFINED(current) || j in array) {
- deleted_elements[j - start_i] = current;
- }
- }
- } else {
- if (!IS_UNDEFINED(key)) {
- if (key >= start_i) {
- // ECMA-262 15.4.4.12 line 10. The spec could also be
- // interpreted such that %HasLocalProperty would be the
- // appropriate test. We follow KJS in consulting the
- // prototype.
- var current = array[key];
- if (!IS_UNDEFINED(current) || key in array) {
- deleted_elements[key - start_i] = current;
- }
- }
- }
- }
- }
-}
-
-
-// This function implements the optimized splice implementation that can use
-// special array operations to handle sparse arrays in a sensible fashion.
-function SmartMove(array, start_i, del_count, len, num_additional_args) {
- // Move data to new array.
- var new_array = new $Array(len - del_count + num_additional_args);
- var intervals = %GetArrayKeys(array, len);
- var length = intervals.length;
- for (var k = 0; k < length; k++) {
- var key = intervals[k];
- if (key < 0) {
- var j = -1 - key;
- var interval_limit = j + intervals[++k];
- while (j < start_i && j < interval_limit) {
- // The spec could also be interpreted such that
- // %HasLocalProperty would be the appropriate test. We follow
- // KJS in consulting the prototype.
- var current = array[j];
- if (!IS_UNDEFINED(current) || j in array) {
- new_array[j] = current;
- }
- j++;
- }
- j = start_i + del_count;
- while (j < interval_limit) {
- // ECMA-262 15.4.4.12 lines 24 and 41. The spec could also be
- // interpreted such that %HasLocalProperty would be the
- // appropriate test. We follow KJS in consulting the
- // prototype.
- var current = array[j];
- if (!IS_UNDEFINED(current) || j in array) {
- new_array[j - del_count + num_additional_args] = current;
- }
- j++;
- }
- } else {
- if (!IS_UNDEFINED(key)) {
- if (key < start_i) {
- // The spec could also be interpreted such that
- // %HasLocalProperty would be the appropriate test. We follow
- // KJS in consulting the prototype.
- var current = array[key];
- if (!IS_UNDEFINED(current) || key in array) {
- new_array[key] = current;
- }
- } else if (key >= start_i + del_count) {
- // ECMA-262 15.4.4.12 lines 24 and 41. The spec could also
- // be interpreted such that %HasLocalProperty would be the
- // appropriate test. We follow KJS in consulting the
- // prototype.
- var current = array[key];
- if (!IS_UNDEFINED(current) || key in array) {
- new_array[key - del_count + num_additional_args] = current;
- }
- }
- }
- }
- }
- // Move contents of new_array into this array
- %MoveArrayContents(new_array, array);
-}
-
-
-// This is part of the old simple-minded splice. We are using it either
-// because the receiver is not an array (so we have no choice) or because we
-// know we are not deleting or moving a lot of elements.
-function SimpleSlice(array, start_i, del_count, len, deleted_elements) {
- for (var i = 0; i < del_count; i++) {
- var index = start_i + i;
- // The spec could also be interpreted such that %HasLocalProperty
- // would be the appropriate test. We follow KJS in consulting the
- // prototype.
- var current = array[index];
- if (!IS_UNDEFINED(current) || index in array)
- deleted_elements[i] = current;
- }
-}
-
-
-function SimpleMove(array, start_i, del_count, len, num_additional_args) {
- if (num_additional_args !== del_count) {
- // Move the existing elements after the elements to be deleted
- // to the right position in the resulting array.
- if (num_additional_args > del_count) {
- for (var i = len - del_count; i > start_i; i--) {
- var from_index = i + del_count - 1;
- var to_index = i + num_additional_args - 1;
- // The spec could also be interpreted such that
- // %HasLocalProperty would be the appropriate test. We follow
- // KJS in consulting the prototype.
- var current = array[from_index];
- if (!IS_UNDEFINED(current) || from_index in array) {
- array[to_index] = current;
- } else {
- delete array[to_index];
- }
- }
- } else {
- for (var i = start_i; i < len - del_count; i++) {
- var from_index = i + del_count;
- var to_index = i + num_additional_args;
- // The spec could also be interpreted such that
- // %HasLocalProperty would be the appropriate test. We follow
- // KJS in consulting the prototype.
- var current = array[from_index];
- if (!IS_UNDEFINED(current) || from_index in array) {
- array[to_index] = current;
- } else {
- delete array[to_index];
- }
- }
- for (var i = len; i > len - del_count + num_additional_args; i--) {
- delete array[i - 1];
- }
- }
- }
-}
-
-
-// -------------------------------------------------------------------
-
-
-function ArrayToString() {
- if (!IS_ARRAY(this)) {
- throw new $TypeError('Array.prototype.toString is not generic');
- }
- return Join(this, this.length, ',', ConvertToString);
-}
-
-
-function ArrayToLocaleString() {
- if (!IS_ARRAY(this)) {
- throw new $TypeError('Array.prototype.toString is not generic');
- }
- return Join(this, this.length, ',', ConvertToLocaleString);
-}
-
-
-function ArrayJoin(separator) {
- if (IS_UNDEFINED(separator)) separator = ',';
- else separator = ToString(separator);
- return Join(this, ToUint32(this.length), separator, ConvertToString);
-}
-
-
-// Removes the last element from the array and returns it. See
-// ECMA-262, section 15.4.4.6.
-function ArrayPop() {
- var n = ToUint32(this.length);
- if (n == 0) {
- this.length = n;
- return;
- }
- n--;
- var value = this[n];
- this.length = n;
- delete this[n];
- return value;
-}
-
-
-// Appends the arguments to the end of the array and returns the new
-// length of the array. See ECMA-262, section 15.4.4.7.
-function ArrayPush() {
- var n = ToUint32(this.length);
- var m = %_ArgumentsLength();
- for (var i = 0; i < m; i++) {
- this[i+n] = %_Arguments(i);
- }
- this.length = n + m;
- return this.length;
-}
-
-
-function ArrayConcat(arg1) { // length == 1
- // TODO: can we just use arguments?
- var arg_count = %_ArgumentsLength();
- var arrays = new $Array(1 + arg_count);
- arrays[0] = this;
- for (var i = 0; i < arg_count; i++) {
- arrays[i + 1] = %_Arguments(i);
- }
-
- return %ArrayConcat(arrays);
-}
-
-
-// For implementing reverse() on large, sparse arrays.
-function SparseReverse(array, len) {
- var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
- var high_counter = keys.length - 1;
- var low_counter = 0;
- while (low_counter <= high_counter) {
- var i = keys[low_counter];
- var j = keys[high_counter];
-
- var j_complement = len - j - 1;
- var low, high;
-
- if (j_complement <= i) {
- high = j;
- while (keys[--high_counter] == j);
- low = j_complement;
- }
- if (j_complement >= i) {
- low = i;
- while (keys[++low_counter] == i);
- high = len - i - 1;
- }
-
- var current_i = array[low];
- if (!IS_UNDEFINED(current_i) || low in array) {
- var current_j = array[high];
- if (!IS_UNDEFINED(current_j) || high in array) {
- array[low] = current_j;
- array[high] = current_i;
- } else {
- array[high] = current_i;
- delete array[low];
- }
- } else {
- var current_j = array[high];
- if (!IS_UNDEFINED(current_j) || high in array) {
- array[low] = current_j;
- delete array[high];
- }
- }
- }
-}
-
-
-function ArrayReverse() {
- var j = ToUint32(this.length) - 1;
-
- if (UseSparseVariant(this, j, IS_ARRAY(this))) {
- SparseReverse(this, j+1);
- return this;
- }
-
- for (var i = 0; i < j; i++, j--) {
- var current_i = this[i];
- if (!IS_UNDEFINED(current_i) || i in this) {
- var current_j = this[j];
- if (!IS_UNDEFINED(current_j) || j in this) {
- this[i] = current_j;
- this[j] = current_i;
- } else {
- this[j] = current_i;
- delete this[i];
- }
- } else {
- var current_j = this[j];
- if (!IS_UNDEFINED(current_j) || j in this) {
- this[i] = current_j;
- delete this[j];
- }
- }
- }
- return this;
-}
-
-
-function ArrayShift() {
- var len = ToUint32(this.length);
-
- if (len === 0) {
- this.length = 0;
- return;
- }
-
- var first = this[0];
-
- if (IS_ARRAY(this))
- SmartMove(this, 0, 1, len, 0);
- else
- SimpleMove(this, 0, 1, len, 0);
-
- this.length = len - 1;
-
- return first;
-}
-
-
-function ArrayUnshift(arg1) { // length == 1
- var len = ToUint32(this.length);
- var num_arguments = %_ArgumentsLength();
-
- if (IS_ARRAY(this))
- SmartMove(this, 0, 0, len, num_arguments);
- else
- SimpleMove(this, 0, 0, len, num_arguments);
-
- for (var i = 0; i < num_arguments; i++) {
- this[i] = %_Arguments(i);
- }
-
- this.length = len + num_arguments;
-
- return len + num_arguments;
-}
-
-
-function ArraySlice(start, end) {
- var len = ToUint32(this.length);
- var start_i = TO_INTEGER(start);
- var end_i = len;
-
- if (end !== void 0) end_i = TO_INTEGER(end);
-
- if (start_i < 0) {
- start_i += len;
- if (start_i < 0) start_i = 0;
- } else {
- if (start_i > len) start_i = len;
- }
-
- if (end_i < 0) {
- end_i += len;
- if (end_i < 0) end_i = 0;
- } else {
- if (end_i > len) end_i = len;
- }
-
- var result = [];
-
- if (end_i < start_i) return result;
-
- if (IS_ARRAY(this)) {
- SmartSlice(this, start_i, end_i - start_i, len, result);
- } else {
- SimpleSlice(this, start_i, end_i - start_i, len, result);
- }
-
- result.length = end_i - start_i;
-
- return result;
-}
-
-
-function ArraySplice(start, delete_count) {
- var num_arguments = %_ArgumentsLength();
-
- // SpiderMonkey and KJS return undefined in the case where no
- // arguments are given instead of using the implicit undefined
- // arguments. This does not follow ECMA-262, but we do the same for
- // compatibility.
- if (num_arguments == 0) return;
-
- var len = ToUint32(this.length);
- var start_i = TO_INTEGER(start);
-
- if (start_i < 0) {
- start_i += len;
- if (start_i < 0) start_i = 0;
- } else {
- if (start_i > len) start_i = len;
- }
-
- // SpiderMonkey and KJS treat the case where no delete count is
- // given differently from when an undefined delete count is given.
- // This does not follow ECMA-262, but we do the same for
- // compatibility.
- var del_count = 0;
- if (num_arguments > 1) {
- del_count = TO_INTEGER(delete_count);
- if (del_count < 0) del_count = 0;
- if (del_count > len - start_i) del_count = len - start_i;
- } else {
- del_count = len - start_i;
- }
-
- var deleted_elements = [];
- deleted_elements.length = del_count;
-
- // Number of elements to add.
- var num_additional_args = 0;
- if (num_arguments > 2) {
- num_additional_args = num_arguments - 2;
- }
-
- var use_simple_splice = true;
-
- if (IS_ARRAY(this) && num_additional_args !== del_count) {
- // If we are only deleting/moving a few things near the end of the
- // array then the simple version is going to be faster, because it
- // doesn't touch most of the array.
- var estimated_non_hole_elements = %EstimateNumberOfElements(this);
- if (len > 20 && (estimated_non_hole_elements >> 2) < (len - start_i)) {
- use_simple_splice = false;
- }
- }
-
- if (use_simple_splice) {
- SimpleSlice(this, start_i, del_count, len, deleted_elements);
- SimpleMove(this, start_i, del_count, len, num_additional_args);
- } else {
- SmartSlice(this, start_i, del_count, len, deleted_elements);
- SmartMove(this, start_i, del_count, len, num_additional_args);
- }
-
- // Insert the arguments into the resulting array in
- // place of the deleted elements.
- var i = start_i;
- var arguments_index = 2;
- var arguments_length = %_ArgumentsLength();
- while (arguments_index < arguments_length) {
- this[i++] = %_Arguments(arguments_index++);
- }
- this.length = len - del_count + num_additional_args;
-
- // Return the deleted elements.
- return deleted_elements;
-}
-
-
-function ArraySort(comparefn) {
- // In-place QuickSort algorithm.
- // For short (length <= 22) arrays, insertion sort is used for efficiency.
-
- var custom_compare = IS_FUNCTION(comparefn);
-
- function Compare(x,y) {
- // Assume the comparefn, if any, is a consistent comparison function.
- // If it isn't, we are allowed arbitrary behavior by ECMA 15.4.4.11.
- if (x === y) return 0;
- if (custom_compare) {
- // Don't call directly to avoid exposing the builtin's global object.
- return comparefn.call(null, x, y);
- }
- if (%_IsSmi(x) && %_IsSmi(y)) {
- return %SmiLexicographicCompare(x, y);
- }
- x = ToString(x);
- y = ToString(y);
- if (x == y) return 0;
- else return x < y ? -1 : 1;
- };
-
- function InsertionSort(a, from, to) {
- for (var i = from + 1; i < to; i++) {
- var element = a[i];
- // Pre-convert the element to a string for comparison if we know
- // it will happen on each compare anyway.
- var key =
- (custom_compare || %_IsSmi(element)) ? element : ToString(element);
- // place element in a[from..i[
- // binary search
- var min = from;
- var max = i;
- // The search interval is a[min..max[
- while (min < max) {
- var mid = min + ((max - min) >> 1);
- var order = Compare(a[mid], key);
- if (order == 0) {
- min = max = mid;
- break;
- }
- if (order < 0) {
- min = mid + 1;
- } else {
- max = mid;
- }
- }
- // place element at position min==max.
- for (var j = i; j > min; j--) {
- a[j] = a[j - 1];
- }
- a[min] = element;
- }
- }
-
- function QuickSort(a, from, to) {
- // Insertion sort is faster for short arrays.
- if (to - from <= 22) {
- InsertionSort(a, from, to);
- return;
- }
- var pivot_index = $floor($random() * (to - from)) + from;
- var pivot = a[pivot_index];
- // Pre-convert the element to a string for comparison if we know
- // it will happen on each compare anyway.
- var pivot_key =
- (custom_compare || %_IsSmi(pivot)) ? pivot : ToString(pivot);
- // Issue 95: Keep the pivot element out of the comparisons to avoid
- // infinite recursion if comparefn(pivot, pivot) != 0.
- a[pivot_index] = a[from];
- a[from] = pivot;
- var low_end = from; // Upper bound of the elements lower than pivot.
- var high_start = to; // Lower bound of the elements greater than pivot.
- // From low_end to i are elements equal to pivot.
- // From i to high_start are elements that haven't been compared yet.
- for (var i = from + 1; i < high_start; ) {
- var element = a[i];
- var order = Compare(element, pivot_key);
- if (order < 0) {
- a[i] = a[low_end];
- a[low_end] = element;
- i++;
- low_end++;
- } else if (order > 0) {
- high_start--;
- a[i] = a[high_start];
- a[high_start] = element;
- } else { // order == 0
- i++;
- }
- }
- QuickSort(a, from, low_end);
- QuickSort(a, high_start, to);
- }
-
- var length;
-
- // 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;
- }
-
- // 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;
- }
- }
- }
- }
- }
- }
-
- 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;
- }
-
- length = ToUint32(this.length);
- 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);
- }
-
- 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);
-
- 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;
-}
-
-
-// The following functions cannot be made efficient on sparse arrays while
-// preserving the semantics, since the calls to the receiver function can add
-// or delete elements from the array.
-function ArrayFilter(f, receiver) {
- if (!IS_FUNCTION(f)) {
- throw MakeTypeError('called_non_callable', [ f ]);
- }
- // Pull out the length so that modifications to the length in the
- // loop will not affect the looping.
- var length = this.length;
- var result = [];
- var result_length = 0;
- for (var i = 0; i < length; i++) {
- var current = this[i];
- if (!IS_UNDEFINED(current) || i in this) {
- if (f.call(receiver, current, i, this)) result[result_length++] = current;
- }
- }
- return result;
-}
-
-
-function ArrayForEach(f, receiver) {
- if (!IS_FUNCTION(f)) {
- throw MakeTypeError('called_non_callable', [ f ]);
- }
- // Pull out the length so that modifications to the length in the
- // loop will not affect the looping.
- var length = this.length;
- for (var i = 0; i < length; i++) {
- var current = this[i];
- if (!IS_UNDEFINED(current) || i in this) {
- f.call(receiver, current, i, this);
- }
- }
-}
-
-
-// Executes the function once for each element present in the
-// array until it finds one where callback returns true.
-function ArraySome(f, receiver) {
- if (!IS_FUNCTION(f)) {
- throw MakeTypeError('called_non_callable', [ f ]);
- }
- // Pull out the length so that modifications to the length in the
- // loop will not affect the looping.
- var length = this.length;
- for (var i = 0; i < length; i++) {
- var current = this[i];
- if (!IS_UNDEFINED(current) || i in this) {
- if (f.call(receiver, current, i, this)) return true;
- }
- }
- return false;
-}
-
-
-function ArrayEvery(f, receiver) {
- if (!IS_FUNCTION(f)) {
- throw MakeTypeError('called_non_callable', [ f ]);
- }
- // Pull out the length so that modifications to the length in the
- // loop will not affect the looping.
- var length = this.length;
- for (var i = 0; i < length; i++) {
- var current = this[i];
- if (!IS_UNDEFINED(current) || i in this) {
- if (!f.call(receiver, current, i, this)) return false;
- }
- }
-
- return true;
-}
-
-
-function ArrayMap(f, receiver) {
- if (!IS_FUNCTION(f)) {
- throw MakeTypeError('called_non_callable', [ f ]);
- }
- // Pull out the length so that modifications to the length in the
- // loop will not affect the looping.
- var length = this.length;
- var result = new $Array(length);
- for (var i = 0; i < length; i++) {
- var current = this[i];
- if (!IS_UNDEFINED(current) || i in this) {
- result[i] = f.call(receiver, current, i, this);
- }
- }
- return result;
-}
-
-
-function ArrayIndexOf(element, index) {
- var length = this.length;
- if (index == null) {
- index = 0;
- } else {
- index = TO_INTEGER(index);
- // If index is negative, index from the end of the array.
- if (index < 0) index = length + index;
- // If index is still negative, search the entire array.
- if (index < 0) index = 0;
- }
- // Lookup through the array.
- for (var i = index; i < length; i++) {
- var current = this[i];
- if (!IS_UNDEFINED(current) || i in this) {
- if (current === element) return i;
- }
- }
- return -1;
-}
-
-
-function ArrayLastIndexOf(element, index) {
- var length = this.length;
- if (index == null) {
- index = length - 1;
- } else {
- index = TO_INTEGER(index);
- // If index is negative, index from end of the array.
- if (index < 0) index = length + index;
- // If index is still negative, do not search the array.
- if (index < 0) index = -1;
- else if (index >= length) index = length - 1;
- }
- // Lookup through the array.
- for (var i = index; i >= 0; i--) {
- var current = this[i];
- if (!IS_UNDEFINED(current) || i in this) {
- if (current === element) return i;
- }
- }
- return -1;
-}
-
-
-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;
-}
-
-
-// -------------------------------------------------------------------
-
-
-function UpdateFunctionLengths(lengths) {
- for (var key in lengths) {
- %FunctionSetLength(this[key], lengths[key]);
- }
-}
-
-
-// -------------------------------------------------------------------
-function SetupArray() {
- // Setup non-enumerable constructor property on the Array.prototype
- // object.
- %SetProperty($Array.prototype, "constructor", $Array, DONT_ENUM);
-
- // Setup non-enumerable functions of the Array.prototype object and
- // set their names.
- InstallFunctionsOnHiddenPrototype($Array.prototype, DONT_ENUM, $Array(
- "toString", ArrayToString,
- "toLocaleString", ArrayToLocaleString,
- "join", ArrayJoin,
- "pop", ArrayPop,
- "push", ArrayPush,
- "concat", ArrayConcat,
- "reverse", ArrayReverse,
- "shift", ArrayShift,
- "unshift", ArrayUnshift,
- "slice", ArraySlice,
- "splice", ArraySplice,
- "sort", ArraySort,
- "filter", ArrayFilter,
- "forEach", ArrayForEach,
- "some", ArraySome,
- "every", ArrayEvery,
- "map", ArrayMap,
- "indexOf", ArrayIndexOf,
- "lastIndexOf", ArrayLastIndexOf,
- "reduce", ArrayReduce,
- "reduceRight", ArrayReduceRight));
-
- // Manipulate the length of some of the functions to meet
- // expectations set by ECMA-262 or Mozilla.
- UpdateFunctionLengths({
- ArrayFilter: 1,
- ArrayForEach: 1,
- ArraySome: 1,
- ArrayEvery: 1,
- ArrayMap: 1,
- ArrayIndexOf: 1,
- ArrayLastIndexOf: 1,
- ArrayPush: 1,
- ArrayReduce: 1,
- ArrayReduceRight: 1
- });
-}
-
-
-SetupArray();