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 :
11 : namespace v8 {
12 : namespace internal {
13 :
14 192048 : BUILTIN(BigIntConstructor) {
15 : HandleScope scope(isolate);
16 144036 : if (!args.new_target()->IsUndefined(isolate)) { // [[Construct]]
17 108 : 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 95916 : if (value->IsJSReceiver()) {
25 198 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
26 : isolate, value,
27 : JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(value),
28 : ToPrimitiveHint::kNumber));
29 : }
30 :
31 95916 : if (value->IsNumber()) {
32 95187 : RETURN_RESULT_OR_FAILURE(isolate, BigInt::FromNumber(isolate, value));
33 : } else {
34 900 : RETURN_RESULT_OR_FAILURE(isolate, BigInt::FromObject(isolate, value));
35 : }
36 : }
37 :
38 4680 : BUILTIN(BigIntAsUintN) {
39 : HandleScope scope(isolate);
40 1170 : Handle<Object> bits_obj = args.atOrUndefined(isolate, 1);
41 1170 : Handle<Object> bigint_obj = args.atOrUndefined(isolate, 2);
42 :
43 : Handle<Object> bits;
44 2367 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
45 : isolate, bits,
46 : Object::ToIndex(isolate, bits_obj, MessageTemplate::kInvalidIndex));
47 :
48 : Handle<BigInt> bigint;
49 2295 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, bigint,
50 : BigInt::FromObject(isolate, bigint_obj));
51 :
52 2268 : RETURN_RESULT_OR_FAILURE(isolate,
53 : BigInt::AsUintN(isolate, bits->Number(), bigint));
54 : }
55 :
56 4680 : BUILTIN(BigIntAsIntN) {
57 : HandleScope scope(isolate);
58 1170 : Handle<Object> bits_obj = args.atOrUndefined(isolate, 1);
59 1170 : Handle<Object> bigint_obj = args.atOrUndefined(isolate, 2);
60 :
61 : Handle<Object> bits;
62 2367 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
63 : isolate, bits,
64 : Object::ToIndex(isolate, bits_obj, MessageTemplate::kInvalidIndex));
65 :
66 : Handle<BigInt> bigint;
67 2295 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, bigint,
68 : BigInt::FromObject(isolate, bigint_obj));
69 :
70 2268 : return *BigInt::AsIntN(isolate, bits->Number(), bigint);
71 : }
72 :
73 : namespace {
74 :
75 1406 : MaybeHandle<BigInt> ThisBigIntValue(Isolate* isolate, Handle<Object> value,
76 : const char* caller) {
77 : // 1. If Type(value) is BigInt, return value.
78 2812 : if (value->IsBigInt()) return Handle<BigInt>::cast(value);
79 : // 2. If Type(value) is Object and value has a [[BigIntData]] internal slot:
80 256 : if (value->IsJSValue()) {
81 : // 2a. Assert: value.[[BigIntData]] is a BigInt value.
82 : // 2b. Return value.[[BigIntData]].
83 119 : Object data = JSValue::cast(*value)->value();
84 238 : if (data->IsBigInt()) return handle(BigInt::cast(data), isolate);
85 : }
86 : // 3. Throw a TypeError exception.
87 27 : THROW_NEW_ERROR(
88 : isolate,
89 : NewTypeError(MessageTemplate::kNotGeneric,
90 : isolate->factory()->NewStringFromAsciiChecked(caller),
91 : isolate->factory()->NewStringFromStaticChars("BigInt")),
92 : BigInt);
93 : }
94 :
95 1278 : 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 2556 : 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 2556 : if (radix->IsUndefined(isolate)) {
105 : radix_number = 10;
106 : } else {
107 : // 4. Else, let radixNumber be ? ToInteger(radix).
108 2520 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, radix,
109 : Object::ToInteger(isolate, radix));
110 1260 : radix_number = static_cast<int>(radix->Number());
111 : }
112 : // 5. If radixNumber < 2 or radixNumber > 36, throw a RangeError exception.
113 1278 : if (radix_number < 2 || radix_number > 36) {
114 0 : 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 2556 : RETURN_RESULT_OR_FAILURE(isolate, BigInt::ToString(isolate, x, radix_number));
120 : }
121 :
122 : } // namespace
123 :
124 0 : BUILTIN(BigIntPrototypeToLocaleString) {
125 : HandleScope scope(isolate);
126 : Handle<Object> radix = isolate->factory()->undefined_value();
127 : return BigIntToStringImpl(args.receiver(), radix, isolate,
128 0 : "BigInt.prototype.toLocaleString");
129 : }
130 :
131 5112 : BUILTIN(BigIntPrototypeToString) {
132 : HandleScope scope(isolate);
133 1278 : Handle<Object> radix = args.atOrUndefined(isolate, 1);
134 : return BigIntToStringImpl(args.receiver(), radix, isolate,
135 2556 : "BigInt.prototype.toString");
136 : }
137 :
138 512 : BUILTIN(BigIntPrototypeValueOf) {
139 : HandleScope scope(isolate);
140 265 : RETURN_RESULT_OR_FAILURE(
141 : isolate,
142 : ThisBigIntValue(isolate, args.receiver(), "BigInt.prototype.valueOf"));
143 : }
144 :
145 : } // namespace internal
146 183867 : } // namespace v8
|