Bug 1874684 - Part 21: Rename SecondsAndNanoseconds::toTotalNanoseconds. r=dminor
[gecko.git] / js / src / builtin / BigInt.cpp
blob378c383295c78aaba14bd8c4a8c9a2ce7f97d7d0
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "builtin/BigInt.h"
9 #include "jit/InlinableNatives.h"
10 #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
11 #include "js/PropertySpec.h"
12 #include "vm/BigIntType.h"
14 #include "vm/GeckoProfiler-inl.h"
15 #include "vm/JSObject-inl.h"
17 using namespace js;
19 static MOZ_ALWAYS_INLINE bool IsBigInt(HandleValue v) {
20 return v.isBigInt() || (v.isObject() && v.toObject().is<BigIntObject>());
23 // BigInt proposal section 5.1.3
24 static bool BigIntConstructor(JSContext* cx, unsigned argc, Value* vp) {
25 AutoJSConstructorProfilerEntry pseudoFrame(cx, "BigInt");
26 CallArgs args = CallArgsFromVp(argc, vp);
28 // Step 1.
29 if (args.isConstructing()) {
30 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
31 JSMSG_NOT_CONSTRUCTOR, "BigInt");
32 return false;
35 // Step 2.
36 RootedValue v(cx, args.get(0));
37 if (!ToPrimitive(cx, JSTYPE_NUMBER, &v)) {
38 return false;
41 // Steps 3-4.
42 BigInt* bi =
43 v.isNumber() ? NumberToBigInt(cx, v.toNumber()) : ToBigInt(cx, v);
44 if (!bi) {
45 return false;
48 args.rval().setBigInt(bi);
49 return true;
52 JSObject* BigIntObject::create(JSContext* cx, HandleBigInt bigInt) {
53 BigIntObject* bn = NewBuiltinClassInstance<BigIntObject>(cx);
54 if (!bn) {
55 return nullptr;
57 bn->setFixedSlot(PRIMITIVE_VALUE_SLOT, BigIntValue(bigInt));
58 return bn;
61 BigInt* BigIntObject::unbox() const {
62 return getFixedSlot(PRIMITIVE_VALUE_SLOT).toBigInt();
65 // BigInt proposal section 5.3.4
66 bool BigIntObject::valueOf_impl(JSContext* cx, const CallArgs& args) {
67 // Step 1.
68 HandleValue thisv = args.thisv();
69 MOZ_ASSERT(IsBigInt(thisv));
70 BigInt* bi = thisv.isBigInt() ? thisv.toBigInt()
71 : thisv.toObject().as<BigIntObject>().unbox();
73 args.rval().setBigInt(bi);
74 return true;
77 bool BigIntObject::valueOf(JSContext* cx, unsigned argc, Value* vp) {
78 CallArgs args = CallArgsFromVp(argc, vp);
79 return CallNonGenericMethod<IsBigInt, valueOf_impl>(cx, args);
82 // BigInt proposal section 5.3.3
83 bool BigIntObject::toString_impl(JSContext* cx, const CallArgs& args) {
84 // Step 1.
85 HandleValue thisv = args.thisv();
86 MOZ_ASSERT(IsBigInt(thisv));
87 RootedBigInt bi(cx, thisv.isBigInt()
88 ? thisv.toBigInt()
89 : thisv.toObject().as<BigIntObject>().unbox());
91 // Steps 2-3.
92 uint8_t radix = 10;
94 // Steps 4-5.
95 if (args.hasDefined(0)) {
96 double d;
97 if (!ToInteger(cx, args[0], &d)) {
98 return false;
100 if (d < 2 || d > 36) {
101 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_RADIX);
102 return false;
104 radix = d;
107 // Steps 6-7.
108 JSLinearString* str = BigInt::toString<CanGC>(cx, bi, radix);
109 if (!str) {
110 return false;
112 args.rval().setString(str);
113 return true;
116 bool BigIntObject::toString(JSContext* cx, unsigned argc, Value* vp) {
117 AutoJSMethodProfilerEntry pseudoFrame(cx, "BigInt.prototype", "toString");
118 CallArgs args = CallArgsFromVp(argc, vp);
119 return CallNonGenericMethod<IsBigInt, toString_impl>(cx, args);
122 #ifndef JS_HAS_INTL_API
123 // BigInt proposal section 5.3.2. "This function is
124 // implementation-dependent, and it is permissible, but not encouraged,
125 // for it to return the same thing as toString."
126 bool BigIntObject::toLocaleString_impl(JSContext* cx, const CallArgs& args) {
127 HandleValue thisv = args.thisv();
128 MOZ_ASSERT(IsBigInt(thisv));
129 RootedBigInt bi(cx, thisv.isBigInt()
130 ? thisv.toBigInt()
131 : thisv.toObject().as<BigIntObject>().unbox());
133 JSString* str = BigInt::toString<CanGC>(cx, bi, 10);
134 if (!str) {
135 return false;
137 args.rval().setString(str);
138 return true;
141 bool BigIntObject::toLocaleString(JSContext* cx, unsigned argc, Value* vp) {
142 AutoJSMethodProfilerEntry pseudoFrame(cx, "BigInt.prototype",
143 "toLocaleString");
144 CallArgs args = CallArgsFromVp(argc, vp);
145 return CallNonGenericMethod<IsBigInt, toLocaleString_impl>(cx, args);
147 #endif /* !JS_HAS_INTL_API */
149 // BigInt proposal section 5.2.1. BigInt.asUintN ( bits, bigint )
150 bool BigIntObject::asUintN(JSContext* cx, unsigned argc, Value* vp) {
151 CallArgs args = CallArgsFromVp(argc, vp);
153 // Step 1.
154 uint64_t bits;
155 if (!ToIndex(cx, args.get(0), &bits)) {
156 return false;
159 // Step 2.
160 RootedBigInt bi(cx, ToBigInt(cx, args.get(1)));
161 if (!bi) {
162 return false;
165 // Step 3.
166 BigInt* res = BigInt::asUintN(cx, bi, bits);
167 if (!res) {
168 return false;
171 args.rval().setBigInt(res);
172 return true;
175 // BigInt proposal section 5.2.2. BigInt.asIntN ( bits, bigint )
176 bool BigIntObject::asIntN(JSContext* cx, unsigned argc, Value* vp) {
177 CallArgs args = CallArgsFromVp(argc, vp);
179 // Step 1.
180 uint64_t bits;
181 if (!ToIndex(cx, args.get(0), &bits)) {
182 return false;
185 // Step 2.
186 RootedBigInt bi(cx, ToBigInt(cx, args.get(1)));
187 if (!bi) {
188 return false;
191 // Step 3.
192 BigInt* res = BigInt::asIntN(cx, bi, bits);
193 if (!res) {
194 return false;
197 args.rval().setBigInt(res);
198 return true;
201 const ClassSpec BigIntObject::classSpec_ = {
202 GenericCreateConstructor<BigIntConstructor, 1, gc::AllocKind::FUNCTION>,
203 GenericCreatePrototype<BigIntObject>,
204 BigIntObject::staticMethods,
205 nullptr,
206 BigIntObject::methods,
207 BigIntObject::properties};
209 const JSClass BigIntObject::class_ = {
210 "BigInt",
211 JSCLASS_HAS_CACHED_PROTO(JSProto_BigInt) |
212 JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS),
213 JS_NULL_CLASS_OPS, &BigIntObject::classSpec_};
215 const JSClass BigIntObject::protoClass_ = {
216 "BigInt.prototype", JSCLASS_HAS_CACHED_PROTO(JSProto_BigInt),
217 JS_NULL_CLASS_OPS, &BigIntObject::classSpec_};
219 const JSPropertySpec BigIntObject::properties[] = {
220 // BigInt proposal section 5.3.5
221 JS_STRING_SYM_PS(toStringTag, "BigInt", JSPROP_READONLY), JS_PS_END};
223 const JSFunctionSpec BigIntObject::methods[] = {
224 JS_FN("valueOf", valueOf, 0, 0), JS_FN("toString", toString, 0, 0),
225 #ifdef JS_HAS_INTL_API
226 JS_SELF_HOSTED_FN("toLocaleString", "BigInt_toLocaleString", 0, 0),
227 #else
228 JS_FN("toLocaleString", toLocaleString, 0, 0),
229 #endif
230 JS_FS_END};
232 const JSFunctionSpec BigIntObject::staticMethods[] = {
233 JS_INLINABLE_FN("asUintN", asUintN, 2, 0, BigIntAsUintN),
234 JS_INLINABLE_FN("asIntN", asIntN, 2, 0, BigIntAsIntN), JS_FS_END};