11use std:: {
2- cell:: { Cell , RefCell } ,
2+ cell:: RefCell ,
33 ffi:: { OsStr , OsString } ,
44 io,
55 sync:: Arc ,
@@ -19,23 +19,23 @@ use vite_str::Str;
1919use vite_task_ipc_shared:: { IPC_ENV_NAME , Request , Response , ResponseBody } ;
2020
2121pub trait Handler {
22- fn ignore_input ( & self , path : & Arc < AbsolutePath > ) ;
23- fn ignore_output ( & self , path : & Arc < AbsolutePath > ) ;
24- fn disable_cache ( & self ) ;
25- fn get_env ( & self , name : & str , tracked : bool ) -> Option < Arc < OsStr > > ;
22+ fn ignore_input ( & mut self , path : & Arc < AbsolutePath > ) ;
23+ fn ignore_output ( & mut self , path : & Arc < AbsolutePath > ) ;
24+ fn disable_cache ( & mut self ) ;
25+ fn get_env ( & mut self , name : & str , tracked : bool ) -> Option < Arc < OsStr > > ;
2626}
2727
28- /// A [`Handler`] that records every report and resolves `get_env` via a
29- /// user- provided lookup closure .
28+ /// A [`Handler`] that records every report and resolves `get_env` against
29+ /// a provided env map .
3030///
3131/// Call [`Recorder::into_reports`] after the driver future completes to
3232/// recover the collected [`Reports`].
33- pub struct Recorder < F > {
34- ignored_inputs : RefCell < FxHashSet < Arc < AbsolutePath > > > ,
35- ignored_outputs : RefCell < FxHashSet < Arc < AbsolutePath > > > ,
36- cache_disabled : Cell < bool > ,
37- env_records : RefCell < FxHashMap < Str , EnvRecord > > ,
38- env_lookup : F ,
33+ pub struct Recorder {
34+ ignored_inputs : FxHashSet < Arc < AbsolutePath > > ,
35+ ignored_outputs : FxHashSet < Arc < AbsolutePath > > ,
36+ cache_disabled : bool ,
37+ env_records : FxHashMap < Str , EnvRecord > ,
38+ env_map : FxHashMap < Str , Arc < OsStr > > ,
3939}
4040
4141/// A record of an env value requested via `get_env`.
@@ -57,56 +57,49 @@ pub struct Reports {
5757 pub env_records : FxHashMap < Str , EnvRecord > ,
5858}
5959
60- impl < F > Recorder < F >
61- where
62- F : Fn ( & str ) -> Option < Arc < OsStr > > ,
63- {
64- pub fn new ( env_lookup : F ) -> Self {
60+ impl Recorder {
61+ #[ must_use]
62+ pub fn new ( env_map : FxHashMap < Str , Arc < OsStr > > ) -> Self {
6563 Self {
66- ignored_inputs : RefCell :: default ( ) ,
67- ignored_outputs : RefCell :: default ( ) ,
68- cache_disabled : Cell :: new ( false ) ,
69- env_records : RefCell :: default ( ) ,
70- env_lookup ,
64+ ignored_inputs : FxHashSet :: default ( ) ,
65+ ignored_outputs : FxHashSet :: default ( ) ,
66+ cache_disabled : false ,
67+ env_records : FxHashMap :: default ( ) ,
68+ env_map ,
7169 }
7270 }
7371
7472 #[ must_use]
7573 pub fn into_reports ( self ) -> Reports {
7674 Reports {
77- ignored_inputs : self . ignored_inputs . into_inner ( ) ,
78- ignored_outputs : self . ignored_outputs . into_inner ( ) ,
79- cache_disabled : self . cache_disabled . get ( ) ,
80- env_records : self . env_records . into_inner ( ) ,
75+ ignored_inputs : self . ignored_inputs ,
76+ ignored_outputs : self . ignored_outputs ,
77+ cache_disabled : self . cache_disabled ,
78+ env_records : self . env_records ,
8179 }
8280 }
8381}
8482
85- impl < F > Handler for Recorder < F >
86- where
87- F : Fn ( & str ) -> Option < Arc < OsStr > > ,
88- {
89- fn ignore_input ( & self , path : & Arc < AbsolutePath > ) {
90- self . ignored_inputs . borrow_mut ( ) . insert ( Arc :: clone ( path) ) ;
83+ impl Handler for Recorder {
84+ fn ignore_input ( & mut self , path : & Arc < AbsolutePath > ) {
85+ self . ignored_inputs . insert ( Arc :: clone ( path) ) ;
9186 }
9287
93- fn ignore_output ( & self , path : & Arc < AbsolutePath > ) {
94- self . ignored_outputs . borrow_mut ( ) . insert ( Arc :: clone ( path) ) ;
88+ fn ignore_output ( & mut self , path : & Arc < AbsolutePath > ) {
89+ self . ignored_outputs . insert ( Arc :: clone ( path) ) ;
9590 }
9691
97- fn disable_cache ( & self ) {
98- self . cache_disabled . set ( true ) ;
92+ fn disable_cache ( & mut self ) {
93+ self . cache_disabled = true ;
9994 }
10095
101- fn get_env ( & self , name : & str , tracked : bool ) -> Option < Arc < OsStr > > {
102- if let Some ( existing) = self . env_records . borrow_mut ( ) . get_mut ( name) {
96+ fn get_env ( & mut self , name : & str , tracked : bool ) -> Option < Arc < OsStr > > {
97+ if let Some ( existing) = self . env_records . get_mut ( name) {
10398 existing. tracked |= tracked;
10499 return existing. value . clone ( ) ;
105100 }
106- let value = ( self . env_lookup ) ( name) ;
107- self . env_records
108- . borrow_mut ( )
109- . insert ( name. into ( ) , EnvRecord { tracked, value : value. clone ( ) } ) ;
101+ let value = self . env_map . get ( name) . cloned ( ) ;
102+ self . env_records . insert ( name. into ( ) , EnvRecord { tracked, value : value. clone ( ) } ) ;
110103 value
111104 }
112105}
@@ -155,8 +148,15 @@ pub fn serve<'h, H: Handler + 'h>(
155148
156149 let run_stop = stop_token. clone ( ) ;
157150 let driver = async move {
151+ // Multiple per-client futures coexist inside `FuturesUnordered` and each
152+ // calls `&mut self` handler methods. `RefCell` provides the interior
153+ // mutability that makes these shared-access method calls compile; at
154+ // runtime the `borrow_mut()` never conflicts because we're on a
155+ // single-threaded runtime and handler methods are synchronous (no
156+ // awaits, so no borrow spans a yield point).
157+ let handler = RefCell :: new ( handler) ;
158158 run ( bound, & handler, run_stop) . await ;
159- handler
159+ handler. into_inner ( )
160160 }
161161 . boxed_local ( ) ;
162162
@@ -203,7 +203,7 @@ const fn listener_of(bound: &Bound) -> &Listener {
203203 bound
204204}
205205
206- async fn run < H : Handler > ( bound : Bound , handler : & H , shutdown : CancellationToken ) {
206+ async fn run < H : Handler > ( bound : Bound , handler : & RefCell < H > , shutdown : CancellationToken ) {
207207 let mut clients = FuturesUnordered :: new ( ) ;
208208
209209 // Accept phase: accept new clients until shutdown fires.
@@ -233,7 +233,7 @@ async fn run<H: Handler>(bound: Bound, handler: &H, shutdown: CancellationToken)
233233 while clients. next ( ) . await . is_some ( ) { }
234234}
235235
236- async fn handle_client < H : Handler > ( mut stream : Stream , handler : & H ) {
236+ async fn handle_client < H : Handler > ( mut stream : Stream , handler : & RefCell < H > ) {
237237 let mut buf = Vec :: new ( ) ;
238238 loop {
239239 match read_frame ( & mut stream, & mut buf) . await {
@@ -256,17 +256,17 @@ async fn handle_client<H: Handler>(mut stream: Stream, handler: &H) {
256256 match request {
257257 Request :: IgnoreInput ( ns) => {
258258 if let Some ( path) = native_str_to_abs_path ( ns) {
259- handler. ignore_input ( & path) ;
259+ handler. borrow_mut ( ) . ignore_input ( & path) ;
260260 }
261261 }
262262 Request :: IgnoreOutput ( ns) => {
263263 if let Some ( path) = native_str_to_abs_path ( ns) {
264- handler. ignore_output ( & path) ;
264+ handler. borrow_mut ( ) . ignore_output ( & path) ;
265265 }
266266 }
267- Request :: DisableCache => handler. disable_cache ( ) ,
267+ Request :: DisableCache => handler. borrow_mut ( ) . disable_cache ( ) ,
268268 Request :: GetEnv { id, name, tracked } => {
269- let value = handler. get_env ( name, tracked) ;
269+ let value = handler. borrow_mut ( ) . get_env ( name, tracked) ;
270270 let boxed: Option < Box < NativeStr > > = value. as_deref ( ) . map ( Into :: into) ;
271271 let body = ResponseBody :: Env ( boxed. as_deref ( ) ) ;
272272 let response = Response { id, body } ;
0 commit comments