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//-----------------------------------------------------------------------------
39var bug = 290592;
40var summary = 'Array extras: forEach, indexOf, filter, map';
41var actual = '';
42var expect = '';
43
44printBugNumber (bug);
45printStatus (summary);
46
47// Utility functions
48
49function identity(v, index, array)
50{
51  reportCompare(v, array[index], 'identity: check callback argument consistency');
52  return v;
53}
54
55function 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
67function 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
79function 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
93function concat(v, index, array)
94{
95  reportCompare(v, array[index], 'concat: check callback argument consistency');
96  actual += v + ',';
97}
98
99
100function 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
113function 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.
121function ArrayCallback(state)
122{
123  this.state = state;
124}
125
126ArrayCallback.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
139ArrayCallback.prototype.concat = function(v, index, array)
140{
141  reportCompare(v, array[index], 'ArrayCallback.prototype.concat: check callback argument consistency');
142  actual += v + ',';
143};
144
145ArrayCallback.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
158ArrayCallback.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
164function 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
173var obj;
174var strings = ['hello', 'Array', 'WORLD'];
175var mixed   = [0, '0', 0];
176var sparsestrings = new Array();
177sparsestrings[2] = 'sparse';
178
179if ('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
279if ('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
374if ('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
435if ('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
536if ('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
635if ('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