1use std::cell::RefCell;
2use std::rc::Rc;
3
4pub(crate) struct FetchRequest {
5 pub(crate) url: String,
6 pub(crate) method: String,
7 pub(crate) headers: Vec<(String, String)>,
8 pub(crate) body: Option<String>,
9 pub(crate) resolver: v8::Global<v8::PromiseResolver>,
10}
11
12#[allow(dead_code)]
14pub(crate) struct ActiveDgramSocket {
15 pub(crate) socket_id: u64,
16 pub(crate) socket_ptr: *mut std::net::UdpSocket,
17 pub(crate) callback: v8::Global<v8::Function>,
18 pub(crate) is_ref: bool, }
20
21#[allow(dead_code)]
23pub(crate) struct StreamingFetch {
24 pub(crate) stream_id: u64,
25 pub(crate) body_data: Vec<u8>,
26 pub(crate) offset: usize,
27}
28
29#[allow(dead_code)]
37pub(crate) struct StringCache {
38 pub(crate) status: Option<v8::Global<v8::String>>,
40 pub(crate) status_text: Option<v8::Global<v8::String>>,
41 pub(crate) headers: Option<v8::Global<v8::String>>,
42
43 pub(crate) name: Option<v8::Global<v8::String>>,
45 pub(crate) type_: Option<v8::Global<v8::String>>,
46 pub(crate) value: Option<v8::Global<v8::String>>,
47 pub(crate) length: Option<v8::Global<v8::String>>,
48 pub(crate) done: Option<v8::Global<v8::String>>,
49 pub(crate) message: Option<v8::Global<v8::String>>,
50 pub(crate) stack: Option<v8::Global<v8::String>>,
51
52 pub(crate) algorithm: Option<v8::Global<v8::String>>,
54 pub(crate) hash: Option<v8::Global<v8::String>>,
55 pub(crate) key_data: Option<v8::Global<v8::String>>,
56 pub(crate) extractable: Option<v8::Global<v8::String>>,
57 pub(crate) usages: Option<v8::Global<v8::String>>,
58 pub(crate) secret: Option<v8::Global<v8::String>>,
59 pub(crate) iv: Option<v8::Global<v8::String>>,
60 pub(crate) additional_data: Option<v8::Global<v8::String>>,
61
62 pub(crate) listeners: Option<v8::Global<v8::String>>,
64 pub(crate) stop_propagation: Option<v8::Global<v8::String>>,
65 pub(crate) stop_immediate_propagation: Option<v8::Global<v8::String>>,
66 pub(crate) default_prevented: Option<v8::Global<v8::String>>,
67 pub(crate) current_target: Option<v8::Global<v8::String>>,
68 pub(crate) target: Option<v8::Global<v8::String>>,
69 pub(crate) cancelable: Option<v8::Global<v8::String>>,
70
71 pub(crate) is_file: Option<v8::Global<v8::String>>,
73 pub(crate) is_directory: Option<v8::Global<v8::String>>,
74 pub(crate) is_symbolic_link: Option<v8::Global<v8::String>>,
75 pub(crate) size: Option<v8::Global<v8::String>>,
76 pub(crate) mtime_ms: Option<v8::Global<v8::String>>,
77 pub(crate) recursive: Option<v8::Global<v8::String>>,
78
79 pub(crate) url: Option<v8::Global<v8::String>>,
81
82 pub(crate) encoding: Option<v8::Global<v8::String>>,
84 pub(crate) path: Option<v8::Global<v8::String>>,
85 pub(crate) data: Option<v8::Global<v8::String>>,
86}
87
88impl StringCache {
89 pub(crate) fn new() -> Self {
90 Self {
91 status: None,
93 status_text: None,
94 headers: None,
95
96 name: None,
98 type_: None,
99 value: None,
100 length: None,
101 done: None,
102 message: None,
103 stack: None,
104
105 algorithm: None,
107 hash: None,
108 key_data: None,
109 extractable: None,
110 usages: None,
111 secret: None,
112 iv: None,
113 additional_data: None,
114
115 listeners: None,
117 stop_propagation: None,
118 stop_immediate_propagation: None,
119 default_prevented: None,
120 current_target: None,
121 target: None,
122 cancelable: None,
123
124 is_file: None,
126 is_directory: None,
127 is_symbolic_link: None,
128 size: None,
129 mtime_ms: None,
130 recursive: None,
131
132 url: None,
134
135 encoding: None,
137 path: None,
138 data: None,
139 }
140 }
141}
142
143#[macro_export]
148macro_rules! get_or_create_cached_string {
149 ($scope:expr, $cache:expr, $field:ident, $literal:expr) => {{
150 if let Some(ref cached) = $cache.$field {
151 v8::Local::new($scope, cached)
152 } else {
153 let key = v8::String::new($scope, $literal).unwrap();
154 let isolate: &v8::Isolate = $scope;
155 $cache.$field = Some(v8::Global::new(isolate, key));
156 key
157 }
158 }};
159}
160
161pub(crate) struct IsolateState {
162 pub(crate) context: Option<v8::Global<v8::Context>>,
163 pub(crate) module_map: crate::module::ModuleMap,
164 pub(crate) event_loop: Rc<RefCell<crate::event_loop::EventLoop>>,
165 pub(crate) timers_to_clear: Rc<RefCell<Vec<crate::event_loop::TimerId>>>,
166 pub(crate) timers_to_add: Rc<RefCell<Vec<crate::event_loop::PendingTimer>>>,
167 pub(crate) next_timer_id: Rc<RefCell<u64>>,
168 pub(crate) pending_fetches: Rc<RefCell<Vec<FetchRequest>>>,
169 pub(crate) string_cache: Rc<RefCell<StringCache>>,
170 pub(crate) http_agent: ureq::Agent,
171 pub(crate) process_argv: Vec<String>,
172 pub(crate) next_stream_id: Rc<RefCell<u64>>,
173 pub(crate) streaming_fetches: Rc<RefCell<rustc_hash::FxHashMap<u64, StreamingFetch>>>,
174 pub(crate) header_vec_pool: Rc<crate::pool::Pool<Vec<(String, String)>>>,
176 pub(crate) buffered_random: RefCell<crate::buffered_random::BufferedRandom>,
178 pub(crate) active_dgram_sockets: Rc<RefCell<rustc_hash::FxHashMap<u64, ActiveDgramSocket>>>,
180 pub(crate) next_dgram_socket_id: Rc<RefCell<u64>>,
182}
183
184impl IsolateState {
185 pub(crate) fn new(
186 context: v8::Global<v8::Context>,
187 process_argv: Vec<String>,
188 ) -> Rc<RefCell<IsolateState>> {
189 let timers_to_clear = Rc::new(RefCell::new(Vec::new()));
190 let timers_to_add = Rc::new(RefCell::new(Vec::new()));
191 let next_timer_id = Rc::new(RefCell::new(1u64));
192 let pending_fetches = Rc::new(RefCell::new(Vec::new()));
193 let string_cache = Rc::new(RefCell::new(StringCache::new()));
194 let next_stream_id = Rc::new(RefCell::new(1u64));
195 let streaming_fetches = Rc::new(RefCell::new(rustc_hash::FxHashMap::default()));
196 let active_dgram_sockets = Rc::new(RefCell::new(rustc_hash::FxHashMap::default()));
197 let next_dgram_socket_id = Rc::new(RefCell::new(1u64));
198
199 let header_vec_pool = Rc::new(crate::pool::Pool::new(200));
201
202 let config = ureq::config::Config::builder()
205 .http_status_as_error(false)
206 .build();
207 let http_agent = ureq::Agent::new_with_config(config);
208
209 Rc::new(RefCell::new(IsolateState {
210 context: Some(context),
211 module_map: crate::module::ModuleMap::new(),
212 event_loop: Rc::new(RefCell::new(crate::event_loop::EventLoop::new(
213 timers_to_clear.clone(),
214 timers_to_add.clone(),
215 next_timer_id.clone(),
216 pending_fetches.clone(),
217 active_dgram_sockets.clone(),
218 ))),
219 timers_to_clear,
220 timers_to_add,
221 next_timer_id,
222 pending_fetches,
223 string_cache,
224 http_agent,
225 process_argv,
226 next_stream_id,
227 streaming_fetches,
228 header_vec_pool,
229 buffered_random: RefCell::new(crate::buffered_random::BufferedRandom::new()),
230 active_dgram_sockets,
231 next_dgram_socket_id,
232 }))
233 }
234
235 pub(crate) fn get(scope: &mut v8::Isolate) -> Rc<RefCell<Self>> {
236 scope
237 .get_slot::<Rc<RefCell<IsolateState>>>()
238 .unwrap()
239 .clone()
240 }
241
242 pub(crate) fn context(&self) -> v8::Global<v8::Context> {
243 match &self.context {
244 Some(c) => c.clone(),
245 None => unsafe { std::hint::unreachable_unchecked() },
246 }
247 }
248
249 pub(crate) fn drop_context(&mut self) {
250 self.context.take();
251 }
252}