Home | History | Annotate | Download | only in js
      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 "Test some array functions on non-array objects."
     26 );
     27 
     28 function properties(object, extraName1, extraName2, extraName3)
     29 {
     30     var string = "";
     31 
     32     // destructive, lists properties
     33     var names = [];
     34     var enumerables = {};
     35     for (propertyName in object) {
     36         names.push(propertyName);
     37         enumerables[propertyName] = 1;
     38     }
     39     names.push("length");
     40     names.push(extraName1);
     41     names.push(extraName2);
     42     names.push(extraName3);
     43     names.sort();
     44 
     45     var propertyStrings = [];
     46     for (i = 0; i < names.length; ++i) {
     47         var name = names[i];
     48         if (name == names[i - 1])
     49             continue;
     50         if (!(name in object))
     51             continue;
     52 
     53         var propertyString = name + ":" + object[name];
     54 
     55         var flags = [];
     56         if (!object.hasOwnProperty(name))
     57             flags.push("FromPrototype");
     58         if (!enumerables[name])
     59             flags.push("DontEnum");
     60         if (name != "length") {
     61             try {
     62                 object[name] = "ReadOnlyTestValue";
     63             } catch (e) {
     64             }
     65             if (object[name] != "ReadOnlyTestValue")
     66                 flags.push("ReadOnly");
     67         }
     68         delete object[name];
     69         if (object.hasOwnProperty(name))
     70             flags.push("DontDelete");
     71 
     72         flags.sort();
     73 
     74         if (flags.length)
     75             propertyString += "(" + flags.join(", ") + ")";
     76 
     77         propertyStrings.push(propertyString);
     78     }
     79     return propertyStrings.join(", ");
     80 }
     81 
     82 var x;
     83 
     84 var oneItemPrototype = { length:1, 0:'a' };
     85 function OneItemConstructor()
     86 {
     87 }
     88 OneItemConstructor.prototype = oneItemPrototype;
     89 
     90 var twoItemPrototype = { length:2, 0:'b', 1:'a' };
     91 function TwoItemConstructor()
     92 {
     93 }
     94 TwoItemConstructor.prototype = twoItemPrototype;
     95 
     96 shouldBe("properties(['b', 'a'])", "'0:b, 1:a, length:2(DontDelete, DontEnum)'");
     97 shouldBe("properties({ length:2, 0:'b', 1:'a' })", "'0:b, 1:a, length:2'");
     98 
     99 shouldBe("properties(new OneItemConstructor)", "'0:a(FromPrototype), length:1(FromPrototype)'");
    100 shouldBe("properties(new TwoItemConstructor)", "'0:b(FromPrototype), 1:a(FromPrototype), length:2(FromPrototype)'");
    101 
    102 shouldBe("Array.prototype.toString.call({})", '"' + ({}).toString() + '"');
    103 shouldBe("Array.prototype.toString.call(new Date)", '"' + Object.prototype.toString.call(new Date) + '"');
    104 shouldBe("Array.prototype.toString.call({sort: function() { return 'sort' }})", '"' + Object.prototype.toString.call({}) + '"');
    105 shouldBe("Array.prototype.toString.call({join: function() { return 'join' }})", '"join"');
    106 shouldBe("Array.prototype.toString.call({__proto__: Array.prototype, 0: 'a', 1: 'b', 2: 'c', length: 3})", '"a,b,c"');
    107 shouldBe("({__proto__: Array.prototype, 0: 'a', 1: 'b', 2: 'c', length: 3}).toString()", '"a,b,c"');
    108 shouldBe("Array.prototype.toString.call({__proto__: Array.prototype, 0: 'a', 1: 'b', 2: 'c', length: 3, join: function() { return 'join' }})", '"join"');
    109 shouldBe("({__proto__: Array.prototype, 0: 'a', 1: 'b', 2: 'c', length: 3, join: function() { return 'join' }}).toString()", '"join"');
    110 Number.prototype.join = function() { return "Number.prototype.join:" + this; }
    111 shouldBe("Array.prototype.toString.call(42)", '"Number.prototype.join:42"');
    112 var arrayJoin = Array.prototype.join;
    113 Array.prototype.join = function() { return 'array-join' };
    114 shouldBe("[0, 1, 2].toString()", '"array-join"');
    115 Array.prototype.join = arrayJoin;
    116 
    117 shouldThrow("Array.prototype.toLocaleString.call({})");
    118 
    119 shouldBe("Array.prototype.concat.call(x = { length:2, 0:'b', 1:'a' })", "[x]");
    120 
    121 shouldBe("Array.prototype.join.call({})", "''");
    122 shouldBe("Array.prototype.join.call(['b', 'a'])", "'b,a'");
    123 shouldBe("Array.prototype.join.call({ length:2, 0:'b', 1:'a' })", "'b,a'");
    124 shouldBe("Array.prototype.join.call(new TwoItemConstructor)", "'b,a'");
    125 
    126 shouldBe("Array.prototype.pop.call({})", "undefined");
    127 shouldBe("Array.prototype.pop.call({ length:2, 0:'b', 1:'a' })", "'a'");
    128 shouldBe("Array.prototype.pop.call({ length:2, 0:'b', 1:'a' })", "'a'");
    129 shouldBe("Array.prototype.pop.call(new TwoItemConstructor)", "'a'");
    130 shouldBe("Array.prototype.pop.call(x = {}); properties(x)", "'length:0'");
    131 shouldBe("Array.prototype.pop.call(x = ['b', 'a']); properties(x)", "'0:b, length:1(DontDelete, DontEnum)'");
    132 shouldBe("Array.prototype.pop.call(x = { length:2, 0:'b', 1:'a' }); properties(x)", "'0:b, length:1'");
    133 shouldBe("Array.prototype.pop.call(x = new TwoItemConstructor); properties(x)", "'0:b(FromPrototype), 1:a(FromPrototype), length:1'");
    134 
    135 shouldBe("Array.prototype.push.call({})", "0");
    136 shouldBe("Array.prototype.push.call(['b', 'a'])", "2");
    137 shouldBe("Array.prototype.push.call({ length:2, 0:'b', 1:'a' })", "2");
    138 shouldBe("Array.prototype.push.call(new TwoItemConstructor)", "2");
    139 shouldBe("Array.prototype.push.call(x = {}); properties(x)", "'length:0'");
    140 shouldBe("Array.prototype.push.call(x = ['b', 'a']); properties(x)", "'0:b, 1:a, length:2(DontDelete, DontEnum)'");
    141 shouldBe("Array.prototype.push.call(x = { length:2, 0:'b', 1:'a' }); properties(x)", "'0:b, 1:a, length:2'");
    142 shouldBe("Array.prototype.push.call(x = new TwoItemConstructor); properties(x)", "'0:b(FromPrototype), 1:a(FromPrototype), length:2'");
    143 shouldBe("Array.prototype.push.call({}, 'c')", "1");
    144 shouldBe("Array.prototype.push.call(['b', 'a'], 'c')", "3");
    145 shouldBe("Array.prototype.push.call({ length:2, 0:'b', 1:'a' }, 'c')", "3");
    146 shouldBe("Array.prototype.push.call(new TwoItemConstructor, 'c')", "3");
    147 shouldBe("Array.prototype.push.call(x = {}, 'c'); properties(x)", "'0:c, length:1'");
    148 shouldBe("Array.prototype.push.call(x = ['b', 'a'], 'c'); properties(x)", "'0:b, 1:a, 2:c, length:3(DontDelete, DontEnum)'");
    149 shouldBe("Array.prototype.push.call(x = { length:2, 0:'b', 1:'a' }, 'c'); properties(x)", "'0:b, 1:a, 2:c, length:3'");
    150 shouldBe("Array.prototype.push.call(x = new TwoItemConstructor, 'c'); properties(x)", "'0:b(FromPrototype), 1:a(FromPrototype), 2:c, length:3'");
    151 
    152 shouldBe("properties(Array.prototype.reverse.call({}))", "''");
    153 shouldBe("properties(Array.prototype.reverse.call(['b', 'a']))", "'0:a, 1:b, length:2(DontDelete, DontEnum)'");
    154 shouldBe("properties(Array.prototype.reverse.call({ length:2, 0:'b', 1:'a' }))", "'0:a, 1:b, length:2'");
    155 shouldBe("properties(Array.prototype.reverse.call(new OneItemConstructor))", "'0:a(FromPrototype), length:1(FromPrototype)'");
    156 shouldBe("properties(Array.prototype.reverse.call(new TwoItemConstructor))", "'0:a, 1:b, length:2(FromPrototype)'");
    157 
    158 shouldBe("Array.prototype.shift.call({})", "undefined");
    159 shouldBe("Array.prototype.shift.call(['b', 'a'])", "'b'");
    160 shouldBe("Array.prototype.shift.call({ length:2, 0:'b', 1:'a' })", "'b'");
    161 shouldBe("Array.prototype.shift.call(new TwoItemConstructor)", "'b'");
    162 shouldBe("Array.prototype.shift.call(x = {}); properties(x)", "'length:0'");
    163 shouldBe("Array.prototype.shift.call(x = ['b', 'a']); properties(x)", "'0:a, length:1(DontDelete, DontEnum)'");
    164 shouldBe("Array.prototype.shift.call(x = { length:2, 0:'b', 1:'a' }); properties(x)", "'0:a, length:1'");
    165 shouldBe("Array.prototype.shift.call(x = new TwoItemConstructor); properties(x)", "'0:a, 1:a(FromPrototype), length:1'");
    166 
    167 shouldBe("Array.prototype.slice.call({}, 0, 1)", "[]");
    168 shouldBe("Array.prototype.slice.call(['b', 'a'], 0, 1)", "['b']");
    169 shouldBe("Array.prototype.slice.call({ length:2, 0:'b', 1:'a' }, 0, 1)", "['b']");
    170 shouldBe("Array.prototype.slice.call(new TwoItemConstructor, 0, 1)", "['b']");
    171 
    172 shouldBe("properties(Array.prototype.sort.call({}))", "''");
    173 shouldBe("properties(Array.prototype.sort.call(['b', 'a']))", "'0:a, 1:b, length:2(DontDelete, DontEnum)'");
    174 shouldBe("properties(Array.prototype.sort.call({ length:2, 0:'b', 1:'a' }))", "'0:a, 1:b, length:2'");
    175 shouldBe("properties(Array.prototype.sort.call(new OneItemConstructor))", "'0:a(FromPrototype), length:1(FromPrototype)'");
    176 shouldBe("properties(Array.prototype.sort.call(new TwoItemConstructor))", "'0:a, 1:b, length:2(FromPrototype)'");
    177 
    178 shouldBe("Array.prototype.splice.call({}, 0, 1)", "[]");
    179 shouldBe("Array.prototype.splice.call(['b', 'a'], 0, 1)", "['b']");
    180 shouldBe("Array.prototype.splice.call({ length:2, 0:'b', 1:'a' }, 0, 1)", "['b']");
    181 shouldBe("Array.prototype.splice.call(new TwoItemConstructor, 0, 1)", "['b']");
    182 shouldBe("Array.prototype.splice.call(x = {}, 0, 1); properties(x)", "'length:0'");
    183 shouldBe("Array.prototype.splice.call(x = ['b', 'a'], 0, 1); properties(x)", "'0:a, length:1(DontDelete, DontEnum)'");
    184 shouldBe("Array.prototype.splice.call(x = { length:2, 0:'b', 1:'a' }, 0, 1); properties(x)", "'0:a, length:1'");
    185 shouldBe("Array.prototype.splice.call(x = new TwoItemConstructor, 0, 1); properties(x)", "'0:a, 1:a(FromPrototype), length:1'");
    186 
    187 shouldBe("Array.prototype.unshift.call({})", "0");
    188 shouldBe("Array.prototype.unshift.call(['b', 'a'])", "2");
    189 shouldBe("Array.prototype.unshift.call({ length:2, 0:'b', 1:'a' })", "2");
    190 shouldBe("Array.prototype.unshift.call(new TwoItemConstructor)", "2");
    191 shouldBe("Array.prototype.unshift.call(x = {}); properties(x)", "'length:0'");
    192 shouldBe("Array.prototype.unshift.call(x = ['b', 'a']); properties(x)", "'0:b, 1:a, length:2(DontDelete, DontEnum)'");
    193 shouldBe("Array.prototype.unshift.call(x = { length:2, 0:'b', 1:'a' }); properties(x)", "'0:b, 1:a, length:2'");
    194 shouldBe("Array.prototype.unshift.call(x = new TwoItemConstructor); properties(x)", "'0:b(FromPrototype), 1:a(FromPrototype), length:2'");
    195 shouldBe("Array.prototype.unshift.call({}, 'c')", "1");
    196 shouldBe("Array.prototype.unshift.call(['b', 'a'], 'c')", "3");
    197 shouldBe("Array.prototype.unshift.call({ length:2, 0:'b', 1:'a' }, 'c')", "3");
    198 shouldBe("Array.prototype.unshift.call(new TwoItemConstructor, 'c')", "3");
    199 shouldBe("Array.prototype.unshift.call(x = {}, 'c'); properties(x)", "'0:c, length:1'");
    200 shouldBe("Array.prototype.unshift.call(x = ['b', 'a'], 'c'); properties(x)", "'0:c, 1:b, 2:a, length:3(DontDelete, DontEnum)'");
    201 shouldBe("Array.prototype.unshift.call(x = { length:2, 0:'b', 1:'a' }, 'c'); properties(x)", "'0:c, 1:b, 2:a, length:3'");
    202 shouldBe("Array.prototype.unshift.call(x = new TwoItemConstructor, 'c'); properties(x)", "'0:c, 1:b, 2:a, length:3'");
    203 
    204 // FIXME: Add tests for every, forEach, some, indexOf, lastIndexOf, filter, and map
    205