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
}
/// 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;
}
}

View File

@ -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<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();
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<Option<(Object<'gc>, 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<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 traits = superclassdef.read().lookup_instance_traits_by_slot(id)?;
@ -847,7 +850,7 @@ impl<'gc> ClassObject<'gc> {
) -> Result<Option<(Object<'gc>, 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((

View File

@ -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<u32> {
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<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.
pub fn as_method(&self) -> Option<Method<'gc>> {
match &self.kind {