avm2: Convert EventDispatcher and IEventDispatcher to AS

This commit is contained in:
Aaron Hill 2023-02-23 13:01:20 -06:00
parent cd2770ce7e
commit 6ce7bd3277
No known key found for this signature in database
GPG Key ID: B4087E510E98B164
8 changed files with 35 additions and 111 deletions

View File

@ -97,6 +97,7 @@ pub struct Avm2<'gc> {
pub flash_display_internal: Namespace<'gc>, pub flash_display_internal: Namespace<'gc>,
pub flash_utils_internal: Namespace<'gc>, pub flash_utils_internal: Namespace<'gc>,
pub flash_geom_internal: Namespace<'gc>, pub flash_geom_internal: Namespace<'gc>,
pub flash_events_internal: Namespace<'gc>,
#[collect(require_static)] #[collect(require_static)]
native_method_table: &'static [Option<(&'static str, NativeMethodImpl)>], native_method_table: &'static [Option<(&'static str, NativeMethodImpl)>],
@ -146,6 +147,7 @@ impl<'gc> Avm2<'gc> {
flash_display_internal: Namespace::internal("flash.display", mc), flash_display_internal: Namespace::internal("flash.display", mc),
flash_utils_internal: Namespace::internal("flash.utils", mc), flash_utils_internal: Namespace::internal("flash.utils", mc),
flash_geom_internal: Namespace::internal("flash.geom", mc), flash_geom_internal: Namespace::internal("flash.geom", mc),
flash_events_internal: Namespace::internal("flash.events", mc),
native_method_table: Default::default(), native_method_table: Default::default(),
native_instance_allocator_table: Default::default(), native_instance_allocator_table: Default::default(),

View File

@ -478,18 +478,6 @@ pub fn load_player_globals<'gc>(
script script
); );
class(
flash::events::ieventdispatcher::create_interface(activation),
script,
activation,
)?;
avm2_system_class!(
eventdispatcher,
activation,
flash::events::eventdispatcher::create_class(activation),
script
);
// package `flash.display` // package `flash.display`
class( class(
flash::display::ibitmapdrawable::create_interface(activation), flash::display::ibitmapdrawable::create_interface(activation),
@ -700,6 +688,7 @@ fn load_playerglobal<'gc>(
("flash.errors", "IOError", ioerror), ("flash.errors", "IOError", ioerror),
("flash.errors", "EOFError", eoferror), ("flash.errors", "EOFError", eoferror),
("flash.events", "Event", event), ("flash.events", "Event", event),
("flash.events", "EventDispatcher", eventdispatcher),
("flash.events", "TextEvent", textevent), ("flash.events", "TextEvent", textevent),
("flash.events", "ErrorEvent", errorevent), ("flash.events", "ErrorEvent", errorevent),
("flash.events", "KeyboardEvent", keyboardevent), ("flash.events", "KeyboardEvent", keyboardevent),

View File

@ -1,7 +1,7 @@
//! `flash.events` namespace //! `flash.events` namespace
pub mod event; pub mod event;
pub mod eventdispatcher; pub mod event_dispatcher;
pub mod gesture_event; pub mod gesture_event;
pub mod ieventdispatcher; pub mod ieventdispatcher;
pub mod mouse_event; pub mod mouse_event;

View File

@ -1,5 +1,19 @@
// This is a stub - the actual class is defined in `eventdispatcher.rs` // This is a stub - the actual class is defined in `eventdispatcher.rs`
package flash.events { package flash.events {
public class EventDispatcher { public class EventDispatcher implements IEventDispatcher {
internal var _target:IEventDispatcher;
internal var _dispatchList:Object;
public function EventDispatcher(target:IEventDispatcher = null) {
this._target = target;
}
public native function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void;
public native function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void;
public native function dispatchEvent(event:Event):Boolean;
public native function hasEventListener(type:String):Boolean;
public native function willTrigger(type:String):Boolean;
public native function toString():String;
} }
} }

View File

@ -0,0 +1,9 @@
package flash.events {
public interface IEventDispatcher {
function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void;
function dispatchEvent(event:Event):Boolean;
function hasEventListener(type:String):Boolean;
function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void;
function willTrigger(type:String):Boolean;
}
}

View File

@ -1,42 +1,11 @@
//! `flash.events.EventDispatcher` builtin/prototype //! `flash.events.EventDispatcher` builtin/prototype
use crate::avm2::activation::Activation; use crate::avm2::activation::Activation;
use crate::avm2::class::{Class, ClassAttributes};
use crate::avm2::events::{dispatch_event as dispatch_event_internal, parent_of}; use crate::avm2::events::{dispatch_event as dispatch_event_internal, parent_of};
use crate::avm2::method::{Method, NativeMethodImpl};
use crate::avm2::object::{DispatchObject, Object, TObject}; use crate::avm2::object::{DispatchObject, Object, TObject};
use crate::avm2::traits::Trait;
use crate::avm2::value::Value; use crate::avm2::value::Value;
use crate::avm2::Multiname; use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::avm2::{Avm2, Error}; use crate::avm2::{Avm2, Error};
use gc_arena::GcCell;
/// Implements `flash.events.EventDispatcher`'s instance constructor.
pub fn instance_init<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Option<Object<'gc>>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(mut this) = this {
activation.super_init(this, &[])?;
let target = args.get(0).cloned().unwrap_or(Value::Null);
this.init_property(
&Multiname::new(activation.avm2().ruffle_private_namespace, "target"),
target,
activation,
)?;
//NOTE: We *cannot* initialize the dispatch list at construction time,
//since it is possible to gain access to some event dispatchers before
//their constructors run. Notably, `SimpleButton` does this
}
Ok(Value::Undefined)
}
/// Get an object's dispatch list, lazily initializing it if necessary. /// Get an object's dispatch list, lazily initializing it if necessary.
fn dispatch_list<'gc>( fn dispatch_list<'gc>(
@ -44,14 +13,14 @@ fn dispatch_list<'gc>(
mut this: Object<'gc>, mut this: Object<'gc>,
) -> Result<Object<'gc>, Error<'gc>> { ) -> Result<Object<'gc>, Error<'gc>> {
match this.get_property( match this.get_property(
&Multiname::new(activation.avm2().ruffle_private_namespace, "dispatch_list"), &Multiname::new(activation.avm2().flash_events_internal, "_dispatchList"),
activation, activation,
)? { )? {
Value::Object(o) => Ok(o), Value::Object(o) => Ok(o),
_ => { _ => {
let dispatch_list = DispatchObject::empty_list(activation.context.gc_context); let dispatch_list = DispatchObject::empty_list(activation.context.gc_context);
this.init_property( this.init_property(
&Multiname::new(activation.avm2().ruffle_private_namespace, "dispatch_list"), &Multiname::new(activation.avm2().flash_events_internal, "_dispatchList"),
dispatch_list.into(), dispatch_list.into(),
activation, activation,
)?; )?;
@ -183,7 +152,7 @@ pub fn will_trigger<'gc>(
let target = this let target = this
.get_property( .get_property(
&Multiname::new(activation.avm2().ruffle_private_namespace, "target"), &Multiname::new(activation.avm2().flash_events_internal, "_target"),
activation, activation,
)? )?
.as_object() .as_object()
@ -216,15 +185,6 @@ pub fn dispatch_event<'gc>(
} }
} }
/// Implements `flash.events.EventDispatcher`'s class constructor.
pub fn class_init<'gc>(
_activation: &mut Activation<'_, 'gc>,
_this: Option<Object<'gc>>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
Ok(Value::Undefined)
}
/// Implements `EventDispatcher.toString`. /// Implements `EventDispatcher.toString`.
/// ///
/// This is an undocumented function, but MX will VerifyError if this isn't /// This is an undocumented function, but MX will VerifyError if this isn't
@ -241,56 +201,3 @@ pub fn to_string<'gc>(
.as_callable(activation, Some(&name), Some(object_proto))? .as_callable(activation, Some(&name), Some(object_proto))?
.call(this, args, activation) .call(this, args, activation)
} }
/// Construct `EventDispatcher`'s class.
pub fn create_class<'gc>(activation: &mut Activation<'_, 'gc>) -> GcCell<'gc, Class<'gc>> {
let mc = activation.context.gc_context;
let class = Class::new(
QName::new(Namespace::package("flash.events", mc), "EventDispatcher"),
Some(Multiname::new(activation.avm2().public_namespace, "Object")),
Method::from_builtin(instance_init, "<EventDispatcher instance initializer>", mc),
Method::from_builtin(class_init, "<EventDispatcher class initializer>", mc),
mc,
);
let mut write = class.write(mc);
write.set_attributes(ClassAttributes::SEALED);
write.implements(Multiname::new(
Namespace::package("flash.events", mc),
"IEventDispatcher",
));
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("addEventListener", add_event_listener),
("removeEventListener", remove_event_listener),
("hasEventListener", has_event_listener),
("willTrigger", will_trigger),
("dispatchEvent", dispatch_event),
("toString", to_string),
];
write.define_builtin_instance_methods(
mc,
activation.avm2().public_namespace,
PUBLIC_INSTANCE_METHODS,
);
write.define_builtin_instance_methods(
mc,
Namespace::package("flash.events:IEventDispatcher", mc),
PUBLIC_INSTANCE_METHODS,
);
write.define_instance_trait(Trait::from_slot(
QName::new(activation.avm2().ruffle_private_namespace, "target"),
Multiname::new(activation.avm2().public_namespace, "Object"),
None,
));
write.define_instance_trait(Trait::from_slot(
QName::new(activation.avm2().ruffle_private_namespace, "dispatch_list"),
Multiname::new(activation.avm2().public_namespace, "Object"),
None,
));
class
}

