LCOV - code coverage report
Current view: top level - src/builtins - builtins-number.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 64 69 92.8 %
Date: 2017-04-26 Functions: 8 15 53.3 %

          Line data    Source code
       1             : // Copyright 2016 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             : #include "src/builtins/builtins-utils.h"
       6             : #include "src/builtins/builtins.h"
       7             : #include "src/code-factory.h"
       8             : #include "src/conversions.h"
       9             : #include "src/counters.h"
      10             : #include "src/objects-inl.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15             : // -----------------------------------------------------------------------------
      16             : // ES6 section 20.1 Number Objects
      17             : 
      18             : // ES6 section 20.1.3.2 Number.prototype.toExponential ( fractionDigits )
      19       22227 : BUILTIN(NumberPrototypeToExponential) {
      20             :   HandleScope scope(isolate);
      21             :   Handle<Object> value = args.at(0);
      22             :   Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1);
      23             : 
      24             :   // Unwrap the receiver {value}.
      25        7409 :   if (value->IsJSValue()) {
      26             :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
      27             :   }
      28        7409 :   if (!value->IsNumber()) {
      29         855 :     THROW_NEW_ERROR_RETURN_FAILURE(
      30             :         isolate, NewTypeError(MessageTemplate::kNotGeneric,
      31             :                               isolate->factory()->NewStringFromAsciiChecked(
      32             :                                   "Number.prototype.toExponential"),
      33             :                               isolate->factory()->Number_string()));
      34             :   }
      35             :   double const value_number = value->Number();
      36             : 
      37             :   // Convert the {fraction_digits} to an integer first.
      38        7124 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      39             :       isolate, fraction_digits, Object::ToInteger(isolate, fraction_digits));
      40             :   double const fraction_digits_number = fraction_digits->Number();
      41             : 
      42        7124 :   if (std::isnan(value_number)) return isolate->heap()->nan_string();
      43        7022 :   if (std::isinf(value_number)) {
      44         102 :     return (value_number < 0.0) ? isolate->heap()->minus_infinity_string()
      45         306 :                                 : isolate->heap()->infinity_string();
      46             :   }
      47        6818 :   if (fraction_digits_number < 0.0 || fraction_digits_number > 20.0) {
      48         801 :     THROW_NEW_ERROR_RETURN_FAILURE(
      49             :         isolate, NewRangeError(MessageTemplate::kNumberFormatRange,
      50             :                                isolate->factory()->NewStringFromAsciiChecked(
      51             :                                    "toExponential()")));
      52             :   }
      53             :   int const f = args.atOrUndefined(isolate, 1)->IsUndefined(isolate)
      54             :                     ? -1
      55        6551 :                     : static_cast<int>(fraction_digits_number);
      56        6551 :   char* const str = DoubleToExponentialCString(value_number, f);
      57        6551 :   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
      58             :   DeleteArray(str);
      59        6551 :   return *result;
      60             : }
      61             : 
      62             : // ES6 section 20.1.3.3 Number.prototype.toFixed ( fractionDigits )
      63       16125 : BUILTIN(NumberPrototypeToFixed) {
      64             :   HandleScope scope(isolate);
      65             :   Handle<Object> value = args.at(0);
      66             :   Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1);
      67             : 
      68             :   // Unwrap the receiver {value}.
      69        5375 :   if (value->IsJSValue()) {
      70             :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
      71             :   }
      72        5375 :   if (!value->IsNumber()) {
      73         855 :     THROW_NEW_ERROR_RETURN_FAILURE(
      74             :         isolate, NewTypeError(MessageTemplate::kNotGeneric,
      75             :                               isolate->factory()->NewStringFromAsciiChecked(
      76             :                                   "Number.prototype.toFixed"),
      77             :                               isolate->factory()->Number_string()));
      78             :   }
      79             :   double const value_number = value->Number();
      80             : 
      81             :   // Convert the {fraction_digits} to an integer first.
      82        5090 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      83             :       isolate, fraction_digits, Object::ToInteger(isolate, fraction_digits));
      84             :   double const fraction_digits_number = fraction_digits->Number();
      85             : 
      86             :   // Check if the {fraction_digits} are in the supported range.
      87        5090 :   if (fraction_digits_number < 0.0 || fraction_digits_number > 20.0) {
      88         768 :     THROW_NEW_ERROR_RETURN_FAILURE(
      89             :         isolate, NewRangeError(MessageTemplate::kNumberFormatRange,
      90             :                                isolate->factory()->NewStringFromAsciiChecked(
      91             :                                    "toFixed() digits")));
      92             :   }
      93             : 
      94        4834 :   if (std::isnan(value_number)) return isolate->heap()->nan_string();
      95        4761 :   if (std::isinf(value_number)) {
      96          73 :     return (value_number < 0.0) ? isolate->heap()->minus_infinity_string()
      97         219 :                                 : isolate->heap()->infinity_string();
      98             :   }
      99             :   char* const str = DoubleToFixedCString(
     100        4615 :       value_number, static_cast<int>(fraction_digits_number));
     101        4615 :   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
     102             :   DeleteArray(str);
     103        4615 :   return *result;
     104             : }
     105             : 
     106             : // ES6 section 20.1.3.4 Number.prototype.toLocaleString ( [ r1 [ , r2 ] ] )
     107           0 : BUILTIN(NumberPrototypeToLocaleString) {
     108             :   HandleScope scope(isolate);
     109             :   Handle<Object> value = args.at(0);
     110             : 
     111             :   // Unwrap the receiver {value}.
     112           0 :   if (value->IsJSValue()) {
     113             :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
     114             :   }
     115           0 :   if (!value->IsNumber()) {
     116           0 :     THROW_NEW_ERROR_RETURN_FAILURE(
     117             :         isolate, NewTypeError(MessageTemplate::kNotGeneric,
     118             :                               isolate->factory()->NewStringFromAsciiChecked(
     119             :                                   "Number.prototype.toLocaleString"),
     120             :                               isolate->factory()->Number_string()));
     121             :   }
     122             : 
     123             :   // Turn the {value} into a String.
     124           0 :   return *isolate->factory()->NumberToString(value);
     125             : }
     126             : 
     127             : // ES6 section 20.1.3.5 Number.prototype.toPrecision ( precision )
     128       16818 : BUILTIN(NumberPrototypeToPrecision) {
     129             :   HandleScope scope(isolate);
     130             :   Handle<Object> value = args.at(0);
     131             :   Handle<Object> precision = args.atOrUndefined(isolate, 1);
     132             : 
     133             :   // Unwrap the receiver {value}.
     134        5606 :   if (value->IsJSValue()) {
     135             :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
     136             :   }
     137        5606 :   if (!value->IsNumber()) {
     138         855 :     THROW_NEW_ERROR_RETURN_FAILURE(
     139             :         isolate, NewTypeError(MessageTemplate::kNotGeneric,
     140             :                               isolate->factory()->NewStringFromAsciiChecked(
     141             :                                   "Number.prototype.toPrecision"),
     142             :                               isolate->factory()->Number_string()));
     143             :   }
     144             :   double const value_number = value->Number();
     145             : 
     146             :   // If no {precision} was specified, just return ToString of {value}.
     147        5321 :   if (precision->IsUndefined(isolate)) {
     148         392 :     return *isolate->factory()->NumberToString(value);
     149             :   }
     150             : 
     151             :   // Convert the {precision} to an integer first.
     152        5125 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, precision,
     153             :                                      Object::ToInteger(isolate, precision));
     154             :   double const precision_number = precision->Number();
     155             : 
     156        5125 :   if (std::isnan(value_number)) return isolate->heap()->nan_string();
     157        5051 :   if (std::isinf(value_number)) {
     158          74 :     return (value_number < 0.0) ? isolate->heap()->minus_infinity_string()
     159         222 :                                 : isolate->heap()->infinity_string();
     160             :   }
     161        4903 :   if (precision_number < 1.0 || precision_number > 21.0) {
     162         452 :     THROW_NEW_ERROR_RETURN_FAILURE(
     163             :         isolate, NewRangeError(MessageTemplate::kToPrecisionFormatRange));
     164             :   }
     165             :   char* const str = DoubleToPrecisionCString(
     166        4677 :       value_number, static_cast<int>(precision_number));
     167        4677 :   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
     168             :   DeleteArray(str);
     169        4677 :   return *result;
     170             : }
     171             : 
     172             : // ES6 section 20.1.3.6 Number.prototype.toString ( [ radix ] )
     173     7777428 : BUILTIN(NumberPrototypeToString) {
     174             :   HandleScope scope(isolate);
     175             :   Handle<Object> value = args.at(0);
     176             :   Handle<Object> radix = args.atOrUndefined(isolate, 1);
     177             : 
     178             :   // Unwrap the receiver {value}.
     179     2592476 :   if (value->IsJSValue()) {
     180             :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
     181             :   }
     182     2592476 :   if (!value->IsNumber()) {
     183         900 :     THROW_NEW_ERROR_RETURN_FAILURE(
     184             :         isolate, NewTypeError(MessageTemplate::kNotGeneric,
     185             :                               isolate->factory()->NewStringFromAsciiChecked(
     186             :                                   "Number.prototype.toString"),
     187             :                               isolate->factory()->Number_string()));
     188             :   }
     189             :   double const value_number = value->Number();
     190             : 
     191             :   // If no {radix} was specified, just return ToString of {value}.
     192     2592176 :   if (radix->IsUndefined(isolate)) {
     193     4831248 :     return *isolate->factory()->NumberToString(value);
     194             :   }
     195             : 
     196             :   // Convert the {radix} to an integer first.
     197      176552 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, radix,
     198             :                                      Object::ToInteger(isolate, radix));
     199             :   double const radix_number = radix->Number();
     200             : 
     201             :   // If {radix} is 10, just return ToString of {value}.
     202      181721 :   if (radix_number == 10.0) return *isolate->factory()->NumberToString(value);
     203             : 
     204             :   // Make sure the {radix} is within the valid range.
     205      171383 :   if (radix_number < 2.0 || radix_number > 36.0) {
     206         366 :     THROW_NEW_ERROR_RETURN_FAILURE(
     207             :         isolate, NewRangeError(MessageTemplate::kToRadixFormatRange));
     208             :   }
     209             : 
     210             :   // Fast case where the result is a one character string.
     211      171200 :   if ((IsUint32Double(value_number) && value_number < radix_number) ||
     212             :       value_number == -0.0) {
     213             :     // Character array used for conversion.
     214             :     static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
     215             :     return *isolate->factory()->LookupSingleCharacterStringFromCode(
     216        8282 :         kCharTable[static_cast<uint32_t>(value_number)]);
     217             :   }
     218             : 
     219             :   // Slow case.
     220      167059 :   if (std::isnan(value_number)) return isolate->heap()->nan_string();
     221      167000 :   if (std::isinf(value_number)) {
     222          59 :     return (value_number < 0.0) ? isolate->heap()->minus_infinity_string()
     223         177 :                                 : isolate->heap()->infinity_string();
     224             :   }
     225             :   char* const str =
     226      166882 :       DoubleToRadixCString(value_number, static_cast<int>(radix_number));
     227      166882 :   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
     228             :   DeleteArray(str);
     229      166882 :   return *result;
     230             : }
     231             : 
     232             : }  // namespace internal
     233             : }  // namespace v8

Generated by: LCOV version 1.10