rquickjs_core/runtime/
base.rs1use super::{
4 opaque::Opaque, raw::RawRuntime, InterruptHandler, MemoryUsage, PromiseHook, RejectionTracker,
5};
6use crate::allocator::Allocator;
7#[cfg(feature = "loader")]
8use crate::loader::{Loader, Resolver};
9use crate::{result::JobException, Context, Mut, Ref, Result, Weak};
10use alloc::{ffi::CString, vec::Vec};
11use core::{ptr::NonNull, result::Result as StdResult};
12
13#[derive(Clone)]
17#[repr(transparent)]
18pub struct WeakRuntime(Weak<Mut<RawRuntime>>);
19
20impl WeakRuntime {
21 pub fn try_ref(&self) -> Option<Runtime> {
22 self.0.upgrade().map(|inner| Runtime { inner })
23 }
24}
25
26#[derive(Clone)]
28#[repr(transparent)]
29pub struct Runtime {
30 pub(crate) inner: Ref<Mut<RawRuntime>>,
31}
32
33impl Runtime {
34 pub fn new() -> Result<Self> {
41 let opaque = Opaque::new();
42 let rt = unsafe { RawRuntime::new(opaque)? };
43 Ok(Self {
44 inner: Ref::new(Mut::new(rt)),
45 })
46 }
47
48 pub fn new_with_alloc<A>(allocator: A) -> Result<Self>
52 where
53 A: Allocator + 'static,
54 {
55 let opaque = Opaque::new();
56 let rt = unsafe { RawRuntime::new_with_allocator(opaque, allocator)? };
57 Ok(Self {
58 inner: Ref::new(Mut::new(rt)),
59 })
60 }
61
62 pub fn weak(&self) -> WeakRuntime {
64 WeakRuntime(Ref::downgrade(&self.inner))
65 }
66
67 #[inline]
69 pub fn set_promise_hook(&self, tracker: Option<PromiseHook>) {
70 unsafe {
71 self.inner.lock().set_promise_hook(tracker);
72 }
73 }
74
75 #[inline]
77 pub fn set_host_promise_rejection_tracker(&self, tracker: Option<RejectionTracker>) {
78 unsafe {
79 self.inner
80 .lock()
81 .set_host_promise_rejection_tracker(tracker);
82 }
83 }
84
85 #[inline]
89 pub fn set_interrupt_handler(&self, handler: Option<InterruptHandler>) {
90 unsafe {
91 self.inner.lock().set_interrupt_handler(handler);
92 }
93 }
94
95 #[cfg(feature = "loader")]
97 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "loader")))]
98 pub fn set_loader<R, L>(&self, resolver: R, loader: L)
99 where
100 R: Resolver + 'static,
101 L: Loader + 'static,
102 {
103 unsafe {
104 self.inner.lock().set_loader(resolver, loader);
105 }
106 }
107
108 pub fn set_info<S: Into<Vec<u8>>>(&self, info: S) -> Result<()> {
110 let string = CString::new(info)?;
111 unsafe {
112 self.inner.lock().set_info(string);
113 }
114 Ok(())
115 }
116
117 pub fn set_memory_limit(&self, limit: usize) {
124 unsafe {
125 self.inner.lock().set_memory_limit(limit);
126 }
127 }
128
129 pub fn set_max_stack_size(&self, limit: usize) {
133 unsafe {
134 self.inner.lock().set_max_stack_size(limit);
135 }
136 }
137
138 pub fn set_gc_threshold(&self, threshold: usize) {
140 unsafe {
141 self.inner.lock().set_gc_threshold(threshold);
142 }
143 }
144
145 pub fn set_dump_flags(&self, flags: u64) {
147 unsafe {
148 self.inner.lock().set_dump_flags(flags);
149 }
150 }
151
152 pub fn run_gc(&self) {
159 unsafe {
160 self.inner.lock().run_gc();
161 }
162 }
163
164 pub fn memory_usage(&self) -> MemoryUsage {
166 unsafe { self.inner.lock().memory_usage() }
167 }
168
169 #[inline]
173 pub fn is_job_pending(&self) -> bool {
174 self.inner.lock().is_job_pending()
175 }
176
177 #[inline]
181 pub fn execute_pending_job(&self) -> StdResult<bool, JobException> {
182 let mut lock = self.inner.lock();
183 lock.update_stack_top();
184 lock.execute_pending_job().map_err(|e| {
185 JobException(unsafe {
186 Context::from_raw(
187 NonNull::new(e).expect("QuickJS returned null ptr for job error"),
188 self.clone(),
189 )
190 })
191 })
192 }
193}
194
195#[cfg(feature = "parallel")]
198unsafe impl Send for Runtime {}
199#[cfg(feature = "parallel")]
200unsafe impl Send for WeakRuntime {}
201
202#[cfg(feature = "parallel")]
206unsafe impl Sync for Runtime {}
207#[cfg(feature = "parallel")]
208unsafe impl Sync for WeakRuntime {}
209
210#[cfg(test)]
211mod test {
212 use super::*;
213 #[test]
214 fn base_runtime() {
215 let rt = Runtime::new().unwrap();
216 rt.set_info("test runtime").unwrap();
217 rt.set_memory_limit(0xFFFF);
218 rt.set_gc_threshold(0xFF);
219 rt.run_gc();
220 }
221}