avm2: Remove `superclass_object` and related parameters from `TObject.call` and other downstream functions.

Turns out there's a *lot* of downstream functions.
This commit is contained in:
David Wendt 2021-10-23 22:48:48 -04:00 committed by Mike Welsh
parent 272b1784b8
commit cea3997396
30 changed files with 199 additions and 249 deletions

View File

@ -252,12 +252,7 @@ impl<'gc> Avm2<'gc> {
context: &mut UpdateContext<'_, 'gc, '_>, context: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut evt_activation = Activation::from_nothing(context.reborrow()); let mut evt_activation = Activation::from_nothing(context.reborrow());
callable.call( callable.call(reciever, args, &mut evt_activation)?;
reciever,
args,
&mut evt_activation,
reciever.and_then(|r| r.instance_of()),
)?;
Ok(()) Ok(())
} }

View File

@ -530,7 +530,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
}); });
let superclass_object = superclass_object?; let superclass_object = superclass_object?;
superclass_object.call_native_init(Some(receiver), args, self, Some(superclass_object)) superclass_object.call_native_init(Some(receiver), args, self)
} }
/// Attempts to lock the activation frame for execution. /// Attempts to lock the activation frame for execution.
@ -621,8 +621,11 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
self.return_value = Some(value); self.return_value = Some(value);
} }
/// Get the base prototype of the object that the currently executing /// Get the class that defined the currently-executing method, if it
/// method was retrieved from, if one exists. /// exists.
///
/// If the currently-executing method is not part of an ES4 class, then
/// this yields `None`.
pub fn subclass_object(&self) -> Option<ClassObject<'gc>> { pub fn subclass_object(&self) -> Option<ClassObject<'gc>> {
self.subclass_object self.subclass_object
} }
@ -1111,8 +1114,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
let args = self.context.avm2.pop_args(arg_count); let args = self.context.avm2.pop_args(arg_count);
let receiver = self.context.avm2.pop().coerce_to_object(self).ok(); let receiver = self.context.avm2.pop().coerce_to_object(self).ok();
let function = self.context.avm2.pop().coerce_to_object(self)?; let function = self.context.avm2.pop().coerce_to_object(self)?;
let superclass_object = receiver.and_then(|r| r.instance_of()); let value = function.call(receiver, &args, self)?;
let value = function.call(receiver, &args, self, superclass_object)?;
self.context.avm2.push(value); self.context.avm2.push(value);
@ -1163,7 +1165,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
let function = receiver let function = receiver
.get_property(receiver, &multiname, self)? .get_property(receiver, &multiname, self)?
.coerce_to_object(self)?; .coerce_to_object(self)?;
let value = function.call(None, &args, self, None)?; let value = function.call(None, &args, self)?;
self.context.avm2.push(value); self.context.avm2.push(value);
@ -1196,8 +1198,8 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
let method = self.table_method(method, index, false)?; let method = self.table_method(method, index, false)?;
// TODO: What scope should the function be executed with? // TODO: What scope should the function be executed with?
let scope = self.create_scopechain(); let scope = self.create_scopechain();
let function = FunctionObject::from_method(self, method.into(), scope, None); let function = FunctionObject::from_method(self, method.into(), scope, None, None);
let value = function.call(Some(receiver), &args, self, receiver.instance_of())?; let value = function.call(Some(receiver), &args, self)?;
self.context.avm2.push(value); self.context.avm2.push(value);

View File

@ -416,9 +416,8 @@ pub fn dispatch_event_to_target<'gc>(
} }
let object = activation.global_scope(); let object = activation.global_scope();
let superclass_object = object.and_then(|o| o.instance_of());
handler.call(object, &[event.into()], activation, superclass_object)?; handler.call(object, &[event.into()], activation)?;
} }
Ok(()) Ok(())

View File

