9ace6ff821db13e977c9c1d387ef433f787805c3
[platform/upstream/v8.git] / src / runtime.js
1 // Copyright 2006-2008 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 // This files contains runtime support implemented in JavaScript.
6
7 // CAUTION: Some of the functions specified in this file are called
8 // directly from compiled code. These are the functions with names in
9 // ALL CAPS. The compiled code passes the first argument in 'this'.
10
11
12 // The following declarations are shared with other native JS files.
13 // They are all declared at this one spot to avoid redeclaration errors.
14 var $defaultString;
15 var $NaN;
16 var $nonNumberToNumber;
17 var $nonStringToString;
18 var $sameValue;
19 var $sameValueZero;
20 var $toInteger;
21 var $toLength;
22 var $toNumber;
23 var $toPositiveInteger;
24 var $toPrimitive;
25 var $toString;
26
27 var harmony_tolength = false;
28
29 (function(global, utils) {
30
31 %CheckIsBootstrapping();
32
33 var GlobalArray = global.Array;
34 var GlobalBoolean = global.Boolean;
35 var GlobalString = global.String;
36 var isConcatSpreadableSymbol =
37     utils.ImportNow("is_concat_spreadable_symbol");
38
39 // ----------------------------------------------------------------------------
40
41 /* -----------------------------
42    - - -   H e l p e r s   - - -
43    -----------------------------
44 */
45
46 function APPLY_PREPARE(args) {
47   var length;
48
49   // First check that the receiver is callable.
50   if (!IS_CALLABLE(this)) {
51     throw %make_type_error(kApplyNonFunction, %to_string_fun(this),
52                            typeof this);
53   }
54
55   // First check whether length is a positive Smi and args is an
56   // array. This is the fast case. If this fails, we do the slow case
57   // that takes care of more eventualities.
58   if (IS_ARRAY(args)) {
59     length = args.length;
60     if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength) {
61       return length;
62     }
63   }
64
65   length = (args == null) ? 0 : TO_UINT32(args.length);
66
67   // We can handle any number of apply arguments if the stack is
68   // big enough, but sanity check the value to avoid overflow when
69   // multiplying with pointer size.
70   if (length > kSafeArgumentsLength) throw %make_range_error(kStackOverflow);
71
72   // Make sure the arguments list has the right type.
73   if (args != null && !IS_SPEC_OBJECT(args)) {
74     throw %make_type_error(kWrongArgs, "Function.prototype.apply");
75   }
76
77   // Return the length which is the number of arguments to copy to the
78   // stack. It is guaranteed to be a small integer at this point.
79   return length;
80 }
81
82
83 function REFLECT_APPLY_PREPARE(args) {
84   var length;
85
86   // First check that the receiver is callable.
87   if (!IS_CALLABLE(this)) {
88     throw %make_type_error(kApplyNonFunction, %to_string_fun(this),
89                            typeof this);
90   }
91
92   // First check whether length is a positive Smi and args is an
93   // array. This is the fast case. If this fails, we do the slow case
94   // that takes care of more eventualities.
95   if (IS_ARRAY(args)) {
96     length = args.length;
97     if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength) {
98       return length;
99     }
100   }
101
102   if (!IS_SPEC_OBJECT(args)) {
103     throw %make_type_error(kWrongArgs, "Reflect.apply");
104   }
105
106   length = %to_length_fun(args.length);
107
108   // We can handle any number of apply arguments if the stack is
109   // big enough, but sanity check the value to avoid overflow when
110   // multiplying with pointer size.
111   if (length > kSafeArgumentsLength) throw %make_range_error(kStackOverflow);
112
113   // Return the length which is the number of arguments to copy to the
114   // stack. It is guaranteed to be a small integer at this point.
115   return length;
116 }
117
118
119 function REFLECT_CONSTRUCT_PREPARE(
120     args, newTarget) {
121   var length;
122   var ctorOk = IS_CALLABLE(this) && %IsConstructor(this);
123   var newTargetOk = IS_CALLABLE(newTarget) && %IsConstructor(newTarget);
124
125   // First check whether length is a positive Smi and args is an
126   // array. This is the fast case. If this fails, we do the slow case
127   // that takes care of more eventualities.
128   if (IS_ARRAY(args)) {
129     length = args.length;
130     if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength &&
131         ctorOk && newTargetOk) {
132       return length;
133     }
134   }
135
136   if (!ctorOk) {
137     if (!IS_CALLABLE(this)) {
138       throw %make_type_error(kCalledNonCallable, %to_string_fun(this));
139     } else {
140       throw %make_type_error(kNotConstructor, %to_string_fun(this));
141     }
142   }
143
144   if (!newTargetOk) {
145     if (!IS_CALLABLE(newTarget)) {
146       throw %make_type_error(kCalledNonCallable, %to_string_fun(newTarget));
147     } else {
148       throw %make_type_error(kNotConstructor, %to_string_fun(newTarget));
149     }
150   }
151
152   if (!IS_SPEC_OBJECT(args)) {
153     throw %make_type_error(kWrongArgs, "Reflect.construct");
154   }
155
156   length = %to_length_fun(args.length);
157
158   // We can handle any number of apply arguments if the stack is
159   // big enough, but sanity check the value to avoid overflow when
160   // multiplying with pointer size.
161   if (length > kSafeArgumentsLength) throw %make_range_error(kStackOverflow);
162
163   // Return the length which is the number of arguments to copy to the
164   // stack. It is guaranteed to be a small integer at this point.
165   return length;
166 }
167
168
169 function CONCAT_ITERABLE_TO_ARRAY(iterable) {
170   return %concat_iterable_to_array(this, iterable);
171 };
172
173
174 /* -------------------------------------
175    - - -   C o n v e r s i o n s   - - -
176    -------------------------------------
177 */
178
179 // ECMA-262, section 9.1, page 30. Use null/undefined for no hint,
180 // (1) for number hint, and (2) for string hint.
181 function ToPrimitive(x, hint) {
182   if (!IS_SPEC_OBJECT(x)) return x;
183   if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
184   return (hint == NUMBER_HINT) ? DefaultNumber(x) : DefaultString(x);
185 }
186
187
188 // ECMA-262, section 9.2, page 30
189 function ToBoolean(x) {
190   if (IS_BOOLEAN(x)) return x;
191   if (IS_STRING(x)) return x.length != 0;
192   if (x == null) return false;
193   if (IS_NUMBER(x)) return !((x == 0) || NUMBER_IS_NAN(x));
194   return true;
195 }
196
197
198 // ECMA-262, section 9.3, page 31.
199 function ToNumber(x) {
200   if (IS_NUMBER(x)) return x;
201   if (IS_STRING(x)) {
202     return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
203                                     : %StringToNumber(x);
204   }
205   if (IS_BOOLEAN(x)) return x ? 1 : 0;
206   if (IS_UNDEFINED(x)) return NAN;
207   // Types that can't be converted to number are caught in DefaultNumber.
208   return (IS_NULL(x)) ? 0 : ToNumber(DefaultNumber(x));
209 }
210
211 function NonNumberToNumber(x) {
212   if (IS_STRING(x)) {
213     return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
214                                     : %StringToNumber(x);
215   }
216   if (IS_BOOLEAN(x)) return x ? 1 : 0;
217   if (IS_UNDEFINED(x)) return NAN;
218   // Types that can't be converted to number are caught in DefaultNumber.
219   return (IS_NULL(x)) ? 0 : ToNumber(DefaultNumber(x));
220 }
221
222
223 // ECMA-262, section 9.8, page 35.
224 function ToString(x) {
225   if (IS_STRING(x)) return x;
226   if (IS_NUMBER(x)) return %_NumberToString(x);
227   if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
228   if (IS_UNDEFINED(x)) return 'undefined';
229   // Types that can't be converted to string are caught in DefaultString.
230   return (IS_NULL(x)) ? 'null' : ToString(DefaultString(x));
231 }
232
233 function NonStringToString(x) {
234   if (IS_NUMBER(x)) return %_NumberToString(x);
235   if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
236   if (IS_UNDEFINED(x)) return 'undefined';
237   // Types that can't be converted to string are caught in DefaultString.
238   return (IS_NULL(x)) ? 'null' : ToString(DefaultString(x));
239 }
240
241
242 // ECMA-262, section 9.4, page 34.
243 function ToInteger(x) {
244   if (%_IsSmi(x)) return x;
245   return %NumberToInteger(ToNumber(x));
246 }
247
248
249 // ES6, draft 08-24-14, section 7.1.15
250 function ToLength(arg) {
251   arg = ToInteger(arg);
252   if (arg < 0) return 0;
253   return arg < kMaxSafeInteger ? arg : kMaxSafeInteger;
254 }
255
256
257 // ES5, section 9.12
258 function SameValue(x, y) {
259   if (typeof x != typeof y) return false;
260   if (IS_NUMBER(x)) {
261     if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
262     // x is +0 and y is -0 or vice versa.
263     if (x === 0 && y === 0 && %_IsMinusZero(x) != %_IsMinusZero(y)) {
264       return false;
265     }
266   }
267   if (IS_SIMD_VALUE(x)) return %SimdSameValue(x, y);
268   return x === y;
269 }
270
271
272 // ES6, section 7.2.4
273 function SameValueZero(x, y) {
274   if (typeof x != typeof y) return false;
275   if (IS_NUMBER(x)) {
276     if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
277   }
278   if (IS_SIMD_VALUE(x)) return %SimdSameValueZero(x, y);
279   return x === y;
280 }
281
282
283 function ConcatIterableToArray(target, iterable) {
284    var index = target.length;
285    for (var element of iterable) {
286      %AddElement(target, index++, element);
287    }
288    return target;
289 }
290
291
292 /* ---------------------------------
293    - - -   U t i l i t i e s   - - -
294    ---------------------------------
295 */
296
297 // Returns if the given x is a primitive value - not an object or a
298 // function.
299 function IsPrimitive(x) {
300   // Even though the type of null is "object", null is still
301   // considered a primitive value. IS_SPEC_OBJECT handles this correctly
302   // (i.e., it will return false if x is null).
303   return !IS_SPEC_OBJECT(x);
304 }
305
306
307 // ES6, draft 10-14-14, section 22.1.3.1.1
308 function IsConcatSpreadable(O) {
309   if (!IS_SPEC_OBJECT(O)) return false;
310   var spreadable = O[isConcatSpreadableSymbol];
311   if (IS_UNDEFINED(spreadable)) return IS_ARRAY(O);
312   return ToBoolean(spreadable);
313 }
314
315
316 // ECMA-262, section 8.6.2.6, page 28.
317 function DefaultNumber(x) {
318   var valueOf = x.valueOf;
319   if (IS_CALLABLE(valueOf)) {
320     var v = %_Call(valueOf, x);
321     if (IS_SYMBOL(v)) throw MakeTypeError(kSymbolToNumber);
322     if (IS_SIMD_VALUE(x)) throw MakeTypeError(kSimdToNumber);
323     if (IsPrimitive(v)) return v;
324   }
325   var toString = x.toString;
326   if (IS_CALLABLE(toString)) {
327     var s = %_Call(toString, x);
328     if (IsPrimitive(s)) return s;
329   }
330   throw MakeTypeError(kCannotConvertToPrimitive);
331 }
332
333 // ECMA-262, section 8.6.2.6, page 28.
334 function DefaultString(x) {
335   if (!IS_SYMBOL_WRAPPER(x)) {
336     if (IS_SYMBOL(x)) throw MakeTypeError(kSymbolToString);
337     var toString = x.toString;
338     if (IS_CALLABLE(toString)) {
339       var s = %_Call(toString, x);
340       if (IsPrimitive(s)) return s;
341     }
342
343     var valueOf = x.valueOf;
344     if (IS_CALLABLE(valueOf)) {
345       var v = %_Call(valueOf, x);
346       if (IsPrimitive(v)) return v;
347     }
348   }
349   throw MakeTypeError(kCannotConvertToPrimitive);
350 }
351
352 function ToPositiveInteger(x, rangeErrorIndex) {
353   var i = TO_INTEGER_MAP_MINUS_ZERO(x);
354   if (i < 0) throw MakeRangeError(rangeErrorIndex);
355   return i;
356 }
357
358 //----------------------------------------------------------------------------
359
360 // NOTE: Setting the prototype for Array must take place as early as
361 // possible due to code generation for array literals.  When
362 // generating code for a array literal a boilerplate array is created
363 // that is cloned when running the code.  It is essential that the
364 // boilerplate gets the right prototype.
365 %FunctionSetPrototype(GlobalArray, new GlobalArray(0));
366
367 // ----------------------------------------------------------------------------
368 // Exports
369
370 $defaultString = DefaultString;
371 $NaN = %GetRootNaN();
372 $nonNumberToNumber = NonNumberToNumber;
373 $nonStringToString = NonStringToString;
374 $sameValue = SameValue;
375 $sameValueZero = SameValueZero;
376 $toInteger = ToInteger;
377 $toLength = ToLength;
378 $toNumber = ToNumber;
379 $toPositiveInteger = ToPositiveInteger;
380 $toPrimitive = ToPrimitive;
381 $toString = ToString;
382
383 %InstallToContext([
384   "apply_prepare_builtin", APPLY_PREPARE,
385   "concat_iterable_to_array_builtin", CONCAT_ITERABLE_TO_ARRAY,
386   "reflect_apply_prepare_builtin", REFLECT_APPLY_PREPARE,
387   "reflect_construct_prepare_builtin", REFLECT_CONSTRUCT_PREPARE,
388 ]);
389
390 %InstallToContext([
391   "concat_iterable_to_array", ConcatIterableToArray,
392   "non_number_to_number", NonNumberToNumber,
393   "non_string_to_string", NonStringToString,
394   "to_integer_fun", ToInteger,
395   "to_length_fun", ToLength,
396   "to_number_fun", ToNumber,
397   "to_primitive", ToPrimitive,
398   "to_string_fun", ToString,
399 ]);
400
401 utils.Export(function(to) {
402   to.ToBoolean = ToBoolean;
403   to.ToLength = ToLength;
404   to.ToNumber = ToNumber;
405   to.ToPrimitive = ToPrimitive;
406   to.ToString = ToString;
407 });
408
409 })