From 8995fe184286d041f6128f639c08c063b182bc04 Mon Sep 17 00:00:00 2001 From: Lord-McSweeney Date: Sun, 9 Jun 2024 10:46:46 -0700 Subject: [PATCH] avm2: Always store a Class on vtable --- core/src/avm2/class.rs | 2 +- core/src/avm2/globals/avmplus.rs | 6 +----- core/src/avm2/object.rs | 5 +++-- core/src/avm2/object/class_object.rs | 19 +++++++++++-------- core/src/avm2/script.rs | 2 +- core/src/avm2/vtable.rs | 26 ++++++++++++++------------ 6 files changed, 31 insertions(+), 29 deletions(-) diff --git a/core/src/avm2/class.rs b/core/src/avm2/class.rs index 69902b5ac9ed4..e37e0575ed777 100644 --- a/core/src/avm2/class.rs +++ b/core/src/avm2/class.rs @@ -604,8 +604,8 @@ impl<'gc> Class<'gc> { } read.instance_vtable.init_vtable( + self, None, - self.protected_namespace(), &read.instance_traits, None, read.super_class.map(|c| c.instance_vtable()), diff --git a/core/src/avm2/globals/avmplus.rs b/core/src/avm2/globals/avmplus.rs index d2edc8d580afa..19bd5b224ecf5 100644 --- a/core/src/avm2/globals/avmplus.rs +++ b/core/src/avm2/globals/avmplus.rs @@ -383,14 +383,12 @@ fn describe_internal_body<'gc>( let declared_by = method.class; if flags.contains(DescribeTypeFlags::HIDE_OBJECT) - && declared_by == Some(activation.avm2().classes().object) + && declared_by == activation.avm2().classes().object.inner_class_definition() { continue; } let declared_by_name = declared_by - .unwrap() - .inner_class_definition() .name() .to_qualified_name(activation.context.gc_context); @@ -477,8 +475,6 @@ fn describe_internal_body<'gc>( let accessor_type = method_type.to_qualified_name_or_star(activation.context.gc_context); let declared_by = defining_class - .unwrap() - .inner_class_definition() .name() .to_qualified_name(activation.context.gc_context); diff --git a/core/src/avm2/object.rs b/core/src/avm2/object.rs index 159a367d61fc6..5cece656cefc2 100644 --- a/core/src/avm2/object.rs +++ b/core/src/avm2/object.rs @@ -597,14 +597,15 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into> + Clone + Copy let ClassBoundMethod { method, scope, - class, + class_obj, + .. } = full_method; return exec( method, scope.expect("Scope should exist here"), self.into(), - class, + class_obj, arguments, activation, self.into(), // Callee deliberately invalid. diff --git a/core/src/avm2/object/class_object.rs b/core/src/avm2/object/class_object.rs index 874a55d2aeb59..6f923765cd40f 100644 --- a/core/src/avm2/object/class_object.rs +++ b/core/src/avm2/object/class_object.rs @@ -239,8 +239,8 @@ impl<'gc> ClassObject<'gc> { class.validate_class(self.superclass_object())?; self.instance_vtable().init_vtable( + class, Some(self), - class.protected_namespace(), &class.instance_traits(), Some(self.instance_scope()), self.superclass_object().map(|cls| cls.instance_vtable()), @@ -275,8 +275,8 @@ impl<'gc> ClassObject<'gc> { // class vtable == class traits + Class instance traits self.class_vtable().init_vtable( + class, Some(self), - class.protected_namespace(), &class.class_traits(), Some(self.class_scope()), Some(self.instance_of().unwrap().instance_vtable()), @@ -516,16 +516,17 @@ impl<'gc> ClassObject<'gc> { if let Some(Property::Method { disp_id, .. }) = property { // todo: handle errors let ClassBoundMethod { - class, + class_obj, scope, method, + .. } = self.instance_vtable().get_full_method(disp_id).unwrap(); let callee = FunctionObject::from_method( activation, method, scope.expect("Scope should exist here"), Some(receiver), - class, + class_obj, ); callee.call(receiver.into(), arguments, activation) @@ -575,16 +576,17 @@ impl<'gc> ClassObject<'gc> { ) => { // todo: handle errors let ClassBoundMethod { - class, + class_obj, scope, method, + .. } = self.instance_vtable().get_full_method(disp_id).unwrap(); let callee = FunctionObject::from_method( activation, method, scope.expect("Scope should exist here"), Some(receiver), - class, + class_obj, ); // We call getters, but return the actual function object for normal methods @@ -657,12 +659,13 @@ impl<'gc> ClassObject<'gc> { }) => { // todo: handle errors let ClassBoundMethod { - class, + class_obj, scope, method, + .. } = self.instance_vtable().get_full_method(disp_id).unwrap(); let callee = - FunctionObject::from_method(activation, method, scope.expect("Scope should exist here"), Some(receiver), class); + FunctionObject::from_method(activation, method, scope.expect("Scope should exist here"), Some(receiver), class_obj); callee.call(receiver.into(), &[value], activation)?; Ok(()) diff --git a/core/src/avm2/script.rs b/core/src/avm2/script.rs index e05d52cb6c8df..2a27c920511d2 100644 --- a/core/src/avm2/script.rs +++ b/core/src/avm2/script.rs @@ -619,8 +619,8 @@ impl<'gc> Script<'gc> { let scope = ScopeChain::new(domain); globals.vtable().unwrap().init_vtable( + globals.instance_class().unwrap(), globals.instance_of(), - globals.instance_class().unwrap().protected_namespace(), &self.traits()?, Some(scope), None, diff --git a/core/src/avm2/vtable.rs b/core/src/avm2/vtable.rs index 8e46a71fedf41..c67b197aaf558 100644 --- a/core/src/avm2/vtable.rs +++ b/core/src/avm2/vtable.rs @@ -7,10 +7,7 @@ use crate::avm2::property_map::PropertyMap; use crate::avm2::scope::ScopeChain; use crate::avm2::traits::{Trait, TraitKind}; use crate::avm2::value::Value; -use crate::avm2::Error; -use crate::avm2::Multiname; -use crate::avm2::Namespace; -use crate::avm2::QName; +use crate::avm2::{Class, Error, Multiname, Namespace, QName}; use crate::context::UpdateContext; use crate::string::AvmString; use gc_arena::{Collect, GcCell, Mutation}; @@ -52,7 +49,8 @@ pub struct VTableData<'gc> { #[derive(Collect, Clone)] #[collect(no_drop)] pub struct ClassBoundMethod<'gc> { - pub class: Option>, + pub class: Class<'gc>, + pub class_obj: Option>, pub scope: Option>, pub method: Method<'gc>, } @@ -211,8 +209,8 @@ impl<'gc> VTable<'gc> { #[allow(clippy::if_same_then_else)] pub fn init_vtable( self, + defining_class_def: Class<'gc>, defining_class: Option>, - protected_namespace: Option>, traits: &[Trait<'gc>], scope: Option>, superclass_vtable: Option, @@ -274,7 +272,7 @@ impl<'gc> VTable<'gc> { write.scope = scope; - write.protected_namespace = protected_namespace; + write.protected_namespace = defining_class_def.protected_namespace(); if let Some(superclass_vtable) = superclass_vtable { write.resolved_traits = superclass_vtable.0.read().resolved_traits.clone(); @@ -321,7 +319,8 @@ impl<'gc> VTable<'gc> { match trait_data.kind() { TraitKind::Method { method, .. } => { let entry = ClassBoundMethod { - class: defining_class, + class: defining_class_def, + class_obj: defining_class, scope, method: *method, }; @@ -349,7 +348,8 @@ impl<'gc> VTable<'gc> { } TraitKind::Getter { method, .. } => { let entry = ClassBoundMethod { - class: defining_class, + class: defining_class_def, + class_obj: defining_class, scope, method: *method, }; @@ -386,7 +386,8 @@ impl<'gc> VTable<'gc> { } TraitKind::Setter { method, .. } => { let entry = ClassBoundMethod { - class: defining_class, + class: defining_class_def, + class_obj: defining_class, scope, method: *method, }; @@ -512,9 +513,10 @@ impl<'gc> VTable<'gc> { method: ClassBoundMethod<'gc>, ) -> FunctionObject<'gc> { let ClassBoundMethod { - class, + class_obj, scope, method, + .. } = method; FunctionObject::from_method( @@ -522,7 +524,7 @@ impl<'gc> VTable<'gc> { method, scope.expect("Scope should exist here"), Some(receiver), - class, + class_obj, ) }