Bug 1874684 - Part 21: Rename SecondsAndNanoseconds::toTotalNanoseconds. r=dminor
[gecko.git] / js / src / builtin / Boolean.cpp
blob7806362d134e36f0f21a3bef91df260a6c150787
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 /*
8 * JS boolean implementation.
9 */
11 #include "builtin/Boolean-inl.h"
13 #include "jstypes.h"
15 #include "jit/InlinableNatives.h"
16 #include "js/PropertySpec.h"
17 #include "util/StringBuffer.h"
18 #include "vm/BigIntType.h"
19 #include "vm/GlobalObject.h"
20 #include "vm/JSContext.h"
21 #include "vm/JSObject.h"
23 #include "vm/BooleanObject-inl.h"
25 using namespace js;
27 const JSClass BooleanObject::class_ = {
28 "Boolean",
29 JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
30 JS_NULL_CLASS_OPS, &BooleanObject::classSpec_};
32 MOZ_ALWAYS_INLINE bool IsBoolean(HandleValue v) {
33 return v.isBoolean() || (v.isObject() && v.toObject().is<BooleanObject>());
36 // ES2020 draft rev ecb4178012d6b4d9abc13fcbd45f5c6394b832ce
37 // 19.4.3 Properties of the Boolean Prototype Object, thisBooleanValue.
38 static MOZ_ALWAYS_INLINE bool ThisBooleanValue(HandleValue val) {
39 // Step 3, the error case, is handled by CallNonGenericMethod.
40 MOZ_ASSERT(IsBoolean(val));
42 // Step 1.
43 if (val.isBoolean()) {
44 return val.toBoolean();
47 // Step 2.
48 return val.toObject().as<BooleanObject>().unbox();
51 MOZ_ALWAYS_INLINE bool bool_toSource_impl(JSContext* cx, const CallArgs& args) {
52 bool b = ThisBooleanValue(args.thisv());
54 JSStringBuilder sb(cx);
55 if (!sb.append("(new Boolean(") || !BooleanToStringBuffer(b, sb) ||
56 !sb.append("))")) {
57 return false;
60 JSString* str = sb.finishString();
61 if (!str) {
62 return false;
64 args.rval().setString(str);
65 return true;
68 static bool bool_toSource(JSContext* cx, unsigned argc, Value* vp) {
69 CallArgs args = CallArgsFromVp(argc, vp);
70 return CallNonGenericMethod<IsBoolean, bool_toSource_impl>(cx, args);
73 // ES2020 draft rev ecb4178012d6b4d9abc13fcbd45f5c6394b832ce
74 // 19.3.3.2 Boolean.prototype.toString ( )
75 MOZ_ALWAYS_INLINE bool bool_toString_impl(JSContext* cx, const CallArgs& args) {
76 // Step 1.
77 bool b = ThisBooleanValue(args.thisv());
79 // Step 2.
80 args.rval().setString(BooleanToString(cx, b));
81 return true;
84 static bool bool_toString(JSContext* cx, unsigned argc, Value* vp) {
85 CallArgs args = CallArgsFromVp(argc, vp);
86 return CallNonGenericMethod<IsBoolean, bool_toString_impl>(cx, args);
89 // ES2020 draft rev ecb4178012d6b4d9abc13fcbd45f5c6394b832ce
90 // 19.3.3.3 Boolean.prototype.valueOf ( )
91 MOZ_ALWAYS_INLINE bool bool_valueOf_impl(JSContext* cx, const CallArgs& args) {
92 // Step 1.
93 args.rval().setBoolean(ThisBooleanValue(args.thisv()));
94 return true;
97 static bool bool_valueOf(JSContext* cx, unsigned argc, Value* vp) {
98 CallArgs args = CallArgsFromVp(argc, vp);
99 return CallNonGenericMethod<IsBoolean, bool_valueOf_impl>(cx, args);
102 static const JSFunctionSpec boolean_methods[] = {
103 JS_FN("toSource", bool_toSource, 0, 0),
104 JS_FN("toString", bool_toString, 0, 0),
105 JS_FN("valueOf", bool_valueOf, 0, 0), JS_FS_END};
107 // ES2020 draft rev ecb4178012d6b4d9abc13fcbd45f5c6394b832ce
108 // 19.3.1.1 Boolean ( value )
109 static bool Boolean(JSContext* cx, unsigned argc, Value* vp) {
110 CallArgs args = CallArgsFromVp(argc, vp);
112 // Step 1.
113 bool b = args.length() != 0 ? JS::ToBoolean(args[0]) : false;
115 if (args.isConstructing()) {
116 // Steps 3-4.
117 RootedObject proto(cx);
118 if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_Boolean,
119 &proto)) {
120 return false;
123 JSObject* obj = BooleanObject::create(cx, b, proto);
124 if (!obj) {
125 return false;
128 // Step 5.
129 args.rval().setObject(*obj);
130 } else {
131 // Step 2.
132 args.rval().setBoolean(b);
134 return true;
137 JSObject* BooleanObject::createPrototype(JSContext* cx, JSProtoKey key) {
138 BooleanObject* booleanProto =
139 GlobalObject::createBlankPrototype<BooleanObject>(cx, cx->global());
140 if (!booleanProto) {
141 return nullptr;
143 booleanProto->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT,
144 BooleanValue(false));
145 return booleanProto;
148 const ClassSpec BooleanObject::classSpec_ = {
149 GenericCreateConstructor<Boolean, 1, gc::AllocKind::FUNCTION,
150 &jit::JitInfo_Boolean>,
151 BooleanObject::createPrototype,
152 nullptr,
153 nullptr,
154 boolean_methods,
155 nullptr};
157 PropertyName* js::BooleanToString(JSContext* cx, bool b) {
158 return b ? cx->names().true_ : cx->names().false_;
161 JS_PUBLIC_API bool js::ToBooleanSlow(HandleValue v) {
162 if (v.isString()) {
163 return v.toString()->length() != 0;
165 if (v.isBigInt()) {
166 return !v.toBigInt()->isZero();
168 #ifdef ENABLE_RECORD_TUPLE
169 // proposal-record-tuple Section 3.1.1
170 if (v.isExtendedPrimitive()) {
171 return true;
173 #endif
175 MOZ_ASSERT(v.isObject());
176 return !EmulatesUndefined(&v.toObject());