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;
69 var $nonNumberToNumber;
70 var $nonStringToString;
80 var $toPositiveInteger;
85 (function(global, utils) {
87 %CheckIsBootstrapping();
89 var GlobalArray = global.Array;
90 var GlobalBoolean = global.Boolean;
91 var GlobalString = global.String;
92 var GlobalNumber = global.Number;
94 // ----------------------------------------------------------------------------
96 // ECMA-262 Section 11.9.3.
97 EQUALS = function EQUALS(y) {
98 if (IS_STRING(this) && IS_STRING(y)) return %StringEquals(this, y);
104 if (IS_NUMBER(y)) return %NumberEquals(x, y);
105 if (IS_NULL_OR_UNDEFINED(y)) return 1; // not equal
106 if (IS_SYMBOL(y) || IS_FLOAT32X4(y)) return 1; // not equal
107 if (!IS_SPEC_OBJECT(y)) {
108 // String or boolean.
109 return %NumberEquals(x, %$toNumber(y));
111 y = %$toPrimitive(y, NO_HINT);
113 } else if (IS_STRING(x)) {
115 if (IS_STRING(y)) return %StringEquals(x, y);
116 if (IS_SYMBOL(y) || IS_FLOAT32X4(y)) return 1; // not equal
117 if (IS_NUMBER(y)) return %NumberEquals(%$toNumber(x), y);
118 if (IS_BOOLEAN(y)) return %NumberEquals(%$toNumber(x), %$toNumber(y));
119 if (IS_NULL_OR_UNDEFINED(y)) return 1; // not equal
120 y = %$toPrimitive(y, NO_HINT);
122 } else if (IS_SYMBOL(x)) {
123 if (IS_SYMBOL(y)) return %_ObjectEquals(x, y) ? 0 : 1;
124 return 1; // not equal
125 } else if (IS_BOOLEAN(x)) {
126 if (IS_BOOLEAN(y)) return %_ObjectEquals(x, y) ? 0 : 1;
127 if (IS_NULL_OR_UNDEFINED(y)) return 1;
128 if (IS_NUMBER(y)) return %NumberEquals(%$toNumber(x), y);
129 if (IS_STRING(y)) return %NumberEquals(%$toNumber(x), %$toNumber(y));
130 if (IS_SYMBOL(y) || IS_FLOAT32X4(y)) return 1; // not equal
133 y = %$toPrimitive(y, NO_HINT);
134 } else if (IS_NULL_OR_UNDEFINED(x)) {
135 return IS_NULL_OR_UNDEFINED(y) ? 0 : 1;
136 } else if (IS_FLOAT32X4(x)) {
138 return %Float32x4Equals(x, y);
139 return 1; // not equal
142 if (IS_SPEC_OBJECT(y)) {
143 return %_ObjectEquals(x, y) ? 0 : 1;
145 if (IS_NULL_OR_UNDEFINED(y)) return 1; // not equal
146 if (IS_SYMBOL(y) || IS_FLOAT32X4(y)) return 1; // not equal
147 if (IS_BOOLEAN(y)) y = %$toNumber(y);
148 x = %$toPrimitive(x, NO_HINT);
153 // ECMA-262, section 11.9.4, page 56.
154 STRICT_EQUALS = function STRICT_EQUALS(x) {
155 if (IS_STRING(this)) {
156 if (!IS_STRING(x)) return 1; // not equal
157 return %StringEquals(this, x);
160 if (IS_NUMBER(this)) {
161 if (!IS_NUMBER(x)) return 1; // not equal
162 return %NumberEquals(this, x);
165 if (IS_FLOAT32X4(this) && IS_FLOAT32X4(x))
166 return %Float32x4Equals(this, x);
168 // If anything else gets here, we just do simple identity check.
169 // Objects (including functions), null, undefined and booleans were
170 // checked in the CompareStub, so there should be nothing left.
171 return %_ObjectEquals(this, x) ? 0 : 1;
175 // ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as
176 // the result when either (or both) the operands are NaN.
177 COMPARE = function COMPARE(x, ncr) {
180 // Fast cases for string, numbers and undefined compares.
181 if (IS_STRING(this)) {
182 if (IS_STRING(x)) return %_StringCompare(this, x);
183 if (IS_UNDEFINED(x)) return ncr;
185 } else if (IS_NUMBER(this)) {
186 if (IS_NUMBER(x)) return %NumberCompare(this, x, ncr);
187 if (IS_UNDEFINED(x)) return ncr;
189 } else if (IS_UNDEFINED(this)) {
190 if (!IS_UNDEFINED(x)) {
191 %$toPrimitive(x, NUMBER_HINT);
194 } else if (IS_UNDEFINED(x)) {
195 %$toPrimitive(this, NUMBER_HINT);
198 left = %$toPrimitive(this, NUMBER_HINT);
201 right = %$toPrimitive(x, NUMBER_HINT);
202 if (IS_STRING(left) && IS_STRING(right)) {
203 return %_StringCompare(left, right);
205 var left_number = %$toNumber(left);
206 var right_number = %$toNumber(right);
207 if (NUMBER_IS_NAN(left_number) || NUMBER_IS_NAN(right_number)) return ncr;
208 return %NumberCompare(left_number, right_number, ncr);
212 // Strong mode COMPARE throws if an implicit conversion would be performed
213 COMPARE_STRONG = function COMPARE_STRONG(x, ncr) {
214 if (IS_STRING(this) && IS_STRING(x)) return %_StringCompare(this, x);
215 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberCompare(this, x, ncr);
217 throw %MakeTypeError(kStrongImplicitConversion);
222 /* -----------------------------------
223 - - - A r i t h m e t i c - - -
224 -----------------------------------
227 // ECMA-262, section 11.6.1, page 50.
228 ADD = function ADD(x) {
229 // Fast case: Check for number operands and do the addition.
230 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x);
231 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x);
233 // Default implementation.
234 var a = %$toPrimitive(this, NO_HINT);
235 var b = %$toPrimitive(x, NO_HINT);
238 return %_StringAdd(a, %$toString(b));
239 } else if (IS_STRING(b)) {
240 return %_StringAdd(%$nonStringToString(a), b);
242 return %NumberAdd(%$toNumber(a), %$toNumber(b));
247 // Strong mode ADD throws if an implicit conversion would be performed
248 ADD_STRONG = function ADD_STRONG(x) {
249 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x);
250 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x);
252 throw %MakeTypeError(kStrongImplicitConversion);
256 // Left operand (this) is already a string.
257 STRING_ADD_LEFT = function STRING_ADD_LEFT(y) {
259 if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) {
263 ? %_NumberToString(y)
264 : %$toString(%$toPrimitive(y, NO_HINT));
267 return %_StringAdd(this, y);
271 // Left operand (this) is already a string.
272 STRING_ADD_LEFT_STRONG = function STRING_ADD_LEFT_STRONG(y) {
274 return %_StringAdd(this, y);
276 throw %MakeTypeError(kStrongImplicitConversion);
280 // Right operand (y) is already a string.
281 STRING_ADD_RIGHT = function STRING_ADD_RIGHT(y) {
284 if (IS_STRING_WRAPPER(x) && %_IsStringWrapperSafeForDefaultValueOf(x)) {
288 ? %_NumberToString(x)
289 : %$toString(%$toPrimitive(x, NO_HINT));
292 return %_StringAdd(x, y);
296 // Right operand (y) is already a string.
297 STRING_ADD_RIGHT_STRONG = function STRING_ADD_RIGHT_STRONG(y) {
298 if (IS_STRING(this)) {
299 return %_StringAdd(this, y);
301 throw %MakeTypeError(kStrongImplicitConversion);
305 // ECMA-262, section 11.6.2, page 50.
306 SUB = function SUB(y) {
307 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
308 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
309 return %NumberSub(x, y);
313 // Strong mode SUB throws if an implicit conversion would be performed
314 SUB_STRONG = function SUB_STRONG(y) {
315 if (IS_NUMBER(this) && IS_NUMBER(y)) {
316 return %NumberSub(this, y);
318 throw %MakeTypeError(kStrongImplicitConversion);
322 // ECMA-262, section 11.5.1, page 48.
323 MUL = function MUL(y) {
324 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
325 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
326 return %NumberMul(x, y);
330 // Strong mode MUL throws if an implicit conversion would be performed
331 MUL_STRONG = function MUL_STRONG(y) {
332 if (IS_NUMBER(this) && IS_NUMBER(y)) {
333 return %NumberMul(this, y);
335 throw %MakeTypeError(kStrongImplicitConversion);
339 // ECMA-262, section 11.5.2, page 49.
340 DIV = function DIV(y) {
341 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
342 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
343 return %NumberDiv(x, y);
347 // Strong mode DIV throws if an implicit conversion would be performed
348 DIV_STRONG = function DIV_STRONG(y) {
349 if (IS_NUMBER(this) && IS_NUMBER(y)) {
350 return %NumberDiv(this, y);
352 throw %MakeTypeError(kStrongImplicitConversion);
356 // ECMA-262, section 11.5.3, page 49.
357 MOD = function MOD(y) {
358 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
359 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
360 return %NumberMod(x, y);
364 // Strong mode MOD throws if an implicit conversion would be performed
365 MOD_STRONG = function MOD_STRONG(y) {
366 if (IS_NUMBER(this) && IS_NUMBER(y)) {
367 return %NumberMod(this, y);
369 throw %MakeTypeError(kStrongImplicitConversion);
373 /* -------------------------------------------
374 - - - B i t o p e r a t i o n s - - -
375 -------------------------------------------
378 // ECMA-262, section 11.10, page 57.
379 BIT_OR = function BIT_OR(y) {
380 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
381 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
382 return %NumberOr(x, y);
386 // Strong mode BIT_OR throws if an implicit conversion would be performed
387 BIT_OR_STRONG = function BIT_OR_STRONG(y) {
388 if (IS_NUMBER(this) && IS_NUMBER(y)) {
389 return %NumberOr(this, y);
391 throw %MakeTypeError(kStrongImplicitConversion);
395 // ECMA-262, section 11.10, page 57.
396 BIT_AND = function BIT_AND(y) {
398 if (IS_NUMBER(this)) {
400 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
402 x = %$nonNumberToNumber(this);
403 // Make sure to convert the right operand to a number before
404 // bailing out in the fast case, but after converting the
405 // left operand. This ensures that valueOf methods on the right
406 // operand are always executed.
407 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
408 // Optimize for the case where we end up AND'ing a value
409 // that doesn't convert to a number. This is common in
410 // certain benchmarks.
411 if (NUMBER_IS_NAN(x)) return 0;
413 return %NumberAnd(x, y);
417 // Strong mode BIT_AND throws if an implicit conversion would be performed
418 BIT_AND_STRONG = function BIT_AND_STRONG(y) {
419 if (IS_NUMBER(this) && IS_NUMBER(y)) {
420 return %NumberAnd(this, y);
422 throw %MakeTypeError(kStrongImplicitConversion);
426 // ECMA-262, section 11.10, page 57.
427 BIT_XOR = function BIT_XOR(y) {
428 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
429 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
430 return %NumberXor(x, y);
434 // Strong mode BIT_XOR throws if an implicit conversion would be performed
435 BIT_XOR_STRONG = function BIT_XOR_STRONG(y) {
436 if (IS_NUMBER(this) && IS_NUMBER(y)) {
437 return %NumberXor(this, y);
439 throw %MakeTypeError(kStrongImplicitConversion);
443 // ECMA-262, section 11.7.1, page 51.
444 SHL = function SHL(y) {
445 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
446 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
447 return %NumberShl(x, y);
451 // Strong mode SHL throws if an implicit conversion would be performed
452 SHL_STRONG = function SHL_STRONG(y) {
453 if (IS_NUMBER(this) && IS_NUMBER(y)) {
454 return %NumberShl(this, y);
456 throw %MakeTypeError(kStrongImplicitConversion);
460 // ECMA-262, section 11.7.2, page 51.
461 SAR = function SAR(y) {
463 if (IS_NUMBER(this)) {
465 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
467 x = %$nonNumberToNumber(this);
468 // Make sure to convert the right operand to a number before
469 // bailing out in the fast case, but after converting the
470 // left operand. This ensures that valueOf methods on the right
471 // operand are always executed.
472 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
473 // Optimize for the case where we end up shifting a value
474 // that doesn't convert to a number. This is common in
475 // certain benchmarks.
476 if (NUMBER_IS_NAN(x)) return 0;
478 return %NumberSar(x, y);
482 // Strong mode SAR throws if an implicit conversion would be performed
483 SAR_STRONG = function SAR_STRONG(y) {
484 if (IS_NUMBER(this) && IS_NUMBER(y)) {
485 return %NumberSar(this, y);
487 throw %MakeTypeError(kStrongImplicitConversion);
491 // ECMA-262, section 11.7.3, page 52.
492 SHR = function SHR(y) {
493 var x = IS_NUMBER(this) ? this : %$nonNumberToNumber(this);
494 if (!IS_NUMBER(y)) y = %$nonNumberToNumber(y);
495 return %NumberShr(x, y);
499 // Strong mode SHR throws if an implicit conversion would be performed
500 SHR_STRONG = function SHR_STRONG(y) {
501 if (IS_NUMBER(this) && IS_NUMBER(y)) {
502 return %NumberShr(this, y);
504 throw %MakeTypeError(kStrongImplicitConversion);
508 /* -----------------------------
509 - - - H e l p e r s - - -
510 -----------------------------
513 // ECMA-262, section 11.4.1, page 46.
514 DELETE = function DELETE(key, language_mode) {
515 return %DeleteProperty(%$toObject(this), key, language_mode);
519 // ECMA-262, section 11.8.7, page 54.
520 IN = function IN(x) {
521 if (!IS_SPEC_OBJECT(x)) {
522 throw %MakeTypeError(kInvalidInOperatorUse, this, x);
524 if (%_IsNonNegativeSmi(this)) {
525 if (IS_ARRAY(x) && %_HasFastPackedElements(x)) {
526 return this < x.length;
528 return %HasElement(x, this);
530 return %HasProperty(x, %$toName(this));
534 // ECMA-262, section 11.8.6, page 54. To make the implementation more
535 // efficient, the return value should be zero if the 'this' is an
536 // instance of F, and non-zero if not. This makes it possible to avoid
537 // an expensive ToBoolean conversion in the generated code.
538 INSTANCE_OF = function INSTANCE_OF(F) {
540 if (!IS_SPEC_FUNCTION(F)) {
541 throw %MakeTypeError(kInstanceofFunctionExpected, F);
544 // If V is not an object, return false.
545 if (!IS_SPEC_OBJECT(V)) {
549 // Check if function is bound, if so, get [[BoundFunction]] from it
550 // and use that instead of F.
551 var bindings = %BoundFunctionGetBindings(F);
553 F = bindings[kBoundFunctionIndex]; // Always a non-bound function.
555 // Get the prototype of F; if it is not an object, throw an error.
557 if (!IS_SPEC_OBJECT(O)) {
558 throw %MakeTypeError(kInstanceofNonobjectProto, O);
561 // Return whether or not O is in the prototype chain of V.
562 return %IsInPrototypeChain(O, V) ? 0 : 1;
566 CALL_NON_FUNCTION = function CALL_NON_FUNCTION() {
567 var delegate = %GetFunctionDelegate(this);
568 if (!IS_FUNCTION(delegate)) {
569 var callsite = %RenderCallSite();
570 if (callsite == "") callsite = typeof this;
571 throw %MakeTypeError(kCalledNonCallable, callsite);
573 return %Apply(delegate, this, arguments, 0, %_ArgumentsLength());
577 CALL_NON_FUNCTION_AS_CONSTRUCTOR = function CALL_NON_FUNCTION_AS_CONSTRUCTOR() {
578 var delegate = %GetConstructorDelegate(this);
579 if (!IS_FUNCTION(delegate)) {
580 var callsite = %RenderCallSite();
581 if (callsite == "") callsite = typeof this;
582 throw %MakeTypeError(kCalledNonCallable, callsite);
584 return %Apply(delegate, this, arguments, 0, %_ArgumentsLength());
588 CALL_FUNCTION_PROXY = function CALL_FUNCTION_PROXY() {
589 var arity = %_ArgumentsLength() - 1;
590 var proxy = %_Arguments(arity); // The proxy comes in as an additional arg.
591 var trap = %GetCallTrap(proxy);
592 return %Apply(trap, this, arguments, 0, arity);
596 CALL_FUNCTION_PROXY_AS_CONSTRUCTOR =
597 function CALL_FUNCTION_PROXY_AS_CONSTRUCTOR () {
599 var trap = %GetConstructTrap(proxy);
600 return %Apply(trap, this, arguments, 0, %_ArgumentsLength());
604 APPLY_PREPARE = function APPLY_PREPARE(args) {
606 // First check whether length is a positive Smi and args is an
607 // array. This is the fast case. If this fails, we do the slow case
608 // that takes care of more eventualities.
609 if (IS_ARRAY(args)) {
610 length = args.length;
611 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength &&
612 IS_SPEC_FUNCTION(this)) {
617 length = (args == null) ? 0 : %$toUint32(args.length);
619 // We can handle any number of apply arguments if the stack is
620 // big enough, but sanity check the value to avoid overflow when
621 // multiplying with pointer size.
622 if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow);
624 if (!IS_SPEC_FUNCTION(this)) {
625 throw %MakeTypeError(kApplyNonFunction, %$toString(this), typeof this);
628 // Make sure the arguments list has the right type.
629 if (args != null && !IS_SPEC_OBJECT(args)) {
630 throw %MakeTypeError(kWrongArgs, "Function.prototype.apply");
633 // Return the length which is the number of arguments to copy to the
634 // stack. It is guaranteed to be a small integer at this point.
639 REFLECT_APPLY_PREPARE = function REFLECT_APPLY_PREPARE(args) {
641 // First check whether length is a positive Smi and args is an
642 // array. This is the fast case. If this fails, we do the slow case
643 // that takes care of more eventualities.
644 if (IS_ARRAY(args)) {
645 length = args.length;
646 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength &&
647 IS_SPEC_FUNCTION(this)) {
652 if (!IS_SPEC_FUNCTION(this)) {
653 throw %MakeTypeError(kCalledNonCallable, %$toString(this));
656 if (!IS_SPEC_OBJECT(args)) {
657 throw %MakeTypeError(kWrongArgs, "Reflect.apply");
660 length = %$toLength(args.length);
662 // We can handle any number of apply arguments if the stack is
663 // big enough, but sanity check the value to avoid overflow when
664 // multiplying with pointer size.
665 if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow);
667 // Return the length which is the number of arguments to copy to the
668 // stack. It is guaranteed to be a small integer at this point.
673 REFLECT_CONSTRUCT_PREPARE = function REFLECT_CONSTRUCT_PREPARE(
676 var ctorOk = IS_SPEC_FUNCTION(this) && %IsConstructor(this);
677 var newTargetOk = IS_SPEC_FUNCTION(newTarget) && %IsConstructor(newTarget);
679 // First check whether length is a positive Smi and args is an
680 // array. This is the fast case. If this fails, we do the slow case
681 // that takes care of more eventualities.
682 if (IS_ARRAY(args)) {
683 length = args.length;
684 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength &&
685 ctorOk && newTargetOk) {
691 if (!IS_SPEC_FUNCTION(this)) {
692 throw %MakeTypeError(kCalledNonCallable, %$toString(this));
694 throw %MakeTypeError(kNotConstructor, %$toString(this));
699 if (!IS_SPEC_FUNCTION(newTarget)) {
700 throw %MakeTypeError(kCalledNonCallable, %$toString(newTarget));
702 throw %MakeTypeError(kNotConstructor, %$toString(newTarget));
706 if (!IS_SPEC_OBJECT(args)) {
707 throw %MakeTypeError(kWrongArgs, "Reflect.construct");
710 length = %$toLength(args.length);
712 // We can handle any number of apply arguments if the stack is
713 // big enough, but sanity check the value to avoid overflow when
714 // multiplying with pointer size.
715 if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow);
717 // Return the length which is the number of arguments to copy to the
718 // stack. It is guaranteed to be a small integer at this point.
723 CONCAT_ITERABLE_TO_ARRAY = function CONCAT_ITERABLE_TO_ARRAY(iterable) {
724 return %$concatIterableToArray(this, iterable);
728 STACK_OVERFLOW = function STACK_OVERFLOW(length) {
729 throw %MakeRangeError(kStackOverflow);
733 // Convert the receiver to an object - forward to ToObject.
734 TO_OBJECT = function TO_OBJECT() {
735 return %$toObject(this);
739 // Convert the receiver to a number - forward to ToNumber.
740 TO_NUMBER = function TO_NUMBER() {
741 return %$toNumber(this);
745 // Convert the receiver to a string - forward to ToString.
746 TO_STRING = function TO_STRING() {
747 return %$toString(this);
751 // Convert the receiver to a string or symbol - forward to ToName.
752 TO_NAME = function TO_NAME() {
753 return %$toName(this);
757 /* -------------------------------------
758 - - - C o n v e r s i o n s - - -
759 -------------------------------------
762 // ECMA-262, section 9.1, page 30. Use null/undefined for no hint,
763 // (1) for number hint, and (2) for string hint.
764 function ToPrimitive(x, hint) {
766 if (IS_STRING(x)) return x;
768 if (!IS_SPEC_OBJECT(x)) return x;
769 if (IS_FLOAT32X4(x)) return x;
770 if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
771 return (hint == NUMBER_HINT) ? DefaultNumber(x) : DefaultString(x);
775 // ECMA-262, section 9.2, page 30
776 function ToBoolean(x) {
777 if (IS_BOOLEAN(x)) return x;
778 if (IS_STRING(x)) return x.length != 0;
779 if (x == null) return false;
780 if (IS_NUMBER(x)) return !((x == 0) || NUMBER_IS_NAN(x));
785 // ECMA-262, section 9.3, page 31.
786 function ToNumber(x) {
787 if (IS_NUMBER(x)) return x;
789 return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
790 : %StringToNumber(x);
792 if (IS_BOOLEAN(x)) return x ? 1 : 0;
793 if (IS_UNDEFINED(x)) return NAN;
794 // Types that can't be converted to number are caught in DefaultNumber.
795 return (IS_NULL(x)) ? 0 : ToNumber(DefaultNumber(x));
798 function NonNumberToNumber(x) {
800 return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
801 : %StringToNumber(x);
803 if (IS_BOOLEAN(x)) return x ? 1 : 0;
804 if (IS_UNDEFINED(x)) return NAN;
805 // Types that can't be converted to number are caught in DefaultNumber.
806 return (IS_NULL(x)) ? 0 : ToNumber(DefaultNumber(x));
810 // ECMA-262, section 9.8, page 35.
811 function ToString(x) {
812 if (IS_STRING(x)) return x;
813 if (IS_NUMBER(x)) return %_NumberToString(x);
814 if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
815 if (IS_UNDEFINED(x)) return 'undefined';
816 // Types that can't be converted to string are caught in DefaultString.
817 return (IS_NULL(x)) ? 'null' : ToString(DefaultString(x));
820 function NonStringToString(x) {
821 if (IS_NUMBER(x)) return %_NumberToString(x);
822 if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
823 if (IS_UNDEFINED(x)) return 'undefined';
824 // Types that can't be converted to string are caught in DefaultString.
825 return (IS_NULL(x)) ? 'null' : ToString(DefaultString(x));
831 return IS_SYMBOL(x) ? x : ToString(x);
835 // ECMA-262, section 9.9, page 36.
836 function ToObject(x) {
837 if (IS_STRING(x)) return new GlobalString(x);
838 if (IS_NUMBER(x)) return new GlobalNumber(x);
839 if (IS_BOOLEAN(x)) return new GlobalBoolean(x);
840 if (IS_SYMBOL(x)) return %NewSymbolWrapper(x);
841 if (IS_FLOAT32X4(x)) return %NewFloat32x4Wrapper(x);
842 if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) {
843 throw MakeTypeError(kUndefinedOrNullToObject);
849 // ECMA-262, section 9.4, page 34.
850 function ToInteger(x) {
851 if (%_IsSmi(x)) return x;
852 return %NumberToInteger(ToNumber(x));
856 // ES6, draft 08-24-14, section 7.1.15
857 function ToLength(arg) {
858 arg = ToInteger(arg);
859 if (arg < 0) return 0;
860 return arg < GlobalNumber.MAX_SAFE_INTEGER ? arg
861 : GlobalNumber.MAX_SAFE_INTEGER;
865 // ECMA-262, section 9.6, page 34.
866 function ToUint32(x) {
867 if (%_IsSmi(x) && x >= 0) return x;
868 return %NumberToJSUint32(ToNumber(x));
872 // ECMA-262, section 9.5, page 34
873 function ToInt32(x) {
874 if (%_IsSmi(x)) return x;
875 return %NumberToJSInt32(ToNumber(x));
880 function SameValue(x, y) {
881 if (typeof x != typeof y) return false;
883 if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
884 // x is +0 and y is -0 or vice versa.
885 if (x === 0 && y === 0 && %_IsMinusZero(x) != %_IsMinusZero(y)) {
889 if (IS_FLOAT32X4(x)) {
890 return %Float32x4SameValue(x, y);
896 // ES6, section 7.2.4
897 function SameValueZero(x, y) {
898 if (typeof x != typeof y) return false;
900 if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
902 if (IS_FLOAT32X4(x)) {
903 return %Float32x4SameValueZero(x, y);
909 function ConcatIterableToArray(target, iterable) {
910 var index = target.length;
911 for (var element of iterable) {
912 %AddElement(target, index++, element);
918 /* ---------------------------------
919 - - - U t i l i t i e s - - -
920 ---------------------------------
923 // Returns if the given x is a primitive value - not an object or a
925 function IsPrimitive(x) {
926 // Even though the type of null is "object", null is still
927 // considered a primitive value. IS_SPEC_OBJECT handles this correctly
928 // (i.e., it will return false if x is null).
929 return !IS_SPEC_OBJECT(x);
933 // ES6, draft 10-14-14, section 22.1.3.1.1
934 function IsConcatSpreadable(O) {
935 if (!IS_SPEC_OBJECT(O)) return false;
936 var spreadable = O[symbolIsConcatSpreadable];
937 if (IS_UNDEFINED(spreadable)) return IS_ARRAY(O);
938 return ToBoolean(spreadable);
942 // ECMA-262, section 8.6.2.6, page 28.
943 function DefaultNumber(x) {
944 var valueOf = x.valueOf;
945 if (IS_SPEC_FUNCTION(valueOf)) {
946 var v = %_CallFunction(x, valueOf);
947 if (IS_SYMBOL(v)) throw MakeTypeError(kSymbolToNumber);
948 if (IS_FLOAT32X4(v)) throw MakeTypeError(kSimdToNumber);
949 if (IsPrimitive(v)) return v;
951 var toString = x.toString;
952 if (IS_SPEC_FUNCTION(toString)) {
953 var s = %_CallFunction(x, toString);
954 if (IsPrimitive(s)) return s;
956 throw MakeTypeError(kCannotConvertToPrimitive);
959 // ECMA-262, section 8.6.2.6, page 28.
960 function DefaultString(x) {
961 if (!IS_SYMBOL_WRAPPER(x)) {
962 if (IS_SYMBOL(x)) throw MakeTypeError(kSymbolToString);
963 var toString = x.toString;
964 if (IS_SPEC_FUNCTION(toString)) {
965 var s = %_CallFunction(x, toString);
966 if (IsPrimitive(s)) return s;
969 var valueOf = x.valueOf;
970 if (IS_SPEC_FUNCTION(valueOf)) {
971 var v = %_CallFunction(x, valueOf);
972 if (IsPrimitive(v)) return v;
975 throw MakeTypeError(kCannotConvertToPrimitive);
978 function ToPositiveInteger(x, rangeErrorIndex) {
979 var i = TO_INTEGER_MAP_MINUS_ZERO(x);
980 if (i < 0) throw MakeRangeError(rangeErrorIndex);
984 //----------------------------------------------------------------------------
986 // NOTE: Setting the prototype for Array must take place as early as
987 // possible due to code generation for array literals. When
988 // generating code for a array literal a boilerplate array is created
989 // that is cloned when running the code. It is essential that the
990 // boilerplate gets the right prototype.
991 %FunctionSetPrototype(GlobalArray, new GlobalArray(0));
993 //----------------------------------------------------------------------------
995 $concatIterableToArray = ConcatIterableToArray;
996 $defaultNumber = DefaultNumber;
997 $defaultString = DefaultString;
998 $NaN = %GetRootNaN();
999 $nonNumberToNumber = NonNumberToNumber;
1000 $nonStringToString = NonStringToString;
1001 $sameValue = SameValue;
1002 $sameValueZero = SameValueZero;
1003 $toBoolean = ToBoolean;
1005 $toInteger = ToInteger;
1006 $toLength = ToLength;
1008 $toNumber = ToNumber;
1009 $toObject = ToObject;
1010 $toPositiveInteger = ToPositiveInteger;
1011 $toPrimitive = ToPrimitive;
1012 $toString = ToString;
1013 $toUint32 = ToUint32;