11use super :: errors:: wasi_exit_error;
22use super :: { caller:: Caller , engine:: Engine , root, trap:: Trap } ;
3+ use crate :: ruby_api:: wasi_config:: WasiRetainedData ;
34use crate :: { define_rb_intern, error, WasiConfig } ;
45use magnus:: value:: ReprValue ;
56use magnus:: value:: StaticSymbol ;
@@ -36,6 +37,7 @@ pub struct StoreData {
3637 wasi_p1 : Option < WasiP1Ctx > ,
3738 wasi : Option < WasiCtx > ,
3839 refs : Vec < Value > ,
40+ wasi_retained_data : Option < WasiRetainedData > ,
3941 last_error : Option < Error > ,
4042 store_limits : TrackingResourceLimiter ,
4143 resource_table : ResourceTable ,
@@ -73,26 +75,19 @@ impl StoreData {
7375 }
7476
7577 pub fn check_socket_errors ( & mut self ) {
76- use crate :: ruby_api:: wasi_config:: WasiRetainedData ;
77-
78- // Check all retained values for WasiRetainedData and extract error storages
79- for value in & self . refs {
80- let ruby = Ruby :: get ( ) . unwrap ( ) ;
81-
82- // Try to convert to WasiRetainedData
83- if let Ok ( retained) = Obj :: < WasiRetainedData > :: try_convert ( * value) {
84- if let Some ( storage) = retained. error_storage ( ) {
85- if let Ok ( mut guard) = storage. lock ( ) {
86- if let Some ( ( class_name, error_msg) ) = guard. take ( ) {
87- // Look up the exception class by name and reconstruct the error
88- let exception_class = ruby
89- . class_object ( )
90- . const_get :: < _ , ExceptionClass > ( class_name)
91- . unwrap_or_else ( |_| ruby. exception_runtime_error ( ) ) ;
92-
93- self . last_error = Some ( Error :: new ( exception_class, error_msg) ) ;
94- return ;
95- }
78+ // Check the wasi_retained_data field for stored socket errors
79+ if let Some ( ref retained_data) = self . wasi_retained_data {
80+ if let Some ( storage) = retained_data. error_storage ( ) {
81+ if let Ok ( mut guard) = storage. lock ( ) {
82+ if let Some ( ( class_name, error_msg) ) = guard. take ( ) {
83+ let ruby = Ruby :: get ( ) . unwrap ( ) ;
84+ // Look up the exception class by name and reconstruct the error
85+ let exception_class = ruby
86+ . class_object ( )
87+ . const_get :: < _ , ExceptionClass > ( class_name)
88+ . unwrap_or_else ( |_| ruby. exception_runtime_error ( ) ) ;
89+
90+ self . last_error = Some ( Error :: new ( exception_class, error_msg) ) ;
9691 }
9792 }
9893 }
@@ -108,6 +103,10 @@ impl StoreData {
108103 }
109104 }
110105
106+ if let Some ( ref retained_data) = self . wasi_retained_data {
107+ retained_data. mark ( marker) ;
108+ }
109+
111110 for value in self . refs . iter ( ) {
112111 marker. mark_movable ( * value) ;
113112 }
@@ -205,12 +204,9 @@ impl Store {
205204 . transpose ( ) ?
206205 . unzip ( ) ;
207206
208- // Collect any Values that need to be retained for GC
209- let refs: Vec < Value > = [ wasi_retained, wasi_p1_retained]
210- . into_iter ( )
211- . flatten ( )
212- . flatten ( )
213- . collect ( ) ;
207+ // Store WasiRetainedData directly (prefer wasi over wasi_p1 if both present)
208+ let wasi_retained_data: Option < WasiRetainedData > =
209+ wasi_retained. flatten ( ) . or ( wasi_p1_retained. flatten ( ) ) ;
214210
215211 let limiter = match kw. optional . 2 {
216212 None => StoreLimitsBuilder :: new ( ) ,
@@ -224,7 +220,8 @@ impl Store {
224220 user_data,
225221 wasi_p1,
226222 wasi,
227- refs,
223+ refs : Default :: default ( ) ,
224+ wasi_retained_data,
228225 last_error : Default :: default ( ) ,
229226 store_limits : limiter,
230227 resource_table : Default :: default ( ) ,
0 commit comments