Skip to main content

boa_engine/property/attribute/
mod.rs

1//! This module implements the `Attribute` struct which contains the attributes for property descriptors.
2
3use bitflags::bitflags;
4
5#[cfg(test)]
6mod tests;
7
8bitflags! {
9    /// This struct contains the property flags as described in the ECMAScript specification.
10    ///
11    /// It contains the following flags:
12    ///  - `[[Writable]]` (`WRITABLE`) - If `false`, attempts by ECMAScript code to change the property's
13    /// `[[Value]]` attribute using `[[Set]]` will not succeed.
14    ///  - `[[Enumerable]]` (`ENUMERABLE`) - If the property will be enumerated by a for-in enumeration.
15    ///  - `[[Configurable]]` (`CONFIGURABLE`) - If `false`, attempts to delete the property,
16    /// change the property to be an `accessor property`, or change its attributes (other than `[[Value]]`,
17    /// or changing `[[Writable]]` to `false`) will fail.
18    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
19    pub struct Attribute: u8 {
20        /// The `Writable` attribute decides whether the value associated with the property can be changed or not, from its initial value.
21        const WRITABLE = 0b0000_0001;
22
23        /// If the property can be enumerated by a `for-in` loop.
24        const ENUMERABLE = 0b0000_0010;
25
26        /// If the property descriptor can be changed later.
27        const CONFIGURABLE = 0b0000_0100;
28
29        /// The property is not writable.
30        const READONLY = 0b0000_0000;
31
32        /// The property can not be enumerated in a `for-in` loop.
33        const NON_ENUMERABLE = 0b0000_0000;
34
35        /// The property descriptor cannot be changed.
36        const PERMANENT = 0b0000_0000;
37    }
38}
39
40impl Attribute {
41    /// Clear all flags.
42    #[inline]
43    pub fn clear(&mut self) {
44        *self.0.bits_mut() = 0;
45    }
46
47    /// Sets the `writable` flag.
48    #[inline]
49    pub fn set_writable(&mut self, value: bool) {
50        if value {
51            *self |= Self::WRITABLE;
52        } else {
53            *self |= *self & !Self::WRITABLE;
54        }
55    }
56
57    /// Gets the `writable` flag.
58    #[inline]
59    #[must_use]
60    pub const fn writable(self) -> bool {
61        self.contains(Self::WRITABLE)
62    }
63
64    /// Sets the `enumerable` flag.
65    #[inline]
66    pub fn set_enumerable(&mut self, value: bool) {
67        if value {
68            *self |= Self::ENUMERABLE;
69        } else {
70            *self |= *self & !Self::ENUMERABLE;
71        }
72    }
73
74    /// Gets the `enumerable` flag.
75    #[inline]
76    #[must_use]
77    pub const fn enumerable(self) -> bool {
78        self.contains(Self::ENUMERABLE)
79    }
80
81    /// Sets the `configurable` flag.
82    #[inline]
83    pub fn set_configurable(&mut self, value: bool) {
84        if value {
85            *self |= Self::CONFIGURABLE;
86        } else {
87            *self |= *self & !Self::CONFIGURABLE;
88        }
89    }
90
91    /// Gets the `configurable` flag.
92    #[inline]
93    #[must_use]
94    pub const fn configurable(self) -> bool {
95        self.contains(Self::CONFIGURABLE)
96    }
97}
98
99impl Default for Attribute {
100    /// Returns the default flags according to the [ECMAScript specification][spec].
101    ///
102    /// [spec]: https://tc39.es/ecma262/#table-default-attribute-values
103    fn default() -> Self {
104        Self::READONLY | Self::NON_ENUMERABLE | Self::PERMANENT
105    }
106}