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.
|
/// Dispatch an event on an object.
|
||||||
///
|
///
|
||||||
/// This will become its own self-contained activation and swallow
|
/// 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.
|
/// Attempts to dispatch a non-event object will panic.
|
||||||
pub fn dispatch_event(
|
pub fn dispatch_event(
|
||||||
context: &mut UpdateContext<'_, 'gc>,
|
context: &mut UpdateContext<'_, 'gc>,
|
||||||
event: Object<'gc>,
|
event: Object<'gc>,
|
||||||
target: 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
|
let event_name = event
|
||||||
.as_event()
|
.as_event()
|
||||||
|
@ -445,7 +468,8 @@ impl<'gc> Avm2<'gc> {
|
||||||
.unwrap_or_else(|| panic!("cannot dispatch non-event object: {:?}", event));
|
.unwrap_or_else(|| panic!("cannot dispatch non-event object: {:?}", event));
|
||||||
|
|
||||||
let mut activation = Activation::from_nothing(context.reborrow());
|
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!(
|
tracing::error!(
|
||||||
"Encountered AVM2 error when dispatching `{}` event: {:?}",
|
"Encountered AVM2 error when dispatching `{}` event: {:?}",
|
||||||
event_name,
|
event_name,
|
||||||
|
@ -537,7 +561,8 @@ impl<'gc> Avm2<'gc> {
|
||||||
let mut activation = Activation::from_nothing(context.reborrow());
|
let mut activation = Activation::from_nothing(context.reborrow());
|
||||||
|
|
||||||
if object.is_of_type(on_type.inner_class_definition()) {
|
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!(
|
tracing::error!(
|
||||||
"Encountered AVM2 error when broadcasting `{}` event: {:?}",
|
"Encountered AVM2 error when broadcasting `{}` event: {:?}",
|
||||||
event_name,
|
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
|
/// `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
|
/// event's phase to match what targets you are dispatching to, or you will
|
||||||
/// call the wrong handlers.
|
/// call the wrong handlers.
|
||||||
pub fn dispatch_event_to_target<'gc>(
|
fn dispatch_event_to_target<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
dispatcher: Object<'gc>,
|
dispatcher: Object<'gc>,
|
||||||
target: Object<'gc>,
|
target: Object<'gc>,
|
||||||
event: Object<'gc>,
|
event: Object<'gc>,
|
||||||
|
simulate_dispatch: bool,
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
avm_debug!(
|
avm_debug!(
|
||||||
activation.context.avm2,
|
activation.context.avm2,
|
||||||
|
@ -413,6 +414,10 @@ pub fn dispatch_event_to_target<'gc>(
|
||||||
|
|
||||||
drop(evtmut);
|
drop(evtmut);
|
||||||
|
|
||||||
|
if simulate_dispatch {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
for handler in handlers.iter() {
|
for handler in handlers.iter() {
|
||||||
if event
|
if event
|
||||||
.as_event()
|
.as_event()
|
||||||
|
@ -441,6 +446,7 @@ pub fn dispatch_event<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
event: Object<'gc>,
|
event: Object<'gc>,
|
||||||
|
simulate_dispatch: bool,
|
||||||
) -> Result<bool, Error<'gc>> {
|
) -> Result<bool, Error<'gc>> {
|
||||||
let target = this
|
let target = this
|
||||||
.get_property(
|
.get_property(
|
||||||
|
@ -486,7 +492,7 @@ pub fn dispatch_event<'gc>(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch_event_to_target(activation, *ancestor, *ancestor, event)?;
|
dispatch_event_to_target(activation, *ancestor, *ancestor, event, simulate_dispatch)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
event
|
event
|
||||||
|
@ -495,7 +501,7 @@ pub fn dispatch_event<'gc>(
|
||||||
.set_phase(EventPhase::AtTarget);
|
.set_phase(EventPhase::AtTarget);
|
||||||
|
|
||||||
if !event.as_event().unwrap().is_propagation_stopped() {
|
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
|
event
|
||||||
|
@ -509,7 +515,7 @@ pub fn dispatch_event<'gc>(
|
||||||
break;
|
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());
|
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`.
|
/// Implements `EventDispatcher.toString`.
|
||||||
|
|
Loading…
Reference in New Issue