avm2: Split the `slot_id` and `disp_id` accessors.

This commit is contained in:
David Wendt 2021-10-30 16:06:14 -04:00 committed by Mike Welsh
parent 0cc55df5ca
commit b0b1c79143
3 changed files with 52 additions and 22 deletions

View File

@ -833,10 +833,11 @@ impl<'gc> Class<'gc> {
false false
} }
/// Determines if this class provides a given trait on its instances. /// Determines if this class provides a given trait with a particular
pub fn has_instance_trait_by_id(&self, id: u32) -> bool { /// dispatch ID on its instances.
pub fn has_instance_trait_by_disp_id(&self, id: u32) -> bool {
for trait_entry in self.instance_traits.iter() { for trait_entry in self.instance_traits.iter() {
if id == trait_entry.slot_id() { if Some(id) == trait_entry.disp_id() {
return true; return true;
} }
} }

View File

@ -386,15 +386,18 @@ impl<'gc> ClassObject<'gc> {
/// ///
/// This function returns `None` for non-trait properties, such as actually /// This function returns `None` for non-trait properties, such as actually
/// defined prototype methods for ES3-style classes. /// defined prototype methods for ES3-style classes.
pub fn find_class_for_trait_by_id(self, id: u32) -> Result<Option<ClassObject<'gc>>, Error> { pub fn find_class_for_trait_by_disp_id(
self,
id: u32,
) -> Result<Option<ClassObject<'gc>>, Error> {
let class_definition = self.inner_class_definition(); let class_definition = self.inner_class_definition();
if class_definition.read().has_instance_trait_by_id(id) { if class_definition.read().has_instance_trait_by_disp_id(id) {
return Ok(Some(self)); return Ok(Some(self));
} }
if let Some(base) = self.superclass_object() { if let Some(base) = self.superclass_object() {
return base.find_class_for_trait_by_id(id); return base.find_class_for_trait_by_disp_id(id);
} }
Ok(None) Ok(None)
@ -749,7 +752,7 @@ impl<'gc> ClassObject<'gc> {
) -> Result<Option<(Object<'gc>, u32)>, Error> { ) -> Result<Option<(Object<'gc>, u32)>, Error> {
if let Some((superclass, method_trait)) = self.instance_method(name)? { if let Some((superclass, method_trait)) = self.instance_method(name)? {
let method = method_trait.as_method().unwrap(); let method = method_trait.as_method().unwrap();
let disp_id = method_trait.slot_id(); let disp_id = method_trait.disp_id().unwrap();
let scope = self.instance_scope(); let scope = self.instance_scope();
Ok(Some(( Ok(Some((
@ -783,7 +786,7 @@ impl<'gc> ClassObject<'gc> {
receiver: Object<'gc>, receiver: Object<'gc>,
id: u32, id: u32,
) -> Result<Option<(Object<'gc>, QName<'gc>)>, Error> { ) -> Result<Option<(Object<'gc>, QName<'gc>)>, Error> {
if let Some(superclass) = self.find_class_for_trait_by_id(id)? { if let Some(superclass) = self.find_class_for_trait_by_disp_id(id)? {
let superclassdef = superclass.inner_class_definition(); let superclassdef = superclass.inner_class_definition();
let traits = superclassdef.read().lookup_instance_traits_by_slot(id)?; let traits = superclassdef.read().lookup_instance_traits_by_slot(id)?;
@ -847,7 +850,7 @@ impl<'gc> ClassObject<'gc> {
) -> Result<Option<(Object<'gc>, u32)>, Error> { ) -> Result<Option<(Object<'gc>, u32)>, Error> {
if let Some(method_trait) = self.class_method(name)? { if let Some(method_trait) = self.class_method(name)? {
let method = method_trait.as_method().unwrap(); let method = method_trait.as_method().unwrap();
let disp_id = method_trait.slot_id(); let disp_id = method_trait.disp_id().unwrap();
let scope = self.class_scope(); let scope = self.class_scope();
Ok(Some(( Ok(Some((

View File

@ -300,32 +300,58 @@ impl<'gc> Trait<'gc> {
self self
} }
/// Get the slot or dispatch ID of this trait. /// Get the slot ID of this trait.
pub fn slot_id(&self) -> u32 { pub fn slot_id(&self) -> Option<u32> {
match self.kind { match self.kind {
TraitKind::Slot { slot_id, .. } => slot_id, TraitKind::Slot { slot_id, .. } => Some(slot_id),
TraitKind::Method { disp_id, .. } => disp_id, TraitKind::Method { .. } => None,
TraitKind::Getter { disp_id, .. } => disp_id, TraitKind::Getter { .. } => None,
TraitKind::Setter { disp_id, .. } => disp_id, TraitKind::Setter { .. } => None,
TraitKind::Class { slot_id, .. } => slot_id, TraitKind::Class { slot_id, .. } => Some(slot_id),
TraitKind::Function { slot_id, .. } => slot_id, TraitKind::Function { slot_id, .. } => Some(slot_id),
TraitKind::Const { slot_id, .. } => slot_id, TraitKind::Const { slot_id, .. } => Some(slot_id),
} }
} }
/// Set the slot or dispatch ID of this trait. /// Set the slot ID of this trait.
pub fn set_slot_id(&mut self, id: u32) { pub fn set_slot_id(&mut self, id: u32) {
match &mut self.kind { match &mut self.kind {
TraitKind::Slot { slot_id, .. } => *slot_id = id, TraitKind::Slot { slot_id, .. } => *slot_id = id,
TraitKind::Method { disp_id, .. } => *disp_id = id, TraitKind::Method { .. } => {}
TraitKind::Getter { disp_id, .. } => *disp_id = id, TraitKind::Getter { .. } => {}
TraitKind::Setter { disp_id, .. } => *disp_id = id, TraitKind::Setter { .. } => {}
TraitKind::Class { slot_id, .. } => *slot_id = id, TraitKind::Class { slot_id, .. } => *slot_id = id,
TraitKind::Function { slot_id, .. } => *slot_id = id, TraitKind::Function { slot_id, .. } => *slot_id = id,
TraitKind::Const { slot_id, .. } => *slot_id = id, TraitKind::Const { slot_id, .. } => *slot_id = id,
} }
} }
/// Get the dispatch ID of this trait.
pub fn disp_id(&self) -> Option<u32> {
match self.kind {
TraitKind::Slot { .. } => None,
TraitKind::Method { disp_id, .. } => Some(disp_id),
TraitKind::Getter { disp_id, .. } => Some(disp_id),
TraitKind::Setter { disp_id, .. } => Some(disp_id),
TraitKind::Class { .. } => None,
TraitKind::Function { .. } => None,
TraitKind::Const { .. } => None,
}
}
/// Set the dispatch ID of this trait.
pub fn set_disp_id(&mut self, id: u32) {
match &mut self.kind {
TraitKind::Slot { .. } => {}
TraitKind::Method { disp_id, .. } => *disp_id = id,
TraitKind::Getter { disp_id, .. } => *disp_id = id,
TraitKind::Setter { disp_id, .. } => *disp_id = id,
TraitKind::Class { .. } => {}
TraitKind::Function { .. } => {}
TraitKind::Const { .. } => {}
}
}
/// Get the method contained within this trait, if it has one. /// Get the method contained within this trait, if it has one.
pub fn as_method(&self) -> Option<Method<'gc>> { pub fn as_method(&self) -> Option<Method<'gc>> {
match &self.kind { match &self.kind {