boa/builtins/boolean/
mod.rs

1//! This module implements the global `Boolean` object.
2//!
3//! The `Boolean` object is an object wrapper for a boolean value.
4//!
5//! More information:
6//!  - [ECMAScript reference][spec]
7//!  - [MDN documentation][mdn]
8//!
9//! [spec]: https://tc39.es/ecma262/#sec-boolean-object
10//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean
11
12#[cfg(test)]
13mod tests;
14
15use crate::{
16    builtins::BuiltIn,
17    context::StandardObjects,
18    object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
19    property::Attribute,
20    BoaProfiler, Context, JsResult, JsValue,
21};
22
23/// Boolean implementation.
24#[derive(Debug, Clone, Copy)]
25pub(crate) struct Boolean;
26
27impl BuiltIn for Boolean {
28    /// The name of the object.
29    const NAME: &'static str = "Boolean";
30
31    fn attribute() -> Attribute {
32        Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
33    }
34
35    fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
36        let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
37
38        let boolean_object = ConstructorBuilder::with_standard_object(
39            context,
40            Self::constructor,
41            context.standard_objects().boolean_object().clone(),
42        )
43        .name(Self::NAME)
44        .length(Self::LENGTH)
45        .method(Self::to_string, "toString", 0)
46        .method(Self::value_of, "valueOf", 0)
47        .build();
48
49        (Self::NAME, boolean_object.into(), Self::attribute())
50    }
51}
52
53impl Boolean {
54    /// The amount of arguments this function object takes.
55    pub(crate) const LENGTH: usize = 1;
56
57    /// `[[Construct]]` Create a new boolean object
58    ///
59    /// `[[Call]]` Creates a new boolean primitive
60    pub(crate) fn constructor(
61        new_target: &JsValue,
62        args: &[JsValue],
63        context: &mut Context,
64    ) -> JsResult<JsValue> {
65        // Get the argument, if any
66        let data = args.get(0).map(|x| x.to_boolean()).unwrap_or(false);
67        if new_target.is_undefined() {
68            return Ok(JsValue::new(data));
69        }
70        let prototype =
71            get_prototype_from_constructor(new_target, StandardObjects::boolean_object, context)?;
72        let boolean = JsValue::new_object(context);
73
74        boolean
75            .as_object()
76            .expect("this should be an object")
77            .set_prototype_instance(prototype.into());
78        boolean.set_data(ObjectData::boolean(data));
79
80        Ok(boolean)
81    }
82
83    /// An Utility function used to get the internal `[[BooleanData]]`.
84    ///
85    /// More information:
86    ///  - [ECMAScript reference][spec]
87    ///
88    /// [spec]: https://tc39.es/ecma262/#sec-thisbooleanvalue
89    fn this_boolean_value(value: &JsValue, context: &mut Context) -> JsResult<bool> {
90        match value {
91            JsValue::Boolean(boolean) => return Ok(*boolean),
92            JsValue::Object(ref object) => {
93                let object = object.borrow();
94                if let Some(boolean) = object.as_boolean() {
95                    return Ok(boolean);
96                }
97            }
98            _ => {}
99        }
100
101        Err(context.construct_type_error("'this' is not a boolean"))
102    }
103
104    /// The `toString()` method returns a string representing the specified `Boolean` object.
105    ///
106    /// More information:
107    ///  - [ECMAScript reference][spec]
108    ///  - [MDN documentation][mdn]
109    ///
110    /// [spec]: https://tc39.es/ecma262/#sec-boolean-object
111    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/toString
112    #[allow(clippy::wrong_self_convention)]
113    pub(crate) fn to_string(
114        this: &JsValue,
115        _: &[JsValue],
116        context: &mut Context,
117    ) -> JsResult<JsValue> {
118        let boolean = Self::this_boolean_value(this, context)?;
119        Ok(JsValue::new(boolean.to_string()))
120    }
121
122    /// The valueOf() method returns the primitive value of a `Boolean` object.
123    ///
124    /// More information:
125    ///  - [ECMAScript reference][spec]
126    /// - [MDN documentation][mdn]
127    ///
128    /// [spec]: https://tc39.es/ecma262/#sec-boolean.prototype.valueof
129    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/valueOf
130    #[inline]
131    pub(crate) fn value_of(
132        this: &JsValue,
133        _: &[JsValue],
134        context: &mut Context,
135    ) -> JsResult<JsValue> {
136        Ok(JsValue::new(Self::this_boolean_value(this, context)?))
137    }
138}