@@ -4,6 +4,7 @@ use std::collections::HashMap;
44use std:: ffi:: CString ;
55use std:: marker:: PhantomData ;
66use std:: os:: raw:: { c_char, c_int, c_void} ;
7+ use std:: panic:: resume_unwind;
78use std:: sync:: { Arc , Mutex , Weak } ;
89use std:: { mem, ptr, str} ;
910
@@ -25,7 +26,7 @@ use crate::util::{
2526 assert_stack, callback_error, check_stack, get_gc_userdata, get_main_state, get_userdata,
2627 get_wrapped_error, init_error_registry, init_gc_metatable_for, init_userdata_metatable,
2728 pop_error, protect_lua, protect_lua_closure, push_gc_userdata, push_meta_gc_userdata,
28- push_string, push_userdata, push_wrapped_error, StackGuard ,
29+ push_string, push_userdata, push_wrapped_error, StackGuard , WrappedPanic ,
2930} ;
3031use crate :: value:: { FromLua , FromLuaMulti , MultiValue , Nil , ToLua , ToLuaMulti , Value } ;
3132
@@ -1402,32 +1403,33 @@ impl Lua {
14021403
14031404 // Uses 2 stack spaces, does not call checkstack
14041405 pub ( crate ) unsafe fn pop_value ( & self ) -> Value {
1405- match ffi:: lua_type ( self . state , -1 ) {
1406+ let state = self . state ;
1407+ match ffi:: lua_type ( state, -1 ) {
14061408 ffi:: LUA_TNIL => {
1407- ffi:: lua_pop ( self . state , 1 ) ;
1409+ ffi:: lua_pop ( state, 1 ) ;
14081410 Nil
14091411 }
14101412
14111413 ffi:: LUA_TBOOLEAN => {
1412- let b = Value :: Boolean ( ffi:: lua_toboolean ( self . state , -1 ) != 0 ) ;
1413- ffi:: lua_pop ( self . state , 1 ) ;
1414+ let b = Value :: Boolean ( ffi:: lua_toboolean ( state, -1 ) != 0 ) ;
1415+ ffi:: lua_pop ( state, 1 ) ;
14141416 b
14151417 }
14161418
14171419 ffi:: LUA_TLIGHTUSERDATA => {
1418- let ud = Value :: LightUserData ( LightUserData ( ffi:: lua_touserdata ( self . state , -1 ) ) ) ;
1419- ffi:: lua_pop ( self . state , 1 ) ;
1420+ let ud = Value :: LightUserData ( LightUserData ( ffi:: lua_touserdata ( state, -1 ) ) ) ;
1421+ ffi:: lua_pop ( state, 1 ) ;
14201422 ud
14211423 }
14221424
14231425 ffi:: LUA_TNUMBER => {
1424- if ffi:: lua_isinteger ( self . state , -1 ) != 0 {
1425- let i = Value :: Integer ( ffi:: lua_tointeger ( self . state , -1 ) ) ;
1426- ffi:: lua_pop ( self . state , 1 ) ;
1426+ if ffi:: lua_isinteger ( state, -1 ) != 0 {
1427+ let i = Value :: Integer ( ffi:: lua_tointeger ( state, -1 ) ) ;
1428+ ffi:: lua_pop ( state, 1 ) ;
14271429 i
14281430 } else {
1429- let n = Value :: Number ( ffi:: lua_tonumber ( self . state , -1 ) ) ;
1430- ffi:: lua_pop ( self . state , 1 ) ;
1431+ let n = Value :: Number ( ffi:: lua_tonumber ( state, -1 ) ) ;
1432+ ffi:: lua_pop ( state, 1 ) ;
14311433 n
14321434 }
14331435 }
@@ -1439,12 +1441,20 @@ impl Lua {
14391441 ffi:: LUA_TFUNCTION => Value :: Function ( Function ( self . pop_ref ( ) ) ) ,
14401442
14411443 ffi:: LUA_TUSERDATA => {
1442- // It should not be possible to interact with userdata types other than custom
1443- // UserData types OR a WrappedError. WrappedPanic should not be here .
1444- if let Some ( err) = get_wrapped_error ( self . state , -1 ) . as_ref ( ) {
1444+ // We must prevent interaction with userdata types other than UserData OR a WrappedError.
1445+ // WrappedPanics are automatically resumed .
1446+ if let Some ( err) = get_wrapped_error ( state, -1 ) . as_ref ( ) {
14451447 let err = err. clone ( ) ;
1446- ffi:: lua_pop ( self . state , 1 ) ;
1448+ ffi:: lua_pop ( state, 1 ) ;
14471449 Value :: Error ( err)
1450+ } else if let Some ( panic) = get_gc_userdata :: < WrappedPanic > ( state, -1 ) . as_mut ( ) {
1451+ if let Some ( panic) = ( * panic) . 0 . take ( ) {
1452+ ffi:: lua_pop ( state, 1 ) ;
1453+ resume_unwind ( panic) ;
1454+ }
1455+ // Previously resumed panic?
1456+ ffi:: lua_pop ( state, 1 ) ;
1457+ Nil
14481458 } else {
14491459 Value :: UserData ( AnyUserData ( self . pop_ref ( ) ) )
14501460 }
0 commit comments