From f4ab57d6e0997ce157bf899cfe212c5e971a325c Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Wed, 22 Jul 2020 22:43:55 +0200 Subject: [PATCH] avm1: Make property watchers take Object, not Executable, so we can track the callee --- core/src/avm1/function.rs | 2 +- core/src/avm1/globals/object.rs | 17 ++++------- core/src/avm1/object.rs | 2 +- core/src/avm1/object/custom_object.rs | 2 +- core/src/avm1/object/script_object.rs | 28 +++++++++++-------- core/src/avm1/object/stage_object.rs | 2 +- core/src/avm1/object/super_object.rs | 2 +- core/src/avm1/object/xml_attributes_object.rs | 2 +- core/src/avm1/object/xml_idmap_object.rs | 2 +- 9 files changed, 29 insertions(+), 30 deletions(-) diff --git a/core/src/avm1/function.rs b/core/src/avm1/function.rs index 220d72419..60b66a207 100644 --- a/core/src/avm1/function.rs +++ b/core/src/avm1/function.rs @@ -619,7 +619,7 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> { activation: &mut Activation<'_, 'gc>, gc_context: MutationContext<'gc, '_>, name: Cow, - callback: Executable<'gc>, + callback: Object<'gc>, user_data: Value<'gc>, ) { self.base diff --git a/core/src/avm1/globals/object.rs b/core/src/avm1/globals/object.rs index c8bcc3da3..a59562d85 100644 --- a/core/src/avm1/globals/object.rs +++ b/core/src/avm1/globals/object.rs @@ -174,18 +174,13 @@ fn watch<'gc>( } else { return Ok(false.into()); }; - let callback = if let Some(callback) = args.get(1) { - if let Some(callback) = callback - .coerce_to_object(activation, context) - .as_executable() - { - callback - } else { - return Ok(false.into()); - } - } else { + let callback = args + .get(1) + .unwrap_or(&Value::Undefined) + .coerce_to_object(activation, context); + if callback.as_executable().is_none() { return Ok(false.into()); - }; + } let user_data = args.get(2).cloned().unwrap_or(Value::Undefined); this.set_watcher( diff --git a/core/src/avm1/object.rs b/core/src/avm1/object.rs index bab78b166..4628f2e3c 100644 --- a/core/src/avm1/object.rs +++ b/core/src/avm1/object.rs @@ -279,7 +279,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into> + Clone + Copy activation: &mut Activation<'_, 'gc>, gc_context: MutationContext<'gc, '_>, name: Cow, - callback: Executable<'gc>, + callback: Object<'gc>, user_data: Value<'gc>, ); diff --git a/core/src/avm1/object/custom_object.rs b/core/src/avm1/object/custom_object.rs index 6a0cd19ec..31ca3cc4c 100644 --- a/core/src/avm1/object/custom_object.rs +++ b/core/src/avm1/object/custom_object.rs @@ -240,7 +240,7 @@ macro_rules! impl_custom_object_without_set { activation: &mut crate::avm1::Activation<'_, 'gc>, gc_context: gc_arena::MutationContext<'gc, '_>, name: std::borrow::Cow, - callback: crate::avm1::function::Executable<'gc>, + callback: crate::avm1::object::Object<'gc>, user_data: crate::avm1::Value<'gc>, ) { self.0 diff --git a/core/src/avm1/object/script_object.rs b/core/src/avm1/object/script_object.rs index 780a3bce9..9e7740a1a 100644 --- a/core/src/avm1/object/script_object.rs +++ b/core/src/avm1/object/script_object.rs @@ -21,12 +21,12 @@ pub enum ArrayStorage<'gc> { #[derive(Debug, Clone, Collect)] #[collect(no_drop)] pub struct Watcher<'gc> { - callback: Executable<'gc>, + callback: Object<'gc>, user_data: Value<'gc>, } impl<'gc> Watcher<'gc> { - pub fn new(callback: Executable<'gc>, user_data: Value<'gc>) -> Self { + pub fn new(callback: Object<'gc>, user_data: Value<'gc>) -> Self { Self { callback, user_data, @@ -50,15 +50,19 @@ impl<'gc> Watcher<'gc> { new_value, self.user_data.clone(), ]; - self.callback.exec( - name, - activation, - context, - this, - base_proto, - &args, - ExecutionReason::Special, - ) + if let Some(executable) = self.callback.as_executable() { + executable.exec( + name, + activation, + context, + this, + base_proto, + &args, + ExecutionReason::Special, + ) + } else { + Ok(Value::Undefined) + } } } @@ -564,7 +568,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> { activation: &mut Activation<'_, 'gc>, gc_context: MutationContext<'gc, '_>, name: Cow, - callback: Executable<'gc>, + callback: Object<'gc>, user_data: Value<'gc>, ) { self.0.write(gc_context).watchers.insert( diff --git a/core/src/avm1/object/stage_object.rs b/core/src/avm1/object/stage_object.rs index 7586a73f4..fe3df0102 100644 --- a/core/src/avm1/object/stage_object.rs +++ b/core/src/avm1/object/stage_object.rs @@ -337,7 +337,7 @@ impl<'gc> TObject<'gc> for StageObject<'gc> { activation: &mut Activation<'_, 'gc>, gc_context: MutationContext<'gc, '_>, name: Cow, - callback: Executable<'gc>, + callback: Object<'gc>, user_data: Value<'gc>, ) { self.0 diff --git a/core/src/avm1/object/super_object.rs b/core/src/avm1/object/super_object.rs index dcb6d6d5a..952e52bf5 100644 --- a/core/src/avm1/object/super_object.rs +++ b/core/src/avm1/object/super_object.rs @@ -242,7 +242,7 @@ impl<'gc> TObject<'gc> for SuperObject<'gc> { _activation: &mut Activation<'_, 'gc>, _gc_context: MutationContext<'gc, '_>, _name: Cow, - _callback: Executable<'gc>, + _callback: Object<'gc>, _user_data: Value<'gc>, ) { //`super` cannot have properties defined on it diff --git a/core/src/avm1/object/xml_attributes_object.rs b/core/src/avm1/object/xml_attributes_object.rs index 41c8274b3..43821f59d 100644 --- a/core/src/avm1/object/xml_attributes_object.rs +++ b/core/src/avm1/object/xml_attributes_object.rs @@ -162,7 +162,7 @@ impl<'gc> TObject<'gc> for XMLAttributesObject<'gc> { activation: &mut Activation<'_, 'gc>, gc_context: MutationContext<'gc, '_>, name: Cow, - callback: Executable<'gc>, + callback: Object<'gc>, user_data: Value<'gc>, ) { self.base() diff --git a/core/src/avm1/object/xml_idmap_object.rs b/core/src/avm1/object/xml_idmap_object.rs index d0394b135..0ba666ae0 100644 --- a/core/src/avm1/object/xml_idmap_object.rs +++ b/core/src/avm1/object/xml_idmap_object.rs @@ -160,7 +160,7 @@ impl<'gc> TObject<'gc> for XMLIDMapObject<'gc> { activation: &mut Activation<'_, 'gc>, gc_context: MutationContext<'gc, '_>, name: Cow, - callback: Executable<'gc>, + callback: Object<'gc>, user_data: Value<'gc>, ) { self.base()