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}