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.
5 // This files contains runtime support implemented in JavaScript.
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'.
12 // The following declarations are shared with other native JS files.
13 // They are all declared at this one spot to avoid redeclaration errors.
16 var $nonNumberToNumber;
17 var $nonStringToString;
23 var $toPositiveInteger;
26 var harmony_tolength = false;
28 (function(global, utils) {
30 %CheckIsBootstrapping();
32 var GlobalArray = global.Array;
33 var GlobalBoolean = global.Boolean;
34 var GlobalString = global.String;
35 var isConcatSpreadableSymbol =
36 utils.ImportNow("is_concat_spreadable_symbol");
38 // ----------------------------------------------------------------------------
40 /* -----------------------------
41 - - - H e l p e r s - - -
42 -----------------------------
45 function APPLY_PREPARE(args) {
48 // First check that the receiver is callable.
49 if (!IS_CALLABLE(this)) {
50 throw %make_type_error(kApplyNonFunction, %to_string_fun(this),
54 // First check whether length is a positive Smi and args is an
55 // array. This is the fast case. If this fails, we do the slow case
56 // that takes care of more eventualities.
59 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength) {
64 length = (args == null) ? 0 : TO_UINT32(args.length);
66 // We can handle any number of apply arguments if the stack is
67 // big enough, but sanity check the value to avoid overflow when
68 // multiplying with pointer size.
69 if (length > kSafeArgumentsLength) throw %make_range_error(kStackOverflow);
71 // Make sure the arguments list has the right type.
72 if (args != null && !IS_SPEC_OBJECT(args)) {
73 throw %make_type_error(kWrongArgs, "Function.prototype.apply");
76 // Return the length which is the number of arguments to copy to the
77 // stack. It is guaranteed to be a small integer at this point.
82 function REFLECT_APPLY_PREPARE(args) {
85 // First check that the receiver is callable.
86 if (!IS_CALLABLE(this)) {
87 throw %make_type_error(kApplyNonFunction, %to_string_fun(this),
91 // First check whether length is a positive Smi and args is an
92 // array. This is the fast case. If this fails, we do the slow case
93 // that takes care of more eventualities.
96 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength) {
101 if (!IS_SPEC_OBJECT(args)) {
102 throw %make_type_error(kWrongArgs, "Reflect.apply");
105 length = %to_length_fun(args.length);
107 // We can handle any number of apply arguments if the stack is
108 // big enough, but sanity check the value to avoid overflow when
109 // multiplying with pointer size.
110 if (length > kSafeArgumentsLength) throw %make_range_error(kStackOverflow);
112 // Return the length which is the number of arguments to copy to the
113 // stack. It is guaranteed to be a small integer at this point.
118 function REFLECT_CONSTRUCT_PREPARE(
121 var ctorOk = IS_CALLABLE(this) && %IsConstructor(this);
122 var newTargetOk = IS_CALLABLE(newTarget) && %IsConstructor(newTarget);
124 // First check whether length is a positive Smi and args is an
125 // array. This is the fast case. If this fails, we do the slow case
126 // that takes care of more eventualities.
127 if (IS_ARRAY(args)) {
128 length = args.length;
129 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength &&
130 ctorOk && newTargetOk) {
136 if (!IS_CALLABLE(this)) {
137 throw %make_type_error(kCalledNonCallable, %to_string_fun(this));
139 throw %make_type_error(kNotConstructor, %to_string_fun(this));
144 if (!IS_CALLABLE(newTarget)) {
145 throw %make_type_error(kCalledNonCallable, %to_string_fun(newTarget));
147 throw %make_type_error(kNotConstructor, %to_string_fun(newTarget));
151 if (!IS_SPEC_OBJECT(args)) {
152 throw %make_type_error(kWrongArgs, "Reflect.construct");
155 length = %to_length_fun(args.length);
157 // We can handle any number of apply arguments if the stack is
158 // big enough, but sanity check the value to avoid overflow when
159 // multiplying with pointer size.
160 if (length > kSafeArgumentsLength) throw %make_range_error(kStackOverflow);
162 // Return the length which is the number of arguments to copy to the
163 // stack. It is guaranteed to be a small integer at this point.
168 function CONCAT_ITERABLE_TO_ARRAY(iterable) {
169 return %concat_iterable_to_array(this, iterable);
173 /* -------------------------------------
174 - - - C o n v e r s i o n s - - -
175 -------------------------------------
178 // ECMA-262, section 9.2, page 30
179 function ToBoolean(x) {
180 if (IS_BOOLEAN(x)) return x;
181 if (IS_STRING(x)) return x.length != 0;
182 if (x == null) return false;
183 if (IS_NUMBER(x)) return !((x == 0) || NUMBER_IS_NAN(x));
188 // ECMA-262, section 9.3, page 31.
189 function ToNumber(x) {
190 if (IS_NUMBER(x)) return x;
192 return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
193 : %StringToNumber(x);
195 if (IS_BOOLEAN(x)) return x ? 1 : 0;
196 if (IS_UNDEFINED(x)) return NAN;
197 // Types that can't be converted to number are caught in DefaultNumber.
198 return (IS_NULL(x)) ? 0 : ToNumber(DefaultNumber(x));
201 function NonNumberToNumber(x) {
203 return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
204 : %StringToNumber(x);
206 if (IS_BOOLEAN(x)) return x ? 1 : 0;
207 if (IS_UNDEFINED(x)) return NAN;
208 // Types that can't be converted to number are caught in DefaultNumber.
209 return (IS_NULL(x)) ? 0 : ToNumber(DefaultNumber(x));
213 // ECMA-262, section 9.8, page 35.
214 function ToString(x) {
215 if (IS_STRING(x)) return x;
216 if (IS_NUMBER(x)) return %_NumberToString(x);
217 if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
218 if (IS_UNDEFINED(x)) return 'undefined';
219 // Types that can't be converted to string are caught in DefaultString.
220 return (IS_NULL(x)) ? 'null' : ToString(DefaultString(x));
223 function NonStringToString(x) {
224 if (IS_NUMBER(x)) return %_NumberToString(x);
225 if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
226 if (IS_UNDEFINED(x)) return 'undefined';
227 // Types that can't be converted to string are caught in DefaultString.
228 return (IS_NULL(x)) ? 'null' : ToString(DefaultString(x));
232 // ECMA-262, section 9.4, page 34.
233 function ToInteger(x) {
234 if (%_IsSmi(x)) return x;
235 return %NumberToInteger(ToNumber(x));
239 // ES6, draft 08-24-14, section 7.1.15
240 function ToLength(arg) {
241 arg = ToInteger(arg);
242 if (arg < 0) return 0;
243 return arg < kMaxSafeInteger ? arg : kMaxSafeInteger;
248 function SameValue(x, y) {
249 if (typeof x != typeof y) return false;
251 if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
252 // x is +0 and y is -0 or vice versa.
253 if (x === 0 && y === 0 && %_IsMinusZero(x) != %_IsMinusZero(y)) {
257 if (IS_SIMD_VALUE(x)) return %SimdSameValue(x, y);
262 // ES6, section 7.2.4
263 function SameValueZero(x, y) {
264 if (typeof x != typeof y) return false;
266 if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
268 if (IS_SIMD_VALUE(x)) return %SimdSameValueZero(x, y);
273 function ConcatIterableToArray(target, iterable) {
274 var index = target.length;
275 for (var element of iterable) {
276 %AddElement(target, index++, element);
282 /* ---------------------------------
283 - - - U t i l i t i e s - - -
284 ---------------------------------
287 // Returns if the given x is a primitive value - not an object or a
289 function IsPrimitive(x) {
290 // Even though the type of null is "object", null is still
291 // considered a primitive value. IS_SPEC_OBJECT handles this correctly
292 // (i.e., it will return false if x is null).
293 return !IS_SPEC_OBJECT(x);
297 // ES6, draft 10-14-14, section 22.1.3.1.1
298 function IsConcatSpreadable(O) {
299 if (!IS_SPEC_OBJECT(O)) return false;
300 var spreadable = O[isConcatSpreadableSymbol];
301 if (IS_UNDEFINED(spreadable)) return IS_ARRAY(O);
302 return ToBoolean(spreadable);
306 // ECMA-262, section 8.6.2.6, page 28.
307 function DefaultNumber(x) {
308 var valueOf = x.valueOf;
309 if (IS_CALLABLE(valueOf)) {
310 var v = %_Call(valueOf, x);
311 if (IS_SYMBOL(v)) throw MakeTypeError(kSymbolToNumber);
312 if (IS_SIMD_VALUE(x)) throw MakeTypeError(kSimdToNumber);
313 if (IsPrimitive(v)) return v;
315 var toString = x.toString;
316 if (IS_CALLABLE(toString)) {
317 var s = %_Call(toString, x);
318 if (IsPrimitive(s)) return s;
320 throw MakeTypeError(kCannotConvertToPrimitive);
323 // ECMA-262, section 8.6.2.6, page 28.
324 function DefaultString(x) {
325 if (!IS_SYMBOL_WRAPPER(x)) {
326 if (IS_SYMBOL(x)) throw MakeTypeError(kSymbolToString);
327 var toString = x.toString;
328 if (IS_CALLABLE(toString)) {
329 var s = %_Call(toString, x);
330 if (IsPrimitive(s)) return s;
333 var valueOf = x.valueOf;
334 if (IS_CALLABLE(valueOf)) {
335 var v = %_Call(valueOf, x);
336 if (IsPrimitive(v)) return v;
339 throw MakeTypeError(kCannotConvertToPrimitive);
342 function ToPositiveInteger(x, rangeErrorIndex) {
343 var i = TO_INTEGER_MAP_MINUS_ZERO(x);
344 if (i < 0) throw MakeRangeError(rangeErrorIndex);
348 //----------------------------------------------------------------------------
350 // NOTE: Setting the prototype for Array must take place as early as
351 // possible due to code generation for array literals. When
352 // generating code for a array literal a boilerplate array is created
353 // that is cloned when running the code. It is essential that the
354 // boilerplate gets the right prototype.
355 %FunctionSetPrototype(GlobalArray, new GlobalArray(0));
357 // ----------------------------------------------------------------------------
360 $defaultString = DefaultString;
361 $NaN = %GetRootNaN();
362 $nonNumberToNumber = NonNumberToNumber;
363 $nonStringToString = NonStringToString;
364 $sameValue = SameValue;
365 $sameValueZero = SameValueZero;
366 $toInteger = ToInteger;
367 $toLength = ToLength;
368 $toNumber = ToNumber;
369 $toPositiveInteger = ToPositiveInteger;
370 $toString = ToString;
373 "apply_prepare_builtin", APPLY_PREPARE,
374 "concat_iterable_to_array_builtin", CONCAT_ITERABLE_TO_ARRAY,
375 "reflect_apply_prepare_builtin", REFLECT_APPLY_PREPARE,
376 "reflect_construct_prepare_builtin", REFLECT_CONSTRUCT_PREPARE,
380 "concat_iterable_to_array", ConcatIterableToArray,
381 "non_number_to_number", NonNumberToNumber,
382 "non_string_to_string", NonStringToString,
383 "to_integer_fun", ToInteger,
384 "to_length_fun", ToLength,
385 "to_number_fun", ToNumber,
386 "to_string_fun", ToString,
389 utils.Export(function(to) {
390 to.ToBoolean = ToBoolean;
391 to.ToLength = ToLength;
392 to.ToNumber = ToNumber;
393 to.ToString = ToString;