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