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-10-20 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       14547 : 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        4849 :   if (value->IsJSValue()) {
      26             :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
      27             :   }
      28        4849 :   if (!value->IsNumber()) {
      29         570 :     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        4659 :   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        4659 :   if (std::isnan(value_number)) return isolate->heap()->NaN_string();
      43        4592 :   if (std::isinf(value_number)) {
      44          67 :     return (value_number < 0.0) ? isolate->heap()->minus_Infinity_string()
      45         201 :                                 : isolate->heap()->Infinity_string();
      46             :   }
      47        4458 :   if (fraction_digits_number < 0.0 ||
      48             :       fraction_digits_number > kMaxFractionDigits) {
      49         300 :     THROW_NEW_ERROR_RETURN_FAILURE(
      50             :         isolate, NewRangeError(MessageTemplate::kNumberFormatRange,
      51             :                                isolate->factory()->NewStringFromAsciiChecked(
      52             :                                    "toExponential()")));
      53             :   }
      54             :   int const f = args.atOrUndefined(isolate, 1)->IsUndefined(isolate)
      55             :                     ? -1
      56        4358 :                     : static_cast<int>(fraction_digits_number);
      57        4358 :   char* const str = DoubleToExponentialCString(value_number, f);
      58        4358 :   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
      59             :   DeleteArray(str);
      60        4358 :   return *result;
      61             : }
      62             : 
      63             : // ES6 section 20.1.3.3 Number.prototype.toFixed ( fractionDigits )
      64       10815 : BUILTIN(NumberPrototypeToFixed) {
      65             :   HandleScope scope(isolate);
      66             :   Handle<Object> value = args.at(0);
      67             :   Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1);
      68             : 
      69             :   // Unwrap the receiver {value}.
      70        3605 :   if (value->IsJSValue()) {
      71             :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
      72             :   }
      73        3605 :   if (!value->IsNumber()) {
      74         570 :     THROW_NEW_ERROR_RETURN_FAILURE(
      75             :         isolate, NewTypeError(MessageTemplate::kNotGeneric,
      76             :                               isolate->factory()->NewStringFromAsciiChecked(
      77             :                                   "Number.prototype.toFixed"),
      78             :                               isolate->factory()->Number_string()));
      79             :   }
      80             :   double const value_number = value->Number();
      81             : 
      82             :   // Convert the {fraction_digits} to an integer first.
      83        3415 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      84             :       isolate, fraction_digits, Object::ToInteger(isolate, fraction_digits));
      85             :   double const fraction_digits_number = fraction_digits->Number();
      86             : 
      87             :   // Check if the {fraction_digits} are in the supported range.
      88        3415 :   if (fraction_digits_number < 0.0 ||
      89             :       fraction_digits_number > kMaxFractionDigits) {
      90         390 :     THROW_NEW_ERROR_RETURN_FAILURE(
      91             :         isolate, NewRangeError(MessageTemplate::kNumberFormatRange,
      92             :                                isolate->factory()->NewStringFromAsciiChecked(
      93             :                                    "toFixed() digits")));
      94             :   }
      95             : 
      96        3285 :   if (std::isnan(value_number)) return isolate->heap()->NaN_string();
      97        3237 :   if (std::isinf(value_number)) {
      98          48 :     return (value_number < 0.0) ? isolate->heap()->minus_Infinity_string()
      99         144 :                                 : isolate->heap()->Infinity_string();
     100             :   }
     101             :   char* const str = DoubleToFixedCString(
     102        3141 :       value_number, static_cast<int>(fraction_digits_number));
     103        3141 :   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
     104             :   DeleteArray(str);
     105        3141 :   return *result;
     106             : }
     107             : 
     108             : // ES6 section 20.1.3.4 Number.prototype.toLocaleString ( [ r1 [ , r2 ] ] )
     109           0 : BUILTIN(NumberPrototypeToLocaleString) {
     110             :   HandleScope scope(isolate);
     111             :   Handle<Object> value = args.at(0);
     112             : 
     113             :   // Unwrap the receiver {value}.
     114           0 :   if (value->IsJSValue()) {
     115             :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
     116             :   }
     117           0 :   if (!value->IsNumber()) {
     118           0 :     THROW_NEW_ERROR_RETURN_FAILURE(
     119             :         isolate, NewTypeError(MessageTemplate::kNotGeneric,
     120             :                               isolate->factory()->NewStringFromAsciiChecked(
     121             :                                   "Number.prototype.toLocaleString"),
     122             :                               isolate->factory()->Number_string()));
     123             :   }
     124             : 
     125             :   // Turn the {value} into a String.
     126           0 :   return *isolate->factory()->NumberToString(value);
     127             : }
     128             : 
     129             : // ES6 section 20.1.3.5 Number.prototype.toPrecision ( precision )
     130       11028 : BUILTIN(NumberPrototypeToPrecision) {
     131             :   HandleScope scope(isolate);
     132             :   Handle<Object> value = args.at(0);
     133             :   Handle<Object> precision = args.atOrUndefined(isolate, 1);
     134             : 
     135             :   // Unwrap the receiver {value}.
     136        3676 :   if (value->IsJSValue()) {
     137             :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
     138             :   }
     139        3676 :   if (!value->IsNumber()) {
     140         570 :     THROW_NEW_ERROR_RETURN_FAILURE(
     141             :         isolate, NewTypeError(MessageTemplate::kNotGeneric,
     142             :                               isolate->factory()->NewStringFromAsciiChecked(
     143             :                                   "Number.prototype.toPrecision"),
     144             :                               isolate->factory()->Number_string()));
     145             :   }
     146             :   double const value_number = value->Number();
     147             : 
     148             :   // If no {precision} was specified, just return ToString of {value}.
     149        3486 :   if (precision->IsUndefined(isolate)) {
     150         252 :     return *isolate->factory()->NumberToString(value);
     151             :   }
     152             : 
     153             :   // Convert the {precision} to an integer first.
     154        3360 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, precision,
     155             :                                      Object::ToInteger(isolate, precision));
     156             :   double const precision_number = precision->Number();
     157             : 
     158        3360 :   if (std::isnan(value_number)) return isolate->heap()->NaN_string();
     159        3311 :   if (std::isinf(value_number)) {
     160          49 :     return (value_number < 0.0) ? isolate->heap()->minus_Infinity_string()
     161         147 :                                 : isolate->heap()->Infinity_string();
     162             :   }
     163        3213 :   if (precision_number < 1.0 || precision_number > kMaxFractionDigits) {
     164         218 :     THROW_NEW_ERROR_RETURN_FAILURE(
     165             :         isolate, NewRangeError(MessageTemplate::kToPrecisionFormatRange));
     166             :   }
     167             :   char* const str = DoubleToPrecisionCString(
     168        3104 :       value_number, static_cast<int>(precision_number));
     169        3104 :   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
     170             :   DeleteArray(str);
     171        3104 :   return *result;
     172             : }
     173             : 
     174             : // ES6 section 20.1.3.6 Number.prototype.toString ( [ radix ] )
     175     5126334 : BUILTIN(NumberPrototypeToString) {
     176             :   HandleScope scope(isolate);
     177             :   Handle<Object> value = args.at(0);
     178             :   Handle<Object> radix = args.atOrUndefined(isolate, 1);
     179             : 
     180             :   // Unwrap the receiver {value}.
     181     1708778 :   if (value->IsJSValue()) {
     182             :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
     183             :   }
     184     1708778 :   if (!value->IsNumber()) {
     185         600 :     THROW_NEW_ERROR_RETURN_FAILURE(
     186             :         isolate, NewTypeError(MessageTemplate::kNotGeneric,
     187             :                               isolate->factory()->NewStringFromAsciiChecked(
     188             :                                   "Number.prototype.toString"),
     189             :                               isolate->factory()->Number_string()));
     190             :   }
     191             :   double const value_number = value->Number();
     192             : 
     193             :   // If no {radix} was specified, just return ToString of {value}.
     194     1708578 :   if (radix->IsUndefined(isolate)) {
     195     3182258 :     return *isolate->factory()->NumberToString(value);
     196             :   }
     197             : 
     198             :   // Convert the {radix} to an integer first.
     199      117449 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, radix,
     200             :                                      Object::ToInteger(isolate, radix));
     201             :   double const radix_number = radix->Number();
     202             : 
     203             :   // If {radix} is 10, just return ToString of {value}.
     204      120973 :   if (radix_number == 10.0) return *isolate->factory()->NumberToString(value);
     205             : 
     206             :   // Make sure the {radix} is within the valid range.
     207      113905 :   if (radix_number < 2.0 || radix_number > 36.0) {
     208         236 :     THROW_NEW_ERROR_RETURN_FAILURE(
     209             :         isolate, NewRangeError(MessageTemplate::kToRadixFormatRange));
     210             :   }
     211             : 
     212             :   // Fast case where the result is a one character string.
     213      113787 :   if ((IsUint32Double(value_number) && value_number < radix_number) ||
     214             :       value_number == -0.0) {
     215             :     // Character array used for conversion.
     216             :     static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
     217             :     return *isolate->factory()->LookupSingleCharacterStringFromCode(
     218        5502 :         kCharTable[static_cast<uint32_t>(value_number)]);
     219             :   }
     220             : 
     221             :   // Slow case.
     222      111036 :   if (std::isnan(value_number)) return isolate->heap()->NaN_string();
     223      110997 :   if (std::isinf(value_number)) {
     224          39 :     return (value_number < 0.0) ? isolate->heap()->minus_Infinity_string()
     225         117 :                                 : isolate->heap()->Infinity_string();
     226             :   }
     227             :   char* const str =
     228      110919 :       DoubleToRadixCString(value_number, static_cast<int>(radix_number));
     229      110919 :   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
     230             :   DeleteArray(str);
     231      110919 :   return *result;
     232             : }
     233             : 
     234             : }  // namespace internal
     235             : }  // namespace v8

Generated by: LCOV version 1.10