Fix some array functions to behave as specified.

This fixes the handling of primitives and the order of how side effects
are visible in some array functions as specified by the ES5.

R=rossberg@chromium.org
TEST=test262

Review URL: http://codereview.chromium.org/8197002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9549 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mstarzinger@chromium.org 2011-10-07 14:07:33 +00:00
parent 0ce4730f92
commit e699434266
2 changed files with 66 additions and 192 deletions

View File

@ -1003,21 +1003,24 @@ function ArrayFilter(f, receiver) {
["Array.prototype.filter"]);
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = ToObject(this);
var length = ToUint32(array.length);
if (!IS_SPEC_FUNCTION(f)) {
throw MakeTypeError('called_non_callable', [ f ]);
}
if (IS_NULL_OR_UNDEFINED(receiver)) {
receiver = %GetDefaultReceiver(f) || receiver;
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping.
var length = ToUint32(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 (%_CallFunction(receiver, current, i, this, f)) {
var current = array[i];
if (!IS_UNDEFINED(current) || i in array) {
if (%_CallFunction(receiver, current, i, array, f)) {
result[result_length++] = current;
}
}
@ -1032,19 +1035,22 @@ function ArrayForEach(f, receiver) {
["Array.prototype.forEach"]);
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = ToObject(this);
var length = TO_UINT32(array.length);
if (!IS_SPEC_FUNCTION(f)) {
throw MakeTypeError('called_non_callable', [ f ]);
}
if (IS_NULL_OR_UNDEFINED(receiver)) {
receiver = %GetDefaultReceiver(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);
for (var i = 0; i < length; i++) {
var current = this[i];
if (!IS_UNDEFINED(current) || i in this) {
%_CallFunction(receiver, current, i, this, f);
var current = array[i];
if (!IS_UNDEFINED(current) || i in array) {
%_CallFunction(receiver, current, i, array, f);
}
}
}
@ -1058,19 +1064,22 @@ function ArraySome(f, receiver) {
["Array.prototype.some"]);
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = ToObject(this);
var length = TO_UINT32(array.length);
if (!IS_SPEC_FUNCTION(f)) {
throw MakeTypeError('called_non_callable', [ f ]);
}
if (IS_NULL_OR_UNDEFINED(receiver)) {
receiver = %GetDefaultReceiver(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);
for (var i = 0; i < length; i++) {
var current = this[i];
if (!IS_UNDEFINED(current) || i in this) {
if (%_CallFunction(receiver, current, i, this, f)) return true;
var current = array[i];
if (!IS_UNDEFINED(current) || i in array) {
if (%_CallFunction(receiver, current, i, array, f)) return true;
}
}
return false;
@ -1083,19 +1092,22 @@ function ArrayEvery(f, receiver) {
["Array.prototype.every"]);
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = ToObject(this);
var length = TO_UINT32(array.length);
if (!IS_SPEC_FUNCTION(f)) {
throw MakeTypeError('called_non_callable', [ f ]);
}
if (IS_NULL_OR_UNDEFINED(receiver)) {
receiver = %GetDefaultReceiver(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);
for (var i = 0; i < length; i++) {
var current = this[i];
if (!IS_UNDEFINED(current) || i in this) {
if (!%_CallFunction(receiver, current, i, this, f)) return false;
var current = array[i];
if (!IS_UNDEFINED(current) || i in array) {
if (!%_CallFunction(receiver, current, i, array, f)) return false;
}
}
return true;
@ -1107,21 +1119,24 @@ function ArrayMap(f, receiver) {
["Array.prototype.map"]);
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = ToObject(this);
var length = TO_UINT32(array.length);
if (!IS_SPEC_FUNCTION(f)) {
throw MakeTypeError('called_non_callable', [ f ]);
}
if (IS_NULL_OR_UNDEFINED(receiver)) {
receiver = %GetDefaultReceiver(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();
var accumulator = new InternalArray(length);
for (var i = 0; i < length; i++) {
var current = this[i];
if (!IS_UNDEFINED(current) || i in this) {
accumulator[i] = %_CallFunction(receiver, current, i, this, f);
var current = array[i];
if (!IS_UNDEFINED(current) || i in array) {
accumulator[i] = %_CallFunction(receiver, current, i, array, f);
}
}
%MoveArrayContents(accumulator, result);
@ -1255,19 +1270,20 @@ function ArrayReduce(callback, current) {
["Array.prototype.reduce"]);
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = ToObject(this);
var length = ToUint32(array.length);
if (!IS_SPEC_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 = ToUint32(this.length);
var i = 0;
find_initial: if (%_ArgumentsLength() < 2) {
for (; i < length; i++) {
current = this[i];
if (!IS_UNDEFINED(current) || i in this) {
current = array[i];
if (!IS_UNDEFINED(current) || i in array) {
i++;
break find_initial;
}
@ -1277,9 +1293,9 @@ function ArrayReduce(callback, current) {
var receiver = %GetDefaultReceiver(callback);
for (; i < length; i++) {
var element = this[i];
if (!IS_UNDEFINED(element) || i in this) {
current = %_CallFunction(receiver, current, element, i, this, callback);
var element = array[i];
if (!IS_UNDEFINED(element) || i in array) {
current = %_CallFunction(receiver, current, element, i, array, callback);
}
}
return current;
@ -1291,15 +1307,20 @@ function ArrayReduceRight(callback, current) {
["Array.prototype.reduceRight"]);
}
// Pull out the length so that side effects are visible before the
// callback function is checked.
var array = ToObject(this);
var length = ToUint32(array.length);
if (!IS_SPEC_FUNCTION(callback)) {
throw MakeTypeError('called_non_callable', [callback]);
}
var i = ToUint32(this.length) - 1;
var i = length - 1;
find_initial: if (%_ArgumentsLength() < 2) {
for (; i >= 0; i--) {
current = this[i];
if (!IS_UNDEFINED(current) || i in this) {
current = array[i];
if (!IS_UNDEFINED(current) || i in array) {
i--;
break find_initial;
}
@ -1309,9 +1330,9 @@ function ArrayReduceRight(callback, current) {
var receiver = %GetDefaultReceiver(callback);
for (; i >= 0; i--) {
var element = this[i];
if (!IS_UNDEFINED(element) || i in this) {
current = %_CallFunction(receiver, current, element, i, this, callback);
var element = array[i];
if (!IS_UNDEFINED(element) || i in array) {
current = %_CallFunction(receiver, current, element, i, array, callback);
}
}
return current;

View File

@ -1106,27 +1106,6 @@ S15.4.4.3_A2_T1: FAIL_OK
# Bug? Array.prototype.lastIndexOf terminates iteration on unhandled exception
# on an Array
15.4.4.15-8-b-i-30: FAIL
# Bug? Array.prototype.every applied to boolean primitive
15.4.4.16-1-3: FAIL
# Bug? Array.prototype.every applied to number primitive
15.4.4.16-1-5: FAIL
# Bug? Array.prototype.every applied to string primitive
15.4.4.16-1-7: FAIL
# Bug? Array.prototype.every - side effects produced by step 2 are visible when
# an exception occurs
15.4.4.16-4-8: FAIL
# Bug? Array.prototype.every - side effects produced by step 3 are visible when
# an exception occurs
15.4.4.16-4-9: FAIL
# Bug? Array.prototype.every - the exception is not thrown if exception was
# thrown by step 2
15.4.4.16-4-10: FAIL
# Bug? Array.prototype.every - the exception is not thrown if exception was
# thrown by step 3
15.4.4.16-4-11: FAIL
# Bug? Array.prototype.every - calling with no callbackfn is the same as passing
# undefined for callbackfn
15.4.4.16-4-15: FAIL
# Bug? Array.prototype.every - decreasing length of array does not delete
# non-configurable properties
15.4.4.16-7-b-16: FAIL
@ -1149,27 +1128,6 @@ S15.4.4.3_A2_T1: FAIL_OK
# Bug? Array.prototype.every - element changed by getter on previous iterations
# is observed on an Array
15.4.4.16-7-c-i-28: FAIL
# Bug? Array.prototype.some applied to boolean primitive
15.4.4.17-1-3: FAIL
# Bug? Array.prototype.some applied to number primitive
15.4.4.17-1-5: FAIL
# Bug? Array.prototype.some applied to applied to string primitive
15.4.4.17-1-7: FAIL
# Bug? Array.prototype.some - side effects produced by step 2 are visible when
# an exception occurs
15.4.4.17-4-8: FAIL
# Bug? Array.prototype.some - side effects produced by step 3 are visible when
# an exception occurs
15.4.4.17-4-9: FAIL
# Bug? Array.prototype.some - the exception is not thrown if exception was
# thrown by step 2
15.4.4.17-4-10: FAIL
# Bug? Array.prototype.some - the exception is not thrown if exception was
# thrown by step 3
15.4.4.17-4-11: FAIL
# Bug? Array.prototype.some - calling with no callbackfn is the same as passing
# undefined for callbackfn
15.4.4.17-4-15: FAIL
# Bug? Array.prototype.some - decreasing length of array does not delete
# non-configurable properties
15.4.4.17-7-b-16: FAIL
@ -1192,27 +1150,6 @@ S15.4.4.3_A2_T1: FAIL_OK
# Bug? Array.prototype.some - element changed by getter on previous iterations
# is observed on an Array
15.4.4.17-7-c-i-28: FAIL
# Bug? Array.prototype.forEach applied to boolean primitive
15.4.4.18-1-3: FAIL
# Bug? Array.prototype.forEach applied to number primitive
15.4.4.18-1-5: FAIL
# Bug? Array.prototype.forEach applied to string primitive
15.4.4.18-1-7: FAIL
# Bug? Array.prototype.forEach - side effects produced by step 2 are visible
# when an exception occurs
15.4.4.18-4-8: FAIL
# Bug? Array.prototype.forEach - side effects produced by step 3 are visible
# when an exception occurs
15.4.4.18-4-9: FAIL
# Bug? Array.prototype.forEach - the exception is not thrown if exception was
# thrown by step 2
15.4.4.18-4-10: FAIL
# Bug? Array.prototype.forEach - the exception is not thrown if exception was
# thrown by step 3
15.4.4.18-4-11: FAIL
# Bug? Array.prototype.forEach - calling with no callbackfn is the same as
# passing undefined for callbackfn
15.4.4.18-4-15: FAIL
# Bug? Array.prototype.forEach - decreasing length of array does not delete
# non-configurable properties
15.4.4.18-7-b-16: FAIL
@ -1235,27 +1172,6 @@ S15.4.4.3_A2_T1: FAIL_OK
# Bug? Array.prototype.forEach - element changed by getter on previous
# iterations is observed on an Array
15.4.4.18-7-c-i-28: FAIL
# Bug? Array.prototype.map - applied to boolean primitive
15.4.4.19-1-3: FAIL
# Bug? Array.prototype.map - applied to number primitive
15.4.4.19-1-5: FAIL
# Bug? Array.prototype.map - applied to string primitive
15.4.4.19-1-7: FAIL
# Bug? Array.prototype.map - Side effects produced by step 2 are visible when an
# exception occurs
15.4.4.19-4-8: FAIL
# Bug? Array.prototype.map - Side effects produced by step 3 are visible when an
# exception occurs
15.4.4.19-4-9: FAIL
# Bug? Array.prototype.map - the exception is not thrown if exception was thrown
# by step 2
15.4.4.19-4-10: FAIL
# Bug? Array.prototype.map - the exception is not thrown if exception was thrown
# by step 3
15.4.4.19-4-11: FAIL
# Bug? Array.prototype.map - calling with no callbackfn is the same as passing
# undefined for callbackfn
15.4.4.19-4-15: FAIL
# Bug? Array.prototype.map - decreasing length of array does not delete
# non-configurable properties
15.4.4.19-8-b-16: FAIL
@ -1278,27 +1194,6 @@ S15.4.4.3_A2_T1: FAIL_OK
# Bug? Array.prototype.map - element changed by getter on previous iterations is
# observed on an Array
15.4.4.19-8-c-i-28: FAIL
# Bug? Array.prototype.filter applied to boolean primitive
15.4.4.20-1-3: FAIL
# Bug? Array.prototype.filter applied to number primitive
15.4.4.20-1-5: FAIL
# Bug? Array.prototype.filter applied to string primitive
15.4.4.20-1-7: FAIL
# Bug? Array.prototype.filter - side effects produced by step 2 are visible when
# an exception occurs
15.4.4.20-4-8: FAIL
# Bug? Array.prototype.filter - side effects produced by step 3 are visible when
# an exception occurs
15.4.4.20-4-9: FAIL
# Bug? Array.prototype.filter - the exception is not thrown if exception was
# thrown by step 2
15.4.4.20-4-10: FAIL
# Bug? Array.prototype.filter - the exception is not thrown if exception was
# thrown by step 3
15.4.4.20-4-11: FAIL
# Bug? Array.prototype.filter - calling with no callbackfn is the same as
# passing undefined for callbackfn
15.4.4.20-4-15: FAIL
# Bug? Array.prototype.filter - properties can be added to prototype after
# current position are visited on an Array-like object
15.4.4.20-9-b-6: FAIL
@ -1333,54 +1228,12 @@ S15.4.4.3_A2_T1: FAIL_OK
# Bug? Array.prototype.filter - element changed by getter on previous iterations
# is observed on an Array
15.4.4.20-9-c-i-28: FAIL
# Bug? Array.prototype.reduce applied to boolean primitive
15.4.4.21-1-3: FAIL
# Bug? Array.prototype.reduce applied to number primitive
15.4.4.21-1-5: FAIL
# Bug? Array.prototype.reduce applied to string primitive
15.4.4.21-1-7: FAIL
# Bug? Array.prototype.reduce - side effects produced by step 2 are visible when
# an exception occurs
15.4.4.21-4-8: FAIL
# Bug? Array.prototype.reduce - side effects produced by step 3 are visible when
# an exception occurs
15.4.4.21-4-9: FAIL
# Bug? Array.prototype.reduce - the exception is not thrown if exception was
# thrown by step 2
15.4.4.21-4-10: FAIL
# Bug? Array.prototype.reduce - the exception is not thrown if exception was
# thrown by step 3
15.4.4.21-4-11: FAIL
# Bug? Array.prototype.reduce - calling with no callbackfn is the same as
# passing undefined for callbackfn
15.4.4.21-4-15: FAIL
# Bug? Array.prototype.reduce - decreasing length of array in step 8 does not
# delete non-configurable properties
15.4.4.21-9-b-16: FAIL
# Bug? Array.prototype.reduce - decreasing length of array does not delete
# non-configurable properties
15.4.4.21-9-b-29: FAIL
# Bug? Array.prototype.reduceRight applied to boolean primitive
15.4.4.22-1-3: FAIL
# Bug? Array.prototype.reduceRight applied to number primitive
15.4.4.22-1-5: FAIL
# Bug? Array.prototype.reduceRight applied to string primitive
15.4.4.22-1-7: FAIL
# Bug? Array.prototype.reduceRight - side effects produced by step 2 are visible
# when an exception occurs
15.4.4.22-4-8: FAIL
# Bug? Array.prototype.reduceRight - side effects produced by step 3 are visible
# when an exception occurs
15.4.4.22-4-9: FAIL
# Bug? Array.prototype.reduceRight - the exception is not thrown if exception
# was thrown by step 2
15.4.4.22-4-10: FAIL
# Bug? Array.prototype.reduceRight - the exception is not thrown if exception
# was thrown by step 3
15.4.4.22-4-11: FAIL
# Bug? Array.prototype.reduceRight - calling with no callbackfn is the same as
# passing undefined for callbackfn
15.4.4.22-4-15: FAIL
# Bug? Array.prototype.reduceRight - element to be retrieved is own accessor
# property that overrides an inherited data property on an Array
15.4.4.22-8-b-iii-1-12: FAIL