1use std::ffi::CStr;
6use std::os::raw::c_uint;
7use std::ptr;
8
9use bitflags::bitflags;
10use js::context::JSContext;
11use js::jsapi::{
12 ExceptionStackBehavior, JSClass, JSObject, JSPROP_ENUMERATE, JSPROP_PERMANENT, JSPROP_READONLY,
13 MutableHandleIdVector, PropertyDescriptor, jsid,
14};
15use js::rust::{
16 HandleId, HandleObject, HandleValue, MutableHandle, MutableHandleObject, MutableHandleValue,
17};
18
19bitflags! {
20 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
22 pub struct PropertyFlags: u8 {
23 const ENUMERABLE = 1 << 0;
25 const WRITABLE = 1 << 1;
27 const CONFIGURABLE = 1 << 2;
29 }
30}
31
32impl PropertyFlags {
33 pub fn as_jsprop_flags(&self) -> u32 {
35 let mut attrs: u32 = 0;
36 if self.contains(Self::ENUMERABLE) {
37 attrs |= JSPROP_ENUMERATE as u32;
38 }
39 if !self.contains(Self::CONFIGURABLE) {
40 attrs |= JSPROP_PERMANENT as u32;
41 }
42 if !self.contains(Self::WRITABLE) {
43 attrs |= JSPROP_READONLY as u32;
44 }
45 attrs
46 }
47}
48
49#[allow(non_snake_case)]
51#[inline]
52pub fn JS_DefineProperty(
53 cx: &mut JSContext,
54 obj: HandleObject,
55 name: &CStr,
56 value: HandleValue,
57 flags: PropertyFlags,
58) -> bool {
59 let attrs = flags.as_jsprop_flags();
60 unsafe { js::rust::wrappers2::JS_DefineProperty(cx, obj, name.as_ptr(), value, attrs) }
61}
62
63#[allow(non_snake_case)]
65#[inline]
66pub fn JS_SetPendingException(
67 cx: &mut JSContext,
68 value: HandleValue,
69 behavior: ExceptionStackBehavior,
70) {
71 unsafe { js::rust::wrappers2::JS_SetPendingException(cx, value, behavior) }
72}
73
74#[allow(non_snake_case)]
76#[inline]
77pub fn JS_IsExceptionPending(cx: &mut JSContext) -> bool {
78 unsafe { js::rust::wrappers2::JS_IsExceptionPending(cx) }
79}
80
81#[allow(non_snake_case)]
83#[inline]
84pub fn JS_IdToValue(cx: &mut JSContext, id: jsid, vp: MutableHandleValue) -> bool {
85 unsafe { js::rust::wrappers2::JS_IdToValue(cx, id, vp) }
86}
87
88#[allow(non_snake_case)]
90#[inline]
91pub fn JS_GetPropertyById(
92 cx: &mut JSContext,
93 obj: HandleObject,
94 id: HandleId,
95 vp: MutableHandleValue,
96) -> bool {
97 unsafe { js::rust::wrappers2::JS_GetPropertyById(cx, obj, id, vp) }
98}
99
100#[allow(non_snake_case)]
103#[inline]
104pub fn JS_NewObject(cx: &mut JSContext, clasp: Option<&'static JSClass>) -> *mut JSObject {
105 let clasp = clasp.map_or(ptr::null(), |clasp| clasp as *const JSClass);
106 unsafe { js::rust::wrappers2::JS_NewObject(cx, clasp) }
107}
108
109#[allow(non_snake_case)]
112#[inline]
113pub fn JS_NewObjectWithGivenProto(
114 cx: &mut JSContext,
115 clasp: Option<&'static JSClass>,
116 proto: HandleObject,
117) -> *mut JSObject {
118 let clasp = clasp.map_or(ptr::null(), |clasp| clasp as *const JSClass);
119 unsafe { js::rust::wrappers2::JS_NewObjectWithGivenProto(cx, clasp, proto) }
120}
121
122#[allow(non_snake_case)]
124#[inline]
125pub fn JS_GetProperty(
126 cx: &mut JSContext,
127 obj: HandleObject,
128 name: &CStr,
129 vp: MutableHandleValue,
130) -> bool {
131 unsafe { js::rust::wrappers2::JS_GetProperty(cx, obj, name.as_ptr(), vp) }
132}
133
134#[allow(non_snake_case)]
136#[inline]
137pub fn JS_GetPrototype(cx: &mut JSContext, obj: HandleObject, result: MutableHandleObject) -> bool {
138 unsafe { js::rust::wrappers2::JS_GetPrototype(cx, obj, result) }
139}
140
141#[allow(non_snake_case)]
143#[inline]
144pub fn GetPropertyKeys(
145 cx: &mut JSContext,
146 obj: HandleObject,
147 flags: c_uint,
148 props: MutableHandleIdVector,
149) -> bool {
150 unsafe { js::rust::wrappers2::GetPropertyKeys(cx, obj, flags, props) }
151}
152
153#[allow(non_snake_case)]
155#[inline]
156pub fn JS_GetOwnPropertyDescriptorById(
157 cx: &mut JSContext,
158 obj: HandleObject,
159 id: HandleId,
160 desc: MutableHandle<PropertyDescriptor>,
161 is_none: &mut bool,
162) -> bool {
163 unsafe { js::rust::wrappers2::JS_GetOwnPropertyDescriptorById(cx, obj, id, desc, is_none) }
164}
165
166#[cfg(test)]
167mod tests {
168 use super::*;
169
170 #[test]
171 fn test_property_flags_mapping() {
172 let all = PropertyFlags::ENUMERABLE | PropertyFlags::WRITABLE | PropertyFlags::CONFIGURABLE;
174 assert_eq!(all.as_jsprop_flags(), JSPROP_ENUMERATE as u32);
175
176 let constant = PropertyFlags::ENUMERABLE;
179 assert_eq!(
180 constant.as_jsprop_flags(),
181 (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) as u32
182 );
183
184 let empty = PropertyFlags::empty();
187 assert_eq!(
188 empty.as_jsprop_flags(),
189 (JSPROP_READONLY | JSPROP_PERMANENT) as u32
190 );
191
192 let method = PropertyFlags::WRITABLE | PropertyFlags::CONFIGURABLE;
195 assert_eq!(method.as_jsprop_flags(), 0);
196 }
197}