Skip to content

Commit 39e6413

Browse files
Lord-McSweeneytorokati44
authored andcommitted
avm2: Use return value of Event.target getter to determine whether to clone when dispatching event
1 parent 32f6322 commit 39e6413

File tree

6 files changed

+50
-34
lines changed

6 files changed

+50
-34
lines changed

core/src/avm2/events.rs

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! Core event structure
22
33
use crate::avm2::activation::Activation;
4-
use crate::avm2::error::make_error_2007;
54
use crate::avm2::globals::slots::flash_events_event_dispatcher as slots;
65
use crate::avm2::object::{EventObject, Object, TObject};
76
use crate::avm2::value::Value;
@@ -73,9 +72,6 @@ pub struct Event<'gc> {
7372

7473
/// The name of the event being triggered.
7574
event_type: AvmString<'gc>,
76-
77-
/// Whether is event has been dispatched before.
78-
dispatched: bool,
7975
}
8076

8177
impl<'gc> Event<'gc> {
@@ -93,7 +89,6 @@ impl<'gc> Event<'gc> {
9389
event_phase: EventPhase::AtTarget,
9490
target: None,
9591
event_type: event_type.into(),
96-
dispatched: false,
9792
}
9893
}
9994

@@ -373,13 +368,14 @@ pub fn parent_of(target: Object<'_>) -> Option<Object<'_>> {
373368
fn dispatch_event_to_target<'gc>(
374369
activation: &mut Activation<'_, 'gc>,
375370
dispatcher: Object<'gc>,
376-
target: Object<'gc>,
371+
real_target: Object<'gc>,
372+
current_target: Object<'gc>,
377373
event: EventObject<'gc>,
378374
simulate_dispatch: bool,
379375
) -> Result<(), Error<'gc>> {
380376
avm_debug!(
381377
activation.context.avm2,
382-
"Event dispatch: {} to {target:?}",
378+
"Event dispatch: {} to {current_target:?}",
383379
event.event().event_type(),
384380
);
385381

@@ -402,10 +398,9 @@ fn dispatch_event_to_target<'gc>(
402398
.iter_event_handlers(name, use_capture)
403399
.collect();
404400

405-
evtmut.set_current_target(target);
406-
407401
if !handlers.is_empty() {
408-
evtmut.dispatched = true;
402+
evtmut.set_target(real_target);
403+
evtmut.set_current_target(current_target);
409404
}
410405

411406
drop(evtmut);
@@ -437,7 +432,7 @@ fn dispatch_event_to_target<'gc>(
437432
pub fn dispatch_event<'gc>(
438433
activation: &mut Activation<'_, 'gc>,
439434
this: Object<'gc>,
440-
event_object: EventObject<'gc>,
435+
event: EventObject<'gc>,
441436
simulate_dispatch: bool,
442437
) -> Result<bool, Error<'gc>> {
443438
let target = this.get_slot(slots::TARGET).as_object().unwrap_or(this);
@@ -455,23 +450,9 @@ pub fn dispatch_event<'gc>(
455450
parent = parent_dobj.parent();
456451
}
457452

458-
let dispatched = event_object.event().dispatched;
459-
460-
let event = if dispatched {
461-
Value::from(event_object)
462-
.call_public_property("clone", &[], activation)?
463-
.as_object()
464-
.ok_or_else(|| make_error_2007(activation, "event"))?
465-
.as_event_object()
466-
.expect("Event.clone should return an Event")
467-
} else {
468-
event_object
469-
};
470-
471453
let mut evtmut = event.event_mut(activation.gc());
472454

473455
evtmut.set_phase(EventPhase::Capturing);
474-
evtmut.set_target(target);
475456

476457
drop(evtmut);
477458

@@ -480,15 +461,22 @@ pub fn dispatch_event<'gc>(
480461
break;
481462
}
482463

483-
dispatch_event_to_target(activation, *ancestor, *ancestor, event, simulate_dispatch)?;
464+
dispatch_event_to_target(
465+
activation,
466+
*ancestor,
467+
target,
468+
*ancestor,
469+
event,
470+
simulate_dispatch,
471+
)?;
484472
}
485473