@ -25,6 +25,13 @@ pub struct BytecodeExecutable<'gc> {
/// If `None`, then the receiver provided by the caller is used. A /// If `None`, then the receiver provided by the caller is used. A
/// `Some` value indicates a bound executable. /// `Some` value indicates a bound executable.
receiver: Option<Object<'gc>>, receiver: Option<Object<'gc>>,
/// The bound superclass for this method.
///
/// The `superclass` is the class that defined this method. If `None`,
/// then there is no defining superclass and `super` operations should fall
/// back to the `receiver`.
bound_superclass: Option<ClassObject<'gc>>,
} }
#[derive(Clone, Collect)] #[derive(Clone, Collect)]
@ -38,6 +45,13 @@ pub struct NativeExecutable<'gc> {
/// The bound reciever for this method. /// The bound reciever for this method.
bound_receiver: Option<Object<'gc>>, bound_receiver: Option<Object<'gc>>,
/// The bound superclass for this method.
///
/// The `superclass` is the class that defined this method. If `None`,
/// then there is no defining superclass and `super` operations should fall
/// back to the `receiver`.
bound_superclass: Option<ClassObject<'gc>>,
} }
/// Represents code that can be executed by some means. /// Represents code that can be executed by some means.
@ -57,6 +71,7 @@ impl<'gc> Executable<'gc> {
method: Method<'gc>, method: Method<'gc>,
scope: ScopeChain<'gc>, scope: ScopeChain<'gc>,
receiver: Option<Object<'gc>>, receiver: Option<Object<'gc>>,
superclass: Option<ClassObject<'gc>>,
mc: MutationContext<'gc, '_>, mc: MutationContext<'gc, '_>,
) -> Self { ) -> Self {
match method { match method {
@ -66,6 +81,7 @@ impl<'gc> Executable<'gc> {
method, method,
scope, scope,
bound_receiver: receiver, bound_receiver: receiver,
bound_superclass: superclass,
}, },
)), )),
Method::Bytecode(method) => Self::Action(Gc::allocate( Method::Bytecode(method) => Self::Action(Gc::allocate(
@ -74,6 +90,7 @@ impl<'gc> Executable<'gc> {
method, method,
scope, scope,
receiver, receiver,
bound_superclass: superclass,
}, },
)), )),
} }
@ -95,7 +112,6 @@ impl<'gc> Executable<'gc> {
unbound_receiver: Option<Object<'gc>>, unbound_receiver: Option<Object<'gc>>,
mut arguments: &[Value<'gc>], mut arguments: &[Value<'gc>],
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
subclass_object: Option<ClassObject<'gc>>,
callee: Object<'gc>, callee: Object<'gc>,
) -> Result<Value<'gc>, Error> { ) -> Result<Value<'gc>, Error> {
match self { match self {
@ -103,6 +119,7 @@ impl<'gc> Executable<'gc> {
let method = bm.method.method; let method = bm.method.method;
let receiver = bm.bound_receiver.or(unbound_receiver); let receiver = bm.bound_receiver.or(unbound_receiver);
let caller_domain = activation.caller_domain(); let caller_domain = activation.caller_domain();
let subclass_object = bm.bound_superclass;
let mut activation = Activation::from_builtin( let mut activation = Activation::from_builtin(
activation.context.reborrow(), activation.context.reborrow(),
receiver, receiver,
@ -138,6 +155,8 @@ impl<'gc> Executable<'gc> {
} }
let receiver = bm.receiver.or(unbound_receiver); let receiver = bm.receiver.or(unbound_receiver);
let subclass_object = bm.bound_superclass;
let mut activation = Activation::from_method( let mut activation = Activation::from_method(
activation.context.reborrow(), activation.context.reborrow(),
bm.method, bm.method,

View File

@ -298,7 +298,7 @@ fn function<'gc>(
let scope = activation.create_scopechain(); let scope = activation.create_scopechain();
let qname = QName::new(Namespace::package(package), name); let qname = QName::new(Namespace::package(package), name);
let method = Method::from_builtin(nf, name, mc); let method = Method::from_builtin(nf, name, mc);
let as3fn = FunctionObject::from_method(activation, method, scope, None).into(); let as3fn = FunctionObject::from_method(activation, method, scope, None, None).into();
domain.export_definition(qname.clone(), script, mc)?; domain.export_definition(qname.clone(), script, mc)?;
script script
.init() .init()

View File

@ -374,12 +374,7 @@ pub fn for_each<'gc>(
while let Some(r) = iter.next(activation) { while let Some(r) = iter.next(activation) {
let (i, item) = r?; let (i, item) = r?;
callback.call( callback.call(receiver, &[item, i.into(), this.into()], activation)?;
receiver,
&[item, i.into(), this.into()],
activation,
receiver.and_then(|r| r.instance_of()),
)?;
} }
} }
@ -409,12 +404,7 @@ pub fn map<'gc>(
while let Some(r) = iter.next(activation) { while let Some(r) = iter.next(activation) {
let (i, item) = r?; let (i, item) = r?;
let new_item = callback.call( let new_item = callback.call(receiver, &[item, i.into(), this.into()], activation)?;
receiver,
&[item, i.into(), this.into()],
activation,
receiver.and_then(|r| r.instance_of()),
)?;
new_array.push(new_item); new_array.push(new_item);
} }
@ -449,12 +439,7 @@ pub fn filter<'gc>(
while let Some(r) = iter.next(activation) { while let Some(r) = iter.next(activation) {
let (i, item) = r?; let (i, item) = r?;
let is_allowed = callback let is_allowed = callback
.call( .call(receiver, &[item.clone(), i.into(), this.into()], activation)?
receiver,
&[item.clone(), i.into(), this.into()],
activation,
receiver.and_then(|r| r.instance_of()),
)?
.coerce_to_boolean(); .coerce_to_boolean();
if is_allowed { if is_allowed {
@ -492,12 +477,7 @@ pub fn every<'gc>(
let (i, item) = r?; let (i, item) = r?;
let result = callback let result = callback
.call( .call(receiver, &[item, i.into(), this.into()], activation)?
receiver,
&[item, i.into(), this.into()],
activation,
receiver.and_then(|r| r.instance_of()),
)?
.coerce_to_boolean(); .coerce_to_boolean();
if !result { if !result {
@ -535,12 +515,7 @@ pub fn some<'gc>(
let (i, item) = r?; let (i, item) = r?;
let result = callback let result = callback
.call( .call(receiver, &[item, i.into(), this.into()], activation)?
receiver,
&[item, i.into(), this.into()],
activation,
receiver.and_then(|r| r.instance_of()),
)?
.coerce_to_boolean(); .coerce_to_boolean();
if result { if result {
@ -1078,7 +1053,7 @@ pub fn sort<'gc>(
options, options,
constrain(|activation, a, b| { constrain(|activation, a, b| {
let order = v let order = v
.call(None, &[a, b], activation, None)? .call(None, &[a, b], activation)?
.coerce_to_number(activation)?; .coerce_to_number(activation)?;
if order > 0.0 { if order > 0.0 {

View File

@ -34,6 +34,8 @@ pub fn class_init<'gc>(
.get_property(this, &QName::dynamic_name("prototype").into(), activation)? .get_property(this, &QName::dynamic_name("prototype").into(), activation)?
.coerce_to_object(activation)?; .coerce_to_object(activation)?;
let scope = activation.create_scopechain(); let scope = activation.create_scopechain();
let this_class = this.as_class_object().unwrap();
function_proto.install_dynamic_property( function_proto.install_dynamic_property(
activation.context.gc_context, activation.context.gc_context,
QName::new(Namespace::public(), "call"), QName::new(Namespace::public(), "call"),
@ -42,6 +44,7 @@ pub fn class_init<'gc>(
Method::from_builtin(call, "call", activation.context.gc_context), Method::from_builtin(call, "call", activation.context.gc_context),
scope, scope,
None, None,
Some(this_class),
) )
.into(), .into(),
)?; )?;
@ -53,6 +56,7 @@ pub fn class_init<'gc>(
Method::from_builtin(apply, "apply", activation.context.gc_context), Method::from_builtin(apply, "apply", activation.context.gc_context),
scope, scope,
None, None,
Some(this_class),
) )
.into(), .into(),
)?; )?;
@ -65,6 +69,7 @@ pub fn class_init<'gc>(
Method::from_builtin(call, "call", activation.context.gc_context), Method::from_builtin(call, "call", activation.context.gc_context),
scope, scope,
None, None,
Some(this_class),
) )
.into(), .into(),
)?; )?;
@ -76,6 +81,7 @@ pub fn class_init<'gc>(
Method::from_builtin(apply, "apply", activation.context.gc_context), Method::from_builtin(apply, "apply", activation.context.gc_context),
scope, scope,
None, None,
Some(this_class),
) )
.into(), .into(),
)?; )?;
@ -92,13 +98,12 @@ fn call<'gc>(
let this = args let this = args
.get(0) .get(0)
.and_then(|v| v.coerce_to_object(activation).ok()); .and_then(|v| v.coerce_to_object(activation).ok());
let base_proto = this.and_then(|that| that.instance_of());
if let Some(func) = func { if let Some(func) = func {
if args.len() > 1 { if args.len() > 1 {
Ok(func.call(this, &args[1..], activation, base_proto)?) Ok(func.call(this, &args[1..], activation)?)
} else { } else {
Ok(func.call(this, &[], activation, base_proto)?) Ok(func.call(this, &[], activation)?)
} }
} else { } else {
Err("Not a callable function".into()) Err("Not a callable function".into())
@ -114,7 +119,6 @@ fn apply<'gc>(
let this = args let this = args
.get(0) .get(0)
.and_then(|v| v.coerce_to_object(activation).ok()); .and_then(|v| v.coerce_to_object(activation).ok());
let base_proto = this.and_then(|that| that.instance_of());
if let Some(func) = func { if let Some(func) = func {
let arg_array = args let arg_array = args
@ -140,7 +144,7 @@ fn apply<'gc>(
Vec::new() Vec::new()
}; };
Ok(func.call(this, &resolved_args, activation, base_proto)?) Ok(func.call(this, &resolved_args, activation)?)
} else { } else {
Err("Not a callable function".into()) Err("Not a callable function".into())
} }

View File

@ -31,6 +31,7 @@ pub fn class_init<'gc>(
.coerce_to_object(activation)?; .coerce_to_object(activation)?;
let scope = activation.create_scopechain(); let scope = activation.create_scopechain();
let gc_context = activation.context.gc_context; let gc_context = activation.context.gc_context;
let this_class = this.as_class_object().unwrap();
object_proto.install_dynamic_property( object_proto.install_dynamic_property(
gc_context, gc_context,
@ -40,6 +41,7 @@ pub fn class_init<'gc>(
Method::from_builtin(has_own_property, "hasOwnProperty", gc_context), Method::from_builtin(has_own_property, "hasOwnProperty", gc_context),
scope, scope,
None, None,
Some(this_class),
) )
.into(), .into(),
)?; )?;
@ -51,6 +53,7 @@ pub fn class_init<'gc>(
Method::from_builtin(property_is_enumerable, "propertyIsEnumerable", gc_context), Method::from_builtin(property_is_enumerable, "propertyIsEnumerable", gc_context),
scope, scope,
None, None,
Some(this_class),
) )
.into(), .into(),
)?; )?;
@ -66,6 +69,7 @@ pub fn class_init<'gc>(
), ),
scope, scope,
None, None,
Some(this_class),
) )
.into(), .into(),
)?; )?;
@ -77,6 +81,7 @@ pub fn class_init<'gc>(
Method::from_builtin(is_prototype_of, "isPrototypeOf", gc_context), Method::from_builtin(is_prototype_of, "isPrototypeOf", gc_context),
scope, scope,
None, None,
Some(this_class),
) )
.into(), .into(),
)?; )?;
@ -88,6 +93,7 @@ pub fn class_init<'gc>(
Method::from_builtin(to_string, "toString", gc_context), Method::from_builtin(to_string, "toString", gc_context),
scope, scope,
None, None,
Some(this_class),
) )
.into(), .into(),
)?; )?;
@ -99,6 +105,7 @@ pub fn class_init<'gc>(
Method::from_builtin(to_locale_string, "toLocaleString", gc_context), Method::from_builtin(to_locale_string, "toLocaleString", gc_context),
scope, scope,
None, None,
Some(this_class),
) )
.into(), .into(),
)?; )?;
@ -110,6 +117,7 @@ pub fn class_init<'gc>(
Method::from_builtin(value_of, "valueOf", gc_context), Method::from_builtin(value_of, "valueOf", gc_context),
scope, scope,
None, None,
Some(this_class),
) )
.into(), .into(),
)?; )?;

