rquickjs_core/runtime/
base.rs1use super::{opaque::Opaque, raw::RawRuntime, InterruptHandler, MemoryUsage, RejectionTracker};
4use crate::allocator::Allocator;
5#[cfg(feature = "loader")]
6use crate::loader::{Loader, Resolver};
7use crate::{result::JobException, Context, Mut, Ref, Result, Weak};
8use std::{ffi::CString, ptr::NonNull, result::Result as StdResult};
9
10#[derive(Clone)]
14#[repr(transparent)]
15pub struct WeakRuntime(Weak<Mut<RawRuntime>>);
16
17impl WeakRuntime {
18 pub fn try_ref(&self) -> Option<Runtime> {
19 self.0.upgrade().map(|inner| Runtime { inner })
20 }
21}
22
23#[derive(Clone)]
25#[repr(transparent)]
26pub struct Runtime {
27 pub(crate) inner: Ref<Mut<RawRuntime>>,
28}
29
30impl Runtime {
31 pub fn new() -> Result<Self> {
38 let opaque = Opaque::new();
39 let rt = unsafe { RawRuntime::new(opaque)? };
40 Ok(Self {
41 inner: Ref::new(Mut::new(rt)),
42 })
43 }
44
45 pub fn new_with_alloc<A>(allocator: A) -> Result<Self>
49 where
50 A: Allocator + 'static,
51 {
52 let opaque = Opaque::new();
53 let rt = unsafe { RawRuntime::new_with_allocator(opaque, allocator)? };
54 Ok(Self {
55 inner: Ref::new(Mut::new(rt)),
56 })
57 }
58
59 pub fn weak(&self) -> WeakRuntime {
61 WeakRuntime(Ref::downgrade(&self.inner))
62 }
63
64 #[inline]
66 pub fn set_host_promise_rejection_tracker(&self, tracker: Option<RejectionTracker>) {
67 unsafe {
68 self.inner
69 .lock()
70 .set_host_promise_rejection_tracker(tracker);
71 }
72 }
73
74 #[inline]
78 pub fn set_interrupt_handler(&self, handler: Option<InterruptHandler>) {
79 unsafe {
80 self.inner.lock().set_interrupt_handler(handler);
81 }
82 }
83
84 #[cfg(feature = "loader")]
86 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "loader")))]
87 pub fn set_loader<R, L>(&self, resolver: R, loader: L)
88 where
89 R: Resolver + 'static,
90 L: Loader + 'static,
91 {
92 unsafe {
93 self.inner.lock().set_loader(resolver, loader);
94 }
95 }
96
97 pub fn set_info<S: Into<Vec<u8>>>(&self, info: S) -> Result<()> {
99 let string = CString::new(info)?;
100 unsafe {
101 self.inner.lock().set_info(string);
102 }
103 Ok(())
104 }
105
106 pub fn set_memory_limit(&self, limit: usize) {
113 unsafe {
114 self.inner.lock().set_memory_limit(limit);
115 }
116 }
117
118 pub fn set_max_stack_size(&self, limit: usize) {
122 unsafe {
123 self.inner.lock().set_max_stack_size(limit);
124 }
125 }
126
127 pub fn set_gc_threshold(&self, threshold: usize) {
129 unsafe {
130 self.inner.lock().set_gc_threshold(threshold);
131 }
132 }
133
134 pub fn set_dump_flags(&self, flags: u64) {
136 unsafe {
137 self.inner.lock().set_dump_flags(flags);
138 }
139 }
140
141 pub fn run_gc(&self) {
148 unsafe {
149 self.inner.lock().run_gc();
150 }
151 }
152
153 pub fn memory_usage(&self) -> MemoryUsage {
155 unsafe { self.inner.lock().memory_usage() }
156 }
157
158 #[inline]
162 pub fn is_job_pending(&self) -> bool {
163 self.inner.lock().is_job_pending()
164 }
165
166 #[inline]
170 pub fn execute_pending_job(&self) -> StdResult<bool, JobException> {
171 let mut lock = self.inner.lock();
172 lock.update_stack_top();
173 lock.execute_pending_job().map_err(|e| {
174 JobException(unsafe {
175 Context::from_raw(
176 NonNull::new(e).expect("QuickJS returned null ptr for job error"),
177 self.clone(),
178 )
179 })
180 })
181 }
182}
183
184#[cfg(feature = "parallel")]
187unsafe impl Send for Runtime {}
188#[cfg(feature = "parallel")]
189unsafe impl Send for WeakRuntime {}
190
191#[cfg(feature = "parallel")]
195unsafe impl Sync for Runtime {}
196#[cfg(feature = "parallel")]
197unsafe impl Sync for WeakRuntime {}
198
199#[cfg(test)]
200mod test {
201 use super::*;
202 #[test]
203 fn base_runtime() {
204 let rt = Runtime::new().unwrap();
205 rt.set_info("test runtime").unwrap();
206 rt.set_memory_limit(0xFFFF);
207 rt.set_gc_threshold(0xFF);
208 rt.run_gc();
209 }
210}