View File

@ -24,6 +24,10 @@ include "flash/utils/ByteArray.as"
include "flash/utils/Dictionary.as" include "flash/utils/Dictionary.as"
include "flash/desktop/ClipboardFormats.as" include "flash/desktop/ClipboardFormats.as"
include "flash/desktop/ClipboardTransferMode.as" include "flash/desktop/ClipboardTransferMode.as"
include "flash/events/IEventDispatcher.as"
include "flash/events/EventDispatcher.as"
include "flash/display/ActionScriptVersion.as" include "flash/display/ActionScriptVersion.as"
include "flash/display/BitmapDataChannel.as" include "flash/display/BitmapDataChannel.as"
include "flash/display/BitmapEncodingColorSpace.as" include "flash/display/BitmapEncodingColorSpace.as"

View File

@ -14,7 +14,6 @@ include "flash/display/InteractiveObject.as"
include "flash/display/DisplayObjectContainer.as" include "flash/display/DisplayObjectContainer.as"
include "flash/display/LoaderInfo.as" include "flash/display/LoaderInfo.as"
include "flash/events/EventDispatcher.as"
include "flash/media/SoundTransform.as" include "flash/media/SoundTransform.as"
include "flash/system/ApplicationDomain.as" include "flash/system/ApplicationDomain.as"
include "Function.as" include "Function.as"