1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
//! Boa's implementation of ECMAScript's global `Boolean` object.
//!
//! The `Boolean` object is an object wrapper for a boolean value.
//!
//! More information:
//! - [ECMAScript reference][spec]
//! - [MDN documentation][mdn]
//!
//! [spec]: https://tc39.es/ecma262/#sec-boolean-object
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean
#[cfg(test)]
mod tests;
use crate::{
builtins::BuiltInObject,
context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
error::JsNativeError,
object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
realm::Realm,
Context, JsResult, JsValue,
};
use boa_profiler::Profiler;
use super::{BuiltInBuilder, BuiltInConstructor, IntrinsicObject};
/// Boolean implementation.
#[derive(Debug, Clone, Copy)]
pub(crate) struct Boolean;
impl IntrinsicObject for Boolean {
fn init(realm: &Realm) {
let _timer = Profiler::global().start_event(Self::NAME, "init");
BuiltInBuilder::from_standard_constructor::<Self>(realm)
.method(Self::to_string, "toString", 0)
.method(Self::value_of, "valueOf", 0)
.build();
}
fn get(intrinsics: &Intrinsics) -> JsObject {
Self::STANDARD_CONSTRUCTOR(intrinsics.constructors()).constructor()
}
}
impl BuiltInObject for Boolean {
const NAME: &'static str = "Boolean";
}
impl BuiltInConstructor for Boolean {
const LENGTH: usize = 1;
const STANDARD_CONSTRUCTOR: fn(&StandardConstructors) -> &StandardConstructor =
StandardConstructors::boolean;
/// `[[Construct]]` Create a new boolean object
///
/// `[[Call]]` Creates a new boolean primitive
fn constructor(
new_target: &JsValue,
args: &[JsValue],
context: &mut Context<'_>,
) -> JsResult<JsValue> {
// Get the argument, if any
let data = args.get(0).map_or(false, JsValue::to_boolean);
if new_target.is_undefined() {
return Ok(JsValue::new(data));
}
let prototype =
get_prototype_from_constructor(new_target, StandardConstructors::boolean, context)?;
let boolean = JsObject::from_proto_and_data_with_shared_shape(
context.root_shape(),
prototype,
ObjectData::boolean(data),
);
Ok(boolean.into())
}
}
impl Boolean {
/// An Utility function used to get the internal `[[BooleanData]]`.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-thisbooleanvalue
fn this_boolean_value(value: &JsValue) -> JsResult<bool> {
value
.as_boolean()
.or_else(|| value.as_object().and_then(|obj| obj.borrow().as_boolean()))
.ok_or_else(|| {
JsNativeError::typ()
.with_message("'this' is not a boolean")
.into()
})
}
/// The `toString()` method returns a string representing the specified `Boolean` object.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-boolean-object
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(
this: &JsValue,
_: &[JsValue],
_: &mut Context<'_>,
) -> JsResult<JsValue> {
let boolean = Self::this_boolean_value(this)?;
Ok(JsValue::new(boolean.to_string()))
}
/// The valueOf() method returns the primitive value of a `Boolean` object.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-boolean.prototype.valueof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/valueOf
pub(crate) fn value_of(
this: &JsValue,
_: &[JsValue],
_: &mut Context<'_>,
) -> JsResult<JsValue> {
Ok(JsValue::new(Self::this_boolean_value(this)?))
}
}