Skip to content

Commit

Permalink
avm2: Unload the contents of a Loader before load and loadBytes
Browse files Browse the repository at this point in the history
  • Loading branch information
Lord-McSweeney authored and Lord-McSweeney committed Jun 30, 2024
1 parent 3ff48e9 commit a5554d6
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 18 deletions.
41 changes: 23 additions & 18 deletions core/src/avm2/globals/flash/display/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,6 @@ pub fn load<'gc>(
let url_request = args.get_object(activation, 0, "request")?;
let context = args.try_get_object(activation, 1);

// This is a dummy MovieClip, which will get overwritten in `Loader`
let content = MovieClip::new(
Arc::new(SwfMovie::empty(activation.context.swf.version())),
activation.context.gc_context,
);

let loader_info = this
.get_property(
&Multiname::new(
Expand All @@ -81,6 +75,17 @@ pub fn load<'gc>(
.as_object()
.unwrap();

let loader_info_object = loader_info.as_loader_info_object().unwrap();

// Unload the loader, in case something was already loaded.
loader_info_object.unload(activation);

// This is a dummy MovieClip, which will get overwritten in `Loader`
let content = MovieClip::new(
Arc::new(SwfMovie::empty(activation.context.swf.version())),
activation.context.gc_context,
);

// Update the LoaderStream - we still have a fake SwfMovie, but we now have the real target clip.
loader_info
.as_loader_info_object()
Expand Down Expand Up @@ -211,12 +216,6 @@ pub fn load_bytes<'gc>(
let bytes = arg0.as_bytearray().unwrap().bytes().to_vec();
let context = args.try_get_object(activation, 1);

// This is a dummy MovieClip, which will get overwritten in `Loader`
let content = MovieClip::new(
Arc::new(SwfMovie::empty(activation.context.swf.version())),
activation.context.gc_context,
);

let loader_info = this
.get_property(
&Multiname::new(
Expand All @@ -228,6 +227,17 @@ pub fn load_bytes<'gc>(
.as_object()
.unwrap();

let loader_info_object = loader_info.as_loader_info_object().unwrap();

// Unload the loader, in case something was already loaded.
loader_info_object.unload(activation);

// This is a dummy MovieClip, which will get overwritten in `Loader`
let content = MovieClip::new(
Arc::new(SwfMovie::empty(activation.context.swf.version())),
activation.context.gc_context,
);

let default_domain = activation
.caller_domain()
.expect("Missing caller domain in Loader.loadBytes");
Expand Down Expand Up @@ -255,13 +265,8 @@ pub fn unload<'gc>(
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
// TODO: Broadcast an "unload" event on the LoaderInfo and reset LoaderInfo properties
// TODO: Broadcast an "unload" event on the LoaderInfo
avm2_stub_method!(activation, "flash.display.Loader", "unload");
let _ = crate::avm2::globals::flash::display::display_object_container::remove_child_at(
activation,
this,
&[0.into()],
);

let loader_info = this
.get_property(
Expand Down
1 change: 1 addition & 0 deletions core/src/avm2/globals/flash/display/loader_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ pub fn get_content<'gc>(
if root.movie().is_action_script_3() || !root.movie().is_movie() {
return Ok(root.object2());
} else {
// The movie was an AVM1 movie, return an AVM1Movie object
let root_obj = *root;
drop(loader_stream);

Expand Down
23 changes: 23 additions & 0 deletions core/src/avm2/object/loaderinfo_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,13 @@ impl<'gc> LoaderInfoObject<'gc> {
self.0.read().init_event_fired
}

pub fn reset_init_and_complete_events(&self, mc: &Mutation<'gc>) {
let mut write = self.0.write(mc);

write.init_event_fired = false;
write.complete_event_fired = false;
}

pub fn fire_init_and_complete_events(
&self,
context: &mut UpdateContext<'_, 'gc>,
Expand Down Expand Up @@ -359,10 +366,26 @@ impl<'gc> LoaderInfoObject<'gc> {
}

pub fn unload(&self, activation: &mut Activation<'_, 'gc>) {
// Reset properties
let empty_swf = Arc::new(SwfMovie::empty(activation.context.swf.version()));
let loader_stream = LoaderStream::NotYetLoaded(empty_swf, None, false);
self.set_loader_stream(loader_stream, activation.context.gc_context);
self.set_errored(false, activation.context.gc_context);
self.reset_init_and_complete_events(activation.context.gc_context);

let loader = self
.0
.read()
.loader
.expect("LoaderInfo must have been created by Loader");

// Remove the Loader's content element, and ignore the resulting
// error if the loader hadn't loaded it.
let _ = crate::avm2::globals::flash::display::display_object_container::remove_child_at(
activation,
loader,
&[0.into()],
);
}
}

Expand Down

0 comments on commit a5554d6

Please sign in to comment.