avm2: Implement `Event.clone`

This commit is contained in:
David Wendt 2020-12-08 20:48:11 -05:00 committed by Mike Welsh
parent 3d12929914
commit 584c6c8b11
7 changed files with 100 additions and 1 deletions

View File

@ -69,6 +69,7 @@ pub struct SystemPrototypes<'gc> {
pub framelabel: Object<'gc>, pub framelabel: Object<'gc>,
pub scene: Object<'gc>, pub scene: Object<'gc>,
pub application_domain: Object<'gc>, pub application_domain: Object<'gc>,
pub event: Object<'gc>,
} }
impl<'gc> SystemPrototypes<'gc> { impl<'gc> SystemPrototypes<'gc> {
@ -101,6 +102,7 @@ impl<'gc> SystemPrototypes<'gc> {
framelabel: empty, framelabel: empty,
scene: empty, scene: empty,
application_domain: empty, application_domain: empty,
event: empty,
} }
} }
} }
@ -428,7 +430,13 @@ pub fn load_player_globals<'gc>(
)?; )?;
// package `flash.events` // package `flash.events`
class( activation
.context
.avm2
.system_prototypes
.as_mut()
.unwrap()
.event = class(
activation, activation,
flash::events::event::create_class(mc), flash::events::event::create_class(mc),
flash::events::event::event_deriver, flash::events::event::event_deriver,

View File

@ -132,6 +132,26 @@ pub fn event_phase<'gc>(
Ok(Value::Undefined) Ok(Value::Undefined)
} }
/// Implements `clone`
pub fn clone<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
this: Option<Object<'gc>>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error> {
if let Some(evt) = this.unwrap().as_event() {
let evt_proto = activation.avm2().system_prototypes.as_ref().unwrap().event;
return Ok(EventObject::from_event(
activation.context.gc_context,
Some(evt_proto),
evt.clone(),
)
.into());
}
Ok(Value::Undefined)
}
/// Construct `Event`'s class. /// Construct `Event`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> { pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
let class = Class::new( let class = Class::new(
@ -168,6 +188,10 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
QName::new(Namespace::public_namespace(), "eventPhase"), QName::new(Namespace::public_namespace(), "eventPhase"),
Method::from_builtin(event_phase), Method::from_builtin(event_phase),
)); ));
write.define_instance_trait(Trait::from_method(
QName::new(Namespace::public_namespace(), "clone"),
Method::from_builtin(clone),
));
class class
} }

View File

@ -449,6 +449,7 @@ swf_tests! {
(as3_event_bubbles, "avm2/event_bubbles", 1), (as3_event_bubbles, "avm2/event_bubbles", 1),
(as3_event_cancelable, "avm2/event_cancelable", 1), (as3_event_cancelable, "avm2/event_cancelable", 1),
(as3_event_type, "avm2/event_type", 1), (as3_event_type, "avm2/event_type", 1),
(as3_event_clone, "avm2/event_clone", 1),
} }
// TODO: These tests have some inaccuracies currently, so we use approx_eq to test that numeric values are close enough. // TODO: These tests have some inaccuracies currently, so we use approx_eq to test that numeric values are close enough.

View File

@ -0,0 +1,46 @@
package {
public class Test {
}
}
import flash.events.Event;
trace("///(DynEvent is a dynamic subclass of Event that fails to override clone)");
dynamic class DynEvent extends Event {
function DynEvent(type: String, bubbles: Boolean = false, cancelable: Boolean = false) {
super(type, bubbles, cancelable);
}
}
trace("///var e = new DynEvent(\"test_event\", false, true);");
var e = new DynEvent("test_event", false, true);
trace("///e.expando = \"Original expando property!\"");
e.expando = "Original expando property!";
trace("///e.expando;");
trace(e.expando);
trace("///var e2 = e.clone();");
var e2 = e.clone();
trace("///e2 === e;");
trace(e2 === e);
trace("///e2.hasOwnProperty('expando');");
trace(e2.hasOwnProperty('expando'));
trace("///e2.type");
trace(e2.type);
trace("///e2.bubbles");
trace(e2.bubbles);
trace("///e2.cancelable");
trace(e2.cancelable);
trace("///e2 instanceof Event");
trace(e2 instanceof Event);
trace("///e2 instanceof DynEvent");
trace(e2 instanceof DynEvent);

View File

@ -0,0 +1,20 @@
///(DynEvent is a dynamic subclass of Event that fails to override clone)
///var e = new DynEvent("test_event", false, true);
///e.expando = "Original expando property!"
///e.expando;
Original expando property!
///var e2 = e.clone();
///e2 === e;
false
///e2.hasOwnProperty('expando');
false
///e2.type
test_event
///e2.bubbles
false
///e2.cancelable
true
///e2 instanceof Event
true
///e2 instanceof DynEvent
false

Binary file not shown.

Binary file not shown.