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 /* -----------------------------------
13 - - - C o m p a r i s o n - - -
14 -----------------------------------
17 // The following declarations are shared with other native JS files.
18 // They are all declared at this one spot to avoid redeclaration errors.
26 var STRING_ADD_LEFT_STRONG;
28 var STRING_ADD_RIGHT_STRONG;
52 var CALL_NON_FUNCTION;
53 var CALL_NON_FUNCTION_AS_CONSTRUCTOR;
54 var CALL_FUNCTION_PROXY;
55 var CALL_FUNCTION_PROXY_AS_CONSTRUCTOR;
56 var CONCAT_ITERABLE_TO_ARRAY;
58 var REFLECT_APPLY_PREPARE;
59 var REFLECT_CONSTRUCT_PREPARE;
68 var $nonNumberToNumber;
69 var $nonStringToString;
77 var $toPositiveInteger;
81 (function(global, utils) {
83 %CheckIsBootstrapping();
85 var GlobalArray = global.Array;
86 var GlobalBoolean = global.Boolean;
87 var GlobalString = global.String;
88 var GlobalNumber = global.Number;
90 // ----------------------------------------------------------------------------
92 // ECMA-262 Section 11.9.3.
93 EQUALS = function EQUALS(y) {
94 if (IS_STRING(this) && IS_STRING(y)) return %StringEquals(this, y);
100 if (IS_NUMBER(y)) return %NumberEquals(x, y);
101 if (IS_NULL_OR_UNDEFINED(y)) return 1; // not equal
102 if (!IS_SPEC_OBJECT(y)) {
103 if (IS_SYMBOL(y) || IS_SIMD_VALUE(y)) return 1; // not equal
104 // String or boolean.
105 return %NumberEquals(x, %$toNumber(y));
107 y = %$toPrimitive(y, NO_HINT);
109 } else if (IS_STRING(x)) {
111 if (IS_STRING(y)) return %StringEquals(x, y);
112 if (IS_NUMBER(y)) return %NumberEquals(%$toNumber(x), y);
113 if (IS_BOOLEAN(y)) return %NumberEquals(%$toNumber(x), %$toNumber(y));
114 if (IS_NULL_OR_UNDEFINED(y)) return 1; // not equal
115 if (IS_SYMBOL(y) || IS_SIMD_VALUE(y)) return 1; // not equal
116 y = %$toPrimitive(y, NO_HINT);
118 } else if (IS_SYMBOL(x)) {
119 if (IS_SYMBOL(y)) return %_ObjectEquals(x, y) ? 0 : 1;
120 return 1; // not equal
121 } else if (IS_BOOLEAN(x)) {
122 if (IS_BOOLEAN(y)) return %_ObjectEquals(x, y) ? 0 : 1;
123 if (IS_NULL_OR_UNDEFINED(y)) return 1;
124 if (IS_NUMBER(y)) return %NumberEquals(%$toNumber(x), y);
125 if (IS_STRING(y)) return %NumberEquals(%$toNumber(x), %$toNumber(y));
126 if (IS_SYMBOL(y) || IS_SIMD_VALUE(y)) return 1; // not equal
129 y = %$toPrimitive(y, NO_HINT);
130 } else if (IS_NULL_OR_UNDEFINED(x)) {
131 return IS_NULL_OR_UNDEFINED(y) ? 0 : 1;
132 } else if (IS_SIMD_VALUE(x)) {
133 return %SimdEquals(x, y);
136 if (IS_SPEC_OBJECT(y)) return %_ObjectEquals(x, y) ? 0 : 1;
137 if (IS_NULL_OR_UNDEFINED(y)) return 1; // not equal
140 } else if (IS_SYMBOL(y) || IS_SIMD_VALUE(y)) {
141 return 1; // not equal
143 x = %$toPrimitive(x, NO_HINT);
148 // ECMA-262, section 11.9.4, page 56.
149 STRICT_EQUALS = function STRICT_EQUALS(x) {
150 if (IS_STRING(this)) {
151 if (!IS_STRING(x)) return 1; // not equal
152 return %StringEquals(this, x);
155 if (IS_NUMBER(this)) {
156 if (!IS_NUMBER(x)) return 1; // not equal
157 return %NumberEquals(this, x);
160 if (IS_SIMD_VALUE(this)) return %SimdEquals(this, x);
162 // If anything else gets here, we just do simple identity check.
163 // Objects (including functions), null, undefined and booleans were
164 // checked in the CompareStub, so there should be nothing left.
165 return %_ObjectEquals(this, x) ? 0 : 1;
169 // ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as
170 // the result when either (or both) the operands are NaN.
171 COMPARE = function COMPARE(x, ncr) {
174 // Fast cases for string, numbers and undefined compares.
175 if (IS_STRING(this)) {
176 if (IS_STRING(x)) return %_StringCompare(this, x);
177 if (IS_UNDEFINED(x)) return ncr;
179 } else if (IS_NUMBER(this)) {
180 if (IS_NUMBER(x)) return %NumberCompare(this, x, ncr);
181 if (IS_UNDEFINED(x)) return ncr;
183 } else if (IS_UNDEFINED(this)) {
184 if (!IS_UNDEFINED(x)) {
185 %$toPrimitive(x, NUMBER_HINT);
188 } else if (IS_UNDEFINED(x)) {
189 %$toPrimitive(this, NUMBER_HINT);
192 left = %$toPrimitive(this, NUMBER_HINT);
195 right = %$toPrimitive(x, NUMBER_HINT);
196 if (IS_STRING(left) && IS_STRING(right)) {
197 return %_StringCompare(left, right);
199 var left_number = %$toNumber(left);
200 var right_number = %$toNumber(right);
201 if (NUMBER_IS_NAN(left_number) || NUMBER_IS_NAN(right_number)) return ncr;
202 return %NumberCompare(left_number, right_number, ncr);
206 // Strong mode COMPARE throws if an implicit conversion would be performed
207 COMPARE_STRONG = function COMPARE_STRONG(x, ncr) {
208 if (IS_STRING(this) && IS_STRING(x)) return %_StringCompare(this, x);
209 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberCompare(this, x, ncr);
211 throw %MakeTypeError(kStrongImplicitConversion);
216 /* -----------------------------------
217 - - - A r i t h m e t i c - - -
218 -----------------------------------
221 // ECMA-262, section 11.6.1, page 50.
222 ADD = function ADD(x) {
223 // Fast case: Check for number operands and do the addition.
224 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x);
225 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x);
227 // Default implementation.
228 var a = %$toPrimitive(this, NO_HINT);
229 var b = %$toPrimitive(x, NO_HINT);
232 return %_StringAdd(a, %$toString(b));
233 } else if (IS_STRING(b)) {
234 return %_StringAdd(%$nonStringToString(a), b);
236 return %NumberAdd(%$toNumber(a), %$toNumber(b));
241 // Strong mode ADD throws if an implicit conversion would be performed
242 ADD_STRONG = function ADD_STRONG(x) {
243 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x);
244 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x);
246 throw %MakeTypeError(kStrongImplicitConversion);
250 // Left operand (this) is already a string.
251 STRING_ADD_LEFT = function STRING_ADD_LEFT(y) {
253 if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) {
257 ? %_NumberToString(y)
258 : %$toString(%$toPrimitive(y, NO_HINT));
261 return %_StringAdd(this, y);
265 // Left operand (this) is already a string.
266 STRING_ADD_LEFT_STRONG = function STRING_ADD_LEFT_STRONG(y) {
268 return %_StringAdd(this, y);
270 throw %MakeTypeError(kStrongImplicitConversion);
274 // Right operand (y) is already a string.
275 STRING_ADD_RIGHT = function STRING_ADD_RIGHT(y) {
278 if (IS_STRING_WRAPPER(x) && %_IsStringWrapperSafeForDefaultValueOf(x)) {
282 ? %_NumberToString(x)
283 : %$toString(%$toPrimitive(x, NO_HINT));
286 return %_StringAdd(x, y);
290 // Right operand (y) is already a string.
291 STRING_ADD_RIGHT_STRONG = function STRING_ADD_RIGHT_STRONG(y) {
292 if (IS_STRING(this)) {
293 return %_StringAdd(this, y);
295 throw %MakeTypeError(kStrongImplicitConversion);
299 // ECMA-262, section 11.6.2, page 50.
300 SUB = function SUB(y) {
301 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
302 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
303 return %NumberSub(x, y);
307 // Strong mode SUB throws if an implicit conversion would be performed
308 SUB_STRONG = function SUB_STRONG(y) {
309 if (IS_NUMBER(this) && IS_NUMBER(y)) {
310 return %NumberSub(this, y);
312 throw %MakeTypeError(kStrongImplicitConversion);
316 // ECMA-262, section 11.5.1, page 48.
317 MUL = function MUL(y) {
318 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
319 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
320 return %NumberMul(x, y);
324 // Strong mode MUL throws if an implicit conversion would be performed
325 MUL_STRONG = function MUL_STRONG(y) {
326 if (IS_NUMBER(this) && IS_NUMBER(y)) {
327 return %NumberMul(this, y);
329 throw %MakeTypeError(kStrongImplicitConversion);
333 // ECMA-262, section 11.5.2, page 49.
334 DIV = function DIV(y) {
335 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
336 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
337 return %NumberDiv(x, y);
341 // Strong mode DIV throws if an implicit conversion would be performed
342 DIV_STRONG = function DIV_STRONG(y) {
343 if (IS_NUMBER(this) && IS_NUMBER(y)) {
344 return %NumberDiv(this, y);
346 throw %MakeTypeError(kStrongImplicitConversion);
350 // ECMA-262, section 11.5.3, page 49.
351 MOD = function MOD(y) {
352 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
353 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
354 return %NumberMod(x, y);
358 // Strong mode MOD throws if an implicit conversion would be performed
359 MOD_STRONG = function MOD_STRONG(y) {
360 if (IS_NUMBER(this) && IS_NUMBER(y)) {
361 return %NumberMod(this, y);
363 throw %MakeTypeError(kStrongImplicitConversion);
367 /* -------------------------------------------
368 - - - B i t o p e r a t i o n s - - -
369 -------------------------------------------
372 // ECMA-262, section 11.10, page 57.
373 BIT_OR = function BIT_OR(y) {
374 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
375 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
376 return %NumberOr(x, y);
380 // Strong mode BIT_OR throws if an implicit conversion would be performed
381 BIT_OR_STRONG = function BIT_OR_STRONG(y) {
382 if (IS_NUMBER(this) && IS_NUMBER(y)) {
383 return %NumberOr(this, y);
385 throw %MakeTypeError(kStrongImplicitConversion);
389 // ECMA-262, section 11.10, page 57.
390 BIT_AND = function BIT_AND(y) {
392 if (IS_NUMBER(this)) {
394 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
396 x = %$nonNumberToNumber(this);
397 // Make sure to convert the right operand to a number before
398 // bailing out in the fast case, but after converting the
399 // left operand. This ensures that valueOf methods on the right
400 // operand are always executed.
401 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
402 // Optimize for the case where we end up AND'ing a value
403 // that doesn't convert to a number. This is common in
404 // certain benchmarks.
405 if (NUMBER_IS_NAN(x)) return 0;
407 return %NumberAnd(x, y);
411 // Strong mode BIT_AND throws if an implicit conversion would be performed
412 BIT_AND_STRONG = function BIT_AND_STRONG(y) {
413 if (IS_NUMBER(this) && IS_NUMBER(y)) {
414 return %NumberAnd(this, y);
416 throw %MakeTypeError(kStrongImplicitConversion);
420 // ECMA-262, section 11.10, page 57.
421 BIT_XOR = function BIT_XOR(y) {
422 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
423 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
424 return %NumberXor(x, y);
428 // Strong mode BIT_XOR throws if an implicit conversion would be performed
429 BIT_XOR_STRONG = function BIT_XOR_STRONG(y) {
430 if (IS_NUMBER(this) && IS_NUMBER(y)) {
431 return %NumberXor(this, y);
433 throw %MakeTypeError(kStrongImplicitConversion);
437 // ECMA-262, section 11.7.1, page 51.
438 SHL = function SHL(y) {
439 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
440 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
441 return %NumberShl(x, y);
445 // Strong mode SHL throws if an implicit conversion would be performed
446 SHL_STRONG = function SHL_STRONG(y) {
447 if (IS_NUMBER(this) && IS_NUMBER(y)) {
448 return %NumberShl(this, y);
450 throw %MakeTypeError(kStrongImplicitConversion);
454 // ECMA-262, section 11.7.2, page 51.
455 SAR = function SAR(y) {
457 if (IS_NUMBER(this)) {
459 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
461 x = %$nonNumberToNumber(this);
462 // Make sure to convert the right operand to a number before
463 // bailing out in the fast case, but after converting the
464 // left operand. This ensures that valueOf methods on the right
465 // operand are always executed.
466 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
467 // Optimize for the case where we end up shifting a value
468 // that doesn't convert to a number. This is common in
469 // certain benchmarks.
470 if (NUMBER_IS_NAN(x)) return 0;
472 return %NumberSar(x, y);
476 // Strong mode SAR throws if an implicit conversion would be performed
477 SAR_STRONG = function SAR_STRONG(y) {
478 if (IS_NUMBER(this) && IS_NUMBER(y)) {
479 return %NumberSar(this, y);
481 throw %MakeTypeError(kStrongImplicitConversion);
485 // ECMA-262, section 11.7.3, page 52.
486 SHR = function SHR(y) {
487 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
488 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
489 return %NumberShr(x, y);
493 // Strong mode SHR throws if an implicit conversion would be performed
494 SHR_STRONG = function SHR_STRONG(y) {
495 if (IS_NUMBER(this) && IS_NUMBER(y)) {
496 return %NumberShr(this, y);
498 throw %MakeTypeError(kStrongImplicitConversion);
502 /* -----------------------------
503 - - - H e l p e r s - - -
504 -----------------------------
507 // ECMA-262, section 11.4.1, page 46.
508 DELETE = function DELETE(key, language_mode) {
509 return %DeleteProperty(TO_OBJECT(this), key, language_mode);
513 // ECMA-262, section 11.8.7, page 54.
514 IN = function IN(x) {
515 if (!IS_SPEC_OBJECT(x)) {
516 throw %MakeTypeError(kInvalidInOperatorUse, this, x);
518 if (%_IsNonNegativeSmi(this)) {
519 if (IS_ARRAY(x) && %_HasFastPackedElements(x)) {
520 return this < x.length;
522 return %HasElement(x, this);
524 return %HasProperty(x, %$toName(this));
528 // ECMA-262, section 11.8.6, page 54. To make the implementation more
529 // efficient, the return value should be zero if the 'this' is an
530 // instance of F, and non-zero if not. This makes it possible to avoid
531 // an expensive ToBoolean conversion in the generated code.
532 INSTANCE_OF = function INSTANCE_OF(F) {
534 if (!IS_SPEC_FUNCTION(F)) {
535 throw %MakeTypeError(kInstanceofFunctionExpected, F);
538 // If V is not an object, return false.
539 if (!IS_SPEC_OBJECT(V)) {
543 // Check if function is bound, if so, get [[BoundFunction]] from it
544 // and use that instead of F.
545 var bindings = %BoundFunctionGetBindings(F);
547 F = bindings[kBoundFunctionIndex]; // Always a non-bound function.
549 // Get the prototype of F; if it is not an object, throw an error.
551 if (!IS_SPEC_OBJECT(O)) {
552 throw %MakeTypeError(kInstanceofNonobjectProto, O);
555 // Return whether or not O is in the prototype chain of V.
556 return %IsInPrototypeChain(O, V) ? 0 : 1;
560 CALL_NON_FUNCTION = function CALL_NON_FUNCTION() {
561 var delegate = %GetFunctionDelegate(this);
562 if (!IS_FUNCTION(delegate)) {
563 var callsite = %RenderCallSite();
564 if (callsite == "") callsite = typeof this;
565 throw %MakeTypeError(kCalledNonCallable, callsite);
567 return %Apply(delegate, this, arguments, 0, %_ArgumentsLength());
571 CALL_NON_FUNCTION_AS_CONSTRUCTOR = function CALL_NON_FUNCTION_AS_CONSTRUCTOR() {
572 var delegate = %GetConstructorDelegate(this);
573 if (!IS_FUNCTION(delegate)) {
574 var callsite = %RenderCallSite();
575 if (callsite == "") callsite = typeof this;
576 throw %MakeTypeError(kCalledNonCallable, callsite);
578 return %Apply(delegate, this, arguments, 0, %_ArgumentsLength());
582 CALL_FUNCTION_PROXY = function CALL_FUNCTION_PROXY() {
583 var arity = %_ArgumentsLength() - 1;
584 var proxy = %_Arguments(arity); // The proxy comes in as an additional arg.
585 var trap = %GetCallTrap(proxy);
586 return %Apply(trap, this, arguments, 0, arity);
590 CALL_FUNCTION_PROXY_AS_CONSTRUCTOR =
591 function CALL_FUNCTION_PROXY_AS_CONSTRUCTOR () {
593 var trap = %GetConstructTrap(proxy);
594 return %Apply(trap, this, arguments, 0, %_ArgumentsLength());
598 APPLY_PREPARE = function APPLY_PREPARE(args) {
600 // First check whether length is a positive Smi and args is an
601 // array. This is the fast case. If this fails, we do the slow case
602 // that takes care of more eventualities.
603 if (IS_ARRAY(args)) {
604 length = args.length;
605 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength &&
606 IS_SPEC_FUNCTION(this)) {
611 length = (args == null) ? 0 : TO_UINT32(args.length);
613 // We can handle any number of apply arguments if the stack is
614 // big enough, but sanity check the value to avoid overflow when
615 // multiplying with pointer size.
616 if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow);
618 if (!IS_SPEC_FUNCTION(this)) {
619 throw %MakeTypeError(kApplyNonFunction, %$toString(this), typeof this);
622 // Make sure the arguments list has the right type.
623 if (args != null && !IS_SPEC_OBJECT(args)) {
624 throw %MakeTypeError(kWrongArgs, "Function.prototype.apply");
627 // Return the length which is the number of arguments to copy to the
628 // stack. It is guaranteed to be a small integer at this point.
633 REFLECT_APPLY_PREPARE = function REFLECT_APPLY_PREPARE(args) {
635 // First check whether length is a positive Smi and args is an
636 // array. This is the fast case. If this fails, we do the slow case
637 // that takes care of more eventualities.
638 if (IS_ARRAY(args)) {
639 length = args.length;
640 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength &&
641 IS_SPEC_FUNCTION(this)) {
646 if (!IS_SPEC_FUNCTION(this)) {
647 throw %MakeTypeError(kCalledNonCallable, %$toString(this));
650 if (!IS_SPEC_OBJECT(args)) {
651 throw %MakeTypeError(kWrongArgs, "Reflect.apply");
654 length = %$toLength(args.length);
656 // We can handle any number of apply arguments if the stack is
657 // big enough, but sanity check the value to avoid overflow when
658 // multiplying with pointer size.
659 if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow);
661 // Return the length which is the number of arguments to copy to the
662 // stack. It is guaranteed to be a small integer at this point.
667 REFLECT_CONSTRUCT_PREPARE = function REFLECT_CONSTRUCT_PREPARE(
670 var ctorOk = IS_SPEC_FUNCTION(this) && %IsConstructor(this);
671 var newTargetOk = IS_SPEC_FUNCTION(newTarget) && %IsConstructor(newTarget);
673 // First check whether length is a positive Smi and args is an
674 // array. This is the fast case. If this fails, we do the slow case
675 // that takes care of more eventualities.
676 if (IS_ARRAY(args)) {
677 length = args.length;
678 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength &&
679 ctorOk && newTargetOk) {
685 if (!IS_SPEC_FUNCTION(this)) {
686 throw %MakeTypeError(kCalledNonCallable, %$toString(this));
688 throw %MakeTypeError(kNotConstructor, %$toString(this));
693 if (!IS_SPEC_FUNCTION(newTarget)) {
694 throw %MakeTypeError(kCalledNonCallable, %$toString(newTarget));
696 throw %MakeTypeError(kNotConstructor, %$toString(newTarget));
700 if (!IS_SPEC_OBJECT(args)) {
701 throw %MakeTypeError(kWrongArgs, "Reflect.construct");
704 length = %$toLength(args.length);
706 // We can handle any number of apply arguments if the stack is
707 // big enough, but sanity check the value to avoid overflow when
708 // multiplying with pointer size.
709 if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow);
711 // Return the length which is the number of arguments to copy to the
712 // stack. It is guaranteed to be a small integer at this point.
717 CONCAT_ITERABLE_TO_ARRAY = function CONCAT_ITERABLE_TO_ARRAY(iterable) {
718 return %$concatIterableToArray(this, iterable);
722 STACK_OVERFLOW = function STACK_OVERFLOW(length) {
723 throw %MakeRangeError(kStackOverflow);
727 // Convert the receiver to a number - forward to ToNumber.
728 TO_NUMBER = function TO_NUMBER() {
729 return %$toNumber(this);
733 // Convert the receiver to a string - forward to ToString.
734 TO_STRING = function TO_STRING() {
735 return %$toString(this);
739 // Convert the receiver to a string or symbol - forward to ToName.
740 TO_NAME = function TO_NAME() {
741 return %$toName(this);
745 /* -------------------------------------
746 - - - C o n v e r s i o n s - - -
747 -------------------------------------
750 // ECMA-262, section 9.1, page 30. Use null/undefined for no hint,
751 // (1) for number hint, and (2) for string hint.
752 function ToPrimitive(x, hint) {
754 if (IS_STRING(x)) return x;
756 if (!IS_SPEC_OBJECT(x)) return x;
757 if (IS_SIMD_VALUE(x)) return x;
758 if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
759 return (hint == NUMBER_HINT) ? DefaultNumber(x) : DefaultString(x);
763 // ECMA-262, section 9.2, page 30
764 function ToBoolean(x) {
765 if (IS_BOOLEAN(x)) return x;
766 if (IS_STRING(x)) return x.length != 0;
767 if (x == null) return false;
768 if (IS_NUMBER(x)) return !((x == 0) || NUMBER_IS_NAN(x));
773 // ECMA-262, section 9.3, page 31.
774 function ToNumber(x) {
775 if (IS_NUMBER(x)) return x;
777 return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
778 : %StringToNumber(x);
780 if (IS_BOOLEAN(x)) return x ? 1 : 0;
781 if (IS_UNDEFINED(x)) return NAN;
782 // Types that can't be converted to number are caught in DefaultNumber.
783 return (IS_NULL(x)) ? 0 : ToNumber(DefaultNumber(x));
786 function NonNumberToNumber(x) {
788 return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
789 : %StringToNumber(x);
791 if (IS_BOOLEAN(x)) return x ? 1 : 0;
792 if (IS_UNDEFINED(x)) return NAN;
793 // Types that can't be converted to number are caught in DefaultNumber.
794 return (IS_NULL(x)) ? 0 : ToNumber(DefaultNumber(x));
798 // ECMA-262, section 9.8, page 35.
799 function ToString(x) {
800 if (IS_STRING(x)) return x;
801 if (IS_NUMBER(x)) return %_NumberToString(x);
802 if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
803 if (IS_UNDEFINED(x)) return 'undefined';
804 // Types that can't be converted to string are caught in DefaultString.
805 return (IS_NULL(x)) ? 'null' : ToString(DefaultString(x));
808 function NonStringToString(x) {
809 if (IS_NUMBER(x)) return %_NumberToString(x);
810 if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
811 if (IS_UNDEFINED(x)) return 'undefined';
812 // Types that can't be converted to string are caught in DefaultString.
813 return (IS_NULL(x)) ? 'null' : ToString(DefaultString(x));
819 return IS_SYMBOL(x) ? x : ToString(x);
823 // ECMA-262, section 9.4, page 34.
824 function ToInteger(x) {
825 if (%_IsSmi(x)) return x;
826 return %NumberToInteger(ToNumber(x));
830 // ES6, draft 08-24-14, section 7.1.15
831 function ToLength(arg) {
832 arg = ToInteger(arg);
833 if (arg < 0) return 0;
834 return arg < GlobalNumber.MAX_SAFE_INTEGER ? arg
835 : GlobalNumber.MAX_SAFE_INTEGER;
840 function SameValue(x, y) {
841 if (typeof x != typeof y) return false;
843 if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
844 // x is +0 and y is -0 or vice versa.
845 if (x === 0 && y === 0 && %_IsMinusZero(x) != %_IsMinusZero(y)) {
849 if (IS_SIMD_VALUE(x)) return %SimdSameValue(x, y);
854 // ES6, section 7.2.4
855 function SameValueZero(x, y) {
856 if (typeof x != typeof y) return false;
858 if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
860 if (IS_SIMD_VALUE(x)) return %SimdSameValueZero(x, y);
865 function ConcatIterableToArray(target, iterable) {
866 var index = target.length;
867 for (var element of iterable) {
868 %AddElement(target, index++, element);
874 /* ---------------------------------
875 - - - U t i l i t i e s - - -
876 ---------------------------------
879 // Returns if the given x is a primitive value - not an object or a
881 function IsPrimitive(x) {
882 // Even though the type of null is "object", null is still
883 // considered a primitive value. IS_SPEC_OBJECT handles this correctly
884 // (i.e., it will return false if x is null).
885 return !IS_SPEC_OBJECT(x);
889 // ES6, draft 10-14-14, section 22.1.3.1.1
890 function IsConcatSpreadable(O) {
891 if (!IS_SPEC_OBJECT(O)) return false;
892 var spreadable = O[symbolIsConcatSpreadable];
893 if (IS_UNDEFINED(spreadable)) return IS_ARRAY(O);
894 return ToBoolean(spreadable);
898 // ECMA-262, section 8.6.2.6, page 28.
899 function DefaultNumber(x) {
900 var valueOf = x.valueOf;
901 if (IS_SPEC_FUNCTION(valueOf)) {
902 var v = %_CallFunction(x, valueOf);
903 if (IS_SYMBOL(v)) throw MakeTypeError(kSymbolToNumber);
904 if (IS_SIMD_VALUE(x)) throw MakeTypeError(kSimdToNumber);
905 if (IsPrimitive(v)) return v;
907 var toString = x.toString;
908 if (IS_SPEC_FUNCTION(toString)) {
909 var s = %_CallFunction(x, toString);
910 if (IsPrimitive(s)) return s;
912 throw MakeTypeError(kCannotConvertToPrimitive);
915 // ECMA-262, section 8.6.2.6, page 28.
916 function DefaultString(x) {
917 if (!IS_SYMBOL_WRAPPER(x)) {
918 if (IS_SYMBOL(x)) throw MakeTypeError(kSymbolToString);
919 var toString = x.toString;
920 if (IS_SPEC_FUNCTION(toString)) {
921 var s = %_CallFunction(x, toString);
922 if (IsPrimitive(s)) return s;
925 var valueOf = x.valueOf;
926 if (IS_SPEC_FUNCTION(valueOf)) {
927 var v = %_CallFunction(x, valueOf);
928 if (IsPrimitive(v)) return v;
931 throw MakeTypeError(kCannotConvertToPrimitive);
934 function ToPositiveInteger(x, rangeErrorIndex) {
935 var i = TO_INTEGER_MAP_MINUS_ZERO(x);
936 if (i < 0) throw MakeRangeError(rangeErrorIndex);
940 //----------------------------------------------------------------------------
942 // NOTE: Setting the prototype for Array must take place as early as
943 // possible due to code generation for array literals. When
944 // generating code for a array literal a boilerplate array is created
945 // that is cloned when running the code. It is essential that the
946 // boilerplate gets the right prototype.
947 %FunctionSetPrototype(GlobalArray, new GlobalArray(0));
949 //----------------------------------------------------------------------------
951 $concatIterableToArray = ConcatIterableToArray;
952 $defaultNumber = DefaultNumber;
953 $defaultString = DefaultString;
954 $NaN = %GetRootNaN();
955 $nonNumberToNumber = NonNumberToNumber;
956 $nonStringToString = NonStringToString;
957 $sameValue = SameValue;
958 $sameValueZero = SameValueZero;
959 $toBoolean = ToBoolean;
960 $toInteger = ToInteger;
961 $toLength = ToLength;
963 $toNumber = ToNumber;
964 $toPositiveInteger = ToPositiveInteger;
965 $toPrimitive = ToPrimitive;
966 $toString = ToString;