Skip to content

Commit

Permalink
avm2: Make EventObject creation functions return an EventObject
Browse files Browse the repository at this point in the history
  • Loading branch information
Lord-McSweeney authored and Lord-McSweeney committed Jan 14, 2025
1 parent bcc2d08 commit 13fb442
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 47 deletions.
34 changes: 15 additions & 19 deletions core/src/avm2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ impl<'gc> Avm2<'gc> {
/// Returns `true` if the event has been handled.
pub fn dispatch_event(
context: &mut UpdateContext<'gc>,
event: Value<'gc>,
event: EventObject<'gc>,
target: Object<'gc>,
) -> bool {
Self::dispatch_event_internal(context, event, target, false)
Expand All @@ -431,28 +431,28 @@ impl<'gc> Avm2<'gc> {
/// Returns `true` when the event would have been handled if not simulated.
pub fn simulate_event_dispatch(
context: &mut UpdateContext<'gc>,
event: Value<'gc>,
event: EventObject<'gc>,
target: Object<'gc>,
) -> bool {
Self::dispatch_event_internal(context, event, target, true)
}

fn dispatch_event_internal(
context: &mut UpdateContext<'gc>,
event: Value<'gc>,
event: EventObject<'gc>,
target: Object<'gc>,
simulate_dispatch: bool,
) -> bool {
let event_name = event
.as_object()
.unwrap()
.as_event()
.map(|e| e.event_type())
.expect("Cannot dispatch non-event object");

let mut activation = Activation::from_nothing(context);
match events::dispatch_event(&mut activation, target, event, simulate_dispatch) {
match events::dispatch_event(
&mut activation,
target,
Value::from(event),
simulate_dispatch,
) {
Err(err) => {
let event_name = event.event().event_type();

tracing::error!(
"Encountered AVM2 error when dispatching `{}` event: {:?}",
event_name,
Expand Down Expand Up @@ -512,15 +512,10 @@ impl<'gc> Avm2<'gc> {
/// Attempts to broadcast a non-event object will panic.
pub fn broadcast_event(
context: &mut UpdateContext<'gc>,
event: Value<'gc>,
event: EventObject<'gc>,
on_type: ClassObject<'gc>,
) {
let event_name = event
.as_object()
.unwrap()
.as_event()
.map(|e| e.event_type())
.expect("Cannot broadcast non-event object");
let event_name = event.event().event_type();

if !BROADCAST_WHITELIST
.iter()
Expand Down Expand Up @@ -549,7 +544,8 @@ 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, event, false)
if let Err(err) =
events::dispatch_event(&mut activation, object, Value::from(event), false)
{
tracing::error!(
"Encountered AVM2 error when broadcasting `{}` event: {:?}",
Expand Down
5 changes: 5 additions & 0 deletions core/src/avm2/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,11 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
None
}

/// Unwrap this object as an event.
fn as_event_object(self) -> Option<EventObject<'gc>> {
None
}

/// Unwrap this object as an event.
fn as_event(&self) -> Option<Ref<Event<'gc>>> {
None
Expand Down
59 changes: 40 additions & 19 deletions core/src/avm2/object/event_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ impl<'gc> EventObject<'gc> {
/// It's just slightly faster and doesn't require an Activation.
/// This is equivalent to
/// classes.event.construct(activation, &[event_type, false, false])
pub fn bare_default_event<S>(context: &mut UpdateContext<'gc>, event_type: S) -> Value<'gc>
pub fn bare_default_event<S>(
context: &mut UpdateContext<'gc>,
event_type: S,
) -> EventObject<'gc>
where
S: Into<AvmString<'gc>>,
{
Expand All @@ -76,7 +79,7 @@ impl<'gc> EventObject<'gc> {
event_type: S,
bubbles: bool,
cancelable: bool,
) -> Value<'gc>
) -> EventObject<'gc>
where
S: Into<AvmString<'gc>>,
{
Expand All @@ -87,24 +90,30 @@ impl<'gc> EventObject<'gc> {
event.set_bubbles(bubbles);
event.set_cancelable(cancelable);

let event_object = EventObject(Gc::new(
EventObject(Gc::new(
context.gc(),
EventObjectData {
base,
event: RefLock::new(event),
},
));

event_object.into()
))
}

#[inline]
pub fn from_class_and_args(
activation: &mut Activation<'_, 'gc>,
class: ClassObject<'gc>,
args: &[Value<'gc>],
) -> Value<'gc> {
// We don't expect Event classes to error in their constructors
class.construct(activation, args).unwrap()
) -> EventObject<'gc> {
// We don't expect Event classes to error in their constructors or to
// return anything other than an EventObject
class
.construct(activation, args)
.unwrap()
.as_object()
.unwrap()
.as_event_object()
.unwrap()
}

pub fn mouse_event<S>(
Expand All @@ -115,7 +124,7 @@ impl<'gc> EventObject<'gc> {
delta: i32,
bubbles: bool,
button: MouseButton,
) -> Value<'gc>
) -> EventObject<'gc>
where
S: Into<AvmString<'gc>>,
{
Expand Down Expand Up @@ -163,7 +172,7 @@ impl<'gc> EventObject<'gc> {
activation: &mut Activation<'_, 'gc>,
target: DisplayObject<'gc>,
button: MouseButton,
) -> Value<'gc> {
) -> EventObject<'gc> {
Self::mouse_event(
activation,
match button {
Expand All @@ -184,7 +193,7 @@ impl<'gc> EventObject<'gc> {
activation: &mut Activation<'_, 'gc>,
target: DisplayObject<'gc>,
button: MouseButton,
) -> Value<'gc> {
) -> EventObject<'gc> {
Self::mouse_event(
activation,
match button {
Expand All @@ -205,7 +214,7 @@ impl<'gc> EventObject<'gc> {
activation: &mut Activation<'_, 'gc>,
target: DisplayObject<'gc>,
button: MouseButton,
) -> Value<'gc> {
) -> EventObject<'gc> {
Self::mouse_event(
activation,
match button {
Expand All @@ -228,7 +237,7 @@ impl<'gc> EventObject<'gc> {
text: AvmString<'gc>,
bubbles: bool,
cancelable: bool,
) -> Value<'gc>
) -> EventObject<'gc>
where
S: Into<AvmString<'gc>>,
{
Expand All @@ -253,7 +262,7 @@ impl<'gc> EventObject<'gc> {
pub fn net_status_event(
activation: &mut Activation<'_, 'gc>,
info: Vec<(impl Into<AvmString<'gc>>, impl Into<AvmString<'gc>>)>,
) -> Value<'gc> {
) -> EventObject<'gc> {
let info_object = ScriptObject::new_object(activation);
for (key, value) in info {
info_object
Expand Down Expand Up @@ -281,7 +290,7 @@ impl<'gc> EventObject<'gc> {
event_type: S,
bytes_loaded: usize,
bytes_total: usize,
) -> Value<'gc>
) -> EventObject<'gc>
where
S: Into<AvmString<'gc>>,
{
Expand Down Expand Up @@ -311,7 +320,7 @@ impl<'gc> EventObject<'gc> {
cancelable: bool,
related_object: Option<InteractiveObject<'gc>>,
key_code: u32,
) -> Value<'gc>
) -> EventObject<'gc>
where
S: Into<AvmString<'gc>>,
{
Expand Down Expand Up @@ -340,7 +349,7 @@ impl<'gc> EventObject<'gc> {
activation: &mut Activation<'_, 'gc>,
error_msg: AvmString<'gc>,
error_code: u32,
) -> Value<'gc> {
) -> EventObject<'gc> {
let io_error_event_cls = activation.avm2().classes().ioerrorevent;
Self::from_class_and_args(
activation,
Expand All @@ -359,7 +368,7 @@ impl<'gc> EventObject<'gc> {
activation: &mut Activation<'_, 'gc>,
status: u16,
redirected: bool,
) -> Value<'gc> {
) -> EventObject<'gc> {
let http_status_event_cls = activation.avm2().classes().httpstatusevent;
Self::from_class_and_args(
activation,
Expand All @@ -373,6 +382,14 @@ impl<'gc> EventObject<'gc> {
],
)
}

pub fn event(&self) -> Ref<Event<'gc>> {
self.0.event.borrow()
}

pub fn event_mut(&self, mc: &Mutation<'gc>) -> RefMut<Event<'gc>> {
unlock!(Gc::write(mc, self.0), EventObjectData, event).borrow_mut()
}
}

impl<'gc> TObject<'gc> for EventObject<'gc> {
Expand All @@ -388,6 +405,10 @@ impl<'gc> TObject<'gc> for EventObject<'gc> {
Gc::as_ptr(self.0) as *const ObjectPtr
}

fn as_event_object(self) -> Option<EventObject<'gc>> {
Some(self)
}

fn as_event(&self) -> Option<Ref<Event<'gc>>> {
Some(self.0.event.borrow())
}
Expand Down
11 changes: 5 additions & 6 deletions core/src/display_object/edit_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use crate::avm1::{
Value as Avm1Value,
};
use crate::avm2::object::StyleSheetObject;
use crate::avm2::Avm2;
use crate::avm2::{
Activation as Avm2Activation, ClassObject as Avm2ClassObject, EventObject as Avm2EventObject,
Object as Avm2Object, StageObject as Avm2StageObject, TObject as _,
use crate::avm2::object::{
ClassObject as Avm2ClassObject, EventObject as Avm2EventObject, Object as Avm2Object,
StageObject as Avm2StageObject,
};
use crate::avm2::{Activation as Avm2Activation, Avm2};
use crate::backend::ui::MouseCursor;
use crate::context::{RenderContext, UpdateContext};
use crate::display_object::interactive::{
Expand Down Expand Up @@ -1935,8 +1935,7 @@ impl<'gc> EditText<'gc> {
);
Avm2::dispatch_event(activation.context, text_evt, target);

let text_evt = text_evt.as_object().unwrap();
if text_evt.as_event().unwrap().is_cancelled() {
if text_evt.event().is_cancelled() {
return;
}
}
Expand Down
5 changes: 2 additions & 3 deletions core/src/focus_tracker.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::avm1::Avm1;
use crate::avm1::Value;
use crate::avm2::{Activation, Avm2, EventObject, TObject};
use crate::avm2::{Activation, Avm2, EventObject};
use crate::context::{RenderContext, UpdateContext};
pub use crate::display_object::{
DisplayObject, TDisplayObject, TDisplayObjectContainer, TextSelection,
Expand Down Expand Up @@ -253,8 +253,7 @@ impl<'gc> FocusTracker<'gc> {
EventObject::focus_event(&mut activation, event_type, true, related_object, key_code);
Avm2::dispatch_event(activation.context, event, target);

let event = event.as_object().unwrap();
let canceled = event.as_event().unwrap().is_cancelled();
let canceled = event.event().is_cancelled();
canceled
}

Expand Down

0 comments on commit 13fb442

Please sign in to comment.