1/*
2 * Copyright (C) 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26function every(callback /*, thisArg */) {
27    "use strict";
28    if (this === null)
29        throw new @TypeError("Array.prototype.every requires that |this| not be null");
30
31    if (this === undefined)
32        throw new @TypeError("Array.prototype.every requires that |this| not be undefined");
33
34    var array = @Object(this);
35    var length = array.length >>> 0;
36
37    if (typeof callback !== "function")
38        throw new @TypeError("Array.prototype.every callback must be a function");
39
40    var thisArg = arguments.length > 1 ? arguments[1] : undefined;
41
42    for (var i = 0; i < length; i++) {
43        if (!(i in array))
44            continue;
45        if (!callback.@call(thisArg, array[i], i, array))
46            return false;
47    }
48
49    return true;
50}
51
52function forEach(callback /*, thisArg */) {
53    "use strict";
54    if (this === null)
55        throw new @TypeError("Array.prototype.forEach requires that |this| not be null");
56
57    if (this === undefined)
58        throw new @TypeError("Array.prototype.forEach requires that |this| not be undefined");
59
60    var array = @Object(this);
61    var length = array.length >>> 0;
62
63    if (typeof callback !== "function")
64        throw new @TypeError("Array.prototype.forEach callback must be a function");
65
66    var thisArg = arguments.length > 1 ? arguments[1] : undefined;
67
68    for (var i = 0; i < length; i++) {
69        if (i in array)
70            callback.@call(thisArg, array[i], i, array);
71    }
72}
73
74function filter(callback /*, thisArg */) {
75    "use strict";
76    if (this === null)
77        throw new @TypeError("Array.prototype.filter requires that |this| not be null");
78
79    if (this === undefined)
80        throw new @TypeError("Array.prototype.filter requires that |this| not be undefined");
81
82    var array = @Object(this);
83    var length = array.length >>> 0;
84
85    if (typeof callback !== "function")
86        throw new @TypeError("Array.prototype.filter callback must be a function");
87
88    var thisArg = arguments.length > 1 ? arguments[1] : undefined;
89    var result = [];
90    var nextIndex = 0;
91    for (var i = 0; i < length; i++) {
92        if (!(i in array))
93            continue;
94        var current = array[i]
95        if (callback.@call(thisArg, current, i, array))
96            result[nextIndex++] = current;
97    }
98    return result;
99}
100
101function map(callback /*, thisArg */) {
102    "use strict";
103    if (this === null)
104        throw new @TypeError("Array.prototype.map requires that |this| not be null");
105
106    if (this === undefined)
107        throw new @TypeError("Array.prototype.map requires that |this| not be undefined");
108
109    var array = @Object(this);
110    var length = array.length >>> 0;
111
112    if (typeof callback !== "function")
113        throw new @TypeError("Array.prototype.map callback must be a function");
114
115    var thisArg = arguments.length > 1 ? arguments[1] : undefined;
116    var result = [];
117    result.length = length;
118    var nextIndex = 0;
119    for (var i = 0; i < length; i++) {
120        if (!(i in array))
121            continue;
122        result[i] = callback.@call(thisArg, array[i], i, array)
123    }
124    return result;
125}
126
127function some(callback /*, thisArg */) {
128    "use strict";
129    if (this === null)
130        throw new @TypeError("Array.prototype.some requires that |this| not be null");
131
132    if (this === undefined)
133        throw new @TypeError("Array.prototype.some requires that |this| not be undefined");
134
135    var array = @Object(this);
136    var length = array.length >>> 0;
137
138    if (typeof callback !== "function")
139        throw new @TypeError("Array.prototype.some callback must be a function");
140
141    var thisArg = arguments.length > 1 ? arguments[1] : undefined;
142    for (var i = 0; i < length; i++) {
143        if (!(i in array))
144            continue;
145        if (callback.@call(thisArg, array[i], i, array))
146            return true;
147    }
148    return false;
149}
150
151function fill(value /* [, start [, end]] */)
152{
153    "use strict";
154    if (this === null)
155        throw new @TypeError("Array.prototype.fill requires that |this| not be null");
156
157    if (this === undefined)
158        throw new @TypeError("Array.prototype.fill requires that |this| not be undefined");
159    var O = @Object(this);
160    var len = O.length >>> 0;
161    var relativeStart = 0;
162    if (arguments.length > 1 && arguments[1] !== undefined)
163        relativeStart = arguments[1] | 0;
164    var k = 0;
165    if (relativeStart < 0) {
166        k = len + relativeStart;
167        if (k < 0)
168            k = 0;
169    } else {
170        k = relativeStart;
171        if (k > len)
172            k = len;
173    }
174    var relativeEnd = len;
175    if (arguments.length > 2 && arguments[2] !== undefined)
176        relativeEnd = arguments[2] | 0;
177    var final = 0;
178    if (relativeEnd < 0) {
179        final = len + relativeEnd;
180        if (final < 0)
181            final = 0;
182    } else {
183        final = relativeEnd;
184        if (final > len)
185            final = len;
186    }
187    for (; k < final; k++)
188        O[k] = value;
189    return O;
190}
191
192function find(callback /*, thisArg */) {
193    "use strict";
194    if (this === null)
195        throw new @TypeError("Array.prototype.find requires that |this| not be null");
196
197    if (this === undefined)
198        throw new @TypeError("Array.prototype.find requires that |this| not be undefined");
199
200    var array = @Object(this);
201    var length = array.length >>> 0;
202
203    if (typeof callback !== "function")
204        throw new @TypeError("Array.prototype.find callback must be a function");
205
206    var thisArg = arguments.length > 1 ? arguments[1] : undefined;
207    for (var i = 0; i < length; i++) {
208        if (!(i in array))
209            continue;
210        if (callback.@call(thisArg, array[i], i, array))
211            return array[i];
212    }
213    return undefined;
214}
215
216function findIndex(callback /*, thisArg */) {
217    "use strict";
218    if (this === null)
219        throw new @TypeError("Array.prototype.findIndex requires that |this| not be null");
220
221    if (this === undefined)
222        throw new @TypeError("Array.prototype.findIndex requires that |this| not be undefined");
223
224    var array = @Object(this);
225    var length = array.length >>> 0;
226
227    if (typeof callback !== "function")
228        throw new @TypeError("Array.prototype.findIndex callback must be a function");
229
230    var thisArg = arguments.length > 1 ? arguments[1] : undefined;
231    for (var i = 0; i < length; i++) {
232        if (!(i in array))
233            continue;
234        if (callback.@call(thisArg, array[i], i, array))
235            return i;
236    }
237    return -1;
238}
239