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