Skip to content

Commit

Permalink
avm2: Allocate a non-static string for the Event name when creating a…
Browse files Browse the repository at this point in the history
…n EventObject
  • Loading branch information
Lord-McSweeney authored and Lord-McSweeney committed Jan 19, 2025
1 parent f3c0a78 commit dae6a07
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 67 deletions.
7 changes: 2 additions & 5 deletions core/src/avm2/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,7 @@ pub struct Event<'gc> {

impl<'gc> Event<'gc> {
/// Construct a new event of a given type.
pub fn new<S>(event_type: S) -> Self
where
S: Into<AvmString<'gc>>,
{
pub fn new(event_type: AvmString<'gc>) -> Self {
Event {
bubbles: false,
cancelable: false,
Expand All @@ -88,7 +85,7 @@ impl<'gc> Event<'gc> {
current_target: None,
event_phase: EventPhase::AtTarget,
target: None,
event_type: event_type.into(),
event_type,
}
}

Expand Down
83 changes: 38 additions & 45 deletions core/src/avm2/object/event_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,31 +61,27 @@ 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>(
pub fn bare_default_event(
context: &mut UpdateContext<'gc>,
event_type: S,
) -> EventObject<'gc>
where
S: Into<AvmString<'gc>>,
{
event_type: &str,
) -> EventObject<'gc> {
Self::bare_event(context, event_type, false, false)
}

/// Create a bare Event instance while skipping the usual `construct()` pipeline.
/// It's just slightly faster and doesn't require an Activation.
/// Note that if you need an Event subclass, you need to construct it via .construct().
pub fn bare_event<S>(
pub fn bare_event(
context: &mut UpdateContext<'gc>,
event_type: S,
event_type: &str,
bubbles: bool,
cancelable: bool,
) -> EventObject<'gc>
where
S: Into<AvmString<'gc>>,
{
) -> EventObject<'gc> {
let class = context.avm2.classes().event;
let base = ScriptObjectData::new(class);

let event_type = AvmString::new_utf8(context.gc(), event_type);

let mut event = Event::new(event_type);
event.set_bubbles(bubbles);
event.set_cancelable(cancelable);
Expand Down Expand Up @@ -116,21 +112,18 @@ impl<'gc> EventObject<'gc> {
.unwrap()
}

pub fn mouse_event<S>(
pub fn mouse_event(
activation: &mut Activation<'_, 'gc>,
event_type: S,
event_type: &str,
target: DisplayObject<'gc>,
related_object: Option<InteractiveObject<'gc>>,
delta: i32,
bubbles: bool,
button: MouseButton,
) -> EventObject<'gc>
where
S: Into<AvmString<'gc>>,
{
) -> EventObject<'gc> {
let local = target.local_mouse_position(activation.context);

let event_type: AvmString<'gc> = event_type.into();
let event_type = AvmString::new_utf8(activation.gc(), event_type);

let mouse_event_cls = activation.avm2().classes().mouseevent;
Self::from_class_and_args(
Expand Down Expand Up @@ -231,17 +224,14 @@ impl<'gc> EventObject<'gc> {
)
}

pub fn text_event<S>(
pub fn text_event(
activation: &mut Activation<'_, 'gc>,
event_type: S,
event_type: &str,
text: AvmString<'gc>,
bubbles: bool,
cancelable: bool,
) -> EventObject<'gc>
where
S: Into<AvmString<'gc>>,
{
let event_type: AvmString<'gc> = event_type.into();
) -> EventObject<'gc> {
let event_type = AvmString::new_utf8(activation.gc(), event_type);

let text_event_cls = activation.avm2().classes().textevent;
Self::from_class_and_args(
Expand All @@ -261,12 +251,17 @@ impl<'gc> EventObject<'gc> {

pub fn net_status_event(
activation: &mut Activation<'_, 'gc>,
info: Vec<(impl Into<AvmString<'gc>>, impl Into<AvmString<'gc>>)>,
info: Vec<(&str, &str)>,
) -> EventObject<'gc> {
let event_type = AvmString::new_utf8(activation.gc(), "netStatus");

let info_object = ScriptObject::new_object(activation);
for (key, value) in info {
let key = AvmString::new_utf8(activation.gc(), key);
let value = AvmString::new_utf8(activation.gc(), value);

info_object
.set_string_property_local(key.into(), Value::String(value.into()), activation)
.set_string_property_local(key, Value::String(value), activation)
.unwrap();
}

Expand All @@ -275,7 +270,7 @@ impl<'gc> EventObject<'gc> {
activation,
net_status_cls,
&[
"netStatus".into(),
event_type.into(),
//bubbles
false.into(),
//cancelable
Expand All @@ -285,16 +280,13 @@ impl<'gc> EventObject<'gc> {
)
}

pub fn progress_event<S>(
pub fn progress_event(
activation: &mut Activation<'_, 'gc>,
event_type: S,
event_type: &str,
bytes_loaded: usize,
bytes_total: usize,
) -> EventObject<'gc>
where
S: Into<AvmString<'gc>>,
{
let event_type: AvmString<'gc> = event_type.into();
) -> EventObject<'gc> {
let event_type = AvmString::new_utf8(activation.gc(), event_type);

let progress_event_cls = activation.avm2().classes().progressevent;
Self::from_class_and_args(
Expand All @@ -314,17 +306,14 @@ impl<'gc> EventObject<'gc> {
)
}

pub fn focus_event<S>(
pub fn focus_event(
activation: &mut Activation<'_, 'gc>,
event_type: S,
event_type: &str,
cancelable: bool,
related_object: Option<InteractiveObject<'gc>>,
key_code: u32,
) -> EventObject<'gc>
where
S: Into<AvmString<'gc>>,
{
let event_type: AvmString<'gc> = event_type.into();
) -> EventObject<'gc> {
let event_type = AvmString::new_utf8(activation.gc(), event_type);
let shift_key = activation.context.input.is_key_down(KeyCode::SHIFT);

let focus_event_cls = activation.avm2().classes().focusevent;
Expand All @@ -350,12 +339,14 @@ impl<'gc> EventObject<'gc> {
error_msg: AvmString<'gc>,
error_code: u32,
) -> EventObject<'gc> {
let event_type = AvmString::new_utf8(activation.gc(), "ioError");

let io_error_event_cls = activation.avm2().classes().ioerrorevent;
Self::from_class_and_args(
activation,
io_error_event_cls,
&[
"ioError".into(),
event_type.into(),
false.into(),
false.into(),
error_msg.into(),
Expand All @@ -369,12 +360,14 @@ impl<'gc> EventObject<'gc> {
status: u16,
redirected: bool,
) -> EventObject<'gc> {
let event_type = AvmString::new_utf8(activation.gc(), "httpStatus");

let http_status_event_cls = activation.avm2().classes().httpstatusevent;
Self::from_class_and_args(
activation,
http_status_event_cls,
&[
"httpStatus".into(),
event_type.into(),
false.into(),
false.into(),
status.into(),
Expand Down
10 changes: 4 additions & 6 deletions core/src/net_connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use crate::avm2::{Activation as Avm2Activation, Avm2, EventObject as Avm2EventOb
use crate::backend::navigator::{ErrorResponse, NavigatorBackend, OwnedFuture, Request};
use crate::context::UpdateContext;
use crate::loader::Error;
use crate::string::AvmString;
use crate::Player;
use flash_lso::packet::{Header, Message, Packet};
use flash_lso::types::{AMFVersion, Value as AmfValue};
Expand Down Expand Up @@ -540,14 +539,13 @@ impl FlashRemoting {
match connection.object {
NetConnectionObject::Avm2(object) => {
let mut activation = Avm2Activation::from_nothing(uc);
let url = AvmString::new_utf8(activation.gc(), response.url);
let event = Avm2EventObject::net_status_event(
&mut activation,
vec![
("code", "NetConnection.Call.Failed".into()),
("level", "error".into()),
("details", url),
("description", "HTTP: Failed".into()),
("code", "NetConnection.Call.Failed"),
("level", "error"),
("details", &response.url),
("description", "HTTP: Failed"),
],
);
Avm2::dispatch_event(activation.context, event, object.into());
Expand Down
20 changes: 9 additions & 11 deletions core/src/streams.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,14 +398,13 @@ impl<'gc> NetStream<'gc> {
StreamManager::activate(context, self);

if notify {
let trigger =
AvmString::new_utf8(context.gc(), format!("Start Seeking {}", offset as u64));
let trigger = format!("Start Seeking {}", offset as u64);
self.trigger_status_event(
context,
vec![
("description", trigger),
("level", "status".into()),
("code", "NetStream.SeekStart.Notify".into()),
("description", &trigger),
("level", "status"),
("code", "NetStream.SeekStart.Notify"),
],
);
}
Expand Down Expand Up @@ -1277,11 +1276,7 @@ impl<'gc> NetStream<'gc> {
}

/// Trigger a status event on the stream.
pub fn trigger_status_event(
self,
context: &mut UpdateContext<'gc>,
values: Vec<(impl Into<AvmString<'gc>>, impl Into<AvmString<'gc>>)>,
) {
pub fn trigger_status_event(self, context: &mut UpdateContext<'gc>, values: Vec<(&str, &str)>) {
let object = self.0.read().avm_object;
match object {
Some(AvmObject::Avm1(object)) => {
Expand All @@ -1295,8 +1290,11 @@ impl<'gc> NetStream<'gc> {
let info_object = Avm1ScriptObject::new(activation.gc(), Some(object_proto));

for (key, value) in values {
let key = AvmString::new_utf8(activation.gc(), key);
let value = AvmString::new_utf8(activation.gc(), value);

info_object
.set(key.into(), Avm1Value::String(value.into()), &mut activation)
.set(key, Avm1Value::String(value), &mut activation)
.expect("valid set");
}

Expand Down

0 comments on commit dae6a07

Please sign in to comment.