View File

@ -74,6 +74,7 @@ pub fn class_init<'gc>(
let mut qname_proto = this let mut qname_proto = this
.get_property(this, &QName::dynamic_name("prototype").into(), activation)? .get_property(this, &QName::dynamic_name("prototype").into(), activation)?
.coerce_to_object(activation)?; .coerce_to_object(activation)?;
let this_class = this.as_class_object().unwrap();
qname_proto.set_property( qname_proto.set_property(
qname_proto, qname_proto,
@ -83,6 +84,7 @@ pub fn class_init<'gc>(
Method::from_builtin(to_string, "toString", activation.context.gc_context), Method::from_builtin(to_string, "toString", activation.context.gc_context),
scope, scope,
None, None,
Some(this_class),
) )
.into(), .into(),
activation, activation,
@ -96,6 +98,7 @@ pub fn class_init<'gc>(
Method::from_builtin(value_of, "valueOf", activation.context.gc_context), Method::from_builtin(value_of, "valueOf", activation.context.gc_context),
scope, scope,
None, None,
Some(this_class),
) )
.into(), .into(),
activation, activation,

View File

@ -425,12 +425,7 @@ pub fn every<'gc>(
let (i, item) = r?; let (i, item) = r?;
let result = callback let result = callback
.call( .call(receiver, &[item, i.into(), this.into()], activation)?
receiver,
&[item, i.into(), this.into()],
activation,
receiver.and_then(|r| r.instance_of()),
)?
.coerce_to_boolean(); .coerce_to_boolean();
if !result { if !result {
@ -468,12 +463,7 @@ pub fn some<'gc>(
let (i, item) = r?; let (i, item) = r?;
let result = callback let result = callback
.call( .call(receiver, &[item, i.into(), this.into()], activation)?
receiver,
&[item, i.into(), this.into()],
activation,
receiver.and_then(|r| r.instance_of()),
)?
.coerce_to_boolean(); .coerce_to_boolean();
if result { if result {
@ -519,12 +509,7 @@ pub fn filter<'gc>(
let (i, item) = r?; let (i, item) = r?;
let result = callback let result = callback
.call( .call(receiver, &[item.clone(), i.into(), this.into()], activation)?
receiver,
&[item.clone(), i.into(), this.into()],
activation,
receiver.and_then(|r| r.instance_of()),
)?
.coerce_to_boolean(); .coerce_to_boolean();
if result { if result {
@ -561,12 +546,7 @@ pub fn for_each<'gc>(
while let Some(r) = iter.next(activation) { while let Some(r) = iter.next(activation) {
let (i, item) = r?; let (i, item) = r?;
callback.call( callback.call(receiver, &[item, i.into(), this.into()], activation)?;
receiver,
&[item, i.into(), this.into()],
activation,
receiver.and_then(|r| r.instance_of()),
)?;
} }
} }
@ -686,12 +666,8 @@ pub fn map<'gc>(
while let Some(r) = iter.next(activation) { while let Some(r) = iter.next(activation) {
let (i, item) = r?; let (i, item) = r?;
let new_item = callback.call( let new_item =
receiver, callback.call(receiver, &[item.clone(), i.into(), this.into()], activation)?;
&[item.clone(), i.into(), this.into()],
activation,
receiver.and_then(|r| r.instance_of()),
)?;
let coerced_item = new_item.coerce_to_type(activation, value_type)?; let coerced_item = new_item.coerce_to_type(activation, value_type)?;
new_storage.push(coerced_item)?; new_storage.push(coerced_item)?;
@ -914,7 +890,7 @@ pub fn sort<'gc>(
let compare = move |activation: &mut Activation<'_, 'gc, '_>, a, b| { let compare = move |activation: &mut Activation<'_, 'gc, '_>, a, b| {
if let Some(compare_fnc) = compare_fnc { if let Some(compare_fnc) = compare_fnc {
let order = compare_fnc let order = compare_fnc
.call(Some(this), &[a, b], activation, None)? .call(Some(this), &[a, b], activation)?
.coerce_to_number(activation)?; .coerce_to_number(activation)?;
if order > 0.0 { if order > 0.0 {

View File

@ -394,38 +394,25 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
} }
let name = name.unwrap(); let name = name.unwrap();
let superclass_object = if let Some(c) = self.instance_of() {
c.find_class_for_trait(&name)?
} else {
None
};
if let Some(superclass_object) = superclass_object { if let Some(class) = self.instance_of() {
let mut traits = Vec::new(); if let Some((superclass, method_trait)) = class.instance_method(&name)? {
superclass_object let method = method_trait.as_method().unwrap();
.inner_class_definition()
.read()
.lookup_instance_traits(&name, &mut traits)?;
if let Some(method) = traits.into_iter().find_map(|t| match t.kind() {
TraitKind::Method { method, .. } => Some(method.clone()),
_ => None,
}) {
if !method.needs_arguments_object() { if !method.needs_arguments_object() {
let scope = superclass_object.instance_scope(); let scope = class.instance_scope();
return Executable::from_method( return Executable::from_method(
method, method,
scope, scope,
None, None,
Some(superclass),
activation.context.gc_context, activation.context.gc_context,
) )
.exec( .exec(
Some(self.into()), Some(self.into()),
arguments, arguments,
activation, activation,
Some(superclass_object), superclass.into(), //Deliberately invalid.
superclass_object.into(), //Deliberately invalid.
); );
} }
} }
@ -441,13 +428,13 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
method, method,
scope, scope,
None, None,
Some(class),
activation.context.gc_context, activation.context.gc_context,
) )
.exec( .exec(
Some(self.into()), Some(self.into()),
arguments, arguments,
activation, activation,
Some(class),
class.into(), //Deliberately invalid. class.into(), //Deliberately invalid.
); );
} }
@ -467,7 +454,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
function function
.unwrap() .unwrap()
.call(Some(self.into()), arguments, activation, superclass_object) .call(Some(self.into()), arguments, activation)
} }
/// Retrieve a slot by its index. /// Retrieve a slot by its index.
@ -542,12 +529,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
} }
if let Some(method_object) = self.base().get_method(id) { if let Some(method_object) = self.base().get_method(id) {
return method_object.call( return method_object.call(Some(self.into()), arguments, activation);
Some(self.into()),
arguments,
activation,
self.instance_of(),
);
} }
Err(format!("Cannot call unknown method id {}", id).into()) Err(format!("Cannot call unknown method id {}", id).into())
@ -864,6 +846,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
activation, activation,
class.read().instance_traits(), class.read().instance_traits(),
from_class_object.instance_scope(), from_class_object.instance_scope(),
Some(from_class_object),
)?; )?;
Ok(()) Ok(())
@ -881,9 +864,10 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
traits: &[Trait<'gc>], traits: &[Trait<'gc>],
scope: ScopeChain<'gc>, scope: ScopeChain<'gc>,
defining_class: Option<ClassObject<'gc>>,
) -> Result<(), Error> { ) -> Result<(), Error> {
for trait_entry in traits { for trait_entry in traits {
self.install_trait(activation, trait_entry, scope)?; self.install_trait(activation, trait_entry, scope, defining_class)?;
} }
Ok(()) Ok(())
@ -911,6 +895,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
trait_entry: &Trait<'gc>, trait_entry: &Trait<'gc>,
scope: ScopeChain<'gc>, scope: ScopeChain<'gc>,
defining_class: Option<ClassObject<'gc>>,
) -> Result<Value<'gc>, Error> { ) -> Result<Value<'gc>, Error> {
let receiver = (*self).into(); let receiver = (*self).into();
let trait_name = trait_entry.name().clone(); let trait_name = trait_entry.name().clone();
@ -972,8 +957,13 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
TraitKind::Getter { TraitKind::Getter {
disp_id, method, .. disp_id, method, ..
} => { } => {
let function = let function = FunctionObject::from_method(
FunctionObject::from_method(activation, method.clone(), scope, Some(receiver)); activation,
method.clone(),
scope,
Some(receiver),
defining_class,
);
self.install_getter( self.install_getter(
activation.context.gc_context, activation.context.gc_context,
trait_name, trait_name,
@ -987,8 +977,13 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
TraitKind::Setter { TraitKind::Setter {
disp_id, method, .. disp_id, method, ..
} => { } => {
let function = let function = FunctionObject::from_method(
FunctionObject::from_method(activation, method.clone(), scope, Some(receiver)); activation,
method.clone(),
scope,
Some(receiver),
defining_class,
);
self.install_setter( self.install_setter(
activation.context.gc_context, activation.context.gc_context,
trait_name, trait_name,
@ -1045,7 +1040,6 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
_reciever: Option<Object<'gc>>, _reciever: Option<Object<'gc>>,
_arguments: &[Value<'gc>], _arguments: &[Value<'gc>],
_activation: &mut Activation<'_, 'gc, '_>, _activation: &mut Activation<'_, 'gc, '_>,
_subclass_object: Option<ClassObject<'gc>>,
) -> Result<Value<'gc>, Error> { ) -> Result<Value<'gc>, Error> {
Err("Object is not callable".into()) Err("Object is not callable".into())
} }

View File

@ -68,7 +68,7 @@ impl<'gc> ArrayObject<'gc> {
.into(); .into();
instance.install_instance_traits(activation, class)?; instance.install_instance_traits(activation, class)?;
class.call_native_init(Some(instance), &[], activation, Some(class))?; class.call_native_init(Some(instance), &[], activation)?;
Ok(instance) Ok(instance)
} }

View File

@ -67,7 +67,7 @@ impl<'gc> BitmapDataObject<'gc> {
.write(activation.context.gc_context) .write(activation.context.gc_context)
.init_object2(instance.into()); .init_object2(instance.into());
instance.install_instance_traits(activation, class)?; instance.install_instance_traits(activation, class)?;
class.call_native_init(Some(instance.into()), &[], activation, Some(class))?; class.call_native_init(Some(instance.into()), &[], activation)?;
Ok(instance.into()) Ok(instance.into())
} }

View File

@ -59,7 +59,7 @@ impl<'gc> ByteArrayObject<'gc> {
.into(); .into();
instance.install_instance_traits(activation, class)?; instance.install_instance_traits(activation, class)?;
class.call_native_init(Some(instance), &[], activation, Some(class))?; class.call_native_init(Some(instance), &[], activation)?;
Ok(instance) Ok(instance)
} }

View File

@ -231,7 +231,12 @@ impl<'gc> ClassObject<'gc> {
)?; )?;
self.link_interfaces(activation)?; self.link_interfaces(activation)?;
self.install_traits(activation, class.read().class_traits(), self.class_scope())?; self.install_traits(
activation,
class.read().class_traits(),
self.class_scope(),
Some(self),
)?;
self.install_instance_traits(activation, class_class)?; self.install_instance_traits(activation, class_class)?;
self.run_class_initializer(activation)?; self.run_class_initializer(activation)?;
@ -327,15 +332,20 @@ impl<'gc> ClassObject<'gc> {
if !class_read.is_class_initialized() { if !class_read.is_class_initialized() {
let class_initializer = class_read.class_init(); let class_initializer = class_read.class_init();
let class_init_fn = let class_init_fn = FunctionObject::from_method(
FunctionObject::from_method(activation, class_initializer, scope, Some(object)); activation,
class_initializer,
scope,
Some(object),
Some(self),
);
drop(class_read); drop(class_read);
class class
.write(activation.context.gc_context) .write(activation.context.gc_context)
.mark_class_initialized(); .mark_class_initialized();
class_init_fn.call(Some(object), &[], activation, None)?; class_init_fn.call(Some(object), &[], activation)?;
} }
Ok(()) Ok(())
@ -440,23 +450,17 @@ impl<'gc> ClassObject<'gc> {
receiver: Option<Object<'gc>>, receiver: Option<Object<'gc>>,
arguments: &[Value<'gc>], arguments: &[Value<'gc>],
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
superclass_object: Option<ClassObject<'gc>>,
) -> Result<Value<'gc>, Error> { ) -> Result<Value<'gc>, Error> {
let scope = self.0.read().instance_scope; let scope = self.0.read().instance_scope;
let constructor = Executable::from_method( let constructor = Executable::from_method(
self.0.read().constructor.clone(), self.0.read().constructor.clone(),
scope, scope,
None, None,
Some(self),
activation.context.gc_context, activation.context.gc_context,
); );
constructor.exec( constructor.exec(receiver, arguments, activation, self.into())
receiver,
arguments,
activation,
superclass_object,
self.into(),
)
} }
/// Call the instance's native initializer. /// Call the instance's native initializer.
@ -469,23 +473,17 @@ impl<'gc> ClassObject<'gc> {
receiver: Option<Object<'gc>>, receiver: Option<Object<'gc>>,
arguments: &[Value<'gc>], arguments: &[Value<'gc>],
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
superclass_object: Option<ClassObject<'gc>>,
) -> Result<Value<'gc>, Error> { ) -> Result<Value<'gc>, Error> {
let scope = self.0.read().instance_scope; let scope = self.0.read().instance_scope;
let constructor = Executable::from_method( let constructor = Executable::from_method(
self.0.read().native_constructor.clone(), self.0.read().native_constructor.clone(),
scope, scope,
None, None,
Some(self),
activation.context.gc_context, activation.context.gc_context,
); );
constructor.exec( constructor.exec(receiver, arguments, activation, self.into())
receiver,
arguments,
activation,
superclass_object,
self.into(),
)
} }
/// Supercall a method defined in this class. /// Supercall a method defined in this class.
@ -547,15 +545,15 @@ impl<'gc> ClassObject<'gc> {
let scope = superclass_object.class_scope(); let scope = superclass_object.class_scope();
if let Some(TraitKind::Method { method, .. }) = base_trait.map(|b| b.kind()) { if let Some(TraitKind::Method { method, .. }) = base_trait.map(|b| b.kind()) {
let callee = let callee = FunctionObject::from_method(
FunctionObject::from_method(activation, method.clone(), scope, Some(reciever));
callee.call(
Some(reciever),
arguments,
activation, activation,
method.clone(),
scope,
Some(reciever),
Some(superclass_object), Some(superclass_object),
) );
callee.call(Some(reciever), arguments, activation)
} else { } else {
reciever.call_property(multiname, arguments, activation) reciever.call_property(multiname, arguments, activation)
} }
@ -619,10 +617,15 @@ impl<'gc> ClassObject<'gc> {
let scope = superclass_object.class_scope(); let scope = superclass_object.class_scope();
if let Some(TraitKind::Getter { method, .. }) = base_trait.map(|b| b.kind()) { if let Some(TraitKind::Getter { method, .. }) = base_trait.map(|b| b.kind()) {
let callee = let callee = FunctionObject::from_method(
FunctionObject::from_method(activation, method.clone(), scope, Some(reciever)); activation,
method.clone(),
scope,
Some(reciever),
Some(superclass_object),
);
callee.call(Some(reciever), &[], activation, Some(superclass_object)) callee.call(Some(reciever), &[], activation)
} else { } else {
reciever.get_property(reciever, multiname, activation) reciever.get_property(reciever, multiname, activation)
} }
@ -688,15 +691,15 @@ impl<'gc> ClassObject<'gc> {
let scope = superclass_object.class_scope(); let scope = superclass_object.class_scope();
if let Some(TraitKind::Setter { method, .. }) = base_trait.map(|b| b.kind()) { if let Some(TraitKind::Setter { method, .. }) = base_trait.map(|b| b.kind()) {
let callee = let callee = FunctionObject::from_method(
FunctionObject::from_method(activation, method.clone(), scope, Some(reciever));
callee.call(
Some(reciever),
&[value],
activation, activation,
method.clone(),
scope,
Some(reciever),
Some(superclass_object), Some(superclass_object),
)?; );
callee.call(Some(reciever), &[value], activation)?;
Ok(()) Ok(())
} else { } else {
@ -746,14 +749,20 @@ impl<'gc> ClassObject<'gc> {
receiver: Object<'gc>, receiver: Object<'gc>,
name: &QName<'gc>, name: &QName<'gc>,
) -> Result<Option<(Object<'gc>, u32, bool)>, Error> { ) -> Result<Option<(Object<'gc>, u32, bool)>, Error> {
if let Some((_superclass, method_trait)) = self.instance_method(name)? { if let Some((superclass, method_trait)) = self.instance_method(name)? {
let method = method_trait.as_method().unwrap(); let method = method_trait.as_method().unwrap();
let disp_id = method_trait.slot_id(); let disp_id = method_trait.slot_id();
let is_final = method_trait.is_final(); let is_final = method_trait.is_final();
let scope = self.instance_scope(); let scope = self.instance_scope();
Ok(Some(( Ok(Some((
FunctionObject::from_method(activation, method, scope, Some(receiver)), FunctionObject::from_method(
activation,
method,
scope,
Some(receiver),
Some(superclass),
),
disp_id, disp_id,
is_final, is_final,
))) )))
@ -782,20 +791,23 @@ impl<'gc> ClassObject<'gc> {
let superclassdef = superclass.inner_class_definition(); let superclassdef = superclass.inner_class_definition();
let traits = superclassdef.read().lookup_instance_traits_by_slot(id)?; let traits = superclassdef.read().lookup_instance_traits_by_slot(id)?;
if let Some((_superclass, method_trait)) = traits if let Some(method_trait) = traits.and_then(|t| match t.kind() {
.and_then(|t| match t.kind() { TraitKind::Method { .. } => Some(t),
TraitKind::Method { .. } => Some(t), _ => None,
_ => None, }) {
})
.map(|t| (superclass, t))
{
let name = method_trait.name().clone(); let name = method_trait.name().clone();
let method = method_trait.as_method().unwrap(); let method = method_trait.as_method().unwrap();
let is_final = method_trait.is_final(); let is_final = method_trait.is_final();
let scope = self.instance_scope(); let scope = self.instance_scope();
Ok(Some(( Ok(Some((
FunctionObject::from_method(activation, method, scope, Some(receiver)), FunctionObject::from_method(
activation,
method,
scope,
Some(receiver),
Some(superclass),
),
name, name,
is_final, is_final,
))) )))
@ -846,7 +858,13 @@ impl<'gc> ClassObject<'gc> {
let scope = self.class_scope(); let scope = self.class_scope();
Ok(Some(( Ok(Some((
FunctionObject::from_method(activation, method, scope, Some(self.into())), FunctionObject::from_method(
activation,
method,
scope,
Some(self.into()),
Some(self),
),
disp_id, disp_id,
is_final, is_final,
))) )))
@ -883,7 +901,13 @@ impl<'gc> ClassObject<'gc> {
let scope = self.class_scope(); let scope = self.class_scope();
Ok(Some(( Ok(Some((
FunctionObject::from_method(activation, method, scope, Some(self.into())), FunctionObject::from_method(
activation,
method,
scope,
Some(self.into()),
Some(self),
),
name, name,
is_final, is_final,
))) )))
@ -955,7 +979,6 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
_receiver: Option<Object<'gc>>, _receiver: Option<Object<'gc>>,
arguments: &[Value<'gc>], arguments: &[Value<'gc>],
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
_superclass_object: Option<ClassObject<'gc>>,
) -> Result<Value<'gc>, Error> { ) -> Result<Value<'gc>, Error> {
arguments arguments
.get(0) .get(0)
@ -982,7 +1005,7 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
instance.install_instance_traits(activation, self)?; instance.install_instance_traits(activation, self)?;
self.call_init(Some(instance), arguments, activation, Some(self))?; self.call_init(Some(instance), arguments, activation)?;
Ok(instance) Ok(instance)
} }
@ -1149,6 +1172,7 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
activation, activation,
parameterized_class.read().class_traits(), parameterized_class.read().class_traits(),
class_scope, class_scope,
Some(class_object),
)?; )?;
class_object.install_instance_traits(activation, class_class)?; class_object.install_instance_traits(activation, class_class)?;
class_object.run_class_initializer(activation)?; class_object.run_class_initializer(activation)?;

View File

@ -59,7 +59,7 @@ impl<'gc> DomainObject<'gc> {
.into(); .into();
this.install_instance_traits(activation, class)?; this.install_instance_traits(activation, class)?;
class.call_init(Some(this), &[], activation, Some(class))?; class.call_init(Some(this), &[], activation)?;
Ok(this) Ok(this)
} }

View File

@ -37,7 +37,7 @@ impl<'gc> FunctionObject<'gc> {
method: Method<'gc>, method: Method<'gc>,
scope: ScopeChain<'gc>, scope: ScopeChain<'gc>,
) -> Result<Object<'gc>, Error> { ) -> Result<Object<'gc>, Error> {
let mut this = Self::from_method(activation, method, scope, None); let mut this = Self::from_method(activation, method, scope, None, None);
let es3_proto = ScriptObject::object( let es3_proto = ScriptObject::object(
activation.context.gc_context, activation.context.gc_context,
activation.avm2().prototypes().object, activation.avm2().prototypes().object,
@ -63,12 +63,14 @@ impl<'gc> FunctionObject<'gc> {
method: Method<'gc>, method: Method<'gc>,
scope: ScopeChain<'gc>, scope: ScopeChain<'gc>,
receiver: Option<Object<'gc>>, receiver: Option<Object<'gc>>,
subclass_object: Option<ClassObject<'gc>>,
) -> Object<'gc> { ) -> Object<'gc> {
let fn_proto = activation.avm2().prototypes().function; let fn_proto = activation.avm2().prototypes().function;
let exec = Some(Executable::from_method( let exec = Some(Executable::from_method(
method, method,
scope, scope,
receiver, receiver,
subclass_object,
activation.context.gc_context, activation.context.gc_context,
)); ));
@ -117,16 +119,9 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
receiver: Option<Object<'gc>>, receiver: Option<Object<'gc>>,
arguments: &[Value<'gc>], arguments: &[Value<'gc>],
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
subclass_object: Option<ClassObject<'gc>>,
) -> Result<Value<'gc>, Error> { ) -> Result<Value<'gc>, Error> {
if let Some(exec) = &self.0.read().exec { if let Some(exec) = &self.0.read().exec {
exec.exec( exec.exec(receiver, arguments, activation, self.into())
receiver,
arguments,
activation,
subclass_object,
self.into(),
)
} else { } else {
Err("Not a callable function!".into()) Err("Not a callable function!".into())
} }
@ -148,7 +143,7 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
let instance = prototype.derive(activation)?; let instance = prototype.derive(activation)?;
self.call(Some(instance), arguments, activation, None)?; self.call(Some(instance), arguments, activation)?;
Ok(instance) Ok(instance)
} }

View File

@ -85,7 +85,7 @@ impl<'gc> LoaderInfoObject<'gc> {
.into(); .into();
this.install_instance_traits(activation, class)?; this.install_instance_traits(activation, class)?;
class.call_native_init(Some(this), &[], activation, Some(class))?; class.call_native_init(Some(this), &[], activation)?;
Ok(this) Ok(this)
} }
@ -106,7 +106,7 @@ impl<'gc> LoaderInfoObject<'gc> {
.into(); .into();
this.install_instance_traits(activation, class)?; this.install_instance_traits(activation, class)?;
class.call_native_init(Some(this), &[], activation, Some(class))?; class.call_native_init(Some(this), &[], activation)?;
Ok(this) Ok(this)
} }

View File

@ -59,7 +59,7 @@ impl<'gc> NamespaceObject<'gc> {
.into(); .into();
this.install_instance_traits(activation, class)?; this.install_instance_traits(activation, class)?;
class.call_native_init(Some(this), &[], activation, Some(class))?; class.call_native_init(Some(this), &[], activation)?;
Ok(this) Ok(this)
} }

View File

@ -59,7 +59,7 @@ impl<'gc> QNameObject<'gc> {
.into(); .into();
this.install_instance_traits(activation, class)?; this.install_instance_traits(activation, class)?;
class.call_native_init(Some(this), &[], activation, Some(class))?; class.call_native_init(Some(this), &[], activation)?;
Ok(this) Ok(this)
} }

View File

@ -57,7 +57,7 @@ impl<'gc> RegExpObject<'gc> {
.into(); .into();
this.install_instance_traits(activation, class)?; this.install_instance_traits(activation, class)?;
class.call_native_init(Some(this), &[], activation, Some(class))?; class.call_native_init(Some(this), &[], activation)?;
Ok(this) Ok(this)
} }

View File

@ -139,18 +139,12 @@ impl<'gc> ScriptObjectData<'gc> {
&self, &self,
receiver: Object<'gc>, receiver: Object<'gc>,
name: &QName<'gc>, name: &QName<'gc>,
activation: &mut Activation<'_, 'gc, '_>, _activation: &mut Activation<'_, 'gc, '_>,
) -> Result<ReturnValue<'gc>, Error> { ) -> Result<ReturnValue<'gc>, Error> {
let prop = self.values.get(name); let prop = self.values.get(name);
if let Some(prop) = prop { if let Some(prop) = prop {
prop.get( prop.get(receiver)
receiver,
// TODO: This used to also .unwrap_or(receiver),
// but this no longer can be done as it's not a ClassObject.
// Despite this, somehow, no tests fail.
activation.subclass_object().or_else(|| self.instance_of()),
)
} else { } else {
Ok(Value::Undefined.into()) Ok(Value::Undefined.into())
} }
@ -163,7 +157,6 @@ impl<'gc> ScriptObjectData<'gc> {
value: Value<'gc>, value: Value<'gc>,
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
) -> Result<ReturnValue<'gc>, Error> { ) -> Result<ReturnValue<'gc>, Error> {
let class = self.instance_of();
let slot_id = if let Some(prop) = self.values.get(name) { let slot_id = if let Some(prop) = self.values.get(name) {
if let Some(slot_id) = prop.slot_id() { if let Some(slot_id) = prop.slot_id() {
Some(slot_id) Some(slot_id)
@ -179,14 +172,7 @@ impl<'gc> ScriptObjectData<'gc> {
Ok(Value::Undefined.into()) Ok(Value::Undefined.into())
} else if self.values.contains_key(name) { } else if self.values.contains_key(name) {
let prop = self.values.get_mut(name).unwrap(); let prop = self.values.get_mut(name).unwrap();
prop.set( prop.set(receiver, value)
receiver,
// TODO: This used to also .unwrap_or(receiver),
// but this no longer can be done as it's not a ClassObject.
// Despite this, somehow, no tests fail.
activation.subclass_object().or(class),
value,
)
} else { } else {
//TODO: Not all classes are dynamic like this //TODO: Not all classes are dynamic like this
self.enumerants.push(name.clone()); self.enumerants.push(name.clone());
@ -204,20 +190,12 @@ impl<'gc> ScriptObjectData<'gc> {
value: Value<'gc>, value: Value<'gc>,
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
) -> Result<ReturnValue<'gc>, Error> { ) -> Result<ReturnValue<'gc>, Error> {
let class = self.instance_of();
if let Some(prop) = self.values.get_mut(name) { if let Some(prop) = self.values.get_mut(name) {
if let Some(slot_id) = prop.slot_id() { if let Some(slot_id) = prop.slot_id() {
self.init_slot(slot_id, value, activation.context.gc_context)?; self.init_slot(slot_id, value, activation.context.gc_context)?;
Ok(Value::Undefined.into()) Ok(Value::Undefined.into())
} else { } else {
prop.init( prop.init(receiver, value)
receiver,
// TODO: This used to also .unwrap_or(receiver),
// but this no longer can be done as it's not a ClassObject.
// Despite this, somehow, no tests fail.
activation.subclass_object().or(class),
value,
)
} }
} else { } else {
//TODO: Not all classes are dynamic like this //TODO: Not all classes are dynamic like this

View File

@ -70,7 +70,7 @@ impl<'gc> SoundObject<'gc> {
.into(); .into();
sound_object.install_instance_traits(activation, class)?; sound_object.install_instance_traits(activation, class)?;
class.call_native_init(Some(sound_object), &[], activation, Some(class))?; class.call_native_init(Some(sound_object), &[], activation)?;
Ok(sound_object) Ok(sound_object)
} }

View File

@ -73,7 +73,7 @@ impl<'gc> SoundChannelObject<'gc> {
)); ));
sound_object.install_instance_traits(activation, class)?; sound_object.install_instance_traits(activation, class)?;
class.call_native_init(Some(sound_object.into()), &[], activation, Some(class))?; class.call_native_init(Some(sound_object.into()), &[], activation)?;
Ok(sound_object) Ok(sound_object)
} }

View File

@ -90,7 +90,7 @@ impl<'gc> StageObject<'gc> {
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let this = Self::for_display_object(activation, display_object, class)?; let this = Self::for_display_object(activation, display_object, class)?;
class.call_native_init(Some(this.into()), &[], activation, Some(class))?; class.call_native_init(Some(this.into()), &[], activation)?;
Ok(this) Ok(this)
} }
@ -111,7 +111,7 @@ impl<'gc> StageObject<'gc> {
)); ));
this.install_instance_traits(activation, class)?; this.install_instance_traits(activation, class)?;
class.call_native_init(Some(this.into()), &[], activation, Some(class))?; class.call_native_init(Some(this.into()), &[], activation)?;
Ok(this) Ok(this)
} }

View File

@ -1,6 +1,6 @@
//! Property data structures //! Property data structures
use crate::avm2::object::{ClassObject, Object, TObject}; use crate::avm2::object::{Object, TObject};
use crate::avm2::return_value::ReturnValue; use crate::avm2::return_value::ReturnValue;
use crate::avm2::value::Value; use crate::avm2::value::Value;
use crate::avm2::Error; use crate::avm2::Error;
@ -164,18 +164,11 @@ impl<'gc> Property<'gc> {
/// ///
/// This function yields `ReturnValue` because some properties may be /// This function yields `ReturnValue` because some properties may be
/// user-defined. /// user-defined.
pub fn get( pub fn get(&self, this: Object<'gc>) -> Result<ReturnValue<'gc>, Error> {
&self,
this: Object<'gc>,
subclass_object: Option<ClassObject<'gc>>,
) -> Result<ReturnValue<'gc>, Error> {
match self { match self {
Property::Virtual { get: Some(get), .. } => Ok(ReturnValue::defer_execution( Property::Virtual { get: Some(get), .. } => {
*get, Ok(ReturnValue::defer_execution(*get, Some(this), vec![]))
Some(this), }
vec![],
subclass_object,
)),
Property::Virtual { get: None, .. } => Ok(Value::Undefined.into()), Property::Virtual { get: None, .. } => Ok(Value::Undefined.into()),
Property::Stored { value, .. } => Ok(value.to_owned().into()), Property::Stored { value, .. } => Ok(value.to_owned().into()),
@ -195,7 +188,6 @@ impl<'gc> Property<'gc> {
pub fn set( pub fn set(
&mut self, &mut self,
this: Object<'gc>, this: Object<'gc>,
subclass_object: Option<ClassObject<'gc>>,
new_value: impl Into<Value<'gc>>, new_value: impl Into<Value<'gc>>,
) -> Result<ReturnValue<'gc>, Error> { ) -> Result<ReturnValue<'gc>, Error> {
match self { match self {
@ -205,7 +197,6 @@ impl<'gc> Property<'gc> {
*function, *function,
Some(this), Some(this),
vec![new_value.into()], vec![new_value.into()],
subclass_object,
)); ));
} }
@ -239,7 +230,6 @@ impl<'gc> Property<'gc> {
pub fn init( pub fn init(
&mut self, &mut self,
this: Object<'gc>, this: Object<'gc>,
subclass_object: Option<ClassObject<'gc>>,
new_value: impl Into<Value<'gc>>, new_value: impl Into<Value<'gc>>,
) -> Result<ReturnValue<'gc>, Error> { ) -> Result<ReturnValue<'gc>, Error> {
match self { match self {
@ -249,7 +239,6 @@ impl<'gc> Property<'gc> {
*function, *function,
Some(this), Some(this),
vec![new_value.into()], vec![new_value.into()],
subclass_object,
)); ));
} }

View File

@ -1,7 +1,7 @@
//! Return value enum //! Return value enum
use crate::avm2::activation::Activation; use crate::avm2::activation::Activation;
use crate::avm2::object::{ClassObject, Object, TObject}; use crate::avm2::object::{Object, TObject};
use crate::avm2::{Error, Value}; use crate::avm2::{Error, Value};
use std::fmt; use std::fmt;
@ -40,7 +40,6 @@ pub enum ReturnValue<'gc> {
callee: Object<'gc>, callee: Object<'gc>,
unbound_reciever: Option<Object<'gc>>, unbound_reciever: Option<Object<'gc>>,
arguments: Vec<Value<'gc>>, arguments: Vec<Value<'gc>>,
subclass_object: Option<ClassObject<'gc>>,
}, },
} }
@ -52,13 +51,11 @@ impl fmt::Debug for ReturnValue<'_> {
callee, callee,
unbound_reciever, unbound_reciever,
arguments, arguments,
subclass_object,
} => f } => f
.debug_struct("ReturnValue") .debug_struct("ReturnValue")
.field("callee", callee) .field("callee", callee)
.field("unbound_reciever", unbound_reciever) .field("unbound_reciever", unbound_reciever)
.field("arguments", arguments) .field("arguments", arguments)
.field("subclass_object", subclass_object)
.finish(), .finish(),
} }
} }
@ -70,13 +67,11 @@ impl<'gc> ReturnValue<'gc> {
callee: Object<'gc>, callee: Object<'gc>,
unbound_reciever: Option<Object<'gc>>, unbound_reciever: Option<Object<'gc>>,
arguments: Vec<Value<'gc>>, arguments: Vec<Value<'gc>>,
subclass_object: Option<ClassObject<'gc>>,
) -> Self { ) -> Self {
Self::ResultOf { Self::ResultOf {
callee, callee,
unbound_reciever, unbound_reciever,
arguments, arguments,
subclass_object,
} }
} }
@ -91,12 +86,10 @@ impl<'gc> ReturnValue<'gc> {
callee, callee,
unbound_reciever, unbound_reciever,
arguments, arguments,
subclass_object,
} => callee.as_executable().unwrap().exec( } => callee.as_executable().unwrap().exec(
unbound_reciever, unbound_reciever,
&arguments, &arguments,
activation, activation,
subclass_object,
callee, callee,
), ),
} }

