1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jsbool.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,204 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* 1.11 + * JS boolean implementation. 1.12 + */ 1.13 + 1.14 +#include "jsboolinlines.h" 1.15 + 1.16 +#include "jsapi.h" 1.17 +#include "jsatom.h" 1.18 +#include "jscntxt.h" 1.19 +#include "jsobj.h" 1.20 +#include "jstypes.h" 1.21 + 1.22 +#include "vm/GlobalObject.h" 1.23 +#include "vm/ProxyObject.h" 1.24 +#include "vm/StringBuffer.h" 1.25 + 1.26 +#include "vm/BooleanObject-inl.h" 1.27 + 1.28 +using namespace js; 1.29 +using namespace js::types; 1.30 + 1.31 +const Class BooleanObject::class_ = { 1.32 + "Boolean", 1.33 + JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean), 1.34 + JS_PropertyStub, /* addProperty */ 1.35 + JS_DeletePropertyStub, /* delProperty */ 1.36 + JS_PropertyStub, /* getProperty */ 1.37 + JS_StrictPropertyStub, /* setProperty */ 1.38 + JS_EnumerateStub, 1.39 + JS_ResolveStub, 1.40 + JS_ConvertStub 1.41 +}; 1.42 + 1.43 +MOZ_ALWAYS_INLINE bool 1.44 +IsBoolean(HandleValue v) 1.45 +{ 1.46 + return v.isBoolean() || (v.isObject() && v.toObject().is<BooleanObject>()); 1.47 +} 1.48 + 1.49 +#if JS_HAS_TOSOURCE 1.50 +MOZ_ALWAYS_INLINE bool 1.51 +bool_toSource_impl(JSContext *cx, CallArgs args) 1.52 +{ 1.53 + HandleValue thisv = args.thisv(); 1.54 + JS_ASSERT(IsBoolean(thisv)); 1.55 + 1.56 + bool b = thisv.isBoolean() ? thisv.toBoolean() : thisv.toObject().as<BooleanObject>().unbox(); 1.57 + 1.58 + StringBuffer sb(cx); 1.59 + if (!sb.append("(new Boolean(") || !BooleanToStringBuffer(b, sb) || !sb.append("))")) 1.60 + return false; 1.61 + 1.62 + JSString *str = sb.finishString(); 1.63 + if (!str) 1.64 + return false; 1.65 + args.rval().setString(str); 1.66 + return true; 1.67 +} 1.68 + 1.69 +static bool 1.70 +bool_toSource(JSContext *cx, unsigned argc, Value *vp) 1.71 +{ 1.72 + CallArgs args = CallArgsFromVp(argc, vp); 1.73 + return CallNonGenericMethod<IsBoolean, bool_toSource_impl>(cx, args); 1.74 +} 1.75 +#endif 1.76 + 1.77 +MOZ_ALWAYS_INLINE bool 1.78 +bool_toString_impl(JSContext *cx, CallArgs args) 1.79 +{ 1.80 + HandleValue thisv = args.thisv(); 1.81 + JS_ASSERT(IsBoolean(thisv)); 1.82 + 1.83 + bool b = thisv.isBoolean() ? thisv.toBoolean() : thisv.toObject().as<BooleanObject>().unbox(); 1.84 + args.rval().setString(js_BooleanToString(cx, b)); 1.85 + return true; 1.86 +} 1.87 + 1.88 +static bool 1.89 +bool_toString(JSContext *cx, unsigned argc, Value *vp) 1.90 +{ 1.91 + CallArgs args = CallArgsFromVp(argc, vp); 1.92 + return CallNonGenericMethod<IsBoolean, bool_toString_impl>(cx, args); 1.93 +} 1.94 + 1.95 +MOZ_ALWAYS_INLINE bool 1.96 +bool_valueOf_impl(JSContext *cx, CallArgs args) 1.97 +{ 1.98 + HandleValue thisv = args.thisv(); 1.99 + JS_ASSERT(IsBoolean(thisv)); 1.100 + 1.101 + bool b = thisv.isBoolean() ? thisv.toBoolean() : thisv.toObject().as<BooleanObject>().unbox(); 1.102 + args.rval().setBoolean(b); 1.103 + return true; 1.104 +} 1.105 + 1.106 +static bool 1.107 +bool_valueOf(JSContext *cx, unsigned argc, Value *vp) 1.108 +{ 1.109 + CallArgs args = CallArgsFromVp(argc, vp); 1.110 + return CallNonGenericMethod<IsBoolean, bool_valueOf_impl>(cx, args); 1.111 +} 1.112 + 1.113 +static const JSFunctionSpec boolean_methods[] = { 1.114 +#if JS_HAS_TOSOURCE 1.115 + JS_FN(js_toSource_str, bool_toSource, 0, 0), 1.116 +#endif 1.117 + JS_FN(js_toString_str, bool_toString, 0, 0), 1.118 + JS_FS_END 1.119 +}; 1.120 + 1.121 +static bool 1.122 +Boolean(JSContext *cx, unsigned argc, Value *vp) 1.123 +{ 1.124 + CallArgs args = CallArgsFromVp(argc, vp); 1.125 + 1.126 + bool b = args.length() != 0 ? JS::ToBoolean(args[0]) : false; 1.127 + 1.128 + if (args.isConstructing()) { 1.129 + JSObject *obj = BooleanObject::create(cx, b); 1.130 + if (!obj) 1.131 + return false; 1.132 + args.rval().setObject(*obj); 1.133 + } else { 1.134 + args.rval().setBoolean(b); 1.135 + } 1.136 + return true; 1.137 +} 1.138 + 1.139 +JSObject * 1.140 +js_InitBooleanClass(JSContext *cx, HandleObject obj) 1.141 +{ 1.142 + JS_ASSERT(obj->isNative()); 1.143 + 1.144 + Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>()); 1.145 + 1.146 + RootedObject booleanProto (cx, global->createBlankPrototype(cx, &BooleanObject::class_)); 1.147 + if (!booleanProto) 1.148 + return nullptr; 1.149 + booleanProto->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT, BooleanValue(false)); 1.150 + 1.151 + RootedFunction ctor(cx, global->createConstructor(cx, Boolean, cx->names().Boolean, 1)); 1.152 + if (!ctor) 1.153 + return nullptr; 1.154 + 1.155 + if (!LinkConstructorAndPrototype(cx, ctor, booleanProto)) 1.156 + return nullptr; 1.157 + 1.158 + if (!DefinePropertiesAndBrand(cx, booleanProto, nullptr, boolean_methods)) 1.159 + return nullptr; 1.160 + 1.161 + Handle<PropertyName*> valueOfName = cx->names().valueOf; 1.162 + RootedFunction 1.163 + valueOf(cx, NewFunction(cx, NullPtr(), bool_valueOf, 0, JSFunction::NATIVE_FUN, 1.164 + global, valueOfName)); 1.165 + if (!valueOf) 1.166 + return nullptr; 1.167 + 1.168 + RootedValue value(cx, ObjectValue(*valueOf)); 1.169 + if (!JSObject::defineProperty(cx, booleanProto, valueOfName, value, 1.170 + JS_PropertyStub, JS_StrictPropertyStub, 0)) 1.171 + { 1.172 + return nullptr; 1.173 + } 1.174 + 1.175 + if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_Boolean, ctor, booleanProto)) 1.176 + return nullptr; 1.177 + 1.178 + return booleanProto; 1.179 +} 1.180 + 1.181 +JSString * 1.182 +js_BooleanToString(ExclusiveContext *cx, bool b) 1.183 +{ 1.184 + return b ? cx->names().true_ : cx->names().false_; 1.185 +} 1.186 + 1.187 +JS_PUBLIC_API(bool) 1.188 +js::ToBooleanSlow(HandleValue v) 1.189 +{ 1.190 + if (v.isString()) 1.191 + return v.toString()->length() != 0; 1.192 + 1.193 + JS_ASSERT(v.isObject()); 1.194 + return !EmulatesUndefined(&v.toObject()); 1.195 +} 1.196 + 1.197 +/* 1.198 + * This slow path is only ever taken for proxies wrapping Boolean objects 1.199 + * The only caller of the fast path, JSON's PreprocessValue, ensures that. 1.200 + */ 1.201 +bool 1.202 +js::BooleanGetPrimitiveValueSlow(HandleObject wrappedBool) 1.203 +{ 1.204 + JSObject *obj = wrappedBool->as<ProxyObject>().target(); 1.205 + JS_ASSERT(obj); 1.206 + return obj->as<BooleanObject>().unbox(); 1.207 +}