1/* The contents of this file are subject to the Netscape Public
2 * License Version 1.1 (the "License"); you may not use this file
3 * except in compliance with the License. You may obtain a copy of
4 * the License at http://www.mozilla.org/NPL/
5 *
6 * Software distributed under the License is distributed on an "AS
7 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
8 * implied. See the License for the specific language governing
9 * rights and limitations under the License.
10 *
11 * The Original Code is Mozilla Communicator client code, released March
12 * 31, 1998.
13 *
14 * The Initial Developer of the Original Code is Netscape Communications
15 * Corporation. Portions created by Netscape are
16 * Copyright (C) 1998 Netscape Communications Corporation. All
17 * Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 */
22/**
23    File Name:          15.4.4.5-2.js
24    ECMA Section:       Array.prototype.sort(comparefn)
25    Description:
26
27    This test file tests cases in which the compare function is supplied.
28    In this cases, the sort creates a reverse sort.
29
30    The elements of this array are sorted. The sort is not necessarily stable.
31    If comparefn is provided, it should be a function that accepts two arguments
32    x and y and returns a negative value if x < y, zero if x = y, or a positive
33    value if x > y.
34
35   1.   Call the [[Get]] method of this object with argument "length".
36   2.   Call ToUint32(Result(1)).
37        1.  Perform an implementation-dependent sequence of calls to the
38        [[Get]] , [[Put]], and [[Delete]] methods of this object and
39        toSortCompare (described below), where the first argument for each call
40            to [[Get]], [[Put]] , or [[Delete]] is a nonnegative integer less
41            than Result(2) and where the arguments for calls to SortCompare are
42            results of previous calls to the [[Get]] method. After this sequence
43            is complete, this object must have the following two properties.
44            (1) There must be some mathematical permutation of the nonnegative
45            integers less than Result(2), such that for every nonnegative integer
46            j less than Result(2), if property old[j] existed, then new[(j)] is
47            exactly the same value as old[j],. but if property old[j] did not exist,
48            then new[(j)] either does not exist or exists with value undefined.
49            (2) If comparefn is not supplied or is a consistent comparison
50            function for the elements of this array, then for all nonnegative
51            integers j and k, each less than Result(2), if old[j] compares less
52            than old[k] (see SortCompare below), then (j) < (k). Here we use the
53            notation old[j] to refer to the hypothetical result of calling the [
54            [Get]] method of this object with argument j before this step is
55            executed, and the notation new[j] to refer to the hypothetical result
56            of calling the [[Get]] method of this object with argument j after this
57            step has been completely executed. A function is a consistent
58            comparison function for a set of values if (a) for any two of those
59            values (possibly the same value) considered as an ordered pair, it
60            always returns the same value when given that pair of values as its
61            two arguments, and the result of applying ToNumber to this value is
62            not NaN; (b) when considered as a relation, where the pair (x, y) is
63            considered to be in the relation if and only if applying the function
64            to x and y and then applying ToNumber to the result produces a
65            negative value, this relation is a partial order; and (c) when
66            considered as a different relation, where the pair (x, y) is considered
67            to be in the relation if and only if applying the function to x and y
68            and then applying ToNumber to the result produces a zero value (of either
69            sign), this relation is an equivalence relation. In this context, the
70            phrase "x compares less than y" means applying Result(2) to x and y and
71            then applying ToNumber to the result produces a negative value.
72    3.Return this object.
73
74    When the SortCompare operator is called with two arguments x and y, the following steps are taken:
75       1.If x and y are both undefined, return +0.
76       2.If x is undefined, return 1.
77       3.If y is undefined, return 1.
78       4.If the argument comparefn was not provided in the call to sort, go to step 7.
79       5.Call comparefn with arguments x and y.
80       6.Return Result(5).
81       7.Call ToString(x).
82       8.Call ToString(y).
83       9.If Result(7) < Result(8), return 1.
84      10.If Result(7) > Result(8), return 1.
85      11.Return +0.
86
87Note that, because undefined always compared greater than any other value, undefined and nonexistent
88property values always sort to the end of the result. It is implementation-dependent whether or not such
89properties will exist or not at the end of the array when the sort is concluded.
90
91Note that the sort function is intentionally generic; it does not require that its this value be an Array object.
92Therefore it can be transferred to other kinds of objects for use as a method. Whether the sort function can be
93applied successfully to a host object is implementation dependent .
94
95    Author:             christine@netscape.com
96    Date:               12 november 1997
97*/
98
99
100    var SECTION = "15.4.4.5-2";
101    var VERSION = "ECMA_1";
102    startTest();
103    var TITLE   = "Array.prototype.sort(comparefn)";
104
105    writeHeaderToLog( SECTION + " "+ TITLE);
106
107    var testcases = new Array();
108    getTestCases();
109    test();
110
111function test() {
112    for ( tc=0; tc < testcases.length; tc++ ) {
113        testcases[tc].passed = writeTestCaseResult(
114                            testcases[tc].expect,
115                            testcases[tc].actual,
116                            testcases[tc].description +" = "+
117                            testcases[tc].actual );
118
119        testcases[tc].reason += ( testcases[tc].passed ) ? "" : "wrong value ";
120    }
121    stopTest();
122    return ( testcases );
123}
124function getTestCases() {
125    var S = new Array();
126    var item = 0;
127
128    // array is empty.
129    S[item++] = "var A = new Array()";
130
131    // array contains one item
132    S[item++] = "var A = new Array( true )";
133
134    // length of array is 2
135    S[item++] = "var A = new Array( true, false, new Boolean(true), new Boolean(false), 'true', 'false' )";
136
137    S[item++] = "var A = new Array(); A[3] = 'undefined'; A[6] = null; A[8] = 'null'; A[0] = void 0";
138
139    S[item] = "var A = new Array( ";
140
141    var limit = 0x0061;
142    for ( var i = 0x007A; i >= limit; i-- ) {
143        S[item] += "\'"+ String.fromCharCode(i) +"\'" ;
144        if ( i > limit ) {
145            S[item] += ",";
146        }
147    }
148
149    S[item] += ")";
150
151    for ( var i = 0; i < S.length; i++ ) {
152        CheckItems( S[i] );
153    }
154
155}
156function CheckItems( S ) {
157    eval( S );
158    var E = Sort( A );
159
160    testcases[testcases.length] = new TestCase(   SECTION,
161                                    S +";  A.sort(Compare); A.length",
162                                    E.length,
163                                    eval( S + "; A.sort(Compare); A.length") );
164
165    for ( var i = 0; i < E.length; i++ ) {
166        testcases[testcases.length] = new TestCase(
167                                            SECTION,
168                                            "A["+i+ "].toString()",
169                                            E[i] +"",
170                                            A[i] +"");
171
172        if ( A[i] == void 0 && typeof A[i] == "undefined" ) {
173            testcases[testcases.length] = new TestCase(
174                                            SECTION,
175                                            "typeof A["+i+ "]",
176                                            typeof E[i],
177                                            typeof A[i] );
178        }
179    }
180}
181function Object_1( value ) {
182    this.array = value.split(",");
183    this.length = this.array.length;
184    for ( var i = 0; i < this.length; i++ ) {
185        this[i] = eval(this.array[i]);
186    }
187    this.sort = Array.prototype.sort;
188    this.getClass = Object.prototype.toString;
189}
190function Sort( a ) {
191    var r1 = a.length;
192    for ( i = 0; i < a.length; i++ ) {
193        for ( j = i+1; j < a.length; j++ ) {
194            var lo = a[i];
195            var hi = a[j];
196            var c = Compare( lo, hi );
197            if ( c == 1 ) {
198                a[i] = hi;
199                a[j] = lo;
200            }
201        }
202    }
203    return a;
204}
205function Compare( x, y ) {
206    if ( x == void 0 && y == void 0  && typeof x == "undefined" && typeof y == "undefined" ) {
207        return +0;
208    }
209    if ( x == void 0  && typeof x == "undefined" ) {
210        return 1;
211    }
212    if ( y == void 0 && typeof y == "undefined" ) {
213        return -1;
214    }
215    x = String(x);
216    y = String(y);
217    if ( x < y ) {
218        return 1;
219    }
220    if ( x > y ) {
221        return -1;
222    }
223    return 0;
224}
225