avm2: Add an option to simulate event dispatch
This commit is contained in:
parent
ebfff6aea1
commit
010310dd1b
|
@ -431,13 +431,36 @@ impl<'gc> Avm2<'gc> {
|
|||
/// Dispatch an event on an object.
|
||||
///
|
||||
/// This will become its own self-contained activation and swallow
|
||||
/// any resulting resulting error (after logging).
|
||||
/// any resulting error (after logging).
|
||||
///
|
||||
/// Attempts to dispatch a non-event object will panic.
|
||||
pub fn dispatch_event(
|
||||
context: &mut UpdateContext<'_, 'gc>,
|
||||
event: Object<'gc>,
|
||||
target: Object<'gc>,
|
||||
) {
|
||||
Self::dispatch_event_internal(context, event, target, false)
|
||||
}
|
||||
|
||||
/// Simulate dispatching an event.
|
||||
///
|
||||
/// This method is similar to [`Self::dispatch_event`],
|
||||
/// but it does not execute event handlers.
|
||||
///
|
||||
/// Returns `true` when the event would have been handled if not simulated.
|
||||
pub fn simulate_event_dispatch(
|
||||
context: &mut UpdateContext<'_, 'gc>,
|
||||
event: Object<'gc>,
|
||||
target: Object<'gc>,
|
||||
) {
|
||||
Self::dispatch_event_internal(context, event, target, true)
|
||||
}
|
||||
|
||||
fn dispatch_event_internal(
|
||||
context: &mut UpdateContext<'_, 'gc>,
|
||||
event: Object<'gc>,
|
||||
target: Object<'gc>,
|
||||
simulate_dispatch: bool,
|
||||
) {
|
||||
let event_name = event
|
||||
.as_event()
|
||||
|
@ -445,7 +468,8 @@ impl<'gc> Avm2<'gc> {
|
|||
.unwrap_or_else(|| panic!("cannot dispatch non-event object: {:?}", event));
|
||||
|
||||
let mut activation = Activation::from_nothing(context.reborrow());
|
||||
if let Err(err) = events::dispatch_event(&mut activation, target, event) {
|
||||
if let Err(err) = events::dispatch_event(&mut activation, target, event, simulate_dispatch)
|
||||
{
|
||||
tracing::error!(
|
||||
"Encountered AVM2 error when dispatching `{}` event: {:?}",
|
||||
event_name,
|
||||
|
@ -537,7 +561,8 @@ impl<'gc> Avm2<'gc> {
|
|||
let mut activation = Activation::from_nothing(context.reborrow());
|
||||
|
||||
if object.is_of_type(on_type.inner_class_definition()) {
|
||||
if let Err(err) = events::dispatch_event(&mut activation, object, event) {
|
||||
if let Err(err) = events::dispatch_event(&mut activation, object, event, false)
|
||||
{
|
||||
tracing::error!(
|
||||
"Encountered AVM2 error when broadcasting `{}` event: {:?}",
|
||||
event_name,
|
||||
|
|
|
@ -370,11 +370,12 @@ pub fn parent_of(target: Object<'_>) -> Option<Object<'_>> {
|
|||
/// `EventObject`, or this function will panic. You must have already set the
|
||||
/// event's phase to match what targets you are dispatching to, or you will
|
||||
/// call the wrong handlers.
|
||||
pub fn dispatch_event_to_target<'gc>(
|
||||
fn dispatch_event_to_target<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
dispatcher: Object<'gc>,
|
||||
target: Object<'gc>,
|
||||
event: Object<'gc>,
|
||||
simulate_dispatch: bool,
|
||||
) -> Result<(), Error<'gc>> {
|
||||
avm_debug!(
|
||||
activation.context.avm2,
|
||||
|
@ -413,6 +414,10 @@ pub fn dispatch_event_to_target<'gc>(
|
|||
|
||||
drop(evtmut);
|
||||
|
||||
if simulate_dispatch {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
for handler in handlers.iter() {
|
||||
if event
|
||||
.as_event()
|
||||
|
@ -441,6 +446,7 @@ pub fn dispatch_event<'gc>(
|
|||
activation: &mut Activation<'_, 'gc>,
|
||||
this: Object<'gc>,
|
||||
event: Object<'gc>,
|
||||
simulate_dispatch: bool,
|
||||
) -> Result<bool, Error<'gc>> {
|
||||
let target = this
|
||||
.get_property(
|
||||
|
@ -486,7 +492,7 @@ pub fn dispatch_event<'gc>(
|
|||
break;
|
||||
}
|
||||
|
||||
dispatch_event_to_target(activation, *ancestor, *ancestor, event)?;
|
||||
dispatch_event_to_target(activation, *ancestor, *ancestor, event, simulate_dispatch)?;
|
||||
}
|
||||
|
||||
event
|
||||
|
@ -495,7 +501,7 @@ pub fn dispatch_event<'gc>(
|
|||
.set_phase(EventPhase::AtTarget);
|
||||
|
||||
if !event.as_event().unwrap().is_propagation_stopped() {
|
||||
dispatch_event_to_target(activation, this, target, event)?;
|
||||
dispatch_event_to_target(activation, this, target, event, simulate_dispatch)?;
|
||||
}
|
||||
|
||||
event
|
||||
|
@ -509,7 +515,7 @@ pub fn dispatch_event<'gc>(
|
|||
break;
|
||||
}
|
||||
|
||||
dispatch_event_to_target(activation, *ancestor, *ancestor, event)?;
|
||||
dispatch_event_to_target(activation, *ancestor, *ancestor, event, simulate_dispatch)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ pub fn dispatch_event<'gc>(
|
|||
return Err("Dispatched Events must be subclasses of Event.".into());
|
||||
}
|
||||
|
||||
Ok(dispatch_event_internal(activation, this, event)?.into())
|
||||
Ok(dispatch_event_internal(activation, this, event, false)?.into())
|
||||
}
|
||||
|
||||
/// Implements `EventDispatcher.toString`.
|
||||
|
|
Loading…
Reference in New Issue