core: Delay completion events until after the SWF is reported as fully loaded.
This commit is contained in:
parent
0a25f265d6
commit
006269e1f8
|
@ -8,7 +8,7 @@ use crate::avm2::Avm2;
|
||||||
use crate::avm2::Error;
|
use crate::avm2::Error;
|
||||||
use crate::avm2::EventObject;
|
use crate::avm2::EventObject;
|
||||||
use crate::context::UpdateContext;
|
use crate::context::UpdateContext;
|
||||||
use crate::display_object::DisplayObject;
|
use crate::display_object::{DisplayObject, TDisplayObject};
|
||||||
use crate::tag_utils::SwfMovie;
|
use crate::tag_utils::SwfMovie;
|
||||||
use gc_arena::{Collect, GcCell, MutationContext};
|
use gc_arena::{Collect, GcCell, MutationContext};
|
||||||
use std::cell::{Ref, RefMut};
|
use std::cell::{Ref, RefMut};
|
||||||
|
@ -27,7 +27,8 @@ pub fn loaderinfo_allocator<'gc>(
|
||||||
base,
|
base,
|
||||||
loaded_stream: None,
|
loaded_stream: None,
|
||||||
loader: None,
|
loader: None,
|
||||||
events_fired: false,
|
init_event_fired: false,
|
||||||
|
complete_event_fired: false,
|
||||||
shared_events: activation
|
shared_events: activation
|
||||||
.context
|
.context
|
||||||
.avm2
|
.avm2
|
||||||
|
@ -75,8 +76,11 @@ pub struct LoaderInfoObjectData<'gc> {
|
||||||
|
|
||||||
loader: Option<Object<'gc>>,
|
loader: Option<Object<'gc>>,
|
||||||
|
|
||||||
/// Whether or not we've fired our 'init' and 'complete' events
|
/// Whether or not we've fired our 'init' event
|
||||||
events_fired: bool,
|
init_event_fired: bool,
|
||||||
|
|
||||||
|
/// Whether or not we've fired our 'complete' event
|
||||||
|
complete_event_fired: bool,
|
||||||
|
|
||||||
/// The `EventDispatcher` used for `LoaderInfo.sharedEvents`.
|
/// The `EventDispatcher` used for `LoaderInfo.sharedEvents`.
|
||||||
// FIXME: If we ever implement sandboxing, then ensure that we allow
|
// FIXME: If we ever implement sandboxing, then ensure that we allow
|
||||||
|
@ -102,7 +106,8 @@ impl<'gc> LoaderInfoObject<'gc> {
|
||||||
base,
|
base,
|
||||||
loaded_stream,
|
loaded_stream,
|
||||||
loader,
|
loader,
|
||||||
events_fired: false,
|
init_event_fired: false,
|
||||||
|
complete_event_fired: false,
|
||||||
shared_events: activation
|
shared_events: activation
|
||||||
.context
|
.context
|
||||||
.avm2
|
.avm2
|
||||||
|
@ -138,7 +143,8 @@ impl<'gc> LoaderInfoObject<'gc> {
|
||||||
base,
|
base,
|
||||||
loaded_stream: Some(LoaderStream::NotYetLoaded(movie, root_clip)),
|
loaded_stream: Some(LoaderStream::NotYetLoaded(movie, root_clip)),
|
||||||
loader,
|
loader,
|
||||||
events_fired: false,
|
init_event_fired: false,
|
||||||
|
complete_event_fired: false,
|
||||||
shared_events: activation
|
shared_events: activation
|
||||||
.context
|
.context
|
||||||
.avm2
|
.avm2
|
||||||
|
@ -164,8 +170,8 @@ impl<'gc> LoaderInfoObject<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fire_init_and_complete_events(&self, context: &mut UpdateContext<'_, 'gc, '_>) {
|
pub fn fire_init_and_complete_events(&self, context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||||
if !self.0.read().events_fired {
|
if !self.0.read().init_event_fired {
|
||||||
self.0.write(context.gc_context).events_fired = true;
|
self.0.write(context.gc_context).init_event_fired = true;
|
||||||
|
|
||||||
// TODO - 'init' should be fired earlier during the download.
|
// TODO - 'init' should be fired earlier during the download.
|
||||||
// Right now, we fire it when downloading is fully completed.
|
// Right now, we fire it when downloading is fully completed.
|
||||||
|
@ -177,14 +183,29 @@ impl<'gc> LoaderInfoObject<'gc> {
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let complete_evt = EventObject::bare_default_event(context, "complete");
|
if !self.0.read().complete_event_fired {
|
||||||
|
// NOTE: We have to check load progress here because this function
|
||||||
|
// is called unconditionally at the end of every frame.
|
||||||
|
let should_complete = match self.0.read().loaded_stream {
|
||||||
|
Some(LoaderStream::Swf(_, root)) => root
|
||||||
|
.as_movie_clip()
|
||||||
|
.map(|mc| mc.loaded_bytes() >= mc.total_bytes())
|
||||||
|
.unwrap_or(false),
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
if let Err(e) = Avm2::dispatch_event(context, complete_evt, (*self).into()) {
|
if should_complete {
|
||||||
log::error!(
|
self.0.write(context.gc_context).complete_event_fired = true;
|
||||||
"Encountered AVM2 error when broadcasting `complete` event: {}",
|
let complete_evt = EventObject::bare_default_event(context, "complete");
|
||||||
e
|
|
||||||
);
|
if let Err(e) = Avm2::dispatch_event(context, complete_evt, (*self).into()) {
|
||||||
|
log::error!(
|
||||||
|
"Encountered AVM2 error when broadcasting `complete` event: {}",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue