Skip to content

Commit

Permalink
avm2: Take EventObject instead of Value or Object in event handling code
Browse files Browse the repository at this point in the history
  • Loading branch information
Lord-McSweeney authored and Lord-McSweeney committed Dec 31, 2024
1 parent cf7b94e commit f4a3a61
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 34 deletions.
10 changes: 2 additions & 8 deletions core/src/avm2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,12 +444,7 @@ impl<'gc> Avm2<'gc> {
simulate_dispatch: bool,
) -> bool {
let mut activation = Activation::from_nothing(context);
match events::dispatch_event(
&mut activation,
target,
Value::from(event),
simulate_dispatch,
) {
match events::dispatch_event(&mut activation, target, event, simulate_dispatch) {
Err(err) => {
let event_name = event.event().event_type();

Expand Down Expand Up @@ -544,8 +539,7 @@ impl<'gc> Avm2<'gc> {
let mut activation = Activation::from_nothing(context);

if object.is_of_type(on_type.inner_class_definition()) {
if let Err(err) =
events::dispatch_event(&mut activation, object, Value::from(event), false)
if let Err(err) = events::dispatch_event(&mut activation, object, event, false)
{
tracing::error!(
"Encountered AVM2 error when broadcasting `{}` event: {:?}",
Expand Down
42 changes: 18 additions & 24 deletions core/src/avm2/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use crate::avm2::activation::Activation;
use crate::avm2::error::make_error_2007;
use crate::avm2::globals::slots::flash_events_event_dispatcher as slots;
use crate::avm2::object::{Object, TObject};
use crate::avm2::object::{EventObject, Object, TObject};
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::display_object::TDisplayObject;
Expand Down Expand Up @@ -374,13 +374,13 @@ fn dispatch_event_to_target<'gc>(
activation: &mut Activation<'_, 'gc>,
dispatcher: Object<'gc>,
target: Object<'gc>,
event: Object<'gc>,
event: EventObject<'gc>,
simulate_dispatch: bool,
) -> Result<(), Error<'gc>> {
avm_debug!(
activation.context.avm2,
"Event dispatch: {} to {target:?}",
event.as_event().unwrap().event_type(),
event.event().event_type(),
);

let dispatch_list = dispatcher.get_slot(slots::DISPATCH_LIST).as_object();
Expand All @@ -392,7 +392,7 @@ fn dispatch_event_to_target<'gc>(

let dispatch_list = dispatch_list.unwrap();

let mut evtmut = event.as_event_mut(activation.gc()).unwrap();
let mut evtmut = event.event_mut(activation.gc());
let name = evtmut.event_type();
let use_capture = evtmut.phase() == EventPhase::Capturing;

Expand All @@ -415,11 +415,7 @@ fn dispatch_event_to_target<'gc>(
}

for handler in handlers.iter() {
if event
.as_event()
.unwrap()
.is_propagation_stopped_immediately()
{
if event.event().is_propagation_stopped_immediately() {
break;
}

Expand All @@ -441,7 +437,7 @@ fn dispatch_event_to_target<'gc>(
pub fn dispatch_event<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
event: Value<'gc>,
event_object: EventObject<'gc>,
simulate_dispatch: bool,
) -> Result<bool, Error<'gc>> {
let target = this.get_slot(slots::TARGET).as_object().unwrap_or(this);
Expand All @@ -459,58 +455,56 @@ pub fn dispatch_event<'gc>(
parent = parent_dobj.parent();
}

let event_object = event.as_object().unwrap();

let dispatched = event_object.as_event().unwrap().dispatched;
let dispatched = event_object.event().dispatched;

let event = if dispatched {
event
Value::from(event_object)
.call_public_property("clone", &[], activation)?
.as_object()
.ok_or_else(|| make_error_2007(activation, "event"))?
.as_event_object()
.expect("Event.clone should return an Event")
} else {
event_object
};

let mut evtmut = event.as_event_mut(activation.gc()).unwrap();
let mut evtmut = event.event_mut(activation.gc());

evtmut.set_phase(EventPhase::Capturing);
evtmut.set_target(target);

drop(evtmut);

for ancestor in ancestor_list.iter().rev() {
if event.as_event().unwrap().is_propagation_stopped() {
if event.event().is_propagation_stopped() {
break;
}

dispatch_event_to_target(activation, *ancestor, *ancestor, event, simulate_dispatch)?;
}

event
.as_event_mut(activation.gc())
.unwrap()
.event_mut(activation.gc())
.set_phase(EventPhase::AtTarget);

if !event.as_event().unwrap().is_propagation_stopped() {
if !event.event().is_propagation_stopped() {
dispatch_event_to_target(activation, this, target, event, simulate_dispatch)?;
}

event
.as_event_mut(activation.gc())
.unwrap()
.event_mut(activation.context.gc_context)
.set_phase(EventPhase::Bubbling);

if event.as_event().unwrap().is_bubbling() {
if event.event().is_bubbling() {
for ancestor in ancestor_list.iter() {
if event.as_event().unwrap().is_propagation_stopped() {
if event.event().is_propagation_stopped() {
break;
}

dispatch_event_to_target(activation, *ancestor, *ancestor, event, simulate_dispatch)?;
}
}

let handled = event.as_event().unwrap().dispatched;
let handled = event.event().dispatched;
Ok(handled)
}
5 changes: 3 additions & 2 deletions core/src/avm2/globals/flash/events/event_dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,10 @@ pub fn dispatch_event<'gc>(
let event = args.get_object(activation, 0, "event")?;

// AS3-side typing guarantees that the event is actually an Event
let event = event.as_event_object().unwrap();

dispatch_event_internal(activation, this, event.into(), false)?;
dispatch_event_internal(activation, this, event, false)?;

let not_canceled = !event.as_event().unwrap().is_cancelled();
let not_canceled = !event.event().is_cancelled();
Ok(not_canceled.into())
}

0 comments on commit f4a3a61

Please sign in to comment.