33use crate :: host:: opaque:: OpaqueDebugger ;
44use crate :: host:: wit;
55use crate :: { DebugRunResult , host:: bindings:: wasm_type_to_val_type} ;
6+ use std:: pin:: Pin ;
67use wasmtime:: {
78 Engine , ExnRef , FrameHandle , Func , Global , Instance , Memory , Module , OwnedRooted , Result ,
89 Table , Tag , Val , component:: Resource , component:: ResourceTable ,
@@ -65,46 +66,81 @@ impl WasmValue {
6566
6667/// Representation of an async debug event that the debugger is
6768/// waiting on.
69+ ///
70+ /// Cancel-safety: the non-cancel-safe OpaqueDebugger async methods
71+ /// are called inside an `async move` block that owns the debugger.
72+ /// `ready()` merely polls this stored future, which is always safe to
73+ /// re-poll after cancelation. The debugger is returned in the `Done`
74+ /// state and extracted by `finish()`.
6875pub struct EventFuture {
69- inner : Box < dyn OpaqueDebugger + Send + ' static > ,
7076 state : EventFutureState ,
7177}
7278
7379enum EventFutureState {
74- SingleStep ( Option < wit:: ResumptionValue > ) ,
75- Continue ( Option < wit:: ResumptionValue > ) ,
76- Done ( Result < DebugRunResult > ) ,
80+ /// The future is running; owns the debugger.
81+ Running (
82+ Pin <
83+ Box <
84+ dyn Future <
85+ Output = (
86+ Box < dyn OpaqueDebugger + Send + ' static > ,
87+ Result < DebugRunResult > ,
88+ ) ,
89+ > + Send ,
90+ > ,
91+ > ,
92+ ) ,
93+ /// The future has completed; debugger is ready to be returned.
94+ Done {
95+ inner : Box < dyn OpaqueDebugger + Send + ' static > ,
96+ result : Option < Result < DebugRunResult > > ,
97+ } ,
98+ }
99+
100+ impl EventFuture {
101+ fn new_single_step (
102+ mut inner : Box < dyn OpaqueDebugger + Send + ' static > ,
103+ resumption : wit:: ResumptionValue ,
104+ ) -> Self {
105+ EventFuture {
106+ state : EventFutureState :: Running ( Box :: pin ( async move {
107+ if let Err ( e) = inner. handle_resumption ( & resumption) . await {
108+ return ( inner, Err ( e) ) ;
109+ }
110+ let result = inner. single_step ( ) . await ;
111+ ( inner, result)
112+ } ) ) ,
113+ }
114+ }
115+
116+ fn new_continue (
117+ mut inner : Box < dyn OpaqueDebugger + Send + ' static > ,
118+ resumption : wit:: ResumptionValue ,
119+ ) -> Self {
120+ EventFuture {
121+ state : EventFutureState :: Running ( Box :: pin ( async move {
122+ if let Err ( e) = inner. handle_resumption ( & resumption) . await {
123+ return ( inner, Err ( e) ) ;
124+ }
125+ let result = inner. continue_ ( ) . await ;
126+ ( inner, result)
127+ } ) ) ,
128+ }
129+ }
77130}
78131
79132#[ async_trait:: async_trait]
80133impl wasmtime_wasi_io:: poll:: Pollable for EventFuture {
81134 async fn ready ( & mut self ) {
82135 match & mut self . state {
83- EventFutureState :: SingleStep ( resumption) => {
84- if let Some ( r) = resumption. as_ref ( ) {
85- if let Err ( e) = self . inner . handle_resumption ( r) . await {
86- self . state = EventFutureState :: Done ( Err ( e) ) ;
87- return ;
88- }
89- // Remove only after success, for cancel safety.
90- resumption. take ( ) ;
91- }
92- let result = self . inner . single_step ( ) . await ;
93- self . state = EventFutureState :: Done ( result) ;
136+ EventFutureState :: Running ( future) => {
137+ let ( inner, result) = future. await ;
138+ self . state = EventFutureState :: Done {
139+ inner,
140+ result : Some ( result) ,
141+ } ;
94142 }
95- EventFutureState :: Continue ( resumption) => {
96- if let Some ( r) = resumption. as_ref ( ) {
97- if let Err ( e) = self . inner . handle_resumption ( r) . await {
98- self . state = EventFutureState :: Done ( Err ( e) ) ;
99- return ;
100- }
101- // Remove only after success, for cancel safety.
102- resumption. take ( ) ;
103- }
104- let result = self . inner . continue_ ( ) . await ;
105- self . state = EventFutureState :: Done ( result) ;
106- }
107- EventFutureState :: Done ( _) => { }
143+ EventFutureState :: Done { .. } => { }
108144 }
109145 }
110146}
@@ -179,13 +215,7 @@ impl wit::HostDebuggee for ResourceTable {
179215 resumption : wit:: ResumptionValue ,
180216 ) -> Result < Resource < EventFuture > > {
181217 let d = self . get_mut ( & debuggee) . unwrap ( ) . inner . take ( ) . unwrap ( ) ;
182- Ok ( self . push_child (
183- EventFuture {
184- inner : d,
185- state : EventFutureState :: SingleStep ( Some ( resumption) ) ,
186- } ,
187- & debuggee,
188- ) ?)
218+ Ok ( self . push_child ( EventFuture :: new_single_step ( d, resumption) , & debuggee) ?)
189219 }
190220
191221 async fn continue_ (
@@ -194,13 +224,7 @@ impl wit::HostDebuggee for ResourceTable {
194224 resumption : wit:: ResumptionValue ,
195225 ) -> Result < Resource < EventFuture > > {
196226 let d = self . get_mut ( & debuggee) . unwrap ( ) . inner . take ( ) . unwrap ( ) ;
197- Ok ( self . push_child (
198- EventFuture {
199- inner : d,
200- state : EventFutureState :: Continue ( Some ( resumption) ) ,
201- } ,
202- & debuggee,
203- ) ?)
227+ Ok ( self . push_child ( EventFuture :: new_continue ( d, resumption) , & debuggee) ?)
204228 }
205229
206230 async fn exit_frames ( & mut self , debuggee : Resource < Debuggee > ) -> Result < Vec < Resource < Frame > > > {
@@ -245,14 +269,17 @@ impl wit::HostEventFuture for ResourceTable {
245269 ) -> Result < wit:: Event > {
246270 let mut f = self . delete ( self_) ?;
247271 f. ready ( ) . await ;
248- let EventFuture { inner, state } = f;
249- self . get_mut ( & debuggee) ?. inner = Some ( inner) ;
250- match state {
251- EventFutureState :: SingleStep ( ..) | EventFutureState :: Continue ( ..) => {
272+ match f. state {
273+ EventFutureState :: Running ( ..) => {
252274 unreachable ! ( "ready() cannot return until setting Done state" )
253275 }
254- EventFutureState :: Done ( Ok ( result) ) => Ok ( result_to_event ( self , result) ?) ,
255- EventFutureState :: Done ( Err ( e) ) => Err ( e) ,
276+ EventFutureState :: Done { inner, result } => {
277+ self . get_mut ( & debuggee) ?. inner = Some ( inner) ;
278+ match result. unwrap ( ) {
279+ Ok ( result) => Ok ( result_to_event ( self , result) ?) ,
280+ Err ( e) => Err ( e) ,
281+ }
282+ }
256283 }
257284 }
258285
0 commit comments