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::EventObject;
|
||||
use crate::context::UpdateContext;
|
||||
use crate::display_object::DisplayObject;
|
||||
use crate::display_object::{DisplayObject, TDisplayObject};
|
||||
use crate::tag_utils::SwfMovie;
|
||||
use gc_arena::{Collect, GcCell, MutationContext};
|
||||
use std::cell::{Ref, RefMut};
|
||||
|
@ -27,7 +27,8 @@ pub fn loaderinfo_allocator<'gc>(
|
|||
base,
|
||||
loaded_stream: None,
|
||||
loader: None,
|
||||
events_fired: false,
|
||||
init_event_fired: false,
|
||||
complete_event_fired: false,
|
||||
shared_events: activation
|
||||
.context
|
||||
.avm2
|
||||
|
@ -75,8 +76,11 @@ pub struct LoaderInfoObjectData<'gc> {
|
|||
|
||||
loader: Option<Object<'gc>>,
|
||||
|
||||
/// Whether or not we've fired our 'init' and 'complete' events
|
||||
events_fired: bool,
|
||||
/// Whether or not we've fired our 'init' event
|
||||
init_event_fired: bool,
|
||||
|
||||
/// Whether or not we've fired our 'complete' event
|
||||
complete_event_fired: bool,
|
||||
|
||||
/// The `EventDispatcher` used for `LoaderInfo.sharedEvents`.
|
||||
// FIXME: If we ever implement sandboxing, then ensure that we allow
|
||||
|
@ -102,7 +106,8 @@ impl<'gc> LoaderInfoObject<'gc> {
|
|||
base,
|
||||
loaded_stream,
|
||||
loader,
|
||||
events_fired: false,
|
||||
init_event_fired: false,
|
||||
complete_event_fired: false,
|
||||
shared_events: activation
|
||||
.context
|
||||
.avm2
|
||||
|
@ -138,7 +143,8 @@ impl<'gc> LoaderInfoObject<'gc> {
|
|||
base,
|
||||
loaded_stream: Some(LoaderStream::NotYetLoaded(movie, root_clip)),
|
||||
loader,
|
||||
events_fired: false,
|
||||
init_event_fired: false,
|
||||
complete_event_fired: false,
|
||||
shared_events: activation
|
||||
.context
|
||||
.avm2
|
||||
|
@ -164,8 +170,8 @@ impl<'gc> LoaderInfoObject<'gc> {
|
|||
}
|
||||
|
||||
pub fn fire_init_and_complete_events(&self, context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||
if !self.0.read().events_fired {
|
||||
self.0.write(context.gc_context).events_fired = true;
|
||||
if !self.0.read().init_event_fired {
|
||||
self.0.write(context.gc_context).init_event_fired = true;
|
||||
|
||||
// TODO - 'init' should be fired earlier during the download.
|
||||
// Right now, we fire it when downloading is fully completed.
|
||||
|
@ -177,7 +183,21 @@ impl<'gc> LoaderInfoObject<'gc> {
|
|||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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 should_complete {
|
||||
self.0.write(context.gc_context).complete_event_fired = true;
|
||||
let complete_evt = EventObject::bare_default_event(context, "complete");
|
||||
|
||||
if let Err(e) = Avm2::dispatch_event(context, complete_evt, (*self).into()) {
|
||||
|
@ -188,6 +208,7 @@ impl<'gc> LoaderInfoObject<'gc> {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Unwrap this object's loader stream
|
||||
pub fn as_loader_stream(&self) -> Option<Ref<LoaderStream<'gc>>> {
|
||||
|
|
Loading…
Reference in New Issue