Home | History | Annotate | Download | only in webkit
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions
      6 // are met:
      7 // 1.  Redistributions of source code must retain the above copyright
      8 //     notice, this list of conditions and the following disclaimer.
      9 // 2.  Redistributions in binary form must reproduce the above copyright
     10 //     notice, this list of conditions and the following disclaimer in the
     11 //     documentation and/or other materials provided with the distribution.
     12 //
     13 // THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     14 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     15 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     16 // DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     17 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     18 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     19 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     20 // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     22 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23 
     24 description(
     25 "This test checks the behavior of the various array enumeration functions in certain edge case scenarios"
     26 );
     27 
     28 var functions = ["every", "forEach", "some", "filter", "reduce", "map", "reduceRight"];
     29 var forwarders = [
     30     function(elem, index, array) { return currentFunc.call(this, elem, index, array); },
     31     function(elem, index, array) { return currentFunc.call(this, elem, index, array); },
     32     function(elem, index, array) { return currentFunc.call(this, elem, index, array); },
     33     function(elem, index, array) { return currentFunc.call(this, elem, index, array); },
     34     function(prev, elem, index, array) { return currentFunc.call(this, elem, index, array); },
     35     function(elem, index, array) { return currentFunc.call(this, elem, index, array); },
     36     function(prev, elem, index, array) { return currentFunc.call(this, elem, index, array); }
     37 ];
     38 
     39 function toObject(array) {
     40     var o = {};
     41     for (var i in array)
     42         o[i] = array[i];
     43     o.length = array.length;
     44     return o;
     45 }
     46 function toUnorderedObject(array) {
     47     var o = {};
     48     var props = [];
     49     for (var i in array)
     50         props.push(i);
     51     for (var i = props.length - 1; i >= 0; i--)
     52         o[props[i]] = array[props[i]];
     53     o.length = array.length;
     54     return o;
     55 }
     56 function returnFalse() { count++; return false; }
     57 function returnTrue() { count++; return true; }
     58 function returnElem(elem) { count++; return elem; }
     59 function returnIndex(a, index) { if (lastIndex >= index) throw "Unordered traversal"; lastIndex = index; count++; return index; }
     60 function increaseLength(a, b, array) { count++; array.length++; }
     61 function decreaseLength(a, b, array) { count++; array.length--; }
     62 function halveLength(a, b, array) { count++; if (!array.halved) array.length = (array.length / 2) | 0; array.halved = true; }
     63 
     64 var testFunctions = ["returnFalse", "returnTrue", "returnElem", "returnIndex", "increaseLength", "decreaseLength", "halveLength"];
     65 
     66 var simpleArray = [0,1,2,3,4,5];
     67 var emptyArray = [];
     68 var largeEmptyArray = new Array(300);
     69 var largeSparseArray = [0,1,2,3,4,5];
     70 largeSparseArray[299] = 299;
     71 
     72 var arrays = ["simpleArray", "emptyArray", "largeEmptyArray", "largeSparseArray"];
     73 function copyArray(a) {
     74     var g = [];
     75     for (var i in a)
     76         g[i] = a[i];
     77     return g;
     78 }
     79 
     80 // Test object and array behaviour matches
     81 for (var f = 0; f < functions.length; f++) {
     82     for (var t = 0; t < testFunctions.length; t++) {
     83         for (var a = 0; a < arrays.length; a++) {
     84             var functionName = functions[f];
     85             currentFunc = this[testFunctions[t]];
     86             if (arrays[a] === "largeEmptyArray" && functionName === "map")
     87                 continue;
     88             if (currentFunc === returnIndex && functionName === "reduceRight")
     89                 continue;
     90             shouldBe("count=0;lastIndex=-1;copyArray("+arrays[a]+")."+functionName+"(forwarders[f], "+testFunctions[t]+", 0)",
     91                      "count=0;lastIndex=-1;Array.prototype."+functionName+".call(toObject("+arrays[a]+"), forwarders[f], "+testFunctions[t]+", 0)");
     92         }
     93     }
     94 }
     95 
     96 // Test unordered object and array behaviour matches
     97 for (var f = 0; f < functions.length; f++) {
     98     for (var t = 0; t < testFunctions.length; t++) {
     99         for (var a = 0; a < arrays.length; a++) {
    100             var functionName = functions[f];
    101             currentFunc = this[testFunctions[t]];
    102             if (arrays[a] === "largeEmptyArray" && functionName === "map")
    103                 continue;
    104             if (currentFunc === returnIndex && functionName === "reduceRight")
    105                 continue;
    106             shouldBe("count=0;lastIndex=-1;copyArray("+arrays[a]+")."+functionName+"(forwarders[f], "+testFunctions[t]+", 0)",
    107                      "count=0;lastIndex=-1;Array.prototype."+functionName+".call(toUnorderedObject("+arrays[a]+"), forwarders[f], "+testFunctions[t]+", 0)");
    108         }
    109     }
    110 }
    111 
    112 // Test number of function calls
    113 var callCounts = [
    114 [[1,0,0,1],[6,0,0,7],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,0,0,1]],
    115 [[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[3,0,0,6],[3,0,0,6]],
    116 [[6,0,0,7],[1,0,0,1],[2,0,0,2],[2,0,0,2],[6,0,0,7],[3,0,0,6],[3,0,0,6]],
    117 [[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[3,0,0,6],[3,0,0,6]],
    118 [[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[3,0,0,6],[3,0,0,6]],
    119 [[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[3,0,0,6],[3,0,0,6]],
    120 [[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[4,0,0,7]]
    121 ];
    122 var objCallCounts = [
    123 [[1,0,0,1],[6,0,0,7],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,0,0,1]],
    124 [[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7]],
    125 [[6,0,0,7],[1,0,0,1],[2,0,0,2],[2,0,0,2],[6,0,0,7],[6,0,0,7],[6,0,0,7]],
    126 [[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7]],
    127 [[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7]],
    128 [[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7]],
    129 [[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7],[6,0,0,7]]
    130 ];
    131 for (var f = 0; f < functions.length; f++) {
    132     for (var t = 0; t < testFunctions.length; t++) {
    133         for (var a = 0; a < arrays.length; a++) {
    134             var functionName = functions[f];
    135             currentFunc = this[testFunctions[t]];
    136             if (currentFunc === returnIndex && functionName === "reduceRight")
    137                 continue;
    138             var expectedCnt = "" + callCounts[f][t][a];
    139             shouldBe("count=0;lastIndex=-1;copyArray("+arrays[a]+")."+functionName+"(forwarders[f], "+testFunctions[t]+", 0); count", expectedCnt);
    140             var expectedCnt = "" + objCallCounts[f][t][a];
    141             shouldBe("count=0;lastIndex=-1;Array.prototype."+functionName+".call(toObject("+arrays[a]+"), forwarders[f], "+testFunctions[t]+", 0); count", expectedCnt);
    142             shouldBe("count=0;lastIndex=-1;Array.prototype."+functionName+".call(toObject("+arrays[a]+"), forwarders[f], "+testFunctions[t]+", 0); count", expectedCnt);
    143         }
    144     }
    145 }
    146