From 2aa4a82499d4becd2284cdb482213d541b8804dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 16:29:10 +0200 Subject: Adding upstream version 86.0.1. Signed-off-by: Daniel Baumann --- js/src/builtin/Boolean.cpp | 174 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 js/src/builtin/Boolean.cpp (limited to 'js/src/builtin/Boolean.cpp') diff --git a/js/src/builtin/Boolean.cpp b/js/src/builtin/Boolean.cpp new file mode 100644 index 0000000000..4703161396 --- /dev/null +++ b/js/src/builtin/Boolean.cpp @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * JS boolean implementation. + */ + +#include "builtin/Boolean-inl.h" + +#include "jsapi.h" +#include "jstypes.h" + +#include "jit/InlinableNatives.h" +#include "js/PropertySpec.h" +#include "util/StringBuffer.h" +#include "vm/BigIntType.h" +#include "vm/GlobalObject.h" +#include "vm/JSAtom.h" +#include "vm/JSContext.h" +#include "vm/JSObject.h" +#include "vm/ProxyObject.h" + +#include "vm/BooleanObject-inl.h" + +using namespace js; + +const JSClass BooleanObject::class_ = { + "Boolean", + JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean), + JS_NULL_CLASS_OPS, &BooleanObject::classSpec_}; + +MOZ_ALWAYS_INLINE bool IsBoolean(HandleValue v) { + return v.isBoolean() || (v.isObject() && v.toObject().is()); +} + +// ES2020 draft rev ecb4178012d6b4d9abc13fcbd45f5c6394b832ce +// 19.4.3 Properties of the Boolean Prototype Object, thisBooleanValue. +static MOZ_ALWAYS_INLINE bool ThisBooleanValue(HandleValue val) { + // Step 3, the error case, is handled by CallNonGenericMethod. + MOZ_ASSERT(IsBoolean(val)); + + // Step 1. + if (val.isBoolean()) { + return val.toBoolean(); + } + + // Step 2. + return val.toObject().as().unbox(); +} + +MOZ_ALWAYS_INLINE bool bool_toSource_impl(JSContext* cx, const CallArgs& args) { + bool b = ThisBooleanValue(args.thisv()); + + JSStringBuilder sb(cx); + if (!sb.append("(new Boolean(") || !BooleanToStringBuffer(b, sb) || + !sb.append("))")) { + return false; + } + + JSString* str = sb.finishString(); + if (!str) { + return false; + } + args.rval().setString(str); + return true; +} + +static bool bool_toSource(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + return CallNonGenericMethod(cx, args); +} + +// ES2020 draft rev ecb4178012d6b4d9abc13fcbd45f5c6394b832ce +// 19.3.3.2 Boolean.prototype.toString ( ) +MOZ_ALWAYS_INLINE bool bool_toString_impl(JSContext* cx, const CallArgs& args) { + // Step 1. + bool b = ThisBooleanValue(args.thisv()); + + // Step 2. + args.rval().setString(BooleanToString(cx, b)); + return true; +} + +static bool bool_toString(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + return CallNonGenericMethod(cx, args); +} + +// ES2020 draft rev ecb4178012d6b4d9abc13fcbd45f5c6394b832ce +// 19.3.3.3 Boolean.prototype.valueOf ( ) +MOZ_ALWAYS_INLINE bool bool_valueOf_impl(JSContext* cx, const CallArgs& args) { + // Step 1. + args.rval().setBoolean(ThisBooleanValue(args.thisv())); + return true; +} + +static bool bool_valueOf(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + return CallNonGenericMethod(cx, args); +} + +static const JSFunctionSpec boolean_methods[] = { + JS_FN(js_toSource_str, bool_toSource, 0, 0), + JS_FN(js_toString_str, bool_toString, 0, 0), + JS_FN(js_valueOf_str, bool_valueOf, 0, 0), JS_FS_END}; + +// ES2020 draft rev ecb4178012d6b4d9abc13fcbd45f5c6394b832ce +// 19.3.1.1 Boolean ( value ) +static bool Boolean(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + + // Step 1. + bool b = args.length() != 0 ? JS::ToBoolean(args[0]) : false; + + if (args.isConstructing()) { + // Steps 3-4. + RootedObject proto(cx); + if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_Boolean, + &proto)) { + return false; + } + + JSObject* obj = BooleanObject::create(cx, b, proto); + if (!obj) { + return false; + } + + // Step 5. + args.rval().setObject(*obj); + } else { + // Step 2. + args.rval().setBoolean(b); + } + return true; +} + +JSObject* BooleanObject::createPrototype(JSContext* cx, JSProtoKey key) { + BooleanObject* booleanProto = + GlobalObject::createBlankPrototype(cx, cx->global()); + if (!booleanProto) { + return nullptr; + } + booleanProto->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT, + BooleanValue(false)); + return booleanProto; +} + +const ClassSpec BooleanObject::classSpec_ = { + GenericCreateConstructor, + BooleanObject::createPrototype, + nullptr, + nullptr, + boolean_methods, + nullptr}; + +PropertyName* js::BooleanToString(JSContext* cx, bool b) { + return b ? cx->names().true_ : cx->names().false_; +} + +JS_PUBLIC_API bool js::ToBooleanSlow(HandleValue v) { + if (v.isString()) { + return v.toString()->length() != 0; + } + if (v.isBigInt()) { + return !v.toBigInt()->isZero(); + } + + MOZ_ASSERT(v.isObject()); + return !EmulatesUndefined(&v.toObject()); +} -- cgit v1.2.3