Skip to content

Commit

Permalink
avm2: Always store a Class on vtable
Browse files Browse the repository at this point in the history
  • Loading branch information
Lord-McSweeney authored and Lord-McSweeney committed Jun 9, 2024
1 parent 257d884 commit cbe8d2a
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 29 deletions.
2 changes: 1 addition & 1 deletion core/src/avm2/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
Expand Down
6 changes: 1 addition & 5 deletions core/src/avm2/globals/avmplus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand Down
5 changes: 3 additions & 2 deletions core/src/avm2/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -597,14 +597,15 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + 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.
Expand Down
19 changes: 11 additions & 8 deletions core/src/avm2/object/class_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
Expand Down Expand Up @@ -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()),
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(())
Expand Down
2 changes: 1 addition & 1 deletion core/src/avm2/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
26 changes: 14 additions & 12 deletions core/src/avm2/vtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -52,7 +49,8 @@ pub struct VTableData<'gc> {
#[derive(Collect, Clone)]
#[collect(no_drop)]
pub struct ClassBoundMethod<'gc> {
pub class: Option<ClassObject<'gc>>,
pub class: Class<'gc>,
pub class_obj: Option<ClassObject<'gc>>,
pub scope: Option<ScopeChain<'gc>>,
pub method: Method<'gc>,
}
Expand Down Expand Up @@ -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<ClassObject<'gc>>,
protected_namespace: Option<Namespace<'gc>>,
traits: &[Trait<'gc>],
scope: Option<ScopeChain<'gc>>,
superclass_vtable: Option<Self>,
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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,
};
Expand Down Expand Up @@ -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,
};
Expand Down Expand Up @@ -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,
};
Expand Down Expand Up @@ -512,17 +513,18 @@ impl<'gc> VTable<'gc> {
method: ClassBoundMethod<'gc>,
) -> FunctionObject<'gc> {
let ClassBoundMethod {
class,
class_obj,
scope,
method,
..
} = method;

FunctionObject::from_method(
activation,
method,
scope.expect("Scope should exist here"),
Some(receiver),
class,
class_obj,
)
}

Expand Down

0 comments on commit cbe8d2a

Please sign in to comment.