ul_next/javascript/
context.rs1use core::fmt;
2use std::sync::Arc;
3
4use crate::Library;
5
6use super::{JSObject, JSString, JSValue};
7
8pub struct JSContext {
15 pub(crate) internal: ul_sys::JSContextRef,
16 pub(crate) lib: Arc<Library>,
17}
18
19impl JSContext {
20 pub(crate) fn copy_from_raw(lib: Arc<Library>, ctx: ul_sys::JSContextRef) -> Self {
21 assert!(!ctx.is_null());
22
23 let ctx = unsafe { lib.ultralight().JSGlobalContextRetain(ctx as _) };
24
25 Self { internal: ctx, lib }
26 }
27
28 pub fn new(lib: Arc<Library>) -> Self {
30 let ctx = unsafe { lib.ultralight().JSGlobalContextCreate(std::ptr::null_mut()) };
31
32 Self { internal: ctx, lib }
33 }
34
35 pub fn global_object(&self) -> JSObject {
37 JSObject::copy_from_raw(self, unsafe {
38 self.lib
39 .ultralight()
40 .JSContextGetGlobalObject(self.internal)
41 })
42 }
43
44 pub fn global_context(&self) -> JSContext {
46 JSContext::copy_from_raw(self.lib.clone(), unsafe {
47 self.lib
48 .ultralight()
49 .JSContextGetGlobalContext(self.internal)
50 })
51 }
52
53 pub fn name(&self) -> Option<JSString> {
60 let name = unsafe {
61 self.lib
62 .ultralight()
63 .JSGlobalContextCopyName(self.internal as _)
64 };
65 if name.is_null() {
66 return None;
67 }
68 Some(JSString::from_raw(self.lib.clone(), name))
69 }
70
71 pub fn is_inspectable(&self) -> bool {
73 unsafe {
74 self.lib
75 .ultralight()
76 .JSGlobalContextIsInspectable(self.internal as _)
77 }
78 }
79
80 pub fn evaluate_script(&self, script: &str) -> Result<JSValue, JSValue> {
86 let script = JSString::new(self.lib.clone(), script);
87 let mut exception = std::ptr::null();
88 let ret = unsafe {
89 self.lib.ultralight().JSEvaluateScript(
90 self.internal,
91 script.internal,
92 std::ptr::null_mut(),
93 std::ptr::null_mut(),
94 0,
95 &mut exception,
96 )
97 };
98
99 if !exception.is_null() {
100 Err(JSValue::copy_from_raw(self, exception))
101 } else if ret.is_null() {
102 Err(JSValue::new_string(self, "Failed to evaluate script"))
103 } else {
104 Ok(JSValue::copy_from_raw(self, ret))
105 }
106 }
107
108 pub fn check_script_syntax(&self, script: &str) -> Result<bool, JSValue> {
112 let script = JSString::new(self.lib.clone(), script);
113 let mut exception = std::ptr::null();
114 let ret = unsafe {
115 self.lib.ultralight().JSCheckScriptSyntax(
116 self.internal,
117 script.internal,
118 std::ptr::null_mut(),
119 0,
120 &mut exception,
121 )
122 };
123
124 if !exception.is_null() {
125 return Err(JSValue::copy_from_raw(self, exception));
126 }
127
128 Ok(ret)
129 }
130
131 pub fn garbage_collect(&self) {
142 unsafe {
143 self.lib.ultralight().JSGarbageCollect(self.internal);
144 }
145 }
146}
147
148impl fmt::Debug for JSContext {
149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150 f.debug_struct("JSContext")
151 .field("name", &self.name())
152 .finish()
153 }
154}
155
156impl Clone for JSContext {
157 fn clone(&self) -> Self {
158 Self::copy_from_raw(self.lib.clone(), self.internal)
159 }
160}
161
162impl Drop for JSContext {
163 fn drop(&mut self) {
164 unsafe {
165 self.lib
166 .ultralight()
167 .JSGlobalContextRelease(self.internal as _);
168 }
169 }
170}