amv2: Move superclass_object() to ClassObject

This commit is contained in:
Adrian Wielgosik 2021-09-18 11:22:54 +02:00 committed by Adrian Wielgosik
parent 2dfa875712
commit 0679fd1a9e
7 changed files with 62 additions and 15 deletions

View File

@ -502,6 +502,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
) -> Result<Value<'gc>, Error> {
let superclass_object: Result<Object<'gc>, Error> = self
.subclass_object()
.and_then(|c| c.as_class_object_really())
.and_then(|c| c.superclass_object())
.ok_or_else(|| {
"Attempted to call super constructor without a superclass."
@ -1205,6 +1206,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
let superclass_object: Result<Object<'gc>, Error> = self
.subclass_object()
.and_then(|c| c.as_class_object_really())
.and_then(|bc| bc.superclass_object())
.ok_or_else(|| {
"Attempted to call super method without a superclass."
@ -1237,6 +1239,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
let superclass_object: Result<Object<'gc>, Error> = self
.subclass_object()
.and_then(|c| c.as_class_object_really())
.and_then(|bc| bc.superclass_object())
.ok_or_else(|| {
"Attempted to call super method without a superclass."
@ -1378,6 +1381,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
let superclass_object: Result<Object<'gc>, Error> = self
.subclass_object()
.and_then(|c| c.as_class_object_really())
.and_then(|bc| bc.superclass_object())
.ok_or_else(|| {
"Attempted to call super method without a superclass."
@ -1409,6 +1413,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
let superclass_object: Result<Object<'gc>, Error> = self
.subclass_object()
.and_then(|c| c.as_class_object_really())
.and_then(|bc| bc.superclass_object())
.ok_or_else(|| {
"Attempted to call super method without a superclass."

View File

@ -29,9 +29,17 @@ pub fn get_qualified_class_name<'gc>(
.unwrap_or(&Value::Undefined)
.coerce_to_object(activation)?;
let class = match obj.as_class_object_really() {
Some(class) => class,
None => match obj.instance_of() {
Some(cls) => cls.as_class_object_really().unwrap(),
None => return Ok(Value::Null),
}
};
Ok(AvmString::new(
activation.context.gc_context,
obj.as_class()
class.as_class()
.ok_or("This object does not have a class")?
.read()
.name()
@ -51,7 +59,15 @@ pub fn get_qualified_super_class_name<'gc>(
.unwrap_or(&Value::Undefined)
.coerce_to_object(activation)?;
if let Some(super_class) = obj.superclass_object() {
let class = match obj.as_class_object_really() {
Some(class) => class,
None => match obj.instance_of() {
Some(cls) => cls.as_class_object_really().unwrap(),
None => return Ok(Value::Null),
}
};
if let Some(super_class) = class.superclass_object() {
Ok(AvmString::new(
activation.context.gc_context,
super_class

View File

@ -138,7 +138,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
return Ok(Some(self.into()));
}
if let Some(base) = self.superclass_object() {
if let Some(base) = self.as_class_object_really().and_then(|cls| cls.superclass_object()) {
return base.find_class_for_trait(name);
}
@ -427,8 +427,10 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
activation: &mut Activation<'_, 'gc, '_>,
from_class_object: Object<'gc>,
) -> Result<(), Error> {
if let Some(superclass_object) = from_class_object.superclass_object() {
self.install_instance_traits(activation, superclass_object)?;
if let Some(from_class_object) = from_class_object.as_class_object_really() {
if let Some(superclass_object) = from_class_object.superclass_object() {
self.install_instance_traits(activation, superclass_object)?;
}
}
if let Some(class) = from_class_object.as_class() {
@ -1063,7 +1065,11 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
}
}
my_class = class.superclass_object()
if let Some(class) = class.as_class_object_really() {
my_class = class.superclass_object()
} else {
my_class = None;
}
}
Ok(false)
@ -1078,6 +1084,8 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
/// Get this object's class object, if it has one.
fn as_class_object(&self) -> Option<Object<'gc>>;
fn instance_of(&self) -> Option<Object<'gc>>;
fn as_class_object_really(&self) -> Option<ClassObject<'gc>> {
None
}
@ -1096,11 +1104,6 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
/// class at allocation time, such as during early runtime setup.
fn set_class_object(self, mc: MutationContext<'gc, '_>, class_object: Object<'gc>);
/// Get the superclass object of this object.
fn superclass_object(self) -> Option<Object<'gc>> {
None
}
/// Get this class's instance allocator.
fn instance_allocator(self) -> Option<AllocatorFn> {
None

View File

@ -339,6 +339,10 @@ impl<'gc> ClassObject<'gc> {
pub fn interfaces(self) -> Vec<Object<'gc>> {
self.0.read().interfaces.clone()
}
pub fn superclass_object(self) -> Option<Object<'gc>> {
self.0.read().superclass_object
}
}
impl<'gc> TObject<'gc> for ClassObject<'gc> {
@ -443,10 +447,6 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
.into())
}
fn superclass_object(self) -> Option<Object<'gc>> {
self.0.read().superclass_object
}
fn instance_allocator(self) -> Option<AllocatorFn> {
Some(self.0.read().instance_allocator.0)
}
@ -490,6 +490,10 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
Some(*self)
}
fn instance_of(&self) -> Option<Object<'gc>> {
self.0.read().base.instance_of()
}
fn as_class_params(&self) -> Option<Option<Object<'gc>>> {
self.0.read().params
}

View File

@ -118,6 +118,10 @@ macro_rules! impl_avm2_custom_object_instance {
self.0.read().$field.as_class_object()
}
fn instance_of(&self) -> Option<Object<'gc>> {
self.0.read().$field.instance_of()
}
fn set_class_object(self, mc: MutationContext<'gc, '_>, class_object: Object<'gc>) {
self.0.write(mc).$field.set_class_object(class_object);
}

View File

@ -311,6 +311,10 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
fn set_class_object(self, mc: MutationContext<'gc, '_>, class_object: Object<'gc>) {
self.0.write(mc).set_class_object(class_object);
}
fn instance_of(&self) -> Option<Object<'gc>> {
self.0.read().instance_of()
}
}
impl<'gc> ScriptObject<'gc> {
@ -527,6 +531,7 @@ impl<'gc> ScriptObjectData<'gc> {
return Ok(true);
}
let class = class.as_class_object_really().unwrap();
cur_class = class.superclass_object();
}
@ -590,6 +595,7 @@ impl<'gc> ScriptObjectData<'gc> {
return Ok(Some(ns));
}
let class = class.as_class_object_really().unwrap();
cur_class = class.superclass_object();
}
@ -835,6 +841,11 @@ impl<'gc> ScriptObjectData<'gc> {
self.instance_of
}
/// Get the class object for this object, if it has one.
pub fn instance_of(&self) -> Option<Object<'gc>> {
self.instance_of
}
/// Associate the object with a particular class object.
///
/// This turns the object into an instance of that class. It should only be

View File

@ -298,6 +298,10 @@ impl<'gc> TObject<'gc> for StageObject<'gc> {
self.0.write(mc).base.set_class_object(class_object);
}
fn instance_of(&self) -> Option<Object<'gc>> {
self.0.read().base.instance_of()
}
fn as_display_object(&self) -> Option<DisplayObject<'gc>> {
self.0.read().display_object
}