Skip to main content

boa_engine/builtins/boolean/
mod.rs

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