Thu, 15 Jan 2015 15:55:04 +0100
Back out 97036ab72558 which inappropriately compared turds to third parties.
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/. */
7 /*
8 * JS boolean implementation.
9 */
11 #include "jsboolinlines.h"
13 #include "jsapi.h"
14 #include "jsatom.h"
15 #include "jscntxt.h"
16 #include "jsobj.h"
17 #include "jstypes.h"
19 #include "vm/GlobalObject.h"
20 #include "vm/ProxyObject.h"
21 #include "vm/StringBuffer.h"
23 #include "vm/BooleanObject-inl.h"
25 using namespace js;
26 using namespace js::types;
28 const Class BooleanObject::class_ = {
29 "Boolean",
30 JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
31 JS_PropertyStub, /* addProperty */
32 JS_DeletePropertyStub, /* delProperty */
33 JS_PropertyStub, /* getProperty */
34 JS_StrictPropertyStub, /* setProperty */
35 JS_EnumerateStub,
36 JS_ResolveStub,
37 JS_ConvertStub
38 };
40 MOZ_ALWAYS_INLINE bool
41 IsBoolean(HandleValue v)
42 {
43 return v.isBoolean() || (v.isObject() && v.toObject().is<BooleanObject>());
44 }
46 #if JS_HAS_TOSOURCE
47 MOZ_ALWAYS_INLINE bool
48 bool_toSource_impl(JSContext *cx, CallArgs args)
49 {
50 HandleValue thisv = args.thisv();
51 JS_ASSERT(IsBoolean(thisv));
53 bool b = thisv.isBoolean() ? thisv.toBoolean() : thisv.toObject().as<BooleanObject>().unbox();
55 StringBuffer sb(cx);
56 if (!sb.append("(new Boolean(") || !BooleanToStringBuffer(b, sb) || !sb.append("))"))
57 return false;
59 JSString *str = sb.finishString();
60 if (!str)
61 return false;
62 args.rval().setString(str);
63 return true;
64 }
66 static bool
67 bool_toSource(JSContext *cx, unsigned argc, Value *vp)
68 {
69 CallArgs args = CallArgsFromVp(argc, vp);
70 return CallNonGenericMethod<IsBoolean, bool_toSource_impl>(cx, args);
71 }
72 #endif
74 MOZ_ALWAYS_INLINE bool
75 bool_toString_impl(JSContext *cx, CallArgs args)
76 {
77 HandleValue thisv = args.thisv();
78 JS_ASSERT(IsBoolean(thisv));
80 bool b = thisv.isBoolean() ? thisv.toBoolean() : thisv.toObject().as<BooleanObject>().unbox();
81 args.rval().setString(js_BooleanToString(cx, b));
82 return true;
83 }
85 static bool
86 bool_toString(JSContext *cx, unsigned argc, Value *vp)
87 {
88 CallArgs args = CallArgsFromVp(argc, vp);
89 return CallNonGenericMethod<IsBoolean, bool_toString_impl>(cx, args);
90 }
92 MOZ_ALWAYS_INLINE bool
93 bool_valueOf_impl(JSContext *cx, CallArgs args)
94 {
95 HandleValue thisv = args.thisv();
96 JS_ASSERT(IsBoolean(thisv));
98 bool b = thisv.isBoolean() ? thisv.toBoolean() : thisv.toObject().as<BooleanObject>().unbox();
99 args.rval().setBoolean(b);
100 return true;
101 }
103 static bool
104 bool_valueOf(JSContext *cx, unsigned argc, Value *vp)
105 {
106 CallArgs args = CallArgsFromVp(argc, vp);
107 return CallNonGenericMethod<IsBoolean, bool_valueOf_impl>(cx, args);
108 }
110 static const JSFunctionSpec boolean_methods[] = {
111 #if JS_HAS_TOSOURCE
112 JS_FN(js_toSource_str, bool_toSource, 0, 0),
113 #endif
114 JS_FN(js_toString_str, bool_toString, 0, 0),
115 JS_FS_END
116 };
118 static bool
119 Boolean(JSContext *cx, unsigned argc, Value *vp)
120 {
121 CallArgs args = CallArgsFromVp(argc, vp);
123 bool b = args.length() != 0 ? JS::ToBoolean(args[0]) : false;
125 if (args.isConstructing()) {
126 JSObject *obj = BooleanObject::create(cx, b);
127 if (!obj)
128 return false;
129 args.rval().setObject(*obj);
130 } else {
131 args.rval().setBoolean(b);
132 }
133 return true;
134 }
136 JSObject *
137 js_InitBooleanClass(JSContext *cx, HandleObject obj)
138 {
139 JS_ASSERT(obj->isNative());
141 Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
143 RootedObject booleanProto (cx, global->createBlankPrototype(cx, &BooleanObject::class_));
144 if (!booleanProto)
145 return nullptr;
146 booleanProto->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT, BooleanValue(false));
148 RootedFunction ctor(cx, global->createConstructor(cx, Boolean, cx->names().Boolean, 1));
149 if (!ctor)
150 return nullptr;
152 if (!LinkConstructorAndPrototype(cx, ctor, booleanProto))
153 return nullptr;
155 if (!DefinePropertiesAndBrand(cx, booleanProto, nullptr, boolean_methods))
156 return nullptr;
158 Handle<PropertyName*> valueOfName = cx->names().valueOf;
159 RootedFunction
160 valueOf(cx, NewFunction(cx, NullPtr(), bool_valueOf, 0, JSFunction::NATIVE_FUN,
161 global, valueOfName));
162 if (!valueOf)
163 return nullptr;
165 RootedValue value(cx, ObjectValue(*valueOf));
166 if (!JSObject::defineProperty(cx, booleanProto, valueOfName, value,
167 JS_PropertyStub, JS_StrictPropertyStub, 0))
168 {
169 return nullptr;
170 }
172 if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_Boolean, ctor, booleanProto))
173 return nullptr;
175 return booleanProto;
176 }
178 JSString *
179 js_BooleanToString(ExclusiveContext *cx, bool b)
180 {
181 return b ? cx->names().true_ : cx->names().false_;
182 }
184 JS_PUBLIC_API(bool)
185 js::ToBooleanSlow(HandleValue v)
186 {
187 if (v.isString())
188 return v.toString()->length() != 0;
190 JS_ASSERT(v.isObject());
191 return !EmulatesUndefined(&v.toObject());
192 }
194 /*
195 * This slow path is only ever taken for proxies wrapping Boolean objects
196 * The only caller of the fast path, JSON's PreprocessValue, ensures that.
197 */
198 bool
199 js::BooleanGetPrimitiveValueSlow(HandleObject wrappedBool)
200 {
201 JSObject *obj = wrappedBool->as<ProxyObject>().target();
202 JS_ASSERT(obj);
203 return obj->as<BooleanObject>().unbox();
204 }