rquickjs_core/value/proxy/
handler.rs1use alloc::string::String as StdString;
2
3use crate::{atom::PredefinedAtom, Ctx, Error, FromJs, Function, IntoJs, Object, Result, Value};
4
5#[derive(Debug, PartialEq, Clone, Hash, Eq)]
7pub struct ProxyTarget<'js>(pub Object<'js>);
8
9impl<'js> FromJs<'js> for ProxyTarget<'js> {
10 fn from_js(_: &Ctx<'js>, value: Value<'js>) -> Result<Self> {
11 Ok(Self(Object::from_value(value)?))
12 }
13}
14
15#[derive(Debug, PartialEq, Clone, Hash, Eq)]
17pub struct ProxyProperty<'js>(pub Value<'js>);
18
19impl<'js> ProxyProperty<'js> {
20 pub fn is_symbol(&self) -> bool {
21 self.0.is_symbol()
22 }
23
24 pub fn is_string(&self) -> bool {
25 self.0.is_string()
26 }
27
28 pub fn to_string(&self) -> Result<StdString> {
29 if let Some(string) = self.0.as_string() {
30 string.to_string()
31 } else if let Some(symbol) = self.0.as_symbol() {
32 symbol.as_atom().to_string()
33 } else {
34 Err(Error::Unknown)
35 }
36 }
37}
38
39impl<'js> FromJs<'js> for ProxyProperty<'js> {
40 fn from_js(_: &Ctx<'js>, value: Value<'js>) -> Result<Self> {
41 Ok(Self(value))
42 }
43}
44
45#[derive(Debug, PartialEq, Clone, Hash, Eq)]
47pub struct ProxyReceiver<'js>(pub Value<'js>);
48
49impl<'js> FromJs<'js> for ProxyReceiver<'js> {
50 fn from_js(_: &Ctx<'js>, value: Value<'js>) -> Result<Self> {
51 Ok(Self(value))
52 }
53}
54
55#[derive(Debug, PartialEq, Clone, Hash, Eq)]
57#[repr(transparent)]
58pub struct ProxyHandler<'js>(pub(crate) Object<'js>);
59
60impl<'js> ProxyHandler<'js> {
61 pub fn new(ctx: Ctx<'js>) -> Result<Self> {
63 Ok(Self(Object::new(ctx)?))
64 }
65
66 pub fn from_object(object: Object<'js>) -> Result<Self> {
68 Ok(Self(object))
69 }
70
71 pub fn set_getter<F, V>(&self, get: F) -> Result<()>
73 where
74 F: Fn(ProxyTarget<'js>, ProxyProperty<'js>, ProxyReceiver<'js>) -> Result<V> + 'js,
75 V: IntoJs<'js> + 'js,
76 {
77 self.0.set(
78 PredefinedAtom::Getter,
79 Function::new(self.0.ctx().clone(), get)?,
80 )?;
81 Ok(())
82 }
83
84 pub fn with_getter<F, V>(self, get: F) -> Result<Self>
86 where
87 F: Fn(ProxyTarget<'js>, ProxyProperty<'js>, ProxyReceiver<'js>) -> Result<V> + 'js,
88 V: IntoJs<'js> + 'js,
89 {
90 self.set_getter(get)?;
91 Ok(self)
92 }
93
94 pub fn set_setter<F>(&self, set: F) -> Result<()>
96 where
97 F: Fn(ProxyTarget<'js>, ProxyProperty<'js>, Value<'js>, ProxyReceiver<'js>) -> Result<bool>
98 + 'js,
99 {
100 self.0.set(
101 PredefinedAtom::Setter,
102 Function::new(self.0.ctx().clone(), set)?,
103 )?;
104 Ok(())
105 }
106
107 pub fn with_setter<F>(self, set: F) -> Result<Self>
109 where
110 F: Fn(ProxyTarget<'js>, ProxyProperty<'js>, Value<'js>, ProxyReceiver<'js>) -> Result<bool>
111 + 'js,
112 {
113 self.set_setter(set)?;
114 Ok(self)
115 }
116
117 pub fn set_has<F>(&self, has: F) -> Result<()>
119 where
120 F: Fn(ProxyTarget<'js>, ProxyProperty<'js>) -> Result<bool> + 'js,
121 {
122 self.0.set(
123 PredefinedAtom::Has,
124 Function::new(self.0.ctx().clone(), has)?,
125 )?;
126 Ok(())
127 }
128
129 pub fn with_has<F>(self, has: F) -> Result<Self>
131 where
132 F: Fn(ProxyTarget<'js>, ProxyProperty<'js>) -> Result<bool> + 'js,
133 {
134 self.set_has(has)?;
135 Ok(self)
136 }
137
138 pub fn set_delete<F>(&self, delete: F) -> Result<()>
140 where
141 F: Fn(ProxyTarget<'js>, ProxyProperty<'js>) -> Result<bool> + 'js,
142 {
143 self.0.set(
144 PredefinedAtom::DeleteProperty,
145 Function::new(self.0.ctx().clone(), delete)?,
146 )?;
147 Ok(())
148 }
149
150 pub fn with_delete<F>(self, delete: F) -> Result<Self>
152 where
153 F: Fn(ProxyTarget<'js>, ProxyProperty<'js>) -> Result<bool> + 'js,
154 {
155 self.set_delete(delete)?;
156 Ok(self)
157 }
158}
159
160impl<'js> IntoJs<'js> for ProxyHandler<'js> {
161 fn into_js(self, ctx: &Ctx<'js>) -> Result<Value<'js>> {
162 self.0.into_js(ctx)
163 }
164}