72625a57f55423d93c72f8f9d674dc8416df9dd5
[platform/upstream/nodejs.git] / deps / v8 / src / harmony-array.js
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 // This file relies on the fact that the following declaration has been made
8 // in runtime.js:
9 // var $Array = global.Array;
10
11 // -------------------------------------------------------------------
12
13 // ES6 draft 07-15-13, section 15.4.3.23
14 function ArrayFind(predicate /* thisArg */) {  // length == 1
15   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.find");
16
17   var array = ToObject(this);
18   var length = ToInteger(array.length);
19
20   if (!IS_SPEC_FUNCTION(predicate)) {
21     throw MakeTypeError('called_non_callable', [predicate]);
22   }
23
24   var thisArg;
25   if (%_ArgumentsLength() > 1) {
26     thisArg = %_Arguments(1);
27   }
28
29   var needs_wrapper = false;
30   if (IS_NULL_OR_UNDEFINED(thisArg)) {
31     thisArg = %GetDefaultReceiver(predicate) || thisArg;
32   } else {
33     needs_wrapper = SHOULD_CREATE_WRAPPER(predicate, thisArg);
34   }
35
36   for (var i = 0; i < length; i++) {
37     if (i in array) {
38       var element = array[i];
39       var newThisArg = needs_wrapper ? ToObject(thisArg) : thisArg;
40       if (%_CallFunction(newThisArg, element, i, array, predicate)) {
41         return element;
42       }
43     }
44   }
45
46   return;
47 }
48
49
50 // ES6 draft 07-15-13, section 15.4.3.24
51 function ArrayFindIndex(predicate /* thisArg */) {  // length == 1
52   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.findIndex");
53
54   var array = ToObject(this);
55   var length = ToInteger(array.length);
56
57   if (!IS_SPEC_FUNCTION(predicate)) {
58     throw MakeTypeError('called_non_callable', [predicate]);
59   }
60
61   var thisArg;
62   if (%_ArgumentsLength() > 1) {
63     thisArg = %_Arguments(1);
64   }
65
66   var needs_wrapper = false;
67   if (IS_NULL_OR_UNDEFINED(thisArg)) {
68     thisArg = %GetDefaultReceiver(predicate) || thisArg;
69   } else {
70     needs_wrapper = SHOULD_CREATE_WRAPPER(predicate, thisArg);
71   }
72
73   for (var i = 0; i < length; i++) {
74     if (i in array) {
75       var element = array[i];
76       var newThisArg = needs_wrapper ? ToObject(thisArg) : thisArg;
77       if (%_CallFunction(newThisArg, element, i, array, predicate)) {
78         return i;
79       }
80     }
81   }
82
83   return -1;
84 }
85
86
87 // ES6, draft 04-05-14, section 22.1.3.6
88 function ArrayFill(value /* [, start [, end ] ] */) {  // length == 1
89   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.fill");
90
91   var array = ToObject(this);
92   var length = TO_UINT32(array.length);
93
94   var i = 0;
95   var end = length;
96
97   if (%_ArgumentsLength() > 1) {
98     i = %_Arguments(1);
99     i = IS_UNDEFINED(i) ? 0 : TO_INTEGER(i);
100     if (%_ArgumentsLength() > 2) {
101       end = %_Arguments(2);
102       end = IS_UNDEFINED(end) ? length : TO_INTEGER(end);
103     }
104   }
105
106   if (i < 0) {
107     i += length;
108     if (i < 0) i = 0;
109   } else {
110     if (i > length) i = length;
111   }
112
113   if (end < 0) {
114     end += length;
115     if (end < 0) end = 0;
116   } else {
117     if (end > length) end = length;
118   }
119
120   if ((end - i) > 0 && ObjectIsFrozen(array)) {
121     throw MakeTypeError("array_functions_on_frozen",
122                         ["Array.prototype.fill"]);
123   }
124
125   for (; i < end; i++)
126     array[i] = value;
127   return array;
128 }
129
130 // ES6, draft 10-14-14, section 22.1.2.1
131 function ArrayFrom(arrayLike, mapfn, receiver) {
132   var items = ToObject(arrayLike);
133   var mapping = !IS_UNDEFINED(mapfn);
134
135   if (mapping) {
136     if (!IS_SPEC_FUNCTION(mapfn)) {
137       throw MakeTypeError('called_non_callable', [ mapfn ]);
138     } else if (IS_NULL_OR_UNDEFINED(receiver)) {
139       receiver = %GetDefaultReceiver(mapfn) || receiver;
140     } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(mapfn)) {
141       receiver = ToObject(receiver);
142     }
143   }
144
145   var iterable = GetMethod(items, symbolIterator);
146   var k;
147   var result;
148   var mappedValue;
149   var nextValue;
150
151   if (!IS_UNDEFINED(iterable)) {
152     result = %IsConstructor(this) ? new this() : [];
153
154     var iterator = GetIterator(items, iterable);
155
156     k = 0;
157     while (true) {
158       var next = iterator.next();
159
160       if (!IS_OBJECT(next)) {
161         throw MakeTypeError("iterator_result_not_an_object", [next]);
162       }
163
164       if (next.done) {
165         result.length = k;
166         return result;
167       }
168
169       nextValue = next.value;
170       if (mapping) {
171         mappedValue = %_CallFunction(receiver, nextValue, k, mapfn);
172       } else {
173         mappedValue = nextValue;
174       }
175       %AddElement(result, k++, mappedValue, NONE);
176     }
177   } else {
178     var len = ToLength(items.length);
179     result = %IsConstructor(this) ? new this(len) : new $Array(len);
180
181     for (k = 0; k < len; ++k) {
182       nextValue = items[k];
183       if (mapping) {
184         mappedValue = %_CallFunction(receiver, nextValue, k, mapfn);
185       } else {
186         mappedValue = nextValue;
187       }
188       %AddElement(result, k, mappedValue, NONE);
189     }
190
191     result.length = k;
192     return result;
193   }
194 }
195
196 // ES6, draft 05-22-14, section 22.1.2.3
197 function ArrayOf() {
198   var length = %_ArgumentsLength();
199   var constructor = this;
200   // TODO: Implement IsConstructor (ES6 section 7.2.5)
201   var array = %IsConstructor(constructor) ? new constructor(length) : [];
202   for (var i = 0; i < length; i++) {
203     %AddElement(array, i, %_Arguments(i), NONE);
204   }
205   array.length = length;
206   return array;
207 }
208
209 // -------------------------------------------------------------------
210
211 function HarmonyArrayExtendSymbolPrototype() {
212   %CheckIsBootstrapping();
213
214   InstallConstants($Symbol, $Array(
215     // TODO(dslomov, caitp): Move to symbol.js when shipping
216    "isConcatSpreadable", symbolIsConcatSpreadable
217   ));
218 }
219
220 HarmonyArrayExtendSymbolPrototype();
221
222 function HarmonyArrayExtendArrayPrototype() {
223   %CheckIsBootstrapping();
224
225   %FunctionSetLength(ArrayFrom, 1);
226
227   // Set up non-enumerable functions on the Array object.
228   InstallFunctions($Array, DONT_ENUM, $Array(
229     "from", ArrayFrom,
230     "of", ArrayOf
231   ));
232
233   // Set up the non-enumerable functions on the Array prototype object.
234   InstallFunctions($Array.prototype, DONT_ENUM, $Array(
235     "find", ArrayFind,
236     "findIndex", ArrayFindIndex,
237     "fill", ArrayFill
238   ));
239 }
240
241 HarmonyArrayExtendArrayPrototype();