avm2: ES3 class instances should be treated as instances of the ES4 class `Object`.

This commit is contained in:
David Wendt 2021-06-30 22:16:57 -04:00 committed by kmeisthax
parent 6b377bed64
commit 3d3b80f8af
4 changed files with 25 additions and 9 deletions

View File

@ -232,8 +232,10 @@ impl<'gc> Avm2<'gc> {
.copied(); .copied();
if let Some(object) = object { if let Some(object) = object {
if object.is_of_type(on_type)? { let mut activation = Activation::from_nothing(context.reborrow());
Avm2::dispatch_event(context, event.clone(), object)?;
if object.is_of_type(on_type, &mut activation)? {
Avm2::dispatch_event(&mut activation.context, event.clone(), object)?;
} }
} }
} }

View File

@ -2486,7 +2486,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
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());
} }
if value.is_of_type(class)? { if value.is_of_type(class, self)? {
self.context.avm2.push(value); self.context.avm2.push(value);
} else { } else {
self.context.avm2.push(Value::Null); self.context.avm2.push(Value::Null);
@ -2503,7 +2503,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
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());
} }
if value.is_of_type(class)? { if value.is_of_type(class, self)? {
self.context.avm2.push(value); self.context.avm2.push(value);
} else { } else {
self.context.avm2.push(Value::Null); self.context.avm2.push(Value::Null);

View File

@ -998,17 +998,31 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
/// The given object should be the class object for the given type we are /// The given object should be the class object for the given type we are
/// checking against this object. /// checking against this object.
#[allow(unused_mut)] //it's not unused #[allow(unused_mut)] //it's not unused
fn is_of_type(&self, mut test_class: Object<'gc>) -> Result<bool, Error> { fn is_of_type(
self.has_class_in_chain(test_class) &self,
mut test_class: Object<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<bool, Error> {
self.has_class_in_chain(test_class, activation)
} }
/// Determine if this object has a given class in its class object chain. /// Determine if this object has a given class in its class object chain.
/// ///
/// The given object `test_class` should be either a superclass or /// The given object `test_class` should be either a superclass or
/// interface we are checking against this object. /// interface we are checking against this object.
fn has_class_in_chain(&self, test_class: Object<'gc>) -> Result<bool, Error> { fn has_class_in_chain(
&self,
test_class: Object<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<bool, Error> {
let mut my_class = self.as_class_object(); let mut my_class = self.as_class_object();
// ES3 objects are not class instances but are still treated as
// instances of Object, which is an ES4 class.
if my_class.is_none() && Object::ptr_eq(test_class, activation.avm2().classes().object) {
return Ok(true);
}
while let Some(class) = my_class { while let Some(class) = my_class {
if Object::ptr_eq(class, test_class) { if Object::ptr_eq(class, test_class) {
return Ok(true); return Ok(true);

View File

@ -606,7 +606,7 @@ impl<'gc> Value<'gc> {
} }
if let Ok(object) = self.coerce_to_object(activation) { if let Ok(object) = self.coerce_to_object(activation) {
if object.is_of_type(class)? { if object.is_of_type(class, activation)? {
return Ok(object.into()); return Ok(object.into());
} }
} }
@ -686,7 +686,7 @@ impl<'gc> Value<'gc> {
} }
if let Ok(o) = self.coerce_to_object(activation) { if let Ok(o) = self.coerce_to_object(activation) {
o.is_of_type(type_object) o.is_of_type(type_object, activation)
} else { } else {
Ok(false) Ok(false)
} }