From bd26790f5b1bf02d87e100bc9563954de7012acf Mon Sep 17 00:00:00 2001 From: Chris Midgley Date: Sat, 11 Sep 2021 13:15:16 +0100 Subject: [PATCH] avm1: Fix `this` inside watchers (#5276) * fix: fix 'this' inside watchers * tests: test value of 'this' in watcher * lint: cargo fmt --- core/src/avm1/function.rs | 3 ++- core/src/avm1/object.rs | 5 +++-- core/src/avm1/object/array_object.rs | 3 ++- core/src/avm1/object/custom_object.rs | 3 ++- core/src/avm1/object/script_object.rs | 2 +- core/src/avm1/object/stage_object.rs | 6 +++++- core/src/avm1/object/super_object.rs | 6 +++++- core/src/avm1/object/xml_attributes_object.rs | 3 ++- core/src/avm1/object/xml_idmap_object.rs | 3 ++- .../swfs/avm1/watch_textfield/output.txt | 2 ++ .../tests/swfs/avm1/watch_textfield/test.fla | Bin 15872 -> 9216 bytes .../tests/swfs/avm1/watch_textfield/test.swf | Bin 265 -> 271 bytes 12 files changed, 26 insertions(+), 10 deletions(-) diff --git a/core/src/avm1/function.rs b/core/src/avm1/function.rs index 8c8340b4e..2d3e93dac 100644 --- a/core/src/avm1/function.rs +++ b/core/src/avm1/function.rs @@ -724,8 +724,9 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> { activation: &mut Activation<'_, 'gc, '_>, name: &str, value: &mut Value<'gc>, + this: Object<'gc>, ) -> Result<(), Error<'gc>> { - self.base.call_watcher(activation, name, value) + self.base.call_watcher(activation, name, value, this) } fn watch( diff --git a/core/src/avm1/object.rs b/core/src/avm1/object.rs index ebff3bcc9..d90dcd0c6 100644 --- a/core/src/avm1/object.rs +++ b/core/src/avm1/object.rs @@ -161,9 +161,9 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into> + Clone + Copy } let mut value = value; - let watcher_result = self.call_watcher(activation, name, &mut value); - let this = (*self).into(); + let watcher_result = self.call_watcher(activation, name, &mut value, this); + if !self.has_own_property(activation, name) { // Before actually inserting a new property, we need to crawl the // prototype chain for virtual setters. @@ -360,6 +360,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into> + Clone + Copy activation: &mut Activation<'_, 'gc, '_>, name: &str, value: &mut Value<'gc>, + this: Object<'gc>, ) -> Result<(), Error<'gc>>; /// Set the 'watcher' of a given property. diff --git a/core/src/avm1/object/array_object.rs b/core/src/avm1/object/array_object.rs index 02dfbadc8..4e4e11cca 100644 --- a/core/src/avm1/object/array_object.rs +++ b/core/src/avm1/object/array_object.rs @@ -186,8 +186,9 @@ impl<'gc> TObject<'gc> for ArrayObject<'gc> { activation: &mut Activation<'_, 'gc, '_>, name: &str, value: &mut Value<'gc>, + this: Object<'gc>, ) -> Result<(), Error<'gc>> { - self.0.read().call_watcher(activation, name, value) + self.0.read().call_watcher(activation, name, value, this) } fn watch( diff --git a/core/src/avm1/object/custom_object.rs b/core/src/avm1/object/custom_object.rs index 2d67b1d49..f2811cbc1 100644 --- a/core/src/avm1/object/custom_object.rs +++ b/core/src/avm1/object/custom_object.rs @@ -254,8 +254,9 @@ macro_rules! impl_custom_object { activation: &mut crate::avm1::Activation<'_, 'gc, '_>, name: &str, value: &mut crate::avm1::Value<'gc>, + this: crate::avm1::object::Object<'gc>, ) -> Result<(), crate::avm1::Error<'gc>> { - self.0.read().$field.call_watcher(activation, name, value) + self.0.read().$field.call_watcher(activation, name, value, this) } fn watch( diff --git a/core/src/avm1/object/script_object.rs b/core/src/avm1/object/script_object.rs index 89396a9cf..9ab0e22bf 100644 --- a/core/src/avm1/object/script_object.rs +++ b/core/src/avm1/object/script_object.rs @@ -319,6 +319,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> { activation: &mut Activation<'_, 'gc, '_>, name: &str, value: &mut Value<'gc>, + this: Object<'gc>, ) -> Result<(), Error<'gc>> { let mut result = Ok(()); let watcher = self @@ -329,7 +330,6 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> { .cloned(); if let Some(watcher) = watcher { let old_value = self.get_stored(name, activation)?; - let this = (*self).into(); match watcher.call(activation, name, old_value, *value, this, Some(this)) { Ok(v) => *value = v, Err(Error::ThrownValue(e)) => { diff --git a/core/src/avm1/object/stage_object.rs b/core/src/avm1/object/stage_object.rs index dad0b90fd..992eccb2b 100644 --- a/core/src/avm1/object/stage_object.rs +++ b/core/src/avm1/object/stage_object.rs @@ -333,8 +333,12 @@ impl<'gc> TObject<'gc> for StageObject<'gc> { activation: &mut Activation<'_, 'gc, '_>, name: &str, value: &mut Value<'gc>, + this: Object<'gc>, ) -> Result<(), Error<'gc>> { - self.0.read().base.call_watcher(activation, name, value) + self.0 + .read() + .base + .call_watcher(activation, name, value, this) } fn watch( diff --git a/core/src/avm1/object/super_object.rs b/core/src/avm1/object/super_object.rs index 0afc74ad5..bd2288478 100644 --- a/core/src/avm1/object/super_object.rs +++ b/core/src/avm1/object/super_object.rs @@ -181,8 +181,12 @@ impl<'gc> TObject<'gc> for SuperObject<'gc> { activation: &mut Activation<'_, 'gc, '_>, name: &str, value: &mut Value<'gc>, + this: Object<'gc>, ) -> Result<(), Error<'gc>> { - self.0.read().this.call_watcher(activation, name, value) + self.0 + .read() + .this + .call_watcher(activation, name, value, this) } fn watch( diff --git a/core/src/avm1/object/xml_attributes_object.rs b/core/src/avm1/object/xml_attributes_object.rs index 67f4ff7af..8c786c6a2 100644 --- a/core/src/avm1/object/xml_attributes_object.rs +++ b/core/src/avm1/object/xml_attributes_object.rs @@ -146,8 +146,9 @@ impl<'gc> TObject<'gc> for XmlAttributesObject<'gc> { activation: &mut Activation<'_, 'gc, '_>, name: &str, value: &mut Value<'gc>, + this: Object<'gc>, ) -> Result<(), Error<'gc>> { - self.base().call_watcher(activation, name, value) + self.base().call_watcher(activation, name, value, this) } fn watch( diff --git a/core/src/avm1/object/xml_idmap_object.rs b/core/src/avm1/object/xml_idmap_object.rs index 92baba373..7d931584a 100644 --- a/core/src/avm1/object/xml_idmap_object.rs +++ b/core/src/avm1/object/xml_idmap_object.rs @@ -148,8 +148,9 @@ impl<'gc> TObject<'gc> for XmlIdMapObject<'gc> { activation: &mut Activation<'_, 'gc, '_>, name: &str, value: &mut Value<'gc>, + this: Object<'gc>, ) -> Result<(), Error<'gc>> { - self.base().call_watcher(activation, name, value) + self.base().call_watcher(activation, name, value, this) } fn watch( diff --git a/tests/tests/swfs/avm1/watch_textfield/output.txt b/tests/tests/swfs/avm1/watch_textfield/output.txt index e11a90170..3bce70e5d 100644 --- a/tests/tests/swfs/avm1/watch_textfield/output.txt +++ b/tests/tests/swfs/avm1/watch_textfield/output.txt @@ -8,3 +8,5 @@ oldVal undefined newVal hello +this +_level0.text_field \ No newline at end of file diff --git a/tests/tests/swfs/avm1/watch_textfield/test.fla b/tests/tests/swfs/avm1/watch_textfield/test.fla index 60e17b80e49b636fc07ea5787011ddc4bf036c8b..6f09c913c25884a57b887a2850603dad76f3d531 100644 GIT binary patch delta 147 zcmZpuY4Dg}puofc1p*8VEI=kB5dZuC|365S8HhJKa%^DS#FWFrHz7(hlWF;NMpm%Y zscIk-5O5gNjQ8dgFSFJO`bDVBQ=RSW?B CWHXNd diff --git a/tests/tests/swfs/avm1/watch_textfield/test.swf b/tests/tests/swfs/avm1/watch_textfield/test.swf index da142d5739137f8a0fbdf4f11064209e2bed3170..62299616e73e62882da9d8310a6ac8f951c4037b 100644 GIT binary patch literal 271 zcmV+q0r37qS5pS30RRAaoNZ7$PQySHoL$?=8mv&zx>#)y83`pP06XFUNEEb@V=vfZ zg{@#I>8OyXDbmouNhrBY?qK$Vk_fTI%+9=dPfu@+U=Eyo01?3z?fX9UCIonWLxdt% zN|xNvA}=1$E}IsODsOXzN4YZ8RrM35Q{KsSH@~Z;DkrPFE2=~oN1X4P&#)U~D%dx` zHvAc4zWjoVN-EU|Si(Es5ApunW`+#~!`L8k7+azao$wqw;XC||#g~QxD+ci<1RD-1 z0LEftg*UcxWKmnbuCwE7q|r!+2z(OEmbG346wjf6;rng+y^Y$Jgdo$0MGyB9xI=sm VPPG~n9UXmU2WQE&{R7O`VlMizdr1HQ literal 265 zcmV+k0rvhwS5pR+0RRAaoNZ7&Ps1<}eRh)8fv5~!Jy;&9AR)T2LW1}KNF7+KkeIf@ zB2g8o-I$PASi7*mFJa`*^gpEjKrKRec<=7LyR&_3L{s4814syNXxDXFzzOjBhGUe4 z)~XVg?u+sf&9ZJ#>*}u1cv34%ohQf^~3cfNS_O z#D?Nh$hp$GmT-i3aTpT(_mB&0C>TZ-iAU~;dh|))@yFp;mO__Ad=rE9`V;``b1Sil zb7F@^3XRW>ZjmJeQ$!Gw=z6&@cZ1?NmashAX5ZVSc}WR!vqp6ACx!p}S8r&t5izBM P&-~XWawG2mMC4wW&bfo<