michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: var BUGNUMBER = 290592; michael@0: var summary = 'Array extras: forEach, indexOf, filter, map'; michael@0: var actual = ''; michael@0: var expect = ''; michael@0: michael@0: printBugNumber(BUGNUMBER); michael@0: printStatus (summary); michael@0: michael@0: // Utility functions michael@0: michael@0: function identity(v, index, array) michael@0: { michael@0: reportCompare(v, array[index], 'identity: check callback argument consistency'); michael@0: return v; michael@0: } michael@0: michael@0: function mutate(v, index, array) michael@0: { michael@0: reportCompare(v, array[index], 'mutate: check callback argument consistency'); michael@0: if (index == 0) michael@0: { michael@0: array[1] = 'mutated'; michael@0: delete array[2]; michael@0: array.push('not visited'); michael@0: } michael@0: return v; michael@0: } michael@0: michael@0: function mutateForEach(v, index, array) michael@0: { michael@0: reportCompare(v, array[index], 'mutateForEach: check callback argument consistency'); michael@0: if (index == 0) michael@0: { michael@0: array[1] = 'mutated'; michael@0: delete array[2]; michael@0: array.push('not visited'); michael@0: } michael@0: actual += v + ','; michael@0: } michael@0: michael@0: function makeUpperCase(v, index, array) michael@0: { michael@0: reportCompare(v, array[index], 'makeUpperCase: check callback argument consistency'); michael@0: try michael@0: { michael@0: return v.toUpperCase(); michael@0: } michael@0: catch(e) michael@0: { michael@0: } michael@0: return v; michael@0: } michael@0: michael@0: michael@0: function concat(v, index, array) michael@0: { michael@0: reportCompare(v, array[index], 'concat: check callback argument consistency'); michael@0: actual += v + ','; michael@0: } michael@0: michael@0: michael@0: function isUpperCase(v, index, array) michael@0: { michael@0: reportCompare(v, array[index], 'isUpperCase: check callback argument consistency'); michael@0: try michael@0: { michael@0: return v == v.toUpperCase(); michael@0: } michael@0: catch(e) michael@0: { michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: function isString(v, index, array) michael@0: { michael@0: reportCompare(v, array[index], 'isString: check callback argument consistency'); michael@0: return typeof v == 'string'; michael@0: } michael@0: michael@0: michael@0: // callback object. michael@0: function ArrayCallback(state) michael@0: { michael@0: this.state = state; michael@0: } michael@0: michael@0: ArrayCallback.prototype.makeUpperCase = function (v, index, array) michael@0: { michael@0: reportCompare(v, array[index], 'ArrayCallback.prototype.makeUpperCase: check callback argument consistency'); michael@0: try michael@0: { michael@0: return this.state ? v.toUpperCase() : v.toLowerCase(); michael@0: } michael@0: catch(e) michael@0: { michael@0: } michael@0: return v; michael@0: }; michael@0: michael@0: ArrayCallback.prototype.concat = function(v, index, array) michael@0: { michael@0: reportCompare(v, array[index], 'ArrayCallback.prototype.concat: check callback argument consistency'); michael@0: actual += v + ','; michael@0: }; michael@0: michael@0: ArrayCallback.prototype.isUpperCase = function(v, index, array) michael@0: { michael@0: reportCompare(v, array[index], 'ArrayCallback.prototype.isUpperCase: check callback argument consistency'); michael@0: try michael@0: { michael@0: return this.state ? true : (v == v.toUpperCase()); michael@0: } michael@0: catch(e) michael@0: { michael@0: } michael@0: return false; michael@0: }; michael@0: michael@0: ArrayCallback.prototype.isString = function(v, index, array) michael@0: { michael@0: reportCompare(v, array[index], 'ArrayCallback.prototype.isString: check callback argument consistency'); michael@0: return this.state ? true : (typeof v == 'string'); michael@0: }; michael@0: michael@0: function dumpError(e) michael@0: { michael@0: var s = e.name + ': ' + e.message + michael@0: ' File: ' + e.fileName + michael@0: ', Line: ' + e.lineNumber + michael@0: ', Stack: ' + e.stack; michael@0: return s; michael@0: } michael@0: michael@0: var obj; michael@0: var strings = ['hello', 'Array', 'WORLD']; michael@0: var mixed = [0, '0', 0]; michael@0: var sparsestrings = new Array(); michael@0: sparsestrings[2] = 'sparse'; michael@0: michael@0: if ('map' in Array.prototype) michael@0: { michael@0: // see http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:map michael@0: michael@0: // test Array.map michael@0: michael@0: // map has 1 required argument michael@0: expect = 1; michael@0: actual = Array.prototype.map.length; michael@0: reportCompare(expect, actual, 'Array.prototype.map.length == 1'); michael@0: michael@0: // throw TypeError if no callback function specified michael@0: expect = 'TypeError'; michael@0: try michael@0: { michael@0: strings.map(); michael@0: actual = 'no error'; michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = e.name; michael@0: } michael@0: reportCompare(expect, actual, 'Array.map(undefined) throws TypeError'); michael@0: michael@0: try michael@0: { michael@0: // identity map michael@0: expect = 'hello,Array,WORLD'; michael@0: actual = strings.map(identity).toString(); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'Array.map: identity'); michael@0: michael@0: michael@0: try michael@0: { michael@0: expect = 'hello,mutated,'; michael@0: actual = strings.map(mutate).toString(); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'Array.map: mutate'); michael@0: michael@0: strings = ['hello', 'Array', 'WORLD']; michael@0: michael@0: try michael@0: { michael@0: // general map michael@0: expect = 'HELLO,ARRAY,WORLD'; michael@0: actual = strings.map(makeUpperCase).toString(); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'Array.map: uppercase'); michael@0: michael@0: try michael@0: { michael@0: // pass object method as map callback michael@0: expect = 'HELLO,ARRAY,WORLD'; michael@0: var obj = new ArrayCallback(true); michael@0: actual = strings.map(obj.makeUpperCase, obj).toString(); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'Array.map: uppercase with object callback'); michael@0: michael@0: try michael@0: { michael@0: expect = 'hello,array,world'; michael@0: obj = new ArrayCallback(false); michael@0: actual = strings.map(obj.makeUpperCase, obj).toString(); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'Array.map: lowercase with object callback'); michael@0: michael@0: try michael@0: { michael@0: // map on sparse arrays michael@0: expect = ',,SPARSE'; michael@0: actual = sparsestrings.map(makeUpperCase).toString(); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'Array.map: uppercase on sparse array'); michael@0: } michael@0: michael@0: if ('forEach' in Array.prototype) michael@0: { michael@0: // see http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach michael@0: michael@0: // test Array.forEach michael@0: michael@0: // forEach has 1 required argument michael@0: expect = 1; michael@0: actual = Array.prototype.forEach.length; michael@0: reportCompare(expect, actual, 'Array.prototype.forEach.length == 1'); michael@0: michael@0: // throw TypeError if no callback function specified michael@0: expect = 'TypeError'; michael@0: try michael@0: { michael@0: strings.forEach(); michael@0: actual = 'no error'; michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = e.name; michael@0: } michael@0: reportCompare(expect, actual, 'Array.forEach(undefined) throws TypeError'); michael@0: michael@0: try michael@0: { michael@0: // general forEach michael@0: expect = 'hello,Array,WORLD,'; michael@0: actual = ''; michael@0: strings.forEach(concat); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'Array.forEach'); michael@0: michael@0: try michael@0: { michael@0: expect = 'hello,mutated,'; michael@0: actual = ''; michael@0: strings.forEach(mutateForEach); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'Array.forEach: mutate'); michael@0: michael@0: strings = ['hello', 'Array', 'WORLD']; michael@0: michael@0: michael@0: michael@0: try michael@0: { michael@0: // pass object method as forEach callback michael@0: expect = 'hello,Array,WORLD,'; michael@0: actual = ''; michael@0: obj = new ArrayCallback(true); michael@0: strings.forEach(obj.concat, obj); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'Array.forEach with object callback 1'); michael@0: michael@0: try michael@0: { michael@0: expect = 'hello,Array,WORLD,'; michael@0: actual = ''; michael@0: obj = new ArrayCallback(false); michael@0: strings.forEach(obj.concat, obj); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'Array.forEach with object callback 2'); michael@0: michael@0: try michael@0: { michael@0: // test forEach on sparse arrays michael@0: // see https://bugzilla.mozilla.org/show_bug.cgi?id=311082 michael@0: expect = 'sparse,'; michael@0: actual = ''; michael@0: sparsestrings.forEach(concat); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'Array.forEach on sparse array'); michael@0: } michael@0: michael@0: if ('filter' in Array.prototype) michael@0: { michael@0: // see http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:filter michael@0: michael@0: // test Array.filter michael@0: michael@0: // filter has 1 required argument michael@0: expect = 1; michael@0: actual = Array.prototype.filter.length; michael@0: reportCompare(expect, actual, 'Array.prototype.filter.length == 1'); michael@0: michael@0: // throw TypeError if no callback function specified michael@0: expect = 'TypeError'; michael@0: try michael@0: { michael@0: strings.filter(); michael@0: actual = 'no error'; michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = e.name; michael@0: } michael@0: reportCompare(expect, actual, 'Array.filter(undefined) throws TypeError'); michael@0: michael@0: try michael@0: { michael@0: // test general filter michael@0: expect = 'WORLD'; michael@0: actual = strings.filter(isUpperCase).toString(); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'Array.filter'); michael@0: michael@0: try michael@0: { michael@0: expect = 'WORLD'; michael@0: obj = new ArrayCallback(false); michael@0: actual = strings.filter(obj.isUpperCase, obj).toString(); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'Array.filter object callback 1'); michael@0: michael@0: try michael@0: { michael@0: expect = 'hello,Array,WORLD'; michael@0: obj = new ArrayCallback(true); michael@0: actual = strings.filter(obj.isUpperCase, obj).toString(); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'Array.filter object callback 2'); michael@0: } michael@0: michael@0: if ('every' in Array.prototype) michael@0: { michael@0: // see http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:every michael@0: michael@0: // test Array.every michael@0: michael@0: // every has 1 required argument michael@0: michael@0: expect = 1; michael@0: actual = Array.prototype.every.length; michael@0: reportCompare(expect, actual, 'Array.prototype.every.length == 1'); michael@0: michael@0: // throw TypeError if no every callback function specified michael@0: expect = 'TypeError'; michael@0: try michael@0: { michael@0: strings.every(); michael@0: actual = 'no error'; michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = e.name; michael@0: } michael@0: reportCompare(expect, actual, 'Array.every(undefined) throws TypeError'); michael@0: michael@0: // test general every michael@0: michael@0: try michael@0: { michael@0: expect = true; michael@0: actual = strings.every(isString); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'strings: every element is a string'); michael@0: michael@0: try michael@0: { michael@0: expect = false; michael@0: actual = mixed.every(isString); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'mixed: every element is a string'); michael@0: michael@0: try michael@0: { michael@0: // see https://bugzilla.mozilla.org/show_bug.cgi?id=311082 michael@0: expect = true; michael@0: actual = sparsestrings.every(isString); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'sparsestrings: every element is a string'); michael@0: michael@0: // pass object method as map callback michael@0: michael@0: obj = new ArrayCallback(false); michael@0: michael@0: try michael@0: { michael@0: expect = true; michael@0: actual = strings.every(obj.isString, obj); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'strings: every element is a string, via object callback'); michael@0: michael@0: try michael@0: { michael@0: expect = false; michael@0: actual = mixed.every(obj.isString, obj); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e) ; michael@0: } michael@0: reportCompare(expect, actual, 'mixed: every element is a string, via object callback'); michael@0: michael@0: try michael@0: { michael@0: // see https://bugzilla.mozilla.org/show_bug.cgi?id=311082 michael@0: expect = true; michael@0: actual = sparsestrings.every(obj.isString, obj); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'sparsestrings: every element is a string, via object callback'); michael@0: michael@0: } michael@0: michael@0: if ('some' in Array.prototype) michael@0: { michael@0: // see http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:some michael@0: michael@0: // test Array.some michael@0: michael@0: // some has 1 required argument michael@0: michael@0: expect = 1; michael@0: actual = Array.prototype.some.length; michael@0: reportCompare(expect, actual, 'Array.prototype.some.length == 1'); michael@0: michael@0: // throw TypeError if no some callback function specified michael@0: expect = 'TypeError'; michael@0: try michael@0: { michael@0: strings.some(); michael@0: actual = 'no error'; michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = e.name; michael@0: } michael@0: reportCompare(expect, actual, 'Array.some(undefined) throws TypeError'); michael@0: michael@0: // test general some michael@0: michael@0: try michael@0: { michael@0: expect = true; michael@0: actual = strings.some(isString); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'strings: some element is a string'); michael@0: michael@0: try michael@0: { michael@0: expect = true; michael@0: actual = mixed.some(isString); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'mixed: some element is a string'); michael@0: michael@0: try michael@0: { michael@0: expect = true; michael@0: actual = sparsestrings.some(isString); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'sparsestrings: some element is a string'); michael@0: michael@0: // pass object method as map callback michael@0: michael@0: obj = new ArrayCallback(false); michael@0: michael@0: try michael@0: { michael@0: expect = true; michael@0: actual = strings.some(obj.isString, obj); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'strings: some element is a string, via object callback'); michael@0: michael@0: try michael@0: { michael@0: expect = true; michael@0: actual = mixed.some(obj.isString, obj); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'mixed: some element is a string, via object callback'); michael@0: michael@0: try michael@0: { michael@0: expect = true; michael@0: actual = sparsestrings.some(obj.isString, obj); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'sparsestrings: some element is a string, via object callback'); michael@0: michael@0: } michael@0: michael@0: if ('indexOf' in Array.prototype) michael@0: { michael@0: // see http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:indexOf michael@0: michael@0: // test Array.indexOf michael@0: michael@0: // indexOf has 1 required argument michael@0: michael@0: expect = 1; michael@0: actual = Array.prototype.indexOf.length; michael@0: reportCompare(expect, actual, 'Array.prototype.indexOf.length == 1'); michael@0: michael@0: // test general indexOf michael@0: michael@0: try michael@0: { michael@0: expect = -1; michael@0: actual = mixed.indexOf('not found'); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'indexOf returns -1 if value not found'); michael@0: michael@0: try michael@0: { michael@0: expect = 0; michael@0: actual = mixed.indexOf(0); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'indexOf matches using strict equality'); michael@0: michael@0: try michael@0: { michael@0: expect = 1; michael@0: actual = mixed.indexOf('0'); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'indexOf matches using strict equality'); michael@0: michael@0: try michael@0: { michael@0: expect = 2; michael@0: actual = mixed.indexOf(0, 1); michael@0: } michael@0: catch(e) michael@0: { michael@0: actual = dumpError(e); michael@0: } michael@0: reportCompare(expect, actual, 'indexOf begins searching at fromIndex'); michael@0: } michael@0: