avm2: Fix get_own_class_definition users to use either instance_of or as_.

This commit is contained in:
Adrian Wielgosik 2021-09-18 17:13:06 +02:00 committed by Adrian Wielgosik
parent 71e41e2c92
commit f8c32d3a68
12 changed files with 53 additions and 51 deletions

View File

@ -216,7 +216,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
.ok_or_else(|| format!("Could not resolve parameter type {:?}", type_name))? .ok_or_else(|| format!("Could not resolve parameter type {:?}", type_name))?
.coerce_to_object(self)?; .coerce_to_object(self)?;
if class.get_own_class_definition().is_none() { if class.as_class_object().is_none() {
return Err(format!("Resolved parameter type {:?} is not a class", type_name).into()); return Err(format!("Resolved parameter type {:?} is not a class", type_name).into());
} }
@ -1279,7 +1279,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
// dynamic properties not yet set // dynamic properties not yet set
if name.is_err() if name.is_err()
&& !object && !object
.get_own_class_definition() .instance_of_class_definition()
.map(|c| c.read().is_sealed()) .map(|c| c.read().is_sealed())
.unwrap_or(false) .unwrap_or(false)
{ {
@ -1357,7 +1357,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
// Unknown properties on a dynamic class delete successfully. // Unknown properties on a dynamic class delete successfully.
self.context.avm2.push( self.context.avm2.push(
!object !object
.get_own_class_definition() .instance_of_class_definition()
.map(|c| c.read().is_sealed()) .map(|c| c.read().is_sealed())
.unwrap_or(false), .unwrap_or(false),
) )
@ -2559,7 +2559,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
}); });
let class = found?.coerce_to_object(self)?; let class = found?.coerce_to_object(self)?;
if class.get_own_class_definition().is_none() { if class.as_class_object().is_none() {
return Err("TypeError: The right-hand side of operator must be a class.".into()); return Err("TypeError: The right-hand side of operator must be a class.".into());
} }
@ -2576,7 +2576,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
let class = self.context.avm2.pop().coerce_to_object(self)?; let class = self.context.avm2.pop().coerce_to_object(self)?;
let value = self.context.avm2.pop().coerce_to_object(self)?; let value = self.context.avm2.pop().coerce_to_object(self)?;
if class.get_own_class_definition().is_none() { if class.as_class_object().is_none() {
return Err("TypeError: The right-hand side of operator must be a class.".into()); return Err("TypeError: The right-hand side of operator must be a class.".into());
} }

View File

