Skip to content

Commit

Permalink
core/avm2: Support accessing applicationDomain on a LoaderInfo before…
Browse files Browse the repository at this point in the history
… load starts/finishes; also improve Loader.unload stub.
  • Loading branch information
Lord-McSweeney authored and Dinnerbone committed Aug 18, 2023
1 parent 1f4bfcf commit 89b9bc3
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 28 deletions.
17 changes: 17 additions & 0 deletions core/src/avm2/globals/flash/display/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ pub fn load_bytes<'gc>(
)?
.as_object()
.unwrap();

let future = activation.context.load_manager.load_movie_into_clip_bytes(
activation.context.player.clone(),
content.into(),
Expand Down Expand Up @@ -255,5 +256,21 @@ pub fn unload<'gc>(
this,
&[0.into()],
);

let loader_info = this
.get_property(
&Multiname::new(
activation.avm2().flash_display_internal,
"_contentLoaderInfo",
),
activation,
)?
.as_object()
.unwrap();

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

loader_info_object.unload(activation);

Ok(Value::Undefined)
}
17 changes: 16 additions & 1 deletion core/src/avm2/globals/flash/display/loader_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,22 @@ pub fn get_application_domain<'gc>(
.and_then(|o| o.as_loader_stream())
{
match &*loader_stream {
LoaderStream::NotYetLoaded(movie, _, _) | LoaderStream::Swf(movie, _) => {
LoaderStream::NotYetLoaded(movie, _, _) => {
let domain = activation
.context
.library
.library_for_movie_mut(movie.clone())
.try_avm2_domain();

if let Some(domain) = domain {
return Ok(DomainObject::from_domain(activation, domain)?.into());
} else {
return Ok(Value::Null);
}
}

// A loaded SWF will always have an AVM2 domain present.
LoaderStream::Swf(movie, _) => {
let domain = activation
.context
.library
Expand Down
43 changes: 16 additions & 27 deletions core/src/avm2/object/loaderinfo_object.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Loader-info object

use crate::avm2::activation::Activation;
use crate::avm2::error::argument_error;
use crate::avm2::object::script_object::ScriptObjectData;
use crate::avm2::object::{ClassObject, Object, ObjectPtr, TObject};
use crate::avm2::value::Value;
Expand All @@ -15,36 +16,18 @@ use gc_arena::{Collect, GcCell, GcWeakCell, Mutation};
use std::cell::{Ref, RefMut};
use std::sync::Arc;

/// A class instance allocator that allocates LoaderInfo objects.
/// ActionScript cannot construct a LoaderInfo. Note that LoaderInfo isn't a final class.
pub fn loader_info_allocator<'gc>(
class: ClassObject<'gc>,
activation: &mut Activation<'_, 'gc>,
) -> Result<Object<'gc>, Error<'gc>> {
let base = ScriptObjectData::new(class);

Ok(LoaderInfoObject(GcCell::new(
activation.context.gc_context,
LoaderInfoObjectData {
base,
loaded_stream: None,
loader: None,
init_event_fired: false,
complete_event_fired: false,
shared_events: activation
.context
.avm2
.classes()
.eventdispatcher
.construct(activation, &[])?,
uncaught_error_events: activation
.context
.avm2
.classes()
.uncaughterrorevents
.construct(activation, &[])?,
},
))
.into())
let class_name = class.inner_class_definition().read().name().local_name();

Err(Error::AvmError(argument_error(
activation,
&format!("Error #2012: {class_name}$ class cannot be instantiated."),
2012,
)?))
}

/// Represents a thing which can be loaded by a loader.
Expand Down Expand Up @@ -97,7 +80,7 @@ pub struct LoaderInfoObjectData<'gc> {
/// All normal script data.
base: ScriptObjectData<'gc>,

/// The loaded stream that this gets it's info from.
/// The loaded stream that this gets its info from.
loaded_stream: Option<LoaderStream<'gc>>,

loader: Option<Object<'gc>>,
Expand Down Expand Up @@ -281,6 +264,12 @@ impl<'gc> LoaderInfoObject<'gc> {
pub fn set_loader_stream(&self, stream: LoaderStream<'gc>, mc: &Mutation<'gc>) {
self.0.write(mc).loaded_stream = Some(stream);
}

pub fn unload(&self, activation: &mut Activation<'_, 'gc>) {
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);
}
}

impl<'gc> TObject<'gc> for LoaderInfoObject<'gc> {
Expand Down
4 changes: 4 additions & 0 deletions core/src/library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,10 @@ impl<'gc> MovieLibrary<'gc> {
pub fn avm2_domain(&self) -> Avm2Domain<'gc> {
self.avm2_domain.unwrap()
}

pub fn try_avm2_domain(&self) -> Option<Avm2Domain<'gc>> {
self.avm2_domain
}
}

pub struct MovieLibrarySource<'a, 'gc> {
Expand Down
26 changes: 26 additions & 0 deletions tests/tests/swfs/avm2/loaderinfo_more/Test.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package {
import flash.display.Loader;
import flash.display.Sprite;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;

public class Test extends Sprite {
public function Test() {
var appDomain:ApplicationDomain = new ApplicationDomain();
var loader:Loader = new Loader();
trace(loader.contentLoaderInfo.applicationDomain);
loader.load(new URLRequest("loadable.swf"), new LoaderContext(null, appDomain));
trace(loader.contentLoaderInfo.applicationDomain);
loader.contentLoaderInfo.addEventListener("complete", function(e:*) {
trace(loader.contentLoaderInfo.applicationDomain);
loader.unload();
trace(loader.contentLoaderInfo.applicationDomain);
trace(loader.contentLoaderInfo.bytesLoaded);
trace(loader.contentLoaderInfo.bytesTotal);
});
addChild(loader);
}
}
}

Binary file added tests/tests/swfs/avm2/loaderinfo_more/loadable.swf
Binary file not shown.
6 changes: 6 additions & 0 deletions tests/tests/swfs/avm2/loaderinfo_more/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
null
null
[object ApplicationDomain]
null
0
0
Binary file added tests/tests/swfs/avm2/loaderinfo_more/test.swf
Binary file not shown.
1 change: 1 addition & 0 deletions tests/tests/swfs/avm2/loaderinfo_more/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
num_ticks = 2

0 comments on commit 89b9bc3

Please sign in to comment.