use core::cell::{Cell, RefCell};
use bun_event_loop::MiniEventLoop::MiniEventLoop;
pub struct BaoEventLoop {
inner: RefCell<Option<MiniEventLoop<'static>>>,
enter_depth: Cell<u32>,
pending_unref_count: Cell<u32>,
auto_tick_enabled: Cell<bool>,
js_context: Cell<*mut core::ffi::c_void>,
}
impl BaoEventLoop {
const fn new() -> Self {
Self {
inner: const { RefCell::new(None) },
enter_depth: const { Cell::new(0) },
pending_unref_count: const { Cell::new(0) },
auto_tick_enabled: const { Cell::new(false) },
js_context: const { Cell::new(core::ptr::null_mut()) },
}
}
fn ensure_inner(&self) -> core::cell::RefMut<'_, MiniEventLoop<'static>> {
let mut guard = self.inner.borrow_mut();
if guard.is_none() {
*guard = Some(MiniEventLoop::init());
}
core::cell::RefMut::map(guard, |opt| opt.as_mut().expect("just initialized"))
}
pub fn register_js_context(cx: *mut core::ffi::c_void) {
let cell = Self::current();
cell.js_context.set(cx);
}
#[inline]
pub fn current() -> &'static BaoEventLoop {
BAO_EVENT_LOOP.with(|cell: &BaoEventLoop| -> &'static BaoEventLoop {
unsafe { &*(cell as *const BaoEventLoop) }
})
}
}
thread_local! {
static BAO_EVENT_LOOP: BaoEventLoop = const { BaoEventLoop::new() };
}
bun_io::link_impl_EventLoopCtx! {
Js for BaoEventLoop => |this| {
platform_event_loop_ptr() => {
let cell = BaoEventLoop::current();
let guard = cell.ensure_inner();
let ptr = guard.loop_ptr();
let _ = this;
ptr
},
file_polls_ptr() => {
let cell = BaoEventLoop::current();
let mut guard = cell.ensure_inner();
let inner_ptr: *mut MiniEventLoop<'static> =
(&mut *guard) as *mut MiniEventLoop<'static>;
drop(guard);
unsafe { MiniEventLoop::file_polls_raw(inner_ptr) }
},
increment_pending_unref_counter() => {
let cell = BaoEventLoop::current();
let count = cell.pending_unref_count.get();
cell.pending_unref_count.set(count.saturating_add(1));
let _ = this;
},
ref_concurrently() => {
let cell = BaoEventLoop::current();
let count = cell.pending_unref_count.get();
cell.pending_unref_count.set(count.saturating_add(1));
let _ = this;
},
unref_concurrently() => {
let cell = BaoEventLoop::current();
let count = cell.pending_unref_count.get();
cell.pending_unref_count.set(count.saturating_sub(1));
let _ = this;
},
after_event_loop_callback() => {
let cell = BaoEventLoop::current();
let guard = cell.ensure_inner();
guard.after_event_loop_callback
},
set_after_event_loop_callback(cb, ctx) => {
let cell = BaoEventLoop::current();
let mut guard = cell.ensure_inner();
guard.after_event_loop_callback = cb;
guard.after_event_loop_callback_ctx = ctx;
},
pipe_read_buffer() => {
let cell = BaoEventLoop::current();
let mut guard = cell.ensure_inner();
core::ptr::from_mut::<[u8]>(guard.pipe_read_buffer())
},
}
}
#[unsafe(no_mangle)]
pub extern "Rust" fn __bun_js_event_loop_current() -> *mut () {
BaoEventLoop::current() as *const BaoEventLoop as *mut ()
}
bun_event_loop::link_impl_JsEventLoop! {
Jsc for BaoEventLoop => |this| {
iteration_number() => {
let cell = BaoEventLoop::current();
let guard = cell.ensure_inner();
unsafe { (*guard.loop_ptr()).iteration_number() }
},
file_polls() => {
let cell = BaoEventLoop::current();
let mut guard = cell.ensure_inner();
let inner_ptr: *mut MiniEventLoop<'static> =
(&mut *guard) as *mut MiniEventLoop<'static>;
drop(guard);
unsafe { MiniEventLoop::file_polls_raw(inner_ptr) }
},
put_file_poll(poll, was_ever_registered) => {
let cell = BaoEventLoop::current();
let mut guard = cell.ensure_inner();
let store_ptr: *mut MiniEventLoop<'static> =
(&mut *guard) as *mut MiniEventLoop<'static>;
drop(guard);
let store = unsafe { MiniEventLoop::file_polls_raw(store_ptr) };
let poll_nn = unsafe { core::ptr::NonNull::new_unchecked(poll) };
let owner_ptr = BaoEventLoop::current() as *const BaoEventLoop as *mut ();
let ctx = unsafe {
bun_io::EventLoopCtx::new(bun_io::EventLoopCtxKind::Js, owner_ptr)
};
unsafe { (*store).put(poll_nn, ctx, was_ever_registered) };
},
uws_loop() => {
let cell = BaoEventLoop::current();
let guard = cell.ensure_inner();
guard.loop_ptr()
},
pipe_read_buffer() => {
let cell = BaoEventLoop::current();
let mut guard = cell.ensure_inner();
core::ptr::from_mut::<[u8]>(guard.pipe_read_buffer())
},
tick() => {
let cell = BaoEventLoop::current();
let cx = cell.js_context.get();
let mut guard = cell.ensure_inner();
guard.tick_once(cx);
if !cx.is_null() {
unsafe {
mozjs::jsapi::js::RunJobs(cx as *mut mozjs::jsapi::JSContext);
}
}
},
auto_tick() => {
let cell = BaoEventLoop::current();
cell.auto_tick_enabled.set(true);
let _ = this;
},
auto_tick_active() => {
let cell = BaoEventLoop::current();
cell.auto_tick_enabled.get();
let _ = this;
},
global_object() => {
let cell = BaoEventLoop::current();
let cx = cell.js_context.get();
if cx.is_null() {
let _ = this;
return core::ptr::null_mut();
}
unsafe {
mozjs::jsapi::JS::CurrentGlobalOrNull(cx as *mut mozjs::jsapi::JSContext)
.cast()
}
},
bun_vm() => {
let cell = BaoEventLoop::current();
cell.js_context.get().cast()
},
stdout() => {
let cell = BaoEventLoop::current();
let mut guard = cell.ensure_inner();
guard.stdout()
},
stderr() => {
let cell = BaoEventLoop::current();
let mut guard = cell.ensure_inner();
guard.stderr()
},
enter() => {
let cell = BaoEventLoop::current();
let depth = cell.enter_depth.get();
cell.enter_depth.set(depth.wrapping_add(1));
},
exit() => {
let cell = BaoEventLoop::current();
let depth = cell.enter_depth.get();
if depth > 0 {
cell.enter_depth.set(depth - 1);
}
},
enqueue_task(task) => {
let cell = BaoEventLoop::current();
let mut guard = cell.ensure_inner();
let task_ptr: *mut bun_event_loop::AnyTaskWithExtraContext::AnyTaskWithExtraContext =
task.ptr.cast();
unsafe { guard.tasks.write_item(task_ptr).expect("task queue full") };
},
enqueue_task_concurrent(task) => {
let cell = BaoEventLoop::current();
let mut guard = cell.ensure_inner();
let any_task: core::ptr::NonNull<bun_event_loop::AnyTaskWithExtraContext::AnyTaskWithExtraContext> =
task.cast();
guard.enqueue_task_concurrent(any_task);
},
env() => {
let cell = BaoEventLoop::current();
let guard = cell.ensure_inner();
match guard.env {
Some(nn) => nn.as_ptr(),
None => core::ptr::null_mut(),
}
},
top_level_dir() => {
let cell = BaoEventLoop::current();
let guard = cell.ensure_inner();
core::ptr::from_ref::<[u8]>(&*guard.top_level_dir)
},
create_null_delimited_env_map() => {
let cell = BaoEventLoop::current();
let guard = cell.ensure_inner();
match guard.env {
Some(nn) => {
unsafe { (*nn.as_ptr()).map.create_null_delimited_env_map() }
},
None => Err(bun_core::AllocError),
}
},
}
}