1use crate::{CheckSyntaxMode, CheckSyntaxResult, Exception, Value, VirtualMachine};
7use glib::{prelude::*, translate::*};
8use std::{boxed::Box as Box_, fmt, ptr};
9
10glib::wrapper! {
11 #[doc(alias = "JSCContext")]
12 pub struct Context(Object<ffi::JSCContext, ffi::JSCContextClass>);
13
14 match fn {
15 type_ => || ffi::jsc_context_get_type(),
16 }
17}
18
19impl Context {
20 pub const NONE: Option<&'static Context> = None;
21
22 #[doc(alias = "jsc_context_new")]
23 pub fn new() -> Context {
24 unsafe { from_glib_full(ffi::jsc_context_new()) }
25 }
26
27 #[doc(alias = "jsc_context_new_with_virtual_machine")]
28 #[doc(alias = "new_with_virtual_machine")]
29 pub fn with_virtual_machine(vm: &impl IsA<VirtualMachine>) -> Context {
30 unsafe {
31 from_glib_full(ffi::jsc_context_new_with_virtual_machine(
32 vm.as_ref().to_glib_none().0,
33 ))
34 }
35 }
36
37 pub fn builder() -> ContextBuilder {
42 ContextBuilder::new()
43 }
44
45 #[doc(alias = "jsc_context_get_current")]
46 #[doc(alias = "get_current")]
47 pub fn current() -> Option<Context> {
48 unsafe { from_glib_none(ffi::jsc_context_get_current()) }
49 }
50}
51
52impl Default for Context {
53 fn default() -> Self {
54 Self::new()
55 }
56}
57
58#[must_use = "The builder must be built to be used"]
63pub struct ContextBuilder {
64 builder: glib::object::ObjectBuilder<'static, Context>,
65}
66
67impl ContextBuilder {
68 fn new() -> Self {
69 Self {
70 builder: glib::object::Object::builder(),
71 }
72 }
73
74 pub fn virtual_machine(self, virtual_machine: &impl IsA<VirtualMachine>) -> Self {
75 Self {
76 builder: self
77 .builder
78 .property("virtual-machine", virtual_machine.clone().upcast()),
79 }
80 }
81
82 #[must_use = "Building the object from the builder is usually expensive and is not expected to have side effects"]
85 pub fn build(self) -> Context {
86 self.builder.build()
87 }
88}
89
90pub trait ContextExt: 'static {
91 #[doc(alias = "jsc_context_check_syntax")]
92 fn check_syntax(
93 &self,
94 code: &str,
95 mode: CheckSyntaxMode,
96 uri: &str,
97 line_number: u32,
98 ) -> (CheckSyntaxResult, Exception);
99
100 #[doc(alias = "jsc_context_clear_exception")]
101 fn clear_exception(&self);
102
103 #[doc(alias = "jsc_context_evaluate")]
104 fn evaluate(&self, code: &str) -> Option<Value>;
105
106 #[doc(alias = "jsc_context_evaluate_with_source_uri")]
110 fn evaluate_with_source_uri(&self, code: &str, uri: &str, line_number: u32) -> Option<Value>;
111
112 #[doc(alias = "jsc_context_get_exception")]
113 #[doc(alias = "get_exception")]
114 fn exception(&self) -> Option<Exception>;
115
116 #[doc(alias = "jsc_context_get_global_object")]
117 #[doc(alias = "get_global_object")]
118 fn global_object(&self) -> Option<Value>;
119
120 #[doc(alias = "jsc_context_get_value")]
121 #[doc(alias = "get_value")]
122 fn value(&self, name: &str) -> Option<Value>;
123
124 #[doc(alias = "jsc_context_get_virtual_machine")]
125 #[doc(alias = "get_virtual_machine")]
126 fn virtual_machine(&self) -> Option<VirtualMachine>;
127
128 #[doc(alias = "jsc_context_pop_exception_handler")]
129 fn pop_exception_handler(&self);
130
131 #[doc(alias = "jsc_context_push_exception_handler")]
132 fn push_exception_handler<P: Fn(&Context, &Exception) + 'static>(&self, handler: P);
133
134 #[doc(alias = "jsc_context_set_value")]
138 fn set_value(&self, name: &str, value: &impl IsA<Value>);
139
140 #[doc(alias = "jsc_context_throw")]
141 fn throw(&self, error_message: &str);
142
143 #[doc(alias = "jsc_context_throw_exception")]
144 fn throw_exception(&self, exception: &impl IsA<Exception>);
145
146 #[doc(alias = "jsc_context_throw_with_name")]
150 fn throw_with_name(&self, error_name: &str, error_message: &str);
151
152 }
155
156impl<O: IsA<Context>> ContextExt for O {
157 fn check_syntax(
158 &self,
159 code: &str,
160 mode: CheckSyntaxMode,
161 uri: &str,
162 line_number: u32,
163 ) -> (CheckSyntaxResult, Exception) {
164 let length = code.len() as _;
165 unsafe {
166 let mut exception = ptr::null_mut();
167 let ret = from_glib(ffi::jsc_context_check_syntax(
168 self.as_ref().to_glib_none().0,
169 code.to_glib_none().0,
170 length,
171 mode.into_glib(),
172 uri.to_glib_none().0,
173 line_number,
174 &mut exception,
175 ));
176 (ret, from_glib_full(exception))
177 }
178 }
179
180 fn clear_exception(&self) {
181 unsafe {
182 ffi::jsc_context_clear_exception(self.as_ref().to_glib_none().0);
183 }
184 }
185
186 fn evaluate(&self, code: &str) -> Option<Value> {
187 let length = code.len() as _;
188 unsafe {
189 from_glib_full(ffi::jsc_context_evaluate(
190 self.as_ref().to_glib_none().0,
191 code.to_glib_none().0,
192 length,
193 ))
194 }
195 }
196
197 fn evaluate_with_source_uri(&self, code: &str, uri: &str, line_number: u32) -> Option<Value> {
202 let length = code.len() as _;
203 unsafe {
204 from_glib_full(ffi::jsc_context_evaluate_with_source_uri(
205 self.as_ref().to_glib_none().0,
206 code.to_glib_none().0,
207 length,
208 uri.to_glib_none().0,
209 line_number,
210 ))
211 }
212 }
213
214 fn exception(&self) -> Option<Exception> {
215 unsafe {
216 from_glib_none(ffi::jsc_context_get_exception(
217 self.as_ref().to_glib_none().0,
218 ))
219 }
220 }
221
222 fn global_object(&self) -> Option<Value> {
223 unsafe {
224 from_glib_full(ffi::jsc_context_get_global_object(
225 self.as_ref().to_glib_none().0,
226 ))
227 }
228 }
229
230 fn value(&self, name: &str) -> Option<Value> {
231 unsafe {
232 from_glib_full(ffi::jsc_context_get_value(
233 self.as_ref().to_glib_none().0,
234 name.to_glib_none().0,
235 ))
236 }
237 }
238
239 fn virtual_machine(&self) -> Option<VirtualMachine> {
240 unsafe {
241 from_glib_none(ffi::jsc_context_get_virtual_machine(
242 self.as_ref().to_glib_none().0,
243 ))
244 }
245 }
246
247 fn pop_exception_handler(&self) {
248 unsafe {
249 ffi::jsc_context_pop_exception_handler(self.as_ref().to_glib_none().0);
250 }
251 }
252
253 fn push_exception_handler<P: Fn(&Context, &Exception) + 'static>(&self, handler: P) {
254 let handler_data: Box_<P> = Box_::new(handler);
255 unsafe extern "C" fn handler_func<P: Fn(&Context, &Exception) + 'static>(
256 context: *mut ffi::JSCContext,
257 exception: *mut ffi::JSCException,
258 user_data: glib::ffi::gpointer,
259 ) {
260 let context = from_glib_borrow(context);
261 let exception = from_glib_borrow(exception);
262 let callback: &P = &*(user_data as *mut _);
263 (*callback)(&context, &exception)
264 }
265 let handler = Some(handler_func::<P> as _);
266 unsafe extern "C" fn destroy_notify_func<P: Fn(&Context, &Exception) + 'static>(
267 data: glib::ffi::gpointer,
268 ) {
269 let _callback: Box_<P> = Box_::from_raw(data as *mut _);
270 }
271 let destroy_call3 = Some(destroy_notify_func::<P> as _);
272 let super_callback0: Box_<P> = handler_data;
273 unsafe {
274 ffi::jsc_context_push_exception_handler(
275 self.as_ref().to_glib_none().0,
276 handler,
277 Box_::into_raw(super_callback0) as *mut _,
278 destroy_call3,
279 );
280 }
281 }
282
283 fn set_value(&self, name: &str, value: &impl IsA<Value>) {
288 unsafe {
289 ffi::jsc_context_set_value(
290 self.as_ref().to_glib_none().0,
291 name.to_glib_none().0,
292 value.as_ref().to_glib_none().0,
293 );
294 }
295 }
296
297 fn throw(&self, error_message: &str) {
298 unsafe {
299 ffi::jsc_context_throw(
300 self.as_ref().to_glib_none().0,
301 error_message.to_glib_none().0,
302 );
303 }
304 }
305
306 fn throw_exception(&self, exception: &impl IsA<Exception>) {
307 unsafe {
308 ffi::jsc_context_throw_exception(
309 self.as_ref().to_glib_none().0,
310 exception.as_ref().to_glib_none().0,
311 );
312 }
313 }
314
315 fn throw_with_name(&self, error_name: &str, error_message: &str) {
320 unsafe {
321 ffi::jsc_context_throw_with_name(
322 self.as_ref().to_glib_none().0,
323 error_name.to_glib_none().0,
324 error_message.to_glib_none().0,
325 );
326 }
327 }
328
329 }
333
334impl fmt::Display for Context {
335 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
336 f.write_str("Context")
337 }
338}