Skip to content

Commit da4404b

Browse files
committed
Add Lua::scope back
1 parent 7c2e9b5 commit da4404b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+847
-1607
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ mod hook;
8787
mod luau;
8888
mod memory;
8989
mod multi;
90-
// mod scope;
90+
mod scope;
9191
mod state;
9292
mod stdlib;
9393
mod string;

src/scope.rs

Lines changed: 111 additions & 789 deletions
Large diffs are not rendered by default.

src/state.rs

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::error::{Error, Result};
1212
use crate::function::Function;
1313
use crate::hook::Debug;
1414
use crate::memory::MemoryState;
15-
// use crate::scope::Scope;
15+
use crate::scope::Scope;
1616
use crate::stdlib::StdLib;
1717
use crate::string::String;
1818
use crate::table::Table;
@@ -21,7 +21,7 @@ use crate::types::{
2121
AppDataRef, AppDataRefMut, ArcReentrantMutexGuard, Integer, LightUserData, MaybeSend, Number,
2222
ReentrantMutex, ReentrantMutexGuard, RegistryKey, XRc, XWeak,
2323
};
24-
use crate::userdata::{AnyUserData, UserData, UserDataProxy, UserDataRegistry, UserDataVariant};
24+
use crate::userdata::{AnyUserData, UserData, UserDataProxy, UserDataRegistry, UserDataStorage};
2525
use crate::util::{assert_stack, check_stack, push_string, push_table, rawset_field, StackGuard};
2626
use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, MultiValue, Nil, Value};
2727

