js/src/jsbool.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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 }

mercurial