Source code

Revision control

Other Tools

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/. */
6
7
/*
8
* JS boolean implementation.
9
*/
10
11
#include "builtin/Boolean-inl.h"
12
13
#include "jsapi.h"
14
#include "jstypes.h"
15
16
#include "jit/InlinableNatives.h"
17
#include "js/PropertySpec.h"
18
#include "util/StringBuffer.h"
19
#include "vm/BigIntType.h"
20
#include "vm/GlobalObject.h"
21
#include "vm/JSAtom.h"
22
#include "vm/JSContext.h"
23
#include "vm/JSObject.h"
24
#include "vm/ProxyObject.h"
25
26
#include "vm/BooleanObject-inl.h"
27
28
using namespace js;
29
30
const JSClass BooleanObject::class_ = {
31
"Boolean",
32
JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean)};
33
34
MOZ_ALWAYS_INLINE bool IsBoolean(HandleValue v) {
35
return v.isBoolean() || (v.isObject() && v.toObject().is<BooleanObject>());
36
}
37
38
MOZ_ALWAYS_INLINE bool bool_toSource_impl(JSContext* cx, const CallArgs& args) {
39
HandleValue thisv = args.thisv();
40
MOZ_ASSERT(IsBoolean(thisv));
41
42
bool b = thisv.isBoolean() ? thisv.toBoolean()
43
: thisv.toObject().as<BooleanObject>().unbox();
44
45
JSStringBuilder sb(cx);
46
if (!sb.append("(new Boolean(") || !BooleanToStringBuffer(b, sb) ||
47
!sb.append("))")) {
48
return false;
49
}
50
51
JSString* str = sb.finishString();
52
if (!str) {
53
return false;
54
}
55
args.rval().setString(str);
56
return true;
57
}
58
59
static bool bool_toSource(JSContext* cx, unsigned argc, Value* vp) {
60
CallArgs args = CallArgsFromVp(argc, vp);
61
return CallNonGenericMethod<IsBoolean, bool_toSource_impl>(cx, args);
62
}
63
64
MOZ_ALWAYS_INLINE bool bool_toString_impl(JSContext* cx, const CallArgs& args) {
65
HandleValue thisv = args.thisv();
66
MOZ_ASSERT(IsBoolean(thisv));
67
68
bool b = thisv.isBoolean() ? thisv.toBoolean()
69
: thisv.toObject().as<BooleanObject>().unbox();
70
args.rval().setString(BooleanToString(cx, b));
71
return true;
72
}
73
74
static bool bool_toString(JSContext* cx, unsigned argc, Value* vp) {
75
CallArgs args = CallArgsFromVp(argc, vp);
76
return CallNonGenericMethod<IsBoolean, bool_toString_impl>(cx, args);
77
}
78
79
MOZ_ALWAYS_INLINE bool bool_valueOf_impl(JSContext* cx, const CallArgs& args) {
80
HandleValue thisv = args.thisv();
81
MOZ_ASSERT(IsBoolean(thisv));
82
83
bool b = thisv.isBoolean() ? thisv.toBoolean()
84
: thisv.toObject().as<BooleanObject>().unbox();
85
args.rval().setBoolean(b);
86
return true;
87
}
88
89
static bool bool_valueOf(JSContext* cx, unsigned argc, Value* vp) {
90
CallArgs args = CallArgsFromVp(argc, vp);
91
return CallNonGenericMethod<IsBoolean, bool_valueOf_impl>(cx, args);
92
}
93
94
static const JSFunctionSpec boolean_methods[] = {
95
JS_FN(js_toSource_str, bool_toSource, 0, 0),
96
JS_FN(js_toString_str, bool_toString, 0, 0),
97
JS_FN(js_valueOf_str, bool_valueOf, 0, 0), JS_FS_END};
98
99
static bool Boolean(JSContext* cx, unsigned argc, Value* vp) {
100
CallArgs args = CallArgsFromVp(argc, vp);
101
102
bool b = args.length() != 0 ? JS::ToBoolean(args[0]) : false;
103
104
if (args.isConstructing()) {
105
RootedObject proto(cx);
106
if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_Boolean,
107
&proto)) {
108
return false;
109
}
110
111
JSObject* obj = BooleanObject::create(cx, b, proto);
112
if (!obj) {
113
return false;
114
}
115
args.rval().setObject(*obj);
116
} else {
117
args.rval().setBoolean(b);
118
}
119
return true;
120
}
121
122
JSObject* js::InitBooleanClass(JSContext* cx, Handle<GlobalObject*> global) {
123
Rooted<BooleanObject*> booleanProto(
124
cx, GlobalObject::createBlankPrototype<BooleanObject>(cx, global));
125
if (!booleanProto) {
126
return nullptr;
127
}
128
booleanProto->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT,
129
BooleanValue(false));
130
131
RootedFunction ctor(cx, GlobalObject::createConstructor(
132
cx, Boolean, cx->names().Boolean, 1,
133
gc::AllocKind::FUNCTION, &jit::JitInfo_Boolean));
134
if (!ctor) {
135
return nullptr;
136
}
137
138
if (!LinkConstructorAndPrototype(cx, ctor, booleanProto)) {
139
return nullptr;
140
}
141
142
if (!DefinePropertiesAndFunctions(cx, booleanProto, nullptr,
143
boolean_methods)) {
144
return nullptr;
145
}
146
147
if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_Boolean, ctor,
148
booleanProto)) {
149
return nullptr;
150
}
151
152
return booleanProto;
153
}
154
155
JSString* js::BooleanToString(JSContext* cx, bool b) {
156
return b ? cx->names().true_ : cx->names().false_;
157
}
158
159
JS_PUBLIC_API bool js::ToBooleanSlow(HandleValue v) {
160
if (v.isString()) {
161
return v.toString()->length() != 0;
162
}
163
if (v.isBigInt()) {
164
return !v.toBigInt()->isZero();
165
}
166
167
MOZ_ASSERT(v.isObject());
168
return !EmulatesUndefined(&v.toObject());
169
}