1use std::ffi::CStr;
6
7use bitflags::bitflags;
8use js::context::JSContext;
9use js::jsapi::{JSPROP_ENUMERATE, JSPROP_PERMANENT, JSPROP_READONLY};
10use js::rust::{HandleObject, HandleValue};
11
12bitflags! {
13 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
15 pub struct PropertyFlags: u8 {
16 const ENUMERABLE = 1 << 0;
18 const WRITABLE = 1 << 1;
20 const CONFIGURABLE = 1 << 2;
22 }
23}
24
25impl PropertyFlags {
26 pub fn as_jsprop_flags(&self) -> u32 {
28 let mut attrs: u32 = 0;
29 if self.contains(Self::ENUMERABLE) {
30 attrs |= JSPROP_ENUMERATE as u32;
31 }
32 if !self.contains(Self::CONFIGURABLE) {
33 attrs |= JSPROP_PERMANENT as u32;
34 }
35 if !self.contains(Self::WRITABLE) {
36 attrs |= JSPROP_READONLY as u32;
37 }
38 attrs
39 }
40}
41
42#[allow(non_snake_case)]
44#[inline]
45pub fn JS_DefineProperty(
46 cx: &mut JSContext,
47 obj: HandleObject,
48 name: &CStr,
49 value: HandleValue,
50 flags: PropertyFlags,
51) -> bool {
52 let attrs = flags.as_jsprop_flags();
53 unsafe { js::rust::wrappers2::JS_DefineProperty(cx, obj, name.as_ptr(), value, attrs) }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn test_property_flags_mapping() {
62 let all = PropertyFlags::ENUMERABLE | PropertyFlags::WRITABLE | PropertyFlags::CONFIGURABLE;
64 assert_eq!(all.as_jsprop_flags(), JSPROP_ENUMERATE as u32);
65
66 let constant = PropertyFlags::ENUMERABLE;
69 assert_eq!(
70 constant.as_jsprop_flags(),
71 (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) as u32
72 );
73
74 let empty = PropertyFlags::empty();
77 assert_eq!(
78 empty.as_jsprop_flags(),
79 (JSPROP_READONLY | JSPROP_PERMANENT) as u32
80 );
81
82 let method = PropertyFlags::WRITABLE | PropertyFlags::CONFIGURABLE;
85 assert_eq!(method.as_jsprop_flags(), 0);
86 }
87}