486474
event
487475
.event_mut(activation.gc())
488476
.set_phase(EventPhase::AtTarget);
489477

490478
if !event.event().is_propagation_stopped() {
491-
dispatch_event_to_target(activation, this, target, event, simulate_dispatch)?;
479+
dispatch_event_to_target(activation, this, target, target, event, simulate_dispatch)?;
492480
}
493481

494482
event
@@ -501,10 +489,17 @@ pub fn dispatch_event<'gc>(
501489
break;
502490
}
503491

504-
dispatch_event_to_target(activation, *ancestor, *ancestor, event, simulate_dispatch)?;
492+
dispatch_event_to_target(
493+
activation,
494+
*ancestor,
495+
target,
496+
*ancestor,
497+
event,
498+
simulate_dispatch,
499+
)?;
505500
}
506501
}
507502

508-
let handled = event.event().dispatched;
503+
let handled = event.event().target.is_some();
509504
Ok(handled)
510505
}

core/src/avm2/globals/flash/events/EventDispatcher.as

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,19 @@ package flash.events {
1212

1313
public native function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void;
1414
public native function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void;
15-
public native function dispatchEvent(event:Event):Boolean;
1615
public native function hasEventListener(type:String):Boolean;
16+
17+
public function dispatchEvent(event:Event):Boolean {
18+
// Some SWFs rely on the getter for `target` being called
19+
if (event.target) {
20+
return this.dispatchEventInternal(event.clone());
21+
} else {
22+
return this.dispatchEventInternal(event);
23+
}
24+
}
25+
26+
private native function dispatchEventInternal(event:Event):Boolean;
27+
1728
public native function willTrigger(type:String):Boolean;
1829

1930
public function toString():String {

core/src/avm2/globals/flash/events/event_dispatcher.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! `flash.events.EventDispatcher` builtin/prototype
22
33
use crate::avm2::activation::Activation;
4-
use crate::avm2::events::{dispatch_event as dispatch_event_internal, parent_of};
4+
use crate::avm2::events;
55
use crate::avm2::globals::slots::flash_events_event_dispatcher as slots;
66
use crate::avm2::object::{DispatchObject, Object, TObject};
77
use crate::avm2::parameters::ParametersExt;
@@ -111,15 +111,15 @@ pub fn will_trigger<'gc>(
111111

112112
let target = this.get_slot(slots::TARGET).as_object().unwrap_or(this);
113113

114-
if let Some(parent) = parent_of(target) {
114+
if let Some(parent) = events::parent_of(target) {
115115
return will_trigger(activation, Value::Object(parent), args);
116116
}
117117

118118
Ok(false.into())
119119
}
120120

121121
/// Implements `EventDispatcher.dispatchEvent`.
122-
pub fn dispatch_event<'gc>(
122+
pub fn dispatch_event_internal<'gc>(
123123
activation: &mut Activation<'_, 'gc>,
124124
this: Value<'gc>,
125125
args: &[Value<'gc>],
@@ -131,7 +131,7 @@ pub fn dispatch_event<'gc>(
131131
// AS3-side typing guarantees that the event is actually an Event
132132
let event = event.as_event_object().unwrap();
133133

134-
dispatch_event_internal(activation, this, event, false)?;
134+
events::dispatch_event(activation, this, event, false)?;
135135

136136
let not_canceled = !event.event().is_cancelled();
137137
Ok(not_canceled.into())
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
target before dispatch 1: null
2+
currentTarget before dispatch 1: null
3+
target after dispatch 1: null
4+
currentTarget after dispatch 1: null
5+
target before dispatch 2: null
6+
currentTarget before dispatch 2: null
7+
Dispatched!
8+
target after dispatch 2: [object EventDispatcher]
9+
currentTarget after dispatch 2: [object EventDispatcher]
644 Bytes
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
num_frames = 1

0 commit comments

Comments
 (0)