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: /** michael@0: File Name: 15.4.4.5-2.js michael@0: ECMA Section: Array.prototype.sort(comparefn) michael@0: Description: michael@0: michael@0: This test file tests cases in which the compare function is supplied. michael@0: In this cases, the sort creates a reverse sort. michael@0: michael@0: The elements of this array are sorted. The sort is not necessarily stable. michael@0: If comparefn is provided, it should be a function that accepts two arguments michael@0: x and y and returns a negative value if x < y, zero if x = y, or a positive michael@0: value if x > y. michael@0: michael@0: 1. Call the [[Get]] method of this object with argument "length". michael@0: 2. Call ToUint32(Result(1)). michael@0: 1. Perform an implementation-dependent sequence of calls to the michael@0: [[Get]] , [[Put]], and [[Delete]] methods of this object and michael@0: toSortCompare (described below), where the first argument for each call michael@0: to [[Get]], [[Put]] , or [[Delete]] is a nonnegative integer less michael@0: than Result(2) and where the arguments for calls to SortCompare are michael@0: results of previous calls to the [[Get]] method. After this sequence michael@0: is complete, this object must have the following two properties. michael@0: (1) There must be some mathematical permutation of the nonnegative michael@0: integers less than Result(2), such that for every nonnegative integer michael@0: j less than Result(2), if property old[j] existed, then new[(j)] is michael@0: exactly the same value as old[j],. but if property old[j] did not exist, michael@0: then new[(j)] either does not exist or exists with value undefined. michael@0: (2) If comparefn is not supplied or is a consistent comparison michael@0: function for the elements of this array, then for all nonnegative michael@0: integers j and k, each less than Result(2), if old[j] compares less michael@0: than old[k] (see SortCompare below), then (j) < (k). Here we use the michael@0: notation old[j] to refer to the hypothetical result of calling the [ michael@0: [Get]] method of this object with argument j before this step is michael@0: executed, and the notation new[j] to refer to the hypothetical result michael@0: of calling the [[Get]] method of this object with argument j after this michael@0: step has been completely executed. A function is a consistent michael@0: comparison function for a set of values if (a) for any two of those michael@0: values (possibly the same value) considered as an ordered pair, it michael@0: always returns the same value when given that pair of values as its michael@0: two arguments, and the result of applying ToNumber to this value is michael@0: not NaN; (b) when considered as a relation, where the pair (x, y) is michael@0: considered to be in the relation if and only if applying the function michael@0: to x and y and then applying ToNumber to the result produces a michael@0: negative value, this relation is a partial order; and (c) when michael@0: considered as a different relation, where the pair (x, y) is considered michael@0: to be in the relation if and only if applying the function to x and y michael@0: and then applying ToNumber to the result produces a zero value (of either michael@0: sign), this relation is an equivalence relation. In this context, the michael@0: phrase "x compares less than y" means applying Result(2) to x and y and michael@0: then applying ToNumber to the result produces a negative value. michael@0: 3.Return this object. michael@0: michael@0: When the SortCompare operator is called with two arguments x and y, the following steps are taken: michael@0: 1.If x and y are both undefined, return +0. michael@0: 2.If x is undefined, return 1. michael@0: 3.If y is undefined, return 1. michael@0: 4.If the argument comparefn was not provided in the call to sort, go to step 7. michael@0: 5.Call comparefn with arguments x and y. michael@0: 6.Return Result(5). michael@0: 7.Call ToString(x). michael@0: 8.Call ToString(y). michael@0: 9.If Result(7) < Result(8), return 1. michael@0: 10.If Result(7) > Result(8), return 1. michael@0: 11.Return +0. michael@0: michael@0: Note that, because undefined always compared greater than any other value, undefined and nonexistent michael@0: property values always sort to the end of the result. It is implementation-dependent whether or not such michael@0: properties will exist or not at the end of the array when the sort is concluded. michael@0: michael@0: Note that the sort function is intentionally generic; it does not require that its this value be an Array object. michael@0: Therefore it can be transferred to other kinds of objects for use as a method. Whether the sort function can be michael@0: applied successfully to a host object is implementation dependent . michael@0: michael@0: Author: christine@netscape.com michael@0: Date: 12 november 1997 michael@0: */ michael@0: michael@0: michael@0: var SECTION = "15.4.4.5-2"; michael@0: var VERSION = "ECMA_1"; michael@0: startTest(); michael@0: var TITLE = "Array.prototype.sort(comparefn)"; michael@0: michael@0: writeHeaderToLog( SECTION + " "+ TITLE); michael@0: michael@0: michael@0: var S = new Array(); michael@0: var item = 0; michael@0: michael@0: // array is empty. michael@0: S[item++] = "var A = new Array()"; michael@0: michael@0: // array contains one item michael@0: S[item++] = "var A = new Array( true )"; michael@0: michael@0: // length of array is 2 michael@0: S[item++] = "var A = new Array( true, false, new Boolean(true), new Boolean(false), 'true', 'false' )"; michael@0: michael@0: S[item++] = "var A = new Array(); A[3] = 'undefined'; A[6] = null; A[8] = 'null'; A[0] = void 0"; michael@0: michael@0: S[item] = "var A = new Array( "; michael@0: michael@0: var limit = 0x0061; michael@0: for ( var i = 0x007A; i >= limit; i-- ) { michael@0: S[item] += "\'"+ String.fromCharCode(i) +"\'" ; michael@0: if ( i > limit ) { michael@0: S[item] += ","; michael@0: } michael@0: } michael@0: michael@0: S[item] += ")"; michael@0: michael@0: for ( var i = 0; i < S.length; i++ ) { michael@0: CheckItems( S[i] ); michael@0: } michael@0: michael@0: test(); michael@0: michael@0: function CheckItems( S ) { michael@0: eval( S ); michael@0: var E = Sort( A ); michael@0: michael@0: new TestCase( SECTION, michael@0: S +"; A.sort(Compare); A.length", michael@0: E.length, michael@0: eval( S + "; A.sort(Compare); A.length") ); michael@0: michael@0: for ( var i = 0; i < E.length; i++ ) { michael@0: new TestCase( michael@0: SECTION, michael@0: "A["+i+ "].toString()", michael@0: E[i] +"", michael@0: A[i] +""); michael@0: michael@0: if ( A[i] == void 0 && typeof A[i] == "undefined" ) { michael@0: new TestCase( michael@0: SECTION, michael@0: "typeof A["+i+ "]", michael@0: typeof E[i], michael@0: typeof A[i] ); michael@0: } michael@0: } michael@0: } michael@0: function Object_1( value ) { michael@0: this.array = value.split(","); michael@0: this.length = this.array.length; michael@0: for ( var i = 0; i < this.length; i++ ) { michael@0: this[i] = eval(this.array[i]); michael@0: } michael@0: this.sort = Array.prototype.sort; michael@0: this.getClass = Object.prototype.toString; michael@0: } michael@0: function Sort( a ) { michael@0: var r1 = a.length; michael@0: for ( i = 0; i < a.length; i++ ) { michael@0: for ( j = i+1; j < a.length; j++ ) { michael@0: var lo = a[i]; michael@0: var hi = a[j]; michael@0: var c = Compare( lo, hi ); michael@0: if ( c == 1 ) { michael@0: a[i] = hi; michael@0: a[j] = lo; michael@0: } michael@0: } michael@0: } michael@0: return a; michael@0: } michael@0: function Compare( x, y ) { michael@0: if ( x == void 0 && y == void 0 && typeof x == "undefined" && typeof y == "undefined" ) { michael@0: return +0; michael@0: } michael@0: if ( x == void 0 && typeof x == "undefined" ) { michael@0: return 1; michael@0: } michael@0: if ( y == void 0 && typeof y == "undefined" ) { michael@0: return -1; michael@0: } michael@0: x = String(x); michael@0: y = String(y); michael@0: if ( x < y ) { michael@0: return 1; michael@0: } michael@0: if ( x > y ) { michael@0: return -1; michael@0: } michael@0: return 0; michael@0: }