1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* ***** BEGIN LICENSE BLOCK ***** 3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 * 5 * The contents of this file are subject to the Mozilla Public License Version 6 * 1.1 (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * http://www.mozilla.org/MPL/ 9 * 10 * Software distributed under the License is distributed on an "AS IS" basis, 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 * for the specific language governing rights and limitations under the 13 * License. 14 * 15 * The Original Code is JavaScript Engine testing utilities. 16 * 17 * The Initial Developer of the Original Code is 18 * Mozilla Foundation. 19 * Portions created by the Initial Developer are Copyright (C) 2005 20 * the Initial Developer. All Rights Reserved. 21 * 22 * Contributor(s): Mike Shaver 23 * Bob Clary 24 * 25 * Alternatively, the contents of this file may be used under the terms of 26 * either the GNU General Public License Version 2 or later (the "GPL"), or 27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 * in which case the provisions of the GPL or the LGPL are applicable instead 29 * of those above. If you wish to allow use of your version of this file only 30 * under the terms of either the GPL or the LGPL, and not to allow others to 31 * use your version of this file under the terms of the MPL, indicate your 32 * decision by deleting the provisions above and replace them with the notice 33 * and other provisions required by the GPL or the LGPL. If you do not delete 34 * the provisions above, a recipient may use your version of this file under 35 * the terms of any one of the MPL, the GPL or the LGPL. 36 * 37 * ***** END LICENSE BLOCK ***** */ 38 //----------------------------------------------------------------------------- 39 var bug = 290592; 40 var summary = 'Array extras: forEach, indexOf, filter, map'; 41 var actual = ''; 42 var expect = ''; 43 44 printBugNumber (bug); 45 printStatus (summary); 46 47 // Utility functions 48 49 function identity(v, index, array) 50 { 51 reportCompare(v, array[index], 'identity: check callback argument consistency'); 52 return v; 53 } 54 55 function mutate(v, index, array) 56 { 57 reportCompare(v, array[index], 'mutate: check callback argument consistency'); 58 if (index == 0) 59 { 60 array[1] = 'mutated'; 61 delete array[2]; 62 array.push('not visited'); 63 } 64 return v; 65 } 66 67 function mutateForEach(v, index, array) 68 { 69 reportCompare(v, array[index], 'mutateForEach: check callback argument consistency'); 70 if (index == 0) 71 { 72 array[1] = 'mutated'; 73 delete array[2]; 74 array.push('not visited'); 75 } 76 actual += v + ','; 77 } 78 79 function makeUpperCase(v, index, array) 80 { 81 reportCompare(v, array[index], 'makeUpperCase: check callback argument consistency'); 82 try 83 { 84 return v.toUpperCase(); 85 } 86 catch(e) 87 { 88 } 89 return v; 90 } 91 92 93 function concat(v, index, array) 94 { 95 reportCompare(v, array[index], 'concat: check callback argument consistency'); 96 actual += v + ','; 97 } 98 99 100 function isUpperCase(v, index, array) 101 { 102 reportCompare(v, array[index], 'isUpperCase: check callback argument consistency'); 103 try 104 { 105 return v == v.toUpperCase(); 106 } 107 catch(e) 108 { 109 } 110 return false; 111 } 112 113 function isString(v, index, array) 114 { 115 reportCompare(v, array[index], 'isString: check callback argument consistency'); 116 return typeof v == 'string'; 117 } 118 119 120 // callback object. 121 function ArrayCallback(state) 122 { 123 this.state = state; 124 } 125 126 ArrayCallback.prototype.makeUpperCase = function (v, index, array) 127 { 128 reportCompare(v, array[index], 'ArrayCallback.prototype.makeUpperCase: check callback argument consistency'); 129 try 130 { 131 return this.state ? v.toUpperCase() : v.toLowerCase(); 132 } 133 catch(e) 134 { 135 } 136 return v; 137 }; 138 139 ArrayCallback.prototype.concat = function(v, index, array) 140 { 141 reportCompare(v, array[index], 'ArrayCallback.prototype.concat: check callback argument consistency'); 142 actual += v + ','; 143 }; 144 145 ArrayCallback.prototype.isUpperCase = function(v, index, array) 146 { 147 reportCompare(v, array[index], 'ArrayCallback.prototype.isUpperCase: check callback argument consistency'); 148 try 149 { 150 return this.state ? true : (v == v.toUpperCase()); 151 } 152 catch(e) 153 { 154 } 155 return false; 156 }; 157 158 ArrayCallback.prototype.isString = function(v, index, array) 159 { 160 reportCompare(v, array[index], 'ArrayCallback.prototype.isString: check callback argument consistency'); 161 return this.state ? true : (typeof v == 'string'); 162 }; 163 164 function dumpError(e) 165 { 166 var s = e.name + ': ' + e.message + 167 ' File: ' + e.fileName + 168 ', Line: ' + e.lineNumber + 169 ', Stack: ' + e.stack; 170 return s; 171 } 172 173 var obj; 174 var strings = ['hello', 'Array', 'WORLD']; 175 var mixed = [0, '0', 0]; 176 var sparsestrings = new Array(); 177 sparsestrings[2] = 'sparse'; 178 179 if ('map' in Array.prototype) 180 { 181 // see http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:map 182 183 // test Array.map 184 185 // map has 1 required argument 186 expect = 1; 187 actual = Array.prototype.map.length; 188 reportCompare(expect, actual, 'Array.prototype.map.length == 1'); 189 190 // throw TypeError if no callback function specified 191 expect = 'TypeError'; 192 try 193 { 194 strings.map(); 195 actual = 'no error'; 196 } 197 catch(e) 198 { 199 actual = e.name; 200 } 201 reportCompare(expect, actual, 'Array.map(undefined) throws TypeError'); 202 203 try 204 { 205 // identity map 206 expect = 'hello,Array,WORLD'; 207 actual = strings.map(identity).toString(); 208 } 209 catch(e) 210 { 211 actual = dumpError(e); 212 } 213 reportCompare(expect, actual, 'Array.map: identity'); 214 215 216 try 217 { 218 expect = 'hello,mutated,'; 219 actual = strings.map(mutate).toString(); 220 } 221 catch(e) 222 { 223 actual = dumpError(e); 224 } 225 reportCompare(expect, actual, 'Array.map: mutate'); 226 227 strings = ['hello', 'Array', 'WORLD']; 228 229 try 230 { 231 // general map 232 expect = 'HELLO,ARRAY,WORLD'; 233 actual = strings.map(makeUpperCase).toString(); 234 } 235 catch(e) 236 { 237 actual = dumpError(e); 238 } 239 reportCompare(expect, actual, 'Array.map: uppercase'); 240 241 try 242 { 243 // pass object method as map callback 244 expect = 'HELLO,ARRAY,WORLD'; 245 var obj = new ArrayCallback(true); 246 actual = strings.map(obj.makeUpperCase, obj).toString(); 247 } 248 catch(e) 249 { 250 actual = dumpError(e); 251 } 252 reportCompare(expect, actual, 'Array.map: uppercase with object callback'); 253 254 try 255 { 256 expect = 'hello,array,world'; 257 obj = new ArrayCallback(false); 258 actual = strings.map(obj.makeUpperCase, obj).toString(); 259 } 260 catch(e) 261 { 262 actual = dumpError(e); 263 } 264 reportCompare(expect, actual, 'Array.map: lowercase with object callback'); 265 266 try 267 { 268 // map on sparse arrays 269 expect = ',,SPARSE'; 270 actual = sparsestrings.map(makeUpperCase).toString(); 271 } 272 catch(e) 273 { 274 actual = dumpError(e); 275 } 276 reportCompare(expect, actual, 'Array.map: uppercase on sparse array'); 277 } 278 279 if ('forEach' in Array.prototype) 280 { 281 // see http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach 282 283 // test Array.forEach 284 285 // forEach has 1 required argument 286 expect = 1; 287 actual = Array.prototype.forEach.length; 288 reportCompare(expect, actual, 'Array.prototype.forEach.length == 1'); 289 290 // throw TypeError if no callback function specified 291 expect = 'TypeError'; 292 try 293 { 294 strings.forEach(); 295 actual = 'no error'; 296 } 297 catch(e) 298 { 299 actual = e.name; 300 } 301 reportCompare(expect, actual, 'Array.forEach(undefined) throws TypeError'); 302 303 try 304 { 305 // general forEach 306 expect = 'hello,Array,WORLD,'; 307 actual = ''; 308 strings.forEach(concat); 309 } 310 catch(e) 311 { 312 actual = dumpError(e); 313 } 314 reportCompare(expect, actual, 'Array.forEach'); 315 316 try 317 { 318 expect = 'hello,mutated,'; 319 actual = ''; 320 strings.forEach(mutateForEach); 321 } 322 catch(e) 323 { 324 actual = dumpError(e); 325 } 326 reportCompare(expect, actual, 'Array.forEach: mutate'); 327 328 strings = ['hello', 'Array', 'WORLD']; 329 330 331 332 try 333 { 334 // pass object method as forEach callback 335 expect = 'hello,Array,WORLD,'; 336 actual = ''; 337 obj = new ArrayCallback(true); 338 strings.forEach(obj.concat, obj); 339 } 340 catch(e) 341 { 342 actual = dumpError(e); 343 } 344 reportCompare(expect, actual, 'Array.forEach with object callback 1'); 345 346 try 347 { 348 expect = 'hello,Array,WORLD,'; 349 actual = ''; 350 obj = new ArrayCallback(false); 351 strings.forEach(obj.concat, obj); 352 } 353 catch(e) 354 { 355 actual = dumpError(e); 356 } 357 reportCompare(expect, actual, 'Array.forEach with object callback 2'); 358 359 try 360 { 361 // test forEach on sparse arrays 362 // see https://bugzilla.mozilla.org/show_bug.cgi?id=311082 363 expect = 'sparse,'; 364 actual = ''; 365 sparsestrings.forEach(concat); 366 } 367 catch(e) 368 { 369 actual = dumpError(e); 370 } 371 reportCompare(expect, actual, 'Array.forEach on sparse array'); 372 } 373 374 if ('filter' in Array.prototype) 375 { 376 // see http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:filter 377 378 // test Array.filter 379 380 // filter has 1 required argument 381 expect = 1; 382 actual = Array.prototype.filter.length; 383 reportCompare(expect, actual, 'Array.prototype.filter.length == 1'); 384 385 // throw TypeError if no callback function specified 386 expect = 'TypeError'; 387 try 388 { 389 strings.filter(); 390 actual = 'no error'; 391 } 392 catch(e) 393 { 394 actual = e.name; 395 } 396 reportCompare(expect, actual, 'Array.filter(undefined) throws TypeError'); 397 398 try 399 { 400 // test general filter 401 expect = 'WORLD'; 402 actual = strings.filter(isUpperCase).toString(); 403 } 404 catch(e) 405 { 406 actual = dumpError(e); 407 } 408 reportCompare(expect, actual, 'Array.filter'); 409 410 try 411 { 412 expect = 'WORLD'; 413 obj = new ArrayCallback(false); 414 actual = strings.filter(obj.isUpperCase, obj).toString(); 415 } 416 catch(e) 417 { 418 actual = dumpError(e); 419 } 420 reportCompare(expect, actual, 'Array.filter object callback 1'); 421 422 try 423 { 424 expect = 'hello,Array,WORLD'; 425 obj = new ArrayCallback(true); 426 actual = strings.filter(obj.isUpperCase, obj).toString(); 427 } 428 catch(e) 429 { 430 actual = dumpError(e); 431 } 432 reportCompare(expect, actual, 'Array.filter object callback 2'); 433 } 434 435 if ('every' in Array.prototype) 436 { 437 // see http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:every 438 439 // test Array.every 440 441 // every has 1 required argument 442 443 expect = 1; 444 actual = Array.prototype.every.length; 445 reportCompare(expect, actual, 'Array.prototype.every.length == 1'); 446 447 // throw TypeError if no every callback function specified 448 expect = 'TypeError'; 449 try 450 { 451 strings.every(); 452 actual = 'no error'; 453 } 454 catch(e) 455 { 456 actual = e.name; 457 } 458 reportCompare(expect, actual, 'Array.every(undefined) throws TypeError'); 459 460 // test general every 461 462 try 463 { 464 expect = true; 465 actual = strings.every(isString); 466 } 467 catch(e) 468 { 469 actual = dumpError(e); 470 } 471 reportCompare(expect, actual, 'strings: every element is a string'); 472 473 try 474 { 475 expect = false; 476 actual = mixed.every(isString); 477 } 478 catch(e) 479 { 480 actual = dumpError(e); 481 } 482 reportCompare(expect, actual, 'mixed: every element is a string'); 483 484 try 485 { 486 // see https://bugzilla.mozilla.org/show_bug.cgi?id=311082 487 expect = true; 488 actual = sparsestrings.every(isString); 489 } 490 catch(e) 491 { 492 actual = dumpError(e); 493 } 494 reportCompare(expect, actual, 'sparsestrings: every element is a string'); 495 496 // pass object method as map callback 497 498 obj = new ArrayCallback(false); 499 500 try 501 { 502 expect = true; 503 actual = strings.every(obj.isString, obj); 504 } 505 catch(e) 506 { 507 actual = dumpError(e); 508 } 509 reportCompare(expect, actual, 'strings: every element is a string, via object callback'); 510 511 try 512 { 513 expect = false; 514 actual = mixed.every(obj.isString, obj); 515 } 516 catch(e) 517 { 518 actual = dumpError(e) ; 519 } 520 reportCompare(expect, actual, 'mixed: every element is a string, via object callback'); 521 522 try 523 { 524 // see https://bugzilla.mozilla.org/show_bug.cgi?id=311082 525 expect = true; 526 actual = sparsestrings.every(obj.isString, obj); 527 } 528 catch(e) 529 { 530 actual = dumpError(e); 531 } 532 reportCompare(expect, actual, 'sparsestrings: every element is a string, via object callback'); 533 534 } 535 536 if ('some' in Array.prototype) 537 { 538 // see http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:some 539 540 // test Array.some 541 542 // some has 1 required argument 543 544 expect = 1; 545 actual = Array.prototype.some.length; 546 reportCompare(expect, actual, 'Array.prototype.some.length == 1'); 547 548 // throw TypeError if no some callback function specified 549 expect = 'TypeError'; 550 try 551 { 552 strings.some(); 553 actual = 'no error'; 554 } 555 catch(e) 556 { 557 actual = e.name; 558 } 559 reportCompare(expect, actual, 'Array.some(undefined) throws TypeError'); 560 561 // test general some 562 563 try 564 { 565 expect = true; 566 actual = strings.some(isString); 567 } 568 catch(e) 569 { 570 actual = dumpError(e); 571 } 572 reportCompare(expect, actual, 'strings: some element is a string'); 573 574 try 575 { 576 expect = true; 577 actual = mixed.some(isString); 578 } 579 catch(e) 580 { 581 actual = dumpError(e); 582 } 583 reportCompare(expect, actual, 'mixed: some element is a string'); 584 585 try 586 { 587 expect = true; 588 actual = sparsestrings.some(isString); 589 } 590 catch(e) 591 { 592 actual = dumpError(e); 593 } 594 reportCompare(expect, actual, 'sparsestrings: some element is a string'); 595 596 // pass object method as map callback 597 598 obj = new ArrayCallback(false); 599 600 try 601 { 602 expect = true; 603 actual = strings.some(obj.isString, obj); 604 } 605 catch(e) 606 { 607 actual = dumpError(e); 608 } 609 reportCompare(expect, actual, 'strings: some element is a string, via object callback'); 610 611 try 612 { 613 expect = true; 614 actual = mixed.some(obj.isString, obj); 615 } 616 catch(e) 617 { 618 actual = dumpError(e); 619 } 620 reportCompare(expect, actual, 'mixed: some element is a string, via object callback'); 621 622 try 623 { 624 expect = true; 625 actual = sparsestrings.some(obj.isString, obj); 626 } 627 catch(e) 628 { 629 actual = dumpError(e); 630 } 631 reportCompare(expect, actual, 'sparsestrings: some element is a string, via object callback'); 632 633 } 634 635 if ('indexOf' in Array.prototype) 636 { 637 // see http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:indexOf 638 639 // test Array.indexOf 640 641 // indexOf has 1 required argument 642 643 expect = 1; 644 actual = Array.prototype.indexOf.length; 645 reportCompare(expect, actual, 'Array.prototype.indexOf.length == 1'); 646 647 // test general indexOf 648 649 try 650 { 651 expect = -1; 652 actual = mixed.indexOf('not found'); 653 } 654 catch(e) 655 { 656 actual = dumpError(e); 657 } 658 reportCompare(expect, actual, 'indexOf returns -1 if value not found'); 659 660 try 661 { 662 expect = 0; 663 actual = mixed.indexOf(0); 664 } 665 catch(e) 666 { 667 actual = dumpError(e); 668 } 669 reportCompare(expect, actual, 'indexOf matches using strict equality'); 670 671 try 672 { 673 expect = 1; 674 actual = mixed.indexOf('0'); 675 } 676 catch(e) 677 { 678 actual = dumpError(e); 679 } 680 reportCompare(expect, actual, 'indexOf matches using strict equality'); 681 682 try 683 { 684 expect = 2; 685 actual = mixed.indexOf(0, 1); 686 } 687 catch(e) 688 { 689 actual = dumpError(e); 690 } 691 reportCompare(expect, actual, 'indexOf begins searching at fromIndex'); 692 } 693 694