From b0b1c79143a80f1bb457833bdb78139944464d9c Mon Sep 17 00:00:00 2001 From: David Wendt Date: Sat, 30 Oct 2021 16:06:14 -0400 Subject: [PATCH] avm2: Split the `slot_id` and `disp_id` accessors. --- core/src/avm2/class.rs | 7 ++-- core/src/avm2/object/class_object.rs | 15 ++++---- core/src/avm2/traits.rs | 52 +++++++++++++++++++++------- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/core/src/avm2/class.rs b/core/src/avm2/class.rs index 247f3a207..d25326da6 100644 --- a/core/src/avm2/class.rs +++ b/core/src/avm2/class.rs @@ -833,10 +833,11 @@ impl<'gc> Class<'gc> { false } - /// Determines if this class provides a given trait on its instances. - pub fn has_instance_trait_by_id(&self, id: u32) -> bool { + /// Determines if this class provides a given trait with a particular + /// 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() { - if id == trait_entry.slot_id() { + if Some(id) == trait_entry.disp_id() { return true; } } diff --git a/core/src/avm2/object/class_object.rs b/core/src/avm2/object/class_object.rs index 2a8d43eea..3ed1310ca 100644 --- a/core/src/avm2/object/class_object.rs +++ b/core/src/avm2/object/class_object.rs @@ -386,15 +386,18 @@ impl<'gc> ClassObject<'gc> { /// /// This function returns `None` for non-trait properties, such as actually /// defined prototype methods for ES3-style classes. - pub fn find_class_for_trait_by_id(self, id: u32) -> Result>, Error> { + pub fn find_class_for_trait_by_disp_id( + self, + id: u32, + ) -> Result>, Error> { 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)); } 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) @@ -749,7 +752,7 @@ impl<'gc> ClassObject<'gc> { ) -> Result, u32)>, Error> { if let Some((superclass, method_trait)) = self.instance_method(name)? { 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(); Ok(Some(( @@ -783,7 +786,7 @@ impl<'gc> ClassObject<'gc> { receiver: Object<'gc>, id: u32, ) -> Result, 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 traits = superclassdef.read().lookup_instance_traits_by_slot(id)?; @@ -847,7 +850,7 @@ impl<'gc> ClassObject<'gc> { ) -> Result, u32)>, Error> { if let Some(method_trait) = self.class_method(name)? { 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(); Ok(Some(( diff --git a/core/src/avm2/traits.rs b/core/src/avm2/traits.rs index 15bc088fc..d9eac4cd4 100644 --- a/core/src/avm2/traits.rs +++ b/core/src/avm2/traits.rs @@ -300,32 +300,58 @@ impl<'gc> Trait<'gc> { self } - /// Get the slot or dispatch ID of this trait. - pub fn slot_id(&self) -> u32 { + /// Get the slot ID of this trait. + pub fn slot_id(&self) -> Option { match self.kind { - TraitKind::Slot { slot_id, .. } => slot_id, - TraitKind::Method { disp_id, .. } => disp_id, - TraitKind::Getter { disp_id, .. } => disp_id, - TraitKind::Setter { disp_id, .. } => disp_id, - TraitKind::Class { slot_id, .. } => slot_id, - TraitKind::Function { slot_id, .. } => slot_id, - TraitKind::Const { slot_id, .. } => slot_id, + TraitKind::Slot { slot_id, .. } => Some(slot_id), + TraitKind::Method { .. } => None, + TraitKind::Getter { .. } => None, + TraitKind::Setter { .. } => None, + TraitKind::Class { slot_id, .. } => Some(slot_id), + TraitKind::Function { slot_id, .. } => Some(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) { match &mut self.kind { TraitKind::Slot { slot_id, .. } => *slot_id = id, - TraitKind::Method { disp_id, .. } => *disp_id = id, - TraitKind::Getter { disp_id, .. } => *disp_id = id, - TraitKind::Setter { disp_id, .. } => *disp_id = id, + TraitKind::Method { .. } => {} + TraitKind::Getter { .. } => {} + TraitKind::Setter { .. } => {} TraitKind::Class { slot_id, .. } => *slot_id = id, TraitKind::Function { 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 { + 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. pub fn as_method(&self) -> Option> { match &self.kind {