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