Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/bundler/Graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ impl<T> Default for OutstandingLink<T> {
}
pub trait OutstandingNode: Sized {
fn link(&mut self) -> &mut OutstandingLink<Self>;
/// The pass's list of outstanding requests of this type.
fn outstanding<'g>(graph: &'g mut Graph<'_>) -> &'g mut OutstandingList<Self>;
}
/// A bundle pass's outstanding plugin requests; single-threaded (bundle thread).
pub struct OutstandingList<T: OutstandingNode> {
Expand Down
116 changes: 43 additions & 73 deletions src/bundler/bundle_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1092,17 +1092,6 @@ pub mod bv2_impl {
/// holds (`Graph::outstanding_resolves`); bundle thread only.
pub(crate) outstanding: crate::Graph::OutstandingLink<Resolve>,
}
impl Default for Resolve {
fn default() -> Self {
Self {
bv2: core::ptr::null_mut(),
import_record: MiniImportRecord::default(),
value: ResolveValue::Pending,
task: bun_event_loop::AnyTaskWithExtraContext::AnyTaskWithExtraContext::default(),
outstanding: Default::default(),
}
}
}
impl bun_event_loop::Taskable for Resolve {
const TAG: bun_event_loop::TaskTag =
bun_event_loop::task_tag::BundleV2PluginResolve;
Expand All @@ -1122,26 +1111,9 @@ pub mod bv2_impl {
outstanding: Default::default(),
}
}
/// Hops to the JS thread to call the `onResolve` plugin chain —
/// unless the pass is already cancelled (that VM is stopping and
/// will never answer): then the request fails here and now.
pub(crate) fn dispatch(&mut self) {
// SAFETY: `bv2` is a valid backref set by `init`; plugins is
// Some (asserted by `enqueue_on_js_loop_for_plugins`).
unsafe {
let bv2 = &mut *self.bv2;
bv2.graph.outstanding_resolves.push(self);
if bv2.graph.cancelled {
// Failed by `is_done` at the loop's top level (not
// here, mid-caller); make sure it runs again.
bv2.wake_own_loop();
return;
}
let task = bun_event_loop::ConcurrentTask::ConcurrentTask::create(
bun_event_loop::Task::init(std::ptr::from_mut::<Self>(self)),
);
bv2.enqueue_on_js_loop_for_plugins(task);
}
/// Bundle thread: hands the request to the `onResolve` plugin chain.
pub(crate) fn dispatch(self, bv2: &mut BundleV2<'_>) {
bv2.dispatch_plugin_request(self);
}
pub fn run_on_js_thread(&mut self) {
let kind = self.import_record.kind;
Expand Down Expand Up @@ -1257,26 +1229,9 @@ pub mod bv2_impl {
pub(crate) fn bake_graph(&self) -> crate::bake_types::Graph {
self.parse_task().known_target.bake_graph()
}
/// Hops to the JS thread to call the `onLoad` plugin chain —
/// unless the pass is already cancelled: see `Resolve::dispatch`.
pub(crate) fn dispatch(&mut self) {
// SAFETY: `bv2` is a valid backref; plugins is Some (asserted
// by `enqueue_on_js_loop_for_plugins`).
unsafe {
let bv2 = &mut *self.bv2;
bv2.graph.outstanding_loads.push(self);
if bv2.graph.cancelled {
// Failed by `is_done` at the loop's top level (not
// here, mid-caller); make sure it runs again.
bv2.wake_own_loop();
return;
}
let concurrent_task =
bun_event_loop::ConcurrentTask::ConcurrentTask::create(
bun_event_loop::Task::init(std::ptr::from_mut::<Self>(self)),
);
bv2.enqueue_on_js_loop_for_plugins(concurrent_task);
}
/// Bundle thread: hands the request to the `onLoad` plugin chain.
pub(crate) fn dispatch(self, bv2: &mut BundleV2<'_>) {
bv2.dispatch_plugin_request(self);
}
pub fn run_on_js_thread(&mut self) {
let is_server_side = self.bake_graph() != crate::bake_types::Graph::Client;
Expand Down Expand Up @@ -1309,11 +1264,21 @@ pub mod bv2_impl {
fn link(&mut self) -> &mut crate::Graph::OutstandingLink<Self> {
&mut self.outstanding
}
fn outstanding<'g>(
graph: &'g mut crate::Graph::Graph<'_>,
) -> &'g mut crate::Graph::OutstandingList<Self> {
&mut graph.outstanding_loads
}
}
impl crate::Graph::OutstandingNode for Resolve {
fn link(&mut self) -> &mut crate::Graph::OutstandingLink<Self> {
&mut self.outstanding
}
fn outstanding<'g>(
graph: &'g mut crate::Graph::Graph<'_>,
) -> &'g mut crate::Graph::OutstandingList<Self> {
&mut graph.outstanding_resolves
}
}
}
}
Expand Down Expand Up @@ -1522,6 +1487,28 @@ pub mod bv2_impl {
pub use super::{BakeOptions, BundleV2, PendingImport};

impl<'a> BundleV2<'a> {
/// Bundle thread: parks an onResolve / onLoad request in the arena, links it
/// into the pass and posts it to the plugins' thread. By value, so that the
/// pointer made here is the only one: the list, the JS thread and the answer
/// all hold it.
Comment thread
robobun marked this conversation as resolved.
pub(crate) fn dispatch_plugin_request<T>(&mut self, request: T)
where
T: bun_event_loop::Taskable + crate::Graph::OutstandingNode,
{
let request: *mut T = self.arena_create(request);
T::outstanding(&mut self.graph).push(request);
if self.graph.cancelled {
// Failed by `is_done` at the loop's top level (not here,
// mid-caller); make sure it runs again.
Comment thread
robobun marked this conversation as resolved.
self.wake_own_loop();
return;
}
let task = bun_event_loop::ConcurrentTask::ConcurrentTask::create(
bun_event_loop::Task::init(request),
);
self.enqueue_on_js_loop_for_plugins(task);
}

/// Folds the JS-loop lookup + enqueue so the bundler never dereferences
/// `JSBundleCompletionTask` (its layout lives in `bun_runtime`); the
/// `completion` handle carries the `&'static` vtable.
Expand Down Expand Up @@ -5628,13 +5615,7 @@ pub mod bv2_impl {
);
self.increment_scan_counter();

// Arena-owned; the dispatch
// chain holds the raw `*mut Resolve` until the JS thread calls
// back, at which point the bundle pass is still alive.
// SAFETY: arena outlives the bundle pass.
let resolve: &mut jsc_api::JSBundler::Resolve =
self.arena_create(jsc_api::JSBundler::Resolve::default());
*resolve = jsc_api::JSBundler::Resolve::init(
let resolve = jsc_api::JSBundler::Resolve::init(
self,
jsc_api::JSBundler::MiniImportRecord {
kind: import_record.kind,
Expand All @@ -5647,8 +5628,7 @@ pub mod bv2_impl {
original_target,
},
);

resolve.dispatch();
resolve.dispatch(self);
return true;
}
}
Expand All @@ -5671,13 +5651,9 @@ pub mod bv2_impl {
bstr::BStr::new(entry_point)
);

// Arena-owned.
// SAFETY: arena outlives the bundle pass.
let resolve: &mut jsc_api::JSBundler::Resolve =
self.arena_create(jsc_api::JSBundler::Resolve::default());
self.increment_scan_counter();

*resolve = jsc_api::JSBundler::Resolve::init(
let resolve = jsc_api::JSBundler::Resolve::init(
self,
jsc_api::JSBundler::MiniImportRecord {
kind: ImportKind::EntryPointBuild,
Expand All @@ -5690,8 +5666,7 @@ pub mod bv2_impl {
original_target: target,
},
);

resolve.dispatch();
resolve.dispatch(self);
return true;
}
}
Expand Down Expand Up @@ -5748,12 +5723,7 @@ pub mod bv2_impl {
bstr::BStr::new(&parse.path.namespace),
bstr::BStr::new(&parse.path.text)
);
// Arena-owned; the dispatch
// chain holds the raw `*mut Load` until the JS thread calls back.
let load_val = jsc_api::JSBundler::Load::init(self, parse);
// SAFETY: arena outlives the bundle pass.
let load: &mut jsc_api::JSBundler::Load = self.arena_create(load_val);
load.dispatch();
jsc_api::JSBundler::Load::init(self, parse).dispatch(self);
return true;
}
}
Expand Down
Loading