1 /* ***** BEGIN LICENSE BLOCK ***** 2 * Version: NPL 1.1/GPL 2.0/LGPL 2.1 3 * 4 * The contents of this file are subject to the Netscape Public License 5 * Version 1.1 (the "License"); you may not use this file except in 6 * compliance with the License. You may obtain a copy of the License at 7 * http://www.mozilla.org/NPL/ 8 * 9 * Software distributed under the License is distributed on an "AS IS" basis, 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 * for the specific language governing rights and limitations under the 12 * License. 13 * 14 * The Original Code is JavaScript Engine testing utilities. 15 * 16 * The Initial Developer of the Original Code is Netscape Communications Corp. 17 * Portions created by the Initial Developer are Copyright (C) 2002 18 * the Initial Developer. All Rights Reserved. 19 * 20 * Contributor(s): brendan (at) mozilla.org, pschwartau (at) netscape.com 21 * 22 * Alternatively, the contents of this file may be used under the terms of 23 * either the GNU General Public License Version 2 or later (the "GPL"), or 24 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 25 * in which case the provisions of the GPL or the LGPL are applicable instead 26 * of those above. If you wish to allow use of your version of this file only 27 * under the terms of either the GPL or the LGPL, and not to allow others to 28 * use your version of this file under the terms of the NPL, indicate your 29 * decision by deleting the provisions above and replace them with the notice 30 * and other provisions required by the GPL or the LGPL. If you do not delete 31 * the provisions above, a recipient may use your version of this file under 32 * the terms of any one of the NPL, the GPL or the LGPL. 33 * 34 * ***** END LICENSE BLOCK ***** 35 * 36 * 37 * Date: 25 Mar 2002 38 * SUMMARY: Array.prototype.sort() should not (re-)define .length 39 * See http://bugzilla.mozilla.org/show_bug.cgi?id=130451 40 * 41 * From the ECMA-262 Edition 3 Final spec: 42 * 43 * NOTE: The sort function is intentionally generic; it does not require that 44 * its |this| value be an Array object. Therefore, it can be transferred to 45 * other kinds of objects for use as a method. Whether the sort function can 46 * be applied successfully to a host object is implementation-dependent. 47 * 48 * The interesting parts of this testcase are the contrasting expectations for 49 * Brendan's test below, when applied to Array objects vs. non-Array objects. 50 * 51 */ 52 //----------------------------------------------------------------------------- 53 var UBound = 0; 54 var bug = 130451; 55 var summary = 'Array.prototype.sort() should not (re-)define .length'; 56 var status = ''; 57 var statusitems = []; 58 var actual = ''; 59 var actualvalues = []; 60 var expect= ''; 61 var expectedvalues = []; 62 var arr = []; 63 var cmp = new Function(); 64 65 66 /* 67 * First: test Array.prototype.sort() on Array objects 68 */ 69 status = inSection(1); 70 arr = [0,1,2,3]; 71 cmp = function(x,y) {return x-y;}; 72 actual = arr.sort(cmp).length; 73 expect = 4; 74 addThis(); 75 76 status = inSection(2); 77 arr = [0,1,2,3]; 78 cmp = function(x,y) {return y-x;}; 79 actual = arr.sort(cmp).length; 80 expect = 4; 81 addThis(); 82 83 status = inSection(3); 84 arr = [0,1,2,3]; 85 cmp = function(x,y) {return x-y;}; 86 arr.length = 1; 87 actual = arr.sort(cmp).length; 88 expect = 1; 89 addThis(); 90 91 /* 92 * This test is by Brendan. Setting arr.length to 93 * 2 and then 4 should cause elements to be deleted. 94 */ 95 arr = [0,1,2,3]; 96 cmp = function(x,y) {return x-y;}; 97 arr.sort(cmp); 98 99 status = inSection(4); 100 actual = arr.join(); 101 expect = '0,1,2,3'; 102 addThis(); 103 104 status = inSection(5); 105 actual = arr.length; 106 expect = 4; 107 addThis(); 108 109 status = inSection(6); 110 arr.length = 2; 111 actual = arr.join(); 112 expect = '0,1'; 113 addThis(); 114 115 status = inSection(7); 116 arr.length = 4; 117 actual = arr.join(); 118 expect = '0,1,,'; //<---- see how 2,3 have been lost 119 addThis(); 120 121 122 123 /* 124 * Now test Array.prototype.sort() on non-Array objects 125 */ 126 status = inSection(8); 127 var obj = new Object(); 128 obj.sort = Array.prototype.sort; 129 obj.length = 4; 130 obj[0] = 0; 131 obj[1] = 1; 132 obj[2] = 2; 133 obj[3] = 3; 134 cmp = function(x,y) {return x-y;}; 135 actual = obj.sort(cmp).length; 136 expect = 4; 137 addThis(); 138 139 140 /* 141 * Here again is Brendan's test. Unlike the array case 142 * above, the setting of obj.length to 2 and then 4 143 * should NOT cause elements to be deleted 144 */ 145 obj = new Object(); 146 obj.sort = Array.prototype.sort; 147 obj.length = 4; 148 obj[0] = 3; 149 obj[1] = 2; 150 obj[2] = 1; 151 obj[3] = 0; 152 cmp = function(x,y) {return x-y;}; 153 obj.sort(cmp); //<---- this is what triggered the buggy behavior below 154 obj.join = Array.prototype.join; 155 156 status = inSection(9); 157 actual = obj.join(); 158 expect = '0,1,2,3'; 159 addThis(); 160 161 status = inSection(10); 162 actual = obj.length; 163 expect = 4; 164 addThis(); 165 166 status = inSection(11); 167 obj.length = 2; 168 actual = obj.join(); 169 expect = '0,1'; 170 addThis(); 171 172 /* 173 * Before this bug was fixed, |actual| held the value '0,1,,' 174 * as in the Array-object case at top. This bug only occurred 175 * if Array.prototype.sort() had been applied to |obj|, 176 * as we have done higher up. 177 */ 178 status = inSection(12); 179 obj.length = 4; 180 actual = obj.join(); 181 expect = '0,1,2,3'; 182 addThis(); 183 184 185 186 187 //----------------------------------------------------------------------------- 188 test(); 189 //----------------------------------------------------------------------------- 190 191 192 193 function addThis() 194 { 195 statusitems[UBound] = status; 196 actualvalues[UBound] = actual; 197 expectedvalues[UBound] = expect; 198 UBound++; 199 } 200 201 202 function test() 203 { 204 enterFunc('test'); 205 printBugNumber(bug); 206 printStatus(summary); 207 208 for (var i=0; i<UBound; i++) 209 { 210 reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); 211 } 212 213 exitFunc ('test'); 214 } 215