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> { ) -> Result<Value<'gc>, Error> {
let superclass_object: Result<Object<'gc>, Error> = self let superclass_object: Result<Object<'gc>, Error> = self
.subclass_object() .subclass_object()
.and_then(|c| c.as_class_object_really())
.and_then(|c| c.superclass_object()) .and_then(|c| c.superclass_object())
.ok_or_else(|| { .ok_or_else(|| {
"Attempted to call super constructor without a superclass." "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 let superclass_object: Result<Object<'gc>, Error> = self
.subclass_object() .subclass_object()
.and_then(|c| c.as_class_object_really())
.and_then(|bc| bc.superclass_object()) .and_then(|bc| bc.superclass_object())
.ok_or_else(|| { .ok_or_else(|| {
"Attempted to call super method without a superclass." "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 let superclass_object: Result<Object<'gc>, Error> = self
.subclass_object() .subclass_object()
.and_then(|c| c.as_class_object_really())
.and_then(|bc| bc.superclass_object()) .and_then(|bc| bc.superclass_object())
.ok_or_else(|| { .ok_or_else(|| {
"Attempted to call super method without a superclass." "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 let superclass_object: Result<Object<'gc>, Error> = self
.subclass_object() .subclass_object()
.and_then(|c| c.as_class_object_really())
.and_then(|bc| bc.superclass_object()) .and_then(|bc| bc.superclass_object())
.ok_or_else(|| { .ok_or_else(|| {
"Attempted to call super method without a superclass." "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 let superclass_object: Result<Object<'gc>, Error> = self
.subclass_object() .subclass_object()
.and_then(|c| c.as_class_object_really())
.and_then(|bc| bc.superclass_object()) .and_then(|bc| bc.superclass_object())
.ok_or_else(|| { .ok_or_else(|| {
"Attempted to call super method without a superclass." "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) .unwrap_or(&Value::Undefined)
.coerce_to_object(activation)?; .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( Ok(AvmString::new(
activation.context.gc_context, activation.context.gc_context,
obj.as_class() class.as_class()
.ok_or("This object does not have a class")? .ok_or("This object does not have a class")?
.read() .read()
.name() .name()
@ -51,7 +59,15 @@ pub fn get_qualified_super_class_name<'gc>(
.unwrap_or(&Value::Undefined) .unwrap_or(&Value::Undefined)
.coerce_to_object(activation)?; .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( Ok(AvmString::new(
activation.context.gc_context, activation.context.gc_context,
super_class 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())); 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); return base.find_class_for_trait(name);
} }
@ -427,9 +427,11 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
from_class_object: Object<'gc>, from_class_object: Object<'gc>,
) -> Result<(), Error> { ) -> Result<(), Error> {
if let Some(from_class_object) = from_class_object.as_class_object_really() {
if let Some(superclass_object) = from_class_object.superclass_object() { if let Some(superclass_object) = from_class_object.superclass_object() {
self.install_instance_traits(activation, superclass_object)?; self.install_instance_traits(activation, superclass_object)?;
} }
}
if let Some(class) = from_class_object.as_class() { if let Some(class) = from_class_object.as_class() {
self.install_traits(activation, class.read().instance_traits())?; self.install_traits(activation, class.read().instance_traits())?;
@ -1063,7 +1065,11 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
} }
} }
if let Some(class) = class.as_class_object_really() {
my_class = class.superclass_object() my_class = class.superclass_object()
} else {
my_class = None;
}
} }
Ok(false) 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. /// Get this object's class object, if it has one.
fn as_class_object(&self) -> Option<Object<'gc>>; fn as_class_object(&self) -> Option<Object<'gc>>;
fn instance_of(&self) -> Option<Object<'gc>>;
fn as_class_object_really(&self) -> Option<ClassObject<'gc>> { fn as_class_object_really(&self) -> Option<ClassObject<'gc>> {
None 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. /// class at allocation time, such as during early runtime setup.
fn set_class_object(self, mc: MutationContext<'gc, '_>, class_object: Object<'gc>); 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. /// Get this class's instance allocator.
fn instance_allocator(self) -> Option<AllocatorFn> { fn instance_allocator(self) -> Option<AllocatorFn> {
None None

View File

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

View File

@ -118,6 +118,10 @@ macro_rules! impl_avm2_custom_object_instance {
self.0.read().$field.as_class_object() 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>) { fn set_class_object(self, mc: MutationContext<'gc, '_>, class_object: Object<'gc>) {
self.0.write(mc).$field.set_class_object(class_object); 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>) { fn set_class_object(self, mc: MutationContext<'gc, '_>, class_object: Object<'gc>) {
self.0.write(mc).set_class_object(class_object); 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> { impl<'gc> ScriptObject<'gc> {
@ -527,6 +531,7 @@ impl<'gc> ScriptObjectData<'gc> {
return Ok(true); return Ok(true);
} }
let class = class.as_class_object_really().unwrap();
cur_class = class.superclass_object(); cur_class = class.superclass_object();
} }
@ -590,6 +595,7 @@ impl<'gc> ScriptObjectData<'gc> {
return Ok(Some(ns)); return Ok(Some(ns));
} }
let class = class.as_class_object_really().unwrap();
cur_class = class.superclass_object(); cur_class = class.superclass_object();
} }
@ -835,6 +841,11 @@ impl<'gc> ScriptObjectData<'gc> {
self.instance_of 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. /// Associate the object with a particular class object.
/// ///
/// This turns the object into an instance of that class. It should only be /// 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); 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>> { fn as_display_object(&self) -> Option<DisplayObject<'gc>> {
self.0.read().display_object self.0.read().display_object
} }