@@ -1201,7 +1201,7 @@ impl Lua {
12011201
where
12021202
T: UserData + MaybeSend + 'static,
12031203
{
1204-
unsafe { self.lock().make_userdata(UserDataVariant::new(data)) }
1204+
unsafe { self.lock().make_userdata(UserDataStorage::new(data)) }
12051205
}
12061206

12071207
/// Creates a Lua userdata object from a custom serializable userdata type.
@@ -1214,7 +1214,7 @@ impl Lua {
12141214
where
12151215
T: UserData + Serialize + MaybeSend + 'static,
12161216
{
1217-
unsafe { self.lock().make_userdata(UserDataVariant::new_ser(data)) }
1217+
unsafe { self.lock().make_userdata(UserDataStorage::new_ser(data)) }
12181218
}
12191219

12201220
/// Creates a Lua userdata object from a custom Rust type.
@@ -1229,7 +1229,7 @@ impl Lua {
12291229
where
12301230
T: MaybeSend + 'static,
12311231
{
1232-
unsafe { self.lock().make_any_userdata(UserDataVariant::new(data)) }
1232+
unsafe { self.lock().make_any_userdata(UserDataStorage::new(data)) }
12331233
}
12341234

12351235
/// Creates a Lua userdata object from a custom serializable Rust type.
@@ -1244,26 +1244,26 @@ impl Lua {
12441244
where
12451245
T: Serialize + MaybeSend + 'static,
12461246
{
1247-
unsafe { (self.lock()).make_any_userdata(UserDataVariant::new_ser(data)) }
1247+
unsafe { (self.lock()).make_any_userdata(UserDataStorage::new_ser(data)) }
12481248
}
12491249

12501250
/// Registers a custom Rust type in Lua to use in userdata objects.
12511251
///
12521252
/// This methods provides a way to add fields or methods to userdata objects of a type `T`.
12531253
pub fn register_userdata_type<T: 'static>(&self, f: impl FnOnce(&mut UserDataRegistry<T>)) -> Result<()> {
1254-
let mut registry = const { UserDataRegistry::new() };
1254+
let type_id = TypeId::of::<T>();
1255+
let mut registry = UserDataRegistry::new(type_id);
12551256
f(&mut registry);
12561257

12571258
let lua = self.lock();
12581259
unsafe {
12591260
// Deregister the type if it already registered
1260-
let type_id = TypeId::of::<T>();
1261-
if let Some(&table_id) = (*lua.extra.get()).registered_userdata.get(&type_id) {
1261+
if let Some(&table_id) = (*lua.extra.get()).registered_userdata_t.get(&type_id) {
12621262
ffi::luaL_unref(lua.state(), ffi::LUA_REGISTRYINDEX, table_id);
12631263
}
12641264

12651265
// Register the type
1266-
lua.register_userdata_metatable(registry)?;
1266+
lua.create_userdata_metatable(registry)?;
12671267
}
12681268
Ok(())
12691269
}
@@ -1306,7 +1306,7 @@ impl Lua {
13061306
T: UserData + 'static,
13071307
{
13081308
let ud = UserDataProxy::<T>(PhantomData);
1309-
unsafe { self.lock().make_userdata(UserDataVariant::new(ud)) }
1309+
unsafe { self.lock().make_userdata(UserDataStorage::new(ud)) }
13101310
}
13111311

13121312
/// Sets the metatable for a Luau builtin vector type.
@@ -1380,15 +1380,12 @@ impl Lua {
13801380
/// dropped. `Function` types will error when called, and `AnyUserData` will be typeless. It
13811381
/// would be impossible to prevent handles to scoped values from escaping anyway, since you
13821382
/// would always be able to smuggle them through Lua state.
1383-
// pub fn scope<'lua, 'scope, R>(
1384-
// &'lua self,
1385-
// f: impl FnOnce(&Scope<'lua, 'scope>) -> Result<R>,
1386-
// ) -> Result<R>
1387-
// where
1388-
// 'lua: 'scope,
1389-
// {
1390-
// f(&Scope::new(self))
1391-
// }
1383+
pub fn scope<'env, R>(
1384+
&self,
1385+
f: impl for<'scope> FnOnce(&'scope mut Scope<'scope, 'env>) -> Result<R>,
1386+
) -> Result<R> {
1387+
f(&mut Scope::new(self.lock_arc()))
1388+
}
13921389

13931390
/// Attempts to coerce a Lua value into a String in a manner consistent with Lua's internal
13941391
/// behavior.

src/state/extra.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub(crate) struct ExtraData {
3535
pub(super) weak: MaybeUninit<WeakLua>,
3636
pub(super) owned: bool,
3737

38-
pub(super) registered_userdata: FxHashMap<TypeId, c_int>,
38+
pub(super) registered_userdata_t: FxHashMap<TypeId, c_int>,
3939
pub(super) registered_userdata_mt: FxHashMap<*const c_void, Option<TypeId>>,
4040
pub(super) last_checked_userdata_mt: (*const c_void, Option<TypeId>),
4141

@@ -144,7 +144,7 @@ impl ExtraData {
144144
lua: MaybeUninit::uninit(),
145145
weak: MaybeUninit::uninit(),
146146
owned,
147-
registered_userdata: FxHashMap::default(),
147+
registered_userdata_t: FxHashMap::default(),
148148
registered_userdata_mt: FxHashMap::default(),
149149
last_checked_userdata_mt: (ptr::null(), None),
150150
registry_unref_list: Arc::new(Mutex::new(Some(Vec::new()))),

src/state/raw.rs

Lines changed: 50 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::types::{
2020
AppDataRef, AppDataRefMut, Callback, CallbackUpvalue, DestructedUserdata, Integer, LightUserData,
2121
MaybeSend, ReentrantMutex, RegistryKey, SubtypeId, ValueRef, XRc,
2222
};
23-
use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataRegistry, UserDataVariant};
23+
use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataRegistry, UserDataStorage};
2424
use crate::util::{
2525
assert_stack, check_stack, get_destructed_userdata_metatable, get_internal_userdata, get_main_state,
2626
get_userdata, init_error_registry, init_internal_metatable, init_userdata_metatable, pop_error,
@@ -711,45 +711,45 @@ impl RawLua {
711711
}
712712
}
713713

714-
pub(crate) unsafe fn make_userdata<T>(&self, data: UserDataVariant<T>) -> Result<AnyUserData>
714+
pub(crate) unsafe fn make_userdata<T>(&self, data: UserDataStorage<T>) -> Result<AnyUserData>
715715
where
716716
T: UserData + 'static,
717717
{
718718
self.make_userdata_with_metatable(data, || {
719719
// Check if userdata/metatable is already registered
720720
let type_id = TypeId::of::<T>();
721-
if let Some(&table_id) = (*self.extra.get()).registered_userdata.get(&type_id) {
721+
if let Some(&table_id) = (*self.extra.get()).registered_userdata_t.get(&type_id) {
722722
return Ok(table_id as Integer);
723723
}
724724

725725
// Create a new metatable from `UserData` definition
726-
let mut registry = const { UserDataRegistry::new() };
726+
let mut registry = UserDataRegistry::new(type_id);
727727
T::register(&mut registry);
728728

729-
self.register_userdata_metatable(registry)
729+
self.create_userdata_metatable(registry)
730730
})
731731
}
732732

733-
pub(crate) unsafe fn make_any_userdata<T>(&self, data: UserDataVariant<T>) -> Result<AnyUserData>
733+
pub(crate) unsafe fn make_any_userdata<T>(&self, data: UserDataStorage<T>) -> Result<AnyUserData>
734734
where
735735
T: 'static,
736736
{
737737
self.make_userdata_with_metatable(data, || {
738738
// Check if userdata/metatable is already registered
739739
let type_id = TypeId::of::<T>();
740-
if let Some(&table_id) = (*self.extra.get()).registered_userdata.get(&type_id) {
740+
if let Some(&table_id) = (*self.extra.get()).registered_userdata_t.get(&type_id) {
741741
return Ok(table_id as Integer);
742742
}
743743

744744
// Create an empty metatable
745-
let registry = const { UserDataRegistry::new() };
746-
self.register_userdata_metatable::<T>(registry)
745+
let registry = UserDataRegistry::<T>::new(type_id);
746+
self.create_userdata_metatable(registry)
747747
})
748748
}
749749

750750
unsafe fn make_userdata_with_metatable<T>(
751751
&self,
752-
data: UserDataVariant<T>,
752+
data: UserDataStorage<T>,
753753
get_metatable_id: impl FnOnce() -> Result<Integer>,
754754
) -> Result<AnyUserData> {
755755
let state = self.state();
@@ -760,10 +760,7 @@ impl RawLua {
760760
ffi::lua_pushnil(state);
761761
ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, get_metatable_id()?);
762762
let protect = !self.unlikely_memory_error();
763-
#[cfg(not(feature = "lua54"))]
764763
crate::util::push_userdata(state, data, protect)?;
765-
#[cfg(feature = "lua54")]
766-
crate::util::push_userdata_uv(state, data, crate::userdata::USER_VALUE_MAXSLOT as c_int, protect)?;
767764
ffi::lua_replace(state, -3);
768765
ffi::lua_setmetatable(state, -2);
769766

@@ -782,12 +779,31 @@ impl RawLua {
782779
Ok(AnyUserData(self.pop_ref(), SubtypeId::None))
783780
}
784781

785-
pub(crate) unsafe fn register_userdata_metatable<T: 'static>(
782+
pub(crate) unsafe fn create_userdata_metatable<T>(
786783
&self,
787-
mut registry: UserDataRegistry<T>,
784+
registry: UserDataRegistry<T>,
788785
) -> Result<Integer> {
789786
let state = self.state();
790-
let _sg = StackGuard::new(state);
787+
let type_id = registry.type_id();
788+
789+
self.push_userdata_metatable(registry)?;
790+
791+
let mt_ptr = ffi::lua_topointer(state, -1);
792+
let id = protect_lua!(state, 1, 0, |state| {
793+
ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
794+
})?;
795+
796+
if let Some(type_id) = type_id {
797+
(*self.extra.get()).registered_userdata_t.insert(type_id, id);
798+
}
799+
self.register_userdata_metatable(mt_ptr, type_id);
800+
801+
Ok(id as Integer)
802+
}
803+
804+
pub(crate) unsafe fn push_userdata_metatable<T>(&self, mut registry: UserDataRegistry<T>) -> Result<()> {
805+
let state = self.state();
806+
let _sg = StackGuard::with_top(state, ffi::lua_gettop(state) + 1);
791807
check_stack(state, 13)?;
792808

793809
// Prepare metatable, add meta methods first and then meta fields
@@ -922,7 +938,7 @@ impl RawLua {
922938
let extra_init = None;
923939
#[cfg(not(feature = "luau"))]
924940
let extra_init: Option<fn(*mut ffi::lua_State) -> Result<()>> = Some(|state| {
925-
ffi::lua_pushcfunction(state, crate::util::userdata_destructor::<UserDataVariant<T>>);
941+
ffi::lua_pushcfunction(state, crate::util::userdata_destructor::<UserDataStorage<T>>);
926942
rawset_field(state, -2, "__gc")
927943
});
928944

@@ -938,44 +954,21 @@ impl RawLua {
938954
// Pop extra tables to get metatable on top of the stack
939955
ffi::lua_pop(state, extra_tables_count);
940956

941-
let mt_ptr = ffi::lua_topointer(state, -1);
942-
let id = protect_lua!(state, 1, 0, |state| {
943-
ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
944-
})?;
945-
946-
let type_id = TypeId::of::<T>();
947-
(*self.extra.get()).registered_userdata.insert(type_id, id);
948-
(*self.extra.get())
949-
.registered_userdata_mt
950-
.insert(mt_ptr, Some(type_id));
957+
Ok(())
958+
}
951959

952-
Ok(id as Integer)
960+
#[inline(always)]
961+
pub(crate) unsafe fn register_userdata_metatable(&self, mt_ptr: *const c_void, type_id: Option<TypeId>) {
962+
(*self.extra.get()).registered_userdata_mt.insert(mt_ptr, type_id);
953963
}
954964

955-
// #[inline]
956-
// pub(crate) unsafe fn register_raw_userdata_metatable(
957-
// &self,
958-
// ptr: *const c_void,
959-
// type_id: Option<TypeId>,
960-
// ) {
961-
// (*self.extra.get())
962-
// .registered_userdata_mt
963-
// .insert(ptr, type_id);
964-
// }
965-
966-
// #[inline]
967-
// pub(crate) unsafe fn deregister_raw_userdata_metatable(&self, ptr: *const c_void) {
968-
// (*self.extra.get()).registered_userdata_mt.remove(&ptr);
969-
// if (*self.extra.get()).last_checked_userdata_mt.0 == ptr {
970-
// (*self.extra.get()).last_checked_userdata_mt = (ptr::null(), None);
971-
// }
972-
// }
973-
974-
// #[inline(always)]
975-
// pub(crate) unsafe fn get_userdata_ref<T: 'static>(&self, idx: c_int) -> Result<UserDataRef<T>> {
976-
// let guard = self.lua().lock_arc();
977-
// (*get_userdata::<UserDataVariant<T>>(self.state(), idx)).try_make_ref(guard)
978-
// }
965+
#[inline(always)]
966+
pub(crate) unsafe fn deregister_userdata_metatable(&self, mt_ptr: *const c_void) {
967+
(*self.extra.get()).registered_userdata_mt.remove(&mt_ptr);
968+
if (*self.extra.get()).last_checked_userdata_mt.0 == mt_ptr {
969+
(*self.extra.get()).last_checked_userdata_mt = (ptr::null(), None);
970+
}
971+
}
979972

980973
// Returns `TypeId` for the userdata ref, checking that it's registered and not destructed.
981974
//
@@ -1028,17 +1021,17 @@ impl RawLua {
10281021

10291022
// Creates a Function out of a Callback containing a 'static Fn.
10301023
pub(crate) fn create_callback(&self, func: Callback) -> Result<Function> {
1031-
// This is non-scoped version of the callback (upvalue is always valid)
1032-
// TODO: add a scoped version
10331024
unsafe extern "C-unwind" fn call_callback(state: *mut ffi::lua_State) -> c_int {
10341025
let upvalue = get_userdata::<CallbackUpvalue>(state, ffi::lua_upvalueindex(1));
10351026
callback_error_ext(state, (*upvalue).extra.get(), |extra, nargs| {
10361027
// Lua ensures that `LUA_MINSTACK` stack spaces are available (after pushing arguments)
10371028
// The lock must be already held as the callback is executed
10381029
let rawlua = (*extra).raw_lua();
10391030
let _guard = StateGuard::new(rawlua, state);
1040-
let func = &*(*upvalue).data;
1041-
func(rawlua, nargs)
1031+
match (*upvalue).data {
1032+
Some(ref func) => func(rawlua, nargs),
1033+
None => Err(Error::CallbackDestructed),
1034+
}
10421035
})
10431036
}
10441037

@@ -1047,6 +1040,7 @@ impl RawLua {
10471040
let _sg = StackGuard::new(state);
10481041
check_stack(state, 4)?;
10491042

1043+
let func = Some(func);
10501044
let extra = XRc::clone(&self.extra);
10511045
let protect = !self.unlikely_memory_error();
10521046
push_internal_userdata(state, CallbackUpvalue { data: func, extra }, protect)?;

src/types.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,14 @@ pub(crate) type Callback = Box<dyn Fn(&RawLua, c_int) -> Result<c_int> + Send +
5252
#[cfg(not(feature = "send"))]
5353
pub(crate) type Callback = Box<dyn Fn(&RawLua, c_int) -> Result<c_int> + 'static>;
5454

55+
pub(crate) type ScopedCallback<'s> = Box<dyn Fn(&RawLua, c_int) -> Result<c_int> + 's>;
56+
5557
pub(crate) struct Upvalue<T> {
5658
pub(crate) data: T,
5759
pub(crate) extra: XRc<UnsafeCell<ExtraData>>,
5860
}
5961

60-
pub(crate) type CallbackUpvalue = Upvalue<Callback>;
62+
pub(crate) type CallbackUpvalue = Upvalue<Option<Callback>>;
6163

6264
#[cfg(all(feature = "async", feature = "send"))]
6365
pub(crate) type AsyncCallback =

0 commit comments

Comments
 (0)