use std::sync::Mutex;
use std::thread;
use std::time::Duration;
use js::rust::{JSEngine, JSEngineError, JSEngineHandle};
static JS_ENGINE: Mutex<Option<JSEngineHandle>> = Mutex::new(None);
pub(crate) fn current_js_engine_handle() -> JSEngineHandle {
JS_ENGINE.lock().unwrap().as_ref().unwrap().clone()
}
pub struct JSEngineSetup(Option<JSEngine>);
impl Default for JSEngineSetup {
fn default() -> Self {
let engine = match JSEngine::init() {
Ok(engine) => {
*JS_ENGINE.lock().unwrap() = Some(engine.handle());
Some(engine)
}
Err(JSEngineError::AlreadyInitialized) => {
let mut attempts = 0;
loop {
if let Some(h) = JSEngine::process_handle() {
let mut slot = JS_ENGINE.lock().unwrap();
if slot.is_none() {
*slot = Some(h);
}
break;
}
if JS_ENGINE.lock().unwrap().is_some() {
break;
}
attempts += 1;
if attempts > 50 {
break;
}
thread::sleep(Duration::from_millis(1));
}
None
}
Err(JSEngineError::AlreadyShutDown) => {
None
}
Err(e) => panic!("JSEngine::init() failed: {:?}", e),
};
Self(engine)
}
}
impl Drop for JSEngineSetup {
fn drop(&mut self) {
let Some(engine) = self.0.take() else {
return;
};
std::mem::forget(engine);
}
}