boa/property/attribute/
mod.rs

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