avm1: Fix `this` inside watchers (#5276)

* fix: fix 'this' inside watchers

* tests: test value of 'this' in watcher

* lint: cargo fmt
This commit is contained in:
Chris Midgley 2021-09-11 13:15:16 +01:00 committed by GitHub
parent 9978eaa954
commit bd26790f5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 26 additions and 10 deletions

View File

@ -724,8 +724,9 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
name: &str, name: &str,
value: &mut Value<'gc>, value: &mut Value<'gc>,
this: Object<'gc>,
) -> Result<(), Error<'gc>> { ) -> Result<(), Error<'gc>> {
self.base.call_watcher(activation, name, value) self.base.call_watcher(activation, name, value, this)
} }
fn watch( fn watch(

View File

@ -161,9 +161,9 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
} }
let mut value = value; let mut value = value;
let watcher_result = self.call_watcher(activation, name, &mut value);
let this = (*self).into(); let this = (*self).into();
let watcher_result = self.call_watcher(activation, name, &mut value, this);
if !self.has_own_property(activation, name) { if !self.has_own_property(activation, name) {
// Before actually inserting a new property, we need to crawl the // Before actually inserting a new property, we need to crawl the
// prototype chain for virtual setters. // prototype chain for virtual setters.
@ -360,6 +360,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
name: &str, name: &str,
value: &mut Value<'gc>, value: &mut Value<'gc>,
this: Object<'gc>,
) -> Result<(), Error<'gc>>; ) -> Result<(), Error<'gc>>;
/// Set the 'watcher' of a given property. /// Set the 'watcher' of a given property.

View File

@ -186,8 +186,9 @@ impl<'gc> TObject<'gc> for ArrayObject<'gc> {
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
name: &str, name: &str,
value: &mut Value<'gc>, value: &mut Value<'gc>,
this: Object<'gc>,
) -> Result<(), Error<'gc>> { ) -> Result<(), Error<'gc>> {
self.0.read().call_watcher(activation, name, value) self.0.read().call_watcher(activation, name, value, this)
} }
fn watch( fn watch(

View File

@ -254,8 +254,9 @@ macro_rules! impl_custom_object {
activation: &mut crate::avm1::Activation<'_, 'gc, '_>, activation: &mut crate::avm1::Activation<'_, 'gc, '_>,
name: &str, name: &str,
value: &mut crate::avm1::Value<'gc>, value: &mut crate::avm1::Value<'gc>,
this: crate::avm1::object::Object<'gc>,
) -> Result<(), crate::avm1::Error<'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( fn watch(

View File

@ -319,6 +319,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
name: &str, name: &str,
value: &mut Value<'gc>, value: &mut Value<'gc>,
this: Object<'gc>,
) -> Result<(), Error<'gc>> { ) -> Result<(), Error<'gc>> {
let mut result = Ok(()); let mut result = Ok(());
let watcher = self let watcher = self
@ -329,7 +330,6 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
.cloned(); .cloned();
if let Some(watcher) = watcher { if let Some(watcher) = watcher {
let old_value = self.get_stored(name, activation)?; let old_value = self.get_stored(name, activation)?;
let this = (*self).into();
match watcher.call(activation, name, old_value, *value, this, Some(this)) { match watcher.call(activation, name, old_value, *value, this, Some(this)) {
Ok(v) => *value = v, Ok(v) => *value = v,
Err(Error::ThrownValue(e)) => { Err(Error::ThrownValue(e)) => {

View File

@ -333,8 +333,12 @@ impl<'gc> TObject<'gc> for StageObject<'gc> {
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
name: &str, name: &str,
value: &mut Value<'gc>, value: &mut Value<'gc>,
this: Object<'gc>,
) -> Result<(), Error<'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( fn watch(

View File

@ -181,8 +181,12 @@ impl<'gc> TObject<'gc> for SuperObject<'gc> {
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
name: &str, name: &str,
value: &mut Value<'gc>, value: &mut Value<'gc>,
this: Object<'gc>,
) -> Result<(), Error<'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( fn watch(

View File

@ -146,8 +146,9 @@ impl<'gc> TObject<'gc> for XmlAttributesObject<'gc> {
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
name: &str, name: &str,
value: &mut Value<'gc>, value: &mut Value<'gc>,
this: Object<'gc>,
) -> Result<(), Error<'gc>> { ) -> Result<(), Error<'gc>> {
self.base().call_watcher(activation, name, value) self.base().call_watcher(activation, name, value, this)
} }
fn watch( fn watch(

View File

@ -148,8 +148,9 @@ impl<'gc> TObject<'gc> for XmlIdMapObject<'gc> {
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
name: &str, name: &str,
value: &mut Value<'gc>, value: &mut Value<'gc>,
this: Object<'gc>,
) -> Result<(), Error<'gc>> { ) -> Result<(), Error<'gc>> {
self.base().call_watcher(activation, name, value) self.base().call_watcher(activation, name, value, this)
} }
fn watch( fn watch(

View File

@ -8,3 +8,5 @@ oldVal
undefined undefined
newVal newVal
hello hello
this
_level0.text_field