• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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/conversions.h"
8 #include "src/counters.h"
9 #include "src/objects-inl.h"
10 
11 namespace v8 {
12 namespace internal {
13 
BUILTIN(BigIntConstructor)14 BUILTIN(BigIntConstructor) {
15   HandleScope scope(isolate);
16   if (!args.new_target()->IsUndefined(isolate)) {  // [[Construct]]
17     THROW_NEW_ERROR_RETURN_FAILURE(
18         isolate, NewTypeError(MessageTemplate::kNotConstructor,
19                               isolate->factory()->BigInt_string()));
20   }
21   // [[Call]]
22   Handle<Object> value = args.atOrUndefined(isolate, 1);
23 
24   if (value->IsJSReceiver()) {
25     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
26         isolate, value,
27         JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(value),
28                                 ToPrimitiveHint::kNumber));
29   }
30 
31   if (value->IsNumber()) {
32     RETURN_RESULT_OR_FAILURE(isolate, BigInt::FromNumber(isolate, value));
33   } else {
34     RETURN_RESULT_OR_FAILURE(isolate, BigInt::FromObject(isolate, value));
35   }
36 }
37 
BUILTIN(BigIntAsUintN)38 BUILTIN(BigIntAsUintN) {
39   HandleScope scope(isolate);
40   Handle<Object> bits_obj = args.atOrUndefined(isolate, 1);
41   Handle<Object> bigint_obj = args.atOrUndefined(isolate, 2);
42 
43   Handle<Object> bits;
44   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
45       isolate, bits,
46       Object::ToIndex(isolate, bits_obj, MessageTemplate::kInvalidIndex));
47 
48   Handle<BigInt> bigint;
49   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, bigint,
50                                      BigInt::FromObject(isolate, bigint_obj));
51 
52   RETURN_RESULT_OR_FAILURE(isolate,
53                            BigInt::AsUintN(isolate, bits->Number(), bigint));
54 }
55 
BUILTIN(BigIntAsIntN)56 BUILTIN(BigIntAsIntN) {
57   HandleScope scope(isolate);
58   Handle<Object> bits_obj = args.atOrUndefined(isolate, 1);
59   Handle<Object> bigint_obj = args.atOrUndefined(isolate, 2);
60 
61   Handle<Object> bits;
62   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
63       isolate, bits,
64       Object::ToIndex(isolate, bits_obj, MessageTemplate::kInvalidIndex));
65 
66   Handle<BigInt> bigint;
67   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, bigint,
68                                      BigInt::FromObject(isolate, bigint_obj));
69 
70   return *BigInt::AsIntN(isolate, bits->Number(), bigint);
71 }
72 
73 namespace {
74 
ThisBigIntValue(Isolate * isolate,Handle<Object> value,const char * caller)75 MaybeHandle<BigInt> ThisBigIntValue(Isolate* isolate, Handle<Object> value,
76                                     const char* caller) {
77   // 1. If Type(value) is BigInt, return value.
78   if (value->IsBigInt()) return Handle<BigInt>::cast(value);
79   // 2. If Type(value) is Object and value has a [[BigIntData]] internal slot:
80   if (value->IsJSValue()) {
81     // 2a. Assert: value.[[BigIntData]] is a BigInt value.
82     // 2b. Return value.[[BigIntData]].
83     Object* data = JSValue::cast(*value)->value();
84     if (data->IsBigInt()) return handle(BigInt::cast(data), isolate);
85   }
86   // 3. Throw a TypeError exception.
87   THROW_NEW_ERROR(
88       isolate,
89       NewTypeError(MessageTemplate::kNotGeneric,
90                    isolate->factory()->NewStringFromAsciiChecked(caller),
91                    isolate->factory()->NewStringFromStaticChars("BigInt")),
92       BigInt);
93 }
94 
BigIntToStringImpl(Handle<Object> receiver,Handle<Object> radix,Isolate * isolate,const char * builtin_name)95 Object* BigIntToStringImpl(Handle<Object> receiver, Handle<Object> radix,
96                            Isolate* isolate, const char* builtin_name) {
97   // 1. Let x be ? thisBigIntValue(this value).
98   Handle<BigInt> x;
99   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
100       isolate, x, ThisBigIntValue(isolate, receiver, builtin_name));
101   // 2. If radix is not present, let radixNumber be 10.
102   // 3. Else if radix is undefined, let radixNumber be 10.
103   int radix_number;
104   if (radix->IsUndefined(isolate)) {
105     radix_number = 10;
106   } else {
107     // 4. Else, let radixNumber be ? ToInteger(radix).
108     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, radix,
109                                        Object::ToInteger(isolate, radix));
110     radix_number = static_cast<int>(radix->Number());
111   }
112   // 5. If radixNumber < 2 or radixNumber > 36, throw a RangeError exception.
113   if (radix_number < 2 || radix_number > 36) {
114     THROW_NEW_ERROR_RETURN_FAILURE(
115         isolate, NewRangeError(MessageTemplate::kToRadixFormatRange));
116   }
117   // Return the String representation of this Number value using the radix
118   // specified by radixNumber.
119   RETURN_RESULT_OR_FAILURE(isolate, BigInt::ToString(isolate, x, radix_number));
120 }
121 
122 }  // namespace
123 
BUILTIN(BigIntPrototypeToLocaleString)124 BUILTIN(BigIntPrototypeToLocaleString) {
125   HandleScope scope(isolate);
126   Handle<Object> radix = isolate->factory()->undefined_value();
127   return BigIntToStringImpl(args.receiver(), radix, isolate,
128                             "BigInt.prototype.toLocaleString");
129 }
130 
BUILTIN(BigIntPrototypeToString)131 BUILTIN(BigIntPrototypeToString) {
132   HandleScope scope(isolate);
133   Handle<Object> radix = args.atOrUndefined(isolate, 1);
134   return BigIntToStringImpl(args.receiver(), radix, isolate,
135                             "BigInt.prototype.toString");
136 }
137 
BUILTIN(BigIntPrototypeValueOf)138 BUILTIN(BigIntPrototypeValueOf) {
139   HandleScope scope(isolate);
140   RETURN_RESULT_OR_FAILURE(
141       isolate,
142       ThisBigIntValue(isolate, args.receiver(), "BigInt.prototype.valueOf"));
143 }
144 
145 }  // namespace internal
146 }  // namespace v8
147