LCOV - code coverage report
Current view: top level - src/builtins - builtins-number.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 81 81 100.0 %
Date: 2019-01-20 Functions: 12 17 70.6 %

          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-inl.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             : #ifdef V8_INTL_SUPPORT
      12             : #include "src/objects/intl-objects.h"
      13             : #endif
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18             : // -----------------------------------------------------------------------------
      19             : // ES6 section 20.1 Number Objects
      20             : 
      21             : // ES6 section 20.1.3.2 Number.prototype.toExponential ( fractionDigits )
      22       18432 : BUILTIN(NumberPrototypeToExponential) {
      23             :   HandleScope scope(isolate);
      24             :   Handle<Object> value = args.at(0);
      25             :   Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1);
      26             : 
      27             :   // Unwrap the receiver {value}.
      28        9216 :   if (value->IsJSValue()) {
      29          27 :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
      30             :   }
      31        9216 :   if (!value->IsNumber()) {
      32         513 :     THROW_NEW_ERROR_RETURN_FAILURE(
      33             :         isolate, NewTypeError(MessageTemplate::kNotGeneric,
      34             :                               isolate->factory()->NewStringFromAsciiChecked(
      35             :                                   "Number.prototype.toExponential"),
      36             :                               isolate->factory()->Number_string()));
      37             :   }
      38        4437 :   double const value_number = value->Number();
      39             : 
      40             :   // Convert the {fraction_digits} to an integer first.
      41        8874 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      42             :       isolate, fraction_digits, Object::ToInteger(isolate, fraction_digits));
      43        4437 :   double const fraction_digits_number = fraction_digits->Number();
      44             : 
      45        4500 :   if (std::isnan(value_number)) return ReadOnlyRoots(isolate).NaN_string();
      46        4374 :   if (std::isinf(value_number)) {
      47             :     return (value_number < 0.0) ? ReadOnlyRoots(isolate).minus_Infinity_string()
      48         252 :                                 : ReadOnlyRoots(isolate).Infinity_string();
      49             :   }
      50        4248 :   if (fraction_digits_number < 0.0 ||
      51             :       fraction_digits_number > kMaxFractionDigits) {
      52         297 :     THROW_NEW_ERROR_RETURN_FAILURE(
      53             :         isolate, NewRangeError(MessageTemplate::kNumberFormatRange,
      54             :                                isolate->factory()->NewStringFromAsciiChecked(
      55             :                                    "toExponential()")));
      56             :   }
      57        8298 :   int const f = args.atOrUndefined(isolate, 1)->IsUndefined(isolate)
      58             :                     ? -1
      59        4149 :                     : static_cast<int>(fraction_digits_number);
      60        4149 :   char* const str = DoubleToExponentialCString(value_number, f);
      61        4149 :   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
      62             :   DeleteArray(str);
      63        4149 :   return *result;
      64             : }
      65             : 
      66             : // ES6 section 20.1.3.3 Number.prototype.toFixed ( fractionDigits )
      67       13440 : BUILTIN(NumberPrototypeToFixed) {
      68             :   HandleScope scope(isolate);
      69             :   Handle<Object> value = args.at(0);
      70             :   Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1);
      71             : 
      72             :   // Unwrap the receiver {value}.
      73        6720 :   if (value->IsJSValue()) {
      74          27 :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
      75             :   }
      76        6720 :   if (!value->IsNumber()) {
      77         513 :     THROW_NEW_ERROR_RETURN_FAILURE(
      78             :         isolate, NewTypeError(MessageTemplate::kNotGeneric,
      79             :                               isolate->factory()->NewStringFromAsciiChecked(
      80             :                                   "Number.prototype.toFixed"),
      81             :                               isolate->factory()->Number_string()));
      82             :   }
      83        3189 :   double const value_number = value->Number();
      84             : 
      85             :   // Convert the {fraction_digits} to an integer first.
      86        6378 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      87             :       isolate, fraction_digits, Object::ToInteger(isolate, fraction_digits));
      88        3189 :   double const fraction_digits_number = fraction_digits->Number();
      89             : 
      90             :   // Check if the {fraction_digits} are in the supported range.
      91        3189 :   if (fraction_digits_number < 0.0 ||
      92             :       fraction_digits_number > kMaxFractionDigits) {
      93         378 :     THROW_NEW_ERROR_RETURN_FAILURE(
      94             :         isolate, NewRangeError(MessageTemplate::kNumberFormatRange,
      95             :                                isolate->factory()->NewStringFromAsciiChecked(
      96             :                                    "toFixed() digits")));
      97             :   }
      98             : 
      99        3108 :   if (std::isnan(value_number)) return ReadOnlyRoots(isolate).NaN_string();
     100        3018 :   if (std::isinf(value_number)) {
     101             :     return (value_number < 0.0) ? ReadOnlyRoots(isolate).minus_Infinity_string()
     102         180 :                                 : ReadOnlyRoots(isolate).Infinity_string();
     103             :   }
     104             :   char* const str = DoubleToFixedCString(
     105        2928 :       value_number, static_cast<int>(fraction_digits_number));
     106        2928 :   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
     107             :   DeleteArray(str);
     108        2928 :   return *result;
     109             : }
     110             : 
     111             : // ES6 section 20.1.3.4 Number.prototype.toLocaleString ( [ r1 [ , r2 ] ] )
     112        5256 : BUILTIN(NumberPrototypeToLocaleString) {
     113             :   HandleScope scope(isolate);
     114             : 
     115        1314 :   isolate->CountUsage(v8::Isolate::UseCounterFeature::kNumberToLocaleString);
     116             : 
     117             :   Handle<Object> value = args.at(0);
     118             : 
     119             :   // Unwrap the receiver {value}.
     120        2628 :   if (value->IsJSValue()) {
     121          27 :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
     122             :   }
     123             :   // 1. Let x be ? thisNumberValue(this value)
     124        2628 :   if (!value->IsNumber()) {
     125          27 :     THROW_NEW_ERROR_RETURN_FAILURE(
     126             :         isolate, NewTypeError(MessageTemplate::kNotGeneric,
     127             :                               isolate->factory()->NewStringFromAsciiChecked(
     128             :                                   "Number.prototype.toLocaleString"),
     129             :                               isolate->factory()->Number_string()));
     130             :   }
     131             : 
     132             : #ifdef V8_INTL_SUPPORT
     133        2619 :   RETURN_RESULT_OR_FAILURE(
     134             :       isolate,
     135             :       Intl::NumberToLocaleString(isolate, value, args.atOrUndefined(isolate, 1),
     136             :                                  args.atOrUndefined(isolate, 2)));
     137             : #else
     138             :   // Turn the {value} into a String.
     139             :   return *isolate->factory()->NumberToString(value);
     140             : #endif  // V8_INTL_SUPPORT
     141             : }
     142             : 
     143             : // ES6 section 20.1.3.5 Number.prototype.toPrecision ( precision )
     144       13896 : BUILTIN(NumberPrototypeToPrecision) {
     145             :   HandleScope scope(isolate);
     146             :   Handle<Object> value = args.at(0);
     147             :   Handle<Object> precision = args.atOrUndefined(isolate, 1);
     148             : 
     149             :   // Unwrap the receiver {value}.
     150        6948 :   if (value->IsJSValue()) {
     151          27 :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
     152             :   }
     153        6948 :   if (!value->IsNumber()) {
     154         513 :     THROW_NEW_ERROR_RETURN_FAILURE(
     155             :         isolate, NewTypeError(MessageTemplate::kNotGeneric,
     156             :                               isolate->factory()->NewStringFromAsciiChecked(
     157             :                                   "Number.prototype.toPrecision"),
     158             :                               isolate->factory()->Number_string()));
     159             :   }
     160        3303 :   double const value_number = value->Number();
     161             : 
     162             :   // If no {precision} was specified, just return ToString of {value}.
     163        6606 :   if (precision->IsUndefined(isolate)) {
     164         252 :     return *isolate->factory()->NumberToString(value);
     165             :   }
     166             : 
     167             :   // Convert the {precision} to an integer first.
     168        6354 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, precision,
     169             :                                      Object::ToInteger(isolate, precision));
     170        3177 :   double const precision_number = precision->Number();
     171             : 
     172        3222 :   if (std::isnan(value_number)) return ReadOnlyRoots(isolate).NaN_string();
     173        3132 :   if (std::isinf(value_number)) {
     174             :     return (value_number < 0.0) ? ReadOnlyRoots(isolate).minus_Infinity_string()
     175         180 :                                 : ReadOnlyRoots(isolate).Infinity_string();
     176             :   }
     177        3042 :   if (precision_number < 1.0 || precision_number > kMaxFractionDigits) {
     178         216 :     THROW_NEW_ERROR_RETURN_FAILURE(
     179             :         isolate, NewRangeError(MessageTemplate::kToPrecisionFormatRange));
     180             :   }
     181             :   char* const str = DoubleToPrecisionCString(
     182        2934 :       value_number, static_cast<int>(precision_number));
     183        2934 :   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
     184             :   DeleteArray(str);
     185        2934 :   return *result;
     186             : }
     187             : 
     188             : // ES6 section 20.1.3.6 Number.prototype.toString ( [ radix ] )
     189     6543664 : BUILTIN(NumberPrototypeToString) {
     190             :   HandleScope scope(isolate);
     191             :   Handle<Object> value = args.at(0);
     192             :   Handle<Object> radix = args.atOrUndefined(isolate, 1);
     193             : 
     194             :   // Unwrap the receiver {value}.
     195     3271832 :   if (value->IsJSValue()) {
     196        3456 :     value = handle(Handle<JSValue>::cast(value)->value(), isolate);
     197             :   }
     198     3271832 :   if (!value->IsNumber()) {
     199         540 :     THROW_NEW_ERROR_RETURN_FAILURE(
     200             :         isolate, NewTypeError(MessageTemplate::kNotGeneric,
     201             :                               isolate->factory()->NewStringFromAsciiChecked(
     202             :                                   "Number.prototype.toString"),
     203             :                               isolate->factory()->Number_string()));
     204             :   }
     205     1635736 :   double const value_number = value->Number();
     206             : 
     207             :   // If no {radix} was specified, just return ToString of {value}.
     208     3271472 :   if (radix->IsUndefined(isolate)) {
     209     3019434 :     return *isolate->factory()->NumberToString(value);
     210             :   }
     211             : 
     212             :   // Convert the {radix} to an integer first.
     213      252047 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, radix,
     214             :                                      Object::ToInteger(isolate, radix));
     215      126010 :   double const radix_number = radix->Number();
     216             : 
     217             :   // If {radix} is 10, just return ToString of {value}.
     218      129245 :   if (radix_number == 10.0) return *isolate->factory()->NumberToString(value);
     219             : 
     220             :   // Make sure the {radix} is within the valid range.
     221      122775 :   if (radix_number < 2.0 || radix_number > 36.0) {
     222         234 :     THROW_NEW_ERROR_RETURN_FAILURE(
     223             :         isolate, NewRangeError(MessageTemplate::kToRadixFormatRange));
     224             :   }
     225             : 
     226             :   // Fast case where the result is a one character string.
     227      122658 :   if ((IsUint32Double(value_number) && value_number < radix_number) ||
     228             :       value_number == -0.0) {
     229             :     // Character array used for conversion.
     230             :     static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
     231             :     return *isolate->factory()->LookupSingleCharacterStringFromCode(
     232        5922 :         kCharTable[static_cast<uint32_t>(value_number)]);
     233             :   }
     234             : 
     235             :   // Slow case.
     236      119733 :   if (std::isnan(value_number)) return ReadOnlyRoots(isolate).NaN_string();
     237      119661 :   if (std::isinf(value_number)) {
     238             :     return (value_number < 0.0) ? ReadOnlyRoots(isolate).minus_Infinity_string()
     239         144 :                                 : ReadOnlyRoots(isolate).Infinity_string();
     240             :   }
     241             :   char* const str =
     242      119589 :       DoubleToRadixCString(value_number, static_cast<int>(radix_number));
     243      119589 :   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
     244             :   DeleteArray(str);
     245      119589 :   return *result;
     246             : }
     247             : 
     248             : }  // namespace internal
     249      183867 : }  // namespace v8

Generated by: LCOV version 1.10