builtins-bigint.cc 5.72 KB
Newer Older
1 2 3 4
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "src/builtins/builtins-utils-inl.h"
6
#include "src/builtins/builtins.h"
7
#include "src/conversions.h"
8 9
#include "src/counters.h"
#include "src/objects-inl.h"
10 11 12
#ifdef V8_INTL_SUPPORT
#include "src/objects/intl-objects.h"
#endif
13 14 15 16 17 18

namespace v8 {
namespace internal {

BUILTIN(BigIntConstructor) {
  HandleScope scope(isolate);
19
  if (!args.new_target()->IsUndefined(isolate)) {  // [[Construct]]
20 21 22
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewTypeError(MessageTemplate::kNotConstructor,
                              isolate->factory()->BigInt_string()));
23
  }
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
  // [[Call]]
  Handle<Object> value = args.atOrUndefined(isolate, 1);

  if (value->IsJSReceiver()) {
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
        isolate, value,
        JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(value),
                                ToPrimitiveHint::kNumber));
  }

  if (value->IsNumber()) {
    RETURN_RESULT_OR_FAILURE(isolate, BigInt::FromNumber(isolate, value));
  } else {
    RETURN_RESULT_OR_FAILURE(isolate, BigInt::FromObject(isolate, value));
  }
39 40 41 42 43 44 45
}

BUILTIN(BigIntAsUintN) {
  HandleScope scope(isolate);
  Handle<Object> bits_obj = args.atOrUndefined(isolate, 1);
  Handle<Object> bigint_obj = args.atOrUndefined(isolate, 2);

46 47 48 49
  Handle<Object> bits;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, bits,
      Object::ToIndex(isolate, bits_obj, MessageTemplate::kInvalidIndex));
50

51 52 53 54
  Handle<BigInt> bigint;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, bigint,
                                     BigInt::FromObject(isolate, bigint_obj));

55 56
  RETURN_RESULT_OR_FAILURE(isolate,
                           BigInt::AsUintN(isolate, bits->Number(), bigint));
57 58 59 60 61 62 63
}

BUILTIN(BigIntAsIntN) {
  HandleScope scope(isolate);
  Handle<Object> bits_obj = args.atOrUndefined(isolate, 1);
  Handle<Object> bigint_obj = args.atOrUndefined(isolate, 2);

64 65 66 67
  Handle<Object> bits;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, bits,
      Object::ToIndex(isolate, bits_obj, MessageTemplate::kInvalidIndex));
68

69 70 71 72
  Handle<BigInt> bigint;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, bigint,
                                     BigInt::FromObject(isolate, bigint_obj));

73
  return *BigInt::AsIntN(isolate, bits->Number(), bigint);
74 75 76 77 78 79 80 81 82 83 84 85
}

namespace {

MaybeHandle<BigInt> ThisBigIntValue(Isolate* isolate, Handle<Object> value,
                                    const char* caller) {
  // 1. If Type(value) is BigInt, return value.
  if (value->IsBigInt()) return Handle<BigInt>::cast(value);
  // 2. If Type(value) is Object and value has a [[BigIntData]] internal slot:
  if (value->IsJSValue()) {
    // 2a. Assert: value.[[BigIntData]] is a BigInt value.
    // 2b. Return value.[[BigIntData]].
86
    Object data = JSValue::cast(*value)->value();
87 88 89 90 91 92 93 94 95 96 97
    if (data->IsBigInt()) return handle(BigInt::cast(data), isolate);
  }
  // 3. Throw a TypeError exception.
  THROW_NEW_ERROR(
      isolate,
      NewTypeError(MessageTemplate::kNotGeneric,
                   isolate->factory()->NewStringFromAsciiChecked(caller),
                   isolate->factory()->NewStringFromStaticChars("BigInt")),
      BigInt);
}

98 99
Object BigIntToStringImpl(Handle<Object> receiver, Handle<Object> radix,
                          Isolate* isolate, const char* builtin_name) {
100 101 102
  // 1. Let x be ? thisBigIntValue(this value).
  Handle<BigInt> x;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
103
      isolate, x, ThisBigIntValue(isolate, receiver, builtin_name));
104 105
  // 2. If radix is not present, let radixNumber be 10.
  // 3. Else if radix is undefined, let radixNumber be 10.
106 107
  int radix_number = 10;
  if (!radix->IsUndefined(isolate)) {
108 109 110
    // 4. Else, let radixNumber be ? ToInteger(radix).
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, radix,
                                       Object::ToInteger(isolate, radix));
111 112 113 114 115 116 117
    double radix_double = radix->Number();
    // 5. If radixNumber < 2 or radixNumber > 36, throw a RangeError exception.
    if (radix_double < 2 || radix_double > 36) {
      THROW_NEW_ERROR_RETURN_FAILURE(
          isolate, NewRangeError(MessageTemplate::kToRadixFormatRange));
    }
    radix_number = static_cast<int>(radix_double);
118 119 120
  }
  // Return the String representation of this Number value using the radix
  // specified by radixNumber.
121
  RETURN_RESULT_OR_FAILURE(isolate, BigInt::ToString(isolate, x, radix_number));
122 123
}

124 125 126 127
}  // namespace

BUILTIN(BigIntPrototypeToLocaleString) {
  HandleScope scope(isolate);
128 129
#ifdef V8_INTL_SUPPORT
  if (FLAG_harmony_intl_bigint) {
130 131 132 133 134 135 136
    // 1. Let x be ? thisBigIntValue(this value).
    Handle<BigInt> x;
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
        isolate, x,
        ThisBigIntValue(isolate, args.receiver(),
                        "BigInt.prototype.toLocaleString"));

137
    RETURN_RESULT_OR_FAILURE(
138 139 140
        isolate,
        Intl::NumberToLocaleString(isolate, x, args.atOrUndefined(isolate, 1),
                                   args.atOrUndefined(isolate, 2)));
141 142 143 144
  }
  // Fallbacks to old toString implemention if flag is off or no
  // V8_INTL_SUPPORT
#endif  // V8_INTL_SUPPORT
145
  Handle<Object> radix = isolate->factory()->undefined_value();
146 147 148 149 150 151 152 153 154 155 156
  return BigIntToStringImpl(args.receiver(), radix, isolate,
                            "BigInt.prototype.toLocaleString");
}

BUILTIN(BigIntPrototypeToString) {
  HandleScope scope(isolate);
  Handle<Object> radix = args.atOrUndefined(isolate, 1);
  return BigIntToStringImpl(args.receiver(), radix, isolate,
                            "BigInt.prototype.toString");
}

157 158 159 160 161 162 163 164 165
BUILTIN(BigIntPrototypeValueOf) {
  HandleScope scope(isolate);
  RETURN_RESULT_OR_FAILURE(
      isolate,
      ThisBigIntValue(isolate, args.receiver(), "BigInt.prototype.valueOf"));
}

}  // namespace internal
}  // namespace v8