js/src/jsbool.cpp

changeset 0
6474c204b198
     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 +}

mercurial