View File

@ -383,6 +383,7 @@ impl<'gc> Script<'gc> {
&mut null_activation, &mut null_activation,
&self.traits()?, &self.traits()?,
ScopeChain::new(domain), ScopeChain::new(domain),
None,
)?; )?;
Avm2::run_script_initializer(*self, context)?; Avm2::run_script_initializer(*self, context)?;

View File

@ -539,7 +539,7 @@ impl<'gc> TDisplayObject<'gc> for Avm2Button<'gc> {
if let Some(avm2_object) = avm2_object { if let Some(avm2_object) = avm2_object {
let mut constr_thing = || { let mut constr_thing = || {
let mut activation = Avm2Activation::from_nothing(context.reborrow()); let mut activation = Avm2Activation::from_nothing(context.reborrow());
class.call_native_init(Some(avm2_object), &[], &mut activation, Some(class))?; class.call_native_init(Some(avm2_object), &[], &mut activation)?;
Ok(()) Ok(())
}; };

View File

@ -1590,12 +1590,7 @@ impl<'gc> MovieClip<'gc> {
if let Avm2Value::Object(object) = self.object2() { if let Avm2Value::Object(object) = self.object2() {
let mut constr_thing = || { let mut constr_thing = || {
let mut activation = Avm2Activation::from_nothing(context.reborrow()); let mut activation = Avm2Activation::from_nothing(context.reborrow());
class_object.call_native_init( class_object.call_native_init(Some(object), &[], &mut activation)?;
Some(object),
&[],
&mut activation,
Some(class_object),
)?;
Ok(()) Ok(())
}; };