Index: src/array.js |
diff --git a/src/array.js b/src/array.js |
index 0753f1e2ab7573a9b7c8ed1b1aa686f99bf8c04c..e8767b2ac660b26c8329a124a9822c98ff83cd6e 100644 |
--- a/src/array.js |
+++ b/src/array.js |
@@ -33,7 +33,7 @@ |
// Global list of arrays visited during toString, toLocaleString and |
// join invocations. |
-var visited_arrays = new $Array(); |
+var visited_arrays = new InternalArray(); |
// Gets a sorted array of array keys. Useful for operations on sparse |
@@ -73,7 +73,7 @@ function SparseJoin(array, len, convert) { |
var last_key = -1; |
var keys_length = keys.length; |
- var elements = new $Array(keys_length); |
+ var elements = new InternalArray(keys_length); |
var elements_length = 0; |
for (var i = 0; i < keys_length; i++) { |
@@ -122,7 +122,7 @@ function Join(array, length, separator, convert) { |
} |
// Construct an array for the elements. |
- var elements = new $Array(length); |
+ var elements = new InternalArray(length); |
// We pull the empty separator check outside the loop for speed! |
if (separator.length == 0) { |
@@ -140,7 +140,7 @@ function Join(array, length, separator, convert) { |
return %StringBuilderConcat(elements, elements_length, ''); |
} |
// Non-empty separator case. |
- // If the first element is a number then use the heuristic that the |
+ // If the first element is a number then use the heuristic that the |
// remaining elements are also likely to be numbers. |
if (!IS_NUMBER(array[0])) { |
for (var i = 0; i < length; i++) { |
@@ -148,7 +148,7 @@ function Join(array, length, separator, convert) { |
if (!IS_STRING(e)) e = convert(e); |
elements[i] = e; |
} |
- } else { |
+ } else { |
for (var i = 0; i < length; i++) { |
var e = array[i]; |
if (IS_NUMBER(e)) elements[i] = %_NumberToString(e); |
@@ -157,9 +157,9 @@ function Join(array, length, separator, convert) { |
elements[i] = e; |
} |
} |
- } |
+ } |
var result = %_FastAsciiArrayJoin(elements, separator); |
- if (!IS_UNDEFINED(result)) return result; |
+ if (!IS_UNDEFINED(result)) return result; |
return %StringBuilderJoin(elements, length, separator); |
} finally { |
@@ -171,7 +171,7 @@ function Join(array, length, separator, convert) { |
function ConvertToString(x) { |
- // Assumes x is a non-string. |
+ // Assumes x is a non-string. |
if (IS_NUMBER(x)) return %_NumberToString(x); |
if (IS_BOOLEAN(x)) return x ? 'true' : 'false'; |
return (IS_NULL_OR_UNDEFINED(x)) ? '' : %ToString(%DefaultString(x)); |
@@ -241,7 +241,7 @@ function SmartSlice(array, start_i, del_count, len, deleted_elements) { |
// 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 new_array = new InternalArray(len - del_count + num_additional_args); |
var intervals = %GetArrayKeys(array, len); |
var length = intervals.length; |
for (var k = 0; k < length; k++) { |
@@ -419,7 +419,7 @@ function ArrayPush() { |
function ArrayConcat(arg1) { // length == 1 |
var arg_count = %_ArgumentsLength(); |
- var arrays = new $Array(1 + arg_count); |
+ var arrays = new InternalArray(1 + arg_count); |
arrays[0] = this; |
for (var i = 0; i < arg_count; i++) { |
arrays[i + 1] = %_Arguments(i); |
@@ -925,7 +925,9 @@ function ArrayFilter(f, receiver) { |
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; |
+ if (%_CallFunction(receiver, current, i, this, f)) { |
+ result[result_length++] = current; |
+ } |
} |
} |
return result; |
@@ -942,7 +944,7 @@ function ArrayForEach(f, receiver) { |
for (var i = 0; i < length; i++) { |
var current = this[i]; |
if (!IS_UNDEFINED(current) || i in this) { |
- f.call(receiver, current, i, this); |
+ %_CallFunction(receiver, current, i, this, f); |
} |
} |
} |
@@ -960,7 +962,7 @@ function ArraySome(f, receiver) { |
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; |
+ if (%_CallFunction(receiver, current, i, this, f)) return true; |
} |
} |
return false; |
@@ -977,7 +979,7 @@ function ArrayEvery(f, receiver) { |
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; |
+ if (!%_CallFunction(receiver, current, i, this, f)) return false; |
} |
} |
return true; |
@@ -990,13 +992,15 @@ function ArrayMap(f, receiver) { |
// Pull out the length so that modifications to the length in the |
// loop will not affect the looping. |
var length = TO_UINT32(this.length); |
- var result = new $Array(length); |
+ var result = new $Array(); |
+ var accumulator = new InternalArray(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); |
+ accumulator[i] = %_CallFunction(receiver, current, i, this, f); |
} |
} |
+ %MoveArrayContents(accumulator, result); |
return result; |
} |
@@ -1134,7 +1138,7 @@ function ArrayReduce(callback, current) { |
for (; i < length; i++) { |
var element = this[i]; |
if (!IS_UNDEFINED(element) || i in this) { |
- current = callback.call(null, current, element, i, this); |
+ current = %_CallFunction(null, current, element, i, this, callback); |
} |
} |
return current; |
@@ -1160,7 +1164,7 @@ function ArrayReduceRight(callback, current) { |
for (; i >= 0; i--) { |
var element = this[i]; |
if (!IS_UNDEFINED(element) || i in this) { |
- current = callback.call(null, current, element, i, this); |
+ current = %_CallFunction(null, current, element, i, this, callback); |
} |
} |
return current; |
@@ -1225,6 +1229,20 @@ function SetupArray() { |
)); |
%FinishArrayPrototypeSetup($Array.prototype); |
+ |
+ // The internal Array prototype doesn't need to be fancy, since it's never |
+ // exposed to user code, so no hidden prototypes or DONT_ENUM attributes |
+ // are necessary. |
+ // The null __proto__ ensures that we never inherit any user created |
+ // getters or setters from, e.g., Object.prototype. |
+ InternalArray.prototype.__proto__ = null; |
+ // Adding only the functions that are actually used, and a toString. |
+ InternalArray.prototype.join = getFunction("join", ArrayJoin); |
+ InternalArray.prototype.pop = getFunction("pop", ArrayPop); |
+ InternalArray.prototype.push = getFunction("push", ArrayPush); |
+ InternalArray.prototype.toString = function() { |
+ return "Internal Array, length " + this.length; |
+ }; |
} |