OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This files contains runtime support implemented in JavaScript. | 5 // This files contains runtime support implemented in JavaScript. |
6 | 6 |
7 // CAUTION: Some of the functions specified in this file are called | 7 // CAUTION: Some of the functions specified in this file are called |
8 // directly from compiled code. These are the functions with names in | 8 // directly from compiled code. These are the functions with names in |
9 // ALL CAPS. The compiled code passes the first argument in 'this'. | 9 // ALL CAPS. The compiled code passes the first argument in 'this'. |
10 | 10 |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 function ADD(x) { | 158 function ADD(x) { |
159 // Fast case: Check for number operands and do the addition. | 159 // Fast case: Check for number operands and do the addition. |
160 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); | 160 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); |
161 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); | 161 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); |
162 | 162 |
163 // Default implementation. | 163 // Default implementation. |
164 var a = %to_primitive(this, NO_HINT); | 164 var a = %to_primitive(this, NO_HINT); |
165 var b = %to_primitive(x, NO_HINT); | 165 var b = %to_primitive(x, NO_HINT); |
166 | 166 |
167 if (IS_STRING(a)) { | 167 if (IS_STRING(a)) { |
168 return %_StringAdd(a, %to_string_fun(b)); | 168 return %_StringAdd(a, TO_STRING(b)); |
169 } else if (IS_STRING(b)) { | 169 } else if (IS_STRING(b)) { |
170 return %_StringAdd(%non_string_to_string(a), b); | 170 return %_StringAdd(%non_string_to_string(a), b); |
171 } else { | 171 } else { |
172 return %NumberAdd(%to_number_fun(a), %to_number_fun(b)); | 172 return %NumberAdd(%to_number_fun(a), %to_number_fun(b)); |
173 } | 173 } |
174 } | 174 } |
175 | 175 |
176 | 176 |
177 // Strong mode ADD throws if an implicit conversion would be performed | 177 // Strong mode ADD throws if an implicit conversion would be performed |
178 function ADD_STRONG(x) { | 178 function ADD_STRONG(x) { |
179 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); | 179 if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); |
180 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); | 180 if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x); |
181 | 181 |
182 throw %make_type_error(kStrongImplicitConversion); | 182 throw %make_type_error(kStrongImplicitConversion); |
183 } | 183 } |
184 | 184 |
185 | 185 |
186 // Left operand (this) is already a string. | 186 // Left operand (this) is already a string. |
187 function STRING_ADD_LEFT(y) { | 187 function STRING_ADD_LEFT(y) { |
188 if (!IS_STRING(y)) { | 188 if (!IS_STRING(y)) { |
189 if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) { | 189 if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) { |
190 y = %_ValueOf(y); | 190 y = %_ValueOf(y); |
191 } else { | 191 } else { |
192 y = IS_NUMBER(y) | 192 y = IS_NUMBER(y) |
193 ? %_NumberToString(y) | 193 ? %_NumberToString(y) |
194 : %to_string_fun(%to_primitive(y, NO_HINT)); | 194 : TO_STRING(%to_primitive(y, NO_HINT)); |
195 } | 195 } |
196 } | 196 } |
197 return %_StringAdd(this, y); | 197 return %_StringAdd(this, y); |
198 } | 198 } |
199 | 199 |
200 | 200 |
201 // Right operand (y) is already a string. | 201 // Right operand (y) is already a string. |
202 function STRING_ADD_RIGHT(y) { | 202 function STRING_ADD_RIGHT(y) { |
203 var x = this; | 203 var x = this; |
204 if (!IS_STRING(x)) { | 204 if (!IS_STRING(x)) { |
205 if (IS_STRING_WRAPPER(x) && %_IsStringWrapperSafeForDefaultValueOf(x)) { | 205 if (IS_STRING_WRAPPER(x) && %_IsStringWrapperSafeForDefaultValueOf(x)) { |
206 x = %_ValueOf(x); | 206 x = %_ValueOf(x); |
207 } else { | 207 } else { |
208 x = IS_NUMBER(x) | 208 x = IS_NUMBER(x) |
209 ? %_NumberToString(x) | 209 ? %_NumberToString(x) |
210 : %to_string_fun(%to_primitive(x, NO_HINT)); | 210 : TO_STRING(%to_primitive(x, NO_HINT)); |
211 } | 211 } |
212 } | 212 } |
213 return %_StringAdd(x, y); | 213 return %_StringAdd(x, y); |
214 } | 214 } |
215 | 215 |
216 | 216 |
217 // ECMA-262, section 11.6.2, page 50. | 217 // ECMA-262, section 11.6.2, page 50. |
218 function SUB(y) { | 218 function SUB(y) { |
219 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); | 219 var x = IS_NUMBER(this) ? this : %non_number_to_number(this); |
220 if (!IS_NUMBER(y)) y = %non_number_to_number(y); | 220 if (!IS_NUMBER(y)) y = %non_number_to_number(y); |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 } | 488 } |
489 | 489 |
490 length = (args == null) ? 0 : TO_UINT32(args.length); | 490 length = (args == null) ? 0 : TO_UINT32(args.length); |
491 | 491 |
492 // We can handle any number of apply arguments if the stack is | 492 // We can handle any number of apply arguments if the stack is |
493 // big enough, but sanity check the value to avoid overflow when | 493 // big enough, but sanity check the value to avoid overflow when |
494 // multiplying with pointer size. | 494 // multiplying with pointer size. |
495 if (length > kSafeArgumentsLength) throw %make_range_error(kStackOverflow); | 495 if (length > kSafeArgumentsLength) throw %make_range_error(kStackOverflow); |
496 | 496 |
497 if (!IS_SPEC_FUNCTION(this)) { | 497 if (!IS_SPEC_FUNCTION(this)) { |
498 throw %make_type_error(kApplyNonFunction, %to_string_fun(this), typeof this)
; | 498 throw %make_type_error(kApplyNonFunction, TO_STRING(this), typeof this); |
499 } | 499 } |
500 | 500 |
501 // Make sure the arguments list has the right type. | 501 // Make sure the arguments list has the right type. |
502 if (args != null && !IS_SPEC_OBJECT(args)) { | 502 if (args != null && !IS_SPEC_OBJECT(args)) { |
503 throw %make_type_error(kWrongArgs, "Function.prototype.apply"); | 503 throw %make_type_error(kWrongArgs, "Function.prototype.apply"); |
504 } | 504 } |
505 | 505 |
506 // Return the length which is the number of arguments to copy to the | 506 // Return the length which is the number of arguments to copy to the |
507 // stack. It is guaranteed to be a small integer at this point. | 507 // stack. It is guaranteed to be a small integer at this point. |
508 return length; | 508 return length; |
509 } | 509 } |
510 | 510 |
511 | 511 |
512 function REFLECT_APPLY_PREPARE(args) { | 512 function REFLECT_APPLY_PREPARE(args) { |
513 var length; | 513 var length; |
514 // First check whether length is a positive Smi and args is an | 514 // First check whether length is a positive Smi and args is an |
515 // array. This is the fast case. If this fails, we do the slow case | 515 // array. This is the fast case. If this fails, we do the slow case |
516 // that takes care of more eventualities. | 516 // that takes care of more eventualities. |
517 if (IS_ARRAY(args)) { | 517 if (IS_ARRAY(args)) { |
518 length = args.length; | 518 length = args.length; |
519 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength && | 519 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength && |
520 IS_SPEC_FUNCTION(this)) { | 520 IS_SPEC_FUNCTION(this)) { |
521 return length; | 521 return length; |
522 } | 522 } |
523 } | 523 } |
524 | 524 |
525 if (!IS_SPEC_FUNCTION(this)) { | 525 if (!IS_SPEC_FUNCTION(this)) { |
526 throw %make_type_error(kCalledNonCallable, %to_string_fun(this)); | 526 throw %make_type_error(kCalledNonCallable, TO_STRING(this)); |
527 } | 527 } |
528 | 528 |
529 if (!IS_SPEC_OBJECT(args)) { | 529 if (!IS_SPEC_OBJECT(args)) { |
530 throw %make_type_error(kWrongArgs, "Reflect.apply"); | 530 throw %make_type_error(kWrongArgs, "Reflect.apply"); |
531 } | 531 } |
532 | 532 |
533 length = %to_length_fun(args.length); | 533 length = %to_length_fun(args.length); |
534 | 534 |
535 // We can handle any number of apply arguments if the stack is | 535 // We can handle any number of apply arguments if the stack is |
536 // big enough, but sanity check the value to avoid overflow when | 536 // big enough, but sanity check the value to avoid overflow when |
(...skipping 18 matching lines...) Expand all Loading... |
555 if (IS_ARRAY(args)) { | 555 if (IS_ARRAY(args)) { |
556 length = args.length; | 556 length = args.length; |
557 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength && | 557 if (%_IsSmi(length) && length >= 0 && length < kSafeArgumentsLength && |
558 ctorOk && newTargetOk) { | 558 ctorOk && newTargetOk) { |
559 return length; | 559 return length; |
560 } | 560 } |
561 } | 561 } |
562 | 562 |
563 if (!ctorOk) { | 563 if (!ctorOk) { |
564 if (!IS_SPEC_FUNCTION(this)) { | 564 if (!IS_SPEC_FUNCTION(this)) { |
565 throw %make_type_error(kCalledNonCallable, %to_string_fun(this)); | 565 throw %make_type_error(kCalledNonCallable, TO_STRING(this)); |
566 } else { | 566 } else { |
567 throw %make_type_error(kNotConstructor, %to_string_fun(this)); | 567 throw %make_type_error(kNotConstructor, TO_STRING(this)); |
568 } | 568 } |
569 } | 569 } |
570 | 570 |
571 if (!newTargetOk) { | 571 if (!newTargetOk) { |
572 if (!IS_SPEC_FUNCTION(newTarget)) { | 572 if (!IS_SPEC_FUNCTION(newTarget)) { |
573 throw %make_type_error(kCalledNonCallable, %to_string_fun(newTarget)); | 573 throw %make_type_error(kCalledNonCallable, TO_STRING(newTarget)); |
574 } else { | 574 } else { |
575 throw %make_type_error(kNotConstructor, %to_string_fun(newTarget)); | 575 throw %make_type_error(kNotConstructor, TO_STRING(newTarget)); |
576 } | 576 } |
577 } | 577 } |
578 | 578 |
579 if (!IS_SPEC_OBJECT(args)) { | 579 if (!IS_SPEC_OBJECT(args)) { |
580 throw %make_type_error(kWrongArgs, "Reflect.construct"); | 580 throw %make_type_error(kWrongArgs, "Reflect.construct"); |
581 } | 581 } |
582 | 582 |
583 length = %to_length_fun(args.length); | 583 length = %to_length_fun(args.length); |
584 | 584 |
585 // We can handle any number of apply arguments if the stack is | 585 // We can handle any number of apply arguments if the stack is |
(...skipping 16 matching lines...) Expand all Loading... |
602 throw %make_range_error(kStackOverflow); | 602 throw %make_range_error(kStackOverflow); |
603 } | 603 } |
604 | 604 |
605 | 605 |
606 // Convert the receiver to a number - forward to ToNumber. | 606 // Convert the receiver to a number - forward to ToNumber. |
607 function TO_NUMBER() { | 607 function TO_NUMBER() { |
608 return %to_number_fun(this); | 608 return %to_number_fun(this); |
609 } | 609 } |
610 | 610 |
611 | 611 |
612 // Convert the receiver to a string - forward to ToString. | |
613 function TO_STRING() { | |
614 return %to_string_fun(this); | |
615 } | |
616 | |
617 | |
618 /* ------------------------------------- | 612 /* ------------------------------------- |
619 - - - C o n v e r s i o n s - - - | 613 - - - C o n v e r s i o n s - - - |
620 ------------------------------------- | 614 ------------------------------------- |
621 */ | 615 */ |
622 | 616 |
623 // ECMA-262, section 9.1, page 30. Use null/undefined for no hint, | 617 // ECMA-262, section 9.1, page 30. Use null/undefined for no hint, |
624 // (1) for number hint, and (2) for string hint. | 618 // (1) for number hint, and (2) for string hint. |
625 function ToPrimitive(x, hint) { | 619 function ToPrimitive(x, hint) { |
626 if (!IS_SPEC_OBJECT(x)) return x; | 620 if (!IS_SPEC_OBJECT(x)) return x; |
627 if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT; | 621 if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT; |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
866 ]); | 860 ]); |
867 | 861 |
868 %InstallToContext([ | 862 %InstallToContext([ |
869 "concat_iterable_to_array", ConcatIterableToArray, | 863 "concat_iterable_to_array", ConcatIterableToArray, |
870 "non_number_to_number", NonNumberToNumber, | 864 "non_number_to_number", NonNumberToNumber, |
871 "non_string_to_string", NonStringToString, | 865 "non_string_to_string", NonStringToString, |
872 "to_integer_fun", ToInteger, | 866 "to_integer_fun", ToInteger, |
873 "to_length_fun", ToLength, | 867 "to_length_fun", ToLength, |
874 "to_number_fun", ToNumber, | 868 "to_number_fun", ToNumber, |
875 "to_primitive", ToPrimitive, | 869 "to_primitive", ToPrimitive, |
876 "to_string_fun", ToString, | |
877 ]); | 870 ]); |
878 | 871 |
879 utils.Export(function(to) { | 872 utils.Export(function(to) { |
880 to.ToBoolean = ToBoolean; | 873 to.ToBoolean = ToBoolean; |
881 to.ToLength = ToLength; | 874 to.ToLength = ToLength; |
882 to.ToNumber = ToNumber; | 875 to.ToNumber = ToNumber; |
883 to.ToPrimitive = ToPrimitive; | 876 to.ToPrimitive = ToPrimitive; |
884 to.ToString = ToString; | 877 to.ToString = ToString; |
885 }); | 878 }); |
886 | 879 |
887 }) | 880 }) |
OLD | NEW |