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/. */
8 * JS boolean implementation.
11 #include "builtin/Boolean-inl.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"
27 const JSClass
BooleanObject::class_
= {
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
));
43 if (val
.isBoolean()) {
44 return val
.toBoolean();
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
) ||
60 JSString
* str
= sb
.finishString();
64 args
.rval().setString(str
);
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
) {
77 bool b
= ThisBooleanValue(args
.thisv());
80 args
.rval().setString(BooleanToString(cx
, b
));
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
) {
93 args
.rval().setBoolean(ThisBooleanValue(args
.thisv()));
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
);
113 bool b
= args
.length() != 0 ? JS::ToBoolean(args
[0]) : false;
115 if (args
.isConstructing()) {
117 RootedObject
proto(cx
);
118 if (!GetPrototypeFromBuiltinConstructor(cx
, args
, JSProto_Boolean
,
123 JSObject
* obj
= BooleanObject::create(cx
, b
, proto
);
129 args
.rval().setObject(*obj
);
132 args
.rval().setBoolean(b
);
137 JSObject
* BooleanObject::createPrototype(JSContext
* cx
, JSProtoKey key
) {
138 BooleanObject
* booleanProto
=
139 GlobalObject::createBlankPrototype
<BooleanObject
>(cx
, cx
->global());
143 booleanProto
->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT
,
144 BooleanValue(false));
148 const ClassSpec
BooleanObject::classSpec_
= {
149 GenericCreateConstructor
<Boolean
, 1, gc::AllocKind::FUNCTION
,
150 &jit::JitInfo_Boolean
>,
151 BooleanObject::createPrototype
,
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
) {
163 return v
.toString()->length() != 0;
166 return !v
.toBigInt()->isZero();
168 #ifdef ENABLE_RECORD_TUPLE
169 // proposal-record-tuple Section 3.1.1
170 if (v
.isExtendedPrimitive()) {
175 MOZ_ASSERT(v
.isObject());
176 return !EmulatesUndefined(&v
.toObject());