diff --git a/lib/roblox_emulator/src/runner/instance/instance.rs b/lib/roblox_emulator/src/runner/instance/instance.rs index 78c6bf4..8e24d87 100644 --- a/lib/roblox_emulator/src/runner/instance/instance.rs +++ b/lib/roblox_emulator/src/runner/instance/instance.rs @@ -219,22 +219,23 @@ impl mlua::UserData for Instance{ }); methods.add_meta_function(mlua::MetaMethod::Index,|lua,(this,index):(Instance,mlua::String)|{ let index_str=&*index.to_str()?; - let Some(index_ustr)=Ustr::from_existing(index_str)else{ - return Ok(mlua::Value::Nil) - }; dom_mut(lua,|dom|{ let instance=this.get(dom)?; //println!("__index t={} i={index:?}",instance.name); let db=rbx_reflection_database::get(); let class=db.classes.get(instance.class.as_str()).ok_or_else(||mlua::Error::runtime("Class missing"))?; - //Find existing property - match instance.properties.get(&index_ustr) - .cloned() + // Find existing property + // Interestingly, ustr can know ahead of time if + // a property does not exist in any runtime instance + match Ustr::from_existing(index_str) + .and_then(|index_ustr| + instance.properties.get(&index_ustr).cloned() + ) //Find default value .or_else(||db.find_default_property(class,index_str).cloned()) //Find virtual property .or_else(||db.superclasses_iter(class).find_map(|class| - find_virtual_property(&instance.properties,class,&index_ustr) + find_virtual_property(&instance.properties,class,index_str) )) { Some(rbx_types::Variant::Int32(val))=>return val.into_lua(lua), @@ -276,9 +277,6 @@ impl mlua::UserData for Instance{ }); methods.add_meta_function(mlua::MetaMethod::NewIndex,|lua,(this,index,value):(Instance,mlua::String,mlua::Value)|{ let index_str=&*index.to_str()?; - let Some(index_ustr)=Ustr::from_existing(index_str)else{ - return Ok(()) - }; dom_mut(lua,|dom|{ let instance=this.get_mut(dom)?; let db=rbx_reflection_database::get(); @@ -288,6 +286,9 @@ impl mlua::UserData for Instance{ ).ok_or_else(|| mlua::Error::runtime(format!("Property '{index_str}' missing on class '{}'",class.name)) )?; + // the index is known to be a real property at this point + // allow creating a permanent ustr (memory leak) + let index_ustr=rbx_dom_weak::ustr(index_str); match &property.data_type{ rbx_reflection::DataType::Value(rbx_types::VariantType::Vector3)=>{ let typed_value:Vector3=*value.as_userdata().ok_or_else(||mlua::Error::runtime("Expected Userdata"))?.borrow()?; @@ -469,7 +470,7 @@ static VIRTUAL_PROPERTY_DATABASE:VPD=phf::phf_map!{ fn find_virtual_property( properties:&rbx_dom_weak::UstrMap<rbx_types::Variant>, class:&rbx_reflection::ClassDescriptor, - index:&Ustr, + index:&str, )->Option<rbx_types::Variant>{ //Find virtual property let class_virtual_properties=VIRTUAL_PROPERTY_DATABASE.get(&class.name)?;