From 540a68fb683f3aae0415aceabd1b4b1e842611c0 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Tue, 23 Feb 2021 21:49:42 -0500 Subject: [PATCH] avm2: Grant each event it's own, separate broadcast list. --- core/src/avm2.rs | 31 +++++++++++++++--- .../globals/flash/events/eventdispatcher.rs | 4 +-- core/tests/regression_tests.rs | 1 + .../output.txt | 18 ++++++++++ .../test.fla | Bin 0 -> 5518 bytes .../test.swf | Bin 0 -> 1100 bytes 6 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 core/tests/swfs/avm2/movieclip_displayevents_dblhandler/output.txt create mode 100644 core/tests/swfs/avm2/movieclip_displayevents_dblhandler/test.fla create mode 100644 core/tests/swfs/avm2/movieclip_displayevents_dblhandler/test.swf diff --git a/core/src/avm2.rs b/core/src/avm2.rs index 64d608c14..93f911ccf 100644 --- a/core/src/avm2.rs +++ b/core/src/avm2.rs @@ -4,9 +4,11 @@ use crate::avm2::globals::SystemPrototypes; use crate::avm2::method::Method; use crate::avm2::object::EventObject; use crate::avm2::script::{Script, TranslationUnit}; +use crate::avm2::string::AvmString; use crate::context::UpdateContext; use crate::tag_utils::SwfSlice; use gc_arena::{Collect, MutationContext}; +use std::collections::HashMap; use std::rc::Rc; use swf::avm2::read::Reader; @@ -73,7 +75,7 @@ pub struct Avm2<'gc> { /// /// TODO: These should be weak object pointers, but our current garbage /// collector does not support weak references. - broadcast_list: Vec>, + broadcast_list: HashMap, Vec>>, #[cfg(feature = "avm_debug")] pub debug_output: bool, @@ -88,7 +90,7 @@ impl<'gc> Avm2<'gc> { stack: Vec::new(), globals, system_prototypes: None, - broadcast_list: Vec::new(), + broadcast_list: HashMap::new(), #[cfg(feature = "avm_debug")] debug_output: false, @@ -155,8 +157,15 @@ impl<'gc> Avm2<'gc> { pub fn register_broadcast_listener( context: &mut UpdateContext<'_, 'gc, '_>, object: Object<'gc>, + event_name: AvmString<'gc>, ) { - context.avm2.broadcast_list.push(object); + let bucket = context.avm2.broadcast_list.entry(event_name).or_default(); + + if bucket.iter().any(|x| Object::ptr_eq(*x, object)) { + return; + } + + bucket.push(object); } /// Dispatch an event on all objects in the current execution list. @@ -170,10 +179,22 @@ impl<'gc> Avm2<'gc> { event: Event<'gc>, on_class_proto: Object<'gc>, ) -> Result<(), Error> { - let el_length = context.avm2.broadcast_list.len(); + let event_name = event.event_type(); + let el_length = context + .avm2 + .broadcast_list + .entry(event_name) + .or_default() + .len(); for i in 0..el_length { - let object = context.avm2.broadcast_list.get(i).copied(); + let object = context + .avm2 + .broadcast_list + .get(&event_name) + .unwrap() + .get(i) + .copied(); if let Some(object) = object { if object.has_prototype_in_chain(on_class_proto, true)? { diff --git a/core/src/avm2/globals/flash/events/eventdispatcher.rs b/core/src/avm2/globals/flash/events/eventdispatcher.rs index 6b306bb4c..ff94eedf6 100644 --- a/core/src/avm2/globals/flash/events/eventdispatcher.rs +++ b/core/src/avm2/globals/flash/events/eventdispatcher.rs @@ -38,8 +38,6 @@ pub fn instance_init<'gc>( dispatch_list.into(), activation, )?; - - Avm2::register_broadcast_listener(&mut activation.context, this); } Ok(Value::Undefined) @@ -85,6 +83,8 @@ pub fn add_event_listener<'gc>( .as_dispatch_mut(activation.context.gc_context) .ok_or_else(|| Error::from("Internal properties should have what I put in them"))? .add_event_listener(event_type, priority, listener, use_capture); + + Avm2::register_broadcast_listener(&mut activation.context, this, event_type); } Ok(Value::Undefined) diff --git a/core/tests/regression_tests.rs b/core/tests/regression_tests.rs index 2e30521a6..0e5b8f18f 100644 --- a/core/tests/regression_tests.rs +++ b/core/tests/regression_tests.rs @@ -526,6 +526,7 @@ swf_tests! { (as3_movieclip_displayevents, "avm2/movieclip_displayevents", 9), (as3_movieclip_displayevents_timeline, "avm2/movieclip_displayevents_timeline", 5), (as3_movieclip_displayevents_looping, "avm2/movieclip_displayevents_looping", 5), + (as3_movieclip_displayevents_dblhandler, "avm2/movieclip_displayevents_dblhandler", 4), } // TODO: These tests have some inaccuracies currently, so we use approx_eq to test that numeric values are close enough. diff --git a/core/tests/swfs/avm2/movieclip_displayevents_dblhandler/output.txt b/core/tests/swfs/avm2/movieclip_displayevents_dblhandler/output.txt new file mode 100644 index 000000000..24ae1bac3 --- /dev/null +++ b/core/tests/swfs/avm2/movieclip_displayevents_dblhandler/output.txt @@ -0,0 +1,18 @@ +mc exitframe +root exitframe +root exitframe 2 +root enterframe +root enterframe 2 +mc enterframe +mc exitframe +root exitframe +root exitframe 2 +root enterframe +root enterframe 2 +mc enterframe +mc exitframe +root exitframe +root exitframe 2 +root enterframe +root enterframe 2 +mc enterframe \ No newline at end of file diff --git a/core/tests/swfs/avm2/movieclip_displayevents_dblhandler/test.fla b/core/tests/swfs/avm2/movieclip_displayevents_dblhandler/test.fla new file mode 100644 index 0000000000000000000000000000000000000000..42accba7d22fd01b7da87713b7233dab6334fb15 GIT binary patch literal 5518 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 S3d9{-neN!|&G{P<^L0i`eJaoZ literal 0 HcmV?d00001