Fix some array functions to behave as specified.
authormstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 7 Oct 2011 14:07:33 +0000 (14:07 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 7 Oct 2011 14:07:33 +0000 (14:07 +0000)
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

src/array.js
test/test262/test262.status

index 397adc7..e1d7c20 100644 (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;
index 4c58e00..a7b5969 100644 (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