Line data Source code
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 : #ifdef V8_INTL_SUPPORT
11 : #include "src/objects/intl-objects.h"
12 : #endif
13 :
14 : namespace v8 {
15 : namespace internal {
16 :
17 241990 : BUILTIN(BigIntConstructor) {
18 : HandleScope scope(isolate);
19 48398 : if (!args.new_target()->IsUndefined(isolate)) { // [[Construct]]
20 108 : 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 48344 : if (value->IsJSReceiver()) {
28 198 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
29 : isolate, value,
30 : JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(value),
31 : ToPrimitiveHint::kNumber));
32 : }
33 :
34 48344 : if (value->IsNumber()) {
35 95959 : RETURN_RESULT_OR_FAILURE(isolate, BigInt::FromNumber(isolate, value));
36 : } else {
37 900 : RETURN_RESULT_OR_FAILURE(isolate, BigInt::FromObject(isolate, value));
38 : }
39 : }
40 :
41 5940 : BUILTIN(BigIntAsUintN) {
42 : HandleScope scope(isolate);
43 1188 : Handle<Object> bits_obj = args.atOrUndefined(isolate, 1);
44 1188 : Handle<Object> bigint_obj = args.atOrUndefined(isolate, 2);
45 :
46 : Handle<Object> bits;
47 2403 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
48 : isolate, bits,
49 : Object::ToIndex(isolate, bits_obj, MessageTemplate::kInvalidIndex));
50 :
51 : Handle<BigInt> bigint;
52 2331 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, bigint,
53 : BigInt::FromObject(isolate, bigint_obj));
54 :
55 2304 : RETURN_RESULT_OR_FAILURE(isolate,
56 : BigInt::AsUintN(isolate, bits->Number(), bigint));
57 : }
58 :
59 5850 : BUILTIN(BigIntAsIntN) {
60 : HandleScope scope(isolate);
61 1170 : Handle<Object> bits_obj = args.atOrUndefined(isolate, 1);
62 1170 : Handle<Object> bigint_obj = args.atOrUndefined(isolate, 2);
63 :
64 : Handle<Object> bits;
65 2367 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
66 : isolate, bits,
67 : Object::ToIndex(isolate, bits_obj, MessageTemplate::kInvalidIndex));
68 :
69 : Handle<BigInt> bigint;
70 2295 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, bigint,
71 : BigInt::FromObject(isolate, bigint_obj));
72 :
73 2268 : return *BigInt::AsIntN(isolate, bits->Number(), bigint);
74 : }
75 :
76 : namespace {
77 :
78 1528 : MaybeHandle<BigInt> ThisBigIntValue(Isolate* isolate, Handle<Object> value,
79 : const char* caller) {
80 : // 1. If Type(value) is BigInt, return value.
81 1528 : if (value->IsBigInt()) return Handle<BigInt>::cast(value);
82 : // 2. If Type(value) is Object and value has a [[BigIntData]] internal slot:
83 128 : if (value->IsJSValue()) {
84 : // 2a. Assert: value.[[BigIntData]] is a BigInt value.
85 : // 2b. Return value.[[BigIntData]].
86 : Object data = JSValue::cast(*value)->value();
87 238 : if (data->IsBigInt()) return handle(BigInt::cast(data), isolate);
88 : }
89 : // 3. Throw a TypeError exception.
90 36 : THROW_NEW_ERROR(
91 : isolate,
92 : NewTypeError(MessageTemplate::kNotGeneric,
93 : isolate->factory()->NewStringFromAsciiChecked(caller),
94 : isolate->factory()->NewStringFromStaticChars("BigInt")),
95 : BigInt);
96 : }
97 :
98 1400 : 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 2800 : 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 1400 : if (!radix->IsUndefined(isolate)) {
108 : // 4. Else, let radixNumber be ? ToInteger(radix).
109 1269 : 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 1269 : if (radix_double < 2 || radix_double > 36) {
114 18 : THROW_NEW_ERROR_RETURN_FAILURE(
115 : isolate, NewRangeError(MessageTemplate::kToRadixFormatRange));
116 : }
117 1260 : 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 2787 : RETURN_RESULT_OR_FAILURE(isolate, BigInt::ToString(isolate, x, radix_number));
122 : }
123 :
124 : } // namespace
125 :
126 2970 : BUILTIN(BigIntPrototypeToLocaleString) {
127 : HandleScope scope(isolate);
128 : #ifdef V8_INTL_SUPPORT
129 594 : if (FLAG_harmony_intl_bigint) {
130 1188 : RETURN_RESULT_OR_FAILURE(
131 : isolate, Intl::NumberToLocaleString(isolate, args.receiver(),
132 : args.atOrUndefined(isolate, 1),
133 : args.atOrUndefined(isolate, 2)));
134 : }
135 : // Fallbacks to old toString implemention if flag is off or no
136 : // V8_INTL_SUPPORT
137 : #endif // V8_INTL_SUPPORT
138 : Handle<Object> radix = isolate->factory()->undefined_value();
139 : return BigIntToStringImpl(args.receiver(), radix, isolate,
140 0 : "BigInt.prototype.toLocaleString");
141 : }
142 :
143 7000 : BUILTIN(BigIntPrototypeToString) {
144 : HandleScope scope(isolate);
145 1400 : Handle<Object> radix = args.atOrUndefined(isolate, 1);
146 : return BigIntToStringImpl(args.receiver(), radix, isolate,
147 2800 : "BigInt.prototype.toString");
148 : }
149 :
150 640 : BUILTIN(BigIntPrototypeValueOf) {
151 : HandleScope scope(isolate);
152 265 : RETURN_RESULT_OR_FAILURE(
153 : isolate,
154 : ThisBigIntValue(isolate, args.receiver(), "BigInt.prototype.valueOf"));
155 : }
156 :
157 : } // namespace internal
158 120216 : } // namespace v8
|