@ -311,7 +311,7 @@ fn dynamic_class<'gc>(
script: Script<'gc>, script: Script<'gc>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let class = class_object let class = class_object
.get_own_class_definition() .as_class_definition()
.ok_or("Attempted to create builtin dynamic class without class on it's constructor!")?; .ok_or("Attempted to create builtin dynamic class without class on it's constructor!")?;
let name = class.read().name().clone(); let name = class.read().name().clone();
@ -464,7 +464,7 @@ pub fn load_player_globals<'gc>(
object_class.install_traits( object_class.install_traits(
activation, activation,
object_class object_class
.get_own_class_definition() .as_class_definition()
.unwrap() .unwrap()
.read() .read()
.class_traits(), .class_traits(),
@ -472,7 +472,7 @@ pub fn load_player_globals<'gc>(
function_class.install_traits( function_class.install_traits(
activation, activation,
function_class function_class
.get_own_class_definition() .as_class_definition()
.unwrap() .unwrap()
.read() .read()
.class_traits(), .class_traits(),
@ -480,7 +480,7 @@ pub fn load_player_globals<'gc>(
class_class.install_traits( class_class.install_traits(
activation, activation,
class_class class_class
.get_own_class_definition() .as_class_definition()
.unwrap() .unwrap()
.read() .read()
.class_traits(), .class_traits(),

View File

@ -22,8 +22,7 @@ pub fn instance_init<'gc>(
activation.super_init(this, &[])?; activation.super_init(this, &[])?;
let name = this let name = this
.instance_of() .instance_of_class_definition()
.and_then(|t| t.get_own_class_definition())
.map(|c| c.read().name().clone()); .map(|c| c.read().name().clone());
let character = this let character = this
.instance_of() .instance_of()

View File

@ -40,7 +40,7 @@ pub fn instance_init<'gc>(
{ {
this.set_sound(activation.context.gc_context, *sound); this.set_sound(activation.context.gc_context, *sound);
} else { } else {
log::warn!("Attempted to construct subclass of Sound, {}, which is associated with non-Sound character {}", class_object.get_own_class_definition().expect("Class object is also a class").read().name().local_name(), symbol); log::warn!("Attempted to construct subclass of Sound, {}, which is associated with non-Sound character {}", class_object.as_class_definition().expect("Class object is also a class").read().name().local_name(), symbol);
} }
} }
} }

View File

@ -40,7 +40,7 @@ pub fn get_qualified_class_name<'gc>(
Ok(AvmString::new( Ok(AvmString::new(
activation.context.gc_context, activation.context.gc_context,
class class
.get_own_class_definition() .as_class_definition()
.ok_or("This object does not have a class")? .ok_or("This object does not have a class")?
.read() .read()
.name() .name()
@ -72,7 +72,7 @@ pub fn get_qualified_super_class_name<'gc>(
Ok(AvmString::new( Ok(AvmString::new(
activation.context.gc_context, activation.context.gc_context,
super_class super_class
.get_own_class_definition() .as_class_definition()
.ok_or("This object does not have a class")? .ok_or("This object does not have a class")?
.read() .read()
.name() .name()

View File

@ -67,7 +67,7 @@ pub fn class_init<'gc>(
let int_vector_class = this.apply(activation, &[int_class.into()])?; let int_vector_class = this.apply(activation, &[int_class.into()])?;
let int_vector_name = QName::new(Namespace::internal(NS_VECTOR), "Vector$int"); let int_vector_name = QName::new(Namespace::internal(NS_VECTOR), "Vector$int");
int_vector_class int_vector_class
.get_own_class_definition() .as_class_definition()
.unwrap() .unwrap()
.write(activation.context.gc_context) .write(activation.context.gc_context)
.set_name(int_vector_name.clone()); .set_name(int_vector_name.clone());
@ -85,7 +85,7 @@ pub fn class_init<'gc>(
let uint_vector_class = this.apply(activation, &[uint_class.into()])?; let uint_vector_class = this.apply(activation, &[uint_class.into()])?;
let uint_vector_name = QName::new(Namespace::internal(NS_VECTOR), "Vector$uint"); let uint_vector_name = QName::new(Namespace::internal(NS_VECTOR), "Vector$uint");
uint_vector_class uint_vector_class
.get_own_class_definition() .as_class_definition()
.unwrap() .unwrap()
.write(activation.context.gc_context) .write(activation.context.gc_context)
.set_name(uint_vector_name.clone()); .set_name(uint_vector_name.clone());
@ -103,7 +103,7 @@ pub fn class_init<'gc>(
let number_vector_class = this.apply(activation, &[number_class.into()])?; let number_vector_class = this.apply(activation, &[number_class.into()])?;
let number_vector_name = QName::new(Namespace::internal(NS_VECTOR), "Vector$double"); let number_vector_name = QName::new(Namespace::internal(NS_VECTOR), "Vector$double");
number_vector_class number_vector_class
.get_own_class_definition() .as_class_definition()
.unwrap() .unwrap()
.write(activation.context.gc_context) .write(activation.context.gc_context)
.set_name(number_vector_name.clone()); .set_name(number_vector_name.clone());
@ -120,7 +120,7 @@ pub fn class_init<'gc>(
let object_vector_class = this.apply(activation, &[Value::Null])?; let object_vector_class = this.apply(activation, &[Value::Null])?;
let object_vector_name = QName::new(Namespace::internal(NS_VECTOR), "Vector$object"); let object_vector_name = QName::new(Namespace::internal(NS_VECTOR), "Vector$object");
object_vector_class object_vector_class
.get_own_class_definition() .as_class_definition()
.unwrap() .unwrap()
.write(activation.context.gc_context) .write(activation.context.gc_context)
.set_name(object_vector_name.clone()); .set_name(object_vector_name.clone());
@ -282,14 +282,14 @@ pub fn concat<'gc>(
for arg in args.iter().map(|a| a.clone()) { for arg in args.iter().map(|a| a.clone()) {
let arg_obj = arg.coerce_to_object(activation)?; let arg_obj = arg.coerce_to_object(activation)?;
let arg_class = arg_obj let arg_class = arg_obj
.get_own_class_definition() .instance_of_class_definition()
.ok_or("TypeError: Tried to concat from a bare object")?; .ok_or("TypeError: Tried to concat from a bare object")?;
if !arg.is_of_type(activation, my_class)? { if !arg.is_of_type(activation, my_class)? {
return Err(format!( return Err(format!(
"TypeError: Cannot coerce argument of type {:?} to argument of type {:?}", "TypeError: Cannot coerce argument of type {:?} to argument of type {:?}",
arg_class.read().name(), arg_class.read().name(),
my_class my_class
.get_own_class_definition() .as_class_definition()
.ok_or("TypeError: Tried to concat into a bare object")? .ok_or("TypeError: Tried to concat into a bare object")?
.read() .read()
.name() .name()
@ -308,13 +308,13 @@ pub fn concat<'gc>(
if let Ok(val_obj) = val.coerce_to_object(activation) { if let Ok(val_obj) = val.coerce_to_object(activation) {
if !val.is_of_type(activation, val_class)? { if !val.is_of_type(activation, val_class)? {
let other_val_class = val_obj let other_val_class = val_obj
.get_own_class_definition() .instance_of_class_definition()
.ok_or("TypeError: Tried to concat a bare object into a Vector")?; .ok_or("TypeError: Tried to concat a bare object into a Vector")?;
return Err(format!( return Err(format!(
"TypeError: Cannot coerce Vector value of type {:?} to type {:?}", "TypeError: Cannot coerce Vector value of type {:?} to type {:?}",
other_val_class.read().name(), other_val_class.read().name(),
val_class val_class
.get_own_class_definition() .as_class_definition()
.ok_or("TypeError: Tried to concat into a bare object")? .ok_or("TypeError: Tried to concat into a bare object")?
.read() .read()
.name() .name()

View File

@ -131,7 +131,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
/// defined prototype methods for ES3-style classes. /// defined prototype methods for ES3-style classes.
fn find_class_for_trait(self, name: &QName<'gc>) -> Result<Option<Object<'gc>>, Error> { fn find_class_for_trait(self, name: &QName<'gc>) -> Result<Option<Object<'gc>>, Error> {
let class = self let class = self
.get_own_class_definition() .as_class_definition()
.ok_or("Cannot get base traits on non-class object")?; .ok_or("Cannot get base traits on non-class object")?;
if class.read().has_instance_trait(name) { if class.read().has_instance_trait(name) {
@ -436,7 +436,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
} }
} }
if let Some(class) = from_class_object.get_own_class_definition() { if let Some(class) = from_class_object.as_class_definition() {
self.install_traits(activation, class.read().instance_traits())?; self.install_traits(activation, class.read().instance_traits())?;
} }
@ -701,7 +701,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
})?; })?;
let mut class_traits = Vec::new(); let mut class_traits = Vec::new();
superclass_object superclass_object
.get_own_class_definition() .as_class_definition()
.unwrap() .unwrap()
.read() .read()
.lookup_instance_traits(name, &mut class_traits)?; .lookup_instance_traits(name, &mut class_traits)?;
@ -767,7 +767,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
})?; })?;
let mut class_traits = Vec::new(); let mut class_traits = Vec::new();
superclass_object superclass_object
.get_own_class_definition() .as_class_definition()
.unwrap() .unwrap()
.read() .read()
.lookup_instance_traits(name, &mut class_traits)?; .lookup_instance_traits(name, &mut class_traits)?;
@ -827,7 +827,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
})?; })?;
let mut class_traits = Vec::new(); let mut class_traits = Vec::new();
superclass_object superclass_object
.get_own_class_definition() .as_class_definition()
.unwrap() .unwrap()
.read() .read()
.lookup_instance_traits(name, &mut class_traits)?; .lookup_instance_traits(name, &mut class_traits)?;
@ -926,7 +926,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
/// coercions. /// coercions.
fn to_string(&self, mc: MutationContext<'gc, '_>) -> Result<Value<'gc>, Error> { fn to_string(&self, mc: MutationContext<'gc, '_>) -> Result<Value<'gc>, Error> {
let class_name = self let class_name = self
.get_own_class_definition() .instance_of_class_definition()
.map(|c| c.read().name().local_name()) .map(|c| c.read().name().local_name())
.unwrap_or_else(|| "Object".into()); .unwrap_or_else(|| "Object".into());
@ -943,7 +943,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
/// of the class that created this object). /// of the class that created this object).
fn to_locale_string(&self, mc: MutationContext<'gc, '_>) -> Result<Value<'gc>, Error> { fn to_locale_string(&self, mc: MutationContext<'gc, '_>) -> Result<Value<'gc>, Error> {
let class_name = self let class_name = self
.get_own_class_definition() .instance_of_class_definition()
.map(|c| c.read().name().local_name()) .map(|c| c.read().name().local_name())
.unwrap_or_else(|| "Object".into()); .unwrap_or_else(|| "Object".into());
@ -1085,22 +1085,25 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
/// Get a raw pointer value for this object. /// Get a raw pointer value for this object.
fn as_ptr(&self) -> *const ObjectPtr; fn as_ptr(&self) -> *const ObjectPtr;
/// Get this object's `Class`, if it has one. /// Get this object's class, if it has one.
/// This this object is already a ClassObject, return its own Class.
/// Note: this probably shouldn't be used in most cases.
fn get_own_class_definition(&self) -> Option<GcCell<'gc, Class<'gc>>> {
let class = self
.as_class_object()
.or_else(|| self.instance_of().and_then(|cls| cls.as_class_object()));
class.map(|cls| cls.inner_class_definition())
}
fn instance_of(&self) -> Option<Object<'gc>>; fn instance_of(&self) -> Option<Object<'gc>>;
/// Get this object's class's `Class`, if it has one.
fn instance_of_class_definition(&self) -> Option<GcCell<'gc, Class<'gc>>> {
self.instance_of().and_then(|cls| cls.as_class_definition())
}
/// Try to corece this object into a `ClassObject`.
fn as_class_object(&self) -> Option<ClassObject<'gc>> { fn as_class_object(&self) -> Option<ClassObject<'gc>> {
None None
} }
/// Get this object's `Class`, if it's a `ClassObject`.
fn as_class_definition(&self) -> Option<GcCell<'gc, Class<'gc>>> {
self.as_class_object()
.map(|cls| cls.inner_class_definition())
}
/// Get this object's `Executable`, if it has one. /// Get this object's `Executable`, if it has one.
fn as_executable(&self) -> Option<Executable<'gc>> { fn as_executable(&self) -> Option<Executable<'gc>> {
None None

View File

@ -85,7 +85,7 @@ impl<'gc> ClassObject<'gc> {
superclass_object: Option<Object<'gc>>, superclass_object: Option<Object<'gc>>,
scope: Option<GcCell<'gc, Scope<'gc>>>, scope: Option<GcCell<'gc, Scope<'gc>>>,
) -> Result<Object<'gc>, Error> { ) -> Result<Object<'gc>, Error> {
if let Some(base_class) = superclass_object.and_then(|b| b.get_own_class_definition()) { if let Some(base_class) = superclass_object.and_then(|b| b.as_class_definition()) {
if base_class.read().is_final() { if base_class.read().is_final() {
return Err(format!( return Err(format!(
"Base class {:?} is final and cannot be extended", "Base class {:?} is final and cannot be extended",
@ -294,7 +294,7 @@ impl<'gc> ClassObject<'gc> {
} }
let interface = interface.unwrap().coerce_to_object(activation)?; let interface = interface.unwrap().coerce_to_object(activation)?;
if let Some(class) = interface.get_own_class_definition() { if let Some(class) = interface.as_class_definition() {
if !class.read().is_interface() { if !class.read().is_interface() {
return Err(format!( return Err(format!(
"Class {:?} is not an interface and cannot be implemented by classes", "Class {:?} is not an interface and cannot be implemented by classes",
@ -530,7 +530,7 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
nullable_params: &[Value<'gc>], nullable_params: &[Value<'gc>],
) -> Result<Object<'gc>, Error> { ) -> Result<Object<'gc>, Error> {
let self_class = self let self_class = self
.get_own_class_definition() .as_class_definition()
.ok_or("Attempted to apply type arguments to non-class!")?; .ok_or("Attempted to apply type arguments to non-class!")?;
if !self_class.read().is_generic() { if !self_class.read().is_generic() {
@ -570,7 +570,7 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
class_params.push( class_params.push(
param param
.unwrap_or(activation.avm2().classes().object) .unwrap_or(activation.avm2().classes().object)
.get_own_class_definition() .as_class_definition()
.ok_or(format!( .ok_or(format!(
"Cannot apply class {:?} with non-class parameter", "Cannot apply class {:?} with non-class parameter",
self_class.read().name() self_class.read().name()

View File

@ -123,7 +123,7 @@ impl<'gc> TObject<'gc> for LoaderInfoObject<'gc> {
impl_avm2_custom_object_instance!(base); impl_avm2_custom_object_instance!(base);
fn value_of(&self, mc: MutationContext<'gc, '_>) -> Result<Value<'gc>, Error> { fn value_of(&self, mc: MutationContext<'gc, '_>) -> Result<Value<'gc>, Error> {
if let Some(class) = self.get_own_class_definition() { if let Some(class) = self.instance_of_class_definition() {
Ok(AvmString::new(mc, format!("[object {}]", class.read().name().local_name())).into()) Ok(AvmString::new(mc, format!("[object {}]", class.read().name().local_name())).into())
} else { } else {
Ok("[object Object]".into()) Ok("[object Object]".into())

View File

@ -118,7 +118,7 @@ impl<'gc> TObject<'gc> for PrimitiveObject<'gc> {
val @ Value::Integer(_) | val @ Value::Unsigned(_) => Ok(val), val @ Value::Integer(_) | val @ Value::Unsigned(_) => Ok(val),
_ => { _ => {
let class_name = self let class_name = self
.get_own_class_definition() .instance_of_class_definition()
.map(|c| c.read().name().local_name()) .map(|c| c.read().name().local_name())
.unwrap_or_else(|| "Object".into()); .unwrap_or_else(|| "Object".into());

View File

@ -218,7 +218,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
} }
fn to_string(&self, mc: MutationContext<'gc, '_>) -> Result<Value<'gc>, Error> { fn to_string(&self, mc: MutationContext<'gc, '_>) -> Result<Value<'gc>, Error> {
if let Some(class) = self.get_own_class_definition() { if let Some(class) = self.instance_of_class_definition() {
Ok(AvmString::new(mc, format!("[object {}]", class.read().name().local_name())).into()) Ok(AvmString::new(mc, format!("[object {}]", class.read().name().local_name())).into())
} else { } else {
Ok("[object Object]".into()) Ok("[object Object]".into())
@ -512,7 +512,7 @@ impl<'gc> ScriptObjectData<'gc> {
while let Some(class) = cur_class { while let Some(class) = cur_class {
let cur_static_class = class let cur_static_class = class
.get_own_class_definition() .as_class_definition()
.ok_or("Object is not a class constructor")?; .ok_or("Object is not a class constructor")?;
if cur_static_class.read().has_instance_trait(name) { if cur_static_class.read().has_instance_trait(name) {
return Ok(true); return Ok(true);
@ -573,7 +573,7 @@ impl<'gc> ScriptObjectData<'gc> {
while let Some(class) = cur_class { while let Some(class) = cur_class {
let cur_static_class = class let cur_static_class = class
.get_own_class_definition() .as_class_definition()
.ok_or("Object is not a class constructor")?; .ok_or("Object is not a class constructor")?;
if let Some(ns) = cur_static_class if let Some(ns) = cur_static_class
.read() .read()
@ -761,7 +761,7 @@ impl<'gc> ScriptObjectData<'gc> {
value: Value<'gc>, value: Value<'gc>,
) -> Result<(), Error> { ) -> Result<(), Error> {
if let Some(class) = self.instance_of() { if let Some(class) = self.instance_of() {
if let Some(class) = class.get_own_class_definition() { if let Some(class) = class.as_class_definition() {
if class.read().is_sealed() { if class.read().is_sealed() {
return Err(format!( return Err(format!(
"Objects of type {:?} are not dynamic", "Objects of type {:?} are not dynamic",

View File

@ -611,7 +611,7 @@ impl<'gc> Value<'gc> {
} }
} }
if let Some(static_class) = class.get_own_class_definition() { if let Some(static_class) = class.as_class_definition() {
return Err(format!( return Err(format!(
"Cannot coerce {:?} to an {:?}", "Cannot coerce {:?} to an {:?}",
self, self,
@ -671,7 +671,7 @@ impl<'gc> Value<'gc> {
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
type_object: Object<'gc>, type_object: Object<'gc>,
) -> Result<bool, Error> { ) -> Result<bool, Error> {
if let Some(type_class) = type_object.get_own_class_definition() { if let Some(type_class) = type_object.as_class_definition() {
if type_class.read().name() == &QName::new(Namespace::public(), "Number") { if type_class.read().name() == &QName::new(Namespace::public(), "Number") {
return Ok(self.is_number()); return Ok(self.is_number());
} }